true&&(function polyfill() {
    const relList = document.createElement('link').relList;
    if (relList && relList.supports && relList.supports('modulepreload')) {
        return;
    }
    for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
        processPreload(link);
    }
    new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            if (mutation.type !== 'childList') {
                continue;
            }
            for (const node of mutation.addedNodes) {
                if (node.tagName === 'LINK' && node.rel === 'modulepreload')
                    processPreload(node);
            }
        }
    }).observe(document, { childList: true, subtree: true });
    function getFetchOpts(link) {
        const fetchOpts = {};
        if (link.integrity)
            fetchOpts.integrity = link.integrity;
        if (link.referrerPolicy)
            fetchOpts.referrerPolicy = link.referrerPolicy;
        if (link.crossOrigin === 'use-credentials')
            fetchOpts.credentials = 'include';
        else if (link.crossOrigin === 'anonymous')
            fetchOpts.credentials = 'omit';
        else
            fetchOpts.credentials = 'same-origin';
        return fetchOpts;
    }
    function processPreload(link) {
        if (link.ep)
            // ep marker = processed
            return;
        link.ep = true;
        // prepopulate the load record
        const fetchOpts = getFetchOpts(link);
        fetch(link.href, fetchOpts);
    }
}());
/* Injected with object hook! */

function makeMap(str, expectsLowerCase) {
  const map = /* @__PURE__ */ Object.create(null);
  const list = str.split(",");
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true;
  }
  return expectsLowerCase ? (val) => !!map[val.toLowerCase()] : (val) => !!map[val];
}

const EMPTY_OBJ$1 = {};
const EMPTY_ARR = [];
const NOOP = () => {
};
const NO = () => false;
const onRE = /^on[^a-z]/;
const isOn = (key) => onRE.test(key);
const isModelListener = (key) => key.startsWith("onUpdate:");
const extend$3 = Object.assign;
const remove = (arr, el) => {
  const i = arr.indexOf(el);
  if (i > -1) {
    arr.splice(i, 1);
  }
};
const hasOwnProperty$3 = Object.prototype.hasOwnProperty;
const hasOwn$m = (val, key) => hasOwnProperty$3.call(val, key);
const isArray$k = Array.isArray;
const isMap = (val) => toTypeString(val) === "[object Map]";
const isSet = (val) => toTypeString(val) === "[object Set]";
const isDate = (val) => toTypeString(val) === "[object Date]";
const isRegExp$1 = (val) => toTypeString(val) === "[object RegExp]";
const isFunction$1 = (val) => typeof val === "function";
const isString$3 = (val) => typeof val === "string";
const isSymbol$7 = (val) => typeof val === "symbol";
const isObject$o = (val) => val !== null && typeof val === "object";
const isPromise = (val) => {
  return (isObject$o(val) || isFunction$1(val)) && isFunction$1(val.then) && isFunction$1(val.catch);
};
const objectToString$2 = Object.prototype.toString;
const toTypeString = (value) => objectToString$2.call(value);
const toRawType = (value) => {
  return toTypeString(value).slice(8, -1);
};
const isPlainObject = (val) => toTypeString(val) === "[object Object]";
const isIntegerKey = (key) => isString$3(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key;
const isReservedProp = /* @__PURE__ */ makeMap(
  // the leading comma is intentional so empty string "" is also included
  ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"
);
const cacheStringFunction = (fn) => {
  const cache = /* @__PURE__ */ Object.create(null);
  return (str) => {
    const hit = cache[str];
    return hit || (cache[str] = fn(str));
  };
};
const camelizeRE = /-(\w)/g;
const camelize = cacheStringFunction((str) => {
  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : "");
});
const hyphenateRE = /\B([A-Z])/g;
const hyphenate = cacheStringFunction(
  (str) => str.replace(hyphenateRE, "-$1").toLowerCase()
);
const capitalize = cacheStringFunction((str) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
});
const toHandlerKey = cacheStringFunction((str) => {
  const s = str ? `on${capitalize(str)}` : ``;
  return s;
});
const hasChanged = (value, oldValue) => !Object.is(value, oldValue);
const invokeArrayFns = (fns, arg) => {
  for (let i = 0; i < fns.length; i++) {
    fns[i](arg);
  }
};
const def = (obj, key, value) => {
  Object.defineProperty(obj, key, {
    configurable: true,
    enumerable: false,
    value
  });
};
const looseToNumber = (val) => {
  const n = parseFloat(val);
  return isNaN(n) ? val : n;
};
const toNumber = (val) => {
  const n = isString$3(val) ? Number(val) : NaN;
  return isNaN(n) ? val : n;
};
let _globalThis;
const getGlobalThis = () => {
  return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {});
};

function normalizeStyle$1(value) {
  if (isArray$k(value)) {
    const res = {};
    for (let i = 0; i < value.length; i++) {
      const item = value[i];
      const normalized = isString$3(item) ? parseStringStyle(item) : normalizeStyle$1(item);
      if (normalized) {
        for (const key in normalized) {
          res[key] = normalized[key];
        }
      }
    }
    return res;
  } else if (isString$3(value) || isObject$o(value)) {
    return value;
  }
}
const listDelimiterRE = /;(?![^(]*\))/g;
const propertyDelimiterRE = /:([^]+)/;
const styleCommentRE = /\/\*[^]*?\*\//g;
function parseStringStyle(cssText) {
  const ret = {};
  cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => {
    if (item) {
      const tmp = item.split(propertyDelimiterRE);
      tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim());
    }
  });
  return ret;
}
function normalizeClass(value) {
  let res = "";
  if (isString$3(value)) {
    res = value;
  } else if (isArray$k(value)) {
    for (let i = 0; i < value.length; i++) {
      const normalized = normalizeClass(value[i]);
      if (normalized) {
        res += normalized + " ";
      }
    }
  } else if (isObject$o(value)) {
    for (const name in value) {
      if (value[name]) {
        res += name + " ";
      }
    }
  }
  return res.trim();
}
function normalizeProps(props) {
  if (!props)
    return null;
  let { class: klass, style } = props;
  if (klass && !isString$3(klass)) {
    props.class = normalizeClass(klass);
  }
  if (style) {
    props.style = normalizeStyle$1(style);
  }
  return props;
}

const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
const isSpecialBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs);
function includeBooleanAttr(value) {
  return !!value || value === "";
}

function looseCompareArrays(a, b) {
  if (a.length !== b.length)
    return false;
  let equal = true;
  for (let i = 0; equal && i < a.length; i++) {
    equal = looseEqual(a[i], b[i]);
  }
  return equal;
}
function looseEqual(a, b) {
  if (a === b)
    return true;
  let aValidType = isDate(a);
  let bValidType = isDate(b);
  if (aValidType || bValidType) {
    return aValidType && bValidType ? a.getTime() === b.getTime() : false;
  }
  aValidType = isSymbol$7(a);
  bValidType = isSymbol$7(b);
  if (aValidType || bValidType) {
    return a === b;
  }
  aValidType = isArray$k(a);
  bValidType = isArray$k(b);
  if (aValidType || bValidType) {
    return aValidType && bValidType ? looseCompareArrays(a, b) : false;
  }
  aValidType = isObject$o(a);
  bValidType = isObject$o(b);
  if (aValidType || bValidType) {
    if (!aValidType || !bValidType) {
      return false;
    }
    const aKeysCount = Object.keys(a).length;
    const bKeysCount = Object.keys(b).length;
    if (aKeysCount !== bKeysCount) {
      return false;
    }
    for (const key in a) {
      const aHasKey = a.hasOwnProperty(key);
      const bHasKey = b.hasOwnProperty(key);
      if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) {
        return false;
      }
    }
  }
  return String(a) === String(b);
}
function looseIndexOf(arr, val) {
  return arr.findIndex((item) => looseEqual(item, val));
}

const toDisplayString = (val) => {
  return isString$3(val) ? val : val == null ? "" : isArray$k(val) || isObject$o(val) && (val.toString === objectToString$2 || !isFunction$1(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val);
};
const replacer = (_key, val) => {
  if (val && val.__v_isRef) {
    return replacer(_key, val.value);
  } else if (isMap(val)) {
    return {
      [`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val2]) => {
        entries[`${key} =>`] = val2;
        return entries;
      }, {})
    };
  } else if (isSet(val)) {
    return {
      [`Set(${val.size})`]: [...val.values()]
    };
  } else if (isObject$o(val) && !isArray$k(val) && !isPlainObject(val)) {
    return String(val);
  }
  return val;
};

/* Injected with object hook! */

let activeEffectScope;
class EffectScope {
  constructor(detached = false) {
    this.detached = detached;
    /**
     * @internal
     */
    this._active = true;
    /**
     * @internal
     */
    this.effects = [];
    /**
     * @internal
     */
    this.cleanups = [];
    this.parent = activeEffectScope;
    if (!detached && activeEffectScope) {
      this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(
        this
      ) - 1;
    }
  }
  get active() {
    return this._active;
  }
  run(fn) {
    if (this._active) {
      const currentEffectScope = activeEffectScope;
      try {
        activeEffectScope = this;
        return fn();
      } finally {
        activeEffectScope = currentEffectScope;
      }
    }
  }
  /**
   * This should only be called on non-detached scopes
   * @internal
   */
  on() {
    activeEffectScope = this;
  }
  /**
   * This should only be called on non-detached scopes
   * @internal
   */
  off() {
    activeEffectScope = this.parent;
  }
  stop(fromParent) {
    if (this._active) {
      let i, l;
      for (i = 0, l = this.effects.length; i < l; i++) {
        this.effects[i].stop();
      }
      for (i = 0, l = this.cleanups.length; i < l; i++) {
        this.cleanups[i]();
      }
      if (this.scopes) {
        for (i = 0, l = this.scopes.length; i < l; i++) {
          this.scopes[i].stop(true);
        }
      }
      if (!this.detached && this.parent && !fromParent) {
        const last = this.parent.scopes.pop();
        if (last && last !== this) {
          this.parent.scopes[this.index] = last;
          last.index = this.index;
        }
      }
      this.parent = void 0;
      this._active = false;
    }
  }
}
function recordEffectScope(effect, scope = activeEffectScope) {
  if (scope && scope.active) {
    scope.effects.push(effect);
  }
}
function getCurrentScope() {
  return activeEffectScope;
}
function onScopeDispose(fn) {
  if (activeEffectScope) {
    activeEffectScope.cleanups.push(fn);
  }
}

const createDep = (effects) => {
  const dep = new Set(effects);
  dep.w = 0;
  dep.n = 0;
  return dep;
};
const wasTracked = (dep) => (dep.w & trackOpBit) > 0;
const newTracked = (dep) => (dep.n & trackOpBit) > 0;
const initDepMarkers = ({ deps }) => {
  if (deps.length) {
    for (let i = 0; i < deps.length; i++) {
      deps[i].w |= trackOpBit;
    }
  }
};
const finalizeDepMarkers = (effect) => {
  const { deps } = effect;
  if (deps.length) {
    let ptr = 0;
    for (let i = 0; i < deps.length; i++) {
      const dep = deps[i];
      if (wasTracked(dep) && !newTracked(dep)) {
        dep.delete(effect);
      } else {
        deps[ptr++] = dep;
      }
      dep.w &= ~trackOpBit;
      dep.n &= ~trackOpBit;
    }
    deps.length = ptr;
  }
};

const targetMap = /* @__PURE__ */ new WeakMap();
let effectTrackDepth = 0;
let trackOpBit = 1;
const maxMarkerBits = 30;
let activeEffect;
const ITERATE_KEY = Symbol("");
const MAP_KEY_ITERATE_KEY = Symbol("");
class ReactiveEffect {
  constructor(fn, scheduler = null, scope) {
    this.fn = fn;
    this.scheduler = scheduler;
    this.active = true;
    this.deps = [];
    this.parent = void 0;
    recordEffectScope(this, scope);
  }
  run() {
    if (!this.active) {
      return this.fn();
    }
    let parent = activeEffect;
    let lastShouldTrack = shouldTrack;
    while (parent) {
      if (parent === this) {
        return;
      }
      parent = parent.parent;
    }
    try {
      this.parent = activeEffect;
      activeEffect = this;
      shouldTrack = true;
      trackOpBit = 1 << ++effectTrackDepth;
      if (effectTrackDepth <= maxMarkerBits) {
        initDepMarkers(this);
      } else {
        cleanupEffect(this);
      }
      return this.fn();
    } finally {
      if (effectTrackDepth <= maxMarkerBits) {
        finalizeDepMarkers(this);
      }
      trackOpBit = 1 << --effectTrackDepth;
      activeEffect = this.parent;
      shouldTrack = lastShouldTrack;
      this.parent = void 0;
      if (this.deferStop) {
        this.stop();
      }
    }
  }
  stop() {
    if (activeEffect === this) {
      this.deferStop = true;
    } else if (this.active) {
      cleanupEffect(this);
      if (this.onStop) {
        this.onStop();
      }
      this.active = false;
    }
  }
}
function cleanupEffect(effect2) {
  const { deps } = effect2;
  if (deps.length) {
    for (let i = 0; i < deps.length; i++) {
      deps[i].delete(effect2);
    }
    deps.length = 0;
  }
}
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
  trackStack.push(shouldTrack);
  shouldTrack = false;
}
function resetTracking() {
  const last = trackStack.pop();
  shouldTrack = last === void 0 ? true : last;
}
function track(target, type, key) {
  if (shouldTrack && activeEffect) {
    let depsMap = targetMap.get(target);
    if (!depsMap) {
      targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
    }
    let dep = depsMap.get(key);
    if (!dep) {
      depsMap.set(key, dep = createDep());
    }
    trackEffects(dep);
  }
}
function trackEffects(dep, debuggerEventExtraInfo) {
  let shouldTrack2 = false;
  if (effectTrackDepth <= maxMarkerBits) {
    if (!newTracked(dep)) {
      dep.n |= trackOpBit;
      shouldTrack2 = !wasTracked(dep);
    }
  } else {
    shouldTrack2 = !dep.has(activeEffect);
  }
  if (shouldTrack2) {
    dep.add(activeEffect);
    activeEffect.deps.push(dep);
  }
}
function trigger(target, type, key, newValue, oldValue, oldTarget) {
  const depsMap = targetMap.get(target);
  if (!depsMap) {
    return;
  }
  let deps = [];
  if (type === "clear") {
    deps = [...depsMap.values()];
  } else if (key === "length" && isArray$k(target)) {
    const newLength = Number(newValue);
    depsMap.forEach((dep, key2) => {
      if (key2 === "length" || !isSymbol$7(key2) && key2 >= newLength) {
        deps.push(dep);
      }
    });
  } else {
    if (key !== void 0) {
      deps.push(depsMap.get(key));
    }
    switch (type) {
      case "add":
        if (!isArray$k(target)) {
          deps.push(depsMap.get(ITERATE_KEY));
          if (isMap(target)) {
            deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
          }
        } else if (isIntegerKey(key)) {
          deps.push(depsMap.get("length"));
        }
        break;
      case "delete":
        if (!isArray$k(target)) {
          deps.push(depsMap.get(ITERATE_KEY));
          if (isMap(target)) {
            deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
          }
        }
        break;
      case "set":
        if (isMap(target)) {
          deps.push(depsMap.get(ITERATE_KEY));
        }
        break;
    }
  }
  if (deps.length === 1) {
    if (deps[0]) {
      {
        triggerEffects(deps[0]);
      }
    }
  } else {
    const effects = [];
    for (const dep of deps) {
      if (dep) {
        effects.push(...dep);
      }
    }
    {
      triggerEffects(createDep(effects));
    }
  }
}
function triggerEffects(dep, debuggerEventExtraInfo) {
  const effects = isArray$k(dep) ? dep : [...dep];
  for (const effect2 of effects) {
    if (effect2.computed) {
      triggerEffect(effect2);
    }
  }
  for (const effect2 of effects) {
    if (!effect2.computed) {
      triggerEffect(effect2);
    }
  }
}
function triggerEffect(effect2, debuggerEventExtraInfo) {
  if (effect2 !== activeEffect || effect2.allowRecurse) {
    if (effect2.scheduler) {
      effect2.scheduler();
    } else {
      effect2.run();
    }
  }
}
function getDepFromReactive(object, key) {
  var _a;
  return (_a = targetMap.get(object)) == null ? void 0 : _a.get(key);
}

const isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`);
const builtInSymbols = new Set(
  /* @__PURE__ */ Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol$7)
);
const arrayInstrumentations = /* @__PURE__ */ createArrayInstrumentations();
function createArrayInstrumentations() {
  const instrumentations = {};
  ["includes", "indexOf", "lastIndexOf"].forEach((key) => {
    instrumentations[key] = function(...args) {
      const arr = toRaw(this);
      for (let i = 0, l = this.length; i < l; i++) {
        track(arr, "get", i + "");
      }
      const res = arr[key](...args);
      if (res === -1 || res === false) {
        return arr[key](...args.map(toRaw));
      } else {
        return res;
      }
    };
  });
  ["push", "pop", "shift", "unshift", "splice"].forEach((key) => {
    instrumentations[key] = function(...args) {
      pauseTracking();
      const res = toRaw(this)[key].apply(this, args);
      resetTracking();
      return res;
    };
  });
  return instrumentations;
}
function hasOwnProperty$2(key) {
  const obj = toRaw(this);
  track(obj, "has", key);
  return obj.hasOwnProperty(key);
}
class BaseReactiveHandler {
  constructor(_isReadonly = false, _shallow = false) {
    this._isReadonly = _isReadonly;
    this._shallow = _shallow;
  }
  get(target, key, receiver) {
    const isReadonly2 = this._isReadonly, shallow = this._shallow;
    if (key === "__v_isReactive") {
      return !isReadonly2;
    } else if (key === "__v_isReadonly") {
      return isReadonly2;
    } else if (key === "__v_isShallow") {
      return shallow;
    } else if (key === "__v_raw" && receiver === (isReadonly2 ? shallow ? shallowReadonlyMap : readonlyMap : shallow ? shallowReactiveMap : reactiveMap).get(target)) {
      return target;
    }
    const targetIsArray = isArray$k(target);
    if (!isReadonly2) {
      if (targetIsArray && hasOwn$m(arrayInstrumentations, key)) {
        return Reflect.get(arrayInstrumentations, key, receiver);
      }
      if (key === "hasOwnProperty") {
        return hasOwnProperty$2;
      }
    }
    const res = Reflect.get(target, key, receiver);
    if (isSymbol$7(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
      return res;
    }
    if (!isReadonly2) {
      track(target, "get", key);
    }
    if (shallow) {
      return res;
    }
    if (isRef(res)) {
      return targetIsArray && isIntegerKey(key) ? res : res.value;
    }
    if (isObject$o(res)) {
      return isReadonly2 ? readonly(res) : reactive(res);
    }
    return res;
  }
}
class MutableReactiveHandler extends BaseReactiveHandler {
  constructor(shallow = false) {
    super(false, shallow);
  }
  set(target, key, value, receiver) {
    let oldValue = target[key];
    if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
      return false;
    }
    if (!this._shallow) {
      if (!isShallow(value) && !isReadonly(value)) {
        oldValue = toRaw(oldValue);
        value = toRaw(value);
      }
      if (!isArray$k(target) && isRef(oldValue) && !isRef(value)) {
        oldValue.value = value;
        return true;
      }
    }
    const hadKey = isArray$k(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn$m(target, key);
    const result = Reflect.set(target, key, value, receiver);
    if (target === toRaw(receiver)) {
      if (!hadKey) {
        trigger(target, "add", key, value);
      } else if (hasChanged(value, oldValue)) {
        trigger(target, "set", key, value);
      }
    }
    return result;
  }
  deleteProperty(target, key) {
    const hadKey = hasOwn$m(target, key);
    target[key];
    const result = Reflect.deleteProperty(target, key);
    if (result && hadKey) {
      trigger(target, "delete", key, void 0);
    }
    return result;
  }
  has(target, key) {
    const result = Reflect.has(target, key);
    if (!isSymbol$7(key) || !builtInSymbols.has(key)) {
      track(target, "has", key);
    }
    return result;
  }
  ownKeys(target) {
    track(
      target,
      "iterate",
      isArray$k(target) ? "length" : ITERATE_KEY
    );
    return Reflect.ownKeys(target);
  }
}
class ReadonlyReactiveHandler extends BaseReactiveHandler {
  constructor(shallow = false) {
    super(true, shallow);
  }
  set(target, key) {
    return true;
  }
  deleteProperty(target, key) {
    return true;
  }
}
const mutableHandlers = /* @__PURE__ */ new MutableReactiveHandler();
const readonlyHandlers = /* @__PURE__ */ new ReadonlyReactiveHandler();
const shallowReactiveHandlers = /* @__PURE__ */ new MutableReactiveHandler(
  true
);

const toShallow = (value) => value;
const getProto = (v) => Reflect.getPrototypeOf(v);
function get$b(target, key, isReadonly = false, isShallow = false) {
  target = target["__v_raw"];
  const rawTarget = toRaw(target);
  const rawKey = toRaw(key);
  if (!isReadonly) {
    if (hasChanged(key, rawKey)) {
      track(rawTarget, "get", key);
    }
    track(rawTarget, "get", rawKey);
  }
  const { has: has2 } = getProto(rawTarget);
  const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
  if (has2.call(rawTarget, key)) {
    return wrap(target.get(key));
  } else if (has2.call(rawTarget, rawKey)) {
    return wrap(target.get(rawKey));
  } else if (target !== rawTarget) {
    target.get(key);
  }
}
function has$2(key, isReadonly = false) {
  const target = this["__v_raw"];
  const rawTarget = toRaw(target);
  const rawKey = toRaw(key);
  if (!isReadonly) {
    if (hasChanged(key, rawKey)) {
      track(rawTarget, "has", key);
    }
    track(rawTarget, "has", rawKey);
  }
  return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey);
}
function size(target, isReadonly = false) {
  target = target["__v_raw"];
  !isReadonly && track(toRaw(target), "iterate", ITERATE_KEY);
  return Reflect.get(target, "size", target);
}
function add$1(value) {
  value = toRaw(value);
  const target = toRaw(this);
  const proto = getProto(target);
  const hadKey = proto.has.call(target, value);
  if (!hadKey) {
    target.add(value);
    trigger(target, "add", value, value);
  }
  return this;
}
function set$6(key, value) {
  value = toRaw(value);
  const target = toRaw(this);
  const { has: has2, get: get2 } = getProto(target);
  let hadKey = has2.call(target, key);
  if (!hadKey) {
    key = toRaw(key);
    hadKey = has2.call(target, key);
  }
  const oldValue = get2.call(target, key);
  target.set(key, value);
  if (!hadKey) {
    trigger(target, "add", key, value);
  } else if (hasChanged(value, oldValue)) {
    trigger(target, "set", key, value);
  }
  return this;
}
function deleteEntry(key) {
  const target = toRaw(this);
  const { has: has2, get: get2 } = getProto(target);
  let hadKey = has2.call(target, key);
  if (!hadKey) {
    key = toRaw(key);
    hadKey = has2.call(target, key);
  }
  get2 ? get2.call(target, key) : void 0;
  const result = target.delete(key);
  if (hadKey) {
    trigger(target, "delete", key, void 0);
  }
  return result;
}
function clear$2() {
  const target = toRaw(this);
  const hadItems = target.size !== 0;
  const result = target.clear();
  if (hadItems) {
    trigger(target, "clear", void 0, void 0);
  }
  return result;
}
function createForEach(isReadonly, isShallow) {
  return function forEach(callback, thisArg) {
    const observed = this;
    const target = observed["__v_raw"];
    const rawTarget = toRaw(target);
    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
    !isReadonly && track(rawTarget, "iterate", ITERATE_KEY);
    return target.forEach((value, key) => {
      return callback.call(thisArg, wrap(value), wrap(key), observed);
    });
  };
}
function createIterableMethod(method, isReadonly, isShallow) {
  return function(...args) {
    const target = this["__v_raw"];
    const rawTarget = toRaw(target);
    const targetIsMap = isMap(rawTarget);
    const isPair = method === "entries" || method === Symbol.iterator && targetIsMap;
    const isKeyOnly = method === "keys" && targetIsMap;
    const innerIterator = target[method](...args);
    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;
    !isReadonly && track(
      rawTarget,
      "iterate",
      isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY
    );
    return {
      // iterator protocol
      next() {
        const { value, done } = innerIterator.next();
        return done ? { value, done } : {
          value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
          done
        };
      },
      // iterable protocol
      [Symbol.iterator]() {
        return this;
      }
    };
  };
}
function createReadonlyMethod(type) {
  return function(...args) {
    return type === "delete" ? false : this;
  };
}
function createInstrumentations() {
  const mutableInstrumentations2 = {
    get(key) {
      return get$b(this, key);
    },
    get size() {
      return size(this);
    },
    has: has$2,
    add: add$1,
    set: set$6,
    delete: deleteEntry,
    clear: clear$2,
    forEach: createForEach(false, false)
  };
  const shallowInstrumentations2 = {
    get(key) {
      return get$b(this, key, false, true);
    },
    get size() {
      return size(this);
    },
    has: has$2,
    add: add$1,
    set: set$6,
    delete: deleteEntry,
    clear: clear$2,
    forEach: createForEach(false, true)
  };
  const readonlyInstrumentations2 = {
    get(key) {
      return get$b(this, key, true);
    },
    get size() {
      return size(this, true);
    },
    has(key) {
      return has$2.call(this, key, true);
    },
    add: createReadonlyMethod("add"),
    set: createReadonlyMethod("set"),
    delete: createReadonlyMethod("delete"),
    clear: createReadonlyMethod("clear"),
    forEach: createForEach(true, false)
  };
  const shallowReadonlyInstrumentations2 = {
    get(key) {
      return get$b(this, key, true, true);
    },
    get size() {
      return size(this, true);
    },
    has(key) {
      return has$2.call(this, key, true);
    },
    add: createReadonlyMethod("add"),
    set: createReadonlyMethod("set"),
    delete: createReadonlyMethod("delete"),
    clear: createReadonlyMethod("clear"),
    forEach: createForEach(true, true)
  };
  const iteratorMethods = ["keys", "values", "entries", Symbol.iterator];
  iteratorMethods.forEach((method) => {
    mutableInstrumentations2[method] = createIterableMethod(
      method,
      false,
      false
    );
    readonlyInstrumentations2[method] = createIterableMethod(
      method,
      true,
      false
    );
    shallowInstrumentations2[method] = createIterableMethod(
      method,
      false,
      true
    );
    shallowReadonlyInstrumentations2[method] = createIterableMethod(
      method,
      true,
      true
    );
  });
  return [
    mutableInstrumentations2,
    readonlyInstrumentations2,
    shallowInstrumentations2,
    shallowReadonlyInstrumentations2
  ];
}
const [
  mutableInstrumentations,
  readonlyInstrumentations,
  shallowInstrumentations,
  shallowReadonlyInstrumentations
] = /* @__PURE__ */ createInstrumentations();
function createInstrumentationGetter(isReadonly, shallow) {
  const instrumentations = shallow ? isReadonly ? shallowReadonlyInstrumentations : shallowInstrumentations : isReadonly ? readonlyInstrumentations : mutableInstrumentations;
  return (target, key, receiver) => {
    if (key === "__v_isReactive") {
      return !isReadonly;
    } else if (key === "__v_isReadonly") {
      return isReadonly;
    } else if (key === "__v_raw") {
      return target;
    }
    return Reflect.get(
      hasOwn$m(instrumentations, key) && key in target ? instrumentations : target,
      key,
      receiver
    );
  };
}
const mutableCollectionHandlers = {
  get: /* @__PURE__ */ createInstrumentationGetter(false, false)
};
const shallowCollectionHandlers = {
  get: /* @__PURE__ */ createInstrumentationGetter(false, true)
};
const readonlyCollectionHandlers = {
  get: /* @__PURE__ */ createInstrumentationGetter(true, false)
};

const reactiveMap = /* @__PURE__ */ new WeakMap();
const shallowReactiveMap = /* @__PURE__ */ new WeakMap();
const readonlyMap = /* @__PURE__ */ new WeakMap();
const shallowReadonlyMap = /* @__PURE__ */ new WeakMap();
function targetTypeMap(rawType) {
  switch (rawType) {
    case "Object":
    case "Array":
      return 1 /* COMMON */;
    case "Map":
    case "Set":
    case "WeakMap":
    case "WeakSet":
      return 2 /* COLLECTION */;
    default:
      return 0 /* INVALID */;
  }
}
function getTargetType(value) {
  return value["__v_skip"] || !Object.isExtensible(value) ? 0 /* INVALID */ : targetTypeMap(toRawType(value));
}
function reactive(target) {
  if (isReadonly(target)) {
    return target;
  }
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  );
}
function shallowReactive(target) {
  return createReactiveObject(
    target,
    false,
    shallowReactiveHandlers,
    shallowCollectionHandlers,
    shallowReactiveMap
  );
}
function readonly(target) {
  return createReactiveObject(
    target,
    true,
    readonlyHandlers,
    readonlyCollectionHandlers,
    readonlyMap
  );
}
function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) {
  if (!isObject$o(target)) {
    return target;
  }
  if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) {
    return target;
  }
  const existingProxy = proxyMap.get(target);
  if (existingProxy) {
    return existingProxy;
  }
  const targetType = getTargetType(target);
  if (targetType === 0 /* INVALID */) {
    return target;
  }
  const proxy = new Proxy(
    target,
    targetType === 2 /* COLLECTION */ ? collectionHandlers : baseHandlers
  );
  proxyMap.set(target, proxy);
  return proxy;
}
function isReactive(value) {
  if (isReadonly(value)) {
    return isReactive(value["__v_raw"]);
  }
  return !!(value && value["__v_isReactive"]);
}
function isReadonly(value) {
  return !!(value && value["__v_isReadonly"]);
}
function isShallow(value) {
  return !!(value && value["__v_isShallow"]);
}
function isProxy(value) {
  return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
  const raw = observed && observed["__v_raw"];
  return raw ? toRaw(raw) : observed;
}
function markRaw(value) {
  def(value, "__v_skip", true);
  return value;
}
const toReactive = (value) => isObject$o(value) ? reactive(value) : value;
const toReadonly = (value) => isObject$o(value) ? readonly(value) : value;

function trackRefValue(ref2) {
  if (shouldTrack && activeEffect) {
    ref2 = toRaw(ref2);
    {
      trackEffects(ref2.dep || (ref2.dep = createDep()));
    }
  }
}
function triggerRefValue(ref2, newVal) {
  ref2 = toRaw(ref2);
  const dep = ref2.dep;
  if (dep) {
    {
      triggerEffects(dep);
    }
  }
}
function isRef(r) {
  return !!(r && r.__v_isRef === true);
}
function ref(value) {
  return createRef(value, false);
}
function shallowRef(value) {
  return createRef(value, true);
}
function createRef(rawValue, shallow) {
  if (isRef(rawValue)) {
    return rawValue;
  }
  return new RefImpl(rawValue, shallow);
}
class RefImpl {
  constructor(value, __v_isShallow) {
    this.__v_isShallow = __v_isShallow;
    this.dep = void 0;
    this.__v_isRef = true;
    this._rawValue = __v_isShallow ? value : toRaw(value);
    this._value = __v_isShallow ? value : toReactive(value);
  }
  get value() {
    trackRefValue(this);
    return this._value;
  }
  set value(newVal) {
    const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
    newVal = useDirectValue ? newVal : toRaw(newVal);
    if (hasChanged(newVal, this._rawValue)) {
      this._rawValue = newVal;
      this._value = useDirectValue ? newVal : toReactive(newVal);
      triggerRefValue(this);
    }
  }
}
function unref(ref2) {
  return isRef(ref2) ? ref2.value : ref2;
}
const shallowUnwrapHandlers = {
  get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
  set: (target, key, value, receiver) => {
    const oldValue = target[key];
    if (isRef(oldValue) && !isRef(value)) {
      oldValue.value = value;
      return true;
    } else {
      return Reflect.set(target, key, value, receiver);
    }
  }
};
function proxyRefs(objectWithRefs) {
  return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers);
}
class CustomRefImpl {
  constructor(factory) {
    this.dep = void 0;
    this.__v_isRef = true;
    const { get, set } = factory(
      () => trackRefValue(this),
      () => triggerRefValue(this)
    );
    this._get = get;
    this._set = set;
  }
  get value() {
    return this._get();
  }
  set value(newVal) {
    this._set(newVal);
  }
}
function customRef(factory) {
  return new CustomRefImpl(factory);
}
function toRefs(object) {
  const ret = isArray$k(object) ? new Array(object.length) : {};
  for (const key in object) {
    ret[key] = propertyToRef(object, key);
  }
  return ret;
}
class ObjectRefImpl {
  constructor(_object, _key, _defaultValue) {
    this._object = _object;
    this._key = _key;
    this._defaultValue = _defaultValue;
    this.__v_isRef = true;
  }
  get value() {
    const val = this._object[this._key];
    return val === void 0 ? this._defaultValue : val;
  }
  set value(newVal) {
    this._object[this._key] = newVal;
  }
  get dep() {
    return getDepFromReactive(toRaw(this._object), this._key);
  }
}
class GetterRefImpl {
  constructor(_getter) {
    this._getter = _getter;
    this.__v_isRef = true;
    this.__v_isReadonly = true;
  }
  get value() {
    return this._getter();
  }
}
function toRef$1(source, key, defaultValue) {
  if (isRef(source)) {
    return source;
  } else if (isFunction$1(source)) {
    return new GetterRefImpl(source);
  } else if (isObject$o(source) && arguments.length > 1) {
    return propertyToRef(source, key, defaultValue);
  } else {
    return ref(source);
  }
}
function propertyToRef(source, key, defaultValue) {
  const val = source[key];
  return isRef(val) ? val : new ObjectRefImpl(source, key, defaultValue);
}

class ComputedRefImpl {
  constructor(getter, _setter, isReadonly, isSSR) {
    this._setter = _setter;
    this.dep = void 0;
    this.__v_isRef = true;
    this["__v_isReadonly"] = false;
    this._dirty = true;
    this.effect = new ReactiveEffect(getter, () => {
      if (!this._dirty) {
        this._dirty = true;
        triggerRefValue(this);
      }
    });
    this.effect.computed = this;
    this.effect.active = this._cacheable = !isSSR;
    this["__v_isReadonly"] = isReadonly;
  }
  get value() {
    const self = toRaw(this);
    trackRefValue(self);
    if (self._dirty || !self._cacheable) {
      self._dirty = false;
      self._value = self.effect.run();
    }
    return self._value;
  }
  set value(newValue) {
    this._setter(newValue);
  }
}
function computed$1(getterOrOptions, debugOptions, isSSR = false) {
  let getter;
  let setter;
  const onlyGetter = isFunction$1(getterOrOptions);
  if (onlyGetter) {
    getter = getterOrOptions;
    setter = NOOP;
  } else {
    getter = getterOrOptions.get;
    setter = getterOrOptions.set;
  }
  const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR);
  return cRef;
}

/* Injected with object hook! */

function warn(msg, ...args) {
  return;
}
function callWithErrorHandling(fn, instance, type, args) {
  let res;
  try {
    res = args ? fn(...args) : fn();
  } catch (err) {
    handleError(err, instance, type);
  }
  return res;
}
function callWithAsyncErrorHandling(fn, instance, type, args) {
  if (isFunction$1(fn)) {
    const res = callWithErrorHandling(fn, instance, type, args);
    if (res && isPromise(res)) {
      res.catch((err) => {
        handleError(err, instance, type);
      });
    }
    return res;
  }
  const values = [];
  for (let i = 0; i < fn.length; i++) {
    values.push(callWithAsyncErrorHandling(fn[i], instance, type, args));
  }
  return values;
}
function handleError(err, instance, type, throwInDev = true) {
  const contextVNode = instance ? instance.vnode : null;
  if (instance) {
    let cur = instance.parent;
    const exposedInstance = instance.proxy;
    const errorInfo = type;
    while (cur) {
      const errorCapturedHooks = cur.ec;
      if (errorCapturedHooks) {
        for (let i = 0; i < errorCapturedHooks.length; i++) {
          if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) {
            return;
          }
        }
      }
      cur = cur.parent;
    }
    const appErrorHandler = instance.appContext.config.errorHandler;
    if (appErrorHandler) {
      callWithErrorHandling(
        appErrorHandler,
        null,
        10,
        [err, exposedInstance, errorInfo]
      );
      return;
    }
  }
  logError$1(err, type, contextVNode, throwInDev);
}
function logError$1(err, type, contextVNode, throwInDev = true) {
  {
    console.error(err);
  }
}

let isFlushing = false;
let isFlushPending = false;
const queue$3 = [];
let flushIndex = 0;
const pendingPostFlushCbs = [];
let activePostFlushCbs = null;
let postFlushIndex = 0;
const resolvedPromise = /* @__PURE__ */ Promise.resolve();
let currentFlushPromise = null;
function nextTick(fn) {
  const p = currentFlushPromise || resolvedPromise;
  return fn ? p.then(this ? fn.bind(this) : fn) : p;
}
function findInsertionIndex(id) {
  let start = flushIndex + 1;
  let end = queue$3.length;
  while (start < end) {
    const middle = start + end >>> 1;
    const middleJob = queue$3[middle];
    const middleJobId = getId$1(middleJob);
    if (middleJobId < id || middleJobId === id && middleJob.pre) {
      start = middle + 1;
    } else {
      end = middle;
    }
  }
  return start;
}
function queueJob(job) {
  if (!queue$3.length || !queue$3.includes(
    job,
    isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex
  )) {
    if (job.id == null) {
      queue$3.push(job);
    } else {
      queue$3.splice(findInsertionIndex(job.id), 0, job);
    }
    queueFlush();
  }
}
function queueFlush() {
  if (!isFlushing && !isFlushPending) {
    isFlushPending = true;
    currentFlushPromise = resolvedPromise.then(flushJobs);
  }
}
function invalidateJob(job) {
  const i = queue$3.indexOf(job);
  if (i > flushIndex) {
    queue$3.splice(i, 1);
  }
}
function queuePostFlushCb(cb) {
  if (!isArray$k(cb)) {
    if (!activePostFlushCbs || !activePostFlushCbs.includes(
      cb,
      cb.allowRecurse ? postFlushIndex + 1 : postFlushIndex
    )) {
      pendingPostFlushCbs.push(cb);
    }
  } else {
    pendingPostFlushCbs.push(...cb);
  }
  queueFlush();
}
function flushPreFlushCbs(seen, i = isFlushing ? flushIndex + 1 : 0) {
  for (; i < queue$3.length; i++) {
    const cb = queue$3[i];
    if (cb && cb.pre) {
      queue$3.splice(i, 1);
      i--;
      cb();
    }
  }
}
function flushPostFlushCbs(seen) {
  if (pendingPostFlushCbs.length) {
    const deduped = [...new Set(pendingPostFlushCbs)];
    pendingPostFlushCbs.length = 0;
    if (activePostFlushCbs) {
      activePostFlushCbs.push(...deduped);
      return;
    }
    activePostFlushCbs = deduped;
    activePostFlushCbs.sort((a, b) => getId$1(a) - getId$1(b));
    for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) {
      activePostFlushCbs[postFlushIndex]();
    }
    activePostFlushCbs = null;
    postFlushIndex = 0;
  }
}
const getId$1 = (job) => job.id == null ? Infinity : job.id;
const comparator = (a, b) => {
  const diff = getId$1(a) - getId$1(b);
  if (diff === 0) {
    if (a.pre && !b.pre)
      return -1;
    if (b.pre && !a.pre)
      return 1;
  }
  return diff;
};
function flushJobs(seen) {
  isFlushPending = false;
  isFlushing = true;
  queue$3.sort(comparator);
  const check = NOOP;
  try {
    for (flushIndex = 0; flushIndex < queue$3.length; flushIndex++) {
      const job = queue$3[flushIndex];
      if (job && job.active !== false) {
        if (!!("production" !== "production") && check(job)) ;
        callWithErrorHandling(job, null, 14);
      }
    }
  } finally {
    flushIndex = 0;
    queue$3.length = 0;
    flushPostFlushCbs();
    isFlushing = false;
    currentFlushPromise = null;
    if (queue$3.length || pendingPostFlushCbs.length) {
      flushJobs();
    }
  }
}

function emit(instance, event, ...rawArgs) {
  if (instance.isUnmounted)
    return;
  const props = instance.vnode.props || EMPTY_OBJ$1;
  let args = rawArgs;
  const isModelListener = event.startsWith("update:");
  const modelArg = isModelListener && event.slice(7);
  if (modelArg && modelArg in props) {
    const modifiersKey = `${modelArg === "modelValue" ? "model" : modelArg}Modifiers`;
    const { number, trim } = props[modifiersKey] || EMPTY_OBJ$1;
    if (trim) {
      args = rawArgs.map((a) => isString$3(a) ? a.trim() : a);
    }
    if (number) {
      args = rawArgs.map(looseToNumber);
    }
  }
  let handlerName;
  let handler = props[handlerName = toHandlerKey(event)] || // also try camelCase event handler (#2249)
  props[handlerName = toHandlerKey(camelize(event))];
  if (!handler && isModelListener) {
    handler = props[handlerName = toHandlerKey(hyphenate(event))];
  }
  if (handler) {
    callWithAsyncErrorHandling(
      handler,
      instance,
      6,
      args
    );
  }
  const onceHandler = props[handlerName + `Once`];
  if (onceHandler) {
    if (!instance.emitted) {
      instance.emitted = {};
    } else if (instance.emitted[handlerName]) {
      return;
    }
    instance.emitted[handlerName] = true;
    callWithAsyncErrorHandling(
      onceHandler,
      instance,
      6,
      args
    );
  }
}
function normalizeEmitsOptions(comp, appContext, asMixin = false) {
  const cache = appContext.emitsCache;
  const cached = cache.get(comp);
  if (cached !== void 0) {
    return cached;
  }
  const raw = comp.emits;
  let normalized = {};
  let hasExtends = false;
  if (!isFunction$1(comp)) {
    const extendEmits = (raw2) => {
      const normalizedFromExtend = normalizeEmitsOptions(raw2, appContext, true);
      if (normalizedFromExtend) {
        hasExtends = true;
        extend$3(normalized, normalizedFromExtend);
      }
    };
    if (!asMixin && appContext.mixins.length) {
      appContext.mixins.forEach(extendEmits);
    }
    if (comp.extends) {
      extendEmits(comp.extends);
    }
    if (comp.mixins) {
      comp.mixins.forEach(extendEmits);
    }
  }
  if (!raw && !hasExtends) {
    if (isObject$o(comp)) {
      cache.set(comp, null);
    }
    return null;
  }
  if (isArray$k(raw)) {
    raw.forEach((key) => normalized[key] = null);
  } else {
    extend$3(normalized, raw);
  }
  if (isObject$o(comp)) {
    cache.set(comp, normalized);
  }
  return normalized;
}
function isEmitListener(options, key) {
  if (!options || !isOn(key)) {
    return false;
  }
  key = key.slice(2).replace(/Once$/, "");
  return hasOwn$m(options, key[0].toLowerCase() + key.slice(1)) || hasOwn$m(options, hyphenate(key)) || hasOwn$m(options, key);
}

let currentRenderingInstance = null;
let currentScopeId = null;
function setCurrentRenderingInstance(instance) {
  const prev = currentRenderingInstance;
  currentRenderingInstance = instance;
  currentScopeId = instance && instance.type.__scopeId || null;
  return prev;
}
function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) {
  if (!ctx)
    return fn;
  if (fn._n) {
    return fn;
  }
  const renderFnWithContext = (...args) => {
    if (renderFnWithContext._d) {
      setBlockTracking(-1);
    }
    const prevInstance = setCurrentRenderingInstance(ctx);
    let res;
    try {
      res = fn(...args);
    } finally {
      setCurrentRenderingInstance(prevInstance);
      if (renderFnWithContext._d) {
        setBlockTracking(1);
      }
    }
    return res;
  };
  renderFnWithContext._n = true;
  renderFnWithContext._c = true;
  renderFnWithContext._d = true;
  return renderFnWithContext;
}
function markAttrsAccessed() {
}
function renderComponentRoot(instance) {
  const {
    type: Component,
    vnode,
    proxy,
    withProxy,
    props,
    propsOptions: [propsOptions],
    slots,
    attrs,
    emit,
    render,
    renderCache,
    data,
    setupState,
    ctx,
    inheritAttrs
  } = instance;
  let result;
  let fallthroughAttrs;
  const prev = setCurrentRenderingInstance(instance);
  try {
    if (vnode.shapeFlag & 4) {
      const proxyToUse = withProxy || proxy;
      result = normalizeVNode(
        render.call(
          proxyToUse,
          proxyToUse,
          renderCache,
          props,
          setupState,
          data,
          ctx
        )
      );
      fallthroughAttrs = attrs;
    } else {
      const render2 = Component;
      if (!!("production" !== "production") && attrs === props) ;
      result = normalizeVNode(
        render2.length > 1 ? render2(
          props,
          !!("production" !== "production") ? {
            get attrs() {
              markAttrsAccessed();
              return attrs;
            },
            slots,
            emit
          } : { attrs, slots, emit }
        ) : render2(
          props,
          null
          /* we know it doesn't need it */
        )
      );
      fallthroughAttrs = Component.props ? attrs : getFunctionalFallthrough(attrs);
    }
  } catch (err) {
    blockStack.length = 0;
    handleError(err, instance, 1);
    result = createVNode(Comment);
  }
  let root = result;
  if (fallthroughAttrs && inheritAttrs !== false) {
    const keys = Object.keys(fallthroughAttrs);
    const { shapeFlag } = root;
    if (keys.length) {
      if (shapeFlag & (1 | 6)) {
        if (propsOptions && keys.some(isModelListener)) {
          fallthroughAttrs = filterModelListeners(
            fallthroughAttrs,
            propsOptions
          );
        }
        root = cloneVNode(root, fallthroughAttrs);
      }
    }
  }
  if (vnode.dirs) {
    root = cloneVNode(root);
    root.dirs = root.dirs ? root.dirs.concat(vnode.dirs) : vnode.dirs;
  }
  if (vnode.transition) {
    root.transition = vnode.transition;
  }
  {
    result = root;
  }
  setCurrentRenderingInstance(prev);
  return result;
}
function filterSingleRoot(children) {
  let singleRoot;
  for (let i = 0; i < children.length; i++) {
    const child = children[i];
    if (isVNode(child)) {
      if (child.type !== Comment || child.children === "v-if") {
        if (singleRoot) {
          return;
        } else {
          singleRoot = child;
        }
      }
    } else {
      return;
    }
  }
  return singleRoot;
}
const getFunctionalFallthrough = (attrs) => {
  let res;
  for (const key in attrs) {
    if (key === "class" || key === "style" || isOn(key)) {
      (res || (res = {}))[key] = attrs[key];
    }
  }
  return res;
};
const filterModelListeners = (attrs, props) => {
  const res = {};
  for (const key in attrs) {
    if (!isModelListener(key) || !(key.slice(9) in props)) {
      res[key] = attrs[key];
    }
  }
  return res;
};
function shouldUpdateComponent(prevVNode, nextVNode, optimized) {
  const { props: prevProps, children: prevChildren, component } = prevVNode;
  const { props: nextProps, children: nextChildren, patchFlag } = nextVNode;
  const emits = component.emitsOptions;
  if (nextVNode.dirs || nextVNode.transition) {
    return true;
  }
  if (optimized && patchFlag >= 0) {
    if (patchFlag & 1024) {
      return true;
    }
    if (patchFlag & 16) {
      if (!prevProps) {
        return !!nextProps;
      }
      return hasPropsChanged(prevProps, nextProps, emits);
    } else if (patchFlag & 8) {
      const dynamicProps = nextVNode.dynamicProps;
      for (let i = 0; i < dynamicProps.length; i++) {
        const key = dynamicProps[i];
        if (nextProps[key] !== prevProps[key] && !isEmitListener(emits, key)) {
          return true;
        }
      }
    }
  } else {
    if (prevChildren || nextChildren) {
      if (!nextChildren || !nextChildren.$stable) {
        return true;
      }
    }
    if (prevProps === nextProps) {
      return false;
    }
    if (!prevProps) {
      return !!nextProps;
    }
    if (!nextProps) {
      return true;
    }
    return hasPropsChanged(prevProps, nextProps, emits);
  }
  return false;
}
function hasPropsChanged(prevProps, nextProps, emitsOptions) {
  const nextKeys = Object.keys(nextProps);
  if (nextKeys.length !== Object.keys(prevProps).length) {
    return true;
  }
  for (let i = 0; i < nextKeys.length; i++) {
    const key = nextKeys[i];
    if (nextProps[key] !== prevProps[key] && !isEmitListener(emitsOptions, key)) {
      return true;
    }
  }
  return false;
}
function updateHOCHostEl({ vnode, parent }, el) {
  while (parent && parent.subTree === vnode) {
    (vnode = parent.vnode).el = el;
    parent = parent.parent;
  }
}

const COMPONENTS = "components";
function resolveComponent(name, maybeSelfReference) {
  return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name;
}
const NULL_DYNAMIC_COMPONENT = Symbol.for("v-ndc");
function resolveDynamicComponent(component) {
  if (isString$3(component)) {
    return resolveAsset(COMPONENTS, component, false) || component;
  } else {
    return component || NULL_DYNAMIC_COMPONENT;
  }
}
function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) {
  const instance = currentRenderingInstance || currentInstance;
  if (instance) {
    const Component = instance.type;
    if (type === COMPONENTS) {
      const selfName = getComponentName(
        Component,
        false
        /* do not include inferred name to avoid breaking existing code */
      );
      if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) {
        return Component;
      }
    }
    const res = (
      // local registration
      // check instance[type] first which is resolved for options API
      resolve(instance[type] || Component[type], name) || // global registration
      resolve(instance.appContext[type], name)
    );
    if (!res && maybeSelfReference) {
      return Component;
    }
    return res;
  }
}
function resolve(registry, name) {
  return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]);
}

const isSuspense = (type) => type.__isSuspense;
const SuspenseImpl = {
  name: "Suspense",
  // In order to make Suspense tree-shakable, we need to avoid importing it
  // directly in the renderer. The renderer checks for the __isSuspense flag
  // on a vnode's type and calls the `process` method, passing in renderer
  // internals.
  __isSuspense: true,
  process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, rendererInternals) {
    if (n1 == null) {
      mountSuspense(
        n2,
        container,
        anchor,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized,
        rendererInternals
      );
    } else {
      patchSuspense(
        n1,
        n2,
        container,
        anchor,
        parentComponent,
        isSVG,
        slotScopeIds,
        optimized,
        rendererInternals
      );
    }
  },
  hydrate: hydrateSuspense,
  create: createSuspenseBoundary,
  normalize: normalizeSuspenseChildren
};
const Suspense = SuspenseImpl ;
function triggerEvent(vnode, name) {
  const eventListener = vnode.props && vnode.props[name];
  if (isFunction$1(eventListener)) {
    eventListener();
  }
}
function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, rendererInternals) {
  const {
    p: patch,
    o: { createElement }
  } = rendererInternals;
  const hiddenContainer = createElement("div");
  const suspense = vnode.suspense = createSuspenseBoundary(
    vnode,
    parentSuspense,
    parentComponent,
    container,
    hiddenContainer,
    anchor,
    isSVG,
    slotScopeIds,
    optimized,
    rendererInternals
  );
  patch(
    null,
    suspense.pendingBranch = vnode.ssContent,
    hiddenContainer,
    null,
    parentComponent,
    suspense,
    isSVG,
    slotScopeIds
  );
  if (suspense.deps > 0) {
    triggerEvent(vnode, "onPending");
    triggerEvent(vnode, "onFallback");
    patch(
      null,
      vnode.ssFallback,
      container,
      anchor,
      parentComponent,
      null,
      // fallback tree will not have suspense context
      isSVG,
      slotScopeIds
    );
    setActiveBranch(suspense, vnode.ssFallback);
  } else {
    suspense.resolve(false, true);
  }
}
function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotScopeIds, optimized, { p: patch, um: unmount, o: { createElement } }) {
  const suspense = n2.suspense = n1.suspense;
  suspense.vnode = n2;
  n2.el = n1.el;
  const newBranch = n2.ssContent;
  const newFallback = n2.ssFallback;
  const { activeBranch, pendingBranch, isInFallback, isHydrating } = suspense;
  if (pendingBranch) {
    suspense.pendingBranch = newBranch;
    if (isSameVNodeType(newBranch, pendingBranch)) {
      patch(
        pendingBranch,
        newBranch,
        suspense.hiddenContainer,
        null,
        parentComponent,
        suspense,
        isSVG,
        slotScopeIds,
        optimized
      );
      if (suspense.deps <= 0) {
        suspense.resolve();
      } else if (isInFallback) {
        patch(
          activeBranch,
          newFallback,
          container,
          anchor,
          parentComponent,
          null,
          // fallback tree will not have suspense context
          isSVG,
          slotScopeIds,
          optimized
        );
        setActiveBranch(suspense, newFallback);
      }
    } else {
      suspense.pendingId++;
      if (isHydrating) {
        suspense.isHydrating = false;
        suspense.activeBranch = pendingBranch;
      } else {
        unmount(pendingBranch, parentComponent, suspense);
      }
      suspense.deps = 0;
      suspense.effects.length = 0;
      suspense.hiddenContainer = createElement("div");
      if (isInFallback) {
        patch(
          null,
          newBranch,
          suspense.hiddenContainer,
          null,
          parentComponent,
          suspense,
          isSVG,
          slotScopeIds,
          optimized
        );
        if (suspense.deps <= 0) {
          suspense.resolve();
        } else {
          patch(
            activeBranch,
            newFallback,
            container,
            anchor,
            parentComponent,
            null,
            // fallback tree will not have suspense context
            isSVG,
            slotScopeIds,
            optimized
          );
          setActiveBranch(suspense, newFallback);
        }
      } else if (activeBranch && isSameVNodeType(newBranch, activeBranch)) {
        patch(
          activeBranch,
          newBranch,
          container,
          anchor,
          parentComponent,
          suspense,
          isSVG,
          slotScopeIds,
          optimized
        );
        suspense.resolve(true);
      } else {
        patch(
          null,
          newBranch,
          suspense.hiddenContainer,
          null,
          parentComponent,
          suspense,
          isSVG,
          slotScopeIds,
          optimized
        );
        if (suspense.deps <= 0) {
          suspense.resolve();
        }
      }
    }
  } else {
    if (activeBranch && isSameVNodeType(newBranch, activeBranch)) {
      patch(
        activeBranch,
        newBranch,
        container,
        anchor,
        parentComponent,
        suspense,
        isSVG,
        slotScopeIds,
        optimized
      );
      setActiveBranch(suspense, newBranch);
    } else {
      triggerEvent(n2, "onPending");
      suspense.pendingBranch = newBranch;
      suspense.pendingId++;
      patch(
        null,
        newBranch,
        suspense.hiddenContainer,
        null,
        parentComponent,
        suspense,
        isSVG,
        slotScopeIds,
        optimized
      );
      if (suspense.deps <= 0) {
        suspense.resolve();
      } else {
        const { timeout, pendingId } = suspense;
        if (timeout > 0) {
          setTimeout(() => {
            if (suspense.pendingId === pendingId) {
              suspense.fallback(newFallback);
            }
          }, timeout);
        } else if (timeout === 0) {
          suspense.fallback(newFallback);
        }
      }
    }
  }
}
function createSuspenseBoundary(vnode, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, slotScopeIds, optimized, rendererInternals, isHydrating = false) {
  const {
    p: patch,
    m: move,
    um: unmount,
    n: next,
    o: { parentNode, remove }
  } = rendererInternals;
  let parentSuspenseId;
  const isSuspensible = isVNodeSuspensible(vnode);
  if (isSuspensible) {
    if (parentSuspense == null ? void 0 : parentSuspense.pendingBranch) {
      parentSuspenseId = parentSuspense.pendingId;
      parentSuspense.deps++;
    }
  }
  const timeout = vnode.props ? toNumber(vnode.props.timeout) : void 0;
  const suspense = {
    vnode,
    parent: parentSuspense,
    parentComponent,
    isSVG,
    container,
    hiddenContainer,
    anchor,
    deps: 0,
    pendingId: 0,
    timeout: typeof timeout === "number" ? timeout : -1,
    activeBranch: null,
    pendingBranch: null,
    isInFallback: true,
    isHydrating,
    isUnmounted: false,
    effects: [],
    resolve(resume = false, sync = false) {
      const {
        vnode: vnode2,
        activeBranch,
        pendingBranch,
        pendingId,
        effects,
        parentComponent: parentComponent2,
        container: container2
      } = suspense;
      let delayEnter = false;
      if (suspense.isHydrating) {
        suspense.isHydrating = false;
      } else if (!resume) {
        delayEnter = activeBranch && pendingBranch.transition && pendingBranch.transition.mode === "out-in";
        if (delayEnter) {
          activeBranch.transition.afterLeave = () => {
            if (pendingId === suspense.pendingId) {
              move(pendingBranch, container2, anchor2, 0);
              queuePostFlushCb(effects);
            }
          };
        }
        let { anchor: anchor2 } = suspense;
        if (activeBranch) {
          anchor2 = next(activeBranch);
          unmount(activeBranch, parentComponent2, suspense, true);
        }
        if (!delayEnter) {
          move(pendingBranch, container2, anchor2, 0);
        }
      }
      setActiveBranch(suspense, pendingBranch);
      suspense.pendingBranch = null;
      suspense.isInFallback = false;
      let parent = suspense.parent;
      let hasUnresolvedAncestor = false;
      while (parent) {
        if (parent.pendingBranch) {
          parent.effects.push(...effects);
          hasUnresolvedAncestor = true;
          break;
        }
        parent = parent.parent;
      }
      if (!hasUnresolvedAncestor && !delayEnter) {
        queuePostFlushCb(effects);
      }
      suspense.effects = [];
      if (isSuspensible) {
        if (parentSuspense && parentSuspense.pendingBranch && parentSuspenseId === parentSuspense.pendingId) {
          parentSuspense.deps--;
          if (parentSuspense.deps === 0 && !sync) {
            parentSuspense.resolve();
          }
        }
      }
      triggerEvent(vnode2, "onResolve");
    },
    fallback(fallbackVNode) {
      if (!suspense.pendingBranch) {
        return;
      }
      const { vnode: vnode2, activeBranch, parentComponent: parentComponent2, container: container2, isSVG: isSVG2 } = suspense;
      triggerEvent(vnode2, "onFallback");
      const anchor2 = next(activeBranch);
      const mountFallback = () => {
        if (!suspense.isInFallback) {
          return;
        }
        patch(
          null,
          fallbackVNode,
          container2,
          anchor2,
          parentComponent2,
          null,
          // fallback tree will not have suspense context
          isSVG2,
          slotScopeIds,
          optimized
        );
        setActiveBranch(suspense, fallbackVNode);
      };
      const delayEnter = fallbackVNode.transition && fallbackVNode.transition.mode === "out-in";
      if (delayEnter) {
        activeBranch.transition.afterLeave = mountFallback;
      }
      suspense.isInFallback = true;
      unmount(
        activeBranch,
        parentComponent2,
        null,
        // no suspense so unmount hooks fire now
        true
        // shouldRemove
      );
      if (!delayEnter) {
        mountFallback();
      }
    },
    move(container2, anchor2, type) {
      suspense.activeBranch && move(suspense.activeBranch, container2, anchor2, type);
      suspense.container = container2;
    },
    next() {
      return suspense.activeBranch && next(suspense.activeBranch);
    },
    registerDep(instance, setupRenderEffect) {
      const isInPendingSuspense = !!suspense.pendingBranch;
      if (isInPendingSuspense) {
        suspense.deps++;
      }
      const hydratedEl = instance.vnode.el;
      instance.asyncDep.catch((err) => {
        handleError(err, instance, 0);
      }).then((asyncSetupResult) => {
        if (instance.isUnmounted || suspense.isUnmounted || suspense.pendingId !== instance.suspenseId) {
          return;
        }
        instance.asyncResolved = true;
        const { vnode: vnode2 } = instance;
        handleSetupResult(instance, asyncSetupResult, false);
        if (hydratedEl) {
          vnode2.el = hydratedEl;
        }
        const placeholder = !hydratedEl && instance.subTree.el;
        setupRenderEffect(
          instance,
          vnode2,
          // component may have been moved before resolve.
          // if this is not a hydration, instance.subTree will be the comment
          // placeholder.
          parentNode(hydratedEl || instance.subTree.el),
          // anchor will not be used if this is hydration, so only need to
          // consider the comment placeholder case.
          hydratedEl ? null : next(instance.subTree),
          suspense,
          isSVG,
          optimized
        );
        if (placeholder) {
          remove(placeholder);
        }
        updateHOCHostEl(instance, vnode2.el);
        if (isInPendingSuspense && --suspense.deps === 0) {
          suspense.resolve();
        }
      });
    },
    unmount(parentSuspense2, doRemove) {
      suspense.isUnmounted = true;
      if (suspense.activeBranch) {
        unmount(
          suspense.activeBranch,
          parentComponent,
          parentSuspense2,
          doRemove
        );
      }
      if (suspense.pendingBranch) {
        unmount(
          suspense.pendingBranch,
          parentComponent,
          parentSuspense2,
          doRemove
        );
      }
    }
  };
  return suspense;
}
function hydrateSuspense(node, vnode, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, rendererInternals, hydrateNode) {
  const suspense = vnode.suspense = createSuspenseBoundary(
    vnode,
    parentSuspense,
    parentComponent,
    node.parentNode,
    document.createElement("div"),
    null,
    isSVG,
    slotScopeIds,
    optimized,
    rendererInternals,
    true
    /* hydrating */
  );
  const result = hydrateNode(
    node,
    suspense.pendingBranch = vnode.ssContent,
    parentComponent,
    suspense,
    slotScopeIds,
    optimized
  );
  if (suspense.deps === 0) {
    suspense.resolve(false, true);
  }
  return result;
}
function normalizeSuspenseChildren(vnode) {
  const { shapeFlag, children } = vnode;
  const isSlotChildren = shapeFlag & 32;
  vnode.ssContent = normalizeSuspenseSlot(
    isSlotChildren ? children.default : children
  );
  vnode.ssFallback = isSlotChildren ? normalizeSuspenseSlot(children.fallback) : createVNode(Comment);
}
function normalizeSuspenseSlot(s) {
  let block;
  if (isFunction$1(s)) {
    const trackBlock = isBlockTreeEnabled && s._c;
    if (trackBlock) {
      s._d = false;
      openBlock();
    }
    s = s();
    if (trackBlock) {
      s._d = true;
      block = currentBlock;
      closeBlock();
    }
  }
  if (isArray$k(s)) {
    const singleChild = filterSingleRoot(s);
    s = singleChild;
  }
  s = normalizeVNode(s);
  if (block && !s.dynamicChildren) {
    s.dynamicChildren = block.filter((c) => c !== s);
  }
  return s;
}
function queueEffectWithSuspense(fn, suspense) {
  if (suspense && suspense.pendingBranch) {
    if (isArray$k(fn)) {
      suspense.effects.push(...fn);
    } else {
      suspense.effects.push(fn);
    }
  } else {
    queuePostFlushCb(fn);
  }
}
function setActiveBranch(suspense, branch) {
  suspense.activeBranch = branch;
  const { vnode, parentComponent } = suspense;
  const el = vnode.el = branch.el;
  if (parentComponent && parentComponent.subTree === vnode) {
    parentComponent.vnode.el = el;
    updateHOCHostEl(parentComponent, el);
  }
}
function isVNodeSuspensible(vnode) {
  var _a;
  return ((_a = vnode.props) == null ? void 0 : _a.suspensible) != null && vnode.props.suspensible !== false;
}

function watchEffect(effect, options) {
  return doWatch(effect, null, options);
}
const INITIAL_WATCHER_VALUE = {};
function watch(source, cb, options) {
  return doWatch(source, cb, options);
}
function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ$1) {
  var _a;
  const instance = getCurrentScope() === ((_a = currentInstance) == null ? void 0 : _a.scope) ? currentInstance : null;
  let getter;
  let forceTrigger = false;
  let isMultiSource = false;
  if (isRef(source)) {
    getter = () => source.value;
    forceTrigger = isShallow(source);
  } else if (isReactive(source)) {
    getter = () => source;
    deep = true;
  } else if (isArray$k(source)) {
    isMultiSource = true;
    forceTrigger = source.some((s) => isReactive(s) || isShallow(s));
    getter = () => source.map((s) => {
      if (isRef(s)) {
        return s.value;
      } else if (isReactive(s)) {
        return traverse(s);
      } else if (isFunction$1(s)) {
        return callWithErrorHandling(s, instance, 2);
      } else ;
    });
  } else if (isFunction$1(source)) {
    if (cb) {
      getter = () => callWithErrorHandling(source, instance, 2);
    } else {
      getter = () => {
        if (instance && instance.isUnmounted) {
          return;
        }
        if (cleanup) {
          cleanup();
        }
        return callWithAsyncErrorHandling(
          source,
          instance,
          3,
          [onCleanup]
        );
      };
    }
  } else {
    getter = NOOP;
  }
  if (cb && deep) {
    const baseGetter = getter;
    getter = () => traverse(baseGetter());
  }
  let cleanup;
  let onCleanup = (fn) => {
    cleanup = effect.onStop = () => {
      callWithErrorHandling(fn, instance, 4);
    };
  };
  let ssrCleanup;
  if (isInSSRComponentSetup) {
    onCleanup = NOOP;
    if (!cb) {
      getter();
    } else if (immediate) {
      callWithAsyncErrorHandling(cb, instance, 3, [
        getter(),
        isMultiSource ? [] : void 0,
        onCleanup
      ]);
    }
    if (flush === "sync") {
      const ctx = useSSRContext();
      ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = []);
    } else {
      return NOOP;
    }
  }
  let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE;
  const job = () => {
    if (!effect.active) {
      return;
    }
    if (cb) {
      const newValue = effect.run();
      if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue)) || false) {
        if (cleanup) {
          cleanup();
        }
        callWithAsyncErrorHandling(cb, instance, 3, [
          newValue,
          // pass undefined as the old value when it's changed for the first time
          oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue,
          onCleanup
        ]);
        oldValue = newValue;
      }
    } else {
      effect.run();
    }
  };
  job.allowRecurse = !!cb;
  let scheduler;
  if (flush === "sync") {
    scheduler = job;
  } else if (flush === "post") {
    scheduler = () => queuePostRenderEffect(job, instance && instance.suspense);
  } else {
    job.pre = true;
    if (instance)
      job.id = instance.uid;
    scheduler = () => queueJob(job);
  }
  const effect = new ReactiveEffect(getter, scheduler);
  if (cb) {
    if (immediate) {
      job();
    } else {
      oldValue = effect.run();
    }
  } else if (flush === "post") {
    queuePostRenderEffect(
      effect.run.bind(effect),
      instance && instance.suspense
    );
  } else {
    effect.run();
  }
  const unwatch = () => {
    effect.stop();
    if (instance && instance.scope) {
      remove(instance.scope.effects, effect);
    }
  };
  if (ssrCleanup)
    ssrCleanup.push(unwatch);
  return unwatch;
}
function instanceWatch(source, value, options) {
  const publicThis = this.proxy;
  const getter = isString$3(source) ? source.includes(".") ? createPathGetter(publicThis, source) : () => publicThis[source] : source.bind(publicThis, publicThis);
  let cb;
  if (isFunction$1(value)) {
    cb = value;
  } else {
    cb = value.handler;
    options = value;
  }
  const cur = currentInstance;
  setCurrentInstance(this);
  const res = doWatch(getter, cb.bind(publicThis), options);
  if (cur) {
    setCurrentInstance(cur);
  } else {
    unsetCurrentInstance();
  }
  return res;
}
function createPathGetter(ctx, path) {
  const segments = path.split(".");
  return () => {
    let cur = ctx;
    for (let i = 0; i < segments.length && cur; i++) {
      cur = cur[segments[i]];
    }
    return cur;
  };
}
function traverse(value, seen) {
  if (!isObject$o(value) || value["__v_skip"]) {
    return value;
  }
  seen = seen || /* @__PURE__ */ new Set();
  if (seen.has(value)) {
    return value;
  }
  seen.add(value);
  if (isRef(value)) {
    traverse(value.value, seen);
  } else if (isArray$k(value)) {
    for (let i = 0; i < value.length; i++) {
      traverse(value[i], seen);
    }
  } else if (isSet(value) || isMap(value)) {
    value.forEach((v) => {
      traverse(v, seen);
    });
  } else if (isPlainObject(value)) {
    for (const key in value) {
      traverse(value[key], seen);
    }
  }
  return value;
}
function withDirectives(vnode, directives) {
  const internalInstance = currentRenderingInstance;
  if (internalInstance === null) {
    return vnode;
  }
  const instance = getExposeProxy(internalInstance) || internalInstance.proxy;
  const bindings = vnode.dirs || (vnode.dirs = []);
  for (let i = 0; i < directives.length; i++) {
    let [dir, value, arg, modifiers = EMPTY_OBJ$1] = directives[i];
    if (dir) {
      if (isFunction$1(dir)) {
        dir = {
          mounted: dir,
          updated: dir
        };
      }
      if (dir.deep) {
        traverse(value);
      }
      bindings.push({
        dir,
        instance,
        value,
        oldValue: void 0,
        arg,
        modifiers
      });
    }
  }
  return vnode;
}
function invokeDirectiveHook(vnode, prevVNode, instance, name) {
  const bindings = vnode.dirs;
  const oldBindings = prevVNode && prevVNode.dirs;
  for (let i = 0; i < bindings.length; i++) {
    const binding = bindings[i];
    if (oldBindings) {
      binding.oldValue = oldBindings[i].value;
    }
    let hook = binding.dir[name];
    if (hook) {
      pauseTracking();
      callWithAsyncErrorHandling(hook, instance, 8, [
        vnode.el,
        binding,
        vnode,
        prevVNode
      ]);
      resetTracking();
    }
  }
}
function setTransitionHooks(vnode, hooks) {
  if (vnode.shapeFlag & 6 && vnode.component) {
    setTransitionHooks(vnode.component.subTree, hooks);
  } else if (vnode.shapeFlag & 128) {
    vnode.ssContent.transition = hooks.clone(vnode.ssContent);
    vnode.ssFallback.transition = hooks.clone(vnode.ssFallback);
  } else {
    vnode.transition = hooks;
  }
}

/*! #__NO_SIDE_EFFECTS__ */
// @__NO_SIDE_EFFECTS__
function defineComponent(options, extraOptions) {
  return isFunction$1(options) ? (
    // #8326: extend call and options.name access are considered side-effects
    // by Rollup, so we have to wrap it in a pure-annotated IIFE.
    /* @__PURE__ */ (() => extend$3({ name: options.name }, extraOptions, { setup: options }))()
  ) : options;
}

const isAsyncWrapper = (i) => !!i.type.__asyncLoader;

const isKeepAlive = (vnode) => vnode.type.__isKeepAlive;
const KeepAliveImpl = {
  name: `KeepAlive`,
  // Marker for special handling inside the renderer. We are not using a ===
  // check directly on KeepAlive in the renderer, because importing it directly
  // would prevent it from being tree-shaken.
  __isKeepAlive: true,
  props: {
    include: [String, RegExp, Array],
    exclude: [String, RegExp, Array],
    max: [String, Number]
  },
  setup(props, { slots }) {
    const instance = getCurrentInstance();
    const sharedContext = instance.ctx;
    if (!sharedContext.renderer) {
      return () => {
        const children = slots.default && slots.default();
        return children && children.length === 1 ? children[0] : children;
      };
    }
    const cache = /* @__PURE__ */ new Map();
    const keys = /* @__PURE__ */ new Set();
    let current = null;
    const parentSuspense = instance.suspense;
    const {
      renderer: {
        p: patch,
        m: move,
        um: _unmount,
        o: { createElement }
      }
    } = sharedContext;
    const storageContainer = createElement("div");
    sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
      const instance2 = vnode.component;
      move(vnode, container, anchor, 0, parentSuspense);
      patch(
        instance2.vnode,
        vnode,
        container,
        anchor,
        instance2,
        parentSuspense,
        isSVG,
        vnode.slotScopeIds,
        optimized
      );
      queuePostRenderEffect(() => {
        instance2.isDeactivated = false;
        if (instance2.a) {
          invokeArrayFns(instance2.a);
        }
        const vnodeHook = vnode.props && vnode.props.onVnodeMounted;
        if (vnodeHook) {
          invokeVNodeHook(vnodeHook, instance2.parent, vnode);
        }
      }, parentSuspense);
    };
    sharedContext.deactivate = (vnode) => {
      const instance2 = vnode.component;
      move(vnode, storageContainer, null, 1, parentSuspense);
      queuePostRenderEffect(() => {
        if (instance2.da) {
          invokeArrayFns(instance2.da);
        }
        const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted;
        if (vnodeHook) {
          invokeVNodeHook(vnodeHook, instance2.parent, vnode);
        }
        instance2.isDeactivated = true;
      }, parentSuspense);
    };
    function unmount(vnode) {
      resetShapeFlag(vnode);
      _unmount(vnode, instance, parentSuspense, true);
    }
    function pruneCache(filter) {
      cache.forEach((vnode, key) => {
        const name = getComponentName(vnode.type);
        if (name && (!filter || !filter(name))) {
          pruneCacheEntry(key);
        }
      });
    }
    function pruneCacheEntry(key) {
      const cached = cache.get(key);
      if (!current || !isSameVNodeType(cached, current)) {
        unmount(cached);
      } else if (current) {
        resetShapeFlag(current);
      }
      cache.delete(key);
      keys.delete(key);
    }
    watch(
      () => [props.include, props.exclude],
      ([include, exclude]) => {
        include && pruneCache((name) => matches(include, name));
        exclude && pruneCache((name) => !matches(exclude, name));
      },
      // prune post-render after `current` has been updated
      { flush: "post", deep: true }
    );
    let pendingCacheKey = null;
    const cacheSubtree = () => {
      if (pendingCacheKey != null) {
        cache.set(pendingCacheKey, getInnerChild(instance.subTree));
      }
    };
    onMounted(cacheSubtree);
    onUpdated(cacheSubtree);
    onBeforeUnmount(() => {
      cache.forEach((cached) => {
        const { subTree, suspense } = instance;
        const vnode = getInnerChild(subTree);
        if (cached.type === vnode.type && cached.key === vnode.key) {
          resetShapeFlag(vnode);
          const da = vnode.component.da;
          da && queuePostRenderEffect(da, suspense);
          return;
        }
        unmount(cached);
      });
    });
    return () => {
      pendingCacheKey = null;
      if (!slots.default) {
        return null;
      }
      const children = slots.default();
      const rawVNode = children[0];
      if (children.length > 1) {
        current = null;
        return children;
      } else if (!isVNode(rawVNode) || !(rawVNode.shapeFlag & 4) && !(rawVNode.shapeFlag & 128)) {
        current = null;
        return rawVNode;
      }
      let vnode = getInnerChild(rawVNode);
      const comp = vnode.type;
      const name = getComponentName(
        isAsyncWrapper(vnode) ? vnode.type.__asyncResolved || {} : comp
      );
      const { include, exclude, max } = props;
      if (include && (!name || !matches(include, name)) || exclude && name && matches(exclude, name)) {
        current = vnode;
        return rawVNode;
      }
      const key = vnode.key == null ? comp : vnode.key;
      const cachedVNode = cache.get(key);
      if (vnode.el) {
        vnode = cloneVNode(vnode);
        if (rawVNode.shapeFlag & 128) {
          rawVNode.ssContent = vnode;
        }
      }
      pendingCacheKey = key;
      if (cachedVNode) {
        vnode.el = cachedVNode.el;
        vnode.component = cachedVNode.component;
        if (vnode.transition) {
          setTransitionHooks(vnode, vnode.transition);
        }
        vnode.shapeFlag |= 512;
        keys.delete(key);
        keys.add(key);
      } else {
        keys.add(key);
        if (max && keys.size > parseInt(max, 10)) {
          pruneCacheEntry(keys.values().next().value);
        }
      }
      vnode.shapeFlag |= 256;
      current = vnode;
      return isSuspense(rawVNode.type) ? rawVNode : vnode;
    };
  }
};
const KeepAlive = KeepAliveImpl;
function matches(pattern, name) {
  if (isArray$k(pattern)) {
    return pattern.some((p) => matches(p, name));
  } else if (isString$3(pattern)) {
    return pattern.split(",").includes(name);
  } else if (isRegExp$1(pattern)) {
    return pattern.test(name);
  }
  return false;
}
function onActivated(hook, target) {
  registerKeepAliveHook(hook, "a", target);
}
function onDeactivated(hook, target) {
  registerKeepAliveHook(hook, "da", target);
}
function registerKeepAliveHook(hook, type, target = currentInstance) {
  const wrappedHook = hook.__wdc || (hook.__wdc = () => {
    let current = target;
    while (current) {
      if (current.isDeactivated) {
        return;
      }
      current = current.parent;
    }
    return hook();
  });
  injectHook(type, wrappedHook, target);
  if (target) {
    let current = target.parent;
    while (current && current.parent) {
      if (isKeepAlive(current.parent.vnode)) {
        injectToKeepAliveRoot(wrappedHook, type, target, current);
      }
      current = current.parent;
    }
  }
}
function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) {
  const injected = injectHook(
    type,
    hook,
    keepAliveRoot,
    true
    /* prepend */
  );
  onUnmounted(() => {
    remove(keepAliveRoot[type], injected);
  }, target);
}
function resetShapeFlag(vnode) {
  vnode.shapeFlag &= ~256;
  vnode.shapeFlag &= ~512;
}
function getInnerChild(vnode) {
  return vnode.shapeFlag & 128 ? vnode.ssContent : vnode;
}

function injectHook(type, hook, target = currentInstance, prepend = false) {
  if (target) {
    const hooks = target[type] || (target[type] = []);
    const wrappedHook = hook.__weh || (hook.__weh = (...args) => {
      if (target.isUnmounted) {
        return;
      }
      pauseTracking();
      setCurrentInstance(target);
      const res = callWithAsyncErrorHandling(hook, target, type, args);
      unsetCurrentInstance();
      resetTracking();
      return res;
    });
    if (prepend) {
      hooks.unshift(wrappedHook);
    } else {
      hooks.push(wrappedHook);
    }
    return wrappedHook;
  }
}
const createHook = (lifecycle) => (hook, target = currentInstance) => (
  // post-create lifecycle registrations are noops during SSR (except for serverPrefetch)
  (!isInSSRComponentSetup || lifecycle === "sp") && injectHook(lifecycle, (...args) => hook(...args), target)
);
const onBeforeMount = createHook("bm");
const onMounted = createHook("m");
const onBeforeUpdate = createHook("bu");
const onUpdated = createHook("u");
const onBeforeUnmount = createHook("bum");
const onUnmounted = createHook("um");
const onServerPrefetch = createHook("sp");
const onRenderTriggered = createHook(
  "rtg"
);
const onRenderTracked = createHook(
  "rtc"
);
function onErrorCaptured(hook, target = currentInstance) {
  injectHook("ec", hook, target);
}

function renderList(source, renderItem, cache, index) {
  let ret;
  const cached = cache && cache[index];
  if (isArray$k(source) || isString$3(source)) {
    ret = new Array(source.length);
    for (let i = 0, l = source.length; i < l; i++) {
      ret[i] = renderItem(source[i], i, void 0, cached && cached[i]);
    }
  } else if (typeof source === "number") {
    ret = new Array(source);
    for (let i = 0; i < source; i++) {
      ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]);
    }
  } else if (isObject$o(source)) {
    if (source[Symbol.iterator]) {
      ret = Array.from(
        source,
        (item, i) => renderItem(item, i, void 0, cached && cached[i])
      );
    } else {
      const keys = Object.keys(source);
      ret = new Array(keys.length);
      for (let i = 0, l = keys.length; i < l; i++) {
        const key = keys[i];
        ret[i] = renderItem(source[key], key, i, cached && cached[i]);
      }
    }
  } else {
    ret = [];
  }
  if (cache) {
    cache[index] = ret;
  }
  return ret;
}

function renderSlot(slots, name, props = {}, fallback, noSlotted) {
  if (currentRenderingInstance.isCE || currentRenderingInstance.parent && isAsyncWrapper(currentRenderingInstance.parent) && currentRenderingInstance.parent.isCE) {
    if (name !== "default")
      props.name = name;
    return createVNode("slot", props, fallback && fallback());
  }
  let slot = slots[name];
  if (slot && slot._c) {
    slot._d = false;
  }
  openBlock();
  const validSlotContent = slot && ensureValidVNode(slot(props));
  const rendered = createBlock(
    Fragment,
    {
      key: props.key || // slot content array of a dynamic conditional slot may have a branch
      // key attached in the `createSlots` helper, respect that
      validSlotContent && validSlotContent.key || `_${name}`
    },
    validSlotContent || (fallback ? fallback() : []),
    validSlotContent && slots._ === 1 ? 64 : -2
  );
  if (!noSlotted && rendered.scopeId) {
    rendered.slotScopeIds = [rendered.scopeId + "-s"];
  }
  if (slot && slot._c) {
    slot._d = true;
  }
  return rendered;
}
function ensureValidVNode(vnodes) {
  return vnodes.some((child) => {
    if (!isVNode(child))
      return true;
    if (child.type === Comment)
      return false;
    if (child.type === Fragment && !ensureValidVNode(child.children))
      return false;
    return true;
  }) ? vnodes : null;
}

const getPublicInstance = (i) => {
  if (!i)
    return null;
  if (isStatefulComponent(i))
    return getExposeProxy(i) || i.proxy;
  return getPublicInstance(i.parent);
};
const publicPropertiesMap = (
  // Move PURE marker to new line to workaround compiler discarding it
  // due to type annotation
  /* @__PURE__ */ extend$3(/* @__PURE__ */ Object.create(null), {
    $: (i) => i,
    $el: (i) => i.vnode.el,
    $data: (i) => i.data,
    $props: (i) => i.props,
    $attrs: (i) => i.attrs,
    $slots: (i) => i.slots,
    $refs: (i) => i.refs,
    $parent: (i) => getPublicInstance(i.parent),
    $root: (i) => getPublicInstance(i.root),
    $emit: (i) => i.emit,
    $options: (i) => resolveMergedOptions(i) ,
    $forceUpdate: (i) => i.f || (i.f = () => queueJob(i.update)),
    $nextTick: (i) => i.n || (i.n = nextTick.bind(i.proxy)),
    $watch: (i) => instanceWatch.bind(i) 
  })
);
const hasSetupBinding = (state, key) => state !== EMPTY_OBJ$1 && !state.__isScriptSetup && hasOwn$m(state, key);
const PublicInstanceProxyHandlers = {
  get({ _: instance }, key) {
    const { ctx, setupState, data, props, accessCache, type, appContext } = instance;
    let normalizedProps;
    if (key[0] !== "$") {
      const n = accessCache[key];
      if (n !== void 0) {
        switch (n) {
          case 1 /* SETUP */:
            return setupState[key];
          case 2 /* DATA */:
            return data[key];
          case 4 /* CONTEXT */:
            return ctx[key];
          case 3 /* PROPS */:
            return props[key];
        }
      } else if (hasSetupBinding(setupState, key)) {
        accessCache[key] = 1 /* SETUP */;
        return setupState[key];
      } else if (data !== EMPTY_OBJ$1 && hasOwn$m(data, key)) {
        accessCache[key] = 2 /* DATA */;
        return data[key];
      } else if (
        // only cache other properties when instance has declared (thus stable)
        // props
        (normalizedProps = instance.propsOptions[0]) && hasOwn$m(normalizedProps, key)
      ) {
        accessCache[key] = 3 /* PROPS */;
        return props[key];
      } else if (ctx !== EMPTY_OBJ$1 && hasOwn$m(ctx, key)) {
        accessCache[key] = 4 /* CONTEXT */;
        return ctx[key];
      } else if (shouldCacheAccess) {
        accessCache[key] = 0 /* OTHER */;
      }
    }
    const publicGetter = publicPropertiesMap[key];
    let cssModule, globalProperties;
    if (publicGetter) {
      if (key === "$attrs") {
        track(instance, "get", key);
      }
      return publicGetter(instance);
    } else if (
      // css module (injected by vue-loader)
      (cssModule = type.__cssModules) && (cssModule = cssModule[key])
    ) {
      return cssModule;
    } else if (ctx !== EMPTY_OBJ$1 && hasOwn$m(ctx, key)) {
      accessCache[key] = 4 /* CONTEXT */;
      return ctx[key];
    } else if (
      // global properties
      globalProperties = appContext.config.globalProperties, hasOwn$m(globalProperties, key)
    ) {
      {
        return globalProperties[key];
      }
    } else ;
  },
  set({ _: instance }, key, value) {
    const { data, setupState, ctx } = instance;
    if (hasSetupBinding(setupState, key)) {
      setupState[key] = value;
      return true;
    } else if (data !== EMPTY_OBJ$1 && hasOwn$m(data, key)) {
      data[key] = value;
      return true;
    } else if (hasOwn$m(instance.props, key)) {
      return false;
    }
    if (key[0] === "$" && key.slice(1) in instance) {
      return false;
    } else {
      {
        ctx[key] = value;
      }
    }
    return true;
  },
  has({
    _: { data, setupState, accessCache, ctx, appContext, propsOptions }
  }, key) {
    let normalizedProps;
    return !!accessCache[key] || data !== EMPTY_OBJ$1 && hasOwn$m(data, key) || hasSetupBinding(setupState, key) || (normalizedProps = propsOptions[0]) && hasOwn$m(normalizedProps, key) || hasOwn$m(ctx, key) || hasOwn$m(publicPropertiesMap, key) || hasOwn$m(appContext.config.globalProperties, key);
  },
  defineProperty(target, key, descriptor) {
    if (descriptor.get != null) {
      target._.accessCache[key] = 0;
    } else if (hasOwn$m(descriptor, "value")) {
      this.set(target, key, descriptor.value, null);
    }
    return Reflect.defineProperty(target, key, descriptor);
  }
};
function normalizePropsOrEmits(props) {
  return isArray$k(props) ? props.reduce(
    (normalized, p) => (normalized[p] = null, normalized),
    {}
  ) : props;
}
function withAsyncContext(getAwaitable) {
  const ctx = getCurrentInstance();
  let awaitable = getAwaitable();
  unsetCurrentInstance();
  if (isPromise(awaitable)) {
    awaitable = awaitable.catch((e) => {
      setCurrentInstance(ctx);
      throw e;
    });
  }
  return [awaitable, () => setCurrentInstance(ctx)];
}
let shouldCacheAccess = true;
function applyOptions(instance) {
  const options = resolveMergedOptions(instance);
  const publicThis = instance.proxy;
  const ctx = instance.ctx;
  shouldCacheAccess = false;
  if (options.beforeCreate) {
    callHook(options.beforeCreate, instance, "bc");
  }
  const {
    // state
    data: dataOptions,
    computed: computedOptions,
    methods,
    watch: watchOptions,
    provide: provideOptions,
    inject: injectOptions,
    // lifecycle
    created,
    beforeMount,
    mounted,
    beforeUpdate,
    updated,
    activated,
    deactivated,
    beforeDestroy,
    beforeUnmount,
    destroyed,
    unmounted,
    render,
    renderTracked,
    renderTriggered,
    errorCaptured,
    serverPrefetch,
    // public API
    expose,
    inheritAttrs,
    // assets
    components,
    directives,
    filters
  } = options;
  const checkDuplicateProperties = null;
  if (injectOptions) {
    resolveInjections(injectOptions, ctx, checkDuplicateProperties);
  }
  if (methods) {
    for (const key in methods) {
      const methodHandler = methods[key];
      if (isFunction$1(methodHandler)) {
        {
          ctx[key] = methodHandler.bind(publicThis);
        }
      }
    }
  }
  if (dataOptions) {
    const data = dataOptions.call(publicThis, publicThis);
    if (!isObject$o(data)) ; else {
      instance.data = reactive(data);
    }
  }
  shouldCacheAccess = true;
  if (computedOptions) {
    for (const key in computedOptions) {
      const opt = computedOptions[key];
      const get = isFunction$1(opt) ? opt.bind(publicThis, publicThis) : isFunction$1(opt.get) ? opt.get.bind(publicThis, publicThis) : NOOP;
      const set = !isFunction$1(opt) && isFunction$1(opt.set) ? opt.set.bind(publicThis) : NOOP;
      const c = computed({
        get,
        set
      });
      Object.defineProperty(ctx, key, {
        enumerable: true,
        configurable: true,
        get: () => c.value,
        set: (v) => c.value = v
      });
    }
  }
  if (watchOptions) {
    for (const key in watchOptions) {
      createWatcher(watchOptions[key], ctx, publicThis, key);
    }
  }
  if (provideOptions) {
    const provides = isFunction$1(provideOptions) ? provideOptions.call(publicThis) : provideOptions;
    Reflect.ownKeys(provides).forEach((key) => {
      provide(key, provides[key]);
    });
  }
  if (created) {
    callHook(created, instance, "c");
  }
  function registerLifecycleHook(register, hook) {
    if (isArray$k(hook)) {
      hook.forEach((_hook) => register(_hook.bind(publicThis)));
    } else if (hook) {
      register(hook.bind(publicThis));
    }
  }
  registerLifecycleHook(onBeforeMount, beforeMount);
  registerLifecycleHook(onMounted, mounted);
  registerLifecycleHook(onBeforeUpdate, beforeUpdate);
  registerLifecycleHook(onUpdated, updated);
  registerLifecycleHook(onActivated, activated);
  registerLifecycleHook(onDeactivated, deactivated);
  registerLifecycleHook(onErrorCaptured, errorCaptured);
  registerLifecycleHook(onRenderTracked, renderTracked);
  registerLifecycleHook(onRenderTriggered, renderTriggered);
  registerLifecycleHook(onBeforeUnmount, beforeUnmount);
  registerLifecycleHook(onUnmounted, unmounted);
  registerLifecycleHook(onServerPrefetch, serverPrefetch);
  if (isArray$k(expose)) {
    if (expose.length) {
      const exposed = instance.exposed || (instance.exposed = {});
      expose.forEach((key) => {
        Object.defineProperty(exposed, key, {
          get: () => publicThis[key],
          set: (val) => publicThis[key] = val
        });
      });
    } else if (!instance.exposed) {
      instance.exposed = {};
    }
  }
  if (render && instance.render === NOOP) {
    instance.render = render;
  }
  if (inheritAttrs != null) {
    instance.inheritAttrs = inheritAttrs;
  }
  if (components)
    instance.components = components;
  if (directives)
    instance.directives = directives;
}
function resolveInjections(injectOptions, ctx, checkDuplicateProperties = NOOP) {
  if (isArray$k(injectOptions)) {
    injectOptions = normalizeInject(injectOptions);
  }
  for (const key in injectOptions) {
    const opt = injectOptions[key];
    let injected;
    if (isObject$o(opt)) {
      if ("default" in opt) {
        injected = inject(
          opt.from || key,
          opt.default,
          true
          /* treat default function as factory */
        );
      } else {
        injected = inject(opt.from || key);
      }
    } else {
      injected = inject(opt);
    }
    if (isRef(injected)) {
      Object.defineProperty(ctx, key, {
        enumerable: true,
        configurable: true,
        get: () => injected.value,
        set: (v) => injected.value = v
      });
    } else {
      ctx[key] = injected;
    }
  }
}
function callHook(hook, instance, type) {
  callWithAsyncErrorHandling(
    isArray$k(hook) ? hook.map((h) => h.bind(instance.proxy)) : hook.bind(instance.proxy),
    instance,
    type
  );
}
function createWatcher(raw, ctx, publicThis, key) {
  const getter = key.includes(".") ? createPathGetter(publicThis, key) : () => publicThis[key];
  if (isString$3(raw)) {
    const handler = ctx[raw];
    if (isFunction$1(handler)) {
      watch(getter, handler);
    }
  } else if (isFunction$1(raw)) {
    watch(getter, raw.bind(publicThis));
  } else if (isObject$o(raw)) {
    if (isArray$k(raw)) {
      raw.forEach((r) => createWatcher(r, ctx, publicThis, key));
    } else {
      const handler = isFunction$1(raw.handler) ? raw.handler.bind(publicThis) : ctx[raw.handler];
      if (isFunction$1(handler)) {
        watch(getter, handler, raw);
      }
    }
  } else ;
}
function resolveMergedOptions(instance) {
  const base = instance.type;
  const { mixins, extends: extendsOptions } = base;
  const {
    mixins: globalMixins,
    optionsCache: cache,
    config: { optionMergeStrategies }
  } = instance.appContext;
  const cached = cache.get(base);
  let resolved;
  if (cached) {
    resolved = cached;
  } else if (!globalMixins.length && !mixins && !extendsOptions) {
    {
      resolved = base;
    }
  } else {
    resolved = {};
    if (globalMixins.length) {
      globalMixins.forEach(
        (m) => mergeOptions$2(resolved, m, optionMergeStrategies, true)
      );
    }
    mergeOptions$2(resolved, base, optionMergeStrategies);
  }
  if (isObject$o(base)) {
    cache.set(base, resolved);
  }
  return resolved;
}
function mergeOptions$2(to, from, strats, asMixin = false) {
  const { mixins, extends: extendsOptions } = from;
  if (extendsOptions) {
    mergeOptions$2(to, extendsOptions, strats, true);
  }
  if (mixins) {
    mixins.forEach(
      (m) => mergeOptions$2(to, m, strats, true)
    );
  }
  for (const key in from) {
    if (asMixin && key === "expose") ; else {
      const strat = internalOptionMergeStrats[key] || strats && strats[key];
      to[key] = strat ? strat(to[key], from[key]) : from[key];
    }
  }
  return to;
}
const internalOptionMergeStrats = {
  data: mergeDataFn,
  props: mergeEmitsOrPropsOptions,
  emits: mergeEmitsOrPropsOptions,
  // objects
  methods: mergeObjectOptions,
  computed: mergeObjectOptions,
  // lifecycle
  beforeCreate: mergeAsArray,
  created: mergeAsArray,
  beforeMount: mergeAsArray,
  mounted: mergeAsArray,
  beforeUpdate: mergeAsArray,
  updated: mergeAsArray,
  beforeDestroy: mergeAsArray,
  beforeUnmount: mergeAsArray,
  destroyed: mergeAsArray,
  unmounted: mergeAsArray,
  activated: mergeAsArray,
  deactivated: mergeAsArray,
  errorCaptured: mergeAsArray,
  serverPrefetch: mergeAsArray,
  // assets
  components: mergeObjectOptions,
  directives: mergeObjectOptions,
  // watch
  watch: mergeWatchOptions,
  // provide / inject
  provide: mergeDataFn,
  inject: mergeInject
};
function mergeDataFn(to, from) {
  if (!from) {
    return to;
  }
  if (!to) {
    return from;
  }
  return function mergedDataFn() {
    return (extend$3)(
      isFunction$1(to) ? to.call(this, this) : to,
      isFunction$1(from) ? from.call(this, this) : from
    );
  };
}
function mergeInject(to, from) {
  return mergeObjectOptions(normalizeInject(to), normalizeInject(from));
}
function normalizeInject(raw) {
  if (isArray$k(raw)) {
    const res = {};
    for (let i = 0; i < raw.length; i++) {
      res[raw[i]] = raw[i];
    }
    return res;
  }
  return raw;
}
function mergeAsArray(to, from) {
  return to ? [...new Set([].concat(to, from))] : from;
}
function mergeObjectOptions(to, from) {
  return to ? extend$3(/* @__PURE__ */ Object.create(null), to, from) : from;
}
function mergeEmitsOrPropsOptions(to, from) {
  if (to) {
    if (isArray$k(to) && isArray$k(from)) {
      return [.../* @__PURE__ */ new Set([...to, ...from])];
    }
    return extend$3(
      /* @__PURE__ */ Object.create(null),
      normalizePropsOrEmits(to),
      normalizePropsOrEmits(from != null ? from : {})
    );
  } else {
    return from;
  }
}
function mergeWatchOptions(to, from) {
  if (!to)
    return from;
  if (!from)
    return to;
  const merged = extend$3(/* @__PURE__ */ Object.create(null), to);
  for (const key in from) {
    merged[key] = mergeAsArray(to[key], from[key]);
  }
  return merged;
}

function createAppContext() {
  return {
    app: null,
    config: {
      isNativeTag: NO,
      performance: false,
      globalProperties: {},
      optionMergeStrategies: {},
      errorHandler: void 0,
      warnHandler: void 0,
      compilerOptions: {}
    },
    mixins: [],
    components: {},
    directives: {},
    provides: /* @__PURE__ */ Object.create(null),
    optionsCache: /* @__PURE__ */ new WeakMap(),
    propsCache: /* @__PURE__ */ new WeakMap(),
    emitsCache: /* @__PURE__ */ new WeakMap()
  };
}
let uid$1$2 = 0;
function createAppAPI(render, hydrate) {
  return function createApp(rootComponent, rootProps = null) {
    if (!isFunction$1(rootComponent)) {
      rootComponent = extend$3({}, rootComponent);
    }
    if (rootProps != null && !isObject$o(rootProps)) {
      rootProps = null;
    }
    const context = createAppContext();
    const installedPlugins = /* @__PURE__ */ new WeakSet();
    let isMounted = false;
    const app = context.app = {
      _uid: uid$1$2++,
      _component: rootComponent,
      _props: rootProps,
      _container: null,
      _context: context,
      _instance: null,
      version: version$2,
      get config() {
        return context.config;
      },
      set config(v) {
      },
      use(plugin, ...options) {
        if (installedPlugins.has(plugin)) ; else if (plugin && isFunction$1(plugin.install)) {
          installedPlugins.add(plugin);
          plugin.install(app, ...options);
        } else if (isFunction$1(plugin)) {
          installedPlugins.add(plugin);
          plugin(app, ...options);
        } else ;
        return app;
      },
      mixin(mixin) {
        {
          if (!context.mixins.includes(mixin)) {
            context.mixins.push(mixin);
          }
        }
        return app;
      },
      component(name, component) {
        if (!component) {
          return context.components[name];
        }
        context.components[name] = component;
        return app;
      },
      directive(name, directive) {
        if (!directive) {
          return context.directives[name];
        }
        context.directives[name] = directive;
        return app;
      },
      mount(rootContainer, isHydrate, isSVG) {
        if (!isMounted) {
          const vnode = createVNode(rootComponent, rootProps);
          vnode.appContext = context;
          if (isHydrate && hydrate) {
            hydrate(vnode, rootContainer);
          } else {
            render(vnode, rootContainer, isSVG);
          }
          isMounted = true;
          app._container = rootContainer;
          rootContainer.__vue_app__ = app;
          return getExposeProxy(vnode.component) || vnode.component.proxy;
        }
      },
      unmount() {
        if (isMounted) {
          render(null, app._container);
          delete app._container.__vue_app__;
        }
      },
      provide(key, value) {
        context.provides[key] = value;
        return app;
      },
      runWithContext(fn) {
        currentApp = app;
        try {
          return fn();
        } finally {
          currentApp = null;
        }
      }
    };
    return app;
  };
}
let currentApp = null;

function provide(key, value) {
  if (!currentInstance) ; else {
    let provides = currentInstance.provides;
    const parentProvides = currentInstance.parent && currentInstance.parent.provides;
    if (parentProvides === provides) {
      provides = currentInstance.provides = Object.create(parentProvides);
    }
    provides[key] = value;
  }
}
function inject(key, defaultValue, treatDefaultAsFactory = false) {
  const instance = currentInstance || currentRenderingInstance;
  if (instance || currentApp) {
    const provides = instance ? instance.parent == null ? instance.vnode.appContext && instance.vnode.appContext.provides : instance.parent.provides : currentApp._context.provides;
    if (provides && key in provides) {
      return provides[key];
    } else if (arguments.length > 1) {
      return treatDefaultAsFactory && isFunction$1(defaultValue) ? defaultValue.call(instance && instance.proxy) : defaultValue;
    } else ;
  }
}

function initProps$1(instance, rawProps, isStateful, isSSR = false) {
  const props = {};
  const attrs = {};
  def(attrs, InternalObjectKey, 1);
  instance.propsDefaults = /* @__PURE__ */ Object.create(null);
  setFullProps(instance, rawProps, props, attrs);
  for (const key in instance.propsOptions[0]) {
    if (!(key in props)) {
      props[key] = void 0;
    }
  }
  if (isStateful) {
    instance.props = isSSR ? props : shallowReactive(props);
  } else {
    if (!instance.type.props) {
      instance.props = attrs;
    } else {
      instance.props = props;
    }
  }
  instance.attrs = attrs;
}
function updateProps$2(instance, rawProps, rawPrevProps, optimized) {
  const {
    props,
    attrs,
    vnode: { patchFlag }
  } = instance;
  const rawCurrentProps = toRaw(props);
  const [options] = instance.propsOptions;
  let hasAttrsChanged = false;
  if (
    // always force full diff in dev
    // - #1942 if hmr is enabled with sfc component
    // - vite#872 non-sfc component used by sfc component
    (optimized || patchFlag > 0) && !(patchFlag & 16)
  ) {
    if (patchFlag & 8) {
      const propsToUpdate = instance.vnode.dynamicProps;
      for (let i = 0; i < propsToUpdate.length; i++) {
        let key = propsToUpdate[i];
        if (isEmitListener(instance.emitsOptions, key)) {
          continue;
        }
        const value = rawProps[key];
        if (options) {
          if (hasOwn$m(attrs, key)) {
            if (value !== attrs[key]) {
              attrs[key] = value;
              hasAttrsChanged = true;
            }
          } else {
            const camelizedKey = camelize(key);
            props[camelizedKey] = resolvePropValue(
              options,
              rawCurrentProps,
              camelizedKey,
              value,
              instance,
              false
              /* isAbsent */
            );
          }
        } else {
          if (value !== attrs[key]) {
            attrs[key] = value;
            hasAttrsChanged = true;
          }
        }
      }
    }
  } else {
    if (setFullProps(instance, rawProps, props, attrs)) {
      hasAttrsChanged = true;
    }
    let kebabKey;
    for (const key in rawCurrentProps) {
      if (!rawProps || // for camelCase
      !hasOwn$m(rawProps, key) && // it's possible the original props was passed in as kebab-case
      // and converted to camelCase (#955)
      ((kebabKey = hyphenate(key)) === key || !hasOwn$m(rawProps, kebabKey))) {
        if (options) {
          if (rawPrevProps && // for camelCase
          (rawPrevProps[key] !== void 0 || // for kebab-case
          rawPrevProps[kebabKey] !== void 0)) {
            props[key] = resolvePropValue(
              options,
              rawCurrentProps,
              key,
              void 0,
              instance,
              true
              /* isAbsent */
            );
          }
        } else {
          delete props[key];
        }
      }
    }
    if (attrs !== rawCurrentProps) {
      for (const key in attrs) {
        if (!rawProps || !hasOwn$m(rawProps, key) && true) {
          delete attrs[key];
          hasAttrsChanged = true;
        }
      }
    }
  }
  if (hasAttrsChanged) {
    trigger(instance, "set", "$attrs");
  }
}
function setFullProps(instance, rawProps, props, attrs) {
  const [options, needCastKeys] = instance.propsOptions;
  let hasAttrsChanged = false;
  let rawCastValues;
  if (rawProps) {
    for (let key in rawProps) {
      if (isReservedProp(key)) {
        continue;
      }
      const value = rawProps[key];
      let camelKey;
      if (options && hasOwn$m(options, camelKey = camelize(key))) {
        if (!needCastKeys || !needCastKeys.includes(camelKey)) {
          props[camelKey] = value;
        } else {
          (rawCastValues || (rawCastValues = {}))[camelKey] = value;
        }
      } else if (!isEmitListener(instance.emitsOptions, key)) {
        if (!(key in attrs) || value !== attrs[key]) {
          attrs[key] = value;
          hasAttrsChanged = true;
        }
      }
    }
  }
  if (needCastKeys) {
    const rawCurrentProps = toRaw(props);
    const castValues = rawCastValues || EMPTY_OBJ$1;
    for (let i = 0; i < needCastKeys.length; i++) {
      const key = needCastKeys[i];
      props[key] = resolvePropValue(
        options,
        rawCurrentProps,
        key,
        castValues[key],
        instance,
        !hasOwn$m(castValues, key)
      );
    }
  }
  return hasAttrsChanged;
}
function resolvePropValue(options, props, key, value, instance, isAbsent) {
  const opt = options[key];
  if (opt != null) {
    const hasDefault = hasOwn$m(opt, "default");
    if (hasDefault && value === void 0) {
      const defaultValue = opt.default;
      if (opt.type !== Function && !opt.skipFactory && isFunction$1(defaultValue)) {
        const { propsDefaults } = instance;
        if (key in propsDefaults) {
          value = propsDefaults[key];
        } else {
          setCurrentInstance(instance);
          value = propsDefaults[key] = defaultValue.call(
            null,
            props
          );
          unsetCurrentInstance();
        }
      } else {
        value = defaultValue;
      }
    }
    if (opt[0 /* shouldCast */]) {
      if (isAbsent && !hasDefault) {
        value = false;
      } else if (opt[1 /* shouldCastTrue */] && (value === "" || value === hyphenate(key))) {
        value = true;
      }
    }
  }
  return value;
}
function normalizePropsOptions(comp, appContext, asMixin = false) {
  const cache = appContext.propsCache;
  const cached = cache.get(comp);
  if (cached) {
    return cached;
  }
  const raw = comp.props;
  const normalized = {};
  const needCastKeys = [];
  let hasExtends = false;
  if (!isFunction$1(comp)) {
    const extendProps = (raw2) => {
      hasExtends = true;
      const [props, keys] = normalizePropsOptions(raw2, appContext, true);
      extend$3(normalized, props);
      if (keys)
        needCastKeys.push(...keys);
    };
    if (!asMixin && appContext.mixins.length) {
      appContext.mixins.forEach(extendProps);
    }
    if (comp.extends) {
      extendProps(comp.extends);
    }
    if (comp.mixins) {
      comp.mixins.forEach(extendProps);
    }
  }
  if (!raw && !hasExtends) {
    if (isObject$o(comp)) {
      cache.set(comp, EMPTY_ARR);
    }
    return EMPTY_ARR;
  }
  if (isArray$k(raw)) {
    for (let i = 0; i < raw.length; i++) {
      const normalizedKey = camelize(raw[i]);
      if (validatePropName(normalizedKey)) {
        normalized[normalizedKey] = EMPTY_OBJ$1;
      }
    }
  } else if (raw) {
    for (const key in raw) {
      const normalizedKey = camelize(key);
      if (validatePropName(normalizedKey)) {
        const opt = raw[key];
        const prop = normalized[normalizedKey] = isArray$k(opt) || isFunction$1(opt) ? { type: opt } : extend$3({}, opt);
        if (prop) {
          const booleanIndex = getTypeIndex(Boolean, prop.type);
          const stringIndex = getTypeIndex(String, prop.type);
          prop[0 /* shouldCast */] = booleanIndex > -1;
          prop[1 /* shouldCastTrue */] = stringIndex < 0 || booleanIndex < stringIndex;
          if (booleanIndex > -1 || hasOwn$m(prop, "default")) {
            needCastKeys.push(normalizedKey);
          }
        }
      }
    }
  }
  const res = [normalized, needCastKeys];
  if (isObject$o(comp)) {
    cache.set(comp, res);
  }
  return res;
}
function validatePropName(key) {
  if (key[0] !== "$") {
    return true;
  }
  return false;
}
function getType(ctor) {
  const match = ctor && ctor.toString().match(/^\s*(function|class) (\w+)/);
  return match ? match[2] : ctor === null ? "null" : "";
}
function isSameType(a, b) {
  return getType(a) === getType(b);
}
function getTypeIndex(type, expectedTypes) {
  if (isArray$k(expectedTypes)) {
    return expectedTypes.findIndex((t) => isSameType(t, type));
  } else if (isFunction$1(expectedTypes)) {
    return isSameType(expectedTypes, type) ? 0 : -1;
  }
  return -1;
}

const isInternalKey = (key) => key[0] === "_" || key === "$stable";
const normalizeSlotValue = (value) => isArray$k(value) ? value.map(normalizeVNode) : [normalizeVNode(value)];
const normalizeSlot$1 = (key, rawSlot, ctx) => {
  if (rawSlot._n) {
    return rawSlot;
  }
  const normalized = withCtx((...args) => {
    if (!!("production" !== "production") && currentInstance) ;
    return normalizeSlotValue(rawSlot(...args));
  }, ctx);
  normalized._c = false;
  return normalized;
};
const normalizeObjectSlots = (rawSlots, slots, instance) => {
  const ctx = rawSlots._ctx;
  for (const key in rawSlots) {
    if (isInternalKey(key))
      continue;
    const value = rawSlots[key];
    if (isFunction$1(value)) {
      slots[key] = normalizeSlot$1(key, value, ctx);
    } else if (value != null) {
      const normalized = normalizeSlotValue(value);
      slots[key] = () => normalized;
    }
  }
};
const normalizeVNodeSlots = (instance, children) => {
  const normalized = normalizeSlotValue(children);
  instance.slots.default = () => normalized;
};
const initSlots = (instance, children) => {
  if (instance.vnode.shapeFlag & 32) {
    const type = children._;
    if (type) {
      instance.slots = toRaw(children);
      def(children, "_", type);
    } else {
      normalizeObjectSlots(
        children,
        instance.slots = {});
    }
  } else {
    instance.slots = {};
    if (children) {
      normalizeVNodeSlots(instance, children);
    }
  }
  def(instance.slots, InternalObjectKey, 1);
};
const updateSlots = (instance, children, optimized) => {
  const { vnode, slots } = instance;
  let needDeletionCheck = true;
  let deletionComparisonTarget = EMPTY_OBJ$1;
  if (vnode.shapeFlag & 32) {
    const type = children._;
    if (type) {
      if (optimized && type === 1) {
        needDeletionCheck = false;
      } else {
        extend$3(slots, children);
        if (!optimized && type === 1) {
          delete slots._;
        }
      }
    } else {
      needDeletionCheck = !children.$stable;
      normalizeObjectSlots(children, slots);
    }
    deletionComparisonTarget = children;
  } else if (children) {
    normalizeVNodeSlots(instance, children);
    deletionComparisonTarget = { default: 1 };
  }
  if (needDeletionCheck) {
    for (const key in slots) {
      if (!isInternalKey(key) && deletionComparisonTarget[key] == null) {
        delete slots[key];
      }
    }
  }
};

function setRef(rawRef, oldRawRef, parentSuspense, vnode, isUnmount = false) {
  if (isArray$k(rawRef)) {
    rawRef.forEach(
      (r, i) => setRef(
        r,
        oldRawRef && (isArray$k(oldRawRef) ? oldRawRef[i] : oldRawRef),
        parentSuspense,
        vnode,
        isUnmount
      )
    );
    return;
  }
  if (isAsyncWrapper(vnode) && !isUnmount) {
    return;
  }
  const refValue = vnode.shapeFlag & 4 ? getExposeProxy(vnode.component) || vnode.component.proxy : vnode.el;
  const value = isUnmount ? null : refValue;
  const { i: owner, r: ref } = rawRef;
  const oldRef = oldRawRef && oldRawRef.r;
  const refs = owner.refs === EMPTY_OBJ$1 ? owner.refs = {} : owner.refs;
  const setupState = owner.setupState;
  if (oldRef != null && oldRef !== ref) {
    if (isString$3(oldRef)) {
      refs[oldRef] = null;
      if (hasOwn$m(setupState, oldRef)) {
        setupState[oldRef] = null;
      }
    } else if (isRef(oldRef)) {
      oldRef.value = null;
    }
  }
  if (isFunction$1(ref)) {
    callWithErrorHandling(ref, owner, 12, [value, refs]);
  } else {
    const _isString = isString$3(ref);
    const _isRef = isRef(ref);
    if (_isString || _isRef) {
      const doSet = () => {
        if (rawRef.f) {
          const existing = _isString ? hasOwn$m(setupState, ref) ? setupState[ref] : refs[ref] : ref.value;
          if (isUnmount) {
            isArray$k(existing) && remove(existing, refValue);
          } else {
            if (!isArray$k(existing)) {
              if (_isString) {
                refs[ref] = [refValue];
                if (hasOwn$m(setupState, ref)) {
                  setupState[ref] = refs[ref];
                }
              } else {
                ref.value = [refValue];
                if (rawRef.k)
                  refs[rawRef.k] = ref.value;
              }
            } else if (!existing.includes(refValue)) {
              existing.push(refValue);
            }
          }
        } else if (_isString) {
          refs[ref] = value;
          if (hasOwn$m(setupState, ref)) {
            setupState[ref] = value;
          }
        } else if (_isRef) {
          ref.value = value;
          if (rawRef.k)
            refs[rawRef.k] = value;
        } else ;
      };
      if (value) {
        doSet.id = -1;
        queuePostRenderEffect(doSet, parentSuspense);
      } else {
        doSet();
      }
    }
  }
}

const queuePostRenderEffect = queueEffectWithSuspense ;
function createRenderer(options) {
  return baseCreateRenderer(options);
}
function baseCreateRenderer(options, createHydrationFns) {
  const target = getGlobalThis();
  target.__VUE__ = true;
  const {
    insert: hostInsert,
    remove: hostRemove,
    patchProp: hostPatchProp,
    createElement: hostCreateElement,
    createText: hostCreateText,
    createComment: hostCreateComment,
    setText: hostSetText,
    setElementText: hostSetElementText,
    parentNode: hostParentNode,
    nextSibling: hostNextSibling,
    setScopeId: hostSetScopeId = NOOP,
    insertStaticContent: hostInsertStaticContent
  } = options;
  const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, slotScopeIds = null, optimized = !!n2.dynamicChildren) => {
    if (n1 === n2) {
      return;
    }
    if (n1 && !isSameVNodeType(n1, n2)) {
      anchor = getNextHostNode(n1);
      unmount(n1, parentComponent, parentSuspense, true);
      n1 = null;
    }
    if (n2.patchFlag === -2) {
      optimized = false;
      n2.dynamicChildren = null;
    }
    const { type, ref, shapeFlag } = n2;
    switch (type) {
      case Text$1:
        processText(n1, n2, container, anchor);
        break;
      case Comment:
        processCommentNode(n1, n2, container, anchor);
        break;
      case Static:
        if (n1 == null) {
          mountStaticNode(n2, container, anchor, isSVG);
        }
        break;
      case Fragment:
        processFragment(
          n1,
          n2,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds,
          optimized
        );
        break;
      default:
        if (shapeFlag & 1) {
          processElement(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
        } else if (shapeFlag & 6) {
          processComponent(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
        } else if (shapeFlag & 64) {
          type.process(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized,
            internals
          );
        } else if (shapeFlag & 128) {
          type.process(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized,
            internals
          );
        } else ;
    }
    if (ref != null && parentComponent) {
      setRef(ref, n1 && n1.ref, parentSuspense, n2 || n1, !n2);
    }
  };
  const processText = (n1, n2, container, anchor) => {
    if (n1 == null) {
      hostInsert(
        n2.el = hostCreateText(n2.children),
        container,
        anchor
      );
    } else {
      const el = n2.el = n1.el;
      if (n2.children !== n1.children) {
        hostSetText(el, n2.children);
      }
    }
  };
  const processCommentNode = (n1, n2, container, anchor) => {
    if (n1 == null) {
      hostInsert(
        n2.el = hostCreateComment(n2.children || ""),
        container,
        anchor
      );
    } else {
      n2.el = n1.el;
    }
  };
  const mountStaticNode = (n2, container, anchor, isSVG) => {
    [n2.el, n2.anchor] = hostInsertStaticContent(
      n2.children,
      container,
      anchor,
      isSVG,
      n2.el,
      n2.anchor
    );
  };
  const moveStaticNode = ({ el, anchor }, container, nextSibling) => {
    let next;
    while (el && el !== anchor) {
      next = hostNextSibling(el);
      hostInsert(el, container, nextSibling);
      el = next;
    }
    hostInsert(anchor, container, nextSibling);
  };
  const removeStaticNode = ({ el, anchor }) => {
    let next;
    while (el && el !== anchor) {
      next = hostNextSibling(el);
      hostRemove(el);
      el = next;
    }
    hostRemove(anchor);
  };
  const processElement = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    isSVG = isSVG || n2.type === "svg";
    if (n1 == null) {
      mountElement(
        n2,
        container,
        anchor,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized
      );
    } else {
      patchElement(
        n1,
        n2,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized
      );
    }
  };
  const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    let el;
    let vnodeHook;
    const { type, props, shapeFlag, transition, dirs } = vnode;
    el = vnode.el = hostCreateElement(
      vnode.type,
      isSVG,
      props && props.is,
      props
    );
    if (shapeFlag & 8) {
      hostSetElementText(el, vnode.children);
    } else if (shapeFlag & 16) {
      mountChildren(
        vnode.children,
        el,
        null,
        parentComponent,
        parentSuspense,
        isSVG && type !== "foreignObject",
        slotScopeIds,
        optimized
      );
    }
    if (dirs) {
      invokeDirectiveHook(vnode, null, parentComponent, "created");
    }
    setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent);
    if (props) {
      for (const key in props) {
        if (key !== "value" && !isReservedProp(key)) {
          hostPatchProp(
            el,
            key,
            null,
            props[key],
            isSVG,
            vnode.children,
            parentComponent,
            parentSuspense,
            unmountChildren
          );
        }
      }
      if ("value" in props) {
        hostPatchProp(el, "value", null, props.value);
      }
      if (vnodeHook = props.onVnodeBeforeMount) {
        invokeVNodeHook(vnodeHook, parentComponent, vnode);
      }
    }
    if (dirs) {
      invokeDirectiveHook(vnode, null, parentComponent, "beforeMount");
    }
    const needCallTransitionHooks = needTransition(parentSuspense, transition);
    if (needCallTransitionHooks) {
      transition.beforeEnter(el);
    }
    hostInsert(el, container, anchor);
    if ((vnodeHook = props && props.onVnodeMounted) || needCallTransitionHooks || dirs) {
      queuePostRenderEffect(() => {
        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);
        needCallTransitionHooks && transition.enter(el);
        dirs && invokeDirectiveHook(vnode, null, parentComponent, "mounted");
      }, parentSuspense);
    }
  };
  const setScopeId = (el, vnode, scopeId, slotScopeIds, parentComponent) => {
    if (scopeId) {
      hostSetScopeId(el, scopeId);
    }
    if (slotScopeIds) {
      for (let i = 0; i < slotScopeIds.length; i++) {
        hostSetScopeId(el, slotScopeIds[i]);
      }
    }
    if (parentComponent) {
      let subTree = parentComponent.subTree;
      if (vnode === subTree) {
        const parentVNode = parentComponent.vnode;
        setScopeId(
          el,
          parentVNode,
          parentVNode.scopeId,
          parentVNode.slotScopeIds,
          parentComponent.parent
        );
      }
    }
  };
  const mountChildren = (children, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, start = 0) => {
    for (let i = start; i < children.length; i++) {
      const child = children[i] = optimized ? cloneIfMounted(children[i]) : normalizeVNode(children[i]);
      patch(
        null,
        child,
        container,
        anchor,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized
      );
    }
  };
  const patchElement = (n1, n2, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    const el = n2.el = n1.el;
    let { patchFlag, dynamicChildren, dirs } = n2;
    patchFlag |= n1.patchFlag & 16;
    const oldProps = n1.props || EMPTY_OBJ$1;
    const newProps = n2.props || EMPTY_OBJ$1;
    let vnodeHook;
    parentComponent && toggleRecurse(parentComponent, false);
    if (vnodeHook = newProps.onVnodeBeforeUpdate) {
      invokeVNodeHook(vnodeHook, parentComponent, n2, n1);
    }
    if (dirs) {
      invokeDirectiveHook(n2, n1, parentComponent, "beforeUpdate");
    }
    parentComponent && toggleRecurse(parentComponent, true);
    const areChildrenSVG = isSVG && n2.type !== "foreignObject";
    if (dynamicChildren) {
      patchBlockChildren(
        n1.dynamicChildren,
        dynamicChildren,
        el,
        parentComponent,
        parentSuspense,
        areChildrenSVG,
        slotScopeIds
      );
    } else if (!optimized) {
      patchChildren(
        n1,
        n2,
        el,
        null,
        parentComponent,
        parentSuspense,
        areChildrenSVG,
        slotScopeIds,
        false
      );
    }
    if (patchFlag > 0) {
      if (patchFlag & 16) {
        patchProps(
          el,
          n2,
          oldProps,
          newProps,
          parentComponent,
          parentSuspense,
          isSVG
        );
      } else {
        if (patchFlag & 2) {
          if (oldProps.class !== newProps.class) {
            hostPatchProp(el, "class", null, newProps.class, isSVG);
          }
        }
        if (patchFlag & 4) {
          hostPatchProp(el, "style", oldProps.style, newProps.style, isSVG);
        }
        if (patchFlag & 8) {
          const propsToUpdate = n2.dynamicProps;
          for (let i = 0; i < propsToUpdate.length; i++) {
            const key = propsToUpdate[i];
            const prev = oldProps[key];
            const next = newProps[key];
            if (next !== prev || key === "value") {
              hostPatchProp(
                el,
                key,
                prev,
                next,
                isSVG,
                n1.children,
                parentComponent,
                parentSuspense,
                unmountChildren
              );
            }
          }
        }
      }
      if (patchFlag & 1) {
        if (n1.children !== n2.children) {
          hostSetElementText(el, n2.children);
        }
      }
    } else if (!optimized && dynamicChildren == null) {
      patchProps(
        el,
        n2,
        oldProps,
        newProps,
        parentComponent,
        parentSuspense,
        isSVG
      );
    }
    if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {
      queuePostRenderEffect(() => {
        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1);
        dirs && invokeDirectiveHook(n2, n1, parentComponent, "updated");
      }, parentSuspense);
    }
  };
  const patchBlockChildren = (oldChildren, newChildren, fallbackContainer, parentComponent, parentSuspense, isSVG, slotScopeIds) => {
    for (let i = 0; i < newChildren.length; i++) {
      const oldVNode = oldChildren[i];
      const newVNode = newChildren[i];
      const container = (
        // oldVNode may be an errored async setup() component inside Suspense
        // which will not have a mounted element
        oldVNode.el && // - In the case of a Fragment, we need to provide the actual parent
        // of the Fragment itself so it can move its children.
        (oldVNode.type === Fragment || // - In the case of different nodes, there is going to be a replacement
        // which also requires the correct parent container
        !isSameVNodeType(oldVNode, newVNode) || // - In the case of a component, it could contain anything.
        oldVNode.shapeFlag & (6 | 64)) ? hostParentNode(oldVNode.el) : (
          // In other cases, the parent container is not actually used so we
          // just pass the block element here to avoid a DOM parentNode call.
          fallbackContainer
        )
      );
      patch(
        oldVNode,
        newVNode,
        container,
        null,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        true
      );
    }
  };
  const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {
    if (oldProps !== newProps) {
      if (oldProps !== EMPTY_OBJ$1) {
        for (const key in oldProps) {
          if (!isReservedProp(key) && !(key in newProps)) {
            hostPatchProp(
              el,
              key,
              oldProps[key],
              null,
              isSVG,
              vnode.children,
              parentComponent,
              parentSuspense,
              unmountChildren
            );
          }
        }
      }
      for (const key in newProps) {
        if (isReservedProp(key))
          continue;
        const next = newProps[key];
        const prev = oldProps[key];
        if (next !== prev && key !== "value") {
          hostPatchProp(
            el,
            key,
            prev,
            next,
            isSVG,
            vnode.children,
            parentComponent,
            parentSuspense,
            unmountChildren
          );
        }
      }
      if ("value" in newProps) {
        hostPatchProp(el, "value", oldProps.value, newProps.value);
      }
    }
  };
  const processFragment = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    const fragmentStartAnchor = n2.el = n1 ? n1.el : hostCreateText("");
    const fragmentEndAnchor = n2.anchor = n1 ? n1.anchor : hostCreateText("");
    let { patchFlag, dynamicChildren, slotScopeIds: fragmentSlotScopeIds } = n2;
    if (fragmentSlotScopeIds) {
      slotScopeIds = slotScopeIds ? slotScopeIds.concat(fragmentSlotScopeIds) : fragmentSlotScopeIds;
    }
    if (n1 == null) {
      hostInsert(fragmentStartAnchor, container, anchor);
      hostInsert(fragmentEndAnchor, container, anchor);
      mountChildren(
        n2.children,
        container,
        fragmentEndAnchor,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized
      );
    } else {
      if (patchFlag > 0 && patchFlag & 64 && dynamicChildren && // #2715 the previous fragment could've been a BAILed one as a result
      // of renderSlot() with no valid children
      n1.dynamicChildren) {
        patchBlockChildren(
          n1.dynamicChildren,
          dynamicChildren,
          container,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds
        );
        if (
          // #2080 if the stable fragment has a key, it's a <template v-for> that may
          //  get moved around. Make sure all root level vnodes inherit el.
          // #2134 or if it's a component root, it may also get moved around
          // as the component is being moved.
          n2.key != null || parentComponent && n2 === parentComponent.subTree
        ) {
          traverseStaticChildren(
            n1,
            n2,
            true
            /* shallow */
          );
        }
      } else {
        patchChildren(
          n1,
          n2,
          container,
          fragmentEndAnchor,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds,
          optimized
        );
      }
    }
  };
  const processComponent = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    n2.slotScopeIds = slotScopeIds;
    if (n1 == null) {
      if (n2.shapeFlag & 512) {
        parentComponent.ctx.activate(
          n2,
          container,
          anchor,
          isSVG,
          optimized
        );
      } else {
        mountComponent(
          n2,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          isSVG,
          optimized
        );
      }
    } else {
      updateComponent(n1, n2, optimized);
    }
  };
  const mountComponent = (initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) => {
    const instance = (initialVNode.component = createComponentInstance(
      initialVNode,
      parentComponent,
      parentSuspense
    ));
    if (isKeepAlive(initialVNode)) {
      instance.ctx.renderer = internals;
    }
    {
      setupComponent(instance);
    }
    if (instance.asyncDep) {
      parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect);
      if (!initialVNode.el) {
        const placeholder = instance.subTree = createVNode(Comment);
        processCommentNode(null, placeholder, container, anchor);
      }
      return;
    }
    setupRenderEffect(
      instance,
      initialVNode,
      container,
      anchor,
      parentSuspense,
      isSVG,
      optimized
    );
  };
  const updateComponent = (n1, n2, optimized) => {
    const instance = n2.component = n1.component;
    if (shouldUpdateComponent(n1, n2, optimized)) {
      if (instance.asyncDep && !instance.asyncResolved) {
        updateComponentPreRender(instance, n2, optimized);
        return;
      } else {
        instance.next = n2;
        invalidateJob(instance.update);
        instance.update();
      }
    } else {
      n2.el = n1.el;
      instance.vnode = n2;
    }
  };
  const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {
    const componentUpdateFn = () => {
      if (!instance.isMounted) {
        let vnodeHook;
        const { el, props } = initialVNode;
        const { bm, m, parent } = instance;
        const isAsyncWrapperVNode = isAsyncWrapper(initialVNode);
        toggleRecurse(instance, false);
        if (bm) {
          invokeArrayFns(bm);
        }
        if (!isAsyncWrapperVNode && (vnodeHook = props && props.onVnodeBeforeMount)) {
          invokeVNodeHook(vnodeHook, parent, initialVNode);
        }
        toggleRecurse(instance, true);
        if (el && hydrateNode) {
          const hydrateSubTree = () => {
            instance.subTree = renderComponentRoot(instance);
            hydrateNode(
              el,
              instance.subTree,
              instance,
              parentSuspense,
              null
            );
          };
          if (isAsyncWrapperVNode) {
            initialVNode.type.__asyncLoader().then(
              // note: we are moving the render call into an async callback,
              // which means it won't track dependencies - but it's ok because
              // a server-rendered async wrapper is already in resolved state
              // and it will never need to change.
              () => !instance.isUnmounted && hydrateSubTree()
            );
          } else {
            hydrateSubTree();
          }
        } else {
          const subTree = instance.subTree = renderComponentRoot(instance);
          patch(
            null,
            subTree,
            container,
            anchor,
            instance,
            parentSuspense,
            isSVG
          );
          initialVNode.el = subTree.el;
        }
        if (m) {
          queuePostRenderEffect(m, parentSuspense);
        }
        if (!isAsyncWrapperVNode && (vnodeHook = props && props.onVnodeMounted)) {
          const scopedInitialVNode = initialVNode;
          queuePostRenderEffect(
            () => invokeVNodeHook(vnodeHook, parent, scopedInitialVNode),
            parentSuspense
          );
        }
        if (initialVNode.shapeFlag & 256 || parent && isAsyncWrapper(parent.vnode) && parent.vnode.shapeFlag & 256) {
          instance.a && queuePostRenderEffect(instance.a, parentSuspense);
        }
        instance.isMounted = true;
        initialVNode = container = anchor = null;
      } else {
        let { next, bu, u, parent, vnode } = instance;
        let originNext = next;
        let vnodeHook;
        toggleRecurse(instance, false);
        if (next) {
          next.el = vnode.el;
          updateComponentPreRender(instance, next, optimized);
        } else {
          next = vnode;
        }
        if (bu) {
          invokeArrayFns(bu);
        }
        if (vnodeHook = next.props && next.props.onVnodeBeforeUpdate) {
          invokeVNodeHook(vnodeHook, parent, next, vnode);
        }
        toggleRecurse(instance, true);
        const nextTree = renderComponentRoot(instance);
        const prevTree = instance.subTree;
        instance.subTree = nextTree;
        patch(
          prevTree,
          nextTree,
          // parent may have changed if it's in a teleport
          hostParentNode(prevTree.el),
          // anchor may have changed if it's in a fragment
          getNextHostNode(prevTree),
          instance,
          parentSuspense,
          isSVG
        );
        next.el = nextTree.el;
        if (originNext === null) {
          updateHOCHostEl(instance, nextTree.el);
        }
        if (u) {
          queuePostRenderEffect(u, parentSuspense);
        }
        if (vnodeHook = next.props && next.props.onVnodeUpdated) {
          queuePostRenderEffect(
            () => invokeVNodeHook(vnodeHook, parent, next, vnode),
            parentSuspense
          );
        }
      }
    };
    const effect = instance.effect = new ReactiveEffect(
      componentUpdateFn,
      () => queueJob(update),
      instance.scope
      // track it in component's effect scope
    );
    const update = instance.update = () => effect.run();
    update.id = instance.uid;
    toggleRecurse(instance, true);
    update();
  };
  const updateComponentPreRender = (instance, nextVNode, optimized) => {
    nextVNode.component = instance;
    const prevProps = instance.vnode.props;
    instance.vnode = nextVNode;
    instance.next = null;
    updateProps$2(instance, nextVNode.props, prevProps, optimized);
    updateSlots(instance, nextVNode.children, optimized);
    pauseTracking();
    flushPreFlushCbs();
    resetTracking();
  };
  const patchChildren = (n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized = false) => {
    const c1 = n1 && n1.children;
    const prevShapeFlag = n1 ? n1.shapeFlag : 0;
    const c2 = n2.children;
    const { patchFlag, shapeFlag } = n2;
    if (patchFlag > 0) {
      if (patchFlag & 128) {
        patchKeyedChildren(
          c1,
          c2,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds,
          optimized
        );
        return;
      } else if (patchFlag & 256) {
        patchUnkeyedChildren(
          c1,
          c2,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds,
          optimized
        );
        return;
      }
    }
    if (shapeFlag & 8) {
      if (prevShapeFlag & 16) {
        unmountChildren(c1, parentComponent, parentSuspense);
      }
      if (c2 !== c1) {
        hostSetElementText(container, c2);
      }
    } else {
      if (prevShapeFlag & 16) {
        if (shapeFlag & 16) {
          patchKeyedChildren(
            c1,
            c2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
        } else {
          unmountChildren(c1, parentComponent, parentSuspense, true);
        }
      } else {
        if (prevShapeFlag & 8) {
          hostSetElementText(container, "");
        }
        if (shapeFlag & 16) {
          mountChildren(
            c2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
        }
      }
    }
  };
  const patchUnkeyedChildren = (c1, c2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    c1 = c1 || EMPTY_ARR;
    c2 = c2 || EMPTY_ARR;
    const oldLength = c1.length;
    const newLength = c2.length;
    const commonLength = Math.min(oldLength, newLength);
    let i;
    for (i = 0; i < commonLength; i++) {
      const nextChild = c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]);
      patch(
        c1[i],
        nextChild,
        container,
        null,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized
      );
    }
    if (oldLength > newLength) {
      unmountChildren(
        c1,
        parentComponent,
        parentSuspense,
        true,
        false,
        commonLength
      );
    } else {
      mountChildren(
        c2,
        container,
        anchor,
        parentComponent,
        parentSuspense,
        isSVG,
        slotScopeIds,
        optimized,
        commonLength
      );
    }
  };
  const patchKeyedChildren = (c1, c2, container, parentAnchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
    let i = 0;
    const l2 = c2.length;
    let e1 = c1.length - 1;
    let e2 = l2 - 1;
    while (i <= e1 && i <= e2) {
      const n1 = c1[i];
      const n2 = c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]);
      if (isSameVNodeType(n1, n2)) {
        patch(
          n1,
          n2,
          container,
          null,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds,
          optimized
        );
      } else {
        break;
      }
      i++;
    }
    while (i <= e1 && i <= e2) {
      const n1 = c1[e1];
      const n2 = c2[e2] = optimized ? cloneIfMounted(c2[e2]) : normalizeVNode(c2[e2]);
      if (isSameVNodeType(n1, n2)) {
        patch(
          n1,
          n2,
          container,
          null,
          parentComponent,
          parentSuspense,
          isSVG,
          slotScopeIds,
          optimized
        );
      } else {
        break;
      }
      e1--;
      e2--;
    }
    if (i > e1) {
      if (i <= e2) {
        const nextPos = e2 + 1;
        const anchor = nextPos < l2 ? c2[nextPos].el : parentAnchor;
        while (i <= e2) {
          patch(
            null,
            c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]),
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
          i++;
        }
      }
    } else if (i > e2) {
      while (i <= e1) {
        unmount(c1[i], parentComponent, parentSuspense, true);
        i++;
      }
    } else {
      const s1 = i;
      const s2 = i;
      const keyToNewIndexMap = /* @__PURE__ */ new Map();
      for (i = s2; i <= e2; i++) {
        const nextChild = c2[i] = optimized ? cloneIfMounted(c2[i]) : normalizeVNode(c2[i]);
        if (nextChild.key != null) {
          keyToNewIndexMap.set(nextChild.key, i);
        }
      }
      let j;
      let patched = 0;
      const toBePatched = e2 - s2 + 1;
      let moved = false;
      let maxNewIndexSoFar = 0;
      const newIndexToOldIndexMap = new Array(toBePatched);
      for (i = 0; i < toBePatched; i++)
        newIndexToOldIndexMap[i] = 0;
      for (i = s1; i <= e1; i++) {
        const prevChild = c1[i];
        if (patched >= toBePatched) {
          unmount(prevChild, parentComponent, parentSuspense, true);
          continue;
        }
        let newIndex;
        if (prevChild.key != null) {
          newIndex = keyToNewIndexMap.get(prevChild.key);
        } else {
          for (j = s2; j <= e2; j++) {
            if (newIndexToOldIndexMap[j - s2] === 0 && isSameVNodeType(prevChild, c2[j])) {
              newIndex = j;
              break;
            }
          }
        }
        if (newIndex === void 0) {
          unmount(prevChild, parentComponent, parentSuspense, true);
        } else {
          newIndexToOldIndexMap[newIndex - s2] = i + 1;
          if (newIndex >= maxNewIndexSoFar) {
            maxNewIndexSoFar = newIndex;
          } else {
            moved = true;
          }
          patch(
            prevChild,
            c2[newIndex],
            container,
            null,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
          patched++;
        }
      }
      const increasingNewIndexSequence = moved ? getSequence(newIndexToOldIndexMap) : EMPTY_ARR;
      j = increasingNewIndexSequence.length - 1;
      for (i = toBePatched - 1; i >= 0; i--) {
        const nextIndex = s2 + i;
        const nextChild = c2[nextIndex];
        const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : parentAnchor;
        if (newIndexToOldIndexMap[i] === 0) {
          patch(
            null,
            nextChild,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            isSVG,
            slotScopeIds,
            optimized
          );
        } else if (moved) {
          if (j < 0 || i !== increasingNewIndexSequence[j]) {
            move(nextChild, container, anchor, 2);
          } else {
            j--;
          }
        }
      }
    }
  };
  const move = (vnode, container, anchor, moveType, parentSuspense = null) => {
    const { el, type, transition, children, shapeFlag } = vnode;
    if (shapeFlag & 6) {
      move(vnode.component.subTree, container, anchor, moveType);
      return;
    }
    if (shapeFlag & 128) {
      vnode.suspense.move(container, anchor, moveType);
      return;
    }
    if (shapeFlag & 64) {
      type.move(vnode, container, anchor, internals);
      return;
    }
    if (type === Fragment) {
      hostInsert(el, container, anchor);
      for (let i = 0; i < children.length; i++) {
        move(children[i], container, anchor, moveType);
      }
      hostInsert(vnode.anchor, container, anchor);
      return;
    }
    if (type === Static) {
      moveStaticNode(vnode, container, anchor);
      return;
    }
    const needTransition2 = moveType !== 2 && shapeFlag & 1 && transition;
    if (needTransition2) {
      if (moveType === 0) {
        transition.beforeEnter(el);
        hostInsert(el, container, anchor);
        queuePostRenderEffect(() => transition.enter(el), parentSuspense);
      } else {
        const { leave, delayLeave, afterLeave } = transition;
        const remove2 = () => hostInsert(el, container, anchor);
        const performLeave = () => {
          leave(el, () => {
            remove2();
            afterLeave && afterLeave();
          });
        };
        if (delayLeave) {
          delayLeave(el, remove2, performLeave);
        } else {
          performLeave();
        }
      }
    } else {
      hostInsert(el, container, anchor);
    }
  };
  const unmount = (vnode, parentComponent, parentSuspense, doRemove = false, optimized = false) => {
    const {
      type,
      props,
      ref,
      children,
      dynamicChildren,
      shapeFlag,
      patchFlag,
      dirs
    } = vnode;
    if (ref != null) {
      setRef(ref, null, parentSuspense, vnode, true);
    }
    if (shapeFlag & 256) {
      parentComponent.ctx.deactivate(vnode);
      return;
    }
    const shouldInvokeDirs = shapeFlag & 1 && dirs;
    const shouldInvokeVnodeHook = !isAsyncWrapper(vnode);
    let vnodeHook;
    if (shouldInvokeVnodeHook && (vnodeHook = props && props.onVnodeBeforeUnmount)) {
      invokeVNodeHook(vnodeHook, parentComponent, vnode);
    }
    if (shapeFlag & 6) {
      unmountComponent(vnode.component, parentSuspense, doRemove);
    } else {
      if (shapeFlag & 128) {
        vnode.suspense.unmount(parentSuspense, doRemove);
        return;
      }
      if (shouldInvokeDirs) {
        invokeDirectiveHook(vnode, null, parentComponent, "beforeUnmount");
      }
      if (shapeFlag & 64) {
        vnode.type.remove(
          vnode,
          parentComponent,
          parentSuspense,
          optimized,
          internals,
          doRemove
        );
      } else if (dynamicChildren && // #1153: fast path should not be taken for non-stable (v-for) fragments
      (type !== Fragment || patchFlag > 0 && patchFlag & 64)) {
        unmountChildren(
          dynamicChildren,
          parentComponent,
          parentSuspense,
          false,
          true
        );
      } else if (type === Fragment && patchFlag & (128 | 256) || !optimized && shapeFlag & 16) {
        unmountChildren(children, parentComponent, parentSuspense);
      }
      if (doRemove) {
        remove(vnode);
      }
    }
    if (shouldInvokeVnodeHook && (vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) {
      queuePostRenderEffect(() => {
        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode);
        shouldInvokeDirs && invokeDirectiveHook(vnode, null, parentComponent, "unmounted");
      }, parentSuspense);
    }
  };
  const remove = (vnode) => {
    const { type, el, anchor, transition } = vnode;
    if (type === Fragment) {
      {
        removeFragment(el, anchor);
      }
      return;
    }
    if (type === Static) {
      removeStaticNode(vnode);
      return;
    }
    const performRemove = () => {
      hostRemove(el);
      if (transition && !transition.persisted && transition.afterLeave) {
        transition.afterLeave();
      }
    };
    if (vnode.shapeFlag & 1 && transition && !transition.persisted) {
      const { leave, delayLeave } = transition;
      const performLeave = () => leave(el, performRemove);
      if (delayLeave) {
        delayLeave(vnode.el, performRemove, performLeave);
      } else {
        performLeave();
      }
    } else {
      performRemove();
    }
  };
  const removeFragment = (cur, end) => {
    let next;
    while (cur !== end) {
      next = hostNextSibling(cur);
      hostRemove(cur);
      cur = next;
    }
    hostRemove(end);
  };
  const unmountComponent = (instance, parentSuspense, doRemove) => {
    const { bum, scope, update, subTree, um } = instance;
    if (bum) {
      invokeArrayFns(bum);
    }
    scope.stop();
    if (update) {
      update.active = false;
      unmount(subTree, instance, parentSuspense, doRemove);
    }
    if (um) {
      queuePostRenderEffect(um, parentSuspense);
    }
    queuePostRenderEffect(() => {
      instance.isUnmounted = true;
    }, parentSuspense);
    if (parentSuspense && parentSuspense.pendingBranch && !parentSuspense.isUnmounted && instance.asyncDep && !instance.asyncResolved && instance.suspenseId === parentSuspense.pendingId) {
      parentSuspense.deps--;
      if (parentSuspense.deps === 0) {
        parentSuspense.resolve();
      }
    }
  };
  const unmountChildren = (children, parentComponent, parentSuspense, doRemove = false, optimized = false, start = 0) => {
    for (let i = start; i < children.length; i++) {
      unmount(children[i], parentComponent, parentSuspense, doRemove, optimized);
    }
  };
  const getNextHostNode = (vnode) => {
    if (vnode.shapeFlag & 6) {
      return getNextHostNode(vnode.component.subTree);
    }
    if (vnode.shapeFlag & 128) {
      return vnode.suspense.next();
    }
    return hostNextSibling(vnode.anchor || vnode.el);
  };
  const render = (vnode, container, isSVG) => {
    if (vnode == null) {
      if (container._vnode) {
        unmount(container._vnode, null, null, true);
      }
    } else {
      patch(container._vnode || null, vnode, container, null, null, null, isSVG);
    }
    flushPreFlushCbs();
    flushPostFlushCbs();
    container._vnode = vnode;
  };
  const internals = {
    p: patch,
    um: unmount,
    m: move,
    r: remove,
    mt: mountComponent,
    mc: mountChildren,
    pc: patchChildren,
    pbc: patchBlockChildren,
    n: getNextHostNode,
    o: options
  };
  let hydrate;
  let hydrateNode;
  if (createHydrationFns) {
    [hydrate, hydrateNode] = createHydrationFns(
      internals
    );
  }
  return {
    render,
    hydrate,
    createApp: createAppAPI(render, hydrate)
  };
}
function toggleRecurse({ effect, update }, allowed) {
  effect.allowRecurse = update.allowRecurse = allowed;
}
function needTransition(parentSuspense, transition) {
  return (!parentSuspense || parentSuspense && !parentSuspense.pendingBranch) && transition && !transition.persisted;
}
function traverseStaticChildren(n1, n2, shallow = false) {
  const ch1 = n1.children;
  const ch2 = n2.children;
  if (isArray$k(ch1) && isArray$k(ch2)) {
    for (let i = 0; i < ch1.length; i++) {
      const c1 = ch1[i];
      let c2 = ch2[i];
      if (c2.shapeFlag & 1 && !c2.dynamicChildren) {
        if (c2.patchFlag <= 0 || c2.patchFlag === 32) {
          c2 = ch2[i] = cloneIfMounted(ch2[i]);
          c2.el = c1.el;
        }
        if (!shallow)
          traverseStaticChildren(c1, c2);
      }
      if (c2.type === Text$1) {
        c2.el = c1.el;
      }
    }
  }
}
function getSequence(arr) {
  const p = arr.slice();
  const result = [0];
  let i, j, u, v, c;
  const len = arr.length;
  for (i = 0; i < len; i++) {
    const arrI = arr[i];
    if (arrI !== 0) {
      j = result[result.length - 1];
      if (arr[j] < arrI) {
        p[i] = j;
        result.push(i);
        continue;
      }
      u = 0;
      v = result.length - 1;
      while (u < v) {
        c = u + v >> 1;
        if (arr[result[c]] < arrI) {
          u = c + 1;
        } else {
          v = c;
        }
      }
      if (arrI < arr[result[u]]) {
        if (u > 0) {
          p[i] = result[u - 1];
        }
        result[u] = i;
      }
    }
  }
  u = result.length;
  v = result[u - 1];
  while (u-- > 0) {
    result[u] = v;
    v = p[v];
  }
  return result;
}

const isTeleport = (type) => type.__isTeleport;

const Fragment = Symbol.for("v-fgt");
const Text$1 = Symbol.for("v-txt");
const Comment = Symbol.for("v-cmt");
const Static = Symbol.for("v-stc");
const blockStack = [];
let currentBlock = null;
function openBlock(disableTracking = false) {
  blockStack.push(currentBlock = disableTracking ? null : []);
}
function closeBlock() {
  blockStack.pop();
  currentBlock = blockStack[blockStack.length - 1] || null;
}
let isBlockTreeEnabled = 1;
function setBlockTracking(value) {
  isBlockTreeEnabled += value;
}
function setupBlock(vnode) {
  vnode.dynamicChildren = isBlockTreeEnabled > 0 ? currentBlock || EMPTY_ARR : null;
  closeBlock();
  if (isBlockTreeEnabled > 0 && currentBlock) {
    currentBlock.push(vnode);
  }
  return vnode;
}
function createElementBlock(type, props, children, patchFlag, dynamicProps, shapeFlag) {
  return setupBlock(
    createBaseVNode(
      type,
      props,
      children,
      patchFlag,
      dynamicProps,
      shapeFlag,
      true
      /* isBlock */
    )
  );
}
function createBlock(type, props, children, patchFlag, dynamicProps) {
  return setupBlock(
    createVNode(
      type,
      props,
      children,
      patchFlag,
      dynamicProps,
      true
      /* isBlock: prevent a block from tracking itself */
    )
  );
}
function isVNode(value) {
  return value ? value.__v_isVNode === true : false;
}
function isSameVNodeType(n1, n2) {
  return n1.type === n2.type && n1.key === n2.key;
}
const InternalObjectKey = `__vInternal`;
const normalizeKey = ({ key }) => key != null ? key : null;
const normalizeRef = ({
  ref,
  ref_key,
  ref_for
}) => {
  if (typeof ref === "number") {
    ref = "" + ref;
  }
  return ref != null ? isString$3(ref) || isRef(ref) || isFunction$1(ref) ? { i: currentRenderingInstance, r: ref, k: ref_key, f: !!ref_for } : ref : null;
};
function createBaseVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, shapeFlag = type === Fragment ? 0 : 1, isBlockNode = false, needFullChildrenNormalization = false) {
  const vnode = {
    __v_isVNode: true,
    __v_skip: true,
    type,
    props,
    key: props && normalizeKey(props),
    ref: props && normalizeRef(props),
    scopeId: currentScopeId,
    slotScopeIds: null,
    children,
    component: null,
    suspense: null,
    ssContent: null,
    ssFallback: null,
    dirs: null,
    transition: null,
    el: null,
    anchor: null,
    target: null,
    targetAnchor: null,
    staticCount: 0,
    shapeFlag,
    patchFlag,
    dynamicProps,
    dynamicChildren: null,
    appContext: null,
    ctx: currentRenderingInstance
  };
  if (needFullChildrenNormalization) {
    normalizeChildren(vnode, children);
    if (shapeFlag & 128) {
      type.normalize(vnode);
    }
  } else if (children) {
    vnode.shapeFlag |= isString$3(children) ? 8 : 16;
  }
  if (isBlockTreeEnabled > 0 && // avoid a block node from tracking itself
  !isBlockNode && // has current parent block
  currentBlock && // presence of a patch flag indicates this node needs patching on updates.
  // component nodes also should always be patched, because even if the
  // component doesn't need to update, it needs to persist the instance on to
  // the next vnode so that it can be properly unmounted later.
  (vnode.patchFlag > 0 || shapeFlag & 6) && // the EVENTS flag is only for hydration and if it is the only flag, the
  // vnode should not be considered dynamic due to handler caching.
  vnode.patchFlag !== 32) {
    currentBlock.push(vnode);
  }
  return vnode;
}
const createVNode = _createVNode;
function _createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, isBlockNode = false) {
  if (!type || type === NULL_DYNAMIC_COMPONENT) {
    type = Comment;
  }
  if (isVNode(type)) {
    const cloned = cloneVNode(
      type,
      props,
      true
      /* mergeRef: true */
    );
    if (children) {
      normalizeChildren(cloned, children);
    }
    if (isBlockTreeEnabled > 0 && !isBlockNode && currentBlock) {
      if (cloned.shapeFlag & 6) {
        currentBlock[currentBlock.indexOf(type)] = cloned;
      } else {
        currentBlock.push(cloned);
      }
    }
    cloned.patchFlag |= -2;
    return cloned;
  }
  if (isClassComponent(type)) {
    type = type.__vccOpts;
  }
  if (props) {
    props = guardReactiveProps(props);
    let { class: klass, style } = props;
    if (klass && !isString$3(klass)) {
      props.class = normalizeClass(klass);
    }
    if (isObject$o(style)) {
      if (isProxy(style) && !isArray$k(style)) {
        style = extend$3({}, style);
      }
      props.style = normalizeStyle$1(style);
    }
  }
  const shapeFlag = isString$3(type) ? 1 : isSuspense(type) ? 128 : isTeleport(type) ? 64 : isObject$o(type) ? 4 : isFunction$1(type) ? 2 : 0;
  return createBaseVNode(
    type,
    props,
    children,
    patchFlag,
    dynamicProps,
    shapeFlag,
    isBlockNode,
    true
  );
}
function guardReactiveProps(props) {
  if (!props)
    return null;
  return isProxy(props) || InternalObjectKey in props ? extend$3({}, props) : props;
}
function cloneVNode(vnode, extraProps, mergeRef = false) {
  const { props, ref, patchFlag, children } = vnode;
  const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props;
  const cloned = {
    __v_isVNode: true,
    __v_skip: true,
    type: vnode.type,
    props: mergedProps,
    key: mergedProps && normalizeKey(mergedProps),
    ref: extraProps && extraProps.ref ? (
      // #2078 in the case of <component :is="vnode" ref="extra"/>
      // if the vnode itself already has a ref, cloneVNode will need to merge
      // the refs so the single vnode can be set on multiple refs
      mergeRef && ref ? isArray$k(ref) ? ref.concat(normalizeRef(extraProps)) : [ref, normalizeRef(extraProps)] : normalizeRef(extraProps)
    ) : ref,
    scopeId: vnode.scopeId,
    slotScopeIds: vnode.slotScopeIds,
    children: children,
    target: vnode.target,
    targetAnchor: vnode.targetAnchor,
    staticCount: vnode.staticCount,
    shapeFlag: vnode.shapeFlag,
    // if the vnode is cloned with extra props, we can no longer assume its
    // existing patch flag to be reliable and need to add the FULL_PROPS flag.
    // note: preserve flag for fragments since they use the flag for children
    // fast paths only.
    patchFlag: extraProps && vnode.type !== Fragment ? patchFlag === -1 ? 16 : patchFlag | 16 : patchFlag,
    dynamicProps: vnode.dynamicProps,
    dynamicChildren: vnode.dynamicChildren,
    appContext: vnode.appContext,
    dirs: vnode.dirs,
    transition: vnode.transition,
    // These should technically only be non-null on mounted VNodes. However,
    // they *should* be copied for kept-alive vnodes. So we just always copy
    // them since them being non-null during a mount doesn't affect the logic as
    // they will simply be overwritten.
    component: vnode.component,
    suspense: vnode.suspense,
    ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),
    ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),
    el: vnode.el,
    anchor: vnode.anchor,
    ctx: vnode.ctx,
    ce: vnode.ce
  };
  return cloned;
}
function createTextVNode(text = " ", flag = 0) {
  return createVNode(Text$1, null, text, flag);
}
function createCommentVNode(text = "", asBlock = false) {
  return asBlock ? (openBlock(), createBlock(Comment, null, text)) : createVNode(Comment, null, text);
}
function normalizeVNode(child) {
  if (child == null || typeof child === "boolean") {
    return createVNode(Comment);
  } else if (isArray$k(child)) {
    return createVNode(
      Fragment,
      null,
      // #3666, avoid reference pollution when reusing vnode
      child.slice()
    );
  } else if (typeof child === "object") {
    return cloneIfMounted(child);
  } else {
    return createVNode(Text$1, null, String(child));
  }
}
function cloneIfMounted(child) {
  return child.el === null && child.patchFlag !== -1 || child.memo ? child : cloneVNode(child);
}
function normalizeChildren(vnode, children) {
  let type = 0;
  const { shapeFlag } = vnode;
  if (children == null) {
    children = null;
  } else if (isArray$k(children)) {
    type = 16;
  } else if (typeof children === "object") {
    if (shapeFlag & (1 | 64)) {
      const slot = children.default;
      if (slot) {
        slot._c && (slot._d = false);
        normalizeChildren(vnode, slot());
        slot._c && (slot._d = true);
      }
      return;
    } else {
      type = 32;
      const slotFlag = children._;
      if (!slotFlag && !(InternalObjectKey in children)) {
        children._ctx = currentRenderingInstance;
      } else if (slotFlag === 3 && currentRenderingInstance) {
        if (currentRenderingInstance.slots._ === 1) {
          children._ = 1;
        } else {
          children._ = 2;
          vnode.patchFlag |= 1024;
        }
      }
    }
  } else if (isFunction$1(children)) {
    children = { default: children, _ctx: currentRenderingInstance };
    type = 32;
  } else {
    children = String(children);
    if (shapeFlag & 64) {
      type = 16;
      children = [createTextVNode(children)];
    } else {
      type = 8;
    }
  }
  vnode.children = children;
  vnode.shapeFlag |= type;
}
function mergeProps(...args) {
  const ret = {};
  for (let i = 0; i < args.length; i++) {
    const toMerge = args[i];
    for (const key in toMerge) {
      if (key === "class") {
        if (ret.class !== toMerge.class) {
          ret.class = normalizeClass([ret.class, toMerge.class]);
        }
      } else if (key === "style") {
        ret.style = normalizeStyle$1([ret.style, toMerge.style]);
      } else if (isOn(key)) {
        const existing = ret[key];
        const incoming = toMerge[key];
        if (incoming && existing !== incoming && !(isArray$k(existing) && existing.includes(incoming))) {
          ret[key] = existing ? [].concat(existing, incoming) : incoming;
        }
      } else if (key !== "") {
        ret[key] = toMerge[key];
      }
    }
  }
  return ret;
}
function invokeVNodeHook(hook, instance, vnode, prevVNode = null) {
  callWithAsyncErrorHandling(hook, instance, 7, [
    vnode,
    prevVNode
  ]);
}

const emptyAppContext = createAppContext();
let uid$6 = 0;
function createComponentInstance(vnode, parent, suspense) {
  const type = vnode.type;
  const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext;
  const instance = {
    uid: uid$6++,
    vnode,
    type,
    parent,
    appContext,
    root: null,
    // to be immediately set
    next: null,
    subTree: null,
    // will be set synchronously right after creation
    effect: null,
    update: null,
    // will be set synchronously right after creation
    scope: new EffectScope(
      true
      /* detached */
    ),
    render: null,
    proxy: null,
    exposed: null,
    exposeProxy: null,
    withProxy: null,
    provides: parent ? parent.provides : Object.create(appContext.provides),
    accessCache: null,
    renderCache: [],
    // local resolved assets
    components: null,
    directives: null,
    // resolved props and emits options
    propsOptions: normalizePropsOptions(type, appContext),
    emitsOptions: normalizeEmitsOptions(type, appContext),
    // emit
    emit: null,
    // to be set immediately
    emitted: null,
    // props default value
    propsDefaults: EMPTY_OBJ$1,
    // inheritAttrs
    inheritAttrs: type.inheritAttrs,
    // state
    ctx: EMPTY_OBJ$1,
    data: EMPTY_OBJ$1,
    props: EMPTY_OBJ$1,
    attrs: EMPTY_OBJ$1,
    slots: EMPTY_OBJ$1,
    refs: EMPTY_OBJ$1,
    setupState: EMPTY_OBJ$1,
    setupContext: null,
    attrsProxy: null,
    slotsProxy: null,
    // suspense related
    suspense,
    suspenseId: suspense ? suspense.pendingId : 0,
    asyncDep: null,
    asyncResolved: false,
    // lifecycle hooks
    // not using enums here because it results in computed properties
    isMounted: false,
    isUnmounted: false,
    isDeactivated: false,
    bc: null,
    c: null,
    bm: null,
    m: null,
    bu: null,
    u: null,
    um: null,
    bum: null,
    da: null,
    a: null,
    rtg: null,
    rtc: null,
    ec: null,
    sp: null
  };
  {
    instance.ctx = { _: instance };
  }
  instance.root = parent ? parent.root : instance;
  instance.emit = emit.bind(null, instance);
  if (vnode.ce) {
    vnode.ce(instance);
  }
  return instance;
}
let currentInstance = null;
const getCurrentInstance = () => currentInstance || currentRenderingInstance;
let internalSetCurrentInstance;
let globalCurrentInstanceSetters;
let settersKey = "__VUE_INSTANCE_SETTERS__";
{
  if (!(globalCurrentInstanceSetters = getGlobalThis()[settersKey])) {
    globalCurrentInstanceSetters = getGlobalThis()[settersKey] = [];
  }
  globalCurrentInstanceSetters.push((i) => currentInstance = i);
  internalSetCurrentInstance = (instance) => {
    if (globalCurrentInstanceSetters.length > 1) {
      globalCurrentInstanceSetters.forEach((s) => s(instance));
    } else {
      globalCurrentInstanceSetters[0](instance);
    }
  };
}
const setCurrentInstance = (instance) => {
  internalSetCurrentInstance(instance);
  instance.scope.on();
};
const unsetCurrentInstance = () => {
  currentInstance && currentInstance.scope.off();
  internalSetCurrentInstance(null);
};
function isStatefulComponent(instance) {
  return instance.vnode.shapeFlag & 4;
}
let isInSSRComponentSetup = false;
function setupComponent(instance, isSSR = false) {
  isInSSRComponentSetup = isSSR;
  const { props, children } = instance.vnode;
  const isStateful = isStatefulComponent(instance);
  initProps$1(instance, props, isStateful, isSSR);
  initSlots(instance, children);
  const setupResult = isStateful ? setupStatefulComponent(instance, isSSR) : void 0;
  isInSSRComponentSetup = false;
  return setupResult;
}
function setupStatefulComponent(instance, isSSR) {
  const Component = instance.type;
  instance.accessCache = /* @__PURE__ */ Object.create(null);
  instance.proxy = markRaw(new Proxy(instance.ctx, PublicInstanceProxyHandlers));
  const { setup } = Component;
  if (setup) {
    const setupContext = instance.setupContext = setup.length > 1 ? createSetupContext(instance) : null;
    setCurrentInstance(instance);
    pauseTracking();
    const setupResult = callWithErrorHandling(
      setup,
      instance,
      0,
      [instance.props, setupContext]
    );
    resetTracking();
    unsetCurrentInstance();
    if (isPromise(setupResult)) {
      setupResult.then(unsetCurrentInstance, unsetCurrentInstance);
      if (isSSR) {
        return setupResult.then((resolvedResult) => {
          handleSetupResult(instance, resolvedResult, isSSR);
        }).catch((e) => {
          handleError(e, instance, 0);
        });
      } else {
        instance.asyncDep = setupResult;
      }
    } else {
      handleSetupResult(instance, setupResult, isSSR);
    }
  } else {
    finishComponentSetup(instance, isSSR);
  }
}
function handleSetupResult(instance, setupResult, isSSR) {
  if (isFunction$1(setupResult)) {
    if (instance.type.__ssrInlineRender) {
      instance.ssrRender = setupResult;
    } else {
      instance.render = setupResult;
    }
  } else if (isObject$o(setupResult)) {
    instance.setupState = proxyRefs(setupResult);
  } else ;
  finishComponentSetup(instance, isSSR);
}
let compile;
function finishComponentSetup(instance, isSSR, skipOptions) {
  const Component = instance.type;
  if (!instance.render) {
    if (!isSSR && compile && !Component.render) {
      const template = Component.template || resolveMergedOptions(instance).template;
      if (template) {
        const { isCustomElement, compilerOptions } = instance.appContext.config;
        const { delimiters, compilerOptions: componentCompilerOptions } = Component;
        const finalCompilerOptions = extend$3(
          extend$3(
            {
              isCustomElement,
              delimiters
            },
            compilerOptions
          ),
          componentCompilerOptions
        );
        Component.render = compile(template, finalCompilerOptions);
      }
    }
    instance.render = Component.render || NOOP;
  }
  {
    setCurrentInstance(instance);
    pauseTracking();
    try {
      applyOptions(instance);
    } finally {
      resetTracking();
      unsetCurrentInstance();
    }
  }
}
function getAttrsProxy(instance) {
  return instance.attrsProxy || (instance.attrsProxy = new Proxy(
    instance.attrs,
    {
      get(target, key) {
        track(instance, "get", "$attrs");
        return target[key];
      }
    }
  ));
}
function createSetupContext(instance) {
  const expose = (exposed) => {
    instance.exposed = exposed || {};
  };
  {
    return {
      get attrs() {
        return getAttrsProxy(instance);
      },
      slots: instance.slots,
      emit: instance.emit,
      expose
    };
  }
}
function getExposeProxy(instance) {
  if (instance.exposed) {
    return instance.exposeProxy || (instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {
      get(target, key) {
        if (key in target) {
          return target[key];
        } else if (key in publicPropertiesMap) {
          return publicPropertiesMap[key](instance);
        }
      },
      has(target, key) {
        return key in target || key in publicPropertiesMap;
      }
    }));
  }
}
function getComponentName(Component, includeInferred = true) {
  return isFunction$1(Component) ? Component.displayName || Component.name : Component.name || includeInferred && Component.__name;
}
function isClassComponent(value) {
  return isFunction$1(value) && "__vccOpts" in value;
}

const computed = (getterOrOptions, debugOptions) => {
  return computed$1(getterOrOptions, debugOptions, isInSSRComponentSetup);
};

function h(type, propsOrChildren, children) {
  const l = arguments.length;
  if (l === 2) {
    if (isObject$o(propsOrChildren) && !isArray$k(propsOrChildren)) {
      if (isVNode(propsOrChildren)) {
        return createVNode(type, null, [propsOrChildren]);
      }
      return createVNode(type, propsOrChildren);
    } else {
      return createVNode(type, null, propsOrChildren);
    }
  } else {
    if (l > 3) {
      children = Array.prototype.slice.call(arguments, 2);
    } else if (l === 3 && isVNode(children)) {
      children = [children];
    }
    return createVNode(type, propsOrChildren, children);
  }
}

const ssrContextKey = Symbol.for("v-scx");
const useSSRContext = () => {
  {
    const ctx = inject(ssrContextKey);
    return ctx;
  }
};

const version$2 = "3.3.8";

/* Injected with object hook! */

const svgNS = "http://www.w3.org/2000/svg";
const doc = typeof document !== "undefined" ? document : null;
const templateContainer = doc && /* @__PURE__ */ doc.createElement("template");
const nodeOps = {
  insert: (child, parent, anchor) => {
    parent.insertBefore(child, anchor || null);
  },
  remove: (child) => {
    const parent = child.parentNode;
    if (parent) {
      parent.removeChild(child);
    }
  },
  createElement: (tag, isSVG, is, props) => {
    const el = isSVG ? doc.createElementNS(svgNS, tag) : doc.createElement(tag, is ? { is } : void 0);
    if (tag === "select" && props && props.multiple != null) {
      el.setAttribute("multiple", props.multiple);
    }
    return el;
  },
  createText: (text) => doc.createTextNode(text),
  createComment: (text) => doc.createComment(text),
  setText: (node, text) => {
    node.nodeValue = text;
  },
  setElementText: (el, text) => {
    el.textContent = text;
  },
  parentNode: (node) => node.parentNode,
  nextSibling: (node) => node.nextSibling,
  querySelector: (selector) => doc.querySelector(selector),
  setScopeId(el, id) {
    el.setAttribute(id, "");
  },
  // __UNSAFE__
  // Reason: innerHTML.
  // Static content here can only come from compiled templates.
  // As long as the user only uses trusted templates, this is safe.
  insertStaticContent(content, parent, anchor, isSVG, start, end) {
    const before = anchor ? anchor.previousSibling : parent.lastChild;
    if (start && (start === end || start.nextSibling)) {
      while (true) {
        parent.insertBefore(start.cloneNode(true), anchor);
        if (start === end || !(start = start.nextSibling))
          break;
      }
    } else {
      templateContainer.innerHTML = isSVG ? `<svg>${content}</svg>` : content;
      const template = templateContainer.content;
      if (isSVG) {
        const wrapper = template.firstChild;
        while (wrapper.firstChild) {
          template.appendChild(wrapper.firstChild);
        }
        template.removeChild(wrapper);
      }
      parent.insertBefore(template, anchor);
    }
    return [
      // first
      before ? before.nextSibling : parent.firstChild,
      // last
      anchor ? anchor.previousSibling : parent.lastChild
    ];
  }
};
const vtcKey = Symbol("_vtc");

function patchClass(el, value, isSVG) {
  const transitionClasses = el[vtcKey];
  if (transitionClasses) {
    value = (value ? [value, ...transitionClasses] : [...transitionClasses]).join(" ");
  }
  if (value == null) {
    el.removeAttribute("class");
  } else if (isSVG) {
    el.setAttribute("class", value);
  } else {
    el.className = value;
  }
}

const vShowOldKey = Symbol("_vod");
const vShow = {
  beforeMount(el, { value }, { transition }) {
    el[vShowOldKey] = el.style.display === "none" ? "" : el.style.display;
    if (transition && value) {
      transition.beforeEnter(el);
    } else {
      setDisplay(el, value);
    }
  },
  mounted(el, { value }, { transition }) {
    if (transition && value) {
      transition.enter(el);
    }
  },
  updated(el, { value, oldValue }, { transition }) {
    if (!value === !oldValue)
      return;
    if (transition) {
      if (value) {
        transition.beforeEnter(el);
        setDisplay(el, true);
        transition.enter(el);
      } else {
        transition.leave(el, () => {
          setDisplay(el, false);
        });
      }
    } else {
      setDisplay(el, value);
    }
  },
  beforeUnmount(el, { value }) {
    setDisplay(el, value);
  }
};
function setDisplay(el, value) {
  el.style.display = value ? el[vShowOldKey] : "none";
}

function patchStyle(el, prev, next) {
  const style = el.style;
  const isCssString = isString$3(next);
  if (next && !isCssString) {
    if (prev && !isString$3(prev)) {
      for (const key in prev) {
        if (next[key] == null) {
          setStyle(style, key, "");
        }
      }
    }
    for (const key in next) {
      setStyle(style, key, next[key]);
    }
  } else {
    const currentDisplay = style.display;
    if (isCssString) {
      if (prev !== next) {
        style.cssText = next;
      }
    } else if (prev) {
      el.removeAttribute("style");
    }
    if (vShowOldKey in el) {
      style.display = currentDisplay;
    }
  }
}
const importantRE = /\s*!important$/;
function setStyle(style, name, val) {
  if (isArray$k(val)) {
    val.forEach((v) => setStyle(style, name, v));
  } else {
    if (val == null)
      val = "";
    if (name.startsWith("--")) {
      style.setProperty(name, val);
    } else {
      const prefixed = autoPrefix(style, name);
      if (importantRE.test(val)) {
        style.setProperty(
          hyphenate(prefixed),
          val.replace(importantRE, ""),
          "important"
        );
      } else {
        style[prefixed] = val;
      }
    }
  }
}
const prefixes = ["Webkit", "Moz", "ms"];
const prefixCache = {};
function autoPrefix(style, rawName) {
  const cached = prefixCache[rawName];
  if (cached) {
    return cached;
  }
  let name = camelize(rawName);
  if (name !== "filter" && name in style) {
    return prefixCache[rawName] = name;
  }
  name = capitalize(name);
  for (let i = 0; i < prefixes.length; i++) {
    const prefixed = prefixes[i] + name;
    if (prefixed in style) {
      return prefixCache[rawName] = prefixed;
    }
  }
  return rawName;
}

const xlinkNS = "http://www.w3.org/1999/xlink";
function patchAttr(el, key, value, isSVG, instance) {
  if (isSVG && key.startsWith("xlink:")) {
    if (value == null) {
      el.removeAttributeNS(xlinkNS, key.slice(6, key.length));
    } else {
      el.setAttributeNS(xlinkNS, key, value);
    }
  } else {
    const isBoolean = isSpecialBooleanAttr(key);
    if (value == null || isBoolean && !includeBooleanAttr(value)) {
      el.removeAttribute(key);
    } else {
      el.setAttribute(key, isBoolean ? "" : value);
    }
  }
}

function patchDOMProp(el, key, value, prevChildren, parentComponent, parentSuspense, unmountChildren) {
  if (key === "innerHTML" || key === "textContent") {
    if (prevChildren) {
      unmountChildren(prevChildren, parentComponent, parentSuspense);
    }
    el[key] = value == null ? "" : value;
    return;
  }
  const tag = el.tagName;
  if (key === "value" && tag !== "PROGRESS" && // custom elements may use _value internally
  !tag.includes("-")) {
    el._value = value;
    const oldValue = tag === "OPTION" ? el.getAttribute("value") : el.value;
    const newValue = value == null ? "" : value;
    if (oldValue !== newValue) {
      el.value = newValue;
    }
    if (value == null) {
      el.removeAttribute(key);
    }
    return;
  }
  let needRemove = false;
  if (value === "" || value == null) {
    const type = typeof el[key];
    if (type === "boolean") {
      value = includeBooleanAttr(value);
    } else if (value == null && type === "string") {
      value = "";
      needRemove = true;
    } else if (type === "number") {
      value = 0;
      needRemove = true;
    }
  }
  try {
    el[key] = value;
  } catch (e) {
  }
  needRemove && el.removeAttribute(key);
}

function addEventListener$2(el, event, handler, options) {
  el.addEventListener(event, handler, options);
}
function removeEventListener$2(el, event, handler, options) {
  el.removeEventListener(event, handler, options);
}
const veiKey = Symbol("_vei");
function patchEvent(el, rawName, prevValue, nextValue, instance = null) {
  const invokers = el[veiKey] || (el[veiKey] = {});
  const existingInvoker = invokers[rawName];
  if (nextValue && existingInvoker) {
    existingInvoker.value = nextValue;
  } else {
    const [name, options] = parseName(rawName);
    if (nextValue) {
      const invoker = invokers[rawName] = createInvoker(nextValue, instance);
      addEventListener$2(el, name, invoker, options);
    } else if (existingInvoker) {
      removeEventListener$2(el, name, existingInvoker, options);
      invokers[rawName] = void 0;
    }
  }
}
const optionsModifierRE = /(?:Once|Passive|Capture)$/;
function parseName(name) {
  let options;
  if (optionsModifierRE.test(name)) {
    options = {};
    let m;
    while (m = name.match(optionsModifierRE)) {
      name = name.slice(0, name.length - m[0].length);
      options[m[0].toLowerCase()] = true;
    }
  }
  const event = name[2] === ":" ? name.slice(3) : hyphenate(name.slice(2));
  return [event, options];
}
let cachedNow = 0;
const p = /* @__PURE__ */ Promise.resolve();
const getNow = () => cachedNow || (p.then(() => cachedNow = 0), cachedNow = Date.now());
function createInvoker(initialValue, instance) {
  const invoker = (e) => {
    if (!e._vts) {
      e._vts = Date.now();
    } else if (e._vts <= invoker.attached) {
      return;
    }
    callWithAsyncErrorHandling(
      patchStopImmediatePropagation(e, invoker.value),
      instance,
      5,
      [e]
    );
  };
  invoker.value = initialValue;
  invoker.attached = getNow();
  return invoker;
}
function patchStopImmediatePropagation(e, value) {
  if (isArray$k(value)) {
    const originalStop = e.stopImmediatePropagation;
    e.stopImmediatePropagation = () => {
      originalStop.call(e);
      e._stopped = true;
    };
    return value.map((fn) => (e2) => !e2._stopped && fn && fn(e2));
  } else {
    return value;
  }
}

const nativeOnRE = /^on[a-z]/;
const patchProp = (el, key, prevValue, nextValue, isSVG = false, prevChildren, parentComponent, parentSuspense, unmountChildren) => {
  if (key === "class") {
    patchClass(el, nextValue, isSVG);
  } else if (key === "style") {
    patchStyle(el, prevValue, nextValue);
  } else if (isOn(key)) {
    if (!isModelListener(key)) {
      patchEvent(el, key, prevValue, nextValue, parentComponent);
    }
  } else if (key[0] === "." ? (key = key.slice(1), true) : key[0] === "^" ? (key = key.slice(1), false) : shouldSetAsProp(el, key, nextValue, isSVG)) {
    patchDOMProp(
      el,
      key,
      nextValue,
      prevChildren,
      parentComponent,
      parentSuspense,
      unmountChildren
    );
  } else {
    if (key === "true-value") {
      el._trueValue = nextValue;
    } else if (key === "false-value") {
      el._falseValue = nextValue;
    }
    patchAttr(el, key, nextValue, isSVG);
  }
};
function shouldSetAsProp(el, key, value, isSVG) {
  if (isSVG) {
    if (key === "innerHTML" || key === "textContent") {
      return true;
    }
    if (key in el && nativeOnRE.test(key) && isFunction$1(value)) {
      return true;
    }
    return false;
  }
  if (key === "spellcheck" || key === "draggable" || key === "translate") {
    return false;
  }
  if (key === "form") {
    return false;
  }
  if (key === "list" && el.tagName === "INPUT") {
    return false;
  }
  if (key === "type" && el.tagName === "TEXTAREA") {
    return false;
  }
  if (nativeOnRE.test(key) && isString$3(value)) {
    return false;
  }
  return key in el;
}

const getModelAssigner = (vnode) => {
  const fn = vnode.props["onUpdate:modelValue"] || false;
  return isArray$k(fn) ? (value) => invokeArrayFns(fn, value) : fn;
};
function onCompositionStart(e) {
  e.target.composing = true;
}
function onCompositionEnd(e) {
  const target = e.target;
  if (target.composing) {
    target.composing = false;
    target.dispatchEvent(new Event("input"));
  }
}
const assignKey = Symbol("_assign");
const vModelText = {
  created(el, { modifiers: { lazy, trim, number } }, vnode) {
    el[assignKey] = getModelAssigner(vnode);
    const castToNumber = number || vnode.props && vnode.props.type === "number";
    addEventListener$2(el, lazy ? "change" : "input", (e) => {
      if (e.target.composing)
        return;
      let domValue = el.value;
      if (trim) {
        domValue = domValue.trim();
      }
      if (castToNumber) {
        domValue = looseToNumber(domValue);
      }
      el[assignKey](domValue);
    });
    if (trim) {
      addEventListener$2(el, "change", () => {
        el.value = el.value.trim();
      });
    }
    if (!lazy) {
      addEventListener$2(el, "compositionstart", onCompositionStart);
      addEventListener$2(el, "compositionend", onCompositionEnd);
      addEventListener$2(el, "change", onCompositionEnd);
    }
  },
  // set value on mounted so it's after min/max for type="range"
  mounted(el, { value }) {
    el.value = value == null ? "" : value;
  },
  beforeUpdate(el, { value, modifiers: { lazy, trim, number } }, vnode) {
    el[assignKey] = getModelAssigner(vnode);
    if (el.composing)
      return;
    if (document.activeElement === el && el.type !== "range") {
      if (lazy) {
        return;
      }
      if (trim && el.value.trim() === value) {
        return;
      }
      if ((number || el.type === "number") && looseToNumber(el.value) === value) {
        return;
      }
    }
    const newValue = value == null ? "" : value;
    if (el.value !== newValue) {
      el.value = newValue;
    }
  }
};
const vModelCheckbox = {
  // #4096 array checkboxes need to be deep traversed
  deep: true,
  created(el, _, vnode) {
    el[assignKey] = getModelAssigner(vnode);
    addEventListener$2(el, "change", () => {
      const modelValue = el._modelValue;
      const elementValue = getValue(el);
      const checked = el.checked;
      const assign = el[assignKey];
      if (isArray$k(modelValue)) {
        const index = looseIndexOf(modelValue, elementValue);
        const found = index !== -1;
        if (checked && !found) {
          assign(modelValue.concat(elementValue));
        } else if (!checked && found) {
          const filtered = [...modelValue];
          filtered.splice(index, 1);
          assign(filtered);
        }
      } else if (isSet(modelValue)) {
        const cloned = new Set(modelValue);
        if (checked) {
          cloned.add(elementValue);
        } else {
          cloned.delete(elementValue);
        }
        assign(cloned);
      } else {
        assign(getCheckboxValue(el, checked));
      }
    });
  },
  // set initial checked on mount to wait for true-value/false-value
  mounted: setChecked,
  beforeUpdate(el, binding, vnode) {
    el[assignKey] = getModelAssigner(vnode);
    setChecked(el, binding, vnode);
  }
};
function setChecked(el, { value, oldValue }, vnode) {
  el._modelValue = value;
  if (isArray$k(value)) {
    el.checked = looseIndexOf(value, vnode.props.value) > -1;
  } else if (isSet(value)) {
    el.checked = value.has(vnode.props.value);
  } else if (value !== oldValue) {
    el.checked = looseEqual(value, getCheckboxValue(el, true));
  }
}
function getValue(el) {
  return "_value" in el ? el._value : el.value;
}
function getCheckboxValue(el, checked) {
  const key = checked ? "_trueValue" : "_falseValue";
  return key in el ? el[key] : checked;
}

const rendererOptions = /* @__PURE__ */ extend$3({ patchProp }, nodeOps);
let renderer;
function ensureRenderer() {
  return renderer || (renderer = createRenderer(rendererOptions));
}
const createApp = (...args) => {
  const app = ensureRenderer().createApp(...args);
  const { mount } = app;
  app.mount = (containerOrSelector) => {
    const container = normalizeContainer(containerOrSelector);
    if (!container)
      return;
    const component = app._component;
    if (!isFunction$1(component) && !component.render && !component.template) {
      component.template = container.innerHTML;
    }
    container.innerHTML = "";
    const proxy = mount(container, false, container instanceof SVGElement);
    if (container instanceof Element) {
      container.removeAttribute("v-cloak");
      container.setAttribute("data-v-app", "");
    }
    return proxy;
  };
  return app;
};
function normalizeContainer(container) {
  if (isString$3(container)) {
    const res = document.querySelector(container);
    return res;
  }
  return container;
}

/* Injected with object hook! */

/*!
  * vue-router v4.2.5
  * (c) 2023 Eduardo San Martin Morote
  * @license MIT
  */

const isBrowser = typeof window !== 'undefined';

function isESModule(obj) {
    return obj.__esModule || obj[Symbol.toStringTag] === 'Module';
}
const assign$7 = Object.assign;
function applyToParams(fn, params) {
    const newParams = {};
    for (const key in params) {
        const value = params[key];
        newParams[key] = isArray$j(value)
            ? value.map(fn)
            : fn(value);
    }
    return newParams;
}
const noop$4 = () => { };
/**
 * Typesafe alternative to Array.isArray
 * https://github.com/microsoft/TypeScript/pull/48228
 */
const isArray$j = Array.isArray;

const TRAILING_SLASH_RE = /\/$/;
const removeTrailingSlash = (path) => path.replace(TRAILING_SLASH_RE, '');
/**
 * Transforms a URI into a normalized history location
 *
 * @param parseQuery
 * @param location - URI to normalize
 * @param currentLocation - current absolute location. Allows resolving relative
 * paths. Must start with `/`. Defaults to `/`
 * @returns a normalized history location
 */
function parseURL(parseQuery, location, currentLocation = '/') {
    let path, query = {}, searchString = '', hash = '';
    // Could use URL and URLSearchParams but IE 11 doesn't support it
    // TODO: move to new URL()
    const hashPos = location.indexOf('#');
    let searchPos = location.indexOf('?');
    // the hash appears before the search, so it's not part of the search string
    if (hashPos < searchPos && hashPos >= 0) {
        searchPos = -1;
    }
    if (searchPos > -1) {
        path = location.slice(0, searchPos);
        searchString = location.slice(searchPos + 1, hashPos > -1 ? hashPos : location.length);
        query = parseQuery(searchString);
    }
    if (hashPos > -1) {
        path = path || location.slice(0, hashPos);
        // keep the # character
        hash = location.slice(hashPos, location.length);
    }
    // no search and no query
    path = resolveRelativePath(path != null ? path : location, currentLocation);
    // empty path means a relative query or hash `?foo=f`, `#thing`
    return {
        fullPath: path + (searchString && '?') + searchString + hash,
        path,
        query,
        hash,
    };
}
/**
 * Stringifies a URL object
 *
 * @param stringifyQuery
 * @param location
 */
function stringifyURL(stringifyQuery, location) {
    const query = location.query ? stringifyQuery(location.query) : '';
    return location.path + (query && '?') + query + (location.hash || '');
}
/**
 * Strips off the base from the beginning of a location.pathname in a non-case-sensitive way.
 *
 * @param pathname - location.pathname
 * @param base - base to strip off
 */
function stripBase(pathname, base) {
    // no base or base is not found at the beginning
    if (!base || !pathname.toLowerCase().startsWith(base.toLowerCase()))
        return pathname;
    return pathname.slice(base.length) || '/';
}
/**
 * Checks if two RouteLocation are equal. This means that both locations are
 * pointing towards the same {@link RouteRecord} and that all `params`, `query`
 * parameters and `hash` are the same
 *
 * @param stringifyQuery - A function that takes a query object of type LocationQueryRaw and returns a string representation of it.
 * @param a - first {@link RouteLocation}
 * @param b - second {@link RouteLocation}
 */
function isSameRouteLocation(stringifyQuery, a, b) {
    const aLastIndex = a.matched.length - 1;
    const bLastIndex = b.matched.length - 1;
    return (aLastIndex > -1 &&
        aLastIndex === bLastIndex &&
        isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) &&
        isSameRouteLocationParams(a.params, b.params) &&
        stringifyQuery(a.query) === stringifyQuery(b.query) &&
        a.hash === b.hash);
}
/**
 * Check if two `RouteRecords` are equal. Takes into account aliases: they are
 * considered equal to the `RouteRecord` they are aliasing.
 *
 * @param a - first {@link RouteRecord}
 * @param b - second {@link RouteRecord}
 */
function isSameRouteRecord(a, b) {
    // since the original record has an undefined value for aliasOf
    // but all aliases point to the original record, this will always compare
    // the original record
    return (a.aliasOf || a) === (b.aliasOf || b);
}
function isSameRouteLocationParams(a, b) {
    if (Object.keys(a).length !== Object.keys(b).length)
        return false;
    for (const key in a) {
        if (!isSameRouteLocationParamsValue(a[key], b[key]))
            return false;
    }
    return true;
}
function isSameRouteLocationParamsValue(a, b) {
    return isArray$j(a)
        ? isEquivalentArray(a, b)
        : isArray$j(b)
            ? isEquivalentArray(b, a)
            : a === b;
}
/**
 * Check if two arrays are the same or if an array with one single entry is the
 * same as another primitive value. Used to check query and parameters
 *
 * @param a - array of values
 * @param b - array of values or a single value
 */
function isEquivalentArray(a, b) {
    return isArray$j(b)
        ? a.length === b.length && a.every((value, i) => value === b[i])
        : a.length === 1 && a[0] === b;
}
/**
 * Resolves a relative path that starts with `.`.
 *
 * @param to - path location we are resolving
 * @param from - currentLocation.path, should start with `/`
 */
function resolveRelativePath(to, from) {
    if (to.startsWith('/'))
        return to;
    if (!to)
        return from;
    const fromSegments = from.split('/');
    const toSegments = to.split('/');
    const lastToSegment = toSegments[toSegments.length - 1];
    // make . and ./ the same (../ === .., ../../ === ../..)
    // this is the same behavior as new URL()
    if (lastToSegment === '..' || lastToSegment === '.') {
        toSegments.push('');
    }
    let position = fromSegments.length - 1;
    let toPosition;
    let segment;
    for (toPosition = 0; toPosition < toSegments.length; toPosition++) {
        segment = toSegments[toPosition];
        // we stay on the same position
        if (segment === '.')
            continue;
        // go up in the from array
        if (segment === '..') {
            // we can't go below zero, but we still need to increment toPosition
            if (position > 1)
                position--;
            // continue
        }
        // we reached a non-relative path, we stop here
        else
            break;
    }
    return (fromSegments.slice(0, position).join('/') +
        '/' +
        toSegments
            // ensure we use at least the last element in the toSegments
            .slice(toPosition - (toPosition === toSegments.length ? 1 : 0))
            .join('/'));
}

var NavigationType;
(function (NavigationType) {
    NavigationType["pop"] = "pop";
    NavigationType["push"] = "push";
})(NavigationType || (NavigationType = {}));
var NavigationDirection;
(function (NavigationDirection) {
    NavigationDirection["back"] = "back";
    NavigationDirection["forward"] = "forward";
    NavigationDirection["unknown"] = "";
})(NavigationDirection || (NavigationDirection = {}));
// Generic utils
/**
 * Normalizes a base by removing any trailing slash and reading the base tag if
 * present.
 *
 * @param base - base to normalize
 */
function normalizeBase(base) {
    if (!base) {
        if (isBrowser) {
            // respect <base> tag
            const baseEl = document.querySelector('base');
            base = (baseEl && baseEl.getAttribute('href')) || '/';
            // strip full URL origin
            base = base.replace(/^\w+:\/\/[^\/]+/, '');
        }
        else {
            base = '/';
        }
    }
    // ensure leading slash when it was removed by the regex above avoid leading
    // slash with hash because the file could be read from the disk like file://
    // and the leading slash would cause problems
    if (base[0] !== '/' && base[0] !== '#')
        base = '/' + base;
    // remove the trailing slash so all other method can just do `base + fullPath`
    // to build an href
    return removeTrailingSlash(base);
}
// remove any character before the hash
const BEFORE_HASH_RE = /^[^#]+#/;
function createHref(base, location) {
    return base.replace(BEFORE_HASH_RE, '#') + location;
}

function getElementPosition(el, offset) {
    const docRect = document.documentElement.getBoundingClientRect();
    const elRect = el.getBoundingClientRect();
    return {
        behavior: offset.behavior,
        left: elRect.left - docRect.left - (offset.left || 0),
        top: elRect.top - docRect.top - (offset.top || 0),
    };
}
const computeScrollPosition = () => ({
    left: window.pageXOffset,
    top: window.pageYOffset,
});
function scrollToPosition(position) {
    let scrollToOptions;
    if ('el' in position) {
        const positionEl = position.el;
        const isIdSelector = typeof positionEl === 'string' && positionEl.startsWith('#');
        const el = typeof positionEl === 'string'
            ? isIdSelector
                ? document.getElementById(positionEl.slice(1))
                : document.querySelector(positionEl)
            : positionEl;
        if (!el) {
            return;
        }
        scrollToOptions = getElementPosition(el, position);
    }
    else {
        scrollToOptions = position;
    }
    if ('scrollBehavior' in document.documentElement.style)
        window.scrollTo(scrollToOptions);
    else {
        window.scrollTo(scrollToOptions.left != null ? scrollToOptions.left : window.pageXOffset, scrollToOptions.top != null ? scrollToOptions.top : window.pageYOffset);
    }
}
function getScrollKey(path, delta) {
    const position = history.state ? history.state.position - delta : -1;
    return position + path;
}
const scrollPositions = new Map();
function saveScrollPosition(key, scrollPosition) {
    scrollPositions.set(key, scrollPosition);
}
function getSavedScrollPosition(key) {
    const scroll = scrollPositions.get(key);
    // consume it so it's not used again
    scrollPositions.delete(key);
    return scroll;
}
// TODO: RFC about how to save scroll position
/**
 * ScrollBehavior instance used by the router to compute and restore the scroll
 * position when navigating.
 */
// export interface ScrollHandler<ScrollPositionEntry extends HistoryStateValue, ScrollPosition extends ScrollPositionEntry> {
//   // returns a scroll position that can be saved in history
//   compute(): ScrollPositionEntry
//   // can take an extended ScrollPositionEntry
//   scroll(position: ScrollPosition): void
// }
// export const scrollHandler: ScrollHandler<ScrollPosition> = {
//   compute: computeScroll,
//   scroll: scrollToPosition,
// }

let createBaseLocation = () => location.protocol + '//' + location.host;
/**
 * Creates a normalized history location from a window.location object
 * @param base - The base path
 * @param location - The window.location object
 */
function createCurrentLocation(base, location) {
    const { pathname, search, hash } = location;
    // allows hash bases like #, /#, #/, #!, #!/, /#!/, or even /folder#end
    const hashPos = base.indexOf('#');
    if (hashPos > -1) {
        let slicePos = hash.includes(base.slice(hashPos))
            ? base.slice(hashPos).length
            : 1;
        let pathFromHash = hash.slice(slicePos);
        // prepend the starting slash to hash so the url starts with /#
        if (pathFromHash[0] !== '/')
            pathFromHash = '/' + pathFromHash;
        return stripBase(pathFromHash, '');
    }
    const path = stripBase(pathname, base);
    return path + search + hash;
}
function useHistoryListeners(base, historyState, currentLocation, replace) {
    let listeners = [];
    let teardowns = [];
    // TODO: should it be a stack? a Dict. Check if the popstate listener
    // can trigger twice
    let pauseState = null;
    const popStateHandler = ({ state, }) => {
        const to = createCurrentLocation(base, location);
        const from = currentLocation.value;
        const fromState = historyState.value;
        let delta = 0;
        if (state) {
            currentLocation.value = to;
            historyState.value = state;
            // ignore the popstate and reset the pauseState
            if (pauseState && pauseState === from) {
                pauseState = null;
                return;
            }
            delta = fromState ? state.position - fromState.position : 0;
        }
        else {
            replace(to);
        }
        // Here we could also revert the navigation by calling history.go(-delta)
        // this listener will have to be adapted to not trigger again and to wait for the url
        // to be updated before triggering the listeners. Some kind of validation function would also
        // need to be passed to the listeners so the navigation can be accepted
        // call all listeners
        listeners.forEach(listener => {
            listener(currentLocation.value, from, {
                delta,
                type: NavigationType.pop,
                direction: delta
                    ? delta > 0
                        ? NavigationDirection.forward
                        : NavigationDirection.back
                    : NavigationDirection.unknown,
            });
        });
    };
    function pauseListeners() {
        pauseState = currentLocation.value;
    }
    function listen(callback) {
        // set up the listener and prepare teardown callbacks
        listeners.push(callback);
        const teardown = () => {
            const index = listeners.indexOf(callback);
            if (index > -1)
                listeners.splice(index, 1);
        };
        teardowns.push(teardown);
        return teardown;
    }
    function beforeUnloadListener() {
        const { history } = window;
        if (!history.state)
            return;
        history.replaceState(assign$7({}, history.state, { scroll: computeScrollPosition() }), '');
    }
    function destroy() {
        for (const teardown of teardowns)
            teardown();
        teardowns = [];
        window.removeEventListener('popstate', popStateHandler);
        window.removeEventListener('beforeunload', beforeUnloadListener);
    }
    // set up the listeners and prepare teardown callbacks
    window.addEventListener('popstate', popStateHandler);
    // TODO: could we use 'pagehide' or 'visibilitychange' instead?
    // https://developer.chrome.com/blog/page-lifecycle-api/
    window.addEventListener('beforeunload', beforeUnloadListener, {
        passive: true,
    });
    return {
        pauseListeners,
        listen,
        destroy,
    };
}
/**
 * Creates a state object
 */
function buildState(back, current, forward, replaced = false, computeScroll = false) {
    return {
        back,
        current,
        forward,
        replaced,
        position: window.history.length,
        scroll: computeScroll ? computeScrollPosition() : null,
    };
}
function useHistoryStateNavigation(base) {
    const { history, location } = window;
    // private variables
    const currentLocation = {
        value: createCurrentLocation(base, location),
    };
    const historyState = { value: history.state };
    // build current history entry as this is a fresh navigation
    if (!historyState.value) {
        changeLocation(currentLocation.value, {
            back: null,
            current: currentLocation.value,
            forward: null,
            // the length is off by one, we need to decrease it
            position: history.length - 1,
            replaced: true,
            // don't add a scroll as the user may have an anchor, and we want
            // scrollBehavior to be triggered without a saved position
            scroll: null,
        }, true);
    }
    function changeLocation(to, state, replace) {
        /**
         * if a base tag is provided, and we are on a normal domain, we have to
         * respect the provided `base` attribute because pushState() will use it and
         * potentially erase anything before the `#` like at
         * https://github.com/vuejs/router/issues/685 where a base of
         * `/folder/#` but a base of `/` would erase the `/folder/` section. If
         * there is no host, the `<base>` tag makes no sense and if there isn't a
         * base tag we can just use everything after the `#`.
         */
        const hashIndex = base.indexOf('#');
        const url = hashIndex > -1
            ? (location.host && document.querySelector('base')
                ? base
                : base.slice(hashIndex)) + to
            : createBaseLocation() + base + to;
        try {
            // BROWSER QUIRK
            // NOTE: Safari throws a SecurityError when calling this function 100 times in 30 seconds
            history[replace ? 'replaceState' : 'pushState'](state, '', url);
            historyState.value = state;
        }
        catch (err) {
            {
                console.error(err);
            }
            // Force the navigation, this also resets the call count
            location[replace ? 'replace' : 'assign'](url);
        }
    }
    function replace(to, data) {
        const state = assign$7({}, history.state, buildState(historyState.value.back, 
        // keep back and forward entries but override current position
        to, historyState.value.forward, true), data, { position: historyState.value.position });
        changeLocation(to, state, true);
        currentLocation.value = to;
    }
    function push(to, data) {
        // Add to current entry the information of where we are going
        // as well as saving the current position
        const currentState = assign$7({}, 
        // use current history state to gracefully handle a wrong call to
        // history.replaceState
        // https://github.com/vuejs/router/issues/366
        historyState.value, history.state, {
            forward: to,
            scroll: computeScrollPosition(),
        });
        changeLocation(currentState.current, currentState, true);
        const state = assign$7({}, buildState(currentLocation.value, to, null), { position: currentState.position + 1 }, data);
        changeLocation(to, state, false);
        currentLocation.value = to;
    }
    return {
        location: currentLocation,
        state: historyState,
        push,
        replace,
    };
}
/**
 * Creates an HTML5 history. Most common history for single page applications.
 *
 * @param base -
 */
function createWebHistory(base) {
    base = normalizeBase(base);
    const historyNavigation = useHistoryStateNavigation(base);
    const historyListeners = useHistoryListeners(base, historyNavigation.state, historyNavigation.location, historyNavigation.replace);
    function go(delta, triggerListeners = true) {
        if (!triggerListeners)
            historyListeners.pauseListeners();
        history.go(delta);
    }
    const routerHistory = assign$7({
        // it's overridden right after
        location: '',
        base,
        go,
        createHref: createHref.bind(null, base),
    }, historyNavigation, historyListeners);
    Object.defineProperty(routerHistory, 'location', {
        enumerable: true,
        get: () => historyNavigation.location.value,
    });
    Object.defineProperty(routerHistory, 'state', {
        enumerable: true,
        get: () => historyNavigation.state.value,
    });
    return routerHistory;
}

/**
 * Creates a hash history. Useful for web applications with no host (e.g. `file://`) or when configuring a server to
 * handle any URL is not possible.
 *
 * @param base - optional base to provide. Defaults to `location.pathname + location.search` If there is a `<base>` tag
 * in the `head`, its value will be ignored in favor of this parameter **but note it affects all the history.pushState()
 * calls**, meaning that if you use a `<base>` tag, it's `href` value **has to match this parameter** (ignoring anything
 * after the `#`).
 *
 * @example
 * ```js
 * // at https://example.com/folder
 * createWebHashHistory() // gives a url of `https://example.com/folder#`
 * createWebHashHistory('/folder/') // gives a url of `https://example.com/folder/#`
 * // if the `#` is provided in the base, it won't be added by `createWebHashHistory`
 * createWebHashHistory('/folder/#/app/') // gives a url of `https://example.com/folder/#/app/`
 * // you should avoid doing this because it changes the original url and breaks copying urls
 * createWebHashHistory('/other-folder/') // gives a url of `https://example.com/other-folder/#`
 *
 * // at file:///usr/etc/folder/index.html
 * // for locations with no `host`, the base is ignored
 * createWebHashHistory('/iAmIgnored') // gives a url of `file:///usr/etc/folder/index.html#`
 * ```
 */
function createWebHashHistory(base) {
    // Make sure this implementation is fine in terms of encoding, specially for IE11
    // for `file://`, directly use the pathname and ignore the base
    // location.pathname contains an initial `/` even at the root: `https://example.com`
    base = location.host ? base || location.pathname + location.search : '';
    // allow the user to provide a `#` in the middle: `/base/#/app`
    if (!base.includes('#'))
        base += '#';
    return createWebHistory(base);
}

function isRouteLocation(route) {
    return typeof route === 'string' || (route && typeof route === 'object');
}
function isRouteName(name) {
    return typeof name === 'string' || typeof name === 'symbol';
}

/**
 * Initial route location where the router is. Can be used in navigation guards
 * to differentiate the initial navigation.
 *
 * @example
 * ```js
 * import { START_LOCATION } from 'vue-router'
 *
 * router.beforeEach((to, from) => {
 *   if (from === START_LOCATION) {
 *     // initial navigation
 *   }
 * })
 * ```
 */
const START_LOCATION_NORMALIZED = {
    path: '/',
    name: undefined,
    params: {},
    query: {},
    hash: '',
    fullPath: '/',
    matched: [],
    meta: {},
    redirectedFrom: undefined,
};

const NavigationFailureSymbol = Symbol('');
/**
 * Enumeration with all possible types for navigation failures. Can be passed to
 * {@link isNavigationFailure} to check for specific failures.
 */
var NavigationFailureType;
(function (NavigationFailureType) {
    /**
     * An aborted navigation is a navigation that failed because a navigation
     * guard returned `false` or called `next(false)`
     */
    NavigationFailureType[NavigationFailureType["aborted"] = 4] = "aborted";
    /**
     * A cancelled navigation is a navigation that failed because a more recent
     * navigation finished started (not necessarily finished).
     */
    NavigationFailureType[NavigationFailureType["cancelled"] = 8] = "cancelled";
    /**
     * A duplicated navigation is a navigation that failed because it was
     * initiated while already being at the exact same location.
     */
    NavigationFailureType[NavigationFailureType["duplicated"] = 16] = "duplicated";
})(NavigationFailureType || (NavigationFailureType = {}));
function createRouterError(type, params) {
    // keep full error messages in cjs versions
    {
        return assign$7(new Error(), {
            type,
            [NavigationFailureSymbol]: true,
        }, params);
    }
}
function isNavigationFailure(error, type) {
    return (error instanceof Error &&
        NavigationFailureSymbol in error &&
        (type == null || !!(error.type & type)));
}

// default pattern for a param: non-greedy everything but /
const BASE_PARAM_PATTERN = '[^/]+?';
const BASE_PATH_PARSER_OPTIONS = {
    sensitive: false,
    strict: false,
    start: true,
    end: true,
};
// Special Regex characters that must be escaped in static tokens
const REGEX_CHARS_RE = /[.+*?^${}()[\]/\\]/g;
/**
 * Creates a path parser from an array of Segments (a segment is an array of Tokens)
 *
 * @param segments - array of segments returned by tokenizePath
 * @param extraOptions - optional options for the regexp
 * @returns a PathParser
 */
function tokensToParser(segments, extraOptions) {
    const options = assign$7({}, BASE_PATH_PARSER_OPTIONS, extraOptions);
    // the amount of scores is the same as the length of segments except for the root segment "/"
    const score = [];
    // the regexp as a string
    let pattern = options.start ? '^' : '';
    // extracted keys
    const keys = [];
    for (const segment of segments) {
        // the root segment needs special treatment
        const segmentScores = segment.length ? [] : [90 /* PathScore.Root */];
        // allow trailing slash
        if (options.strict && !segment.length)
            pattern += '/';
        for (let tokenIndex = 0; tokenIndex < segment.length; tokenIndex++) {
            const token = segment[tokenIndex];
            // resets the score if we are inside a sub-segment /:a-other-:b
            let subSegmentScore = 40 /* PathScore.Segment */ +
                (options.sensitive ? 0.25 /* PathScore.BonusCaseSensitive */ : 0);
            if (token.type === 0 /* TokenType.Static */) {
                // prepend the slash if we are starting a new segment
                if (!tokenIndex)
                    pattern += '/';
                pattern += token.value.replace(REGEX_CHARS_RE, '\\$&');
                subSegmentScore += 40 /* PathScore.Static */;
            }
            else if (token.type === 1 /* TokenType.Param */) {
                const { value, repeatable, optional, regexp } = token;
                keys.push({
                    name: value,
                    repeatable,
                    optional,
                });
                const re = regexp ? regexp : BASE_PARAM_PATTERN;
                // the user provided a custom regexp /:id(\\d+)
                if (re !== BASE_PARAM_PATTERN) {
                    subSegmentScore += 10 /* PathScore.BonusCustomRegExp */;
                    // make sure the regexp is valid before using it
                    try {
                        new RegExp(`(${re})`);
                    }
                    catch (err) {
                        throw new Error(`Invalid custom RegExp for param "${value}" (${re}): ` +
                            err.message);
                    }
                }
                // when we repeat we must take care of the repeating leading slash
                let subPattern = repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`;
                // prepend the slash if we are starting a new segment
                if (!tokenIndex)
                    subPattern =
                        // avoid an optional / if there are more segments e.g. /:p?-static
                        // or /:p?-:p2
                        optional && segment.length < 2
                            ? `(?:/${subPattern})`
                            : '/' + subPattern;
                if (optional)
                    subPattern += '?';
                pattern += subPattern;
                subSegmentScore += 20 /* PathScore.Dynamic */;
                if (optional)
                    subSegmentScore += -8 /* PathScore.BonusOptional */;
                if (repeatable)
                    subSegmentScore += -20 /* PathScore.BonusRepeatable */;
                if (re === '.*')
                    subSegmentScore += -50 /* PathScore.BonusWildcard */;
            }
            segmentScores.push(subSegmentScore);
        }
        // an empty array like /home/ -> [[{home}], []]
        // if (!segment.length) pattern += '/'
        score.push(segmentScores);
    }
    // only apply the strict bonus to the last score
    if (options.strict && options.end) {
        const i = score.length - 1;
        score[i][score[i].length - 1] += 0.7000000000000001 /* PathScore.BonusStrict */;
    }
    // TODO: dev only warn double trailing slash
    if (!options.strict)
        pattern += '/?';
    if (options.end)
        pattern += '$';
    // allow paths like /dynamic to only match dynamic or dynamic/... but not dynamic_something_else
    else if (options.strict)
        pattern += '(?:/|$)';
    const re = new RegExp(pattern, options.sensitive ? '' : 'i');
    function parse(path) {
        const match = path.match(re);
        const params = {};
        if (!match)
            return null;
        for (let i = 1; i < match.length; i++) {
            const value = match[i] || '';
            const key = keys[i - 1];
            params[key.name] = value && key.repeatable ? value.split('/') : value;
        }
        return params;
    }
    function stringify(params) {
        let path = '';
        // for optional parameters to allow to be empty
        let avoidDuplicatedSlash = false;
        for (const segment of segments) {
            if (!avoidDuplicatedSlash || !path.endsWith('/'))
                path += '/';
            avoidDuplicatedSlash = false;
            for (const token of segment) {
                if (token.type === 0 /* TokenType.Static */) {
                    path += token.value;
                }
                else if (token.type === 1 /* TokenType.Param */) {
                    const { value, repeatable, optional } = token;
                    const param = value in params ? params[value] : '';
                    if (isArray$j(param) && !repeatable) {
                        throw new Error(`Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`);
                    }
                    const text = isArray$j(param)
                        ? param.join('/')
                        : param;
                    if (!text) {
                        if (optional) {
                            // if we have more than one optional param like /:a?-static we don't need to care about the optional param
                            if (segment.length < 2) {
                                // remove the last slash as we could be at the end
                                if (path.endsWith('/'))
                                    path = path.slice(0, -1);
                                // do not append a slash on the next iteration
                                else
                                    avoidDuplicatedSlash = true;
                            }
                        }
                        else
                            throw new Error(`Missing required param "${value}"`);
                    }
                    path += text;
                }
            }
        }
        // avoid empty path when we have multiple optional params
        return path || '/';
    }
    return {
        re,
        score,
        keys,
        parse,
        stringify,
    };
}
/**
 * Compares an array of numbers as used in PathParser.score and returns a
 * number. This function can be used to `sort` an array
 *
 * @param a - first array of numbers
 * @param b - second array of numbers
 * @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
 * should be sorted first
 */
function compareScoreArray(a, b) {
    let i = 0;
    while (i < a.length && i < b.length) {
        const diff = b[i] - a[i];
        // only keep going if diff === 0
        if (diff)
            return diff;
        i++;
    }
    // if the last subsegment was Static, the shorter segments should be sorted first
    // otherwise sort the longest segment first
    if (a.length < b.length) {
        return a.length === 1 && a[0] === 40 /* PathScore.Static */ + 40 /* PathScore.Segment */
            ? -1
            : 1;
    }
    else if (a.length > b.length) {
        return b.length === 1 && b[0] === 40 /* PathScore.Static */ + 40 /* PathScore.Segment */
            ? 1
            : -1;
    }
    return 0;
}
/**
 * Compare function that can be used with `sort` to sort an array of PathParser
 *
 * @param a - first PathParser
 * @param b - second PathParser
 * @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
 */
function comparePathParserScore(a, b) {
    let i = 0;
    const aScore = a.score;
    const bScore = b.score;
    while (i < aScore.length && i < bScore.length) {
        const comp = compareScoreArray(aScore[i], bScore[i]);
        // do not return if both are equal
        if (comp)
            return comp;
        i++;
    }
    if (Math.abs(bScore.length - aScore.length) === 1) {
        if (isLastScoreNegative(aScore))
            return 1;
        if (isLastScoreNegative(bScore))
            return -1;
    }
    // if a and b share the same score entries but b has more, sort b first
    return bScore.length - aScore.length;
    // this is the ternary version
    // return aScore.length < bScore.length
    //   ? 1
    //   : aScore.length > bScore.length
    //   ? -1
    //   : 0
}
/**
 * This allows detecting splats at the end of a path: /home/:id(.*)*
 *
 * @param score - score to check
 * @returns true if the last entry is negative
 */
function isLastScoreNegative(score) {
    const last = score[score.length - 1];
    return score.length > 0 && last[last.length - 1] < 0;
}

const ROOT_TOKEN = {
    type: 0 /* TokenType.Static */,
    value: '',
};
const VALID_PARAM_RE = /[a-zA-Z0-9_]/;
// After some profiling, the cache seems to be unnecessary because tokenizePath
// (the slowest part of adding a route) is very fast
// const tokenCache = new Map<string, Token[][]>()
function tokenizePath(path) {
    if (!path)
        return [[]];
    if (path === '/')
        return [[ROOT_TOKEN]];
    if (!path.startsWith('/')) {
        throw new Error(`Invalid path "${path}"`);
    }
    // if (tokenCache.has(path)) return tokenCache.get(path)!
    function crash(message) {
        throw new Error(`ERR (${state})/"${buffer}": ${message}`);
    }
    let state = 0 /* TokenizerState.Static */;
    let previousState = state;
    const tokens = [];
    // the segment will always be valid because we get into the initial state
    // with the leading /
    let segment;
    function finalizeSegment() {
        if (segment)
            tokens.push(segment);
        segment = [];
    }
    // index on the path
    let i = 0;
    // char at index
    let char;
    // buffer of the value read
    let buffer = '';
    // custom regexp for a param
    let customRe = '';
    function consumeBuffer() {
        if (!buffer)
            return;
        if (state === 0 /* TokenizerState.Static */) {
            segment.push({
                type: 0 /* TokenType.Static */,
                value: buffer,
            });
        }
        else if (state === 1 /* TokenizerState.Param */ ||
            state === 2 /* TokenizerState.ParamRegExp */ ||
            state === 3 /* TokenizerState.ParamRegExpEnd */) {
            if (segment.length > 1 && (char === '*' || char === '+'))
                crash(`A repeatable param (${buffer}) must be alone in its segment. eg: '/:ids+.`);
            segment.push({
                type: 1 /* TokenType.Param */,
                value: buffer,
                regexp: customRe,
                repeatable: char === '*' || char === '+',
                optional: char === '*' || char === '?',
            });
        }
        else {
            crash('Invalid state to consume buffer');
        }
        buffer = '';
    }
    function addCharToBuffer() {
        buffer += char;
    }
    while (i < path.length) {
        char = path[i++];
        if (char === '\\' && state !== 2 /* TokenizerState.ParamRegExp */) {
            previousState = state;
            state = 4 /* TokenizerState.EscapeNext */;
            continue;
        }
        switch (state) {
            case 0 /* TokenizerState.Static */:
                if (char === '/') {
                    if (buffer) {
                        consumeBuffer();
                    }
                    finalizeSegment();
                }
                else if (char === ':') {
                    consumeBuffer();
                    state = 1 /* TokenizerState.Param */;
                }
                else {
                    addCharToBuffer();
                }
                break;
            case 4 /* TokenizerState.EscapeNext */:
                addCharToBuffer();
                state = previousState;
                break;
            case 1 /* TokenizerState.Param */:
                if (char === '(') {
                    state = 2 /* TokenizerState.ParamRegExp */;
                }
                else if (VALID_PARAM_RE.test(char)) {
                    addCharToBuffer();
                }
                else {
                    consumeBuffer();
                    state = 0 /* TokenizerState.Static */;
                    // go back one character if we were not modifying
                    if (char !== '*' && char !== '?' && char !== '+')
                        i--;
                }
                break;
            case 2 /* TokenizerState.ParamRegExp */:
                // TODO: is it worth handling nested regexp? like :p(?:prefix_([^/]+)_suffix)
                // it already works by escaping the closing )
                // https://paths.esm.dev/?p=AAMeJbiAwQEcDKbAoAAkP60PG2R6QAvgNaA6AFACM2ABuQBB#
                // is this really something people need since you can also write
                // /prefix_:p()_suffix
                if (char === ')') {
                    // handle the escaped )
                    if (customRe[customRe.length - 1] == '\\')
                        customRe = customRe.slice(0, -1) + char;
                    else
                        state = 3 /* TokenizerState.ParamRegExpEnd */;
                }
                else {
                    customRe += char;
                }
                break;
            case 3 /* TokenizerState.ParamRegExpEnd */:
                // same as finalizing a param
                consumeBuffer();
                state = 0 /* TokenizerState.Static */;
                // go back one character if we were not modifying
                if (char !== '*' && char !== '?' && char !== '+')
                    i--;
                customRe = '';
                break;
            default:
                crash('Unknown state');
                break;
        }
    }
    if (state === 2 /* TokenizerState.ParamRegExp */)
        crash(`Unfinished custom RegExp for param "${buffer}"`);
    consumeBuffer();
    finalizeSegment();
    // tokenCache.set(path, tokens)
    return tokens;
}

function createRouteRecordMatcher(record, parent, options) {
    const parser = tokensToParser(tokenizePath(record.path), options);
    const matcher = assign$7(parser, {
        record,
        parent,
        // these needs to be populated by the parent
        children: [],
        alias: [],
    });
    if (parent) {
        // both are aliases or both are not aliases
        // we don't want to mix them because the order is used when
        // passing originalRecord in Matcher.addRoute
        if (!matcher.record.aliasOf === !parent.record.aliasOf)
            parent.children.push(matcher);
    }
    return matcher;
}

/**
 * Creates a Router Matcher.
 *
 * @internal
 * @param routes - array of initial routes
 * @param globalOptions - global route options
 */
function createRouterMatcher(routes, globalOptions) {
    // normalized ordered array of matchers
    const matchers = [];
    const matcherMap = new Map();
    globalOptions = mergeOptions$1({ strict: false, end: true, sensitive: false }, globalOptions);
    function getRecordMatcher(name) {
        return matcherMap.get(name);
    }
    function addRoute(record, parent, originalRecord) {
        // used later on to remove by name
        const isRootAdd = !originalRecord;
        const mainNormalizedRecord = normalizeRouteRecord(record);
        // we might be the child of an alias
        mainNormalizedRecord.aliasOf = originalRecord && originalRecord.record;
        const options = mergeOptions$1(globalOptions, record);
        // generate an array of records to correctly handle aliases
        const normalizedRecords = [
            mainNormalizedRecord,
        ];
        if ('alias' in record) {
            const aliases = typeof record.alias === 'string' ? [record.alias] : record.alias;
            for (const alias of aliases) {
                normalizedRecords.push(assign$7({}, mainNormalizedRecord, {
                    // this allows us to hold a copy of the `components` option
                    // so that async components cache is hold on the original record
                    components: originalRecord
                        ? originalRecord.record.components
                        : mainNormalizedRecord.components,
                    path: alias,
                    // we might be the child of an alias
                    aliasOf: originalRecord
                        ? originalRecord.record
                        : mainNormalizedRecord,
                    // the aliases are always of the same kind as the original since they
                    // are defined on the same record
                }));
            }
        }
        let matcher;
        let originalMatcher;
        for (const normalizedRecord of normalizedRecords) {
            const { path } = normalizedRecord;
            // Build up the path for nested routes if the child isn't an absolute
            // route. Only add the / delimiter if the child path isn't empty and if the
            // parent path doesn't have a trailing slash
            if (parent && path[0] !== '/') {
                const parentPath = parent.record.path;
                const connectingSlash = parentPath[parentPath.length - 1] === '/' ? '' : '/';
                normalizedRecord.path =
                    parent.record.path + (path && connectingSlash + path);
            }
            // create the object beforehand, so it can be passed to children
            matcher = createRouteRecordMatcher(normalizedRecord, parent, options);
            // if we are an alias we must tell the original record that we exist,
            // so we can be removed
            if (originalRecord) {
                originalRecord.alias.push(matcher);
            }
            else {
                // otherwise, the first record is the original and others are aliases
                originalMatcher = originalMatcher || matcher;
                if (originalMatcher !== matcher)
                    originalMatcher.alias.push(matcher);
                // remove the route if named and only for the top record (avoid in nested calls)
                // this works because the original record is the first one
                if (isRootAdd && record.name && !isAliasRecord(matcher))
                    removeRoute(record.name);
            }
            if (mainNormalizedRecord.children) {
                const children = mainNormalizedRecord.children;
                for (let i = 0; i < children.length; i++) {
                    addRoute(children[i], matcher, originalRecord && originalRecord.children[i]);
                }
            }
            // if there was no original record, then the first one was not an alias and all
            // other aliases (if any) need to reference this record when adding children
            originalRecord = originalRecord || matcher;
            // TODO: add normalized records for more flexibility
            // if (parent && isAliasRecord(originalRecord)) {
            //   parent.children.push(originalRecord)
            // }
            // Avoid adding a record that doesn't display anything. This allows passing through records without a component to
            // not be reached and pass through the catch all route
            if ((matcher.record.components &&
                Object.keys(matcher.record.components).length) ||
                matcher.record.name ||
                matcher.record.redirect) {
                insertMatcher(matcher);
            }
        }
        return originalMatcher
            ? () => {
                // since other matchers are aliases, they should be removed by the original matcher
                removeRoute(originalMatcher);
            }
            : noop$4;
    }
    function removeRoute(matcherRef) {
        if (isRouteName(matcherRef)) {
            const matcher = matcherMap.get(matcherRef);
            if (matcher) {
                matcherMap.delete(matcherRef);
                matchers.splice(matchers.indexOf(matcher), 1);
                matcher.children.forEach(removeRoute);
                matcher.alias.forEach(removeRoute);
            }
        }
        else {
            const index = matchers.indexOf(matcherRef);
            if (index > -1) {
                matchers.splice(index, 1);
                if (matcherRef.record.name)
                    matcherMap.delete(matcherRef.record.name);
                matcherRef.children.forEach(removeRoute);
                matcherRef.alias.forEach(removeRoute);
            }
        }
    }
    function getRoutes() {
        return matchers;
    }
    function insertMatcher(matcher) {
        let i = 0;
        while (i < matchers.length &&
            comparePathParserScore(matcher, matchers[i]) >= 0 &&
            // Adding children with empty path should still appear before the parent
            // https://github.com/vuejs/router/issues/1124
            (matcher.record.path !== matchers[i].record.path ||
                !isRecordChildOf(matcher, matchers[i])))
            i++;
        matchers.splice(i, 0, matcher);
        // only add the original record to the name map
        if (matcher.record.name && !isAliasRecord(matcher))
            matcherMap.set(matcher.record.name, matcher);
    }
    function resolve(location, currentLocation) {
        let matcher;
        let params = {};
        let path;
        let name;
        if ('name' in location && location.name) {
            matcher = matcherMap.get(location.name);
            if (!matcher)
                throw createRouterError(1 /* ErrorTypes.MATCHER_NOT_FOUND */, {
                    location,
                });
            name = matcher.record.name;
            params = assign$7(
            // paramsFromLocation is a new object
            paramsFromLocation(currentLocation.params, 
            // only keep params that exist in the resolved location
            // TODO: only keep optional params coming from a parent record
            matcher.keys.filter(k => !k.optional).map(k => k.name)), 
            // discard any existing params in the current location that do not exist here
            // #1497 this ensures better active/exact matching
            location.params &&
                paramsFromLocation(location.params, matcher.keys.map(k => k.name)));
            // throws if cannot be stringified
            path = matcher.stringify(params);
        }
        else if ('path' in location) {
            // no need to resolve the path with the matcher as it was provided
            // this also allows the user to control the encoding
            path = location.path;
            matcher = matchers.find(m => m.re.test(path));
            // matcher should have a value after the loop
            if (matcher) {
                // we know the matcher works because we tested the regexp
                params = matcher.parse(path);
                name = matcher.record.name;
            }
            // location is a relative path
        }
        else {
            // match by name or path of current route
            matcher = currentLocation.name
                ? matcherMap.get(currentLocation.name)
                : matchers.find(m => m.re.test(currentLocation.path));
            if (!matcher)
                throw createRouterError(1 /* ErrorTypes.MATCHER_NOT_FOUND */, {
                    location,
                    currentLocation,
                });
            name = matcher.record.name;
            // since we are navigating to the same location, we don't need to pick the
            // params like when `name` is provided
            params = assign$7({}, currentLocation.params, location.params);
            path = matcher.stringify(params);
        }
        const matched = [];
        let parentMatcher = matcher;
        while (parentMatcher) {
            // reversed order so parents are at the beginning
            matched.unshift(parentMatcher.record);
            parentMatcher = parentMatcher.parent;
        }
        return {
            name,
            path,
            params,
            matched,
            meta: mergeMetaFields(matched),
        };
    }
    // add initial routes
    routes.forEach(route => addRoute(route));
    return { addRoute, resolve, removeRoute, getRoutes, getRecordMatcher };
}
function paramsFromLocation(params, keys) {
    const newParams = {};
    for (const key of keys) {
        if (key in params)
            newParams[key] = params[key];
    }
    return newParams;
}
/**
 * Normalizes a RouteRecordRaw. Creates a copy
 *
 * @param record
 * @returns the normalized version
 */
function normalizeRouteRecord(record) {
    return {
        path: record.path,
        redirect: record.redirect,
        name: record.name,
        meta: record.meta || {},
        aliasOf: undefined,
        beforeEnter: record.beforeEnter,
        props: normalizeRecordProps(record),
        children: record.children || [],
        instances: {},
        leaveGuards: new Set(),
        updateGuards: new Set(),
        enterCallbacks: {},
        components: 'components' in record
            ? record.components || null
            : record.component && { default: record.component },
    };
}
/**
 * Normalize the optional `props` in a record to always be an object similar to
 * components. Also accept a boolean for components.
 * @param record
 */
function normalizeRecordProps(record) {
    const propsObject = {};
    // props does not exist on redirect records, but we can set false directly
    const props = record.props || false;
    if ('component' in record) {
        propsObject.default = props;
    }
    else {
        // NOTE: we could also allow a function to be applied to every component.
        // Would need user feedback for use cases
        for (const name in record.components)
            propsObject[name] = typeof props === 'object' ? props[name] : props;
    }
    return propsObject;
}
/**
 * Checks if a record or any of its parent is an alias
 * @param record
 */
function isAliasRecord(record) {
    while (record) {
        if (record.record.aliasOf)
            return true;
        record = record.parent;
    }
    return false;
}
/**
 * Merge meta fields of an array of records
 *
 * @param matched - array of matched records
 */
function mergeMetaFields(matched) {
    return matched.reduce((meta, record) => assign$7(meta, record.meta), {});
}
function mergeOptions$1(defaults, partialOptions) {
    const options = {};
    for (const key in defaults) {
        options[key] = key in partialOptions ? partialOptions[key] : defaults[key];
    }
    return options;
}
function isRecordChildOf(record, parent) {
    return parent.children.some(child => child === record || isRecordChildOf(record, child));
}

/**
 * Encoding Rules ␣ = Space Path: ␣ " < > # ? { } Query: ␣ " < > # & = Hash: ␣ "
 * < > `
 *
 * On top of that, the RFC3986 (https://tools.ietf.org/html/rfc3986#section-2.2)
 * defines some extra characters to be encoded. Most browsers do not encode them
 * in encodeURI https://github.com/whatwg/url/issues/369, so it may be safer to
 * also encode `!'()*`. Leaving un-encoded only ASCII alphanumeric(`a-zA-Z0-9`)
 * plus `-._~`. This extra safety should be applied to query by patching the
 * string returned by encodeURIComponent encodeURI also encodes `[\]^`. `\`
 * should be encoded to avoid ambiguity. Browsers (IE, FF, C) transform a `\`
 * into a `/` if directly typed in. The _backtick_ (`````) should also be
 * encoded everywhere because some browsers like FF encode it when directly
 * written while others don't. Safari and IE don't encode ``"<>{}``` in hash.
 */
// const EXTRA_RESERVED_RE = /[!'()*]/g
// const encodeReservedReplacer = (c: string) => '%' + c.charCodeAt(0).toString(16)
const HASH_RE = /#/g; // %23
const AMPERSAND_RE = /&/g; // %26
const SLASH_RE = /\//g; // %2F
const EQUAL_RE = /=/g; // %3D
const IM_RE = /\?/g; // %3F
const PLUS_RE = /\+/g; // %2B
/**
 * NOTE: It's not clear to me if we should encode the + symbol in queries, it
 * seems to be less flexible than not doing so and I can't find out the legacy
 * systems requiring this for regular requests like text/html. In the standard,
 * the encoding of the plus character is only mentioned for
 * application/x-www-form-urlencoded
 * (https://url.spec.whatwg.org/#urlencoded-parsing) and most browsers seems lo
 * leave the plus character as is in queries. To be more flexible, we allow the
 * plus character on the query, but it can also be manually encoded by the user.
 *
 * Resources:
 * - https://url.spec.whatwg.org/#urlencoded-parsing
 * - https://stackoverflow.com/questions/1634271/url-encoding-the-space-character-or-20
 */
const ENC_BRACKET_OPEN_RE = /%5B/g; // [
const ENC_BRACKET_CLOSE_RE = /%5D/g; // ]
const ENC_CARET_RE = /%5E/g; // ^
const ENC_BACKTICK_RE = /%60/g; // `
const ENC_CURLY_OPEN_RE = /%7B/g; // {
const ENC_PIPE_RE = /%7C/g; // |
const ENC_CURLY_CLOSE_RE = /%7D/g; // }
const ENC_SPACE_RE = /%20/g; // }
/**
 * Encode characters that need to be encoded on the path, search and hash
 * sections of the URL.
 *
 * @internal
 * @param text - string to encode
 * @returns encoded string
 */
function commonEncode(text) {
    return encodeURI('' + text)
        .replace(ENC_PIPE_RE, '|')
        .replace(ENC_BRACKET_OPEN_RE, '[')
        .replace(ENC_BRACKET_CLOSE_RE, ']');
}
/**
 * Encode characters that need to be encoded on the hash section of the URL.
 *
 * @param text - string to encode
 * @returns encoded string
 */
function encodeHash(text) {
    return commonEncode(text)
        .replace(ENC_CURLY_OPEN_RE, '{')
        .replace(ENC_CURLY_CLOSE_RE, '}')
        .replace(ENC_CARET_RE, '^');
}
/**
 * Encode characters that need to be encoded query values on the query
 * section of the URL.
 *
 * @param text - string to encode
 * @returns encoded string
 */
function encodeQueryValue(text) {
    return (commonEncode(text)
        // Encode the space as +, encode the + to differentiate it from the space
        .replace(PLUS_RE, '%2B')
        .replace(ENC_SPACE_RE, '+')
        .replace(HASH_RE, '%23')
        .replace(AMPERSAND_RE, '%26')
        .replace(ENC_BACKTICK_RE, '`')
        .replace(ENC_CURLY_OPEN_RE, '{')
        .replace(ENC_CURLY_CLOSE_RE, '}')
        .replace(ENC_CARET_RE, '^'));
}
/**
 * Like `encodeQueryValue` but also encodes the `=` character.
 *
 * @param text - string to encode
 */
function encodeQueryKey(text) {
    return encodeQueryValue(text).replace(EQUAL_RE, '%3D');
}
/**
 * Encode characters that need to be encoded on the path section of the URL.
 *
 * @param text - string to encode
 * @returns encoded string
 */
function encodePath(text) {
    return commonEncode(text).replace(HASH_RE, '%23').replace(IM_RE, '%3F');
}
/**
 * Encode characters that need to be encoded on the path section of the URL as a
 * param. This function encodes everything {@link encodePath} does plus the
 * slash (`/`) character. If `text` is `null` or `undefined`, returns an empty
 * string instead.
 *
 * @param text - string to encode
 * @returns encoded string
 */
function encodeParam(text) {
    return text == null ? '' : encodePath(text).replace(SLASH_RE, '%2F');
}
/**
 * Decode text using `decodeURIComponent`. Returns the original text if it
 * fails.
 *
 * @param text - string to decode
 * @returns decoded string
 */
function decode(text) {
    try {
        return decodeURIComponent('' + text);
    }
    catch (err) {
    }
    return '' + text;
}

/**
 * Transforms a queryString into a {@link LocationQuery} object. Accept both, a
 * version with the leading `?` and without Should work as URLSearchParams

 * @internal
 *
 * @param search - search string to parse
 * @returns a query object
 */
function parseQuery$1(search) {
    const query = {};
    // avoid creating an object with an empty key and empty value
    // because of split('&')
    if (search === '' || search === '?')
        return query;
    const hasLeadingIM = search[0] === '?';
    const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&');
    for (let i = 0; i < searchParams.length; ++i) {
        // pre decode the + into space
        const searchParam = searchParams[i].replace(PLUS_RE, ' ');
        // allow the = character
        const eqPos = searchParam.indexOf('=');
        const key = decode(eqPos < 0 ? searchParam : searchParam.slice(0, eqPos));
        const value = eqPos < 0 ? null : decode(searchParam.slice(eqPos + 1));
        if (key in query) {
            // an extra variable for ts types
            let currentValue = query[key];
            if (!isArray$j(currentValue)) {
                currentValue = query[key] = [currentValue];
            }
            currentValue.push(value);
        }
        else {
            query[key] = value;
        }
    }
    return query;
}
/**
 * Stringifies a {@link LocationQueryRaw} object. Like `URLSearchParams`, it
 * doesn't prepend a `?`
 *
 * @internal
 *
 * @param query - query object to stringify
 * @returns string version of the query without the leading `?`
 */
function stringifyQuery(query) {
    let search = '';
    for (let key in query) {
        const value = query[key];
        key = encodeQueryKey(key);
        if (value == null) {
            // only null adds the value
            if (value !== undefined) {
                search += (search.length ? '&' : '') + key;
            }
            continue;
        }
        // keep null values
        const values = isArray$j(value)
            ? value.map(v => v && encodeQueryValue(v))
            : [value && encodeQueryValue(value)];
        values.forEach(value => {
            // skip undefined values in arrays as if they were not present
            // smaller code than using filter
            if (value !== undefined) {
                // only append & with non-empty search
                search += (search.length ? '&' : '') + key;
                if (value != null)
                    search += '=' + value;
            }
        });
    }
    return search;
}
/**
 * Transforms a {@link LocationQueryRaw} into a {@link LocationQuery} by casting
 * numbers into strings, removing keys with an undefined value and replacing
 * undefined with null in arrays
 *
 * @param query - query object to normalize
 * @returns a normalized query object
 */
function normalizeQuery(query) {
    const normalizedQuery = {};
    for (const key in query) {
        const value = query[key];
        if (value !== undefined) {
            normalizedQuery[key] = isArray$j(value)
                ? value.map(v => (v == null ? null : '' + v))
                : value == null
                    ? value
                    : '' + value;
        }
    }
    return normalizedQuery;
}

/**
 * RouteRecord being rendered by the closest ancestor Router View. Used for
 * `onBeforeRouteUpdate` and `onBeforeRouteLeave`. rvlm stands for Router View
 * Location Matched
 *
 * @internal
 */
const matchedRouteKey = Symbol('');
/**
 * Allows overriding the router view depth to control which component in
 * `matched` is rendered. rvd stands for Router View Depth
 *
 * @internal
 */
const viewDepthKey = Symbol('');
/**
 * Allows overriding the router instance returned by `useRouter` in tests. r
 * stands for router
 *
 * @internal
 */
const routerKey = Symbol('');
/**
 * Allows overriding the current route returned by `useRoute` in tests. rl
 * stands for route location
 *
 * @internal
 */
const routeLocationKey = Symbol('');
/**
 * Allows overriding the current route used by router-view. Internally this is
 * used when the `route` prop is passed.
 *
 * @internal
 */
const routerViewLocationKey = Symbol('');

/**
 * Create a list of callbacks that can be reset. Used to create before and after navigation guards list
 */
function useCallbacks() {
    let handlers = [];
    function add(handler) {
        handlers.push(handler);
        return () => {
            const i = handlers.indexOf(handler);
            if (i > -1)
                handlers.splice(i, 1);
        };
    }
    function reset() {
        handlers = [];
    }
    return {
        add,
        list: () => handlers.slice(),
        reset,
    };
}
function guardToPromiseFn(guard, to, from, record, name) {
    // keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
    const enterCallbackArray = record &&
        // name is defined if record is because of the function overload
        (record.enterCallbacks[name] = record.enterCallbacks[name] || []);
    return () => new Promise((resolve, reject) => {
        const next = (valid) => {
            if (valid === false) {
                reject(createRouterError(4 /* ErrorTypes.NAVIGATION_ABORTED */, {
                    from,
                    to,
                }));
            }
            else if (valid instanceof Error) {
                reject(valid);
            }
            else if (isRouteLocation(valid)) {
                reject(createRouterError(2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */, {
                    from: to,
                    to: valid,
                }));
            }
            else {
                if (enterCallbackArray &&
                    // since enterCallbackArray is truthy, both record and name also are
                    record.enterCallbacks[name] === enterCallbackArray &&
                    typeof valid === 'function') {
                    enterCallbackArray.push(valid);
                }
                resolve();
            }
        };
        // wrapping with Promise.resolve allows it to work with both async and sync guards
        const guardReturn = guard.call(record && record.instances[name], to, from, next);
        let guardCall = Promise.resolve(guardReturn);
        if (guard.length < 3)
            guardCall = guardCall.then(next);
        guardCall.catch(err => reject(err));
    });
}
function extractComponentsGuards(matched, guardType, to, from) {
    const guards = [];
    for (const record of matched) {
        for (const name in record.components) {
            let rawComponent = record.components[name];
            // skip update and leave guards if the route component is not mounted
            if (guardType !== 'beforeRouteEnter' && !record.instances[name])
                continue;
            if (isRouteComponent(rawComponent)) {
                // __vccOpts is added by vue-class-component and contain the regular options
                const options = rawComponent.__vccOpts || rawComponent;
                const guard = options[guardType];
                guard && guards.push(guardToPromiseFn(guard, to, from, record, name));
            }
            else {
                // start requesting the chunk already
                let componentPromise = rawComponent();
                guards.push(() => componentPromise.then(resolved => {
                    if (!resolved)
                        return Promise.reject(new Error(`Couldn't resolve component "${name}" at "${record.path}"`));
                    const resolvedComponent = isESModule(resolved)
                        ? resolved.default
                        : resolved;
                    // replace the function with the resolved component
                    // cannot be null or undefined because we went into the for loop
                    record.components[name] = resolvedComponent;
                    // __vccOpts is added by vue-class-component and contain the regular options
                    const options = resolvedComponent.__vccOpts || resolvedComponent;
                    const guard = options[guardType];
                    return guard && guardToPromiseFn(guard, to, from, record, name)();
                }));
            }
        }
    }
    return guards;
}
/**
 * Allows differentiating lazy components from functional components and vue-class-component
 * @internal
 *
 * @param component
 */
function isRouteComponent(component) {
    return (typeof component === 'object' ||
        'displayName' in component ||
        'props' in component ||
        '__vccOpts' in component);
}

// TODO: we could allow currentRoute as a prop to expose `isActive` and
// `isExactActive` behavior should go through an RFC
function useLink(props) {
    const router = inject(routerKey);
    const currentRoute = inject(routeLocationKey);
    const route = computed(() => router.resolve(unref(props.to)));
    const activeRecordIndex = computed(() => {
        const { matched } = route.value;
        const { length } = matched;
        const routeMatched = matched[length - 1];
        const currentMatched = currentRoute.matched;
        if (!routeMatched || !currentMatched.length)
            return -1;
        const index = currentMatched.findIndex(isSameRouteRecord.bind(null, routeMatched));
        if (index > -1)
            return index;
        // possible parent record
        const parentRecordPath = getOriginalPath(matched[length - 2]);
        return (
        // we are dealing with nested routes
        length > 1 &&
            // if the parent and matched route have the same path, this link is
            // referring to the empty child. Or we currently are on a different
            // child of the same parent
            getOriginalPath(routeMatched) === parentRecordPath &&
            // avoid comparing the child with its parent
            currentMatched[currentMatched.length - 1].path !== parentRecordPath
            ? currentMatched.findIndex(isSameRouteRecord.bind(null, matched[length - 2]))
            : index);
    });
    const isActive = computed(() => activeRecordIndex.value > -1 &&
        includesParams(currentRoute.params, route.value.params));
    const isExactActive = computed(() => activeRecordIndex.value > -1 &&
        activeRecordIndex.value === currentRoute.matched.length - 1 &&
        isSameRouteLocationParams(currentRoute.params, route.value.params));
    function navigate(e = {}) {
        if (guardEvent(e)) {
            return router[unref(props.replace) ? 'replace' : 'push'](unref(props.to)
            // avoid uncaught errors are they are logged anyway
            ).catch(noop$4);
        }
        return Promise.resolve();
    }
    /**
     * NOTE: update {@link _RouterLinkI}'s `$slots` type when updating this
     */
    return {
        route,
        href: computed(() => route.value.href),
        isActive,
        isExactActive,
        navigate,
    };
}
const RouterLinkImpl = /*#__PURE__*/ defineComponent({
    name: 'RouterLink',
    compatConfig: { MODE: 3 },
    props: {
        to: {
            type: [String, Object],
            required: true,
        },
        replace: Boolean,
        activeClass: String,
        // inactiveClass: String,
        exactActiveClass: String,
        custom: Boolean,
        ariaCurrentValue: {
            type: String,
            default: 'page',
        },
    },
    useLink,
    setup(props, { slots }) {
        const link = reactive(useLink(props));
        const { options } = inject(routerKey);
        const elClass = computed(() => ({
            [getLinkClass(props.activeClass, options.linkActiveClass, 'router-link-active')]: link.isActive,
            // [getLinkClass(
            //   props.inactiveClass,
            //   options.linkInactiveClass,
            //   'router-link-inactive'
            // )]: !link.isExactActive,
            [getLinkClass(props.exactActiveClass, options.linkExactActiveClass, 'router-link-exact-active')]: link.isExactActive,
        }));
        return () => {
            const children = slots.default && slots.default(link);
            return props.custom
                ? children
                : h('a', {
                    'aria-current': link.isExactActive
                        ? props.ariaCurrentValue
                        : null,
                    href: link.href,
                    // this would override user added attrs but Vue will still add
                    // the listener, so we end up triggering both
                    onClick: link.navigate,
                    class: elClass.value,
                }, children);
        };
    },
});
// export the public type for h/tsx inference
// also to avoid inline import() in generated d.ts files
/**
 * Component to render a link that triggers a navigation on click.
 */
const RouterLink = RouterLinkImpl;
function guardEvent(e) {
    // don't redirect with control keys
    if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)
        return;
    // don't redirect when preventDefault called
    if (e.defaultPrevented)
        return;
    // don't redirect on right click
    if (e.button !== undefined && e.button !== 0)
        return;
    // don't redirect if `target="_blank"`
    // @ts-expect-error getAttribute does exist
    if (e.currentTarget && e.currentTarget.getAttribute) {
        // @ts-expect-error getAttribute exists
        const target = e.currentTarget.getAttribute('target');
        if (/\b_blank\b/i.test(target))
            return;
    }
    // this may be a Weex event which doesn't have this method
    if (e.preventDefault)
        e.preventDefault();
    return true;
}
function includesParams(outer, inner) {
    for (const key in inner) {
        const innerValue = inner[key];
        const outerValue = outer[key];
        if (typeof innerValue === 'string') {
            if (innerValue !== outerValue)
                return false;
        }
        else {
            if (!isArray$j(outerValue) ||
                outerValue.length !== innerValue.length ||
                innerValue.some((value, i) => value !== outerValue[i]))
                return false;
        }
    }
    return true;
}
/**
 * Get the original path value of a record by following its aliasOf
 * @param record
 */
function getOriginalPath(record) {
    return record ? (record.aliasOf ? record.aliasOf.path : record.path) : '';
}
/**
 * Utility class to get the active class based on defaults.
 * @param propClass
 * @param globalClass
 * @param defaultClass
 */
const getLinkClass = (propClass, globalClass, defaultClass) => propClass != null
    ? propClass
    : globalClass != null
        ? globalClass
        : defaultClass;

const RouterViewImpl = /*#__PURE__*/ defineComponent({
    name: 'RouterView',
    // #674 we manually inherit them
    inheritAttrs: false,
    props: {
        name: {
            type: String,
            default: 'default',
        },
        route: Object,
    },
    // Better compat for @vue/compat users
    // https://github.com/vuejs/router/issues/1315
    compatConfig: { MODE: 3 },
    setup(props, { attrs, slots }) {
        const injectedRoute = inject(routerViewLocationKey);
        const routeToDisplay = computed(() => props.route || injectedRoute.value);
        const injectedDepth = inject(viewDepthKey, 0);
        // The depth changes based on empty components option, which allows passthrough routes e.g. routes with children
        // that are used to reuse the `path` property
        const depth = computed(() => {
            let initialDepth = unref(injectedDepth);
            const { matched } = routeToDisplay.value;
            let matchedRoute;
            while ((matchedRoute = matched[initialDepth]) &&
                !matchedRoute.components) {
                initialDepth++;
            }
            return initialDepth;
        });
        const matchedRouteRef = computed(() => routeToDisplay.value.matched[depth.value]);
        provide(viewDepthKey, computed(() => depth.value + 1));
        provide(matchedRouteKey, matchedRouteRef);
        provide(routerViewLocationKey, routeToDisplay);
        const viewRef = ref();
        // watch at the same time the component instance, the route record we are
        // rendering, and the name
        watch(() => [viewRef.value, matchedRouteRef.value, props.name], ([instance, to, name], [oldInstance, from, oldName]) => {
            // copy reused instances
            if (to) {
                // this will update the instance for new instances as well as reused
                // instances when navigating to a new route
                to.instances[name] = instance;
                // the component instance is reused for a different route or name, so
                // we copy any saved update or leave guards. With async setup, the
                // mounting component will mount before the matchedRoute changes,
                // making instance === oldInstance, so we check if guards have been
                // added before. This works because we remove guards when
                // unmounting/deactivating components
                if (from && from !== to && instance && instance === oldInstance) {
                    if (!to.leaveGuards.size) {
                        to.leaveGuards = from.leaveGuards;
                    }
                    if (!to.updateGuards.size) {
                        to.updateGuards = from.updateGuards;
                    }
                }
            }
            // trigger beforeRouteEnter next callbacks
            if (instance &&
                to &&
                // if there is no instance but to and from are the same this might be
                // the first visit
                (!from || !isSameRouteRecord(to, from) || !oldInstance)) {
                (to.enterCallbacks[name] || []).forEach(callback => callback(instance));
            }
        }, { flush: 'post' });
        return () => {
            const route = routeToDisplay.value;
            // we need the value at the time we render because when we unmount, we
            // navigated to a different location so the value is different
            const currentName = props.name;
            const matchedRoute = matchedRouteRef.value;
            const ViewComponent = matchedRoute && matchedRoute.components[currentName];
            if (!ViewComponent) {
                return normalizeSlot(slots.default, { Component: ViewComponent, route });
            }
            // props from route configuration
            const routePropsOption = matchedRoute.props[currentName];
            const routeProps = routePropsOption
                ? routePropsOption === true
                    ? route.params
                    : typeof routePropsOption === 'function'
                        ? routePropsOption(route)
                        : routePropsOption
                : null;
            const onVnodeUnmounted = vnode => {
                // remove the instance reference to prevent leak
                if (vnode.component.isUnmounted) {
                    matchedRoute.instances[currentName] = null;
                }
            };
            const component = h(ViewComponent, assign$7({}, routeProps, attrs, {
                onVnodeUnmounted,
                ref: viewRef,
            }));
            return (
            // pass the vnode to the slot as a prop.
            // h and <component :is="..."> both accept vnodes
            normalizeSlot(slots.default, { Component: component, route }) ||
                component);
        };
    },
});
function normalizeSlot(slot, data) {
    if (!slot)
        return null;
    const slotContent = slot(data);
    return slotContent.length === 1 ? slotContent[0] : slotContent;
}
// export the public type for h/tsx inference
// also to avoid inline import() in generated d.ts files
/**
 * Component to display the current route the user is at.
 */
const RouterView = RouterViewImpl;

/**
 * Creates a Router instance that can be used by a Vue app.
 *
 * @param options - {@link RouterOptions}
 */
function createRouter(options) {
    const matcher = createRouterMatcher(options.routes, options);
    const parseQuery$1$1 = options.parseQuery || parseQuery$1;
    const stringifyQuery$1 = options.stringifyQuery || stringifyQuery;
    const routerHistory = options.history;
    const beforeGuards = useCallbacks();
    const beforeResolveGuards = useCallbacks();
    const afterGuards = useCallbacks();
    const currentRoute = shallowRef(START_LOCATION_NORMALIZED);
    let pendingLocation = START_LOCATION_NORMALIZED;
    // leave the scrollRestoration if no scrollBehavior is provided
    if (isBrowser && options.scrollBehavior && 'scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
    }
    const normalizeParams = applyToParams.bind(null, paramValue => '' + paramValue);
    const encodeParams = applyToParams.bind(null, encodeParam);
    const decodeParams = 
    // @ts-expect-error: intentionally avoid the type check
    applyToParams.bind(null, decode);
    function addRoute(parentOrRoute, route) {
        let parent;
        let record;
        if (isRouteName(parentOrRoute)) {
            parent = matcher.getRecordMatcher(parentOrRoute);
            record = route;
        }
        else {
            record = parentOrRoute;
        }
        return matcher.addRoute(record, parent);
    }
    function removeRoute(name) {
        const recordMatcher = matcher.getRecordMatcher(name);
        if (recordMatcher) {
            matcher.removeRoute(recordMatcher);
        }
    }
    function getRoutes() {
        return matcher.getRoutes().map(routeMatcher => routeMatcher.record);
    }
    function hasRoute(name) {
        return !!matcher.getRecordMatcher(name);
    }
    function resolve(rawLocation, currentLocation) {
        // const objectLocation = routerLocationAsObject(rawLocation)
        // we create a copy to modify it later
        currentLocation = assign$7({}, currentLocation || currentRoute.value);
        if (typeof rawLocation === 'string') {
            const locationNormalized = parseURL(parseQuery$1$1, rawLocation, currentLocation.path);
            const matchedRoute = matcher.resolve({ path: locationNormalized.path }, currentLocation);
            const href = routerHistory.createHref(locationNormalized.fullPath);
            // locationNormalized is always a new object
            return assign$7(locationNormalized, matchedRoute, {
                params: decodeParams(matchedRoute.params),
                hash: decode(locationNormalized.hash),
                redirectedFrom: undefined,
                href,
            });
        }
        let matcherLocation;
        // path could be relative in object as well
        if ('path' in rawLocation) {
            matcherLocation = assign$7({}, rawLocation, {
                path: parseURL(parseQuery$1$1, rawLocation.path, currentLocation.path).path,
            });
        }
        else {
            // remove any nullish param
            const targetParams = assign$7({}, rawLocation.params);
            for (const key in targetParams) {
                if (targetParams[key] == null) {
                    delete targetParams[key];
                }
            }
            // pass encoded values to the matcher, so it can produce encoded path and fullPath
            matcherLocation = assign$7({}, rawLocation, {
                params: encodeParams(targetParams),
            });
            // current location params are decoded, we need to encode them in case the
            // matcher merges the params
            currentLocation.params = encodeParams(currentLocation.params);
        }
        const matchedRoute = matcher.resolve(matcherLocation, currentLocation);
        const hash = rawLocation.hash || '';
        // the matcher might have merged current location params, so
        // we need to run the decoding again
        matchedRoute.params = normalizeParams(decodeParams(matchedRoute.params));
        const fullPath = stringifyURL(stringifyQuery$1, assign$7({}, rawLocation, {
            hash: encodeHash(hash),
            path: matchedRoute.path,
        }));
        const href = routerHistory.createHref(fullPath);
        return assign$7({
            fullPath,
            // keep the hash encoded so fullPath is effectively path + encodedQuery +
            // hash
            hash,
            query: 
            // if the user is using a custom query lib like qs, we might have
            // nested objects, so we keep the query as is, meaning it can contain
            // numbers at `$route.query`, but at the point, the user will have to
            // use their own type anyway.
            // https://github.com/vuejs/router/issues/328#issuecomment-649481567
            stringifyQuery$1 === stringifyQuery
                ? normalizeQuery(rawLocation.query)
                : (rawLocation.query || {}),
        }, matchedRoute, {
            redirectedFrom: undefined,
            href,
        });
    }
    function locationAsObject(to) {
        return typeof to === 'string'
            ? parseURL(parseQuery$1$1, to, currentRoute.value.path)
            : assign$7({}, to);
    }
    function checkCanceledNavigation(to, from) {
        if (pendingLocation !== to) {
            return createRouterError(8 /* ErrorTypes.NAVIGATION_CANCELLED */, {
                from,
                to,
            });
        }
    }
    function push(to) {
        return pushWithRedirect(to);
    }
    function replace(to) {
        return push(assign$7(locationAsObject(to), { replace: true }));
    }
    function handleRedirectRecord(to) {
        const lastMatched = to.matched[to.matched.length - 1];
        if (lastMatched && lastMatched.redirect) {
            const { redirect } = lastMatched;
            let newTargetLocation = typeof redirect === 'function' ? redirect(to) : redirect;
            if (typeof newTargetLocation === 'string') {
                newTargetLocation =
                    newTargetLocation.includes('?') || newTargetLocation.includes('#')
                        ? (newTargetLocation = locationAsObject(newTargetLocation))
                        : // force empty params
                            { path: newTargetLocation };
                // @ts-expect-error: force empty params when a string is passed to let
                // the router parse them again
                newTargetLocation.params = {};
            }
            return assign$7({
                query: to.query,
                hash: to.hash,
                // avoid transferring params if the redirect has a path
                params: 'path' in newTargetLocation ? {} : to.params,
            }, newTargetLocation);
        }
    }
    function pushWithRedirect(to, redirectedFrom) {
        const targetLocation = (pendingLocation = resolve(to));
        const from = currentRoute.value;
        const data = to.state;
        const force = to.force;
        // to could be a string where `replace` is a function
        const replace = to.replace === true;
        const shouldRedirect = handleRedirectRecord(targetLocation);
        if (shouldRedirect)
            return pushWithRedirect(assign$7(locationAsObject(shouldRedirect), {
                state: typeof shouldRedirect === 'object'
                    ? assign$7({}, data, shouldRedirect.state)
                    : data,
                force,
                replace,
            }), 
            // keep original redirectedFrom if it exists
            redirectedFrom || targetLocation);
        // if it was a redirect we already called `pushWithRedirect` above
        const toLocation = targetLocation;
        toLocation.redirectedFrom = redirectedFrom;
        let failure;
        if (!force && isSameRouteLocation(stringifyQuery$1, from, targetLocation)) {
            failure = createRouterError(16 /* ErrorTypes.NAVIGATION_DUPLICATED */, { to: toLocation, from });
            // trigger scroll to allow scrolling to the same anchor
            handleScroll(from, from, 
            // this is a push, the only way for it to be triggered from a
            // history.listen is with a redirect, which makes it become a push
            true, 
            // This cannot be the first navigation because the initial location
            // cannot be manually navigated to
            false);
        }
        return (failure ? Promise.resolve(failure) : navigate(toLocation, from))
            .catch((error) => isNavigationFailure(error)
            ? // navigation redirects still mark the router as ready
                isNavigationFailure(error, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)
                    ? error
                    : markAsReady(error) // also returns the error
            : // reject any unknown error
                triggerError(error, toLocation, from))
            .then((failure) => {
            if (failure) {
                if (isNavigationFailure(failure, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)) {
                    return pushWithRedirect(
                    // keep options
                    assign$7({
                        // preserve an existing replacement but allow the redirect to override it
                        replace,
                    }, locationAsObject(failure.to), {
                        state: typeof failure.to === 'object'
                            ? assign$7({}, data, failure.to.state)
                            : data,
                        force,
                    }), 
                    // preserve the original redirectedFrom if any
                    redirectedFrom || toLocation);
                }
            }
            else {
                // if we fail we don't finalize the navigation
                failure = finalizeNavigation(toLocation, from, true, replace, data);
            }
            triggerAfterEach(toLocation, from, failure);
            return failure;
        });
    }
    /**
     * Helper to reject and skip all navigation guards if a new navigation happened
     * @param to
     * @param from
     */
    function checkCanceledNavigationAndReject(to, from) {
        const error = checkCanceledNavigation(to, from);
        return error ? Promise.reject(error) : Promise.resolve();
    }
    function runWithContext(fn) {
        const app = installedApps.values().next().value;
        // support Vue < 3.3
        return app && typeof app.runWithContext === 'function'
            ? app.runWithContext(fn)
            : fn();
    }
    // TODO: refactor the whole before guards by internally using router.beforeEach
    function navigate(to, from) {
        let guards;
        const [leavingRecords, updatingRecords, enteringRecords] = extractChangingRecords(to, from);
        // all components here have been resolved once because we are leaving
        guards = extractComponentsGuards(leavingRecords.reverse(), 'beforeRouteLeave', to, from);
        // leavingRecords is already reversed
        for (const record of leavingRecords) {
            record.leaveGuards.forEach(guard => {
                guards.push(guardToPromiseFn(guard, to, from));
            });
        }
        const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(null, to, from);
        guards.push(canceledNavigationCheck);
        // run the queue of per route beforeRouteLeave guards
        return (runGuardQueue(guards)
            .then(() => {
            // check global guards beforeEach
            guards = [];
            for (const guard of beforeGuards.list()) {
                guards.push(guardToPromiseFn(guard, to, from));
            }
            guards.push(canceledNavigationCheck);
            return runGuardQueue(guards);
        })
            .then(() => {
            // check in components beforeRouteUpdate
            guards = extractComponentsGuards(updatingRecords, 'beforeRouteUpdate', to, from);
            for (const record of updatingRecords) {
                record.updateGuards.forEach(guard => {
                    guards.push(guardToPromiseFn(guard, to, from));
                });
            }
            guards.push(canceledNavigationCheck);
            // run the queue of per route beforeEnter guards
            return runGuardQueue(guards);
        })
            .then(() => {
            // check the route beforeEnter
            guards = [];
            for (const record of enteringRecords) {
                // do not trigger beforeEnter on reused views
                if (record.beforeEnter) {
                    if (isArray$j(record.beforeEnter)) {
                        for (const beforeEnter of record.beforeEnter)
                            guards.push(guardToPromiseFn(beforeEnter, to, from));
                    }
                    else {
                        guards.push(guardToPromiseFn(record.beforeEnter, to, from));
                    }
                }
            }
            guards.push(canceledNavigationCheck);
            // run the queue of per route beforeEnter guards
            return runGuardQueue(guards);
        })
            .then(() => {
            // NOTE: at this point to.matched is normalized and does not contain any () => Promise<Component>
            // clear existing enterCallbacks, these are added by extractComponentsGuards
            to.matched.forEach(record => (record.enterCallbacks = {}));
            // check in-component beforeRouteEnter
            guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from);
            guards.push(canceledNavigationCheck);
            // run the queue of per route beforeEnter guards
            return runGuardQueue(guards);
        })
            .then(() => {
            // check global guards beforeResolve
            guards = [];
            for (const guard of beforeResolveGuards.list()) {
                guards.push(guardToPromiseFn(guard, to, from));
            }
            guards.push(canceledNavigationCheck);
            return runGuardQueue(guards);
        })
            // catch any navigation canceled
            .catch(err => isNavigationFailure(err, 8 /* ErrorTypes.NAVIGATION_CANCELLED */)
            ? err
            : Promise.reject(err)));
    }
    function triggerAfterEach(to, from, failure) {
        // navigation is confirmed, call afterGuards
        // TODO: wrap with error handlers
        afterGuards
            .list()
            .forEach(guard => runWithContext(() => guard(to, from, failure)));
    }
    /**
     * - Cleans up any navigation guards
     * - Changes the url if necessary
     * - Calls the scrollBehavior
     */
    function finalizeNavigation(toLocation, from, isPush, replace, data) {
        // a more recent navigation took place
        const error = checkCanceledNavigation(toLocation, from);
        if (error)
            return error;
        // only consider as push if it's not the first navigation
        const isFirstNavigation = from === START_LOCATION_NORMALIZED;
        const state = !isBrowser ? {} : history.state;
        // change URL only if the user did a push/replace and if it's not the initial navigation because
        // it's just reflecting the url
        if (isPush) {
            // on the initial navigation, we want to reuse the scroll position from
            // history state if it exists
            if (replace || isFirstNavigation)
                routerHistory.replace(toLocation.fullPath, assign$7({
                    scroll: isFirstNavigation && state && state.scroll,
                }, data));
            else
                routerHistory.push(toLocation.fullPath, data);
        }
        // accept current navigation
        currentRoute.value = toLocation;
        handleScroll(toLocation, from, isPush, isFirstNavigation);
        markAsReady();
    }
    let removeHistoryListener;
    // attach listener to history to trigger navigations
    function setupListeners() {
        // avoid setting up listeners twice due to an invalid first navigation
        if (removeHistoryListener)
            return;
        removeHistoryListener = routerHistory.listen((to, _from, info) => {
            if (!router.listening)
                return;
            // cannot be a redirect route because it was in history
            const toLocation = resolve(to);
            // due to dynamic routing, and to hash history with manual navigation
            // (manually changing the url or calling history.hash = '#/somewhere'),
            // there could be a redirect record in history
            const shouldRedirect = handleRedirectRecord(toLocation);
            if (shouldRedirect) {
                pushWithRedirect(assign$7(shouldRedirect, { replace: true }), toLocation).catch(noop$4);
                return;
            }
            pendingLocation = toLocation;
            const from = currentRoute.value;
            // TODO: should be moved to web history?
            if (isBrowser) {
                saveScrollPosition(getScrollKey(from.fullPath, info.delta), computeScrollPosition());
            }
            navigate(toLocation, from)
                .catch((error) => {
                if (isNavigationFailure(error, 4 /* ErrorTypes.NAVIGATION_ABORTED */ | 8 /* ErrorTypes.NAVIGATION_CANCELLED */)) {
                    return error;
                }
                if (isNavigationFailure(error, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)) {
                    // Here we could call if (info.delta) routerHistory.go(-info.delta,
                    // false) but this is bug prone as we have no way to wait the
                    // navigation to be finished before calling pushWithRedirect. Using
                    // a setTimeout of 16ms seems to work but there is no guarantee for
                    // it to work on every browser. So instead we do not restore the
                    // history entry and trigger a new navigation as requested by the
                    // navigation guard.
                    // the error is already handled by router.push we just want to avoid
                    // logging the error
                    pushWithRedirect(error.to, toLocation
                    // avoid an uncaught rejection, let push call triggerError
                    )
                        .then(failure => {
                        // manual change in hash history #916 ending up in the URL not
                        // changing, but it was changed by the manual url change, so we
                        // need to manually change it ourselves
                        if (isNavigationFailure(failure, 4 /* ErrorTypes.NAVIGATION_ABORTED */ |
                            16 /* ErrorTypes.NAVIGATION_DUPLICATED */) &&
                            !info.delta &&
                            info.type === NavigationType.pop) {
                            routerHistory.go(-1, false);
                        }
                    })
                        .catch(noop$4);
                    // avoid the then branch
                    return Promise.reject();
                }
                // do not restore history on unknown direction
                if (info.delta) {
                    routerHistory.go(-info.delta, false);
                }
                // unrecognized error, transfer to the global handler
                return triggerError(error, toLocation, from);
            })
                .then((failure) => {
                failure =
                    failure ||
                        finalizeNavigation(
                        // after navigation, all matched components are resolved
                        toLocation, from, false);
                // revert the navigation
                if (failure) {
                    if (info.delta &&
                        // a new navigation has been triggered, so we do not want to revert, that will change the current history
                        // entry while a different route is displayed
                        !isNavigationFailure(failure, 8 /* ErrorTypes.NAVIGATION_CANCELLED */)) {
                        routerHistory.go(-info.delta, false);
                    }
                    else if (info.type === NavigationType.pop &&
                        isNavigationFailure(failure, 4 /* ErrorTypes.NAVIGATION_ABORTED */ | 16 /* ErrorTypes.NAVIGATION_DUPLICATED */)) {
                        // manual change in hash history #916
                        // it's like a push but lacks the information of the direction
                        routerHistory.go(-1, false);
                    }
                }
                triggerAfterEach(toLocation, from, failure);
            })
                // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors
                .catch(noop$4);
        });
    }
    // Initialization and Errors
    let readyHandlers = useCallbacks();
    let errorListeners = useCallbacks();
    let ready;
    /**
     * Trigger errorListeners added via onError and throws the error as well
     *
     * @param error - error to throw
     * @param to - location we were navigating to when the error happened
     * @param from - location we were navigating from when the error happened
     * @returns the error as a rejected promise
     */
    function triggerError(error, to, from) {
        markAsReady(error);
        const list = errorListeners.list();
        if (list.length) {
            list.forEach(handler => handler(error, to, from));
        }
        else {
            console.error(error);
        }
        // reject the error no matter there were error listeners or not
        return Promise.reject(error);
    }
    function isReady() {
        if (ready && currentRoute.value !== START_LOCATION_NORMALIZED)
            return Promise.resolve();
        return new Promise((resolve, reject) => {
            readyHandlers.add([resolve, reject]);
        });
    }
    function markAsReady(err) {
        if (!ready) {
            // still not ready if an error happened
            ready = !err;
            setupListeners();
            readyHandlers
                .list()
                .forEach(([resolve, reject]) => (err ? reject(err) : resolve()));
            readyHandlers.reset();
        }
        return err;
    }
    // Scroll behavior
    function handleScroll(to, from, isPush, isFirstNavigation) {
        const { scrollBehavior } = options;
        if (!isBrowser || !scrollBehavior)
            return Promise.resolve();
        const scrollPosition = (!isPush && getSavedScrollPosition(getScrollKey(to.fullPath, 0))) ||
            ((isFirstNavigation || !isPush) &&
                history.state &&
                history.state.scroll) ||
            null;
        return nextTick()
            .then(() => scrollBehavior(to, from, scrollPosition))
            .then(position => position && scrollToPosition(position))
            .catch(err => triggerError(err, to, from));
    }
    const go = (delta) => routerHistory.go(delta);
    let started;
    const installedApps = new Set();
    const router = {
        currentRoute,
        listening: true,
        addRoute,
        removeRoute,
        hasRoute,
        getRoutes,
        resolve,
        options,
        push,
        replace,
        go,
        back: () => go(-1),
        forward: () => go(1),
        beforeEach: beforeGuards.add,
        beforeResolve: beforeResolveGuards.add,
        afterEach: afterGuards.add,
        onError: errorListeners.add,
        isReady,
        install(app) {
            const router = this;
            app.component('RouterLink', RouterLink);
            app.component('RouterView', RouterView);
            app.config.globalProperties.$router = router;
            Object.defineProperty(app.config.globalProperties, '$route', {
                enumerable: true,
                get: () => unref(currentRoute),
            });
            // this initial navigation is only necessary on client, on server it doesn't
            // make sense because it will create an extra unnecessary navigation and could
            // lead to problems
            if (isBrowser &&
                // used for the initial navigation client side to avoid pushing
                // multiple times when the router is used in multiple apps
                !started &&
                currentRoute.value === START_LOCATION_NORMALIZED) {
                // see above
                started = true;
                push(routerHistory.location).catch(err => {
                });
            }
            const reactiveRoute = {};
            for (const key in START_LOCATION_NORMALIZED) {
                Object.defineProperty(reactiveRoute, key, {
                    get: () => currentRoute.value[key],
                    enumerable: true,
                });
            }
            app.provide(routerKey, router);
            app.provide(routeLocationKey, shallowReactive(reactiveRoute));
            app.provide(routerViewLocationKey, currentRoute);
            const unmountApp = app.unmount;
            installedApps.add(app);
            app.unmount = function () {
                installedApps.delete(app);
                // the router is not attached to an app anymore
                if (installedApps.size < 1) {
                    // invalidate the current navigation
                    pendingLocation = START_LOCATION_NORMALIZED;
                    removeHistoryListener && removeHistoryListener();
                    removeHistoryListener = null;
                    currentRoute.value = START_LOCATION_NORMALIZED;
                    started = false;
                    ready = false;
                }
                unmountApp();
            };
        },
    };
    // TODO: type this as NavigationGuardReturn or similar instead of any
    function runGuardQueue(guards) {
        return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve());
    }
    return router;
}
function extractChangingRecords(to, from) {
    const leavingRecords = [];
    const updatingRecords = [];
    const enteringRecords = [];
    const len = Math.max(from.matched.length, to.matched.length);
    for (let i = 0; i < len; i++) {
        const recordFrom = from.matched[i];
        if (recordFrom) {
            if (to.matched.find(record => isSameRouteRecord(record, recordFrom)))
                updatingRecords.push(recordFrom);
            else
                leavingRecords.push(recordFrom);
        }
        const recordTo = to.matched[i];
        if (recordTo) {
            // the type doesn't matter because we are comparing per reference
            if (!from.matched.find(record => isSameRouteRecord(record, recordTo))) {
                enteringRecords.push(recordTo);
            }
        }
    }
    return [leavingRecords, updatingRecords, enteringRecords];
}

/**
 * Returns the router instance. Equivalent to using `$router` inside
 * templates.
 */
function useRouter() {
    return inject(routerKey);
}
/**
 * Returns the current route location. Equivalent to using `$route` inside
 * templates.
 */
function useRoute() {
    return inject(routeLocationKey);
}

/* Injected with object hook! */

const _export_sfc = (sfc, props) => {
  const target = sfc.__vccOpts || sfc;
  for (const [key, val] of props) {
    target[key] = val;
  }
  return target;
};

/* Injected with object hook! */

/* unplugin-vue-components disabled */const _sfc_main$k = {};

const _hoisted_1$j = { class: "h-[calc(100vh-55px)]" };

function _sfc_render$2(_ctx, _cache) {
  return (openBlock(), createElementBlock("div", _hoisted_1$j, [
    renderSlot(_ctx.$slots, "default")
  ]))
}
const __unplugin_components_7 = /*#__PURE__*/_export_sfc(_sfc_main$k, [['render',_sfc_render$2]]);
/* Injected with object hook! */

const _hoisted_1$i = {
  "ml-0.4": "",
  "text-xs": "",
  op50: ""
};
const _sfc_main$j = /* @__PURE__ */ defineComponent({
  __name: "DurationDisplay",
  props: {
    duration: {},
    factor: { default: 1 },
    color: { type: Boolean, default: true }
  },
  setup(__props) {
    const props = __props;
    function getDurationColor(duration) {
      if (!props.color)
        return "";
      if (duration == null)
        return "text-gray:75";
      duration = duration * props.factor;
      if (duration < 1)
        return "text-gray:75";
      if (duration > 1e3)
        return "text-red-400";
      if (duration > 500)
        return "text-orange-400";
      if (duration > 200)
        return "text-yellow-400";
      return "";
    }
    const units = computed(() => {
      if (!props.duration)
        return ["-", ""];
      if (props.duration < 1)
        return ["<1", "ms"];
      if (props.duration < 1e3)
        return [props.duration.toFixed(0), "ms"];
      if (props.duration < 1e3 * 60)
        return [(props.duration / 1e3).toFixed(1), "s"];
      return [(props.duration / 1e3 / 60).toFixed(1), "min"];
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(getDurationColor(_ctx.duration))
      }, [
        createTextVNode(toDisplayString(unref(units)[0]), 1),
        createBaseVNode("span", _hoisted_1$i, toDisplayString(unref(units)[1]), 1)
      ], 2);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$h = {
  key: 0,
  class: "op50"
};
const _sfc_main$i = /* @__PURE__ */ defineComponent({
  __name: "PluginName",
  props: {
    name: {},
    hide: { type: Boolean }
  },
  setup(__props) {
    const props = __props;
    const starts = [
      "__load__",
      "vite:",
      "vite-plugin-",
      "vite-",
      "rollup-plugin-",
      "rollup-",
      "unplugin-"
    ];
    const parts = computed(() => {
      for (const s of starts) {
        if (props.name.startsWith(s))
          return [s, props.name.slice(s.length)];
      }
      return ["", props.name];
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        unref(parts)[0] && !_ctx.hide ? (openBlock(), createElementBlock("span", _hoisted_1$h, toDisplayString(unref(parts)[0]), 1)) : createCommentVNode("", true),
        createBaseVNode("span", null, toDisplayString(unref(parts)[1]), 1)
      ], 64);
    };
  }
});

/* Injected with object hook! */

/* unplugin-vue-components disabled */const _sfc_main$h = {};

const _hoisted_1$g = {
  "ws-nowrap": "",
  rounded: "",
  "px-1": "",
  "text-11px": "",
  "leading-1.6em": ""
};

function _sfc_render$1(_ctx, _cache) {
  return (openBlock(), createElementBlock("span", _hoisted_1$g, [
    renderSlot(_ctx.$slots, "default")
  ]))
}
const __unplugin_components_5 = /*#__PURE__*/_export_sfc(_sfc_main$h, [['render',_sfc_render$1]]);
/* Injected with object hook! */

function tryOnScopeDispose(fn) {
  if (getCurrentScope()) {
    onScopeDispose(fn);
    return true;
  }
  return false;
}

function createEventHook() {
  const fns = /* @__PURE__ */ new Set();
  const off = (fn) => {
    fns.delete(fn);
  };
  const on = (fn) => {
    fns.add(fn);
    const offFn = () => off(fn);
    tryOnScopeDispose(offFn);
    return {
      off: offFn
    };
  };
  const trigger = (param) => {
    return Promise.all(Array.from(fns).map((fn) => fn(param)));
  };
  return {
    on,
    off,
    trigger
  };
}

function toValue(r) {
  return typeof r === "function" ? r() : unref(r);
}

const isClient = typeof window !== "undefined" && typeof document !== "undefined";
const toString$f = Object.prototype.toString;
const isObject$n = (val) => toString$f.call(val) === "[object Object]";
const noop$3 = () => {
};

function createFilterWrapper(filter, fn) {
  function wrapper(...args) {
    return new Promise((resolve, reject) => {
      Promise.resolve(filter(() => fn.apply(this, args), { fn, thisArg: this, args })).then(resolve).catch(reject);
    });
  }
  return wrapper;
}
const bypassFilter = (invoke) => {
  return invoke();
};
function pausableFilter(extendFilter = bypassFilter) {
  const isActive = ref(true);
  function pause() {
    isActive.value = false;
  }
  function resume() {
    isActive.value = true;
  }
  const eventFilter = (...args) => {
    if (isActive.value)
      extendFilter(...args);
  };
  return { isActive: readonly(isActive), pause, resume, eventFilter };
}

function toRef(...args) {
  if (args.length !== 1)
    return toRef$1(...args);
  const r = args[0];
  return typeof r === "function" ? readonly(customRef(() => ({ get: r, set: noop$3 }))) : ref(r);
}

function watchWithFilter(source, cb, options = {}) {
  const {
    eventFilter = bypassFilter,
    ...watchOptions
  } = options;
  return watch(
    source,
    createFilterWrapper(
      eventFilter,
      cb
    ),
    watchOptions
  );
}

function watchPausable(source, cb, options = {}) {
  const {
    eventFilter: filter,
    ...watchOptions
  } = options;
  const { eventFilter, pause, resume, isActive } = pausableFilter(filter);
  const stop = watchWithFilter(
    source,
    cb,
    {
      ...watchOptions,
      eventFilter
    }
  );
  return { stop, pause, resume, isActive };
}

function tryOnMounted(fn, sync = true) {
  if (getCurrentInstance())
    onMounted(fn);
  else if (sync)
    fn();
  else
    nextTick(fn);
}

function useToggle(initialValue = false, options = {}) {
  const {
    truthyValue = true,
    falsyValue = false
  } = options;
  const valueIsRef = isRef(initialValue);
  const _value = ref(initialValue);
  function toggle(value) {
    if (arguments.length) {
      _value.value = value;
      return _value.value;
    } else {
      const truthy = toValue(truthyValue);
      _value.value = _value.value === truthy ? toValue(falsyValue) : truthy;
      return _value.value;
    }
  }
  if (valueIsRef)
    return toggle;
  else
    return [_value, toggle];
}

/* Injected with object hook! */

function unrefElement(elRef) {
  var _a;
  const plain = toValue(elRef);
  return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;
}

const defaultWindow = isClient ? window : void 0;

function useEventListener(...args) {
  let target;
  let events;
  let listeners;
  let options;
  if (typeof args[0] === "string" || Array.isArray(args[0])) {
    [events, listeners, options] = args;
    target = defaultWindow;
  } else {
    [target, events, listeners, options] = args;
  }
  if (!target)
    return noop$3;
  if (!Array.isArray(events))
    events = [events];
  if (!Array.isArray(listeners))
    listeners = [listeners];
  const cleanups = [];
  const cleanup = () => {
    cleanups.forEach((fn) => fn());
    cleanups.length = 0;
  };
  const register = (el, event, listener, options2) => {
    el.addEventListener(event, listener, options2);
    return () => el.removeEventListener(event, listener, options2);
  };
  const stopWatch = watch(
    () => [unrefElement(target), toValue(options)],
    ([el, options2]) => {
      cleanup();
      if (!el)
        return;
      const optionsClone = isObject$n(options2) ? { ...options2 } : options2;
      cleanups.push(
        ...events.flatMap((event) => {
          return listeners.map((listener) => register(el, event, listener, optionsClone));
        })
      );
    },
    { immediate: true, flush: "post" }
  );
  const stop = () => {
    stopWatch();
    cleanup();
  };
  tryOnScopeDispose(stop);
  return stop;
}

function useMounted() {
  const isMounted = ref(false);
  if (getCurrentInstance()) {
    onMounted(() => {
      isMounted.value = true;
    });
  }
  return isMounted;
}

function useSupported(callback) {
  const isMounted = useMounted();
  return computed(() => {
    isMounted.value;
    return Boolean(callback());
  });
}

function useMediaQuery(query, options = {}) {
  const { window = defaultWindow } = options;
  const isSupported = useSupported(() => window && "matchMedia" in window && typeof window.matchMedia === "function");
  let mediaQuery;
  const matches = ref(false);
  const handler = (event) => {
    matches.value = event.matches;
  };
  const cleanup = () => {
    if (!mediaQuery)
      return;
    if ("removeEventListener" in mediaQuery)
      mediaQuery.removeEventListener("change", handler);
    else
      mediaQuery.removeListener(handler);
  };
  const stopWatch = watchEffect(() => {
    if (!isSupported.value)
      return;
    cleanup();
    mediaQuery = window.matchMedia(toValue(query));
    if ("addEventListener" in mediaQuery)
      mediaQuery.addEventListener("change", handler);
    else
      mediaQuery.addListener(handler);
    matches.value = mediaQuery.matches;
  });
  tryOnScopeDispose(() => {
    stopWatch();
    cleanup();
    mediaQuery = void 0;
  });
  return matches;
}

const _global = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
const globalKey = "__vueuse_ssr_handlers__";
const handlers = /* @__PURE__ */ getHandlers();
function getHandlers() {
  if (!(globalKey in _global))
    _global[globalKey] = _global[globalKey] || {};
  return _global[globalKey];
}
function getSSRHandler(key, fallback) {
  return handlers[key] || fallback;
}

function guessSerializerType(rawInit) {
  return rawInit == null ? "any" : rawInit instanceof Set ? "set" : rawInit instanceof Map ? "map" : rawInit instanceof Date ? "date" : typeof rawInit === "boolean" ? "boolean" : typeof rawInit === "string" ? "string" : typeof rawInit === "object" ? "object" : !Number.isNaN(rawInit) ? "number" : "any";
}

const StorageSerializers = {
  boolean: {
    read: (v) => v === "true",
    write: (v) => String(v)
  },
  object: {
    read: (v) => JSON.parse(v),
    write: (v) => JSON.stringify(v)
  },
  number: {
    read: (v) => Number.parseFloat(v),
    write: (v) => String(v)
  },
  any: {
    read: (v) => v,
    write: (v) => String(v)
  },
  string: {
    read: (v) => v,
    write: (v) => String(v)
  },
  map: {
    read: (v) => new Map(JSON.parse(v)),
    write: (v) => JSON.stringify(Array.from(v.entries()))
  },
  set: {
    read: (v) => new Set(JSON.parse(v)),
    write: (v) => JSON.stringify(Array.from(v))
  },
  date: {
    read: (v) => new Date(v),
    write: (v) => v.toISOString()
  }
};
const customStorageEventName = "vueuse-storage";
function useStorage(key, defaults, storage, options = {}) {
  var _a;
  const {
    flush = "pre",
    deep = true,
    listenToStorageChanges = true,
    writeDefaults = true,
    mergeDefaults = false,
    shallow,
    window = defaultWindow,
    eventFilter,
    onError = (e) => {
      console.error(e);
    }
  } = options;
  const data = (shallow ? shallowRef : ref)(defaults);
  if (!storage) {
    try {
      storage = getSSRHandler("getDefaultStorage", () => {
        var _a2;
        return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;
      })();
    } catch (e) {
      onError(e);
    }
  }
  if (!storage)
    return data;
  const rawInit = toValue(defaults);
  const type = guessSerializerType(rawInit);
  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];
  const { pause: pauseWatch, resume: resumeWatch } = watchPausable(
    data,
    () => write(data.value),
    { flush, deep, eventFilter }
  );
  if (window && listenToStorageChanges) {
    useEventListener(window, "storage", update);
    useEventListener(window, customStorageEventName, updateFromCustomEvent);
  }
  update();
  return data;
  function write(v) {
    try {
      if (v == null) {
        storage.removeItem(key);
      } else {
        const serialized = serializer.write(v);
        const oldValue = storage.getItem(key);
        if (oldValue !== serialized) {
          storage.setItem(key, serialized);
          if (window) {
            window.dispatchEvent(new CustomEvent(customStorageEventName, {
              detail: {
                key,
                oldValue,
                newValue: serialized,
                storageArea: storage
              }
            }));
          }
        }
      }
    } catch (e) {
      onError(e);
    }
  }
  function read(event) {
    const rawValue = event ? event.newValue : storage.getItem(key);
    if (rawValue == null) {
      if (writeDefaults && rawInit !== null)
        storage.setItem(key, serializer.write(rawInit));
      return rawInit;
    } else if (!event && mergeDefaults) {
      const value = serializer.read(rawValue);
      if (typeof mergeDefaults === "function")
        return mergeDefaults(value, rawInit);
      else if (type === "object" && !Array.isArray(value))
        return { ...rawInit, ...value };
      return value;
    } else if (typeof rawValue !== "string") {
      return rawValue;
    } else {
      return serializer.read(rawValue);
    }
  }
  function updateFromCustomEvent(event) {
    update(event.detail);
  }
  function update(event) {
    if (event && event.storageArea !== storage)
      return;
    if (event && event.key == null) {
      data.value = rawInit;
      return;
    }
    if (event && event.key !== key)
      return;
    pauseWatch();
    try {
      if ((event == null ? void 0 : event.newValue) !== serializer.write(data.value))
        data.value = read(event);
    } catch (e) {
      onError(e);
    } finally {
      if (event)
        nextTick(resumeWatch);
      else
        resumeWatch();
    }
  }
}

function usePreferredDark(options) {
  return useMediaQuery("(prefers-color-scheme: dark)", options);
}

function useColorMode(options = {}) {
  const {
    selector = "html",
    attribute = "class",
    initialValue = "auto",
    window = defaultWindow,
    storage,
    storageKey = "vueuse-color-scheme",
    listenToStorageChanges = true,
    storageRef,
    emitAuto,
    disableTransition = true
  } = options;
  const modes = {
    auto: "",
    light: "light",
    dark: "dark",
    ...options.modes || {}
  };
  const preferredDark = usePreferredDark({ window });
  const system = computed(() => preferredDark.value ? "dark" : "light");
  const store = storageRef || (storageKey == null ? toRef(initialValue) : useStorage(storageKey, initialValue, storage, { window, listenToStorageChanges }));
  const state = computed(() => store.value === "auto" ? system.value : store.value);
  const updateHTMLAttrs = getSSRHandler(
    "updateHTMLAttrs",
    (selector2, attribute2, value) => {
      const el = typeof selector2 === "string" ? window == null ? void 0 : window.document.querySelector(selector2) : unrefElement(selector2);
      if (!el)
        return;
      let style;
      if (disableTransition) {
        style = window.document.createElement("style");
        const styleString = "*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";
        style.appendChild(document.createTextNode(styleString));
        window.document.head.appendChild(style);
      }
      if (attribute2 === "class") {
        const current = value.split(/\s/g);
        Object.values(modes).flatMap((i) => (i || "").split(/\s/g)).filter(Boolean).forEach((v) => {
          if (current.includes(v))
            el.classList.add(v);
          else
            el.classList.remove(v);
        });
      } else {
        el.setAttribute(attribute2, value);
      }
      if (disableTransition) {
        window.getComputedStyle(style).opacity;
        document.head.removeChild(style);
      }
    }
  );
  function defaultOnChanged(mode) {
    var _a;
    updateHTMLAttrs(selector, attribute, (_a = modes[mode]) != null ? _a : mode);
  }
  function onChanged(mode) {
    if (options.onChanged)
      options.onChanged(mode, defaultOnChanged);
    else
      defaultOnChanged(mode);
  }
  watch(state, onChanged, { flush: "post", immediate: true });
  tryOnMounted(() => onChanged(state.value));
  const auto = computed({
    get() {
      return emitAuto ? store.value : state.value;
    },
    set(v) {
      store.value = v;
    }
  });
  try {
    return Object.assign(auto, { store, system, state });
  } catch (e) {
    return auto;
  }
}

function useDark(options = {}) {
  const {
    valueDark = "dark",
    valueLight = ""
  } = options;
  const mode = useColorMode({
    ...options,
    onChanged: (mode2, defaultHandler) => {
      var _a;
      if (options.onChanged)
        (_a = options.onChanged) == null ? void 0 : _a.call(options, mode2 === "dark", defaultHandler, mode2);
      else
        defaultHandler(mode2);
    },
    modes: {
      dark: valueDark,
      light: valueLight
    }
  });
  const isDark = computed({
    get() {
      return mode.value === "dark";
    },
    set(v) {
      const modeVal = v ? "dark" : "light";
      if (mode.system.value === modeVal)
        mode.value = "auto";
      else
        mode.value = modeVal;
    }
  });
  return isDark;
}

function useResizeObserver(target, callback, options = {}) {
  const { window = defaultWindow, ...observerOptions } = options;
  let observer;
  const isSupported = useSupported(() => window && "ResizeObserver" in window);
  const cleanup = () => {
    if (observer) {
      observer.disconnect();
      observer = void 0;
    }
  };
  const targets = computed(() => Array.isArray(target) ? target.map((el) => unrefElement(el)) : [unrefElement(target)]);
  const stopWatch = watch(
    targets,
    (els) => {
      cleanup();
      if (isSupported.value && window) {
        observer = new ResizeObserver(callback);
        for (const _el of els)
          _el && observer.observe(_el, observerOptions);
      }
    },
    { immediate: true, flush: "post", deep: true }
  );
  const stop = () => {
    cleanup();
    stopWatch();
  };
  tryOnScopeDispose(stop);
  return {
    isSupported,
    stop
  };
}

function useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) {
  const { window = defaultWindow, box = "content-box" } = options;
  const isSVG = computed(() => {
    var _a, _b;
    return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.includes("svg");
  });
  const width = ref(initialSize.width);
  const height = ref(initialSize.height);
  useResizeObserver(
    target,
    ([entry]) => {
      const boxSize = box === "border-box" ? entry.borderBoxSize : box === "content-box" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;
      if (window && isSVG.value) {
        const $elem = unrefElement(target);
        if ($elem) {
          const styles = window.getComputedStyle($elem);
          width.value = Number.parseFloat(styles.width);
          height.value = Number.parseFloat(styles.height);
        }
      } else {
        if (boxSize) {
          const formatBoxSize = Array.isArray(boxSize) ? boxSize : [boxSize];
          width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);
          height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);
        } else {
          width.value = entry.contentRect.width;
          height.value = entry.contentRect.height;
        }
      }
    },
    options
  );
  watch(
    () => unrefElement(target),
    (ele) => {
      width.value = ele ? initialSize.width : 0;
      height.value = ele ? initialSize.height : 0;
    }
  );
  return {
    width,
    height
  };
}

function useLocalStorage(key, initialValue, options = {}) {
  const { window = defaultWindow } = options;
  return useStorage(key, initialValue, window == null ? void 0 : window.localStorage, options);
}

function useVirtualList(list, options) {
  const { containerStyle, wrapperProps, scrollTo, calculateRange, currentList, containerRef } = "itemHeight" in options ? useVerticalVirtualList(options, list) : useHorizontalVirtualList(options, list);
  return {
    list: currentList,
    scrollTo,
    containerProps: {
      ref: containerRef,
      onScroll: () => {
        calculateRange();
      },
      style: containerStyle
    },
    wrapperProps
  };
}
function useVirtualListResources(list) {
  const containerRef = ref(null);
  const size = useElementSize(containerRef);
  const currentList = ref([]);
  const source = shallowRef(list);
  const state = ref({ start: 0, end: 10 });
  return { state, source, currentList, size, containerRef };
}
function createGetViewCapacity(state, source, itemSize) {
  return (containerSize) => {
    if (typeof itemSize === "number")
      return Math.ceil(containerSize / itemSize);
    const { start = 0 } = state.value;
    let sum = 0;
    let capacity = 0;
    for (let i = start; i < source.value.length; i++) {
      const size = itemSize(i);
      sum += size;
      capacity = i;
      if (sum > containerSize)
        break;
    }
    return capacity - start;
  };
}
function createGetOffset(source, itemSize) {
  return (scrollDirection) => {
    if (typeof itemSize === "number")
      return Math.floor(scrollDirection / itemSize) + 1;
    let sum = 0;
    let offset = 0;
    for (let i = 0; i < source.value.length; i++) {
      const size = itemSize(i);
      sum += size;
      if (sum >= scrollDirection) {
        offset = i;
        break;
      }
    }
    return offset + 1;
  };
}
function createCalculateRange(type, overscan, getOffset, getViewCapacity, { containerRef, state, currentList, source }) {
  return () => {
    const element = containerRef.value;
    if (element) {
      const offset = getOffset(type === "vertical" ? element.scrollTop : element.scrollLeft);
      const viewCapacity = getViewCapacity(type === "vertical" ? element.clientHeight : element.clientWidth);
      const from = offset - overscan;
      const to = offset + viewCapacity + overscan;
      state.value = {
        start: from < 0 ? 0 : from,
        end: to > source.value.length ? source.value.length : to
      };
      currentList.value = source.value.slice(state.value.start, state.value.end).map((ele, index) => ({
        data: ele,
        index: index + state.value.start
      }));
    }
  };
}
function createGetDistance(itemSize, source) {
  return (index) => {
    if (typeof itemSize === "number") {
      const size2 = index * itemSize;
      return size2;
    }
    const size = source.value.slice(0, index).reduce((sum, _, i) => sum + itemSize(i), 0);
    return size;
  };
}
function useWatchForSizes(size, list, calculateRange) {
  watch([size.width, size.height, list], () => {
    calculateRange();
  });
}
function createComputedTotalSize(itemSize, source) {
  return computed(() => {
    if (typeof itemSize === "number")
      return source.value.length * itemSize;
    return source.value.reduce((sum, _, index) => sum + itemSize(index), 0);
  });
}
const scrollToDictionaryForElementScrollKey = {
  horizontal: "scrollLeft",
  vertical: "scrollTop"
};
function createScrollTo(type, calculateRange, getDistance, containerRef) {
  return (index) => {
    if (containerRef.value) {
      containerRef.value[scrollToDictionaryForElementScrollKey[type]] = getDistance(index);
      calculateRange();
    }
  };
}
function useHorizontalVirtualList(options, list) {
  const resources = useVirtualListResources(list);
  const { state, source, currentList, size, containerRef } = resources;
  const containerStyle = { overflowX: "auto" };
  const { itemWidth, overscan = 5 } = options;
  const getViewCapacity = createGetViewCapacity(state, source, itemWidth);
  const getOffset = createGetOffset(source, itemWidth);
  const calculateRange = createCalculateRange("horizontal", overscan, getOffset, getViewCapacity, resources);
  const getDistanceLeft = createGetDistance(itemWidth, source);
  const offsetLeft = computed(() => getDistanceLeft(state.value.start));
  const totalWidth = createComputedTotalSize(itemWidth, source);
  useWatchForSizes(size, list, calculateRange);
  const scrollTo = createScrollTo("horizontal", calculateRange, getDistanceLeft, containerRef);
  const wrapperProps = computed(() => {
    return {
      style: {
        height: "100%",
        width: `${totalWidth.value - offsetLeft.value}px`,
        marginLeft: `${offsetLeft.value}px`,
        display: "flex"
      }
    };
  });
  return {
    scrollTo,
    calculateRange,
    wrapperProps,
    containerStyle,
    currentList,
    containerRef
  };
}
function useVerticalVirtualList(options, list) {
  const resources = useVirtualListResources(list);
  const { state, source, currentList, size, containerRef } = resources;
  const containerStyle = { overflowY: "auto" };
  const { itemHeight, overscan = 5 } = options;
  const getViewCapacity = createGetViewCapacity(state, source, itemHeight);
  const getOffset = createGetOffset(source, itemHeight);
  const calculateRange = createCalculateRange("vertical", overscan, getOffset, getViewCapacity, resources);
  const getDistanceTop = createGetDistance(itemHeight, source);
  const offsetTop = computed(() => getDistanceTop(state.value.start));
  const totalHeight = createComputedTotalSize(itemHeight, source);
  useWatchForSizes(size, list, calculateRange);
  const scrollTo = createScrollTo("vertical", calculateRange, getDistanceTop, containerRef);
  const wrapperProps = computed(() => {
    return {
      style: {
        width: "100%",
        height: `${totalHeight.value - offsetTop.value}px`,
        marginTop: `${offsetTop.value}px`
      }
    };
  });
  return {
    calculateRange,
    scrollTo,
    containerStyle,
    wrapperProps,
    currentList,
    containerRef
  };
}

/* Injected with object hook! */

const isDark = useDark();
const toggleDark = useToggle(isDark);

/* Injected with object hook! */

const scriptRel = 'modulepreload';const assetsURL = function(dep, importerUrl) { return new URL(dep, importerUrl).href };const seen = {};const __vitePreload = function preload(baseModule, deps, importerUrl) {
    // @ts-expect-error true will be replaced with boolean later
    if (!true || !deps || deps.length === 0) {
        return baseModule();
    }
    const links = document.getElementsByTagName('link');
    return Promise.all(deps.map((dep) => {
        // @ts-expect-error assetsURL is declared before preload.toString()
        dep = assetsURL(dep, importerUrl);
        if (dep in seen)
            return;
        seen[dep] = true;
        const isCss = dep.endsWith('.css');
        const cssSelector = isCss ? '[rel="stylesheet"]' : '';
        const isBaseRelative = !!importerUrl;
        // check if the file is already preloaded by SSR markup
        if (isBaseRelative) {
            // When isBaseRelative is true then we have `importerUrl` and `dep` is
            // already converted to an absolute URL by the `assetsURL` function
            for (let i = links.length - 1; i >= 0; i--) {
                const link = links[i];
                // The `links[i].href` is an absolute URL thanks to browser doing the work
                // for us. See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:idl-domstring-5
                if (link.href === dep && (!isCss || link.rel === 'stylesheet')) {
                    return;
                }
            }
        }
        else if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
            return;
        }
        const link = document.createElement('link');
        link.rel = isCss ? 'stylesheet' : scriptRel;
        if (!isCss) {
            link.as = 'script';
            link.crossOrigin = '';
        }
        link.href = dep;
        document.head.appendChild(link);
        if (isCss) {
            return new Promise((res, rej) => {
                link.addEventListener('load', res);
                link.addEventListener('error', () => rej(new Error(`Unable to preload CSS for ${dep}`)));
            });
        }
    }))
        .then(() => baseModule())
        .catch((err) => {
        const e = new Event('vite:preloadError', { cancelable: true });
        // @ts-expect-error custom payload
        e.payload = err;
        window.dispatchEvent(e);
        if (!e.defaultPrevented) {
            throw err;
        }
    });
};
/* Injected with object hook! */

const DEFAULT_TIMEOUT = 6e4;
function defaultSerialize(i) {
  return i;
}
const defaultDeserialize = defaultSerialize;
const { setTimeout: setTimeout$4 } = globalThis;
function createBirpc(functions, options) {
  const {
    post,
    on,
    eventNames = [],
    serialize = defaultSerialize,
    deserialize = defaultDeserialize,
    resolver,
    timeout = DEFAULT_TIMEOUT
  } = options;
  const rpcPromiseMap = /* @__PURE__ */ new Map();
  let _promise;
  const rpc = new Proxy({}, {
    get(_, method) {
      if (method === "$functions")
        return functions;
      const sendEvent = (...args) => {
        post(serialize({ m: method, a: args, t: "q" }));
      };
      if (eventNames.includes(method)) {
        sendEvent.asEvent = sendEvent;
        return sendEvent;
      }
      const sendCall = async (...args) => {
        await _promise;
        return new Promise((resolve, reject) => {
          const id = nanoid();
          rpcPromiseMap.set(id, { resolve, reject });
          post(serialize({ m: method, a: args, i: id, t: "q" }));
          if (timeout >= 0) {
            setTimeout$4(() => {
              reject(new Error(`[birpc] timeout on calling "${method}"`));
              rpcPromiseMap.delete(id);
            }, timeout);
          }
        });
      };
      sendCall.asEvent = sendEvent;
      return sendCall;
    }
  });
  _promise = on(async (data, ...extra) => {
    const msg = deserialize(data);
    if (msg.t === "q") {
      const { m: method, a: args } = msg;
      let result, error;
      const fn = resolver ? resolver(method, functions[method]) : functions[method];
      if (!fn) {
        error = new Error(`[birpc] function "${method}" not found`);
      } else {
        try {
          result = await fn.apply(rpc, args);
        } catch (e) {
          error = e;
        }
      }
      if (msg.i) {
        if (error && options.onError)
          options.onError(error, method, args);
        post(serialize({ t: "s", i: msg.i, r: result, e: error }), ...extra);
      }
    } else {
      const { i: ack, r: result, e: error } = msg;
      const promise = rpcPromiseMap.get(ack);
      if (promise) {
        if (error)
          promise.reject(error);
        else
          promise.resolve(result);
      }
      rpcPromiseMap.delete(ack);
    }
  });
  return rpc;
}
const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
function nanoid(size = 21) {
  let id = "";
  let i = size;
  while (i--)
    id += urlAlphabet[Math.random() * 64 | 0];
  return id;
}

/* Injected with object hook! */

function createRPCClient(name, hot, functions = {}) {
  const event = `${name}:rpc`;
  return createBirpc(
    functions,
    {
      on: async (fn) => {
        (await hot).on(event, fn);
      },
      post: async (data) => {
        (await hot).send(event, data);
      }
    }
  );
}

/* Injected with object hook! */

async function getViteClient(base = "/", warning = true) {
  try {
    const url = `${base}@vite/client`;
    const res = await fetch(url);
    const text = await res.text();
    if (text.startsWith("<") || !res.headers.get("content-type")?.includes("javascript"))
      throw new Error("Not javascript");
    return await __vitePreload(() => import(
      /* @vite-ignore */
      url
    ),true?[]:void 0,import.meta.url);
  } catch {
    if (warning)
      console.error(`[vite-hot-client] Failed to import "${base}@vite/client"`);
  }
  return void 0;
}
async function createHotContext(path = "/____", base = "/") {
  const viteClient = await getViteClient(base);
  return viteClient?.createHotContext(path);
}

/* Injected with object hook! */

const isStaticMode = document.body.getAttribute("data-vite-inspect-mode") === "BUILD";
function createStaticRpcClient() {
  async function getIdInfo(id, ssr = false) {
    const { hash } = await __vitePreload(() => import('./index-d51e03c4.js'),true?[]:void 0,import.meta.url);
    return await fetch(`./reports/${ssr ? "transform-ssr" : "transform"}/${hash(id)}.json`).then((r) => r.json());
  }
  return {
    list: async () => {
      return await fetch("./reports/list.json").then((r) => r.json());
    },
    async resolveId(id, ssr) {
      return (await getIdInfo(id, ssr)).resolvedId || id;
    },
    async clear() {
    },
    async getPluginMetrics(ssr) {
      try {
        return await fetch(`./reports/${ssr ? "metrics-ssr" : "metrics"}.json`).then((r) => r.json());
      } catch (e) {
        return [];
      }
    },
    async getServerMetrics() {
      return {};
    },
    getIdInfo
  };
}
const rpc = isStaticMode ? createStaticRpcClient() : createRPCClient("vite-plugin-inspect", await createHotContext("/___", `${location.pathname.split("/__inspect")[0] || ""}/`.replace(/\/\//g, "/")));

/* Injected with object hook! */

/**
 * Fuse.js v7.0.0 - Lightweight fuzzy-search (http://fusejs.io)
 *
 * Copyright (c) 2023 Kiro Risk (http://kiro.me)
 * All Rights Reserved. Apache Software License 2.0
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 */

function isArray$i(value) {
  return !Array.isArray
    ? getTag(value) === '[object Array]'
    : Array.isArray(value)
}

// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js
const INFINITY = 1 / 0;
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value
  }
  let result = value + '';
  return result == '0' && 1 / value == -INFINITY ? '-0' : result
}

function toString$e(value) {
  return value == null ? '' : baseToString(value)
}

function isString$2(value) {
  return typeof value === 'string'
}

function isNumber$1(value) {
  return typeof value === 'number'
}

// Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js
function isBoolean(value) {
  return (
    value === true ||
    value === false ||
    (isObjectLike(value) && getTag(value) == '[object Boolean]')
  )
}

function isObject$m(value) {
  return typeof value === 'object'
}

// Checks if `value` is object-like.
function isObjectLike(value) {
  return isObject$m(value) && value !== null
}

function isDefined(value) {
  return value !== undefined && value !== null
}

function isBlank(value) {
  return !value.trim().length
}

// Gets the `toStringTag` of `value`.
// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js
function getTag(value) {
  return value == null
    ? value === undefined
      ? '[object Undefined]'
      : '[object Null]'
    : Object.prototype.toString.call(value)
}

const EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available';

const INCORRECT_INDEX_TYPE = "Incorrect 'index' type";

const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) =>
  `Invalid value for key ${key}`;

const PATTERN_LENGTH_TOO_LARGE = (max) =>
  `Pattern length exceeds max of ${max}.`;

const MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`;

const INVALID_KEY_WEIGHT_VALUE = (key) =>
  `Property 'weight' in key '${key}' must be a positive integer`;

const hasOwn$l = Object.prototype.hasOwnProperty;

class KeyStore {
  constructor(keys) {
    this._keys = [];
    this._keyMap = {};

    let totalWeight = 0;

    keys.forEach((key) => {
      let obj = createKey(key);

      this._keys.push(obj);
      this._keyMap[obj.id] = obj;

      totalWeight += obj.weight;
    });

    // Normalize weights so that their sum is equal to 1
    this._keys.forEach((key) => {
      key.weight /= totalWeight;
    });
  }
  get(keyId) {
    return this._keyMap[keyId]
  }
  keys() {
    return this._keys
  }
  toJSON() {
    return JSON.stringify(this._keys)
  }
}

function createKey(key) {
  let path = null;
  let id = null;
  let src = null;
  let weight = 1;
  let getFn = null;

  if (isString$2(key) || isArray$i(key)) {
    src = key;
    path = createKeyPath(key);
    id = createKeyId(key);
  } else {
    if (!hasOwn$l.call(key, 'name')) {
      throw new Error(MISSING_KEY_PROPERTY('name'))
    }

    const name = key.name;
    src = name;

    if (hasOwn$l.call(key, 'weight')) {
      weight = key.weight;

      if (weight <= 0) {
        throw new Error(INVALID_KEY_WEIGHT_VALUE(name))
      }
    }

    path = createKeyPath(name);
    id = createKeyId(name);
    getFn = key.getFn;
  }

  return { path, id, weight, src, getFn }
}

function createKeyPath(key) {
  return isArray$i(key) ? key : key.split('.')
}

function createKeyId(key) {
  return isArray$i(key) ? key.join('.') : key
}

function get$a(obj, path) {
  let list = [];
  let arr = false;

  const deepGet = (obj, path, index) => {
    if (!isDefined(obj)) {
      return
    }
    if (!path[index]) {
      // If there's no path left, we've arrived at the object we care about.
      list.push(obj);
    } else {
      let key = path[index];

      const value = obj[key];

      if (!isDefined(value)) {
        return
      }

      // If we're at the last value in the path, and if it's a string/number/bool,
      // add it to the list
      if (
        index === path.length - 1 &&
        (isString$2(value) || isNumber$1(value) || isBoolean(value))
      ) {
        list.push(toString$e(value));
      } else if (isArray$i(value)) {
        arr = true;
        // Search each item in the array.
        for (let i = 0, len = value.length; i < len; i += 1) {
          deepGet(value[i], path, index + 1);
        }
      } else if (path.length) {
        // An object. Recurse further.
        deepGet(value, path, index + 1);
      }
    }
  };

  // Backwards compatibility (since path used to be a string)
  deepGet(obj, isString$2(path) ? path.split('.') : path, 0);

  return arr ? list : list[0]
}

const MatchOptions = {
  // Whether the matches should be included in the result set. When `true`, each record in the result
  // set will include the indices of the matched characters.
  // These can consequently be used for highlighting purposes.
  includeMatches: false,
  // When `true`, the matching function will continue to the end of a search pattern even if
  // a perfect match has already been located in the string.
  findAllMatches: false,
  // Minimum number of characters that must be matched before a result is considered a match
  minMatchCharLength: 1
};

const BasicOptions = {
  // When `true`, the algorithm continues searching to the end of the input even if a perfect
  // match is found before the end of the same input.
  isCaseSensitive: false,
  // When true, the matching function will continue to the end of a search pattern even if
  includeScore: false,
  // List of properties that will be searched. This also supports nested properties.
  keys: [],
  // Whether to sort the result list, by score
  shouldSort: true,
  // Default sort function: sort by ascending score, ascending index
  sortFn: (a, b) =>
    a.score === b.score ? (a.idx < b.idx ? -1 : 1) : a.score < b.score ? -1 : 1
};

const FuzzyOptions = {
  // Approximately where in the text is the pattern expected to be found?
  location: 0,
  // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match
  // (of both letters and location), a threshold of '1.0' would match anything.
  threshold: 0.6,
  // Determines how close the match must be to the fuzzy location (specified above).
  // An exact letter match which is 'distance' characters away from the fuzzy location
  // would score as a complete mismatch. A distance of '0' requires the match be at
  // the exact location specified, a threshold of '1000' would require a perfect match
  // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.
  distance: 100
};

const AdvancedOptions = {
  // When `true`, it enables the use of unix-like search commands
  useExtendedSearch: false,
  // The get function to use when fetching an object's properties.
  // The default will search nested paths *ie foo.bar.baz*
  getFn: get$a,
  // When `true`, search will ignore `location` and `distance`, so it won't matter
  // where in the string the pattern appears.
  // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score
  ignoreLocation: false,
  // When `true`, the calculation for the relevance score (used for sorting) will
  // ignore the field-length norm.
  // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm
  ignoreFieldNorm: false,
  // The weight to determine how much field length norm effects scoring.
  fieldNormWeight: 1
};

var Config = {
  ...BasicOptions,
  ...MatchOptions,
  ...FuzzyOptions,
  ...AdvancedOptions
};

const SPACE = /[^ ]+/g;

// Field-length norm: the shorter the field, the higher the weight.
// Set to 3 decimals to reduce index size.
function norm(weight = 1, mantissa = 3) {
  const cache = new Map();
  const m = Math.pow(10, mantissa);

  return {
    get(value) {
      const numTokens = value.match(SPACE).length;

      if (cache.has(numTokens)) {
        return cache.get(numTokens)
      }

      // Default function is 1/sqrt(x), weight makes that variable
      const norm = 1 / Math.pow(numTokens, 0.5 * weight);

      // In place of `toFixed(mantissa)`, for faster computation
      const n = parseFloat(Math.round(norm * m) / m);

      cache.set(numTokens, n);

      return n
    },
    clear() {
      cache.clear();
    }
  }
}

class FuseIndex {
  constructor({
    getFn = Config.getFn,
    fieldNormWeight = Config.fieldNormWeight
  } = {}) {
    this.norm = norm(fieldNormWeight, 3);
    this.getFn = getFn;
    this.isCreated = false;

    this.setIndexRecords();
  }
  setSources(docs = []) {
    this.docs = docs;
  }
  setIndexRecords(records = []) {
    this.records = records;
  }
  setKeys(keys = []) {
    this.keys = keys;
    this._keysMap = {};
    keys.forEach((key, idx) => {
      this._keysMap[key.id] = idx;
    });
  }
  create() {
    if (this.isCreated || !this.docs.length) {
      return
    }

    this.isCreated = true;

    // List is Array<String>
    if (isString$2(this.docs[0])) {
      this.docs.forEach((doc, docIndex) => {
        this._addString(doc, docIndex);
      });
    } else {
      // List is Array<Object>
      this.docs.forEach((doc, docIndex) => {
        this._addObject(doc, docIndex);
      });
    }

    this.norm.clear();
  }
  // Adds a doc to the end of the index
  add(doc) {
    const idx = this.size();

    if (isString$2(doc)) {
      this._addString(doc, idx);
    } else {
      this._addObject(doc, idx);
    }
  }
  // Removes the doc at the specified index of the index
  removeAt(idx) {
    this.records.splice(idx, 1);

    // Change ref index of every subsquent doc
    for (let i = idx, len = this.size(); i < len; i += 1) {
      this.records[i].i -= 1;
    }
  }
  getValueForItemAtKeyId(item, keyId) {
    return item[this._keysMap[keyId]]
  }
  size() {
    return this.records.length
  }
  _addString(doc, docIndex) {
    if (!isDefined(doc) || isBlank(doc)) {
      return
    }

    let record = {
      v: doc,
      i: docIndex,
      n: this.norm.get(doc)
    };

    this.records.push(record);
  }
  _addObject(doc, docIndex) {
    let record = { i: docIndex, $: {} };

    // Iterate over every key (i.e, path), and fetch the value at that key
    this.keys.forEach((key, keyIndex) => {
      let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path);

      if (!isDefined(value)) {
        return
      }

      if (isArray$i(value)) {
        let subRecords = [];
        const stack = [{ nestedArrIndex: -1, value }];

        while (stack.length) {
          const { nestedArrIndex, value } = stack.pop();

          if (!isDefined(value)) {
            continue
          }

          if (isString$2(value) && !isBlank(value)) {
            let subRecord = {
              v: value,
              i: nestedArrIndex,
              n: this.norm.get(value)
            };

            subRecords.push(subRecord);
          } else if (isArray$i(value)) {
            value.forEach((item, k) => {
              stack.push({
                nestedArrIndex: k,
                value: item
              });
            });
          } else ;
        }
        record.$[keyIndex] = subRecords;
      } else if (isString$2(value) && !isBlank(value)) {
        let subRecord = {
          v: value,
          n: this.norm.get(value)
        };

        record.$[keyIndex] = subRecord;
      }
    });

    this.records.push(record);
  }
  toJSON() {
    return {
      keys: this.keys,
      records: this.records
    }
  }
}

function createIndex(
  keys,
  docs,
  { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}
) {
  const myIndex = new FuseIndex({ getFn, fieldNormWeight });
  myIndex.setKeys(keys.map(createKey));
  myIndex.setSources(docs);
  myIndex.create();
  return myIndex
}

function parseIndex(
  data,
  { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}
) {
  const { keys, records } = data;
  const myIndex = new FuseIndex({ getFn, fieldNormWeight });
  myIndex.setKeys(keys);
  myIndex.setIndexRecords(records);
  return myIndex
}

function computeScore$1(
  pattern,
  {
    errors = 0,
    currentLocation = 0,
    expectedLocation = 0,
    distance = Config.distance,
    ignoreLocation = Config.ignoreLocation
  } = {}
) {
  const accuracy = errors / pattern.length;

  if (ignoreLocation) {
    return accuracy
  }

  const proximity = Math.abs(expectedLocation - currentLocation);

  if (!distance) {
    // Dodge divide by zero error.
    return proximity ? 1.0 : accuracy
  }

  return accuracy + proximity / distance
}

function convertMaskToIndices(
  matchmask = [],
  minMatchCharLength = Config.minMatchCharLength
) {
  let indices = [];
  let start = -1;
  let end = -1;
  let i = 0;

  for (let len = matchmask.length; i < len; i += 1) {
    let match = matchmask[i];
    if (match && start === -1) {
      start = i;
    } else if (!match && start !== -1) {
      end = i - 1;
      if (end - start + 1 >= minMatchCharLength) {
        indices.push([start, end]);
      }
      start = -1;
    }
  }

  // (i-1 - start) + 1 => i - start
  if (matchmask[i - 1] && i - start >= minMatchCharLength) {
    indices.push([start, i - 1]);
  }

  return indices
}

// Machine word size
const MAX_BITS = 32;

function search(
  text,
  pattern,
  patternAlphabet,
  {
    location = Config.location,
    distance = Config.distance,
    threshold = Config.threshold,
    findAllMatches = Config.findAllMatches,
    minMatchCharLength = Config.minMatchCharLength,
    includeMatches = Config.includeMatches,
    ignoreLocation = Config.ignoreLocation
  } = {}
) {
  if (pattern.length > MAX_BITS) {
    throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS))
  }

  const patternLen = pattern.length;
  // Set starting location at beginning text and initialize the alphabet.
  const textLen = text.length;
  // Handle the case when location > text.length
  const expectedLocation = Math.max(0, Math.min(location, textLen));
  // Highest score beyond which we give up.
  let currentThreshold = threshold;
  // Is there a nearby exact match? (speedup)
  let bestLocation = expectedLocation;

  // Performance: only computer matches when the minMatchCharLength > 1
  // OR if `includeMatches` is true.
  const computeMatches = minMatchCharLength > 1 || includeMatches;
  // A mask of the matches, used for building the indices
  const matchMask = computeMatches ? Array(textLen) : [];

  let index;

  // Get all exact matches, here for speed up
  while ((index = text.indexOf(pattern, bestLocation)) > -1) {
    let score = computeScore$1(pattern, {
      currentLocation: index,
      expectedLocation,
      distance,
      ignoreLocation
    });

    currentThreshold = Math.min(score, currentThreshold);
    bestLocation = index + patternLen;

    if (computeMatches) {
      let i = 0;
      while (i < patternLen) {
        matchMask[index + i] = 1;
        i += 1;
      }
    }
  }

  // Reset the best location
  bestLocation = -1;

  let lastBitArr = [];
  let finalScore = 1;
  let binMax = patternLen + textLen;

  const mask = 1 << (patternLen - 1);

  for (let i = 0; i < patternLen; i += 1) {
    // Scan for the best match; each iteration allows for one more error.
    // Run a binary search to determine how far from the match location we can stray
    // at this error level.
    let binMin = 0;
    let binMid = binMax;

    while (binMin < binMid) {
      const score = computeScore$1(pattern, {
        errors: i,
        currentLocation: expectedLocation + binMid,
        expectedLocation,
        distance,
        ignoreLocation
      });

      if (score <= currentThreshold) {
        binMin = binMid;
      } else {
        binMax = binMid;
      }

      binMid = Math.floor((binMax - binMin) / 2 + binMin);
    }

    // Use the result from this iteration as the maximum for the next.
    binMax = binMid;

    let start = Math.max(1, expectedLocation - binMid + 1);
    let finish = findAllMatches
      ? textLen
      : Math.min(expectedLocation + binMid, textLen) + patternLen;

    // Initialize the bit array
    let bitArr = Array(finish + 2);

    bitArr[finish + 1] = (1 << i) - 1;

    for (let j = finish; j >= start; j -= 1) {
      let currentLocation = j - 1;
      let charMatch = patternAlphabet[text.charAt(currentLocation)];

      if (computeMatches) {
        // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`)
        matchMask[currentLocation] = +!!charMatch;
      }

      // First pass: exact match
      bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch;

      // Subsequent passes: fuzzy match
      if (i) {
        bitArr[j] |=
          ((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1 | lastBitArr[j + 1];
      }

      if (bitArr[j] & mask) {
        finalScore = computeScore$1(pattern, {
          errors: i,
          currentLocation,
          expectedLocation,
          distance,
          ignoreLocation
        });

        // This match will almost certainly be better than any existing match.
        // But check anyway.
        if (finalScore <= currentThreshold) {
          // Indeed it is
          currentThreshold = finalScore;
          bestLocation = currentLocation;

          // Already passed `loc`, downhill from here on in.
          if (bestLocation <= expectedLocation) {
            break
          }

          // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`.
          start = Math.max(1, 2 * expectedLocation - bestLocation);
        }
      }
    }

    // No hope for a (better) match at greater error levels.
    const score = computeScore$1(pattern, {
      errors: i + 1,
      currentLocation: expectedLocation,
      expectedLocation,
      distance,
      ignoreLocation
    });

    if (score > currentThreshold) {
      break
    }

    lastBitArr = bitArr;
  }

  const result = {
    isMatch: bestLocation >= 0,
    // Count exact matches (those with a score of 0) to be "almost" exact
    score: Math.max(0.001, finalScore)
  };

  if (computeMatches) {
    const indices = convertMaskToIndices(matchMask, minMatchCharLength);
    if (!indices.length) {
      result.isMatch = false;
    } else if (includeMatches) {
      result.indices = indices;
    }
  }

  return result
}

function createPatternAlphabet(pattern) {
  let mask = {};

  for (let i = 0, len = pattern.length; i < len; i += 1) {
    const char = pattern.charAt(i);
    mask[char] = (mask[char] || 0) | (1 << (len - i - 1));
  }

  return mask
}

class BitapSearch {
  constructor(
    pattern,
    {
      location = Config.location,
      threshold = Config.threshold,
      distance = Config.distance,
      includeMatches = Config.includeMatches,
      findAllMatches = Config.findAllMatches,
      minMatchCharLength = Config.minMatchCharLength,
      isCaseSensitive = Config.isCaseSensitive,
      ignoreLocation = Config.ignoreLocation
    } = {}
  ) {
    this.options = {
      location,
      threshold,
      distance,
      includeMatches,
      findAllMatches,
      minMatchCharLength,
      isCaseSensitive,
      ignoreLocation
    };

    this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase();

    this.chunks = [];

    if (!this.pattern.length) {
      return
    }

    const addChunk = (pattern, startIndex) => {
      this.chunks.push({
        pattern,
        alphabet: createPatternAlphabet(pattern),
        startIndex
      });
    };

    const len = this.pattern.length;

    if (len > MAX_BITS) {
      let i = 0;
      const remainder = len % MAX_BITS;
      const end = len - remainder;

      while (i < end) {
        addChunk(this.pattern.substr(i, MAX_BITS), i);
        i += MAX_BITS;
      }

      if (remainder) {
        const startIndex = len - MAX_BITS;
        addChunk(this.pattern.substr(startIndex), startIndex);
      }
    } else {
      addChunk(this.pattern, 0);
    }
  }

  searchIn(text) {
    const { isCaseSensitive, includeMatches } = this.options;

    if (!isCaseSensitive) {
      text = text.toLowerCase();
    }

    // Exact match
    if (this.pattern === text) {
      let result = {
        isMatch: true,
        score: 0
      };

      if (includeMatches) {
        result.indices = [[0, text.length - 1]];
      }

      return result
    }

    // Otherwise, use Bitap algorithm
    const {
      location,
      distance,
      threshold,
      findAllMatches,
      minMatchCharLength,
      ignoreLocation
    } = this.options;

    let allIndices = [];
    let totalScore = 0;
    let hasMatches = false;

    this.chunks.forEach(({ pattern, alphabet, startIndex }) => {
      const { isMatch, score, indices } = search(text, pattern, alphabet, {
        location: location + startIndex,
        distance,
        threshold,
        findAllMatches,
        minMatchCharLength,
        includeMatches,
        ignoreLocation
      });

      if (isMatch) {
        hasMatches = true;
      }

      totalScore += score;

      if (isMatch && indices) {
        allIndices = [...allIndices, ...indices];
      }
    });

    let result = {
      isMatch: hasMatches,
      score: hasMatches ? totalScore / this.chunks.length : 1
    };

    if (hasMatches && includeMatches) {
      result.indices = allIndices;
    }

    return result
  }
}

class BaseMatch {
  constructor(pattern) {
    this.pattern = pattern;
  }
  static isMultiMatch(pattern) {
    return getMatch(pattern, this.multiRegex)
  }
  static isSingleMatch(pattern) {
    return getMatch(pattern, this.singleRegex)
  }
  search(/*text*/) {}
}

function getMatch(pattern, exp) {
  const matches = pattern.match(exp);
  return matches ? matches[1] : null
}

// Token: 'file

class ExactMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'exact'
  }
  static get multiRegex() {
    return /^="(.*)"$/
  }
  static get singleRegex() {
    return /^=(.*)$/
  }
  search(text) {
    const isMatch = text === this.pattern;

    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices: [0, this.pattern.length - 1]
    }
  }
}

// Token: !fire

class InverseExactMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'inverse-exact'
  }
  static get multiRegex() {
    return /^!"(.*)"$/
  }
  static get singleRegex() {
    return /^!(.*)$/
  }
  search(text) {
    const index = text.indexOf(this.pattern);
    const isMatch = index === -1;

    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices: [0, text.length - 1]
    }
  }
}

// Token: ^file

class PrefixExactMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'prefix-exact'
  }
  static get multiRegex() {
    return /^\^"(.*)"$/
  }
  static get singleRegex() {
    return /^\^(.*)$/
  }
  search(text) {
    const isMatch = text.startsWith(this.pattern);

    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices: [0, this.pattern.length - 1]
    }
  }
}

// Token: !^fire

class InversePrefixExactMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'inverse-prefix-exact'
  }
  static get multiRegex() {
    return /^!\^"(.*)"$/
  }
  static get singleRegex() {
    return /^!\^(.*)$/
  }
  search(text) {
    const isMatch = !text.startsWith(this.pattern);

    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices: [0, text.length - 1]
    }
  }
}

// Token: .file$

class SuffixExactMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'suffix-exact'
  }
  static get multiRegex() {
    return /^"(.*)"\$$/
  }
  static get singleRegex() {
    return /^(.*)\$$/
  }
  search(text) {
    const isMatch = text.endsWith(this.pattern);

    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices: [text.length - this.pattern.length, text.length - 1]
    }
  }
}

// Token: !.file$

class InverseSuffixExactMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'inverse-suffix-exact'
  }
  static get multiRegex() {
    return /^!"(.*)"\$$/
  }
  static get singleRegex() {
    return /^!(.*)\$$/
  }
  search(text) {
    const isMatch = !text.endsWith(this.pattern);
    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices: [0, text.length - 1]
    }
  }
}

class FuzzyMatch extends BaseMatch {
  constructor(
    pattern,
    {
      location = Config.location,
      threshold = Config.threshold,
      distance = Config.distance,
      includeMatches = Config.includeMatches,
      findAllMatches = Config.findAllMatches,
      minMatchCharLength = Config.minMatchCharLength,
      isCaseSensitive = Config.isCaseSensitive,
      ignoreLocation = Config.ignoreLocation
    } = {}
  ) {
    super(pattern);
    this._bitapSearch = new BitapSearch(pattern, {
      location,
      threshold,
      distance,
      includeMatches,
      findAllMatches,
      minMatchCharLength,
      isCaseSensitive,
      ignoreLocation
    });
  }
  static get type() {
    return 'fuzzy'
  }
  static get multiRegex() {
    return /^"(.*)"$/
  }
  static get singleRegex() {
    return /^(.*)$/
  }
  search(text) {
    return this._bitapSearch.searchIn(text)
  }
}

// Token: 'file

class IncludeMatch extends BaseMatch {
  constructor(pattern) {
    super(pattern);
  }
  static get type() {
    return 'include'
  }
  static get multiRegex() {
    return /^'"(.*)"$/
  }
  static get singleRegex() {
    return /^'(.*)$/
  }
  search(text) {
    let location = 0;
    let index;

    const indices = [];
    const patternLen = this.pattern.length;

    // Get all exact matches
    while ((index = text.indexOf(this.pattern, location)) > -1) {
      location = index + patternLen;
      indices.push([index, location - 1]);
    }

    const isMatch = !!indices.length;

    return {
      isMatch,
      score: isMatch ? 0 : 1,
      indices
    }
  }
}

// ❗Order is important. DO NOT CHANGE.
const searchers = [
  ExactMatch,
  IncludeMatch,
  PrefixExactMatch,
  InversePrefixExactMatch,
  InverseSuffixExactMatch,
  SuffixExactMatch,
  InverseExactMatch,
  FuzzyMatch
];

const searchersLen = searchers.length;

// Regex to split by spaces, but keep anything in quotes together
const SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;
const OR_TOKEN = '|';

// Return a 2D array representation of the query, for simpler parsing.
// Example:
// "^core go$ | rb$ | py$ xy$" => [["^core", "go$"], ["rb$"], ["py$", "xy$"]]
function parseQuery(pattern, options = {}) {
  return pattern.split(OR_TOKEN).map((item) => {
    let query = item
      .trim()
      .split(SPACE_RE)
      .filter((item) => item && !!item.trim());

    let results = [];
    for (let i = 0, len = query.length; i < len; i += 1) {
      const queryItem = query[i];

      // 1. Handle multiple query match (i.e, once that are quoted, like `"hello world"`)
      let found = false;
      let idx = -1;
      while (!found && ++idx < searchersLen) {
        const searcher = searchers[idx];
        let token = searcher.isMultiMatch(queryItem);
        if (token) {
          results.push(new searcher(token, options));
          found = true;
        }
      }

      if (found) {
        continue
      }

      // 2. Handle single query matches (i.e, once that are *not* quoted)
      idx = -1;
      while (++idx < searchersLen) {
        const searcher = searchers[idx];
        let token = searcher.isSingleMatch(queryItem);
        if (token) {
          results.push(new searcher(token, options));
          break
        }
      }
    }

    return results
  })
}

// These extended matchers can return an array of matches, as opposed
// to a singl match
const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]);

/**
 * Command-like searching
 * ======================
 *
 * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`,
 * search in a given text.
 *
 * Search syntax:
 *
 * | Token       | Match type                 | Description                            |
 * | ----------- | -------------------------- | -------------------------------------- |
 * | `jscript`   | fuzzy-match                | Items that fuzzy match `jscript`       |
 * | `=scheme`   | exact-match                | Items that are `scheme`                |
 * | `'python`   | include-match              | Items that include `python`            |
 * | `!ruby`     | inverse-exact-match        | Items that do not include `ruby`       |
 * | `^java`     | prefix-exact-match         | Items that start with `java`           |
 * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` |
 * | `.js$`      | suffix-exact-match         | Items that end with `.js`              |
 * | `!.go$`     | inverse-suffix-exact-match | Items that do not end with `.go`       |
 *
 * A single pipe character acts as an OR operator. For example, the following
 * query matches entries that start with `core` and end with either`go`, `rb`,
 * or`py`.
 *
 * ```
 * ^core go$ | rb$ | py$
 * ```
 */
class ExtendedSearch {
  constructor(
    pattern,
    {
      isCaseSensitive = Config.isCaseSensitive,
      includeMatches = Config.includeMatches,
      minMatchCharLength = Config.minMatchCharLength,
      ignoreLocation = Config.ignoreLocation,
      findAllMatches = Config.findAllMatches,
      location = Config.location,
      threshold = Config.threshold,
      distance = Config.distance
    } = {}
  ) {
    this.query = null;
    this.options = {
      isCaseSensitive,
      includeMatches,
      minMatchCharLength,
      findAllMatches,
      ignoreLocation,
      location,
      threshold,
      distance
    };

    this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase();
    this.query = parseQuery(this.pattern, this.options);
  }

  static condition(_, options) {
    return options.useExtendedSearch
  }

  searchIn(text) {
    const query = this.query;

    if (!query) {
      return {
        isMatch: false,
        score: 1
      }
    }

    const { includeMatches, isCaseSensitive } = this.options;

    text = isCaseSensitive ? text : text.toLowerCase();

    let numMatches = 0;
    let allIndices = [];
    let totalScore = 0;

    // ORs
    for (let i = 0, qLen = query.length; i < qLen; i += 1) {
      const searchers = query[i];

      // Reset indices
      allIndices.length = 0;
      numMatches = 0;

      // ANDs
      for (let j = 0, pLen = searchers.length; j < pLen; j += 1) {
        const searcher = searchers[j];
        const { isMatch, indices, score } = searcher.search(text);

        if (isMatch) {
          numMatches += 1;
          totalScore += score;
          if (includeMatches) {
            const type = searcher.constructor.type;
            if (MultiMatchSet.has(type)) {
              allIndices = [...allIndices, ...indices];
            } else {
              allIndices.push(indices);
            }
          }
        } else {
          totalScore = 0;
          numMatches = 0;
          allIndices.length = 0;
          break
        }
      }

      // OR condition, so if TRUE, return
      if (numMatches) {
        let result = {
          isMatch: true,
          score: totalScore / numMatches
        };

        if (includeMatches) {
          result.indices = allIndices;
        }

        return result
      }
    }

    // Nothing was matched
    return {
      isMatch: false,
      score: 1
    }
  }
}

const registeredSearchers = [];

function register$1(...args) {
  registeredSearchers.push(...args);
}

function createSearcher(pattern, options) {
  for (let i = 0, len = registeredSearchers.length; i < len; i += 1) {
    let searcherClass = registeredSearchers[i];
    if (searcherClass.condition(pattern, options)) {
      return new searcherClass(pattern, options)
    }
  }

  return new BitapSearch(pattern, options)
}

const LogicalOperator = {
  AND: '$and',
  OR: '$or'
};

const KeyType = {
  PATH: '$path',
  PATTERN: '$val'
};

const isExpression = (query) =>
  !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]);

const isPath$1 = (query) => !!query[KeyType.PATH];

const isLeaf = (query) =>
  !isArray$i(query) && isObject$m(query) && !isExpression(query);

const convertToExplicit = (query) => ({
  [LogicalOperator.AND]: Object.keys(query).map((key) => ({
    [key]: query[key]
  }))
});

// When `auto` is `true`, the parse function will infer and initialize and add
// the appropriate `Searcher` instance
function parse$1(query, options, { auto = true } = {}) {
  const next = (query) => {
    let keys = Object.keys(query);

    const isQueryPath = isPath$1(query);

    if (!isQueryPath && keys.length > 1 && !isExpression(query)) {
      return next(convertToExplicit(query))
    }

    if (isLeaf(query)) {
      const key = isQueryPath ? query[KeyType.PATH] : keys[0];

      const pattern = isQueryPath ? query[KeyType.PATTERN] : query[key];

      if (!isString$2(pattern)) {
        throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key))
      }

      const obj = {
        keyId: createKeyId(key),
        pattern
      };

      if (auto) {
        obj.searcher = createSearcher(pattern, options);
      }

      return obj
    }

    let node = {
      children: [],
      operator: keys[0]
    };

    keys.forEach((key) => {
      const value = query[key];

      if (isArray$i(value)) {
        value.forEach((item) => {
          node.children.push(next(item));
        });
      }
    });

    return node
  };

  if (!isExpression(query)) {
    query = convertToExplicit(query);
  }

  return next(query)
}

// Practical scoring function
function computeScore(
  results,
  { ignoreFieldNorm = Config.ignoreFieldNorm }
) {
  results.forEach((result) => {
    let totalScore = 1;

    result.matches.forEach(({ key, norm, score }) => {
      const weight = key ? key.weight : null;

      totalScore *= Math.pow(
        score === 0 && weight ? Number.EPSILON : score,
        (weight || 1) * (ignoreFieldNorm ? 1 : norm)
      );
    });

    result.score = totalScore;
  });
}

function transformMatches(result, data) {
  const matches = result.matches;
  data.matches = [];

  if (!isDefined(matches)) {
    return
  }

  matches.forEach((match) => {
    if (!isDefined(match.indices) || !match.indices.length) {
      return
    }

    const { indices, value } = match;

    let obj = {
      indices,
      value
    };

    if (match.key) {
      obj.key = match.key.src;
    }

    if (match.idx > -1) {
      obj.refIndex = match.idx;
    }

    data.matches.push(obj);
  });
}

function transformScore(result, data) {
  data.score = result.score;
}

function format$1(
  results,
  docs,
  {
    includeMatches = Config.includeMatches,
    includeScore = Config.includeScore
  } = {}
) {
  const transformers = [];

  if (includeMatches) transformers.push(transformMatches);
  if (includeScore) transformers.push(transformScore);

  return results.map((result) => {
    const { idx } = result;

    const data = {
      item: docs[idx],
      refIndex: idx
    };

    if (transformers.length) {
      transformers.forEach((transformer) => {
        transformer(result, data);
      });
    }

    return data
  })
}

class Fuse {
  constructor(docs, options = {}, index) {
    this.options = { ...Config, ...options };

    if (
      this.options.useExtendedSearch &&
      !true
    ) {
      throw new Error(EXTENDED_SEARCH_UNAVAILABLE)
    }

    this._keyStore = new KeyStore(this.options.keys);

    this.setCollection(docs, index);
  }

  setCollection(docs, index) {
    this._docs = docs;

    if (index && !(index instanceof FuseIndex)) {
      throw new Error(INCORRECT_INDEX_TYPE)
    }

    this._myIndex =
      index ||
      createIndex(this.options.keys, this._docs, {
        getFn: this.options.getFn,
        fieldNormWeight: this.options.fieldNormWeight
      });
  }

  add(doc) {
    if (!isDefined(doc)) {
      return
    }

    this._docs.push(doc);
    this._myIndex.add(doc);
  }

  remove(predicate = (/* doc, idx */) => false) {
    const results = [];

    for (let i = 0, len = this._docs.length; i < len; i += 1) {
      const doc = this._docs[i];
      if (predicate(doc, i)) {
        this.removeAt(i);
        i -= 1;
        len -= 1;

        results.push(doc);
      }
    }

    return results
  }

  removeAt(idx) {
    this._docs.splice(idx, 1);
    this._myIndex.removeAt(idx);
  }

  getIndex() {
    return this._myIndex
  }

  search(query, { limit = -1 } = {}) {
    const {
      includeMatches,
      includeScore,
      shouldSort,
      sortFn,
      ignoreFieldNorm
    } = this.options;

    let results = isString$2(query)
      ? isString$2(this._docs[0])
        ? this._searchStringList(query)
        : this._searchObjectList(query)
      : this._searchLogical(query);

    computeScore(results, { ignoreFieldNorm });

    if (shouldSort) {
      results.sort(sortFn);
    }

    if (isNumber$1(limit) && limit > -1) {
      results = results.slice(0, limit);
    }

    return format$1(results, this._docs, {
      includeMatches,
      includeScore
    })
  }

  _searchStringList(query) {
    const searcher = createSearcher(query, this.options);
    const { records } = this._myIndex;
    const results = [];

    // Iterate over every string in the index
    records.forEach(({ v: text, i: idx, n: norm }) => {
      if (!isDefined(text)) {
        return
      }

      const { isMatch, score, indices } = searcher.searchIn(text);

      if (isMatch) {
        results.push({
          item: text,
          idx,
          matches: [{ score, value: text, norm, indices }]
        });
      }
    });

    return results
  }

  _searchLogical(query) {

    const expression = parse$1(query, this.options);

    const evaluate = (node, item, idx) => {
      if (!node.children) {
        const { keyId, searcher } = node;

        const matches = this._findMatches({
          key: this._keyStore.get(keyId),
          value: this._myIndex.getValueForItemAtKeyId(item, keyId),
          searcher
        });

        if (matches && matches.length) {
          return [
            {
              idx,
              item,
              matches
            }
          ]
        }

        return []
      }

      const res = [];
      for (let i = 0, len = node.children.length; i < len; i += 1) {
        const child = node.children[i];
        const result = evaluate(child, item, idx);
        if (result.length) {
          res.push(...result);
        } else if (node.operator === LogicalOperator.AND) {
          return []
        }
      }
      return res
    };

    const records = this._myIndex.records;
    const resultMap = {};
    const results = [];

    records.forEach(({ $: item, i: idx }) => {
      if (isDefined(item)) {
        let expResults = evaluate(expression, item, idx);

        if (expResults.length) {
          // Dedupe when adding
          if (!resultMap[idx]) {
            resultMap[idx] = { idx, item, matches: [] };
            results.push(resultMap[idx]);
          }
          expResults.forEach(({ matches }) => {
            resultMap[idx].matches.push(...matches);
          });
        }
      }
    });

    return results
  }

  _searchObjectList(query) {
    const searcher = createSearcher(query, this.options);
    const { keys, records } = this._myIndex;
    const results = [];

    // List is Array<Object>
    records.forEach(({ $: item, i: idx }) => {
      if (!isDefined(item)) {
        return
      }

      let matches = [];

      // Iterate over every key (i.e, path), and fetch the value at that key
      keys.forEach((key, keyIndex) => {
        matches.push(
          ...this._findMatches({
            key,
            value: item[keyIndex],
            searcher
          })
        );
      });

      if (matches.length) {
        results.push({
          idx,
          item,
          matches
        });
      }
    });

    return results
  }
  _findMatches({ key, value, searcher }) {
    if (!isDefined(value)) {
      return []
    }

    let matches = [];

    if (isArray$i(value)) {
      value.forEach(({ v: text, i: idx, n: norm }) => {
        if (!isDefined(text)) {
          return
        }

        const { isMatch, score, indices } = searcher.searchIn(text);

        if (isMatch) {
          matches.push({
            score,
            key,
            value: text,
            idx,
            norm,
            indices
          });
        }
      });
    } else {
      const { v: text, n: norm } = value;

      const { isMatch, score, indices } = searcher.searchIn(text);

      if (isMatch) {
        matches.push({ score, key, value: text, norm, indices });
      }
    }

    return matches
  }
}

Fuse.version = '7.0.0';
Fuse.createIndex = createIndex;
Fuse.parseIndex = parseIndex;
Fuse.config = Config;

{
  Fuse.parseQuery = parse$1;
}

{
  register$1(ExtendedSearch);
}

/* Injected with object hook! */

const searchText = useStorage("vite-inspect-search-text", "");
const includeNodeModules = useStorage("vite-inspect-include-node-modules", false);
const includeVirtual = useStorage("vite-inspect-include-virtual", false);
const exactSearch = useStorage("vite-inspect-exact-search", false);
const searchResults = computed(() => {
  let data = (inspectSSR.value ? list.value?.ssrModules : list.value?.modules) || [];
  if (!includeNodeModules.value)
    data = data.filter((item) => !item.id.includes("/node_modules/"));
  if (!includeVirtual.value)
    data = data.filter((item) => !item.virtual);
  if (!searchText.value)
    return data;
  if (exactSearch.value) {
    return data.filter(
      (item) => item.id.includes(searchText.value) || item.plugins.some((plugin) => plugin.name.includes(searchText.value))
    );
  } else {
    const fuse = new Fuse(data, {
      shouldSort: true,
      keys: ["id", "plugins"]
    });
    return fuse.search(searchText.value).map((i) => i.item);
  }
});

/* Injected with object hook! */

const onRefetch = createEventHook();
const enableDiff = useStorage("vite-inspect-diff", true);
const showOneColumn = useStorage("vite-inspect-one-column", false);
const showBailout = useStorage("vite-inspect-bailout", false);
const listMode = useStorage("vite-inspect-mode", "detailed");
const lineWrapping = useStorage("vite-inspect-line-wrapping", false);
const inspectSSR = useStorage("vite-inspect-ssr", false);
const metricDisplayHook = useStorage("vite-inspect-metric-display-hook", "transform");
const sortMode = useStorage("vite-inspect-sort", "default");
const list = ref(await rpc.list());
const modes = [
  "detailed",
  "graph",
  "list"
];
function toggleMode() {
  listMode.value = modes[(modes.indexOf(listMode.value) + 1) % modes.length];
}
const root = computed(() => list.value?.root || "");
async function refetch() {
  onRefetch.trigger();
  list.value = await rpc.list();
  return list.value;
}
const rules = [
  "default",
  "time-asc",
  "time-desc"
];
function toggleSort() {
  sortMode.value = rules[(rules.indexOf(sortMode.value) + 1) % rules.length];
}
const sortedSearchResults = computed(() => {
  if (searchText.value)
    return searchResults.value;
  const clonedSearchResults = [...searchResults.value];
  if (sortMode.value === "time-asc")
    clonedSearchResults.sort((a, b) => b.totalTime - a.totalTime);
  if (sortMode.value === "time-desc")
    clonedSearchResults.sort((a, b) => a.totalTime - b.totalTime);
  return clonedSearchResults;
});

/* Injected with object hook! */

function guessMode(code) {
  if (code.trimStart().startsWith("<"))
    return "htmlmixed";
  if (code.match(/^import\s/))
    return "javascript";
  if (code.match(/^[.#].+\{/))
    return "css";
  return "javascript";
}
function inspectSourcemaps({ code, sourcemaps }) {
  console.info("sourcemaps", JSON.stringify(sourcemaps, null, 2));
  const serialized = serializeForSourcemapsVisualizer(code, sourcemaps);
  window.open(`https://evanw.github.io/source-map-visualization#${serialized}`, "_blank");
}
function safeJsonParse(str) {
  try {
    return JSON.parse(str);
  } catch (e) {
    console.error("Failed to parse JSON", str);
    return null;
  }
}
function serializeForSourcemapsVisualizer(code, map) {
  const encoder = new TextEncoder();
  const codeArray = encoder.encode(code);
  const mapArray = encoder.encode(map);
  const codeLengthArray = encoder.encode(codeArray.length.toString());
  const mapLengthArray = encoder.encode(mapArray.length.toString());
  const combinedArray = new Uint8Array(codeLengthArray.length + 1 + codeArray.length + mapLengthArray.length + 1 + mapArray.length);
  combinedArray.set(codeLengthArray);
  combinedArray.set([0], codeLengthArray.length);
  combinedArray.set(codeArray, codeLengthArray.length + 1);
  combinedArray.set(mapLengthArray, codeLengthArray.length + 1 + codeArray.length);
  combinedArray.set([0], codeLengthArray.length + 1 + codeArray.length + mapLengthArray.length);
  combinedArray.set(mapArray, codeLengthArray.length + 1 + codeArray.length + mapLengthArray.length + 1);
  let binary = "";
  const len = combinedArray.byteLength;
  for (let i = 0; i < len; i++)
    binary += String.fromCharCode(combinedArray[i]);
  return btoa(binary);
}

/* Injected with object hook! */

const graphWeightMode = useStorage("vite-inspect-graph-weight-mode", "deps");
function getModuleWeight(mod, mode) {
  const value = 10 + (mode === "deps" ? Math.min(mod.deps.length, 30) : Math.min(mod.plugins.reduce((total, plg) => total + (plg[mode] || 0), 0) / 20, 30));
  return value;
}

/* Injected with object hook! */

const _hoisted_1$f = {
  key: 0,
  "my-auto": "",
  "text-sm": "",
  "font-mono": "",
  flex: "~ items-center"
};
const _hoisted_2$e = /* @__PURE__ */ createBaseVNode("span", { class: "op50" }, ".", -1);
const _hoisted_3$a = { key: 1 };
const _sfc_main$g = /* @__PURE__ */ defineComponent({
  __name: "ModuleId",
  props: {
    id: {}
  },
  setup(__props) {
    const props = __props;
    const isVirtual = computed(() => list.value?.modules.find((i) => i.id === props.id)?.virtual);
    return (_ctx, _cache) => {
      const _component_Badge = __unplugin_components_5;
      return _ctx.id ? (openBlock(), createElementBlock("div", _hoisted_1$f, [
        _ctx.id.startsWith(unref(root)) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
          _hoisted_2$e,
          createBaseVNode("span", null, toDisplayString(_ctx.id.slice(unref(root).length)), 1)
        ], 64)) : (openBlock(), createElementBlock("span", _hoisted_3$a, toDisplayString(_ctx.id), 1)),
        renderSlot(_ctx.$slots, "default"),
        isVirtual.value ? (openBlock(), createBlock(_component_Badge, {
          key: 2,
          class: "ml1 bg-teal-400:10 text-green-700 dark:text-teal-400",
          textContent: "virtual"
        })) : createCommentVNode("", true)
      ])) : createCommentVNode("", true);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$e = {
  key: 0,
  class: "h-full"
};
const _hoisted_2$d = {
  key: 0,
  "px-6": "",
  "py-4": "",
  italic: "",
  op50: ""
};
const _hoisted_3$9 = { key: 0 };
const _hoisted_4$9 = { key: 1 };
const _hoisted_5$9 = /* @__PURE__ */ createBaseVNode("a", {
  href: "/",
  target: "_blank"
}, "your app", -1);
const _hoisted_6$8 = {
  key: 0,
  "text-xs": "",
  flex: "~ gap-1"
};
const _hoisted_7$7 = {
  key: 0,
  op20: ""
};
const _hoisted_8$5 = { op50: "" };
const _hoisted_9$5 = /* @__PURE__ */ createBaseVNode("span", { op40: "" }, "·", -1);
const _hoisted_10$4 = ["title"];
const _hoisted_11$3 = /* @__PURE__ */ createBaseVNode("div", { "flex-auto": "" }, null, -1);
const _hoisted_12$2 = { op75: "" };
const _hoisted_13$2 = /* @__PURE__ */ createBaseVNode("span", { op40: "" }, "·", -1);
const _hoisted_14$2 = { op50: "" };
const _hoisted_15$2 = /* @__PURE__ */ createBaseVNode("span", {
  "i-carbon-arrow-right": "",
  op40: ""
}, null, -1);
const _sfc_main$f = /* @__PURE__ */ defineComponent({
  __name: "ModuleList",
  props: {
    modules: {}
  },
  setup(__props) {
    const props = __props;
    const { list, containerProps, wrapperProps } = useVirtualList(
      toRef$1(props, "modules"),
      {
        itemHeight: listMode.value === "detailed" ? 53 : 37
      }
    );
    function byteToHumanReadable(byte) {
      if (byte < 1024)
        return `${byte}B`;
      if (byte < 1024 * 1024)
        return `${(byte / 1024).toFixed(2)}KB`;
      if (byte < 1024 * 1024 * 1024)
        return `${(byte / 1024 / 1024).toFixed(2)}MB`;
      return `${(byte / 1024 / 1024 / 1024).toFixed(2)}GB`;
    }
    return (_ctx, _cache) => {
      const _component_ModuleId = _sfc_main$g;
      const _component_PluginName = _sfc_main$i;
      const _component_DurationDisplay = _sfc_main$j;
      const _component_RouterLink = resolveComponent("RouterLink");
      return _ctx.modules ? (openBlock(), createElementBlock("div", _hoisted_1$e, [
        !_ctx.modules.length ? (openBlock(), createElementBlock("div", _hoisted_2$d, [
          unref(searchText) ? (openBlock(), createElementBlock("div", _hoisted_3$9, " No search result ")) : (openBlock(), createElementBlock("div", _hoisted_4$9, [
            createTextVNode(" No module recorded yet, visit "),
            _hoisted_5$9,
            createTextVNode(" first and then refresh this page. ")
          ]))
        ])) : (openBlock(), createElementBlock("div", mergeProps({ key: 1 }, unref(containerProps), { class: "h-full" }), [
          createBaseVNode("div", normalizeProps(guardReactiveProps(unref(wrapperProps))), [
            (openBlock(true), createElementBlock(Fragment, null, renderList(unref(list), (m) => {
              return openBlock(), createBlock(_component_RouterLink, {
                key: m.data.id,
                class: "block border-b border-main px-3 py-2 text-left text-sm font-mono",
                to: `/module?id=${encodeURIComponent(m.data.id)}`
              }, {
                default: withCtx(() => [
                  createVNode(_component_ModuleId, {
                    id: m.data.id
                  }, null, 8, ["id"]),
                  unref(listMode) === "detailed" ? (openBlock(), createElementBlock("div", _hoisted_6$8, [
                    (openBlock(true), createElementBlock(Fragment, null, renderList(m.data.plugins.slice(1).filter((plugin) => plugin.transform !== void 0), (i, idx) => {
                      return openBlock(), createElementBlock(Fragment, { key: i }, [
                        idx !== 0 ? (openBlock(), createElementBlock("span", _hoisted_7$7, "|")) : createCommentVNode("", true),
                        createBaseVNode("span", _hoisted_8$5, [
                          createVNode(_component_PluginName, {
                            name: i.name,
                            hide: true
                          }, null, 8, ["name"])
                        ])
                      ], 64);
                    }), 128)),
                    m.data.invokeCount > 2 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
                      _hoisted_9$5,
                      createBaseVNode("span", {
                        "text-green": "",
                        title: `Transform invoked ${m.data.invokeCount} times`
                      }, "x" + toDisplayString(m.data.invokeCount), 9, _hoisted_10$4)
                    ], 64)) : createCommentVNode("", true),
                    _hoisted_11$3,
                    createBaseVNode("span", _hoisted_12$2, [
                      createVNode(_component_DurationDisplay, {
                        duration: m.data.totalTime
                      }, null, 8, ["duration"])
                    ]),
                    m.data.sourceSize && m.data.distSize ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
                      _hoisted_13$2,
                      createBaseVNode("span", _hoisted_14$2, toDisplayString(byteToHumanReadable(m.data.sourceSize)), 1),
                      _hoisted_15$2,
                      createBaseVNode("span", {
                        op50: "",
                        class: normalizeClass(m.data.distSize > m.data.sourceSize ? "text-orange" : "text-green")
                      }, toDisplayString(byteToHumanReadable(m.data.distSize)), 3)
                    ], 64)) : createCommentVNode("", true)
                  ])) : createCommentVNode("", true)
                ]),
                _: 2
              }, 1032, ["to"]);
            }), 128))
          ], 16)
        ], 16))
      ])) : createCommentVNode("", true);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$d = { flex: "~ gap-1" };
const _hoisted_2$c = ["id", "name", "checked", "value"];
const _sfc_main$e = /* @__PURE__ */ defineComponent({
  __name: "RadioGroup",
  props: {
    name: {},
    modelValue: {},
    options: {}
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const emit = __emit;
    function onChange(e) {
      const target = e.target;
      emit("update:modelValue", target.value);
    }
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$d, [
        (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.options, (opt) => {
          return openBlock(), createElementBlock("label", {
            key: opt.value,
            flex: "~ gap-2"
          }, [
            createBaseVNode("input", {
              id: opt.value,
              name: _ctx.name,
              checked: _ctx.modelValue === opt.value,
              value: opt.value,
              type: "radio",
              onChange
            }, null, 40, _hoisted_2$c),
            createBaseVNode("div", null, toDisplayString(opt.label), 1)
          ]);
        }), 128))
      ]);
    };
  }
});

/* Injected with object hook! */

/**
 * vis-data
 * http://visjs.org/
 *
 * Manage unstructured data using DataSet. Add, update, and remove data, and listen for changes in the data.
 *
 * @version 7.1.7
 * @date    2023-09-13T18:13:28.258Z
 *
 * @copyright (c) 2011-2017 Almende B.V, http://almende.com
 * @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs
 *
 * @license
 * vis.js is dual licensed under both
 *
 *   1. The Apache 2.0 License
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   and
 *
 *   2. The MIT License
 *      http://opensource.org/licenses/MIT
 *
 * vis.js may be distributed under either license.
 */

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

var commonjsGlobal$2 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function getDefaultExportFromCjs$2 (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

var defineProperty$f$1 = {exports: {}};

var check$1 = function (it) {
  return it && it.Math == Math && it;
};

// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global$m =
  // eslint-disable-next-line es/no-global-this -- safe
  check$1(typeof globalThis == 'object' && globalThis) ||
  check$1(typeof window == 'object' && window) ||
  // eslint-disable-next-line no-restricted-globals -- safe
  check$1(typeof self == 'object' && self) ||
  check$1(typeof commonjsGlobal$2 == 'object' && commonjsGlobal$2) ||
  // eslint-disable-next-line no-new-func -- fallback
  (function () { return this; })() || Function('return this')();

var fails$t$1 = function (exec) {
  try {
    return !!exec();
  } catch (error) {
    return true;
  }
};

var fails$s$1 = fails$t$1;

var functionBindNative$1 = !fails$s$1(function () {
  // eslint-disable-next-line es/no-function-prototype-bind -- safe
  var test = (function () { /* empty */ }).bind();
  // eslint-disable-next-line no-prototype-builtins -- safe
  return typeof test != 'function' || test.hasOwnProperty('prototype');
});

var NATIVE_BIND$4$1 = functionBindNative$1;

var FunctionPrototype$3$1 = Function.prototype;
var apply$6 = FunctionPrototype$3$1.apply;
var call$k = FunctionPrototype$3$1.call;

// eslint-disable-next-line es/no-reflect -- safe
var functionApply$1 = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND$4$1 ? call$k.bind(apply$6) : function () {
  return call$k.apply(apply$6, arguments);
});

var NATIVE_BIND$3$1 = functionBindNative$1;

var FunctionPrototype$2$1 = Function.prototype;
var call$j = FunctionPrototype$2$1.call;
var uncurryThisWithBind$1 = NATIVE_BIND$3$1 && FunctionPrototype$2$1.bind.bind(call$j, call$j);

var functionUncurryThis$1 = NATIVE_BIND$3$1 ? uncurryThisWithBind$1 : function (fn) {
  return function () {
    return call$j.apply(fn, arguments);
  };
};

var uncurryThis$q$1 = functionUncurryThis$1;

var toString$9$1 = uncurryThis$q$1({}.toString);
var stringSlice$1$1 = uncurryThis$q$1(''.slice);

var classofRaw$2$1 = function (it) {
  return stringSlice$1$1(toString$9$1(it), 8, -1);
};

var classofRaw$1$1 = classofRaw$2$1;
var uncurryThis$p$1 = functionUncurryThis$1;

var functionUncurryThisClause$1 = function (fn) {
  // Nashorn bug:
  //   https://github.com/zloirock/core-js/issues/1128
  //   https://github.com/zloirock/core-js/issues/1130
  if (classofRaw$1$1(fn) === 'Function') return uncurryThis$p$1(fn);
};

var documentAll$2$1 = typeof document == 'object' && document.all;

// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
var IS_HTMLDDA$1 = typeof documentAll$2$1 == 'undefined' && documentAll$2$1 !== undefined;

var documentAll_1$1 = {
  all: documentAll$2$1,
  IS_HTMLDDA: IS_HTMLDDA$1
};

var $documentAll$1$1 = documentAll_1$1;

var documentAll$1$1 = $documentAll$1$1.all;

// `IsCallable` abstract operation
// https://tc39.es/ecma262/#sec-iscallable
var isCallable$m = $documentAll$1$1.IS_HTMLDDA ? function (argument) {
  return typeof argument == 'function' || argument === documentAll$1$1;
} : function (argument) {
  return typeof argument == 'function';
};

var objectGetOwnPropertyDescriptor$1 = {};

var fails$r$1 = fails$t$1;

// Detect IE8's incomplete defineProperty implementation
var descriptors$1 = !fails$r$1(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
});

var NATIVE_BIND$2$1 = functionBindNative$1;

var call$i = Function.prototype.call;

var functionCall$1 = NATIVE_BIND$2$1 ? call$i.bind(call$i) : function () {
  return call$i.apply(call$i, arguments);
};

var objectPropertyIsEnumerable$1 = {};

var $propertyIsEnumerable$1$1 = {}.propertyIsEnumerable;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor$7$1 = Object.getOwnPropertyDescriptor;

// Nashorn ~ JDK8 bug
var NASHORN_BUG$1 = getOwnPropertyDescriptor$7$1 && !$propertyIsEnumerable$1$1.call({ 1: 2 }, 1);

// `Object.prototype.propertyIsEnumerable` method implementation
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
objectPropertyIsEnumerable$1.f = NASHORN_BUG$1 ? function propertyIsEnumerable(V) {
  var descriptor = getOwnPropertyDescriptor$7$1(this, V);
  return !!descriptor && descriptor.enumerable;
} : $propertyIsEnumerable$1$1;

var createPropertyDescriptor$7 = function (bitmap, value) {
  return {
    enumerable: !(bitmap & 1),
    configurable: !(bitmap & 2),
    writable: !(bitmap & 4),
    value: value
  };
};

var uncurryThis$o$1 = functionUncurryThis$1;
var fails$q$1 = fails$t$1;
var classof$f = classofRaw$2$1;

var $Object$4$1 = Object;
var split$1 = uncurryThis$o$1(''.split);

// fallback for non-array-like ES3 and non-enumerable old V8 strings
var indexedObject$1 = fails$q$1(function () {
  // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
  // eslint-disable-next-line no-prototype-builtins -- safe
  return !$Object$4$1('z').propertyIsEnumerable(0);
}) ? function (it) {
  return classof$f(it) == 'String' ? split$1(it, '') : $Object$4$1(it);
} : $Object$4$1;

// we can't use just `it == null` since of `document.all` special case
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
var isNullOrUndefined$5$1 = function (it) {
  return it === null || it === undefined;
};

var isNullOrUndefined$4$1 = isNullOrUndefined$5$1;

var $TypeError$g$1 = TypeError;

// `RequireObjectCoercible` abstract operation
// https://tc39.es/ecma262/#sec-requireobjectcoercible
var requireObjectCoercible$3$1 = function (it) {
  if (isNullOrUndefined$4$1(it)) throw $TypeError$g$1("Can't call method on " + it);
  return it;
};

// toObject with fallback for non-array-like ES3 strings
var IndexedObject$3$1 = indexedObject$1;
var requireObjectCoercible$2$1 = requireObjectCoercible$3$1;

var toIndexedObject$a$1 = function (it) {
  return IndexedObject$3$1(requireObjectCoercible$2$1(it));
};

var isCallable$l = isCallable$m;
var $documentAll$2 = documentAll_1$1;

var documentAll$3 = $documentAll$2.all;

var isObject$h$1 = $documentAll$2.IS_HTMLDDA ? function (it) {
  return typeof it == 'object' ? it !== null : isCallable$l(it) || it === documentAll$3;
} : function (it) {
  return typeof it == 'object' ? it !== null : isCallable$l(it);
};

var path$o$1 = {};

var path$n$1 = path$o$1;
var global$l$1 = global$m;
var isCallable$k = isCallable$m;

var aFunction$1 = function (variable) {
  return isCallable$k(variable) ? variable : undefined;
};

var getBuiltIn$f = function (namespace, method) {
  return arguments.length < 2 ? aFunction$1(path$n$1[namespace]) || aFunction$1(global$l$1[namespace])
    : path$n$1[namespace] && path$n$1[namespace][method] || global$l$1[namespace] && global$l$1[namespace][method];
};

var uncurryThis$n$1 = functionUncurryThis$1;

var objectIsPrototypeOf$1 = uncurryThis$n$1({}.isPrototypeOf);

var engineUserAgent$1 = typeof navigator != 'undefined' && String(navigator.userAgent) || '';

var global$k$1 = global$m;
var userAgent$5 = engineUserAgent$1;

var process$4 = global$k$1.process;
var Deno$1$1 = global$k$1.Deno;
var versions$1 = process$4 && process$4.versions || Deno$1$1 && Deno$1$1.version;
var v8$1 = versions$1 && versions$1.v8;
var match$1, version$1;

if (v8$1) {
  match$1 = v8$1.split('.');
  // in old Chrome, versions of V8 isn't V8 = Chrome / 10
  // but their correct versions are not interesting for us
  version$1 = match$1[0] > 0 && match$1[0] < 4 ? 1 : +(match$1[0] + match$1[1]);
}

// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
// so check `userAgent` even if `.v8` exists, but 0
if (!version$1 && userAgent$5) {
  match$1 = userAgent$5.match(/Edge\/(\d+)/);
  if (!match$1 || match$1[1] >= 74) {
    match$1 = userAgent$5.match(/Chrome\/(\d+)/);
    if (match$1) version$1 = +match$1[1];
  }
}

var engineV8Version$1 = version$1;

/* eslint-disable es/no-symbol -- required for testing */

var V8_VERSION$3 = engineV8Version$1;
var fails$p$1 = fails$t$1;

// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
var symbolConstructorDetection$1 = !!Object.getOwnPropertySymbols && !fails$p$1(function () {
  var symbol = Symbol();
  // Chrome 38 Symbol has incorrect toString conversion
  // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
  return !String(symbol) || !(Object(symbol) instanceof Symbol) ||
    // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
    !Symbol.sham && V8_VERSION$3 && V8_VERSION$3 < 41;
});

/* eslint-disable es/no-symbol -- required for testing */

var NATIVE_SYMBOL$5$1 = symbolConstructorDetection$1;

var useSymbolAsUid$1 = NATIVE_SYMBOL$5$1
  && !Symbol.sham
  && typeof Symbol.iterator == 'symbol';

var getBuiltIn$e = getBuiltIn$f;
var isCallable$j = isCallable$m;
var isPrototypeOf$j$1 = objectIsPrototypeOf$1;
var USE_SYMBOL_AS_UID$1$1 = useSymbolAsUid$1;

var $Object$3$1 = Object;

var isSymbol$5$1 = USE_SYMBOL_AS_UID$1$1 ? function (it) {
  return typeof it == 'symbol';
} : function (it) {
  var $Symbol = getBuiltIn$e('Symbol');
  return isCallable$j($Symbol) && isPrototypeOf$j$1($Symbol.prototype, $Object$3$1(it));
};

var $String$4$1 = String;

var tryToString$6$1 = function (argument) {
  try {
    return $String$4$1(argument);
  } catch (error) {
    return 'Object';
  }
};

var isCallable$i$1 = isCallable$m;
var tryToString$5$1 = tryToString$6$1;

var $TypeError$f$1 = TypeError;

// `Assert: IsCallable(argument) is true`
var aCallable$e = function (argument) {
  if (isCallable$i$1(argument)) return argument;
  throw $TypeError$f$1(tryToString$5$1(argument) + ' is not a function');
};

var aCallable$d = aCallable$e;
var isNullOrUndefined$3$1 = isNullOrUndefined$5$1;

// `GetMethod` abstract operation
// https://tc39.es/ecma262/#sec-getmethod
var getMethod$3$1 = function (V, P) {
  var func = V[P];
  return isNullOrUndefined$3$1(func) ? undefined : aCallable$d(func);
};

var call$h = functionCall$1;
var isCallable$h$1 = isCallable$m;
var isObject$g$1 = isObject$h$1;

var $TypeError$e$1 = TypeError;

// `OrdinaryToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-ordinarytoprimitive
var ordinaryToPrimitive$1$1 = function (input, pref) {
  var fn, val;
  if (pref === 'string' && isCallable$h$1(fn = input.toString) && !isObject$g$1(val = call$h(fn, input))) return val;
  if (isCallable$h$1(fn = input.valueOf) && !isObject$g$1(val = call$h(fn, input))) return val;
  if (pref !== 'string' && isCallable$h$1(fn = input.toString) && !isObject$g$1(val = call$h(fn, input))) return val;
  throw $TypeError$e$1("Can't convert object to primitive value");
};

var shared$7$1 = {exports: {}};

var isPure = true;

var global$j$1 = global$m;

// eslint-disable-next-line es/no-object-defineproperty -- safe
var defineProperty$e$1 = Object.defineProperty;

var defineGlobalProperty$1$1 = function (key, value) {
  try {
    defineProperty$e$1(global$j$1, key, { value: value, configurable: true, writable: true });
  } catch (error) {
    global$j$1[key] = value;
  } return value;
};

var global$i$1 = global$m;
var defineGlobalProperty$2 = defineGlobalProperty$1$1;

var SHARED$1 = '__core-js_shared__';
var store$3$1 = global$i$1[SHARED$1] || defineGlobalProperty$2(SHARED$1, {});

var sharedStore$1 = store$3$1;

var store$2$1 = sharedStore$1;

(shared$7$1.exports = function (key, value) {
  return store$2$1[key] || (store$2$1[key] = value !== undefined ? value : {});
})('versions', []).push({
  version: '3.29.0',
  mode: 'pure' ,
  copyright: '© 2014-2023 Denis Pushkarev (zloirock.ru)',
  license: 'https://github.com/zloirock/core-js/blob/v3.29.0/LICENSE',
  source: 'https://github.com/zloirock/core-js'
});

var sharedExports$1 = shared$7$1.exports;

var requireObjectCoercible$1$1 = requireObjectCoercible$3$1;

var $Object$2$1 = Object;

// `ToObject` abstract operation
// https://tc39.es/ecma262/#sec-toobject
var toObject$d$1 = function (argument) {
  return $Object$2$1(requireObjectCoercible$1$1(argument));
};

var uncurryThis$m$1 = functionUncurryThis$1;
var toObject$c$1 = toObject$d$1;

var hasOwnProperty$1 = uncurryThis$m$1({}.hasOwnProperty);

// `HasOwnProperty` abstract operation
// https://tc39.es/ecma262/#sec-hasownproperty
// eslint-disable-next-line es/no-object-hasown -- safe
var hasOwnProperty_1$1 = Object.hasOwn || function hasOwn(it, key) {
  return hasOwnProperty$1(toObject$c$1(it), key);
};

var uncurryThis$l$1 = functionUncurryThis$1;

var id$1$1 = 0;
var postfix$1 = Math.random();
var toString$8$1 = uncurryThis$l$1(1.0.toString);

var uid$4$1 = function (key) {
  return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$8$1(++id$1$1 + postfix$1, 36);
};

var global$h$1 = global$m;
var shared$6$1 = sharedExports$1;
var hasOwn$j = hasOwnProperty_1$1;
var uid$3$1 = uid$4$1;
var NATIVE_SYMBOL$4$1 = symbolConstructorDetection$1;
var USE_SYMBOL_AS_UID$2 = useSymbolAsUid$1;

var Symbol$3$1 = global$h$1.Symbol;
var WellKnownSymbolsStore$2$1 = shared$6$1('wks');
var createWellKnownSymbol$1 = USE_SYMBOL_AS_UID$2 ? Symbol$3$1['for'] || Symbol$3$1 : Symbol$3$1 && Symbol$3$1.withoutSetter || uid$3$1;

var wellKnownSymbol$m = function (name) {
  if (!hasOwn$j(WellKnownSymbolsStore$2$1, name)) {
    WellKnownSymbolsStore$2$1[name] = NATIVE_SYMBOL$4$1 && hasOwn$j(Symbol$3$1, name)
      ? Symbol$3$1[name]
      : createWellKnownSymbol$1('Symbol.' + name);
  } return WellKnownSymbolsStore$2$1[name];
};

var call$g = functionCall$1;
var isObject$f$1 = isObject$h$1;
var isSymbol$4$1 = isSymbol$5$1;
var getMethod$2$1 = getMethod$3$1;
var ordinaryToPrimitive$2 = ordinaryToPrimitive$1$1;
var wellKnownSymbol$l$1 = wellKnownSymbol$m;

var $TypeError$d$1 = TypeError;
var TO_PRIMITIVE$1 = wellKnownSymbol$l$1('toPrimitive');

// `ToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-toprimitive
var toPrimitive$7$1 = function (input, pref) {
  if (!isObject$f$1(input) || isSymbol$4$1(input)) return input;
  var exoticToPrim = getMethod$2$1(input, TO_PRIMITIVE$1);
  var result;
  if (exoticToPrim) {
    if (pref === undefined) pref = 'default';
    result = call$g(exoticToPrim, input, pref);
    if (!isObject$f$1(result) || isSymbol$4$1(result)) return result;
    throw $TypeError$d$1("Can't convert object to primitive value");
  }
  if (pref === undefined) pref = 'number';
  return ordinaryToPrimitive$2(input, pref);
};

var toPrimitive$6$1 = toPrimitive$7$1;
var isSymbol$3$1 = isSymbol$5$1;

// `ToPropertyKey` abstract operation
// https://tc39.es/ecma262/#sec-topropertykey
var toPropertyKey$4$1 = function (argument) {
  var key = toPrimitive$6$1(argument, 'string');
  return isSymbol$3$1(key) ? key : key + '';
};

var global$g$1 = global$m;
var isObject$e$1 = isObject$h$1;

var document$3 = global$g$1.document;
// typeof document.createElement is 'object' in old IE
var EXISTS$1$1 = isObject$e$1(document$3) && isObject$e$1(document$3.createElement);

var documentCreateElement$1$1 = function (it) {
  return EXISTS$1$1 ? document$3.createElement(it) : {};
};

var DESCRIPTORS$h$1 = descriptors$1;
var fails$o$1 = fails$t$1;
var createElement$1$1 = documentCreateElement$1$1;

// Thanks to IE8 for its funny defineProperty
var ie8DomDefine$1 = !DESCRIPTORS$h$1 && !fails$o$1(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty(createElement$1$1('div'), 'a', {
    get: function () { return 7; }
  }).a != 7;
});

var DESCRIPTORS$g$1 = descriptors$1;
var call$f$1 = functionCall$1;
var propertyIsEnumerableModule$2$1 = objectPropertyIsEnumerable$1;
var createPropertyDescriptor$6 = createPropertyDescriptor$7;
var toIndexedObject$9$1 = toIndexedObject$a$1;
var toPropertyKey$3$1 = toPropertyKey$4$1;
var hasOwn$i$1 = hasOwnProperty_1$1;
var IE8_DOM_DEFINE$1$1 = ie8DomDefine$1;

// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor$2$1 = Object.getOwnPropertyDescriptor;

// `Object.getOwnPropertyDescriptor` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
objectGetOwnPropertyDescriptor$1.f = DESCRIPTORS$g$1 ? $getOwnPropertyDescriptor$2$1 : function getOwnPropertyDescriptor(O, P) {
  O = toIndexedObject$9$1(O);
  P = toPropertyKey$3$1(P);
  if (IE8_DOM_DEFINE$1$1) try {
    return $getOwnPropertyDescriptor$2$1(O, P);
  } catch (error) { /* empty */ }
  if (hasOwn$i$1(O, P)) return createPropertyDescriptor$6(!call$f$1(propertyIsEnumerableModule$2$1.f, O, P), O[P]);
};

var fails$n$1 = fails$t$1;
var isCallable$g$1 = isCallable$m;

var replacement$1 = /#|\.prototype\./;

var isForced$2 = function (feature, detection) {
  var value = data$1[normalize$3(feature)];
  return value == POLYFILL$1 ? true
    : value == NATIVE$1 ? false
    : isCallable$g$1(detection) ? fails$n$1(detection)
    : !!detection;
};

var normalize$3 = isForced$2.normalize = function (string) {
  return String(string).replace(replacement$1, '.').toLowerCase();
};

var data$1 = isForced$2.data = {};
var NATIVE$1 = isForced$2.NATIVE = 'N';
var POLYFILL$1 = isForced$2.POLYFILL = 'P';

var isForced_1$1 = isForced$2;

var uncurryThis$k$1 = functionUncurryThisClause$1;
var aCallable$c = aCallable$e;
var NATIVE_BIND$1$1 = functionBindNative$1;

var bind$j = uncurryThis$k$1(uncurryThis$k$1.bind);

// optional / simple context binding
var functionBindContext$1 = function (fn, that) {
  aCallable$c(fn);
  return that === undefined ? fn : NATIVE_BIND$1$1 ? bind$j(fn, that) : function (/* ...args */) {
    return fn.apply(that, arguments);
  };
};

var objectDefineProperty$1 = {};

var DESCRIPTORS$f$1 = descriptors$1;
var fails$m$1 = fails$t$1;

// V8 ~ Chrome 36-
// https://bugs.chromium.org/p/v8/issues/detail?id=3334
var v8PrototypeDefineBug$1 = DESCRIPTORS$f$1 && fails$m$1(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty(function () { /* empty */ }, 'prototype', {
    value: 42,
    writable: false
  }).prototype != 42;
});

var isObject$d$1 = isObject$h$1;

var $String$3$1 = String;
var $TypeError$c$1 = TypeError;

// `Assert: Type(argument) is Object`
var anObject$d$1 = function (argument) {
  if (isObject$d$1(argument)) return argument;
  throw $TypeError$c$1($String$3$1(argument) + ' is not an object');
};

var DESCRIPTORS$e$1 = descriptors$1;
var IE8_DOM_DEFINE$2 = ie8DomDefine$1;
var V8_PROTOTYPE_DEFINE_BUG$1$1 = v8PrototypeDefineBug$1;
var anObject$c$1 = anObject$d$1;
var toPropertyKey$2$1 = toPropertyKey$4$1;

var $TypeError$b$1 = TypeError;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var $defineProperty$1$1 = Object.defineProperty;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor$1$1 = Object.getOwnPropertyDescriptor;
var ENUMERABLE$1 = 'enumerable';
var CONFIGURABLE$1$1 = 'configurable';
var WRITABLE$1 = 'writable';

// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
objectDefineProperty$1.f = DESCRIPTORS$e$1 ? V8_PROTOTYPE_DEFINE_BUG$1$1 ? function defineProperty(O, P, Attributes) {
  anObject$c$1(O);
  P = toPropertyKey$2$1(P);
  anObject$c$1(Attributes);
  if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE$1 in Attributes && !Attributes[WRITABLE$1]) {
    var current = $getOwnPropertyDescriptor$1$1(O, P);
    if (current && current[WRITABLE$1]) {
      O[P] = Attributes.value;
      Attributes = {
        configurable: CONFIGURABLE$1$1 in Attributes ? Attributes[CONFIGURABLE$1$1] : current[CONFIGURABLE$1$1],
        enumerable: ENUMERABLE$1 in Attributes ? Attributes[ENUMERABLE$1] : current[ENUMERABLE$1],
        writable: false
      };
    }
  } return $defineProperty$1$1(O, P, Attributes);
} : $defineProperty$1$1 : function defineProperty(O, P, Attributes) {
  anObject$c$1(O);
  P = toPropertyKey$2$1(P);
  anObject$c$1(Attributes);
  if (IE8_DOM_DEFINE$2) try {
    return $defineProperty$1$1(O, P, Attributes);
  } catch (error) { /* empty */ }
  if ('get' in Attributes || 'set' in Attributes) throw $TypeError$b$1('Accessors not supported');
  if ('value' in Attributes) O[P] = Attributes.value;
  return O;
};

var DESCRIPTORS$d$1 = descriptors$1;
var definePropertyModule$4 = objectDefineProperty$1;
var createPropertyDescriptor$5$1 = createPropertyDescriptor$7;

var createNonEnumerableProperty$9 = DESCRIPTORS$d$1 ? function (object, key, value) {
  return definePropertyModule$4.f(object, key, createPropertyDescriptor$5$1(1, value));
} : function (object, key, value) {
  object[key] = value;
  return object;
};

var global$f$1 = global$m;
var apply$5$1 = functionApply$1;
var uncurryThis$j$1 = functionUncurryThisClause$1;
var isCallable$f$1 = isCallable$m;
var getOwnPropertyDescriptor$6$1 = objectGetOwnPropertyDescriptor$1.f;
var isForced$1$1 = isForced_1$1;
var path$m$1 = path$o$1;
var bind$i = functionBindContext$1;
var createNonEnumerableProperty$8 = createNonEnumerableProperty$9;
var hasOwn$h$1 = hasOwnProperty_1$1;

var wrapConstructor$1 = function (NativeConstructor) {
  var Wrapper = function (a, b, c) {
    if (this instanceof Wrapper) {
      switch (arguments.length) {
        case 0: return new NativeConstructor();
        case 1: return new NativeConstructor(a);
        case 2: return new NativeConstructor(a, b);
      } return new NativeConstructor(a, b, c);
    } return apply$5$1(NativeConstructor, this, arguments);
  };
  Wrapper.prototype = NativeConstructor.prototype;
  return Wrapper;
};

/*
  options.target         - name of the target object
  options.global         - target is the global object
  options.stat           - export as static methods of target
  options.proto          - export as prototype methods of target
  options.real           - real prototype method for the `pure` version
  options.forced         - export even if the native feature is available
  options.bind           - bind methods to the target, required for the `pure` version
  options.wrap           - wrap constructors to preventing global pollution, required for the `pure` version
  options.unsafe         - use the simple assignment of property instead of delete + defineProperty
  options.sham           - add a flag to not completely full polyfills
  options.enumerable     - export as enumerable property
  options.dontCallGetSet - prevent calling a getter on target
  options.name           - the .name of the function if it does not match the key
*/
var _export$1 = function (options, source) {
  var TARGET = options.target;
  var GLOBAL = options.global;
  var STATIC = options.stat;
  var PROTO = options.proto;

  var nativeSource = GLOBAL ? global$f$1 : STATIC ? global$f$1[TARGET] : (global$f$1[TARGET] || {}).prototype;

  var target = GLOBAL ? path$m$1 : path$m$1[TARGET] || createNonEnumerableProperty$8(path$m$1, TARGET, {})[TARGET];
  var targetPrototype = target.prototype;

  var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE;
  var key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor;

  for (key in source) {
    FORCED = isForced$1$1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
    // contains in native
    USE_NATIVE = !FORCED && nativeSource && hasOwn$h$1(nativeSource, key);

    targetProperty = target[key];

    if (USE_NATIVE) if (options.dontCallGetSet) {
      descriptor = getOwnPropertyDescriptor$6$1(nativeSource, key);
      nativeProperty = descriptor && descriptor.value;
    } else nativeProperty = nativeSource[key];

    // export native or implementation
    sourceProperty = (USE_NATIVE && nativeProperty) ? nativeProperty : source[key];

    if (USE_NATIVE && typeof targetProperty == typeof sourceProperty) continue;

    // bind methods to global for calling from export context
    if (options.bind && USE_NATIVE) resultProperty = bind$i(sourceProperty, global$f$1);
    // wrap global constructors for prevent changes in this version
    else if (options.wrap && USE_NATIVE) resultProperty = wrapConstructor$1(sourceProperty);
    // make static versions for prototype methods
    else if (PROTO && isCallable$f$1(sourceProperty)) resultProperty = uncurryThis$j$1(sourceProperty);
    // default case
    else resultProperty = sourceProperty;

    // add a flag to not completely full polyfills
    if (options.sham || (sourceProperty && sourceProperty.sham) || (targetProperty && targetProperty.sham)) {
      createNonEnumerableProperty$8(resultProperty, 'sham', true);
    }

    createNonEnumerableProperty$8(target, key, resultProperty);

    if (PROTO) {
      VIRTUAL_PROTOTYPE = TARGET + 'Prototype';
      if (!hasOwn$h$1(path$m$1, VIRTUAL_PROTOTYPE)) {
        createNonEnumerableProperty$8(path$m$1, VIRTUAL_PROTOTYPE, {});
      }
      // export virtual prototype methods
      createNonEnumerableProperty$8(path$m$1[VIRTUAL_PROTOTYPE], key, sourceProperty);
      // export real prototype methods
      if (options.real && targetPrototype && (FORCED || !targetPrototype[key])) {
        createNonEnumerableProperty$8(targetPrototype, key, sourceProperty);
      }
    }
  }
};

var $$L$1 = _export$1;
var DESCRIPTORS$c$1 = descriptors$1;
var defineProperty$d$1 = objectDefineProperty$1.f;

// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
// eslint-disable-next-line es/no-object-defineproperty -- safe
$$L$1({ target: 'Object', stat: true, forced: Object.defineProperty !== defineProperty$d$1, sham: !DESCRIPTORS$c$1 }, {
  defineProperty: defineProperty$d$1
});

var path$l$1 = path$o$1;

var Object$4$1 = path$l$1.Object;

var defineProperty$c$1 = defineProperty$f$1.exports = function defineProperty(it, key, desc) {
  return Object$4$1.defineProperty(it, key, desc);
};

if (Object$4$1.defineProperty.sham) defineProperty$c$1.sham = true;

var definePropertyExports$4 = defineProperty$f$1.exports;

var parent$15$1 = definePropertyExports$4;

var defineProperty$b$1 = parent$15$1;

var parent$14$1 = defineProperty$b$1;

var defineProperty$a$1 = parent$14$1;

var parent$13$1 = defineProperty$a$1;

var defineProperty$9$1 = parent$13$1;

var defineProperty$8$1 = defineProperty$9$1;

var defineProperty$7$1 = defineProperty$8$1;

var _Object$defineProperty$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(defineProperty$7$1);

var classof$e$1 = classofRaw$2$1;

// `IsArray` abstract operation
// https://tc39.es/ecma262/#sec-isarray
// eslint-disable-next-line es/no-array-isarray -- safe
var isArray$f$1 = Array.isArray || function isArray(argument) {
  return classof$e$1(argument) == 'Array';
};

var ceil$1 = Math.ceil;
var floor$1$1 = Math.floor;

// `Math.trunc` method
// https://tc39.es/ecma262/#sec-math.trunc
// eslint-disable-next-line es/no-math-trunc -- safe
var mathTrunc$1 = Math.trunc || function trunc(x) {
  var n = +x;
  return (n > 0 ? floor$1$1 : ceil$1)(n);
};

var trunc$1 = mathTrunc$1;

// `ToIntegerOrInfinity` abstract operation
// https://tc39.es/ecma262/#sec-tointegerorinfinity
var toIntegerOrInfinity$4$1 = function (argument) {
  var number = +argument;
  // eslint-disable-next-line no-self-compare -- NaN check
  return number !== number || number === 0 ? 0 : trunc$1(number);
};

var toIntegerOrInfinity$3$1 = toIntegerOrInfinity$4$1;

var min$2$1 = Math.min;

// `ToLength` abstract operation
// https://tc39.es/ecma262/#sec-tolength
var toLength$1$1 = function (argument) {
  return argument > 0 ? min$2$1(toIntegerOrInfinity$3$1(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
};

var toLength$2 = toLength$1$1;

// `LengthOfArrayLike` abstract operation
// https://tc39.es/ecma262/#sec-lengthofarraylike
var lengthOfArrayLike$c = function (obj) {
  return toLength$2(obj.length);
};

var $TypeError$a$1 = TypeError;
var MAX_SAFE_INTEGER$1 = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991

var doesNotExceedSafeInteger$3 = function (it) {
  if (it > MAX_SAFE_INTEGER$1) throw $TypeError$a$1('Maximum allowed index exceeded');
  return it;
};

var toPropertyKey$1$1 = toPropertyKey$4$1;
var definePropertyModule$3$1 = objectDefineProperty$1;
var createPropertyDescriptor$4$1 = createPropertyDescriptor$7;

var createProperty$6$1 = function (object, key, value) {
  var propertyKey = toPropertyKey$1$1(key);
  if (propertyKey in object) definePropertyModule$3$1.f(object, propertyKey, createPropertyDescriptor$4$1(0, value));
  else object[propertyKey] = value;
};

var wellKnownSymbol$k$1 = wellKnownSymbol$m;

var TO_STRING_TAG$4 = wellKnownSymbol$k$1('toStringTag');
var test$2$1 = {};

test$2$1[TO_STRING_TAG$4] = 'z';

var toStringTagSupport$1 = String(test$2$1) === '[object z]';

var TO_STRING_TAG_SUPPORT$2$1 = toStringTagSupport$1;
var isCallable$e$1 = isCallable$m;
var classofRaw$3 = classofRaw$2$1;
var wellKnownSymbol$j$1 = wellKnownSymbol$m;

var TO_STRING_TAG$3$1 = wellKnownSymbol$j$1('toStringTag');
var $Object$1$1 = Object;

// ES3 wrong here
var CORRECT_ARGUMENTS$1 = classofRaw$3(function () { return arguments; }()) == 'Arguments';

// fallback for IE11 Script Access Denied error
var tryGet$1 = function (it, key) {
  try {
    return it[key];
  } catch (error) { /* empty */ }
};

// getting tag from ES6+ `Object.prototype.toString`
var classof$d$1 = TO_STRING_TAG_SUPPORT$2$1 ? classofRaw$3 : function (it) {
  var O, tag, result;
  return it === undefined ? 'Undefined' : it === null ? 'Null'
    // @@toStringTag case
    : typeof (tag = tryGet$1(O = $Object$1$1(it), TO_STRING_TAG$3$1)) == 'string' ? tag
    // builtinTag case
    : CORRECT_ARGUMENTS$1 ? classofRaw$3(O)
    // ES3 arguments fallback
    : (result = classofRaw$3(O)) == 'Object' && isCallable$e$1(O.callee) ? 'Arguments' : result;
};

var uncurryThis$i$1 = functionUncurryThis$1;
var isCallable$d$1 = isCallable$m;
var store$1$1 = sharedStore$1;

var functionToString$1 = uncurryThis$i$1(Function.toString);

// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
if (!isCallable$d$1(store$1$1.inspectSource)) {
  store$1$1.inspectSource = function (it) {
    return functionToString$1(it);
  };
}

var inspectSource$2 = store$1$1.inspectSource;

var uncurryThis$h$1 = functionUncurryThis$1;
var fails$l$1 = fails$t$1;
var isCallable$c$1 = isCallable$m;
var classof$c$1 = classof$d$1;
var getBuiltIn$d = getBuiltIn$f;
var inspectSource$1$1 = inspectSource$2;

var noop$2 = function () { /* empty */ };
var empty$1 = [];
var construct$4$1 = getBuiltIn$d('Reflect', 'construct');
var constructorRegExp$1 = /^\s*(?:class|function)\b/;
var exec$1$1 = uncurryThis$h$1(constructorRegExp$1.exec);
var INCORRECT_TO_STRING$1 = !constructorRegExp$1.exec(noop$2);

var isConstructorModern$1 = function isConstructor(argument) {
  if (!isCallable$c$1(argument)) return false;
  try {
    construct$4$1(noop$2, empty$1, argument);
    return true;
  } catch (error) {
    return false;
  }
};

var isConstructorLegacy$1 = function isConstructor(argument) {
  if (!isCallable$c$1(argument)) return false;
  switch (classof$c$1(argument)) {
    case 'AsyncFunction':
    case 'GeneratorFunction':
    case 'AsyncGeneratorFunction': return false;
  }
  try {
    // we can't check .prototype since constructors produced by .bind haven't it
    // `Function#toString` throws on some built-it function in some legacy engines
    // (for example, `DOMQuad` and similar in FF41-)
    return INCORRECT_TO_STRING$1 || !!exec$1$1(constructorRegExp$1, inspectSource$1$1(argument));
  } catch (error) {
    return true;
  }
};

isConstructorLegacy$1.sham = true;

// `IsConstructor` abstract operation
// https://tc39.es/ecma262/#sec-isconstructor
var isConstructor$4$1 = !construct$4$1 || fails$l$1(function () {
  var called;
  return isConstructorModern$1(isConstructorModern$1.call)
    || !isConstructorModern$1(Object)
    || !isConstructorModern$1(function () { called = true; })
    || called;
}) ? isConstructorLegacy$1 : isConstructorModern$1;

var isArray$e$1 = isArray$f$1;
var isConstructor$3$1 = isConstructor$4$1;
var isObject$c$1 = isObject$h$1;
var wellKnownSymbol$i$1 = wellKnownSymbol$m;

var SPECIES$5 = wellKnownSymbol$i$1('species');
var $Array$3$1 = Array;

// a part of `ArraySpeciesCreate` abstract operation
// https://tc39.es/ecma262/#sec-arrayspeciescreate
var arraySpeciesConstructor$1$1 = function (originalArray) {
  var C;
  if (isArray$e$1(originalArray)) {
    C = originalArray.constructor;
    // cross-realm fallback
    if (isConstructor$3$1(C) && (C === $Array$3$1 || isArray$e$1(C.prototype))) C = undefined;
    else if (isObject$c$1(C)) {
      C = C[SPECIES$5];
      if (C === null) C = undefined;
    }
  } return C === undefined ? $Array$3$1 : C;
};

var arraySpeciesConstructor$2 = arraySpeciesConstructor$1$1;

// `ArraySpeciesCreate` abstract operation
// https://tc39.es/ecma262/#sec-arrayspeciescreate
var arraySpeciesCreate$4 = function (originalArray, length) {
  return new (arraySpeciesConstructor$2(originalArray))(length === 0 ? 0 : length);
};

var fails$k$1 = fails$t$1;
var wellKnownSymbol$h$1 = wellKnownSymbol$m;
var V8_VERSION$2$1 = engineV8Version$1;

var SPECIES$4 = wellKnownSymbol$h$1('species');

var arrayMethodHasSpeciesSupport$5$1 = function (METHOD_NAME) {
  // We can't use this feature detection in V8 since it causes
  // deoptimization and serious performance degradation
  // https://github.com/zloirock/core-js/issues/677
  return V8_VERSION$2$1 >= 51 || !fails$k$1(function () {
    var array = [];
    var constructor = array.constructor = {};
    constructor[SPECIES$4] = function () {
      return { foo: 1 };
    };
    return array[METHOD_NAME](Boolean).foo !== 1;
  });
};

var $$K$1 = _export$1;
var fails$j$1 = fails$t$1;
var isArray$d$1 = isArray$f$1;
var isObject$b$1 = isObject$h$1;
var toObject$b$1 = toObject$d$1;
var lengthOfArrayLike$b$1 = lengthOfArrayLike$c;
var doesNotExceedSafeInteger$2$1 = doesNotExceedSafeInteger$3;
var createProperty$5$1 = createProperty$6$1;
var arraySpeciesCreate$3$1 = arraySpeciesCreate$4;
var arrayMethodHasSpeciesSupport$4$1 = arrayMethodHasSpeciesSupport$5$1;
var wellKnownSymbol$g$1 = wellKnownSymbol$m;
var V8_VERSION$1$1 = engineV8Version$1;

var IS_CONCAT_SPREADABLE$1 = wellKnownSymbol$g$1('isConcatSpreadable');

// We can't use this feature detection in V8 since it causes
// deoptimization and serious performance degradation
// https://github.com/zloirock/core-js/issues/679
var IS_CONCAT_SPREADABLE_SUPPORT$1 = V8_VERSION$1$1 >= 51 || !fails$j$1(function () {
  var array = [];
  array[IS_CONCAT_SPREADABLE$1] = false;
  return array.concat()[0] !== array;
});

var isConcatSpreadable$1 = function (O) {
  if (!isObject$b$1(O)) return false;
  var spreadable = O[IS_CONCAT_SPREADABLE$1];
  return spreadable !== undefined ? !!spreadable : isArray$d$1(O);
};

var FORCED$5$1 = !IS_CONCAT_SPREADABLE_SUPPORT$1 || !arrayMethodHasSpeciesSupport$4$1('concat');

// `Array.prototype.concat` method
// https://tc39.es/ecma262/#sec-array.prototype.concat
// with adding support of @@isConcatSpreadable and @@species
$$K$1({ target: 'Array', proto: true, arity: 1, forced: FORCED$5$1 }, {
  // eslint-disable-next-line no-unused-vars -- required for `.length`
  concat: function concat(arg) {
    var O = toObject$b$1(this);
    var A = arraySpeciesCreate$3$1(O, 0);
    var n = 0;
    var i, k, length, len, E;
    for (i = -1, length = arguments.length; i < length; i++) {
      E = i === -1 ? O : arguments[i];
      if (isConcatSpreadable$1(E)) {
        len = lengthOfArrayLike$b$1(E);
        doesNotExceedSafeInteger$2$1(n + len);
        for (k = 0; k < len; k++, n++) if (k in E) createProperty$5$1(A, n, E[k]);
      } else {
        doesNotExceedSafeInteger$2$1(n + 1);
        createProperty$5$1(A, n++, E);
      }
    }
    A.length = n;
    return A;
  }
});

var classof$b$1 = classof$d$1;

var $String$2$1 = String;

var toString$7$1 = function (argument) {
  if (classof$b$1(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
  return $String$2$1(argument);
};

var objectDefineProperties$1 = {};

var toIntegerOrInfinity$2$1 = toIntegerOrInfinity$4$1;

var max$3$1 = Math.max;
var min$1$2 = Math.min;

// Helper for a popular repeating case of the spec:
// Let integer be ? ToInteger(index).
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
var toAbsoluteIndex$4$1 = function (index, length) {
  var integer = toIntegerOrInfinity$2$1(index);
  return integer < 0 ? max$3$1(integer + length, 0) : min$1$2(integer, length);
};

var toIndexedObject$8$1 = toIndexedObject$a$1;
var toAbsoluteIndex$3$1 = toAbsoluteIndex$4$1;
var lengthOfArrayLike$a$1 = lengthOfArrayLike$c;

// `Array.prototype.{ indexOf, includes }` methods implementation
var createMethod$3$1 = function (IS_INCLUDES) {
  return function ($this, el, fromIndex) {
    var O = toIndexedObject$8$1($this);
    var length = lengthOfArrayLike$a$1(O);
    var index = toAbsoluteIndex$3$1(fromIndex, length);
    var value;
    // Array#includes uses SameValueZero equality algorithm
    // eslint-disable-next-line no-self-compare -- NaN check
    if (IS_INCLUDES && el != el) while (length > index) {
      value = O[index++];
      // eslint-disable-next-line no-self-compare -- NaN check
      if (value != value) return true;
    // Array#indexOf ignores holes, Array#includes - not
    } else for (;length > index; index++) {
      if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
    } return !IS_INCLUDES && -1;
  };
};

var arrayIncludes$1 = {
  // `Array.prototype.includes` method
  // https://tc39.es/ecma262/#sec-array.prototype.includes
  includes: createMethod$3$1(true),
  // `Array.prototype.indexOf` method
  // https://tc39.es/ecma262/#sec-array.prototype.indexof
  indexOf: createMethod$3$1(false)
};

var hiddenKeys$6$1 = {};

var uncurryThis$g$1 = functionUncurryThis$1;
var hasOwn$g$1 = hasOwnProperty_1$1;
var toIndexedObject$7$1 = toIndexedObject$a$1;
var indexOf$6 = arrayIncludes$1.indexOf;
var hiddenKeys$5$1 = hiddenKeys$6$1;

var push$6$1 = uncurryThis$g$1([].push);

var objectKeysInternal$1 = function (object, names) {
  var O = toIndexedObject$7$1(object);
  var i = 0;
  var result = [];
  var key;
  for (key in O) !hasOwn$g$1(hiddenKeys$5$1, key) && hasOwn$g$1(O, key) && push$6$1(result, key);
  // Don't enum bug & hidden keys
  while (names.length > i) if (hasOwn$g$1(O, key = names[i++])) {
    ~indexOf$6(result, key) || push$6$1(result, key);
  }
  return result;
};

// IE8- don't enum bug keys
var enumBugKeys$3$1 = [
  'constructor',
  'hasOwnProperty',
  'isPrototypeOf',
  'propertyIsEnumerable',
  'toLocaleString',
  'toString',
  'valueOf'
];

var internalObjectKeys$1$1 = objectKeysInternal$1;
var enumBugKeys$2$1 = enumBugKeys$3$1;

// `Object.keys` method
// https://tc39.es/ecma262/#sec-object.keys
// eslint-disable-next-line es/no-object-keys -- safe
var objectKeys$3$1 = Object.keys || function keys(O) {
  return internalObjectKeys$1$1(O, enumBugKeys$2$1);
};

var DESCRIPTORS$b$1 = descriptors$1;
var V8_PROTOTYPE_DEFINE_BUG$2 = v8PrototypeDefineBug$1;
var definePropertyModule$2$1 = objectDefineProperty$1;
var anObject$b$1 = anObject$d$1;
var toIndexedObject$6$1 = toIndexedObject$a$1;
var objectKeys$2$1 = objectKeys$3$1;

// `Object.defineProperties` method
// https://tc39.es/ecma262/#sec-object.defineproperties
// eslint-disable-next-line es/no-object-defineproperties -- safe
objectDefineProperties$1.f = DESCRIPTORS$b$1 && !V8_PROTOTYPE_DEFINE_BUG$2 ? Object.defineProperties : function defineProperties(O, Properties) {
  anObject$b$1(O);
  var props = toIndexedObject$6$1(Properties);
  var keys = objectKeys$2$1(Properties);
  var length = keys.length;
  var index = 0;
  var key;
  while (length > index) definePropertyModule$2$1.f(O, key = keys[index++], props[key]);
  return O;
};

var getBuiltIn$c$1 = getBuiltIn$f;

var html$2 = getBuiltIn$c$1('document', 'documentElement');

var shared$5$1 = sharedExports$1;
var uid$2$1 = uid$4$1;

var keys$7 = shared$5$1('keys');

var sharedKey$4$1 = function (key) {
  return keys$7[key] || (keys$7[key] = uid$2$1(key));
};

/* global ActiveXObject -- old IE, WSH */

var anObject$a$1 = anObject$d$1;
var definePropertiesModule$1$1 = objectDefineProperties$1;
var enumBugKeys$1$1 = enumBugKeys$3$1;
var hiddenKeys$4$1 = hiddenKeys$6$1;
var html$1$1 = html$2;
var documentCreateElement$2 = documentCreateElement$1$1;
var sharedKey$3$1 = sharedKey$4$1;

var GT$1 = '>';
var LT$1 = '<';
var PROTOTYPE$1$1 = 'prototype';
var SCRIPT$1 = 'script';
var IE_PROTO$1$1 = sharedKey$3$1('IE_PROTO');

var EmptyConstructor$1 = function () { /* empty */ };

var scriptTag$1 = function (content) {
  return LT$1 + SCRIPT$1 + GT$1 + content + LT$1 + '/' + SCRIPT$1 + GT$1;
};

// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
var NullProtoObjectViaActiveX$1 = function (activeXDocument) {
  activeXDocument.write(scriptTag$1(''));
  activeXDocument.close();
  var temp = activeXDocument.parentWindow.Object;
  activeXDocument = null; // avoid memory leak
  return temp;
};

// Create object with fake `null` prototype: use iframe Object with cleared prototype
var NullProtoObjectViaIFrame$1 = function () {
  // Thrash, waste and sodomy: IE GC bug
  var iframe = documentCreateElement$2('iframe');
  var JS = 'java' + SCRIPT$1 + ':';
  var iframeDocument;
  iframe.style.display = 'none';
  html$1$1.appendChild(iframe);
  // https://github.com/zloirock/core-js/issues/475
  iframe.src = String(JS);
  iframeDocument = iframe.contentWindow.document;
  iframeDocument.open();
  iframeDocument.write(scriptTag$1('document.F=Object'));
  iframeDocument.close();
  return iframeDocument.F;
};

// Check for document.domain and active x support
// No need to use active x approach when document.domain is not set
// see https://github.com/es-shims/es5-shim/issues/150
// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
// avoid IE GC bug
var activeXDocument$1;
var NullProtoObject$1 = function () {
  try {
    activeXDocument$1 = new ActiveXObject('htmlfile');
  } catch (error) { /* ignore */ }
  NullProtoObject$1 = typeof document != 'undefined'
    ? document.domain && activeXDocument$1
      ? NullProtoObjectViaActiveX$1(activeXDocument$1) // old IE
      : NullProtoObjectViaIFrame$1()
    : NullProtoObjectViaActiveX$1(activeXDocument$1); // WSH
  var length = enumBugKeys$1$1.length;
  while (length--) delete NullProtoObject$1[PROTOTYPE$1$1][enumBugKeys$1$1[length]];
  return NullProtoObject$1();
};

hiddenKeys$4$1[IE_PROTO$1$1] = true;

// `Object.create` method
// https://tc39.es/ecma262/#sec-object.create
// eslint-disable-next-line es/no-object-create -- safe
var objectCreate$1 = Object.create || function create(O, Properties) {
  var result;
  if (O !== null) {
    EmptyConstructor$1[PROTOTYPE$1$1] = anObject$a$1(O);
    result = new EmptyConstructor$1();
    EmptyConstructor$1[PROTOTYPE$1$1] = null;
    // add "__proto__" for Object.getPrototypeOf polyfill
    result[IE_PROTO$1$1] = O;
  } else result = NullProtoObject$1();
  return Properties === undefined ? result : definePropertiesModule$1$1.f(result, Properties);
};

var objectGetOwnPropertyNames$1 = {};

var internalObjectKeys$2 = objectKeysInternal$1;
var enumBugKeys$4 = enumBugKeys$3$1;

var hiddenKeys$3$1 = enumBugKeys$4.concat('length', 'prototype');

// `Object.getOwnPropertyNames` method
// https://tc39.es/ecma262/#sec-object.getownpropertynames
// eslint-disable-next-line es/no-object-getownpropertynames -- safe
objectGetOwnPropertyNames$1.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
  return internalObjectKeys$2(O, hiddenKeys$3$1);
};

var objectGetOwnPropertyNamesExternal$1 = {};

var toAbsoluteIndex$2$1 = toAbsoluteIndex$4$1;
var lengthOfArrayLike$9$1 = lengthOfArrayLike$c;
var createProperty$4$1 = createProperty$6$1;

var $Array$2$1 = Array;
var max$2$1 = Math.max;

var arraySliceSimple$1 = function (O, start, end) {
  var length = lengthOfArrayLike$9$1(O);
  var k = toAbsoluteIndex$2$1(start, length);
  var fin = toAbsoluteIndex$2$1(end === undefined ? length : end, length);
  var result = $Array$2$1(max$2$1(fin - k, 0));
  for (var n = 0; k < fin; k++, n++) createProperty$4$1(result, n, O[k]);
  result.length = n;
  return result;
};

/* eslint-disable es/no-object-getownpropertynames -- safe */

var classof$a$1 = classofRaw$2$1;
var toIndexedObject$5$1 = toIndexedObject$a$1;
var $getOwnPropertyNames$1$1 = objectGetOwnPropertyNames$1.f;
var arraySlice$6$1 = arraySliceSimple$1;

var windowNames$1 = typeof window == 'object' && window && Object.getOwnPropertyNames
  ? Object.getOwnPropertyNames(window) : [];

var getWindowNames$1 = function (it) {
  try {
    return $getOwnPropertyNames$1$1(it);
  } catch (error) {
    return arraySlice$6$1(windowNames$1);
  }
};

// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
objectGetOwnPropertyNamesExternal$1.f = function getOwnPropertyNames(it) {
  return windowNames$1 && classof$a$1(it) == 'Window'
    ? getWindowNames$1(it)
    : $getOwnPropertyNames$1$1(toIndexedObject$5$1(it));
};

var objectGetOwnPropertySymbols$1 = {};

// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
objectGetOwnPropertySymbols$1.f = Object.getOwnPropertySymbols;

var createNonEnumerableProperty$7 = createNonEnumerableProperty$9;

var defineBuiltIn$6 = function (target, key, value, options) {
  if (options && options.enumerable) target[key] = value;
  else createNonEnumerableProperty$7(target, key, value);
  return target;
};

var defineProperty$6$1 = objectDefineProperty$1;

var defineBuiltInAccessor$3$1 = function (target, name, descriptor) {
  return defineProperty$6$1.f(target, name, descriptor);
};

var wellKnownSymbolWrapped$1 = {};

var wellKnownSymbol$f$1 = wellKnownSymbol$m;

wellKnownSymbolWrapped$1.f = wellKnownSymbol$f$1;

var path$k$1 = path$o$1;
var hasOwn$f$1 = hasOwnProperty_1$1;
var wrappedWellKnownSymbolModule$1$1 = wellKnownSymbolWrapped$1;
var defineProperty$5$1 = objectDefineProperty$1.f;

var wellKnownSymbolDefine$1 = function (NAME) {
  var Symbol = path$k$1.Symbol || (path$k$1.Symbol = {});
  if (!hasOwn$f$1(Symbol, NAME)) defineProperty$5$1(Symbol, NAME, {
    value: wrappedWellKnownSymbolModule$1$1.f(NAME)
  });
};

var call$e$1 = functionCall$1;
var getBuiltIn$b$1 = getBuiltIn$f;
var wellKnownSymbol$e$1 = wellKnownSymbol$m;
var defineBuiltIn$5$1 = defineBuiltIn$6;

var symbolDefineToPrimitive$1 = function () {
  var Symbol = getBuiltIn$b$1('Symbol');
  var SymbolPrototype = Symbol && Symbol.prototype;
  var valueOf = SymbolPrototype && SymbolPrototype.valueOf;
  var TO_PRIMITIVE = wellKnownSymbol$e$1('toPrimitive');

  if (SymbolPrototype && !SymbolPrototype[TO_PRIMITIVE]) {
    // `Symbol.prototype[@@toPrimitive]` method
    // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
    // eslint-disable-next-line no-unused-vars -- required for .length
    defineBuiltIn$5$1(SymbolPrototype, TO_PRIMITIVE, function (hint) {
      return call$e$1(valueOf, this);
    }, { arity: 1 });
  }
};

var TO_STRING_TAG_SUPPORT$1$1 = toStringTagSupport$1;
var classof$9$1 = classof$d$1;

// `Object.prototype.toString` method implementation
// https://tc39.es/ecma262/#sec-object.prototype.tostring
var objectToString$1 = TO_STRING_TAG_SUPPORT$1$1 ? {}.toString : function toString() {
  return '[object ' + classof$9$1(this) + ']';
};

var TO_STRING_TAG_SUPPORT$3 = toStringTagSupport$1;
var defineProperty$4$1 = objectDefineProperty$1.f;
var createNonEnumerableProperty$6$1 = createNonEnumerableProperty$9;
var hasOwn$e$1 = hasOwnProperty_1$1;
var toString$6$1 = objectToString$1;
var wellKnownSymbol$d$1 = wellKnownSymbol$m;

var TO_STRING_TAG$2$1 = wellKnownSymbol$d$1('toStringTag');

var setToStringTag$7 = function (it, TAG, STATIC, SET_METHOD) {
  if (it) {
    var target = STATIC ? it : it.prototype;
    if (!hasOwn$e$1(target, TO_STRING_TAG$2$1)) {
      defineProperty$4$1(target, TO_STRING_TAG$2$1, { configurable: true, value: TAG });
    }
    if (SET_METHOD && !TO_STRING_TAG_SUPPORT$3) {
      createNonEnumerableProperty$6$1(target, 'toString', toString$6$1);
    }
  }
};

var global$e$1 = global$m;
var isCallable$b$1 = isCallable$m;

var WeakMap$1$2 = global$e$1.WeakMap;

var weakMapBasicDetection$1 = isCallable$b$1(WeakMap$1$2) && /native code/.test(String(WeakMap$1$2));

var NATIVE_WEAK_MAP$2 = weakMapBasicDetection$1;
var global$d$1 = global$m;
var isObject$a$1 = isObject$h$1;
var createNonEnumerableProperty$5$1 = createNonEnumerableProperty$9;
var hasOwn$d$1 = hasOwnProperty_1$1;
var shared$4$1 = sharedStore$1;
var sharedKey$2$1 = sharedKey$4$1;
var hiddenKeys$2$1 = hiddenKeys$6$1;

var OBJECT_ALREADY_INITIALIZED$1 = 'Object already initialized';
var TypeError$3 = global$d$1.TypeError;
var WeakMap$4 = global$d$1.WeakMap;
var set$4$1, get$9, has$1;

var enforce$1 = function (it) {
  return has$1(it) ? get$9(it) : set$4$1(it, {});
};

var getterFor$1 = function (TYPE) {
  return function (it) {
    var state;
    if (!isObject$a$1(it) || (state = get$9(it)).type !== TYPE) {
      throw TypeError$3('Incompatible receiver, ' + TYPE + ' required');
    } return state;
  };
};

if (NATIVE_WEAK_MAP$2 || shared$4$1.state) {
  var store$4 = shared$4$1.state || (shared$4$1.state = new WeakMap$4());
  /* eslint-disable no-self-assign -- prototype methods protection */
  store$4.get = store$4.get;
  store$4.has = store$4.has;
  store$4.set = store$4.set;
  /* eslint-enable no-self-assign -- prototype methods protection */
  set$4$1 = function (it, metadata) {
    if (store$4.has(it)) throw TypeError$3(OBJECT_ALREADY_INITIALIZED$1);
    metadata.facade = it;
    store$4.set(it, metadata);
    return metadata;
  };
  get$9 = function (it) {
    return store$4.get(it) || {};
  };
  has$1 = function (it) {
    return store$4.has(it);
  };
} else {
  var STATE$1 = sharedKey$2$1('state');
  hiddenKeys$2$1[STATE$1] = true;
  set$4$1 = function (it, metadata) {
    if (hasOwn$d$1(it, STATE$1)) throw TypeError$3(OBJECT_ALREADY_INITIALIZED$1);
    metadata.facade = it;
    createNonEnumerableProperty$5$1(it, STATE$1, metadata);
    return metadata;
  };
  get$9 = function (it) {
    return hasOwn$d$1(it, STATE$1) ? it[STATE$1] : {};
  };
  has$1 = function (it) {
    return hasOwn$d$1(it, STATE$1);
  };
}

var internalState$1 = {
  set: set$4$1,
  get: get$9,
  has: has$1,
  enforce: enforce$1,
  getterFor: getterFor$1
};

var bind$h = functionBindContext$1;
var uncurryThis$f$1 = functionUncurryThis$1;
var IndexedObject$2$1 = indexedObject$1;
var toObject$a$1 = toObject$d$1;
var lengthOfArrayLike$8$1 = lengthOfArrayLike$c;
var arraySpeciesCreate$2$1 = arraySpeciesCreate$4;

var push$5$1 = uncurryThis$f$1([].push);

// `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterReject }` methods implementation
var createMethod$2$1 = function (TYPE) {
  var IS_MAP = TYPE == 1;
  var IS_FILTER = TYPE == 2;
  var IS_SOME = TYPE == 3;
  var IS_EVERY = TYPE == 4;
  var IS_FIND_INDEX = TYPE == 6;
  var IS_FILTER_REJECT = TYPE == 7;
  var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
  return function ($this, callbackfn, that, specificCreate) {
    var O = toObject$a$1($this);
    var self = IndexedObject$2$1(O);
    var boundFunction = bind$h(callbackfn, that);
    var length = lengthOfArrayLike$8$1(self);
    var index = 0;
    var create = specificCreate || arraySpeciesCreate$2$1;
    var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_REJECT ? create($this, 0) : undefined;
    var value, result;
    for (;length > index; index++) if (NO_HOLES || index in self) {
      value = self[index];
      result = boundFunction(value, index, O);
      if (TYPE) {
        if (IS_MAP) target[index] = result; // map
        else if (result) switch (TYPE) {
          case 3: return true;              // some
          case 5: return value;             // find
          case 6: return index;             // findIndex
          case 2: push$5$1(target, value);      // filter
        } else switch (TYPE) {
          case 4: return false;             // every
          case 7: push$5$1(target, value);      // filterReject
        }
      }
    }
    return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
  };
};

var arrayIteration$1 = {
  // `Array.prototype.forEach` method
  // https://tc39.es/ecma262/#sec-array.prototype.foreach
  forEach: createMethod$2$1(0),
  // `Array.prototype.map` method
  // https://tc39.es/ecma262/#sec-array.prototype.map
  map: createMethod$2$1(1),
  // `Array.prototype.filter` method
  // https://tc39.es/ecma262/#sec-array.prototype.filter
  filter: createMethod$2$1(2),
  // `Array.prototype.some` method
  // https://tc39.es/ecma262/#sec-array.prototype.some
  some: createMethod$2$1(3),
  // `Array.prototype.every` method
  // https://tc39.es/ecma262/#sec-array.prototype.every
  every: createMethod$2$1(4),
  // `Array.prototype.find` method
  // https://tc39.es/ecma262/#sec-array.prototype.find
  find: createMethod$2$1(5),
  // `Array.prototype.findIndex` method
  // https://tc39.es/ecma262/#sec-array.prototype.findIndex
  findIndex: createMethod$2$1(6),
  // `Array.prototype.filterReject` method
  // https://github.com/tc39/proposal-array-filtering
  filterReject: createMethod$2$1(7)
};

var $$J$1 = _export$1;
var global$c$1 = global$m;
var call$d$1 = functionCall$1;
var uncurryThis$e$1 = functionUncurryThis$1;
var DESCRIPTORS$a$1 = descriptors$1;
var NATIVE_SYMBOL$3$1 = symbolConstructorDetection$1;
var fails$i$1 = fails$t$1;
var hasOwn$c$1 = hasOwnProperty_1$1;
var isPrototypeOf$i$1 = objectIsPrototypeOf$1;
var anObject$9$1 = anObject$d$1;
var toIndexedObject$4$1 = toIndexedObject$a$1;
var toPropertyKey$5 = toPropertyKey$4$1;
var $toString$1 = toString$7$1;
var createPropertyDescriptor$3$1 = createPropertyDescriptor$7;
var nativeObjectCreate$1 = objectCreate$1;
var objectKeys$1$1 = objectKeys$3$1;
var getOwnPropertyNamesModule$2$1 = objectGetOwnPropertyNames$1;
var getOwnPropertyNamesExternal$1 = objectGetOwnPropertyNamesExternal$1;
var getOwnPropertySymbolsModule$3$1 = objectGetOwnPropertySymbols$1;
var getOwnPropertyDescriptorModule$2$1 = objectGetOwnPropertyDescriptor$1;
var definePropertyModule$1$1 = objectDefineProperty$1;
var definePropertiesModule$2 = objectDefineProperties$1;
var propertyIsEnumerableModule$1$1 = objectPropertyIsEnumerable$1;
var defineBuiltIn$4$1 = defineBuiltIn$6;
var defineBuiltInAccessor$2$1 = defineBuiltInAccessor$3$1;
var shared$3$1 = sharedExports$1;
var sharedKey$1$1 = sharedKey$4$1;
var hiddenKeys$1$1 = hiddenKeys$6$1;
var uid$1$1 = uid$4$1;
var wellKnownSymbol$c$1 = wellKnownSymbol$m;
var wrappedWellKnownSymbolModule$2 = wellKnownSymbolWrapped$1;
var defineWellKnownSymbol$l$1 = wellKnownSymbolDefine$1;
var defineSymbolToPrimitive$1$1 = symbolDefineToPrimitive$1;
var setToStringTag$6$1 = setToStringTag$7;
var InternalStateModule$5$1 = internalState$1;
var $forEach$1$1 = arrayIteration$1.forEach;

var HIDDEN$1 = sharedKey$1$1('hidden');
var SYMBOL$1 = 'Symbol';
var PROTOTYPE$2 = 'prototype';

var setInternalState$5$1 = InternalStateModule$5$1.set;
var getInternalState$2$1 = InternalStateModule$5$1.getterFor(SYMBOL$1);

var ObjectPrototype$2$1 = Object[PROTOTYPE$2];
var $Symbol$1 = global$c$1.Symbol;
var SymbolPrototype$1 = $Symbol$1 && $Symbol$1[PROTOTYPE$2];
var TypeError$2$1 = global$c$1.TypeError;
var QObject$1 = global$c$1.QObject;
var nativeGetOwnPropertyDescriptor$1$1 = getOwnPropertyDescriptorModule$2$1.f;
var nativeDefineProperty$1 = definePropertyModule$1$1.f;
var nativeGetOwnPropertyNames$1 = getOwnPropertyNamesExternal$1.f;
var nativePropertyIsEnumerable$1 = propertyIsEnumerableModule$1$1.f;
var push$4$1 = uncurryThis$e$1([].push);

var AllSymbols$1 = shared$3$1('symbols');
var ObjectPrototypeSymbols$1 = shared$3$1('op-symbols');
var WellKnownSymbolsStore$1$1 = shared$3$1('wks');

// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
var USE_SETTER$1 = !QObject$1 || !QObject$1[PROTOTYPE$2] || !QObject$1[PROTOTYPE$2].findChild;

// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
var setSymbolDescriptor$1 = DESCRIPTORS$a$1 && fails$i$1(function () {
  return nativeObjectCreate$1(nativeDefineProperty$1({}, 'a', {
    get: function () { return nativeDefineProperty$1(this, 'a', { value: 7 }).a; }
  })).a != 7;
}) ? function (O, P, Attributes) {
  var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$1$1(ObjectPrototype$2$1, P);
  if (ObjectPrototypeDescriptor) delete ObjectPrototype$2$1[P];
  nativeDefineProperty$1(O, P, Attributes);
  if (ObjectPrototypeDescriptor && O !== ObjectPrototype$2$1) {
    nativeDefineProperty$1(ObjectPrototype$2$1, P, ObjectPrototypeDescriptor);
  }
} : nativeDefineProperty$1;

var wrap$2 = function (tag, description) {
  var symbol = AllSymbols$1[tag] = nativeObjectCreate$1(SymbolPrototype$1);
  setInternalState$5$1(symbol, {
    type: SYMBOL$1,
    tag: tag,
    description: description
  });
  if (!DESCRIPTORS$a$1) symbol.description = description;
  return symbol;
};

var $defineProperty$2 = function defineProperty(O, P, Attributes) {
  if (O === ObjectPrototype$2$1) $defineProperty$2(ObjectPrototypeSymbols$1, P, Attributes);
  anObject$9$1(O);
  var key = toPropertyKey$5(P);
  anObject$9$1(Attributes);
  if (hasOwn$c$1(AllSymbols$1, key)) {
    if (!Attributes.enumerable) {
      if (!hasOwn$c$1(O, HIDDEN$1)) nativeDefineProperty$1(O, HIDDEN$1, createPropertyDescriptor$3$1(1, {}));
      O[HIDDEN$1][key] = true;
    } else {
      if (hasOwn$c$1(O, HIDDEN$1) && O[HIDDEN$1][key]) O[HIDDEN$1][key] = false;
      Attributes = nativeObjectCreate$1(Attributes, { enumerable: createPropertyDescriptor$3$1(0, false) });
    } return setSymbolDescriptor$1(O, key, Attributes);
  } return nativeDefineProperty$1(O, key, Attributes);
};

var $defineProperties$1 = function defineProperties(O, Properties) {
  anObject$9$1(O);
  var properties = toIndexedObject$4$1(Properties);
  var keys = objectKeys$1$1(properties).concat($getOwnPropertySymbols$1(properties));
  $forEach$1$1(keys, function (key) {
    if (!DESCRIPTORS$a$1 || call$d$1($propertyIsEnumerable$3, properties, key)) $defineProperty$2(O, key, properties[key]);
  });
  return O;
};

var $create$1 = function create(O, Properties) {
  return Properties === undefined ? nativeObjectCreate$1(O) : $defineProperties$1(nativeObjectCreate$1(O), Properties);
};

var $propertyIsEnumerable$3 = function propertyIsEnumerable(V) {
  var P = toPropertyKey$5(V);
  var enumerable = call$d$1(nativePropertyIsEnumerable$1, this, P);
  if (this === ObjectPrototype$2$1 && hasOwn$c$1(AllSymbols$1, P) && !hasOwn$c$1(ObjectPrototypeSymbols$1, P)) return false;
  return enumerable || !hasOwn$c$1(this, P) || !hasOwn$c$1(AllSymbols$1, P) || hasOwn$c$1(this, HIDDEN$1) && this[HIDDEN$1][P]
    ? enumerable : true;
};

var $getOwnPropertyDescriptor$3 = function getOwnPropertyDescriptor(O, P) {
  var it = toIndexedObject$4$1(O);
  var key = toPropertyKey$5(P);
  if (it === ObjectPrototype$2$1 && hasOwn$c$1(AllSymbols$1, key) && !hasOwn$c$1(ObjectPrototypeSymbols$1, key)) return;
  var descriptor = nativeGetOwnPropertyDescriptor$1$1(it, key);
  if (descriptor && hasOwn$c$1(AllSymbols$1, key) && !(hasOwn$c$1(it, HIDDEN$1) && it[HIDDEN$1][key])) {
    descriptor.enumerable = true;
  }
  return descriptor;
};

var $getOwnPropertyNames$2 = function getOwnPropertyNames(O) {
  var names = nativeGetOwnPropertyNames$1(toIndexedObject$4$1(O));
  var result = [];
  $forEach$1$1(names, function (key) {
    if (!hasOwn$c$1(AllSymbols$1, key) && !hasOwn$c$1(hiddenKeys$1$1, key)) push$4$1(result, key);
  });
  return result;
};

var $getOwnPropertySymbols$1 = function (O) {
  var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$2$1;
  var names = nativeGetOwnPropertyNames$1(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols$1 : toIndexedObject$4$1(O));
  var result = [];
  $forEach$1$1(names, function (key) {
    if (hasOwn$c$1(AllSymbols$1, key) && (!IS_OBJECT_PROTOTYPE || hasOwn$c$1(ObjectPrototype$2$1, key))) {
      push$4$1(result, AllSymbols$1[key]);
    }
  });
  return result;
};

// `Symbol` constructor
// https://tc39.es/ecma262/#sec-symbol-constructor
if (!NATIVE_SYMBOL$3$1) {
  $Symbol$1 = function Symbol() {
    if (isPrototypeOf$i$1(SymbolPrototype$1, this)) throw TypeError$2$1('Symbol is not a constructor');
    var description = !arguments.length || arguments[0] === undefined ? undefined : $toString$1(arguments[0]);
    var tag = uid$1$1(description);
    var setter = function (value) {
      if (this === ObjectPrototype$2$1) call$d$1(setter, ObjectPrototypeSymbols$1, value);
      if (hasOwn$c$1(this, HIDDEN$1) && hasOwn$c$1(this[HIDDEN$1], tag)) this[HIDDEN$1][tag] = false;
      setSymbolDescriptor$1(this, tag, createPropertyDescriptor$3$1(1, value));
    };
    if (DESCRIPTORS$a$1 && USE_SETTER$1) setSymbolDescriptor$1(ObjectPrototype$2$1, tag, { configurable: true, set: setter });
    return wrap$2(tag, description);
  };

  SymbolPrototype$1 = $Symbol$1[PROTOTYPE$2];

  defineBuiltIn$4$1(SymbolPrototype$1, 'toString', function toString() {
    return getInternalState$2$1(this).tag;
  });

  defineBuiltIn$4$1($Symbol$1, 'withoutSetter', function (description) {
    return wrap$2(uid$1$1(description), description);
  });

  propertyIsEnumerableModule$1$1.f = $propertyIsEnumerable$3;
  definePropertyModule$1$1.f = $defineProperty$2;
  definePropertiesModule$2.f = $defineProperties$1;
  getOwnPropertyDescriptorModule$2$1.f = $getOwnPropertyDescriptor$3;
  getOwnPropertyNamesModule$2$1.f = getOwnPropertyNamesExternal$1.f = $getOwnPropertyNames$2;
  getOwnPropertySymbolsModule$3$1.f = $getOwnPropertySymbols$1;

  wrappedWellKnownSymbolModule$2.f = function (name) {
    return wrap$2(wellKnownSymbol$c$1(name), name);
  };

  if (DESCRIPTORS$a$1) {
    // https://github.com/tc39/proposal-Symbol-description
    defineBuiltInAccessor$2$1(SymbolPrototype$1, 'description', {
      configurable: true,
      get: function description() {
        return getInternalState$2$1(this).description;
      }
    });
  }
}

$$J$1({ global: true, constructor: true, wrap: true, forced: !NATIVE_SYMBOL$3$1, sham: !NATIVE_SYMBOL$3$1 }, {
  Symbol: $Symbol$1
});

$forEach$1$1(objectKeys$1$1(WellKnownSymbolsStore$1$1), function (name) {
  defineWellKnownSymbol$l$1(name);
});

$$J$1({ target: SYMBOL$1, stat: true, forced: !NATIVE_SYMBOL$3$1 }, {
  useSetter: function () { USE_SETTER$1 = true; },
  useSimple: function () { USE_SETTER$1 = false; }
});

$$J$1({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$3$1, sham: !DESCRIPTORS$a$1 }, {
  // `Object.create` method
  // https://tc39.es/ecma262/#sec-object.create
  create: $create$1,
  // `Object.defineProperty` method
  // https://tc39.es/ecma262/#sec-object.defineproperty
  defineProperty: $defineProperty$2,
  // `Object.defineProperties` method
  // https://tc39.es/ecma262/#sec-object.defineproperties
  defineProperties: $defineProperties$1,
  // `Object.getOwnPropertyDescriptor` method
  // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
  getOwnPropertyDescriptor: $getOwnPropertyDescriptor$3
});

$$J$1({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$3$1 }, {
  // `Object.getOwnPropertyNames` method
  // https://tc39.es/ecma262/#sec-object.getownpropertynames
  getOwnPropertyNames: $getOwnPropertyNames$2
});

// `Symbol.prototype[@@toPrimitive]` method
// https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
defineSymbolToPrimitive$1$1();

// `Symbol.prototype[@@toStringTag]` property
// https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
setToStringTag$6$1($Symbol$1, SYMBOL$1);

hiddenKeys$1$1[HIDDEN$1] = true;

var NATIVE_SYMBOL$2$1 = symbolConstructorDetection$1;

/* eslint-disable es/no-symbol -- safe */
var symbolRegistryDetection$1 = NATIVE_SYMBOL$2$1 && !!Symbol['for'] && !!Symbol.keyFor;

var $$I$1 = _export$1;
var getBuiltIn$a$1 = getBuiltIn$f;
var hasOwn$b$1 = hasOwnProperty_1$1;
var toString$5$1 = toString$7$1;
var shared$2$1 = sharedExports$1;
var NATIVE_SYMBOL_REGISTRY$1$1 = symbolRegistryDetection$1;

var StringToSymbolRegistry$1 = shared$2$1('string-to-symbol-registry');
var SymbolToStringRegistry$1$1 = shared$2$1('symbol-to-string-registry');

// `Symbol.for` method
// https://tc39.es/ecma262/#sec-symbol.for
$$I$1({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY$1$1 }, {
  'for': function (key) {
    var string = toString$5$1(key);
    if (hasOwn$b$1(StringToSymbolRegistry$1, string)) return StringToSymbolRegistry$1[string];
    var symbol = getBuiltIn$a$1('Symbol')(string);
    StringToSymbolRegistry$1[string] = symbol;
    SymbolToStringRegistry$1$1[symbol] = string;
    return symbol;
  }
});

var $$H$1 = _export$1;
var hasOwn$a$1 = hasOwnProperty_1$1;
var isSymbol$2$1 = isSymbol$5$1;
var tryToString$4$1 = tryToString$6$1;
var shared$1$1 = sharedExports$1;
var NATIVE_SYMBOL_REGISTRY$2 = symbolRegistryDetection$1;

var SymbolToStringRegistry$2 = shared$1$1('symbol-to-string-registry');

// `Symbol.keyFor` method
// https://tc39.es/ecma262/#sec-symbol.keyfor
$$H$1({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY$2 }, {
  keyFor: function keyFor(sym) {
    if (!isSymbol$2$1(sym)) throw TypeError(tryToString$4$1(sym) + ' is not a symbol');
    if (hasOwn$a$1(SymbolToStringRegistry$2, sym)) return SymbolToStringRegistry$2[sym];
  }
});

var uncurryThis$d$1 = functionUncurryThis$1;

var arraySlice$5$1 = uncurryThis$d$1([].slice);

var uncurryThis$c$1 = functionUncurryThis$1;
var isArray$c$1 = isArray$f$1;
var isCallable$a$1 = isCallable$m;
var classof$8$1 = classofRaw$2$1;
var toString$4$1 = toString$7$1;

var push$3$1 = uncurryThis$c$1([].push);

var getJsonReplacerFunction$1 = function (replacer) {
  if (isCallable$a$1(replacer)) return replacer;
  if (!isArray$c$1(replacer)) return;
  var rawLength = replacer.length;
  var keys = [];
  for (var i = 0; i < rawLength; i++) {
    var element = replacer[i];
    if (typeof element == 'string') push$3$1(keys, element);
    else if (typeof element == 'number' || classof$8$1(element) == 'Number' || classof$8$1(element) == 'String') push$3$1(keys, toString$4$1(element));
  }
  var keysLength = keys.length;
  var root = true;
  return function (key, value) {
    if (root) {
      root = false;
      return value;
    }
    if (isArray$c$1(this)) return value;
    for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value;
  };
};

var $$G$1 = _export$1;
var getBuiltIn$9$1 = getBuiltIn$f;
var apply$4$1 = functionApply$1;
var call$c$1 = functionCall$1;
var uncurryThis$b$1 = functionUncurryThis$1;
var fails$h$1 = fails$t$1;
var isCallable$9$1 = isCallable$m;
var isSymbol$1$1 = isSymbol$5$1;
var arraySlice$4$1 = arraySlice$5$1;
var getReplacerFunction$1 = getJsonReplacerFunction$1;
var NATIVE_SYMBOL$1$1 = symbolConstructorDetection$1;

var $String$1$1 = String;
var $stringify$1 = getBuiltIn$9$1('JSON', 'stringify');
var exec$3 = uncurryThis$b$1(/./.exec);
var charAt$2$1 = uncurryThis$b$1(''.charAt);
var charCodeAt$1$1 = uncurryThis$b$1(''.charCodeAt);
var replace$1$1 = uncurryThis$b$1(''.replace);
var numberToString$1 = uncurryThis$b$1(1.0.toString);

var tester$1 = /[\uD800-\uDFFF]/g;
var low$1 = /^[\uD800-\uDBFF]$/;
var hi$1 = /^[\uDC00-\uDFFF]$/;

var WRONG_SYMBOLS_CONVERSION$1 = !NATIVE_SYMBOL$1$1 || fails$h$1(function () {
  var symbol = getBuiltIn$9$1('Symbol')();
  // MS Edge converts symbol values to JSON as {}
  return $stringify$1([symbol]) != '[null]'
    // WebKit converts symbol values to JSON as null
    || $stringify$1({ a: symbol }) != '{}'
    // V8 throws on boxed symbols
    || $stringify$1(Object(symbol)) != '{}';
});

// https://github.com/tc39/proposal-well-formed-stringify
var ILL_FORMED_UNICODE$1 = fails$h$1(function () {
  return $stringify$1('\uDF06\uD834') !== '"\\udf06\\ud834"'
    || $stringify$1('\uDEAD') !== '"\\udead"';
});

var stringifyWithSymbolsFix$1 = function (it, replacer) {
  var args = arraySlice$4$1(arguments);
  var $replacer = getReplacerFunction$1(replacer);
  if (!isCallable$9$1($replacer) && (it === undefined || isSymbol$1$1(it))) return; // IE8 returns string on undefined
  args[1] = function (key, value) {
    // some old implementations (like WebKit) could pass numbers as keys
    if (isCallable$9$1($replacer)) value = call$c$1($replacer, this, $String$1$1(key), value);
    if (!isSymbol$1$1(value)) return value;
  };
  return apply$4$1($stringify$1, null, args);
};

var fixIllFormed$1 = function (match, offset, string) {
  var prev = charAt$2$1(string, offset - 1);
  var next = charAt$2$1(string, offset + 1);
  if ((exec$3(low$1, match) && !exec$3(hi$1, next)) || (exec$3(hi$1, match) && !exec$3(low$1, prev))) {
    return '\\u' + numberToString$1(charCodeAt$1$1(match, 0), 16);
  } return match;
};

if ($stringify$1) {
  // `JSON.stringify` method
  // https://tc39.es/ecma262/#sec-json.stringify
  $$G$1({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION$1 || ILL_FORMED_UNICODE$1 }, {
    // eslint-disable-next-line no-unused-vars -- required for `.length`
    stringify: function stringify(it, replacer, space) {
      var args = arraySlice$4$1(arguments);
      var result = apply$4$1(WRONG_SYMBOLS_CONVERSION$1 ? stringifyWithSymbolsFix$1 : $stringify$1, null, args);
      return ILL_FORMED_UNICODE$1 && typeof result == 'string' ? replace$1$1(result, tester$1, fixIllFormed$1) : result;
    }
  });
}

var $$F$1 = _export$1;
var NATIVE_SYMBOL$6 = symbolConstructorDetection$1;
var fails$g$1 = fails$t$1;
var getOwnPropertySymbolsModule$2$1 = objectGetOwnPropertySymbols$1;
var toObject$9$1 = toObject$d$1;

// V8 ~ Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
// https://bugs.chromium.org/p/v8/issues/detail?id=3443
var FORCED$4$1 = !NATIVE_SYMBOL$6 || fails$g$1(function () { getOwnPropertySymbolsModule$2$1.f(1); });

// `Object.getOwnPropertySymbols` method
// https://tc39.es/ecma262/#sec-object.getownpropertysymbols
$$F$1({ target: 'Object', stat: true, forced: FORCED$4$1 }, {
  getOwnPropertySymbols: function getOwnPropertySymbols(it) {
    var $getOwnPropertySymbols = getOwnPropertySymbolsModule$2$1.f;
    return $getOwnPropertySymbols ? $getOwnPropertySymbols(toObject$9$1(it)) : [];
  }
});

var defineWellKnownSymbol$k$1 = wellKnownSymbolDefine$1;

// `Symbol.asyncIterator` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.asynciterator
defineWellKnownSymbol$k$1('asyncIterator');

var defineWellKnownSymbol$j$1 = wellKnownSymbolDefine$1;

// `Symbol.hasInstance` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.hasinstance
defineWellKnownSymbol$j$1('hasInstance');

var defineWellKnownSymbol$i$1 = wellKnownSymbolDefine$1;

// `Symbol.isConcatSpreadable` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.isconcatspreadable
defineWellKnownSymbol$i$1('isConcatSpreadable');

var defineWellKnownSymbol$h$1 = wellKnownSymbolDefine$1;

// `Symbol.iterator` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.iterator
defineWellKnownSymbol$h$1('iterator');

var defineWellKnownSymbol$g$1 = wellKnownSymbolDefine$1;

// `Symbol.match` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.match
defineWellKnownSymbol$g$1('match');

var defineWellKnownSymbol$f$1 = wellKnownSymbolDefine$1;

// `Symbol.matchAll` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.matchall
defineWellKnownSymbol$f$1('matchAll');

var defineWellKnownSymbol$e$1 = wellKnownSymbolDefine$1;

// `Symbol.replace` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.replace
defineWellKnownSymbol$e$1('replace');

var defineWellKnownSymbol$d$1 = wellKnownSymbolDefine$1;

// `Symbol.search` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.search
defineWellKnownSymbol$d$1('search');

var defineWellKnownSymbol$c$1 = wellKnownSymbolDefine$1;

// `Symbol.species` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.species
defineWellKnownSymbol$c$1('species');

var defineWellKnownSymbol$b$1 = wellKnownSymbolDefine$1;

// `Symbol.split` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.split
defineWellKnownSymbol$b$1('split');

var defineWellKnownSymbol$a$1 = wellKnownSymbolDefine$1;
var defineSymbolToPrimitive$2 = symbolDefineToPrimitive$1;

// `Symbol.toPrimitive` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.toprimitive
defineWellKnownSymbol$a$1('toPrimitive');

// `Symbol.prototype[@@toPrimitive]` method
// https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
defineSymbolToPrimitive$2();

var getBuiltIn$8$1 = getBuiltIn$f;
var defineWellKnownSymbol$9$1 = wellKnownSymbolDefine$1;
var setToStringTag$5$1 = setToStringTag$7;

// `Symbol.toStringTag` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.tostringtag
defineWellKnownSymbol$9$1('toStringTag');

// `Symbol.prototype[@@toStringTag]` property
// https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
setToStringTag$5$1(getBuiltIn$8$1('Symbol'), 'Symbol');

var defineWellKnownSymbol$8$1 = wellKnownSymbolDefine$1;

// `Symbol.unscopables` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.unscopables
defineWellKnownSymbol$8$1('unscopables');

var global$b$1 = global$m;
var setToStringTag$4$1 = setToStringTag$7;

// JSON[@@toStringTag] property
// https://tc39.es/ecma262/#sec-json-@@tostringtag
setToStringTag$4$1(global$b$1.JSON, 'JSON', true);

var path$j$1 = path$o$1;

var symbol$6$1 = path$j$1.Symbol;

var iterators$1 = {};

var DESCRIPTORS$9$1 = descriptors$1;
var hasOwn$9$1 = hasOwnProperty_1$1;

var FunctionPrototype$1$1 = Function.prototype;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getDescriptor$1 = DESCRIPTORS$9$1 && Object.getOwnPropertyDescriptor;

var EXISTS$2 = hasOwn$9$1(FunctionPrototype$1$1, 'name');
// additional protection from minified / mangled / dropped function names
var PROPER$1 = EXISTS$2 && (function something() { /* empty */ }).name === 'something';
var CONFIGURABLE$2 = EXISTS$2 && (!DESCRIPTORS$9$1 || (DESCRIPTORS$9$1 && getDescriptor$1(FunctionPrototype$1$1, 'name').configurable));

var functionName$1 = {
  EXISTS: EXISTS$2,
  PROPER: PROPER$1,
  CONFIGURABLE: CONFIGURABLE$2
};

var fails$f$1 = fails$t$1;

var correctPrototypeGetter$1 = !fails$f$1(function () {
  function F() { /* empty */ }
  F.prototype.constructor = null;
  // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
  return Object.getPrototypeOf(new F()) !== F.prototype;
});

var hasOwn$8$1 = hasOwnProperty_1$1;
var isCallable$8$1 = isCallable$m;
var toObject$8$1 = toObject$d$1;
var sharedKey$5 = sharedKey$4$1;
var CORRECT_PROTOTYPE_GETTER$1$1 = correctPrototypeGetter$1;

var IE_PROTO$2 = sharedKey$5('IE_PROTO');
var $Object$6 = Object;
var ObjectPrototype$1$1 = $Object$6.prototype;

// `Object.getPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.getprototypeof
// eslint-disable-next-line es/no-object-getprototypeof -- safe
var objectGetPrototypeOf$1 = CORRECT_PROTOTYPE_GETTER$1$1 ? $Object$6.getPrototypeOf : function (O) {
  var object = toObject$8$1(O);
  if (hasOwn$8$1(object, IE_PROTO$2)) return object[IE_PROTO$2];
  var constructor = object.constructor;
  if (isCallable$8$1(constructor) && object instanceof constructor) {
    return constructor.prototype;
  } return object instanceof $Object$6 ? ObjectPrototype$1$1 : null;
};

var fails$e$1 = fails$t$1;
var isCallable$7$1 = isCallable$m;
var isObject$9$1 = isObject$h$1;
var create$c$1 = objectCreate$1;
var getPrototypeOf$8$1 = objectGetPrototypeOf$1;
var defineBuiltIn$3$1 = defineBuiltIn$6;
var wellKnownSymbol$b$1 = wellKnownSymbol$m;

var ITERATOR$4$1 = wellKnownSymbol$b$1('iterator');
var BUGGY_SAFARI_ITERATORS$1$1 = false;

// `%IteratorPrototype%` object
// https://tc39.es/ecma262/#sec-%iteratorprototype%-object
var IteratorPrototype$1$1, PrototypeOfArrayIteratorPrototype$1, arrayIterator$1;

/* eslint-disable es/no-array-prototype-keys -- safe */
if ([].keys) {
  arrayIterator$1 = [].keys();
  // Safari 8 has buggy iterators w/o `next`
  if (!('next' in arrayIterator$1)) BUGGY_SAFARI_ITERATORS$1$1 = true;
  else {
    PrototypeOfArrayIteratorPrototype$1 = getPrototypeOf$8$1(getPrototypeOf$8$1(arrayIterator$1));
    if (PrototypeOfArrayIteratorPrototype$1 !== Object.prototype) IteratorPrototype$1$1 = PrototypeOfArrayIteratorPrototype$1;
  }
}

var NEW_ITERATOR_PROTOTYPE$1 = !isObject$9$1(IteratorPrototype$1$1) || fails$e$1(function () {
  var test = {};
  // FF44- legacy iterators case
  return IteratorPrototype$1$1[ITERATOR$4$1].call(test) !== test;
});

if (NEW_ITERATOR_PROTOTYPE$1) IteratorPrototype$1$1 = {};
else IteratorPrototype$1$1 = create$c$1(IteratorPrototype$1$1);

// `%IteratorPrototype%[@@iterator]()` method
// https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
if (!isCallable$7$1(IteratorPrototype$1$1[ITERATOR$4$1])) {
  defineBuiltIn$3$1(IteratorPrototype$1$1, ITERATOR$4$1, function () {
    return this;
  });
}

var iteratorsCore$1 = {
  IteratorPrototype: IteratorPrototype$1$1,
  BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1$1
};

var IteratorPrototype$2 = iteratorsCore$1.IteratorPrototype;
var create$b$1 = objectCreate$1;
var createPropertyDescriptor$2$1 = createPropertyDescriptor$7;
var setToStringTag$3$1 = setToStringTag$7;
var Iterators$5$1 = iterators$1;

var returnThis$1$1 = function () { return this; };

var iteratorCreateConstructor$1 = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
  var TO_STRING_TAG = NAME + ' Iterator';
  IteratorConstructor.prototype = create$b$1(IteratorPrototype$2, { next: createPropertyDescriptor$2$1(+!ENUMERABLE_NEXT, next) });
  setToStringTag$3$1(IteratorConstructor, TO_STRING_TAG, false, true);
  Iterators$5$1[TO_STRING_TAG] = returnThis$1$1;
  return IteratorConstructor;
};

var uncurryThis$a$1 = functionUncurryThis$1;
var aCallable$b = aCallable$e;

var functionUncurryThisAccessor$1 = function (object, key, method) {
  try {
    // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
    return uncurryThis$a$1(aCallable$b(Object.getOwnPropertyDescriptor(object, key)[method]));
  } catch (error) { /* empty */ }
};

var isCallable$6$1 = isCallable$m;

var $String$5 = String;
var $TypeError$9$1 = TypeError;

var aPossiblePrototype$1$1 = function (argument) {
  if (typeof argument == 'object' || isCallable$6$1(argument)) return argument;
  throw $TypeError$9$1("Can't set " + $String$5(argument) + ' as a prototype');
};

/* eslint-disable no-proto -- safe */

var uncurryThisAccessor$1 = functionUncurryThisAccessor$1;
var anObject$8$1 = anObject$d$1;
var aPossiblePrototype$2 = aPossiblePrototype$1$1;

// `Object.setPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.setprototypeof
// Works with __proto__ only. Old v8 can't work with null proto objects.
// eslint-disable-next-line es/no-object-setprototypeof -- safe
var objectSetPrototypeOf$1 = Object.setPrototypeOf || ('__proto__' in {} ? function () {
  var CORRECT_SETTER = false;
  var test = {};
  var setter;
  try {
    setter = uncurryThisAccessor$1(Object.prototype, '__proto__', 'set');
    setter(test, []);
    CORRECT_SETTER = test instanceof Array;
  } catch (error) { /* empty */ }
  return function setPrototypeOf(O, proto) {
    anObject$8$1(O);
    aPossiblePrototype$2(proto);
    if (CORRECT_SETTER) setter(O, proto);
    else O.__proto__ = proto;
    return O;
  };
}() : undefined);

var $$E$1 = _export$1;
var call$b$1 = functionCall$1;
var FunctionName$1 = functionName$1;
var createIteratorConstructor$1 = iteratorCreateConstructor$1;
var getPrototypeOf$7$1 = objectGetPrototypeOf$1;
var setToStringTag$2$1 = setToStringTag$7;
var defineBuiltIn$2$1 = defineBuiltIn$6;
var wellKnownSymbol$a$1 = wellKnownSymbol$m;
var Iterators$4$1 = iterators$1;
var IteratorsCore$1 = iteratorsCore$1;

var PROPER_FUNCTION_NAME$2 = FunctionName$1.PROPER;
var BUGGY_SAFARI_ITERATORS$2 = IteratorsCore$1.BUGGY_SAFARI_ITERATORS;
var ITERATOR$3$1 = wellKnownSymbol$a$1('iterator');
var KEYS$1 = 'keys';
var VALUES$1 = 'values';
var ENTRIES$1 = 'entries';

var returnThis$2 = function () { return this; };

var iteratorDefine$1 = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
  createIteratorConstructor$1(IteratorConstructor, NAME, next);

  var getIterationMethod = function (KIND) {
    if (KIND === DEFAULT && defaultIterator) return defaultIterator;
    if (!BUGGY_SAFARI_ITERATORS$2 && KIND in IterablePrototype) return IterablePrototype[KIND];
    switch (KIND) {
      case KEYS$1: return function keys() { return new IteratorConstructor(this, KIND); };
      case VALUES$1: return function values() { return new IteratorConstructor(this, KIND); };
      case ENTRIES$1: return function entries() { return new IteratorConstructor(this, KIND); };
    } return function () { return new IteratorConstructor(this); };
  };

  var TO_STRING_TAG = NAME + ' Iterator';
  var INCORRECT_VALUES_NAME = false;
  var IterablePrototype = Iterable.prototype;
  var nativeIterator = IterablePrototype[ITERATOR$3$1]
    || IterablePrototype['@@iterator']
    || DEFAULT && IterablePrototype[DEFAULT];
  var defaultIterator = !BUGGY_SAFARI_ITERATORS$2 && nativeIterator || getIterationMethod(DEFAULT);
  var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
  var CurrentIteratorPrototype, methods, KEY;

  // fix native
  if (anyNativeIterator) {
    CurrentIteratorPrototype = getPrototypeOf$7$1(anyNativeIterator.call(new Iterable()));
    if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
      // Set @@toStringTag to native iterators
      setToStringTag$2$1(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
      Iterators$4$1[TO_STRING_TAG] = returnThis$2;
    }
  }

  // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
  if (PROPER_FUNCTION_NAME$2 && DEFAULT == VALUES$1 && nativeIterator && nativeIterator.name !== VALUES$1) {
    {
      INCORRECT_VALUES_NAME = true;
      defaultIterator = function values() { return call$b$1(nativeIterator, this); };
    }
  }

  // export additional methods
  if (DEFAULT) {
    methods = {
      values: getIterationMethod(VALUES$1),
      keys: IS_SET ? defaultIterator : getIterationMethod(KEYS$1),
      entries: getIterationMethod(ENTRIES$1)
    };
    if (FORCED) for (KEY in methods) {
      if (BUGGY_SAFARI_ITERATORS$2 || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
        defineBuiltIn$2$1(IterablePrototype, KEY, methods[KEY]);
      }
    } else $$E$1({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS$2 || INCORRECT_VALUES_NAME }, methods);
  }

  // define iterator
  if ((FORCED) && IterablePrototype[ITERATOR$3$1] !== defaultIterator) {
    defineBuiltIn$2$1(IterablePrototype, ITERATOR$3$1, defaultIterator, { name: DEFAULT });
  }
  Iterators$4$1[NAME] = defaultIterator;

  return methods;
};

// `CreateIterResultObject` abstract operation
// https://tc39.es/ecma262/#sec-createiterresultobject
var createIterResultObject$3$1 = function (value, done) {
  return { value: value, done: done };
};

var toIndexedObject$3$1 = toIndexedObject$a$1;
var Iterators$3$1 = iterators$1;
var InternalStateModule$4$1 = internalState$1;
objectDefineProperty$1.f;
var defineIterator$2$1 = iteratorDefine$1;
var createIterResultObject$2$1 = createIterResultObject$3$1;

var ARRAY_ITERATOR$1 = 'Array Iterator';
var setInternalState$4$1 = InternalStateModule$4$1.set;
var getInternalState$1$1 = InternalStateModule$4$1.getterFor(ARRAY_ITERATOR$1);

// `Array.prototype.entries` method
// https://tc39.es/ecma262/#sec-array.prototype.entries
// `Array.prototype.keys` method
// https://tc39.es/ecma262/#sec-array.prototype.keys
// `Array.prototype.values` method
// https://tc39.es/ecma262/#sec-array.prototype.values
// `Array.prototype[@@iterator]` method
// https://tc39.es/ecma262/#sec-array.prototype-@@iterator
// `CreateArrayIterator` internal method
// https://tc39.es/ecma262/#sec-createarrayiterator
defineIterator$2$1(Array, 'Array', function (iterated, kind) {
  setInternalState$4$1(this, {
    type: ARRAY_ITERATOR$1,
    target: toIndexedObject$3$1(iterated), // target
    index: 0,                          // next index
    kind: kind                         // kind
  });
// `%ArrayIteratorPrototype%.next` method
// https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
}, function () {
  var state = getInternalState$1$1(this);
  var target = state.target;
  var kind = state.kind;
  var index = state.index++;
  if (!target || index >= target.length) {
    state.target = undefined;
    return createIterResultObject$2$1(undefined, true);
  }
  if (kind == 'keys') return createIterResultObject$2$1(index, false);
  if (kind == 'values') return createIterResultObject$2$1(target[index], false);
  return createIterResultObject$2$1([index, target[index]], false);
}, 'values');

// argumentsList[@@iterator] is %ArrayProto_values%
// https://tc39.es/ecma262/#sec-createunmappedargumentsobject
// https://tc39.es/ecma262/#sec-createmappedargumentsobject
Iterators$3$1.Arguments = Iterators$3$1.Array;

// iterable DOM collections
// flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
var domIterables$1 = {
  CSSRuleList: 0,
  CSSStyleDeclaration: 0,
  CSSValueList: 0,
  ClientRectList: 0,
  DOMRectList: 0,
  DOMStringList: 0,
  DOMTokenList: 1,
  DataTransferItemList: 0,
  FileList: 0,
  HTMLAllCollection: 0,
  HTMLCollection: 0,
  HTMLFormElement: 0,
  HTMLSelectElement: 0,
  MediaList: 0,
  MimeTypeArray: 0,
  NamedNodeMap: 0,
  NodeList: 1,
  PaintRequestList: 0,
  Plugin: 0,
  PluginArray: 0,
  SVGLengthList: 0,
  SVGNumberList: 0,
  SVGPathSegList: 0,
  SVGPointList: 0,
  SVGStringList: 0,
  SVGTransformList: 0,
  SourceBufferList: 0,
  StyleSheetList: 0,
  TextTrackCueList: 0,
  TextTrackList: 0,
  TouchList: 0
};

var DOMIterables$4 = domIterables$1;
var global$a$1 = global$m;
var classof$7$1 = classof$d$1;
var createNonEnumerableProperty$4$1 = createNonEnumerableProperty$9;
var Iterators$2$1 = iterators$1;
var wellKnownSymbol$9$1 = wellKnownSymbol$m;

var TO_STRING_TAG$1$1 = wellKnownSymbol$9$1('toStringTag');

for (var COLLECTION_NAME$1 in DOMIterables$4) {
  var Collection$1 = global$a$1[COLLECTION_NAME$1];
  var CollectionPrototype$1 = Collection$1 && Collection$1.prototype;
  if (CollectionPrototype$1 && classof$7$1(CollectionPrototype$1) !== TO_STRING_TAG$1$1) {
    createNonEnumerableProperty$4$1(CollectionPrototype$1, TO_STRING_TAG$1$1, COLLECTION_NAME$1);
  }
  Iterators$2$1[COLLECTION_NAME$1] = Iterators$2$1.Array;
}

var parent$12$1 = symbol$6$1;


var symbol$5$1 = parent$12$1;

var defineWellKnownSymbol$7$1 = wellKnownSymbolDefine$1;

// `Symbol.dispose` well-known symbol
// https://github.com/tc39/proposal-explicit-resource-management
defineWellKnownSymbol$7$1('dispose');

var parent$11$1 = symbol$5$1;



var symbol$4$1 = parent$11$1;

var defineWellKnownSymbol$6$1 = wellKnownSymbolDefine$1;

// `Symbol.asyncDispose` well-known symbol
// https://github.com/tc39/proposal-async-explicit-resource-management
defineWellKnownSymbol$6$1('asyncDispose');

var $$D$1 = _export$1;
var getBuiltIn$7$1 = getBuiltIn$f;
var uncurryThis$9$1 = functionUncurryThis$1;

var Symbol$2$1 = getBuiltIn$7$1('Symbol');
var keyFor$1 = Symbol$2$1.keyFor;
var thisSymbolValue$1$1 = uncurryThis$9$1(Symbol$2$1.prototype.valueOf);

// `Symbol.isRegistered` method
// https://tc39.es/proposal-symbol-predicates/#sec-symbol-isregistered
$$D$1({ target: 'Symbol', stat: true }, {
  isRegistered: function isRegistered(value) {
    try {
      return keyFor$1(thisSymbolValue$1$1(value)) !== undefined;
    } catch (error) {
      return false;
    }
  }
});

var $$C$1 = _export$1;
var shared$8 = sharedExports$1;
var getBuiltIn$6$1 = getBuiltIn$f;
var uncurryThis$8$1 = functionUncurryThis$1;
var isSymbol$6 = isSymbol$5$1;
var wellKnownSymbol$8$1 = wellKnownSymbol$m;

var Symbol$1$1 = getBuiltIn$6$1('Symbol');
var $isWellKnown$1 = Symbol$1$1.isWellKnown;
var getOwnPropertyNames$5 = getBuiltIn$6$1('Object', 'getOwnPropertyNames');
var thisSymbolValue$2 = uncurryThis$8$1(Symbol$1$1.prototype.valueOf);
var WellKnownSymbolsStore$3 = shared$8('wks');

for (var i$1 = 0, symbolKeys$1 = getOwnPropertyNames$5(Symbol$1$1), symbolKeysLength$1 = symbolKeys$1.length; i$1 < symbolKeysLength$1; i$1++) {
  // some old engines throws on access to some keys like `arguments` or `caller`
  try {
    var symbolKey$1 = symbolKeys$1[i$1];
    if (isSymbol$6(Symbol$1$1[symbolKey$1])) wellKnownSymbol$8$1(symbolKey$1);
  } catch (error) { /* empty */ }
}

// `Symbol.isWellKnown` method
// https://tc39.es/proposal-symbol-predicates/#sec-symbol-iswellknown
// We should patch it for newly added well-known symbols. If it's not required, this module just will not be injected
$$C$1({ target: 'Symbol', stat: true, forced: true }, {
  isWellKnown: function isWellKnown(value) {
    if ($isWellKnown$1 && $isWellKnown$1(value)) return true;
    try {
      var symbol = thisSymbolValue$2(value);
      for (var j = 0, keys = getOwnPropertyNames$5(WellKnownSymbolsStore$3), keysLength = keys.length; j < keysLength; j++) {
        if (WellKnownSymbolsStore$3[keys[j]] == symbol) return true;
      }
    } catch (error) { /* empty */ }
    return false;
  }
});

var defineWellKnownSymbol$5$1 = wellKnownSymbolDefine$1;

// `Symbol.matcher` well-known symbol
// https://github.com/tc39/proposal-pattern-matching
defineWellKnownSymbol$5$1('matcher');

var defineWellKnownSymbol$4$1 = wellKnownSymbolDefine$1;

// `Symbol.metadataKey` well-known symbol
// https://github.com/tc39/proposal-decorator-metadata
defineWellKnownSymbol$4$1('metadataKey');

var defineWellKnownSymbol$3$1 = wellKnownSymbolDefine$1;

// `Symbol.observable` well-known symbol
// https://github.com/tc39/proposal-observable
defineWellKnownSymbol$3$1('observable');

// TODO: Remove from `core-js@4`
var defineWellKnownSymbol$2$1 = wellKnownSymbolDefine$1;

// `Symbol.metadata` well-known symbol
// https://github.com/tc39/proposal-decorators
defineWellKnownSymbol$2$1('metadata');

// TODO: remove from `core-js@4`
var defineWellKnownSymbol$1$1 = wellKnownSymbolDefine$1;

// `Symbol.patternMatch` well-known symbol
// https://github.com/tc39/proposal-pattern-matching
defineWellKnownSymbol$1$1('patternMatch');

// TODO: remove from `core-js@4`
var defineWellKnownSymbol$m = wellKnownSymbolDefine$1;

defineWellKnownSymbol$m('replaceAll');

var parent$10$1 = symbol$4$1;






// TODO: Remove from `core-js@4`




var symbol$3$1 = parent$10$1;

var symbol$2$1 = symbol$3$1;

var symbol$1$1 = symbol$2$1;

var _Symbol$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(symbol$1$1);

var uncurryThis$7$1 = functionUncurryThis$1;
var toIntegerOrInfinity$1$1 = toIntegerOrInfinity$4$1;
var toString$3$1 = toString$7$1;
var requireObjectCoercible$6 = requireObjectCoercible$3$1;

var charAt$1$1 = uncurryThis$7$1(''.charAt);
var charCodeAt$2 = uncurryThis$7$1(''.charCodeAt);
var stringSlice$2 = uncurryThis$7$1(''.slice);

var createMethod$1$1 = function (CONVERT_TO_STRING) {
  return function ($this, pos) {
    var S = toString$3$1(requireObjectCoercible$6($this));
    var position = toIntegerOrInfinity$1$1(pos);
    var size = S.length;
    var first, second;
    if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
    first = charCodeAt$2(S, position);
    return first < 0xD800 || first > 0xDBFF || position + 1 === size
      || (second = charCodeAt$2(S, position + 1)) < 0xDC00 || second > 0xDFFF
        ? CONVERT_TO_STRING
          ? charAt$1$1(S, position)
          : first
        : CONVERT_TO_STRING
          ? stringSlice$2(S, position, position + 2)
          : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
  };
};

var stringMultibyte$1 = {
  // `String.prototype.codePointAt` method
  // https://tc39.es/ecma262/#sec-string.prototype.codepointat
  codeAt: createMethod$1$1(false),
  // `String.prototype.at` method
  // https://github.com/mathiasbynens/String.prototype.at
  charAt: createMethod$1$1(true)
};

var charAt$4 = stringMultibyte$1.charAt;
var toString$2$1 = toString$7$1;
var InternalStateModule$3$1 = internalState$1;
var defineIterator$1$1 = iteratorDefine$1;
var createIterResultObject$1$1 = createIterResultObject$3$1;

var STRING_ITERATOR$1 = 'String Iterator';
var setInternalState$3$1 = InternalStateModule$3$1.set;
var getInternalState$3 = InternalStateModule$3$1.getterFor(STRING_ITERATOR$1);

// `String.prototype[@@iterator]` method
// https://tc39.es/ecma262/#sec-string.prototype-@@iterator
defineIterator$1$1(String, 'String', function (iterated) {
  setInternalState$3$1(this, {
    type: STRING_ITERATOR$1,
    string: toString$2$1(iterated),
    index: 0
  });
// `%StringIteratorPrototype%.next` method
// https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next
}, function next() {
  var state = getInternalState$3(this);
  var string = state.string;
  var index = state.index;
  var point;
  if (index >= string.length) return createIterResultObject$1$1(undefined, true);
  point = charAt$4(string, index);
  state.index += point.length;
  return createIterResultObject$1$1(point, false);
});

var WrappedWellKnownSymbolModule$1$1 = wellKnownSymbolWrapped$1;

var iterator$6$1 = WrappedWellKnownSymbolModule$1$1.f('iterator');

var parent$$$1 = iterator$6$1;


var iterator$5$1 = parent$$$1;

var parent$_$1 = iterator$5$1;

var iterator$4$1 = parent$_$1;

var parent$Z$1 = iterator$4$1;

var iterator$3$1 = parent$Z$1;

var iterator$2$1 = iterator$3$1;

var iterator$1$1 = iterator$2$1;

var _Symbol$iterator$2 = /*@__PURE__*/getDefaultExportFromCjs$2(iterator$1$1);

function _typeof$1(obj) {
  "@babel/helpers - typeof";

  return _typeof$1 = "function" == typeof _Symbol$1$1 && "symbol" == typeof _Symbol$iterator$2 ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && "function" == typeof _Symbol$1$1 && obj.constructor === _Symbol$1$1 && obj !== _Symbol$1$1.prototype ? "symbol" : typeof obj;
  }, _typeof$1(obj);
}

var WrappedWellKnownSymbolModule$2 = wellKnownSymbolWrapped$1;

var toPrimitive$5$1 = WrappedWellKnownSymbolModule$2.f('toPrimitive');

var parent$Y$1 = toPrimitive$5$1;

var toPrimitive$4$1 = parent$Y$1;

var parent$X$1 = toPrimitive$4$1;

var toPrimitive$3$1 = parent$X$1;

var parent$W$1 = toPrimitive$3$1;

var toPrimitive$2$1 = parent$W$1;

var toPrimitive$1$1 = toPrimitive$2$1;

var toPrimitive$8 = toPrimitive$1$1;

var _Symbol$toPrimitive$1 = /*@__PURE__*/getDefaultExportFromCjs$2(toPrimitive$8);

function _toPrimitive$1(input, hint) {
  if (_typeof$1(input) !== "object" || input === null) return input;
  var prim = input[_Symbol$toPrimitive$1];
  if (prim !== undefined) {
    var res = prim.call(input, hint || "default");
    if (_typeof$1(res) !== "object") return res;
    throw new TypeError("@@toPrimitive must return a primitive value.");
  }
  return (hint === "string" ? String : Number)(input);
}

function _toPropertyKey$1(arg) {
  var key = _toPrimitive$1(arg, "string");
  return _typeof$1(key) === "symbol" ? key : String(key);
}

function _defineProperties$1(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$1$1(target, _toPropertyKey$1(descriptor.key), descriptor);
  }
}
function _createClass$1(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties$1(Constructor, staticProps);
  _Object$defineProperty$1$1(Constructor, "prototype", {
    writable: false
  });
  return Constructor;
}

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

var uncurryThis$6$1 = functionUncurryThis$1;
var aCallable$a = aCallable$e;
var isObject$8$1 = isObject$h$1;
var hasOwn$7$1 = hasOwnProperty_1$1;
var arraySlice$3$1 = arraySlice$5$1;
var NATIVE_BIND$5 = functionBindNative$1;

var $Function$1 = Function;
var concat$6$1 = uncurryThis$6$1([].concat);
var join$1 = uncurryThis$6$1([].join);
var factories$1 = {};

var construct$3$1 = function (C, argsLength, args) {
  if (!hasOwn$7$1(factories$1, argsLength)) {
    for (var list = [], i = 0; i < argsLength; i++) list[i] = 'a[' + i + ']';
    factories$1[argsLength] = $Function$1('C,a', 'return new C(' + join$1(list, ',') + ')');
  } return factories$1[argsLength](C, args);
};

// `Function.prototype.bind` method implementation
// https://tc39.es/ecma262/#sec-function.prototype.bind
// eslint-disable-next-line es/no-function-prototype-bind -- detection
var functionBind$1 = NATIVE_BIND$5 ? $Function$1.bind : function bind(that /* , ...args */) {
  var F = aCallable$a(this);
  var Prototype = F.prototype;
  var partArgs = arraySlice$3$1(arguments, 1);
  var boundFunction = function bound(/* args... */) {
    var args = concat$6$1(partArgs, arraySlice$3$1(arguments));
    return this instanceof boundFunction ? construct$3$1(F, args.length, args) : F.apply(that, args);
  };
  if (isObject$8$1(Prototype)) boundFunction.prototype = Prototype;
  return boundFunction;
};

// TODO: Remove from `core-js@4`
var $$B$1 = _export$1;
var bind$g$1 = functionBind$1;

// `Function.prototype.bind` method
// https://tc39.es/ecma262/#sec-function.prototype.bind
// eslint-disable-next-line es/no-function-prototype-bind -- detection
$$B$1({ target: 'Function', proto: true, forced: Function.bind !== bind$g$1 }, {
  bind: bind$g$1
});

var path$i$1 = path$o$1;

var entryVirtual$f$1 = function (CONSTRUCTOR) {
  return path$i$1[CONSTRUCTOR + 'Prototype'];
};

var entryVirtual$e$1 = entryVirtual$f$1;

var bind$f$1 = entryVirtual$e$1('Function').bind;

var isPrototypeOf$h$1 = objectIsPrototypeOf$1;
var method$e$1 = bind$f$1;

var FunctionPrototype$4 = Function.prototype;

var bind$e$1 = function (it) {
  var own = it.bind;
  return it === FunctionPrototype$4 || (isPrototypeOf$h$1(FunctionPrototype$4, it) && own === FunctionPrototype$4.bind) ? method$e$1 : own;
};

var parent$V$1 = bind$e$1;

var bind$d$1 = parent$V$1;

var bind$c$1 = bind$d$1;

var _bindInstanceProperty$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(bind$c$1);

var aCallable$9 = aCallable$e;
var toObject$7$1 = toObject$d$1;
var IndexedObject$1$1 = indexedObject$1;
var lengthOfArrayLike$7$1 = lengthOfArrayLike$c;

var $TypeError$8$1 = TypeError;

// `Array.prototype.{ reduce, reduceRight }` methods implementation
var createMethod$6 = function (IS_RIGHT) {
  return function (that, callbackfn, argumentsLength, memo) {
    aCallable$9(callbackfn);
    var O = toObject$7$1(that);
    var self = IndexedObject$1$1(O);
    var length = lengthOfArrayLike$7$1(O);
    var index = IS_RIGHT ? length - 1 : 0;
    var i = IS_RIGHT ? -1 : 1;
    if (argumentsLength < 2) while (true) {
      if (index in self) {
        memo = self[index];
        index += i;
        break;
      }
      index += i;
      if (IS_RIGHT ? index < 0 : length <= index) {
        throw $TypeError$8$1('Reduce of empty array with no initial value');
      }
    }
    for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
      memo = callbackfn(memo, self[index], index, O);
    }
    return memo;
  };
};

var arrayReduce$1 = {
  // `Array.prototype.reduce` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduce
  left: createMethod$6(false),
  // `Array.prototype.reduceRight` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduceright
  right: createMethod$6(true)
};

var fails$d$1 = fails$t$1;

var arrayMethodIsStrict$4$1 = function (METHOD_NAME, argument) {
  var method = [][METHOD_NAME];
  return !!method && fails$d$1(function () {
    // eslint-disable-next-line no-useless-call -- required for testing
    method.call(null, argument || function () { return 1; }, 1);
  });
};

var classof$6$1 = classofRaw$2$1;

var engineIsNode$1 = typeof process != 'undefined' && classof$6$1(process) == 'process';

var $$A$1 = _export$1;
var $reduce$1 = arrayReduce$1.left;
var arrayMethodIsStrict$3$1 = arrayMethodIsStrict$4$1;
var CHROME_VERSION$1 = engineV8Version$1;
var IS_NODE$4 = engineIsNode$1;

// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG$1 = !IS_NODE$4 && CHROME_VERSION$1 > 79 && CHROME_VERSION$1 < 83;
var FORCED$3$1 = CHROME_BUG$1 || !arrayMethodIsStrict$3$1('reduce');

// `Array.prototype.reduce` method
// https://tc39.es/ecma262/#sec-array.prototype.reduce
$$A$1({ target: 'Array', proto: true, forced: FORCED$3$1 }, {
  reduce: function reduce(callbackfn /* , initialValue */) {
    var length = arguments.length;
    return $reduce$1(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$d$1 = entryVirtual$f$1;

var reduce$3$1 = entryVirtual$d$1('Array').reduce;

var isPrototypeOf$g$1 = objectIsPrototypeOf$1;
var method$d$1 = reduce$3$1;

var ArrayPrototype$e$1 = Array.prototype;

var reduce$2$1 = function (it) {
  var own = it.reduce;
  return it === ArrayPrototype$e$1 || (isPrototypeOf$g$1(ArrayPrototype$e$1, it) && own === ArrayPrototype$e$1.reduce) ? method$d$1 : own;
};

var parent$U$1 = reduce$2$1;

var reduce$1$1 = parent$U$1;

var reduce$5 = reduce$1$1;

var _reduceInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(reduce$5);

var $$z$1 = _export$1;
var $filter$1 = arrayIteration$1.filter;
var arrayMethodHasSpeciesSupport$3$1 = arrayMethodHasSpeciesSupport$5$1;

var HAS_SPECIES_SUPPORT$3$1 = arrayMethodHasSpeciesSupport$3$1('filter');

// `Array.prototype.filter` method
// https://tc39.es/ecma262/#sec-array.prototype.filter
// with adding support of @@species
$$z$1({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3$1 }, {
  filter: function filter(callbackfn /* , thisArg */) {
    return $filter$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$c$1 = entryVirtual$f$1;

var filter$3$1 = entryVirtual$c$1('Array').filter;

var isPrototypeOf$f$1 = objectIsPrototypeOf$1;
var method$c$1 = filter$3$1;

var ArrayPrototype$d$1 = Array.prototype;

var filter$2$1 = function (it) {
  var own = it.filter;
  return it === ArrayPrototype$d$1 || (isPrototypeOf$f$1(ArrayPrototype$d$1, it) && own === ArrayPrototype$d$1.filter) ? method$c$1 : own;
};

var parent$T$1 = filter$2$1;

var filter$1$1 = parent$T$1;

var filter$5 = filter$1$1;

var _filterInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(filter$5);

var $$y$1 = _export$1;
var $map$1 = arrayIteration$1.map;
var arrayMethodHasSpeciesSupport$2$1 = arrayMethodHasSpeciesSupport$5$1;

var HAS_SPECIES_SUPPORT$2$1 = arrayMethodHasSpeciesSupport$2$1('map');

// `Array.prototype.map` method
// https://tc39.es/ecma262/#sec-array.prototype.map
// with adding support of @@species
$$y$1({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2$1 }, {
  map: function map(callbackfn /* , thisArg */) {
    return $map$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$b$1 = entryVirtual$f$1;

var map$6$1 = entryVirtual$b$1('Array').map;

var isPrototypeOf$e$1 = objectIsPrototypeOf$1;
var method$b$1 = map$6$1;

var ArrayPrototype$c$1 = Array.prototype;

var map$5$1 = function (it) {
  var own = it.map;
  return it === ArrayPrototype$c$1 || (isPrototypeOf$e$1(ArrayPrototype$c$1, it) && own === ArrayPrototype$c$1.map) ? method$b$1 : own;
};

var parent$S$1 = map$5$1;

var map$4$1 = parent$S$1;

var map$3$1 = map$4$1;

var _mapInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(map$3$1);

var isArray$b$1 = isArray$f$1;
var lengthOfArrayLike$6$1 = lengthOfArrayLike$c;
var doesNotExceedSafeInteger$1$1 = doesNotExceedSafeInteger$3;
var bind$b$1 = functionBindContext$1;

// `FlattenIntoArray` abstract operation
// https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
var flattenIntoArray$1 = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
  var targetIndex = start;
  var sourceIndex = 0;
  var mapFn = mapper ? bind$b$1(mapper, thisArg) : false;
  var element, elementLen;

  while (sourceIndex < sourceLen) {
    if (sourceIndex in source) {
      element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];

      if (depth > 0 && isArray$b$1(element)) {
        elementLen = lengthOfArrayLike$6$1(element);
        targetIndex = flattenIntoArray$1(target, original, element, elementLen, targetIndex, depth - 1) - 1;
      } else {
        doesNotExceedSafeInteger$1$1(targetIndex + 1);
        target[targetIndex] = element;
      }

      targetIndex++;
    }
    sourceIndex++;
  }
  return targetIndex;
};

var flattenIntoArray_1 = flattenIntoArray$1;

var $$x$1 = _export$1;
var flattenIntoArray = flattenIntoArray_1;
var aCallable$8 = aCallable$e;
var toObject$6$1 = toObject$d$1;
var lengthOfArrayLike$5$1 = lengthOfArrayLike$c;
var arraySpeciesCreate$1$1 = arraySpeciesCreate$4;

// `Array.prototype.flatMap` method
// https://tc39.es/ecma262/#sec-array.prototype.flatmap
$$x$1({ target: 'Array', proto: true }, {
  flatMap: function flatMap(callbackfn /* , thisArg */) {
    var O = toObject$6$1(this);
    var sourceLen = lengthOfArrayLike$5$1(O);
    var A;
    aCallable$8(callbackfn);
    A = arraySpeciesCreate$1$1(O, 0);
    A.length = flattenIntoArray(A, O, O, sourceLen, 0, 1, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
    return A;
  }
});

var entryVirtual$a$1 = entryVirtual$f$1;

entryVirtual$a$1('Array').flatMap;

var call$a$1 = functionCall$1;
var anObject$7$1 = anObject$d$1;
var getMethod$1$1 = getMethod$3$1;

var iteratorClose$2$1 = function (iterator, kind, value) {
  var innerResult, innerError;
  anObject$7$1(iterator);
  try {
    innerResult = getMethod$1$1(iterator, 'return');
    if (!innerResult) {
      if (kind === 'throw') throw value;
      return value;
    }
    innerResult = call$a$1(innerResult, iterator);
  } catch (error) {
    innerError = true;
    innerResult = error;
  }
  if (kind === 'throw') throw value;
  if (innerError) throw innerResult;
  anObject$7$1(innerResult);
  return value;
};

var anObject$6$1 = anObject$d$1;
var iteratorClose$1$1 = iteratorClose$2$1;

// call something on iterator step with safe closing on error
var callWithSafeIterationClosing$1$1 = function (iterator, fn, value, ENTRIES) {
  try {
    return ENTRIES ? fn(anObject$6$1(value)[0], value[1]) : fn(value);
  } catch (error) {
    iteratorClose$1$1(iterator, 'throw', error);
  }
};

var wellKnownSymbol$7$1 = wellKnownSymbol$m;
var Iterators$1$1 = iterators$1;

var ITERATOR$2$1 = wellKnownSymbol$7$1('iterator');
var ArrayPrototype$a$1 = Array.prototype;

// check on default Array iterator
var isArrayIteratorMethod$2$1 = function (it) {
  return it !== undefined && (Iterators$1$1.Array === it || ArrayPrototype$a$1[ITERATOR$2$1] === it);
};

var classof$5$1 = classof$d$1;
var getMethod$4 = getMethod$3$1;
var isNullOrUndefined$2$1 = isNullOrUndefined$5$1;
var Iterators$6 = iterators$1;
var wellKnownSymbol$6$1 = wellKnownSymbol$m;

var ITERATOR$1$1 = wellKnownSymbol$6$1('iterator');

var getIteratorMethod$9$1 = function (it) {
  if (!isNullOrUndefined$2$1(it)) return getMethod$4(it, ITERATOR$1$1)
    || getMethod$4(it, '@@iterator')
    || Iterators$6[classof$5$1(it)];
};

var call$9$1 = functionCall$1;
var aCallable$7$1 = aCallable$e;
var anObject$5$1 = anObject$d$1;
var tryToString$3$1 = tryToString$6$1;
var getIteratorMethod$8$1 = getIteratorMethod$9$1;

var $TypeError$7$1 = TypeError;

var getIterator$8 = function (argument, usingIterator) {
  var iteratorMethod = arguments.length < 2 ? getIteratorMethod$8$1(argument) : usingIterator;
  if (aCallable$7$1(iteratorMethod)) return anObject$5$1(call$9$1(iteratorMethod, argument));
  throw $TypeError$7$1(tryToString$3$1(argument) + ' is not iterable');
};

var bind$a$1 = functionBindContext$1;
var call$8$1 = functionCall$1;
var toObject$5$1 = toObject$d$1;
var callWithSafeIterationClosing$2 = callWithSafeIterationClosing$1$1;
var isArrayIteratorMethod$1$1 = isArrayIteratorMethod$2$1;
var isConstructor$2$1 = isConstructor$4$1;
var lengthOfArrayLike$4$1 = lengthOfArrayLike$c;
var createProperty$3$1 = createProperty$6$1;
var getIterator$7 = getIterator$8;
var getIteratorMethod$7$1 = getIteratorMethod$9$1;

var $Array$1$1 = Array;

// `Array.from` method implementation
// https://tc39.es/ecma262/#sec-array.from
var arrayFrom$1 = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
  var O = toObject$5$1(arrayLike);
  var IS_CONSTRUCTOR = isConstructor$2$1(this);
  var argumentsLength = arguments.length;
  var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
  var mapping = mapfn !== undefined;
  if (mapping) mapfn = bind$a$1(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
  var iteratorMethod = getIteratorMethod$7$1(O);
  var index = 0;
  var length, result, step, iterator, next, value;
  // if the target is not iterable or it's an array with the default iterator - use a simple case
  if (iteratorMethod && !(this === $Array$1$1 && isArrayIteratorMethod$1$1(iteratorMethod))) {
    iterator = getIterator$7(O, iteratorMethod);
    next = iterator.next;
    result = IS_CONSTRUCTOR ? new this() : [];
    for (;!(step = call$8$1(next, iterator)).done; index++) {
      value = mapping ? callWithSafeIterationClosing$2(iterator, mapfn, [step.value, index], true) : step.value;
      createProperty$3$1(result, index, value);
    }
  } else {
    length = lengthOfArrayLike$4$1(O);
    result = IS_CONSTRUCTOR ? new this(length) : $Array$1$1(length);
    for (;length > index; index++) {
      value = mapping ? mapfn(O[index], index) : O[index];
      createProperty$3$1(result, index, value);
    }
  }
  result.length = index;
  return result;
};

var wellKnownSymbol$5$1 = wellKnownSymbol$m;

var ITERATOR$7 = wellKnownSymbol$5$1('iterator');
var SAFE_CLOSING$1 = false;

try {
  var called$1 = 0;
  var iteratorWithReturn$1 = {
    next: function () {
      return { done: !!called$1++ };
    },
    'return': function () {
      SAFE_CLOSING$1 = true;
    }
  };
  iteratorWithReturn$1[ITERATOR$7] = function () {
    return this;
  };
  // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
  Array.from(iteratorWithReturn$1, function () { throw 2; });
} catch (error) { /* empty */ }

var checkCorrectnessOfIteration$2 = function (exec, SKIP_CLOSING) {
  if (!SKIP_CLOSING && !SAFE_CLOSING$1) return false;
  var ITERATION_SUPPORT = false;
  try {
    var object = {};
    object[ITERATOR$7] = function () {
      return {
        next: function () {
          return { done: ITERATION_SUPPORT = true };
        }
      };
    };
    exec(object);
  } catch (error) { /* empty */ }
  return ITERATION_SUPPORT;
};

var $$w$1 = _export$1;
var from$7$1 = arrayFrom$1;
var checkCorrectnessOfIteration$1$1 = checkCorrectnessOfIteration$2;

var INCORRECT_ITERATION$1 = !checkCorrectnessOfIteration$1$1(function (iterable) {
  // eslint-disable-next-line es/no-array-from -- required for testing
  Array.from(iterable);
});

// `Array.from` method
// https://tc39.es/ecma262/#sec-array.from
$$w$1({ target: 'Array', stat: true, forced: INCORRECT_ITERATION$1 }, {
  from: from$7$1
});

var path$h$1 = path$o$1;

var from$6$1 = path$h$1.Array.from;

var parent$Q$1 = from$6$1;

var from$5$1 = parent$Q$1;

var from$4$1 = from$5$1;

var _Array$from$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(from$4$1);

var getIteratorMethod$6$1 = getIteratorMethod$9$1;

var getIteratorMethod_1$1 = getIteratorMethod$6$1;

var parent$P$1 = getIteratorMethod_1$1;


var getIteratorMethod$5$1 = parent$P$1;

var parent$O$1 = getIteratorMethod$5$1;

var getIteratorMethod$4$1 = parent$O$1;

var parent$N$1 = getIteratorMethod$4$1;

var getIteratorMethod$3$1 = parent$N$1;

var getIteratorMethod$2$1 = getIteratorMethod$3$1;

var getIteratorMethod$1$1 = getIteratorMethod$2$1;

var _getIteratorMethod$1 = /*@__PURE__*/getDefaultExportFromCjs$2(getIteratorMethod$1$1);

var path$g$1 = path$o$1;

var getOwnPropertySymbols$2$1 = path$g$1.Object.getOwnPropertySymbols;

var parent$M$1 = getOwnPropertySymbols$2$1;

var getOwnPropertySymbols$1$1 = parent$M$1;

var getOwnPropertySymbols$3 = getOwnPropertySymbols$1$1;

var _Object$getOwnPropertySymbols$1 = /*@__PURE__*/getDefaultExportFromCjs$2(getOwnPropertySymbols$3);

var getOwnPropertyDescriptor$5$1 = {exports: {}};

var $$v$1 = _export$1;
var fails$c$1 = fails$t$1;
var toIndexedObject$2$1 = toIndexedObject$a$1;
var nativeGetOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor$1.f;
var DESCRIPTORS$8$1 = descriptors$1;

var FORCED$2$1 = !DESCRIPTORS$8$1 || fails$c$1(function () { nativeGetOwnPropertyDescriptor$2(1); });

// `Object.getOwnPropertyDescriptor` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
$$v$1({ target: 'Object', stat: true, forced: FORCED$2$1, sham: !DESCRIPTORS$8$1 }, {
  getOwnPropertyDescriptor: function getOwnPropertyDescriptor(it, key) {
    return nativeGetOwnPropertyDescriptor$2(toIndexedObject$2$1(it), key);
  }
});

var path$f$1 = path$o$1;

var Object$3$1 = path$f$1.Object;

var getOwnPropertyDescriptor$4$1 = getOwnPropertyDescriptor$5$1.exports = function getOwnPropertyDescriptor(it, key) {
  return Object$3$1.getOwnPropertyDescriptor(it, key);
};

if (Object$3$1.getOwnPropertyDescriptor.sham) getOwnPropertyDescriptor$4$1.sham = true;

var getOwnPropertyDescriptorExports$4 = getOwnPropertyDescriptor$5$1.exports;

var parent$L$1 = getOwnPropertyDescriptorExports$4;

var getOwnPropertyDescriptor$3$1 = parent$L$1;

var getOwnPropertyDescriptor$2$1 = getOwnPropertyDescriptor$3$1;

var _Object$getOwnPropertyDescriptor$2 = /*@__PURE__*/getDefaultExportFromCjs$2(getOwnPropertyDescriptor$2$1);

var getBuiltIn$5$1 = getBuiltIn$f;
var uncurryThis$5$1 = functionUncurryThis$1;
var getOwnPropertyNamesModule$1$1 = objectGetOwnPropertyNames$1;
var getOwnPropertySymbolsModule$1$1 = objectGetOwnPropertySymbols$1;
var anObject$4$1 = anObject$d$1;

var concat$5$1 = uncurryThis$5$1([].concat);

// all object keys, includes non-enumerable and symbols
var ownKeys$7$1 = getBuiltIn$5$1('Reflect', 'ownKeys') || function ownKeys(it) {
  var keys = getOwnPropertyNamesModule$1$1.f(anObject$4$1(it));
  var getOwnPropertySymbols = getOwnPropertySymbolsModule$1$1.f;
  return getOwnPropertySymbols ? concat$5$1(keys, getOwnPropertySymbols(it)) : keys;
};

var $$u$1 = _export$1;
var DESCRIPTORS$7$1 = descriptors$1;
var ownKeys$6$1 = ownKeys$7$1;
var toIndexedObject$1$1 = toIndexedObject$a$1;
var getOwnPropertyDescriptorModule$1$1 = objectGetOwnPropertyDescriptor$1;
var createProperty$2$1 = createProperty$6$1;

// `Object.getOwnPropertyDescriptors` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
$$u$1({ target: 'Object', stat: true, sham: !DESCRIPTORS$7$1 }, {
  getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) {
    var O = toIndexedObject$1$1(object);
    var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$1$1.f;
    var keys = ownKeys$6$1(O);
    var result = {};
    var index = 0;
    var key, descriptor;
    while (keys.length > index) {
      descriptor = getOwnPropertyDescriptor(O, key = keys[index++]);
      if (descriptor !== undefined) createProperty$2$1(result, key, descriptor);
    }
    return result;
  }
});

var path$e$1 = path$o$1;

var getOwnPropertyDescriptors$2$1 = path$e$1.Object.getOwnPropertyDescriptors;

var parent$K$1 = getOwnPropertyDescriptors$2$1;

var getOwnPropertyDescriptors$1$1 = parent$K$1;

var getOwnPropertyDescriptors$3 = getOwnPropertyDescriptors$1$1;

var _Object$getOwnPropertyDescriptors$1 = /*@__PURE__*/getDefaultExportFromCjs$2(getOwnPropertyDescriptors$3);

var defineProperties$4$1 = {exports: {}};

var $$t$1 = _export$1;
var DESCRIPTORS$6$1 = descriptors$1;
var defineProperties$3$1 = objectDefineProperties$1.f;

// `Object.defineProperties` method
// https://tc39.es/ecma262/#sec-object.defineproperties
// eslint-disable-next-line es/no-object-defineproperties -- safe
$$t$1({ target: 'Object', stat: true, forced: Object.defineProperties !== defineProperties$3$1, sham: !DESCRIPTORS$6$1 }, {
  defineProperties: defineProperties$3$1
});

var path$d$1 = path$o$1;

var Object$2$1 = path$d$1.Object;

var defineProperties$2$1 = defineProperties$4$1.exports = function defineProperties(T, D) {
  return Object$2$1.defineProperties(T, D);
};

if (Object$2$1.defineProperties.sham) defineProperties$2$1.sham = true;

var definePropertiesExports$2 = defineProperties$4$1.exports;

var parent$J$1 = definePropertiesExports$2;

var defineProperties$1$1 = parent$J$1;

var defineProperties$5 = defineProperties$1$1;

var _Object$defineProperties$1 = /*@__PURE__*/getDefaultExportFromCjs$2(defineProperties$5);

var defineProperty$3$1 = defineProperty$b$1;

var _Object$defineProperty$2 = /*@__PURE__*/getDefaultExportFromCjs$2(defineProperty$3$1);

var $$s$1 = _export$1;
var isArray$a$1 = isArray$f$1;

// `Array.isArray` method
// https://tc39.es/ecma262/#sec-array.isarray
$$s$1({ target: 'Array', stat: true }, {
  isArray: isArray$a$1
});

var path$c$1 = path$o$1;

var isArray$9$1 = path$c$1.Array.isArray;

var parent$I$1 = isArray$9$1;

var isArray$8$1 = parent$I$1;

var parent$H$1 = isArray$8$1;

var isArray$7$1 = parent$H$1;

var parent$G$1 = isArray$7$1;

var isArray$6$1 = parent$G$1;

var isArray$5$1 = isArray$6$1;

var isArray$4$1 = isArray$5$1;

var _Array$isArray$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(isArray$4$1);

function _arrayWithHoles$1(arr) {
  if (_Array$isArray$1$1(arr)) return arr;
}

function _iterableToArrayLimit$1(arr, i) {
  var _i = null == arr ? null : "undefined" != typeof _Symbol$1$1 && _getIteratorMethod$1(arr) || arr["@@iterator"];
  if (null != _i) {
    var _s,
      _e,
      _x,
      _r,
      _arr = [],
      _n = !0,
      _d = !1;
    try {
      if (_x = (_i = _i.call(arr)).next, 0 === i) {
        if (Object(_i) !== _i) return;
        _n = !1;
      } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
    } catch (err) {
      _d = !0, _e = err;
    } finally {
      try {
        if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return;
      } finally {
        if (_d) throw _e;
      }
    }
    return _arr;
  }
}

var $$r$1 = _export$1;
var isArray$3$1 = isArray$f$1;
var isConstructor$1$1 = isConstructor$4$1;
var isObject$7$1 = isObject$h$1;
var toAbsoluteIndex$1$1 = toAbsoluteIndex$4$1;
var lengthOfArrayLike$3$1 = lengthOfArrayLike$c;
var toIndexedObject$c = toIndexedObject$a$1;
var createProperty$1$1 = createProperty$6$1;
var wellKnownSymbol$4$1 = wellKnownSymbol$m;
var arrayMethodHasSpeciesSupport$1$1 = arrayMethodHasSpeciesSupport$5$1;
var nativeSlice$2 = arraySlice$5$1;

var HAS_SPECIES_SUPPORT$1$1 = arrayMethodHasSpeciesSupport$1$1('slice');

var SPECIES$3$1 = wellKnownSymbol$4$1('species');
var $Array$4 = Array;
var max$1$2 = Math.max;

// `Array.prototype.slice` method
// https://tc39.es/ecma262/#sec-array.prototype.slice
// fallback for not array-like ES3 strings and DOM objects
$$r$1({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1$1 }, {
  slice: function slice(start, end) {
    var O = toIndexedObject$c(this);
    var length = lengthOfArrayLike$3$1(O);
    var k = toAbsoluteIndex$1$1(start, length);
    var fin = toAbsoluteIndex$1$1(end === undefined ? length : end, length);
    // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
    var Constructor, result, n;
    if (isArray$3$1(O)) {
      Constructor = O.constructor;
      // cross-realm fallback
      if (isConstructor$1$1(Constructor) && (Constructor === $Array$4 || isArray$3$1(Constructor.prototype))) {
        Constructor = undefined;
      } else if (isObject$7$1(Constructor)) {
        Constructor = Constructor[SPECIES$3$1];
        if (Constructor === null) Constructor = undefined;
      }
      if (Constructor === $Array$4 || Constructor === undefined) {
        return nativeSlice$2(O, k, fin);
      }
    }
    result = new (Constructor === undefined ? $Array$4 : Constructor)(max$1$2(fin - k, 0));
    for (n = 0; k < fin; k++, n++) if (k in O) createProperty$1$1(result, n, O[k]);
    result.length = n;
    return result;
  }
});

var entryVirtual$9$1 = entryVirtual$f$1;

var slice$7$1 = entryVirtual$9$1('Array').slice;

var isPrototypeOf$c$1 = objectIsPrototypeOf$1;
var method$9$1 = slice$7$1;

var ArrayPrototype$9$1 = Array.prototype;

var slice$6$1 = function (it) {
  var own = it.slice;
  return it === ArrayPrototype$9$1 || (isPrototypeOf$c$1(ArrayPrototype$9$1, it) && own === ArrayPrototype$9$1.slice) ? method$9$1 : own;
};

var parent$F$1 = slice$6$1;

var slice$5$1 = parent$F$1;

var parent$E$1 = slice$5$1;

var slice$4$1 = parent$E$1;

var parent$D$1 = slice$4$1;

var slice$3$1 = parent$D$1;

var slice$2$1 = slice$3$1;

var slice$1$1 = slice$2$1;

var _sliceInstanceProperty$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(slice$1$1);

var parent$C$1 = from$5$1;

var from$3$1 = parent$C$1;

var parent$B$1 = from$3$1;

var from$2$1 = parent$B$1;

var from$1$1 = from$2$1;

var from$8 = from$1$1;

var _Array$from$2 = /*@__PURE__*/getDefaultExportFromCjs$2(from$8);

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

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

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

function _slicedToArray$1(arr, i) {
  return _arrayWithHoles$1(arr) || _iterableToArrayLimit$1(arr, i) || _unsupportedIterableToArray$4$1(arr, i) || _nonIterableRest$1();
}

function _arrayWithoutHoles$1(arr) {
  if (_Array$isArray$1$1(arr)) return _arrayLikeToArray$4$1(arr);
}

function _iterableToArray$1(iter) {
  if (typeof _Symbol$1$1 !== "undefined" && _getIteratorMethod$1(iter) != null || iter["@@iterator"] != null) return _Array$from$2(iter);
}

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

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

var symbol$7 = symbol$5$1;

var _Symbol$2 = /*@__PURE__*/getDefaultExportFromCjs$2(symbol$7);

var entryVirtual$8$1 = entryVirtual$f$1;

var concat$4$1 = entryVirtual$8$1('Array').concat;

var isPrototypeOf$b$1 = objectIsPrototypeOf$1;
var method$8$1 = concat$4$1;

var ArrayPrototype$8$1 = Array.prototype;

var concat$3$1 = function (it) {
  var own = it.concat;
  return it === ArrayPrototype$8$1 || (isPrototypeOf$b$1(ArrayPrototype$8$1, it) && own === ArrayPrototype$8$1.concat) ? method$8$1 : own;
};

var parent$A$1 = concat$3$1;

var concat$2$1 = parent$A$1;

var concat$1$1 = concat$2$1;

var _concatInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(concat$1$1);

var slice$9 = slice$5$1;

var _sliceInstanceProperty$2 = /*@__PURE__*/getDefaultExportFromCjs$2(slice$9);

var $$q$1 = _export$1;
var ownKeys$5$1 = ownKeys$7$1;

// `Reflect.ownKeys` method
// https://tc39.es/ecma262/#sec-reflect.ownkeys
$$q$1({ target: 'Reflect', stat: true }, {
  ownKeys: ownKeys$5$1
});

var path$b$1 = path$o$1;

var ownKeys$4$1 = path$b$1.Reflect.ownKeys;

var parent$z$1 = ownKeys$4$1;

var ownKeys$3$1 = parent$z$1;

var ownKeys$2$1 = ownKeys$3$1;

var _Reflect$ownKeys = /*@__PURE__*/getDefaultExportFromCjs$2(ownKeys$2$1);

var isArray$2$1 = isArray$8$1;

var _Array$isArray$2 = /*@__PURE__*/getDefaultExportFromCjs$2(isArray$2$1);

var $$p$1 = _export$1;
var toObject$4$1 = toObject$d$1;
var nativeKeys$1 = objectKeys$3$1;
var fails$b$1 = fails$t$1;

var FAILS_ON_PRIMITIVES$2$1 = fails$b$1(function () { nativeKeys$1(1); });

// `Object.keys` method
// https://tc39.es/ecma262/#sec-object.keys
$$p$1({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$2$1 }, {
  keys: function keys(it) {
    return nativeKeys$1(toObject$4$1(it));
  }
});

var path$a$1 = path$o$1;

var keys$6 = path$a$1.Object.keys;

var parent$y$1 = keys$6;

var keys$5 = parent$y$1;

var keys$4$1 = keys$5;

var _Object$keys$1 = /*@__PURE__*/getDefaultExportFromCjs$2(keys$4$1);

var $forEach$2 = arrayIteration$1.forEach;
var arrayMethodIsStrict$2$1 = arrayMethodIsStrict$4$1;

var STRICT_METHOD$2$1 = arrayMethodIsStrict$2$1('forEach');

// `Array.prototype.forEach` method implementation
// https://tc39.es/ecma262/#sec-array.prototype.foreach
var arrayForEach$1 = !STRICT_METHOD$2$1 ? function forEach(callbackfn /* , thisArg */) {
  return $forEach$2(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
// eslint-disable-next-line es/no-array-prototype-foreach -- safe
} : [].forEach;

var $$o$1 = _export$1;
var forEach$9 = arrayForEach$1;

// `Array.prototype.forEach` method
// https://tc39.es/ecma262/#sec-array.prototype.foreach
// eslint-disable-next-line es/no-array-prototype-foreach -- safe
$$o$1({ target: 'Array', proto: true, forced: [].forEach != forEach$9 }, {
  forEach: forEach$9
});

var entryVirtual$7$1 = entryVirtual$f$1;

var forEach$8 = entryVirtual$7$1('Array').forEach;

var parent$x$1 = forEach$8;

var forEach$7 = parent$x$1;

var classof$4$1 = classof$d$1;
var hasOwn$6$1 = hasOwnProperty_1$1;
var isPrototypeOf$a$1 = objectIsPrototypeOf$1;
var method$7$1 = forEach$7;

var ArrayPrototype$7$1 = Array.prototype;

var DOMIterables$3 = {
  DOMTokenList: true,
  NodeList: true
};

var forEach$6$1 = function (it) {
  var own = it.forEach;
  return it === ArrayPrototype$7$1 || (isPrototypeOf$a$1(ArrayPrototype$7$1, it) && own === ArrayPrototype$7$1.forEach)
    || hasOwn$6$1(DOMIterables$3, classof$4$1(it)) ? method$7$1 : own;
};

var forEach$5$1 = forEach$6$1;

var _forEachInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(forEach$5$1);

var $$n$1 = _export$1;
var uncurryThis$4$1 = functionUncurryThis$1;
var isArray$1$1 = isArray$f$1;

var nativeReverse$1 = uncurryThis$4$1([].reverse);
var test$1$1 = [1, 2];

// `Array.prototype.reverse` method
// https://tc39.es/ecma262/#sec-array.prototype.reverse
// fix for Safari 12.0 bug
// https://bugs.webkit.org/show_bug.cgi?id=188794
$$n$1({ target: 'Array', proto: true, forced: String(test$1$1) === String(test$1$1.reverse()) }, {
  reverse: function reverse() {
    // eslint-disable-next-line no-self-assign -- dirty hack
    if (isArray$1$1(this)) this.length = this.length;
    return nativeReverse$1(this);
  }
});

var entryVirtual$6$1 = entryVirtual$f$1;

var reverse$7 = entryVirtual$6$1('Array').reverse;

var isPrototypeOf$9$1 = objectIsPrototypeOf$1;
var method$6$1 = reverse$7;

var ArrayPrototype$6$1 = Array.prototype;

var reverse$6 = function (it) {
  var own = it.reverse;
  return it === ArrayPrototype$6$1 || (isPrototypeOf$9$1(ArrayPrototype$6$1, it) && own === ArrayPrototype$6$1.reverse) ? method$6$1 : own;
};

var parent$w$1 = reverse$6;

var reverse$5 = parent$w$1;

var reverse$4 = reverse$5;

var _reverseInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(reverse$4);

var DESCRIPTORS$5$1 = descriptors$1;
var isArray$h = isArray$f$1;

var $TypeError$6$1 = TypeError;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor$1$1 = Object.getOwnPropertyDescriptor;

// Safari < 13 does not throw an error in this case
var SILENT_ON_NON_WRITABLE_LENGTH_SET$1 = DESCRIPTORS$5$1 && !function () {
  // makes no sense without proper strict mode support
  if (this !== undefined) return true;
  try {
    // eslint-disable-next-line es/no-object-defineproperty -- safe
    Object.defineProperty([], 'length', { writable: false }).length = 1;
  } catch (error) {
    return error instanceof TypeError;
  }
}();

var arraySetLength$1 = SILENT_ON_NON_WRITABLE_LENGTH_SET$1 ? function (O, length) {
  if (isArray$h(O) && !getOwnPropertyDescriptor$1$1(O, 'length').writable) {
    throw $TypeError$6$1('Cannot set read only .length');
  } return O.length = length;
} : function (O, length) {
  return O.length = length;
};

var tryToString$2$1 = tryToString$6$1;

var $TypeError$5$1 = TypeError;

var deletePropertyOrThrow$2$1 = function (O, P) {
  if (!delete O[P]) throw $TypeError$5$1('Cannot delete property ' + tryToString$2$1(P) + ' of ' + tryToString$2$1(O));
};

var $$m$1 = _export$1;
var toObject$3$1 = toObject$d$1;
var toAbsoluteIndex$6 = toAbsoluteIndex$4$1;
var toIntegerOrInfinity$5 = toIntegerOrInfinity$4$1;
var lengthOfArrayLike$2$1 = lengthOfArrayLike$c;
var setArrayLength$1 = arraySetLength$1;
var doesNotExceedSafeInteger$4 = doesNotExceedSafeInteger$3;
var arraySpeciesCreate$5 = arraySpeciesCreate$4;
var createProperty$7 = createProperty$6$1;
var deletePropertyOrThrow$1$1 = deletePropertyOrThrow$2$1;
var arrayMethodHasSpeciesSupport$6 = arrayMethodHasSpeciesSupport$5$1;

var HAS_SPECIES_SUPPORT$4 = arrayMethodHasSpeciesSupport$6('splice');

var max$5 = Math.max;
var min$4 = Math.min;

// `Array.prototype.splice` method
// https://tc39.es/ecma262/#sec-array.prototype.splice
// with adding support of @@species
$$m$1({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$4 }, {
  splice: function splice(start, deleteCount /* , ...items */) {
    var O = toObject$3$1(this);
    var len = lengthOfArrayLike$2$1(O);
    var actualStart = toAbsoluteIndex$6(start, len);
    var argumentsLength = arguments.length;
    var insertCount, actualDeleteCount, A, k, from, to;
    if (argumentsLength === 0) {
      insertCount = actualDeleteCount = 0;
    } else if (argumentsLength === 1) {
      insertCount = 0;
      actualDeleteCount = len - actualStart;
    } else {
      insertCount = argumentsLength - 2;
      actualDeleteCount = min$4(max$5(toIntegerOrInfinity$5(deleteCount), 0), len - actualStart);
    }
    doesNotExceedSafeInteger$4(len + insertCount - actualDeleteCount);
    A = arraySpeciesCreate$5(O, actualDeleteCount);
    for (k = 0; k < actualDeleteCount; k++) {
      from = actualStart + k;
      if (from in O) createProperty$7(A, k, O[from]);
    }
    A.length = actualDeleteCount;
    if (insertCount < actualDeleteCount) {
      for (k = actualStart; k < len - actualDeleteCount; k++) {
        from = k + actualDeleteCount;
        to = k + insertCount;
        if (from in O) O[to] = O[from];
        else deletePropertyOrThrow$1$1(O, to);
      }
      for (k = len; k > len - actualDeleteCount + insertCount; k--) deletePropertyOrThrow$1$1(O, k - 1);
    } else if (insertCount > actualDeleteCount) {
      for (k = len - actualDeleteCount; k > actualStart; k--) {
        from = k + actualDeleteCount - 1;
        to = k + insertCount - 1;
        if (from in O) O[to] = O[from];
        else deletePropertyOrThrow$1$1(O, to);
      }
    }
    for (k = 0; k < insertCount; k++) {
      O[k + actualStart] = arguments[k + 2];
    }
    setArrayLength$1(O, len - actualDeleteCount + insertCount);
    return A;
  }
});

var entryVirtual$5$1 = entryVirtual$f$1;

var splice$3$1 = entryVirtual$5$1('Array').splice;

var isPrototypeOf$8$1 = objectIsPrototypeOf$1;
var method$5$1 = splice$3$1;

var ArrayPrototype$5$1 = Array.prototype;

var splice$2$1 = function (it) {
  var own = it.splice;
  return it === ArrayPrototype$5$1 || (isPrototypeOf$8$1(ArrayPrototype$5$1, it) && own === ArrayPrototype$5$1.splice) ? method$5$1 : own;
};

var parent$v$1 = splice$2$1;

var splice$1$1 = parent$v$1;

var splice$5 = splice$1$1;

var _spliceInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(splice$5);

var DESCRIPTORS$4$1 = descriptors$1;
var uncurryThis$3$1 = functionUncurryThis$1;
var call$7$1 = functionCall$1;
var fails$a$1 = fails$t$1;
var objectKeys$5 = objectKeys$3$1;
var getOwnPropertySymbolsModule$4 = objectGetOwnPropertySymbols$1;
var propertyIsEnumerableModule$3 = objectPropertyIsEnumerable$1;
var toObject$2$1 = toObject$d$1;
var IndexedObject$4 = indexedObject$1;

// eslint-disable-next-line es/no-object-assign -- safe
var $assign$1 = Object.assign;
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
var defineProperty$2$1 = Object.defineProperty;
var concat$7 = uncurryThis$3$1([].concat);

// `Object.assign` method
// https://tc39.es/ecma262/#sec-object.assign
var objectAssign$1 = !$assign$1 || fails$a$1(function () {
  // should have correct order of operations (Edge bug)
  if (DESCRIPTORS$4$1 && $assign$1({ b: 1 }, $assign$1(defineProperty$2$1({}, 'a', {
    enumerable: true,
    get: function () {
      defineProperty$2$1(this, 'b', {
        value: 3,
        enumerable: false
      });
    }
  }), { b: 2 })).b !== 1) return true;
  // should work with symbols and should have deterministic property order (V8 bug)
  var A = {};
  var B = {};
  // eslint-disable-next-line es/no-symbol -- safe
  var symbol = Symbol();
  var alphabet = 'abcdefghijklmnopqrst';
  A[symbol] = 7;
  alphabet.split('').forEach(function (chr) { B[chr] = chr; });
  return $assign$1({}, A)[symbol] != 7 || objectKeys$5($assign$1({}, B)).join('') != alphabet;
}) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
  var T = toObject$2$1(target);
  var argumentsLength = arguments.length;
  var index = 1;
  var getOwnPropertySymbols = getOwnPropertySymbolsModule$4.f;
  var propertyIsEnumerable = propertyIsEnumerableModule$3.f;
  while (argumentsLength > index) {
    var S = IndexedObject$4(arguments[index++]);
    var keys = getOwnPropertySymbols ? concat$7(objectKeys$5(S), getOwnPropertySymbols(S)) : objectKeys$5(S);
    var length = keys.length;
    var j = 0;
    var key;
    while (length > j) {
      key = keys[j++];
      if (!DESCRIPTORS$4$1 || call$7$1(propertyIsEnumerable, S, key)) T[key] = S[key];
    }
  } return T;
} : $assign$1;

var $$l$1 = _export$1;
var assign$5$1 = objectAssign$1;

// `Object.assign` method
// https://tc39.es/ecma262/#sec-object.assign
// eslint-disable-next-line es/no-object-assign -- required for testing
$$l$1({ target: 'Object', stat: true, arity: 2, forced: Object.assign !== assign$5$1 }, {
  assign: assign$5$1
});

var path$9$1 = path$o$1;

var assign$4$1 = path$9$1.Object.assign;

var parent$u$1 = assign$4$1;

var assign$3$1 = parent$u$1;

var assign$2$1 = assign$3$1;

var _Object$assign$1 = /*@__PURE__*/getDefaultExportFromCjs$2(assign$2$1);

var $$k$1 = _export$1;
var fails$9$1 = fails$t$1;
var toObject$1$1 = toObject$d$1;
var nativeGetPrototypeOf$1 = objectGetPrototypeOf$1;
var CORRECT_PROTOTYPE_GETTER$2 = correctPrototypeGetter$1;

var FAILS_ON_PRIMITIVES$1$1 = fails$9$1(function () { nativeGetPrototypeOf$1(1); });

// `Object.getPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.getprototypeof
$$k$1({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$1$1, sham: !CORRECT_PROTOTYPE_GETTER$2 }, {
  getPrototypeOf: function getPrototypeOf(it) {
    return nativeGetPrototypeOf$1(toObject$1$1(it));
  }
});

var path$8$1 = path$o$1;

var getPrototypeOf$6$1 = path$8$1.Object.getPrototypeOf;

var parent$t$1 = getPrototypeOf$6$1;

var getPrototypeOf$5$1 = parent$t$1;

// TODO: Remove from `core-js@4`
var $$j$1 = _export$1;
var DESCRIPTORS$3$1 = descriptors$1;
var create$a$1 = objectCreate$1;

// `Object.create` method
// https://tc39.es/ecma262/#sec-object.create
$$j$1({ target: 'Object', stat: true, sham: !DESCRIPTORS$3$1 }, {
  create: create$a$1
});

var path$7$1 = path$o$1;

var Object$1$1 = path$7$1.Object;

var create$9$1 = function create(P, D) {
  return Object$1$1.create(P, D);
};

var parent$s$1 = create$9$1;

var create$8$1 = parent$s$1;

var create$7$1 = create$8$1;

var _Object$create$1$1 = /*@__PURE__*/getDefaultExportFromCjs$2(create$7$1);

var path$6$1 = path$o$1;
var apply$3$1 = functionApply$1;

// eslint-disable-next-line es/no-json -- safe
if (!path$6$1.JSON) path$6$1.JSON = { stringify: JSON.stringify };

// eslint-disable-next-line no-unused-vars -- required for `.length`
var stringify$2$1 = function stringify(it, replacer, space) {
  return apply$3$1(path$6$1.JSON.stringify, null, arguments);
};

var parent$r$1 = stringify$2$1;

var stringify$1$1 = parent$r$1;

var stringify$4 = stringify$1$1;

var _JSON$stringify$1 = /*@__PURE__*/getDefaultExportFromCjs$2(stringify$4);

/* global Bun -- Deno case */

var engineIsBun$1 = typeof Bun == 'function' && Bun && typeof Bun.version == 'string';

var $TypeError$4$1 = TypeError;

var validateArgumentsLength$2 = function (passed, required) {
  if (passed < required) throw $TypeError$4$1('Not enough arguments');
  return passed;
};

var global$9$1 = global$m;
var apply$2$1 = functionApply$1;
var isCallable$5$1 = isCallable$m;
var ENGINE_IS_BUN$1 = engineIsBun$1;
var USER_AGENT$1 = engineUserAgent$1;
var arraySlice$2$1 = arraySlice$5$1;
var validateArgumentsLength$1$1 = validateArgumentsLength$2;

var Function$2 = global$9$1.Function;
// dirty IE9- and Bun 0.3.0- checks
var WRAP$1 = /MSIE .\./.test(USER_AGENT$1) || ENGINE_IS_BUN$1 && (function () {
  var version = global$9$1.Bun.version.split('.');
  return version.length < 3 || version[0] == 0 && (version[1] < 3 || version[1] == 3 && version[2] == 0);
})();

// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
// https://github.com/oven-sh/bun/issues/1633
var schedulersFix$2$1 = function (scheduler, hasTimeArg) {
  var firstParamIndex = hasTimeArg ? 2 : 1;
  return WRAP$1 ? function (handler, timeout /* , ...arguments */) {
    var boundArgs = validateArgumentsLength$1$1(arguments.length, 1) > firstParamIndex;
    var fn = isCallable$5$1(handler) ? handler : Function$2(handler);
    var params = boundArgs ? arraySlice$2$1(arguments, firstParamIndex) : [];
    var callback = boundArgs ? function () {
      apply$2$1(fn, this, params);
    } : fn;
    return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);
  } : scheduler;
};

var $$i$1 = _export$1;
var global$8$1 = global$m;
var schedulersFix$1$1 = schedulersFix$2$1;

var setInterval$4 = schedulersFix$1$1(global$8$1.setInterval, true);

// Bun / IE9- setInterval additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
$$i$1({ global: true, bind: true, forced: global$8$1.setInterval !== setInterval$4 }, {
  setInterval: setInterval$4
});

var $$h$1 = _export$1;
var global$7$1 = global$m;
var schedulersFix$3 = schedulersFix$2$1;

var setTimeout$3$1 = schedulersFix$3(global$7$1.setTimeout, true);

// Bun / IE9- setTimeout additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
$$h$1({ global: true, bind: true, forced: global$7$1.setTimeout !== setTimeout$3$1 }, {
  setTimeout: setTimeout$3$1
});

var path$5$1 = path$o$1;

var setTimeout$2$1 = path$5$1.setTimeout;

var setTimeout$1$1 = setTimeout$2$1;

var _setTimeout$1 = /*@__PURE__*/getDefaultExportFromCjs$2(setTimeout$1$1);

var componentEmitter$1 = {exports: {}};

(function (module) {
	/**
	 * Expose `Emitter`.
	 */

	{
	  module.exports = Emitter;
	}

	/**
	 * Initialize a new `Emitter`.
	 *
	 * @api public
	 */

	function Emitter(obj) {
	  if (obj) return mixin(obj);
	}
	/**
	 * Mixin the emitter properties.
	 *
	 * @param {Object} obj
	 * @return {Object}
	 * @api private
	 */

	function mixin(obj) {
	  for (var key in Emitter.prototype) {
	    obj[key] = Emitter.prototype[key];
	  }
	  return obj;
	}

	/**
	 * Listen on the given `event` with `fn`.
	 *
	 * @param {String} event
	 * @param {Function} fn
	 * @return {Emitter}
	 * @api public
	 */

	Emitter.prototype.on =
	Emitter.prototype.addEventListener = function(event, fn){
	  this._callbacks = this._callbacks || {};
	  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
	    .push(fn);
	  return this;
	};

	/**
	 * Adds an `event` listener that will be invoked a single
	 * time then automatically removed.
	 *
	 * @param {String} event
	 * @param {Function} fn
	 * @return {Emitter}
	 * @api public
	 */

	Emitter.prototype.once = function(event, fn){
	  function on() {
	    this.off(event, on);
	    fn.apply(this, arguments);
	  }

	  on.fn = fn;
	  this.on(event, on);
	  return this;
	};

	/**
	 * Remove the given callback for `event` or all
	 * registered callbacks.
	 *
	 * @param {String} event
	 * @param {Function} fn
	 * @return {Emitter}
	 * @api public
	 */

	Emitter.prototype.off =
	Emitter.prototype.removeListener =
	Emitter.prototype.removeAllListeners =
	Emitter.prototype.removeEventListener = function(event, fn){
	  this._callbacks = this._callbacks || {};

	  // all
	  if (0 == arguments.length) {
	    this._callbacks = {};
	    return this;
	  }

	  // specific event
	  var callbacks = this._callbacks['$' + event];
	  if (!callbacks) return this;

	  // remove all handlers
	  if (1 == arguments.length) {
	    delete this._callbacks['$' + event];
	    return this;
	  }

	  // remove specific handler
	  var cb;
	  for (var i = 0; i < callbacks.length; i++) {
	    cb = callbacks[i];
	    if (cb === fn || cb.fn === fn) {
	      callbacks.splice(i, 1);
	      break;
	    }
	  }

	  // Remove event specific arrays for event types that no
	  // one is subscribed for to avoid memory leak.
	  if (callbacks.length === 0) {
	    delete this._callbacks['$' + event];
	  }

	  return this;
	};

	/**
	 * Emit `event` with the given args.
	 *
	 * @param {String} event
	 * @param {Mixed} ...
	 * @return {Emitter}
	 */

	Emitter.prototype.emit = function(event){
	  this._callbacks = this._callbacks || {};

	  var args = new Array(arguments.length - 1)
	    , callbacks = this._callbacks['$' + event];

	  for (var i = 1; i < arguments.length; i++) {
	    args[i - 1] = arguments[i];
	  }

	  if (callbacks) {
	    callbacks = callbacks.slice(0);
	    for (var i = 0, len = callbacks.length; i < len; ++i) {
	      callbacks[i].apply(this, args);
	    }
	  }

	  return this;
	};

	/**
	 * Return array of callbacks for `event`.
	 *
	 * @param {String} event
	 * @return {Array}
	 * @api public
	 */

	Emitter.prototype.listeners = function(event){
	  this._callbacks = this._callbacks || {};
	  return this._callbacks['$' + event] || [];
	};

	/**
	 * Check if this emitter has `event` handlers.
	 *
	 * @param {String} event
	 * @return {Boolean}
	 * @api public
	 */

	Emitter.prototype.hasListeners = function(event){
	  return !! this.listeners(event).length;
	}; 
} (componentEmitter$1));

var componentEmitterExports$1 = componentEmitter$1.exports;
var Emitter$1 = /*@__PURE__*/getDefaultExportFromCjs$2(componentEmitterExports$1);

/*! Hammer.JS - v2.0.17-rc - 2019-12-16
 * http://naver.github.io/egjs
 *
 * Forked By Naver egjs
 * Copyright (c) hammerjs
 * Licensed under the MIT license */
function _extends$1() {
  _extends$1 = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  return _extends$1.apply(this, arguments);
}

function _inheritsLoose$1(subClass, superClass) {
  subClass.prototype = Object.create(superClass.prototype);
  subClass.prototype.constructor = subClass;
  subClass.__proto__ = superClass;
}

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

  return self;
}

/**
 * @private
 * extend object.
 * means that properties in dest will be overwritten by the ones in src.
 * @param {Object} target
 * @param {...Object} objects_to_assign
 * @returns {Object} target
 */
var assign$6;

if (typeof Object.assign !== 'function') {
  assign$6 = function assign(target) {
    if (target === undefined || target === null) {
      throw new TypeError('Cannot convert undefined or null to object');
    }

    var output = Object(target);

    for (var index = 1; index < arguments.length; index++) {
      var source = arguments[index];

      if (source !== undefined && source !== null) {
        for (var nextKey in source) {
          if (source.hasOwnProperty(nextKey)) {
            output[nextKey] = source[nextKey];
          }
        }
      }
    }

    return output;
  };
} else {
  assign$6 = Object.assign;
}

var assign$1$1 = assign$6;

var VENDOR_PREFIXES$1 = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
var TEST_ELEMENT$1 = typeof document === "undefined" ? {
  style: {}
} : document.createElement('div');
var TYPE_FUNCTION$1 = 'function';
var round$3 = Math.round,
    abs$3 = Math.abs;
var now$4 = Date.now;

/**
 * @private
 * get the prefixed property
 * @param {Object} obj
 * @param {String} property
 * @returns {String|Undefined} prefixed
 */

function prefixed$1(obj, property) {
  var prefix;
  var prop;
  var camelProp = property[0].toUpperCase() + property.slice(1);
  var i = 0;

  while (i < VENDOR_PREFIXES$1.length) {
    prefix = VENDOR_PREFIXES$1[i];
    prop = prefix ? prefix + camelProp : property;

    if (prop in obj) {
      return prop;
    }

    i++;
  }

  return undefined;
}

/* eslint-disable no-new-func, no-nested-ternary */
var win$1;

if (typeof window === "undefined") {
  // window is undefined in node.js
  win$1 = {};
} else {
  win$1 = window;
}

var PREFIXED_TOUCH_ACTION$1 = prefixed$1(TEST_ELEMENT$1.style, 'touchAction');
var NATIVE_TOUCH_ACTION$1 = PREFIXED_TOUCH_ACTION$1 !== undefined;
function getTouchActionProps$1() {
  if (!NATIVE_TOUCH_ACTION$1) {
    return false;
  }

  var touchMap = {};
  var cssSupports = win$1.CSS && win$1.CSS.supports;
  ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) {
    // If css.supports is not supported but there is native touch-action assume it supports
    // all values. This is the case for IE 10 and 11.
    return touchMap[val] = cssSupports ? win$1.CSS.supports('touch-action', val) : true;
  });
  return touchMap;
}

var TOUCH_ACTION_COMPUTE$1 = 'compute';
var TOUCH_ACTION_AUTO$1 = 'auto';
var TOUCH_ACTION_MANIPULATION$1 = 'manipulation'; // not implemented

var TOUCH_ACTION_NONE$1 = 'none';
var TOUCH_ACTION_PAN_X$1 = 'pan-x';
var TOUCH_ACTION_PAN_Y$1 = 'pan-y';
var TOUCH_ACTION_MAP$1 = getTouchActionProps$1();

var MOBILE_REGEX$1 = /mobile|tablet|ip(ad|hone|od)|android/i;
var SUPPORT_TOUCH$1 = 'ontouchstart' in win$1;
var SUPPORT_POINTER_EVENTS$1 = prefixed$1(win$1, 'PointerEvent') !== undefined;
var SUPPORT_ONLY_TOUCH$1 = SUPPORT_TOUCH$1 && MOBILE_REGEX$1.test(navigator.userAgent);
var INPUT_TYPE_TOUCH$1 = 'touch';
var INPUT_TYPE_PEN$1 = 'pen';
var INPUT_TYPE_MOUSE$1 = 'mouse';
var INPUT_TYPE_KINECT$1 = 'kinect';
var COMPUTE_INTERVAL$1 = 25;
var INPUT_START$1 = 1;
var INPUT_MOVE$1 = 2;
var INPUT_END$1 = 4;
var INPUT_CANCEL$1 = 8;
var DIRECTION_NONE$1 = 1;
var DIRECTION_LEFT$1 = 2;
var DIRECTION_RIGHT$1 = 4;
var DIRECTION_UP$1 = 8;
var DIRECTION_DOWN$1 = 16;
var DIRECTION_HORIZONTAL$1 = DIRECTION_LEFT$1 | DIRECTION_RIGHT$1;
var DIRECTION_VERTICAL$1 = DIRECTION_UP$1 | DIRECTION_DOWN$1;
var DIRECTION_ALL$1 = DIRECTION_HORIZONTAL$1 | DIRECTION_VERTICAL$1;
var PROPS_XY$1 = ['x', 'y'];
var PROPS_CLIENT_XY$1 = ['clientX', 'clientY'];

/**
 * @private
 * walk objects and arrays
 * @param {Object} obj
 * @param {Function} iterator
 * @param {Object} context
 */
function each$6(obj, iterator, context) {
  var i;

  if (!obj) {
    return;
  }

  if (obj.forEach) {
    obj.forEach(iterator, context);
  } else if (obj.length !== undefined) {
    i = 0;

    while (i < obj.length) {
      iterator.call(context, obj[i], i, obj);
      i++;
    }
  } else {
    for (i in obj) {
      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
    }
  }
}

/**
 * @private
 * let a boolean value also be a function that must return a boolean
 * this first item in args will be used as the context
 * @param {Boolean|Function} val
 * @param {Array} [args]
 * @returns {Boolean}
 */

function boolOrFn$1(val, args) {
  if (typeof val === TYPE_FUNCTION$1) {
    return val.apply(args ? args[0] || undefined : undefined, args);
  }

  return val;
}

/**
 * @private
 * small indexOf wrapper
 * @param {String} str
 * @param {String} find
 * @returns {Boolean} found
 */
function inStr$1(str, find) {
  return str.indexOf(find) > -1;
}

/**
 * @private
 * when the touchActions are collected they are not a valid value, so we need to clean things up. *
 * @param {String} actions
 * @returns {*}
 */

function cleanTouchActions$1(actions) {
  // none
  if (inStr$1(actions, TOUCH_ACTION_NONE$1)) {
    return TOUCH_ACTION_NONE$1;
  }

  var hasPanX = inStr$1(actions, TOUCH_ACTION_PAN_X$1);
  var hasPanY = inStr$1(actions, TOUCH_ACTION_PAN_Y$1); // if both pan-x and pan-y are set (different recognizers
  // for different directions, e.g. horizontal pan but vertical swipe?)
  // we need none (as otherwise with pan-x pan-y combined none of these
  // recognizers will work, since the browser would handle all panning

  if (hasPanX && hasPanY) {
    return TOUCH_ACTION_NONE$1;
  } // pan-x OR pan-y


  if (hasPanX || hasPanY) {
    return hasPanX ? TOUCH_ACTION_PAN_X$1 : TOUCH_ACTION_PAN_Y$1;
  } // manipulation


  if (inStr$1(actions, TOUCH_ACTION_MANIPULATION$1)) {
    return TOUCH_ACTION_MANIPULATION$1;
  }

  return TOUCH_ACTION_AUTO$1;
}

/**
 * @private
 * Touch Action
 * sets the touchAction property or uses the js alternative
 * @param {Manager} manager
 * @param {String} value
 * @constructor
 */

var TouchAction$1 =
/*#__PURE__*/
function () {
  function TouchAction(manager, value) {
    this.manager = manager;
    this.set(value);
  }
  /**
   * @private
   * set the touchAction value on the element or enable the polyfill
   * @param {String} value
   */


  var _proto = TouchAction.prototype;

  _proto.set = function set(value) {
    // find out the touch-action by the event handlers
    if (value === TOUCH_ACTION_COMPUTE$1) {
      value = this.compute();
    }

    if (NATIVE_TOUCH_ACTION$1 && this.manager.element.style && TOUCH_ACTION_MAP$1[value]) {
      this.manager.element.style[PREFIXED_TOUCH_ACTION$1] = value;
    }

    this.actions = value.toLowerCase().trim();
  };
  /**
   * @private
   * just re-set the touchAction value
   */


  _proto.update = function update() {
    this.set(this.manager.options.touchAction);
  };
  /**
   * @private
   * compute the value for the touchAction property based on the recognizer's settings
   * @returns {String} value
   */


  _proto.compute = function compute() {
    var actions = [];
    each$6(this.manager.recognizers, function (recognizer) {
      if (boolOrFn$1(recognizer.options.enable, [recognizer])) {
        actions = actions.concat(recognizer.getTouchAction());
      }
    });
    return cleanTouchActions$1(actions.join(' '));
  };
  /**
   * @private
   * this method is called on each input cycle and provides the preventing of the browser behavior
   * @param {Object} input
   */


  _proto.preventDefaults = function preventDefaults(input) {
    var srcEvent = input.srcEvent;
    var direction = input.offsetDirection; // if the touch action did prevented once this session

    if (this.manager.session.prevented) {
      srcEvent.preventDefault();
      return;
    }

    var actions = this.actions;
    var hasNone = inStr$1(actions, TOUCH_ACTION_NONE$1) && !TOUCH_ACTION_MAP$1[TOUCH_ACTION_NONE$1];
    var hasPanY = inStr$1(actions, TOUCH_ACTION_PAN_Y$1) && !TOUCH_ACTION_MAP$1[TOUCH_ACTION_PAN_Y$1];
    var hasPanX = inStr$1(actions, TOUCH_ACTION_PAN_X$1) && !TOUCH_ACTION_MAP$1[TOUCH_ACTION_PAN_X$1];

    if (hasNone) {
      // do not prevent defaults if this is a tap gesture
      var isTapPointer = input.pointers.length === 1;
      var isTapMovement = input.distance < 2;
      var isTapTouchTime = input.deltaTime < 250;

      if (isTapPointer && isTapMovement && isTapTouchTime) {
        return;
      }
    }

    if (hasPanX && hasPanY) {
      // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
      return;
    }

    if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL$1 || hasPanX && direction & DIRECTION_VERTICAL$1) {
      return this.preventSrc(srcEvent);
    }
  };
  /**
   * @private
   * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
   * @param {Object} srcEvent
   */


  _proto.preventSrc = function preventSrc(srcEvent) {
    this.manager.session.prevented = true;
    srcEvent.preventDefault();
  };

  return TouchAction;
}();

/**
 * @private
 * find if a node is in the given parent
 * @method hasParent
 * @param {HTMLElement} node
 * @param {HTMLElement} parent
 * @return {Boolean} found
 */
function hasParent$1(node, parent) {
  while (node) {
    if (node === parent) {
      return true;
    }

    node = node.parentNode;
  }

  return false;
}

/**
 * @private
 * get the center of all the pointers
 * @param {Array} pointers
 * @return {Object} center contains `x` and `y` properties
 */

function getCenter$1(pointers) {
  var pointersLength = pointers.length; // no need to loop when only one touch

  if (pointersLength === 1) {
    return {
      x: round$3(pointers[0].clientX),
      y: round$3(pointers[0].clientY)
    };
  }

  var x = 0;
  var y = 0;
  var i = 0;

  while (i < pointersLength) {
    x += pointers[i].clientX;
    y += pointers[i].clientY;
    i++;
  }

  return {
    x: round$3(x / pointersLength),
    y: round$3(y / pointersLength)
  };
}

/**
 * @private
 * create a simple clone from the input used for storage of firstInput and firstMultiple
 * @param {Object} input
 * @returns {Object} clonedInputData
 */

function simpleCloneInputData$1(input) {
  // make a simple copy of the pointers because we will get a reference if we don't
  // we only need clientXY for the calculations
  var pointers = [];
  var i = 0;

  while (i < input.pointers.length) {
    pointers[i] = {
      clientX: round$3(input.pointers[i].clientX),
      clientY: round$3(input.pointers[i].clientY)
    };
    i++;
  }

  return {
    timeStamp: now$4(),
    pointers: pointers,
    center: getCenter$1(pointers),
    deltaX: input.deltaX,
    deltaY: input.deltaY
  };
}

/**
 * @private
 * calculate the absolute distance between two points
 * @param {Object} p1 {x, y}
 * @param {Object} p2 {x, y}
 * @param {Array} [props] containing x and y keys
 * @return {Number} distance
 */

function getDistance$1(p1, p2, props) {
  if (!props) {
    props = PROPS_XY$1;
  }

  var x = p2[props[0]] - p1[props[0]];
  var y = p2[props[1]] - p1[props[1]];
  return Math.sqrt(x * x + y * y);
}

/**
 * @private
 * calculate the angle between two coordinates
 * @param {Object} p1
 * @param {Object} p2
 * @param {Array} [props] containing x and y keys
 * @return {Number} angle
 */

function getAngle$1(p1, p2, props) {
  if (!props) {
    props = PROPS_XY$1;
  }

  var x = p2[props[0]] - p1[props[0]];
  var y = p2[props[1]] - p1[props[1]];
  return Math.atan2(y, x) * 180 / Math.PI;
}

/**
 * @private
 * get the direction between two points
 * @param {Number} x
 * @param {Number} y
 * @return {Number} direction
 */

function getDirection$1(x, y) {
  if (x === y) {
    return DIRECTION_NONE$1;
  }

  if (abs$3(x) >= abs$3(y)) {
    return x < 0 ? DIRECTION_LEFT$1 : DIRECTION_RIGHT$1;
  }

  return y < 0 ? DIRECTION_UP$1 : DIRECTION_DOWN$1;
}

function computeDeltaXY$1(session, input) {
  var center = input.center; // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;
  // jscs throwing error on defalut destructured values and without defaults tests fail

  var offset = session.offsetDelta || {};
  var prevDelta = session.prevDelta || {};
  var prevInput = session.prevInput || {};

  if (input.eventType === INPUT_START$1 || prevInput.eventType === INPUT_END$1) {
    prevDelta = session.prevDelta = {
      x: prevInput.deltaX || 0,
      y: prevInput.deltaY || 0
    };
    offset = session.offsetDelta = {
      x: center.x,
      y: center.y
    };
  }

  input.deltaX = prevDelta.x + (center.x - offset.x);
  input.deltaY = prevDelta.y + (center.y - offset.y);
}

/**
 * @private
 * calculate the velocity between two points. unit is in px per ms.
 * @param {Number} deltaTime
 * @param {Number} x
 * @param {Number} y
 * @return {Object} velocity `x` and `y`
 */
function getVelocity$1(deltaTime, x, y) {
  return {
    x: x / deltaTime || 0,
    y: y / deltaTime || 0
  };
}

/**
 * @private
 * calculate the scale factor between two pointersets
 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} scale
 */

function getScale$1(start, end) {
  return getDistance$1(end[0], end[1], PROPS_CLIENT_XY$1) / getDistance$1(start[0], start[1], PROPS_CLIENT_XY$1);
}

/**
 * @private
 * calculate the rotation degrees between two pointersets
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} rotation
 */

function getRotation$1(start, end) {
  return getAngle$1(end[1], end[0], PROPS_CLIENT_XY$1) + getAngle$1(start[1], start[0], PROPS_CLIENT_XY$1);
}

/**
 * @private
 * velocity is calculated every x ms
 * @param {Object} session
 * @param {Object} input
 */

function computeIntervalInputData$1(session, input) {
  var last = session.lastInterval || input;
  var deltaTime = input.timeStamp - last.timeStamp;
  var velocity;
  var velocityX;
  var velocityY;
  var direction;

  if (input.eventType !== INPUT_CANCEL$1 && (deltaTime > COMPUTE_INTERVAL$1 || last.velocity === undefined)) {
    var deltaX = input.deltaX - last.deltaX;
    var deltaY = input.deltaY - last.deltaY;
    var v = getVelocity$1(deltaTime, deltaX, deltaY);
    velocityX = v.x;
    velocityY = v.y;
    velocity = abs$3(v.x) > abs$3(v.y) ? v.x : v.y;
    direction = getDirection$1(deltaX, deltaY);
    session.lastInterval = input;
  } else {
    // use latest velocity info if it doesn't overtake a minimum period
    velocity = last.velocity;
    velocityX = last.velocityX;
    velocityY = last.velocityY;
    direction = last.direction;
  }

  input.velocity = velocity;
  input.velocityX = velocityX;
  input.velocityY = velocityY;
  input.direction = direction;
}

/**
* @private
 * extend the data with some usable properties like scale, rotate, velocity etc
 * @param {Object} manager
 * @param {Object} input
 */

function computeInputData$1(manager, input) {
  var session = manager.session;
  var pointers = input.pointers;
  var pointersLength = pointers.length; // store the first input to calculate the distance and direction

  if (!session.firstInput) {
    session.firstInput = simpleCloneInputData$1(input);
  } // to compute scale and rotation we need to store the multiple touches


  if (pointersLength > 1 && !session.firstMultiple) {
    session.firstMultiple = simpleCloneInputData$1(input);
  } else if (pointersLength === 1) {
    session.firstMultiple = false;
  }

  var firstInput = session.firstInput,
      firstMultiple = session.firstMultiple;
  var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
  var center = input.center = getCenter$1(pointers);
  input.timeStamp = now$4();
  input.deltaTime = input.timeStamp - firstInput.timeStamp;
  input.angle = getAngle$1(offsetCenter, center);
  input.distance = getDistance$1(offsetCenter, center);
  computeDeltaXY$1(session, input);
  input.offsetDirection = getDirection$1(input.deltaX, input.deltaY);
  var overallVelocity = getVelocity$1(input.deltaTime, input.deltaX, input.deltaY);
  input.overallVelocityX = overallVelocity.x;
  input.overallVelocityY = overallVelocity.y;
  input.overallVelocity = abs$3(overallVelocity.x) > abs$3(overallVelocity.y) ? overallVelocity.x : overallVelocity.y;
  input.scale = firstMultiple ? getScale$1(firstMultiple.pointers, pointers) : 1;
  input.rotation = firstMultiple ? getRotation$1(firstMultiple.pointers, pointers) : 0;
  input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers;
  computeIntervalInputData$1(session, input); // find the correct target

  var target = manager.element;
  var srcEvent = input.srcEvent;
  var srcEventTarget;

  if (srcEvent.composedPath) {
    srcEventTarget = srcEvent.composedPath()[0];
  } else if (srcEvent.path) {
    srcEventTarget = srcEvent.path[0];
  } else {
    srcEventTarget = srcEvent.target;
  }

  if (hasParent$1(srcEventTarget, target)) {
    target = srcEventTarget;
  }

  input.target = target;
}

/**
 * @private
 * handle input events
 * @param {Manager} manager
 * @param {String} eventType
 * @param {Object} input
 */

function inputHandler$1(manager, eventType, input) {
  var pointersLen = input.pointers.length;
  var changedPointersLen = input.changedPointers.length;
  var isFirst = eventType & INPUT_START$1 && pointersLen - changedPointersLen === 0;
  var isFinal = eventType & (INPUT_END$1 | INPUT_CANCEL$1) && pointersLen - changedPointersLen === 0;
  input.isFirst = !!isFirst;
  input.isFinal = !!isFinal;

  if (isFirst) {
    manager.session = {};
  } // source event is the normalized value of the domEvents
  // like 'touchstart, mouseup, pointerdown'


  input.eventType = eventType; // compute scale, rotation etc

  computeInputData$1(manager, input); // emit secret event

  manager.emit('hammer.input', input);
  manager.recognize(input);
  manager.session.prevInput = input;
}

/**
 * @private
 * split string on whitespace
 * @param {String} str
 * @returns {Array} words
 */
function splitStr$1(str) {
  return str.trim().split(/\s+/g);
}

/**
 * @private
 * addEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */

function addEventListeners$1(target, types, handler) {
  each$6(splitStr$1(types), function (type) {
    target.addEventListener(type, handler, false);
  });
}

/**
 * @private
 * removeEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */

function removeEventListeners$1(target, types, handler) {
  each$6(splitStr$1(types), function (type) {
    target.removeEventListener(type, handler, false);
  });
}

/**
 * @private
 * get the window object of an element
 * @param {HTMLElement} element
 * @returns {DocumentView|Window}
 */
function getWindowForElement$1(element) {
  var doc = element.ownerDocument || element;
  return doc.defaultView || doc.parentWindow || window;
}

/**
 * @private
 * create new input type manager
 * @param {Manager} manager
 * @param {Function} callback
 * @returns {Input}
 * @constructor
 */

var Input$1 =
/*#__PURE__*/
function () {
  function Input(manager, callback) {
    var self = this;
    this.manager = manager;
    this.callback = callback;
    this.element = manager.element;
    this.target = manager.options.inputTarget; // smaller wrapper around the handler, for the scope and the enabled state of the manager,
    // so when disabled the input events are completely bypassed.

    this.domHandler = function (ev) {
      if (boolOrFn$1(manager.options.enable, [manager])) {
        self.handler(ev);
      }
    };

    this.init();
  }
  /**
   * @private
   * should handle the inputEvent data and trigger the callback
   * @virtual
   */


  var _proto = Input.prototype;

  _proto.handler = function handler() {};
  /**
   * @private
   * bind the events
   */


  _proto.init = function init() {
    this.evEl && addEventListeners$1(this.element, this.evEl, this.domHandler);
    this.evTarget && addEventListeners$1(this.target, this.evTarget, this.domHandler);
    this.evWin && addEventListeners$1(getWindowForElement$1(this.element), this.evWin, this.domHandler);
  };
  /**
   * @private
   * unbind the events
   */


  _proto.destroy = function destroy() {
    this.evEl && removeEventListeners$1(this.element, this.evEl, this.domHandler);
    this.evTarget && removeEventListeners$1(this.target, this.evTarget, this.domHandler);
    this.evWin && removeEventListeners$1(getWindowForElement$1(this.element), this.evWin, this.domHandler);
  };

  return Input;
}();

/**
 * @private
 * find if a array contains the object using indexOf or a simple polyFill
 * @param {Array} src
 * @param {String} find
 * @param {String} [findByKey]
 * @return {Boolean|Number} false when not found, or the index
 */
function inArray$1(src, find, findByKey) {
  if (src.indexOf && !findByKey) {
    return src.indexOf(find);
  } else {
    var i = 0;

    while (i < src.length) {
      if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) {
        // do not use === here, test fails
        return i;
      }

      i++;
    }

    return -1;
  }
}

var POINTER_INPUT_MAP$1 = {
  pointerdown: INPUT_START$1,
  pointermove: INPUT_MOVE$1,
  pointerup: INPUT_END$1,
  pointercancel: INPUT_CANCEL$1,
  pointerout: INPUT_CANCEL$1
}; // in IE10 the pointer types is defined as an enum

var IE10_POINTER_TYPE_ENUM$1 = {
  2: INPUT_TYPE_TOUCH$1,
  3: INPUT_TYPE_PEN$1,
  4: INPUT_TYPE_MOUSE$1,
  5: INPUT_TYPE_KINECT$1 // see https://twitter.com/jacobrossi/status/480596438489890816

};
var POINTER_ELEMENT_EVENTS$1 = 'pointerdown';
var POINTER_WINDOW_EVENTS$1 = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive

if (win$1.MSPointerEvent && !win$1.PointerEvent) {
  POINTER_ELEMENT_EVENTS$1 = 'MSPointerDown';
  POINTER_WINDOW_EVENTS$1 = 'MSPointerMove MSPointerUp MSPointerCancel';
}
/**
 * @private
 * Pointer events input
 * @constructor
 * @extends Input
 */


var PointerEventInput$1 =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose$1(PointerEventInput, _Input);

  function PointerEventInput() {
    var _this;

    var proto = PointerEventInput.prototype;
    proto.evEl = POINTER_ELEMENT_EVENTS$1;
    proto.evWin = POINTER_WINDOW_EVENTS$1;
    _this = _Input.apply(this, arguments) || this;
    _this.store = _this.manager.session.pointerEvents = [];
    return _this;
  }
  /**
   * @private
   * handle mouse events
   * @param {Object} ev
   */


  var _proto = PointerEventInput.prototype;

  _proto.handler = function handler(ev) {
    var store = this.store;
    var removePointer = false;
    var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
    var eventType = POINTER_INPUT_MAP$1[eventTypeNormalized];
    var pointerType = IE10_POINTER_TYPE_ENUM$1[ev.pointerType] || ev.pointerType;
    var isTouch = pointerType === INPUT_TYPE_TOUCH$1; // get index of the event in the store

    var storeIndex = inArray$1(store, ev.pointerId, 'pointerId'); // start and mouse must be down

    if (eventType & INPUT_START$1 && (ev.button === 0 || isTouch)) {
      if (storeIndex < 0) {
        store.push(ev);
        storeIndex = store.length - 1;
      }
    } else if (eventType & (INPUT_END$1 | INPUT_CANCEL$1)) {
      removePointer = true;
    } // it not found, so the pointer hasn't been down (so it's probably a hover)


    if (storeIndex < 0) {
      return;
    } // update the event in the store


    store[storeIndex] = ev;
    this.callback(this.manager, eventType, {
      pointers: store,
      changedPointers: [ev],
      pointerType: pointerType,
      srcEvent: ev
    });

    if (removePointer) {
      // remove from the store
      store.splice(storeIndex, 1);
    }
  };

  return PointerEventInput;
}(Input$1);

/**
 * @private
 * convert array-like objects to real arrays
 * @param {Object} obj
 * @returns {Array}
 */
function toArray$1(obj) {
  return Array.prototype.slice.call(obj, 0);
}

/**
 * @private
 * unique array with objects based on a key (like 'id') or just by the array's value
 * @param {Array} src [{id:1},{id:2},{id:1}]
 * @param {String} [key]
 * @param {Boolean} [sort=False]
 * @returns {Array} [{id:1},{id:2}]
 */

function uniqueArray$1(src, key, sort) {
  var results = [];
  var values = [];
  var i = 0;

  while (i < src.length) {
    var val = key ? src[i][key] : src[i];

    if (inArray$1(values, val) < 0) {
      results.push(src[i]);
    }

    values[i] = val;
    i++;
  }

  if (sort) {
    if (!key) {
      results = results.sort();
    } else {
      results = results.sort(function (a, b) {
        return a[key] > b[key];
      });
    }
  }

  return results;
}

var TOUCH_INPUT_MAP$1 = {
  touchstart: INPUT_START$1,
  touchmove: INPUT_MOVE$1,
  touchend: INPUT_END$1,
  touchcancel: INPUT_CANCEL$1
};
var TOUCH_TARGET_EVENTS$1 = 'touchstart touchmove touchend touchcancel';
/**
 * @private
 * Multi-user touch events input
 * @constructor
 * @extends Input
 */

var TouchInput$1 =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose$1(TouchInput, _Input);

  function TouchInput() {
    var _this;

    TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS$1;
    _this = _Input.apply(this, arguments) || this;
    _this.targetIds = {}; // this.evTarget = TOUCH_TARGET_EVENTS;

    return _this;
  }

  var _proto = TouchInput.prototype;

  _proto.handler = function handler(ev) {
    var type = TOUCH_INPUT_MAP$1[ev.type];
    var touches = getTouches$1.call(this, ev, type);

    if (!touches) {
      return;
    }

    this.callback(this.manager, type, {
      pointers: touches[0],
      changedPointers: touches[1],
      pointerType: INPUT_TYPE_TOUCH$1,
      srcEvent: ev
    });
  };

  return TouchInput;
}(Input$1);

function getTouches$1(ev, type) {
  var allTouches = toArray$1(ev.touches);
  var targetIds = this.targetIds; // when there is only one touch, the process can be simplified

  if (type & (INPUT_START$1 | INPUT_MOVE$1) && allTouches.length === 1) {
    targetIds[allTouches[0].identifier] = true;
    return [allTouches, allTouches];
  }

  var i;
  var targetTouches;
  var changedTouches = toArray$1(ev.changedTouches);
  var changedTargetTouches = [];
  var target = this.target; // get target touches from touches

  targetTouches = allTouches.filter(function (touch) {
    return hasParent$1(touch.target, target);
  }); // collect touches

  if (type === INPUT_START$1) {
    i = 0;

    while (i < targetTouches.length) {
      targetIds[targetTouches[i].identifier] = true;
      i++;
    }
  } // filter changed touches to only contain touches that exist in the collected target ids


  i = 0;

  while (i < changedTouches.length) {
    if (targetIds[changedTouches[i].identifier]) {
      changedTargetTouches.push(changedTouches[i]);
    } // cleanup removed touches


    if (type & (INPUT_END$1 | INPUT_CANCEL$1)) {
      delete targetIds[changedTouches[i].identifier];
    }

    i++;
  }

  if (!changedTargetTouches.length) {
    return;
  }

  return [// merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
  uniqueArray$1(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches];
}

var MOUSE_INPUT_MAP$1 = {
  mousedown: INPUT_START$1,
  mousemove: INPUT_MOVE$1,
  mouseup: INPUT_END$1
};
var MOUSE_ELEMENT_EVENTS$1 = 'mousedown';
var MOUSE_WINDOW_EVENTS$1 = 'mousemove mouseup';
/**
 * @private
 * Mouse events input
 * @constructor
 * @extends Input
 */

var MouseInput$1 =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose$1(MouseInput, _Input);

  function MouseInput() {
    var _this;

    var proto = MouseInput.prototype;
    proto.evEl = MOUSE_ELEMENT_EVENTS$1;
    proto.evWin = MOUSE_WINDOW_EVENTS$1;
    _this = _Input.apply(this, arguments) || this;
    _this.pressed = false; // mousedown state

    return _this;
  }
  /**
   * @private
   * handle mouse events
   * @param {Object} ev
   */


  var _proto = MouseInput.prototype;

  _proto.handler = function handler(ev) {
    var eventType = MOUSE_INPUT_MAP$1[ev.type]; // on start we want to have the left mouse button down

    if (eventType & INPUT_START$1 && ev.button === 0) {
      this.pressed = true;
    }

    if (eventType & INPUT_MOVE$1 && ev.which !== 1) {
      eventType = INPUT_END$1;
    } // mouse must be down


    if (!this.pressed) {
      return;
    }

    if (eventType & INPUT_END$1) {
      this.pressed = false;
    }

    this.callback(this.manager, eventType, {
      pointers: [ev],
      changedPointers: [ev],
      pointerType: INPUT_TYPE_MOUSE$1,
      srcEvent: ev
    });
  };

  return MouseInput;
}(Input$1);

/**
 * @private
 * Combined touch and mouse input
 *
 * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
 * This because touch devices also emit mouse events while doing a touch.
 *
 * @constructor
 * @extends Input
 */

var DEDUP_TIMEOUT$1 = 2500;
var DEDUP_DISTANCE$1 = 25;

function setLastTouch$1(eventData) {
  var _eventData$changedPoi = eventData.changedPointers,
      touch = _eventData$changedPoi[0];

  if (touch.identifier === this.primaryTouch) {
    var lastTouch = {
      x: touch.clientX,
      y: touch.clientY
    };
    var lts = this.lastTouches;
    this.lastTouches.push(lastTouch);

    var removeLastTouch = function removeLastTouch() {
      var i = lts.indexOf(lastTouch);

      if (i > -1) {
        lts.splice(i, 1);
      }
    };

    setTimeout(removeLastTouch, DEDUP_TIMEOUT$1);
  }
}

function recordTouches$1(eventType, eventData) {
  if (eventType & INPUT_START$1) {
    this.primaryTouch = eventData.changedPointers[0].identifier;
    setLastTouch$1.call(this, eventData);
  } else if (eventType & (INPUT_END$1 | INPUT_CANCEL$1)) {
    setLastTouch$1.call(this, eventData);
  }
}

function isSyntheticEvent$1(eventData) {
  var x = eventData.srcEvent.clientX;
  var y = eventData.srcEvent.clientY;

  for (var i = 0; i < this.lastTouches.length; i++) {
    var t = this.lastTouches[i];
    var dx = Math.abs(x - t.x);
    var dy = Math.abs(y - t.y);

    if (dx <= DEDUP_DISTANCE$1 && dy <= DEDUP_DISTANCE$1) {
      return true;
    }
  }

  return false;
}

var TouchMouseInput$1 =
/*#__PURE__*/
function () {
  var TouchMouseInput =
  /*#__PURE__*/
  function (_Input) {
    _inheritsLoose$1(TouchMouseInput, _Input);

    function TouchMouseInput(_manager, callback) {
      var _this;

      _this = _Input.call(this, _manager, callback) || this;

      _this.handler = function (manager, inputEvent, inputData) {
        var isTouch = inputData.pointerType === INPUT_TYPE_TOUCH$1;
        var isMouse = inputData.pointerType === INPUT_TYPE_MOUSE$1;

        if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
          return;
        } // when we're in a touch event, record touches to  de-dupe synthetic mouse event


        if (isTouch) {
          recordTouches$1.call(_assertThisInitialized$1$1(_assertThisInitialized$1$1(_this)), inputEvent, inputData);
        } else if (isMouse && isSyntheticEvent$1.call(_assertThisInitialized$1$1(_assertThisInitialized$1$1(_this)), inputData)) {
          return;
        }

        _this.callback(manager, inputEvent, inputData);
      };

      _this.touch = new TouchInput$1(_this.manager, _this.handler);
      _this.mouse = new MouseInput$1(_this.manager, _this.handler);
      _this.primaryTouch = null;
      _this.lastTouches = [];
      return _this;
    }
    /**
     * @private
     * handle mouse and touch events
     * @param {Hammer} manager
     * @param {String} inputEvent
     * @param {Object} inputData
     */


    var _proto = TouchMouseInput.prototype;

    /**
     * @private
     * remove the event listeners
     */
    _proto.destroy = function destroy() {
      this.touch.destroy();
      this.mouse.destroy();
    };

    return TouchMouseInput;
  }(Input$1);

  return TouchMouseInput;
}();

/**
 * @private
 * create new input type manager
 * called by the Manager constructor
 * @param {Hammer} manager
 * @returns {Input}
 */

function createInputInstance$1(manager) {
  var Type; // let inputClass = manager.options.inputClass;

  var inputClass = manager.options.inputClass;

  if (inputClass) {
    Type = inputClass;
  } else if (SUPPORT_POINTER_EVENTS$1) {
    Type = PointerEventInput$1;
  } else if (SUPPORT_ONLY_TOUCH$1) {
    Type = TouchInput$1;
  } else if (!SUPPORT_TOUCH$1) {
    Type = MouseInput$1;
  } else {
    Type = TouchMouseInput$1;
  }

  return new Type(manager, inputHandler$1);
}

/**
 * @private
 * if the argument is an array, we want to execute the fn on each entry
 * if it aint an array we don't want to do a thing.
 * this is used by all the methods that accept a single and array argument.
 * @param {*|Array} arg
 * @param {String} fn
 * @param {Object} [context]
 * @returns {Boolean}
 */

function invokeArrayArg$1(arg, fn, context) {
  if (Array.isArray(arg)) {
    each$6(arg, context[fn], context);
    return true;
  }

  return false;
}

var STATE_POSSIBLE$1 = 1;
var STATE_BEGAN$1 = 2;
var STATE_CHANGED$1 = 4;
var STATE_ENDED$1 = 8;
var STATE_RECOGNIZED$1 = STATE_ENDED$1;
var STATE_CANCELLED$1 = 16;
var STATE_FAILED$1 = 32;

/**
 * @private
 * get a unique id
 * @returns {number} uniqueId
 */
var _uniqueId$1 = 1;
function uniqueId$1() {
  return _uniqueId$1++;
}

/**
 * @private
 * get a recognizer by name if it is bound to a manager
 * @param {Recognizer|String} otherRecognizer
 * @param {Recognizer} recognizer
 * @returns {Recognizer}
 */
function getRecognizerByNameIfManager$1(otherRecognizer, recognizer) {
  var manager = recognizer.manager;

  if (manager) {
    return manager.get(otherRecognizer);
  }

  return otherRecognizer;
}

/**
 * @private
 * get a usable string, used as event postfix
 * @param {constant} state
 * @returns {String} state
 */

function stateStr$1(state) {
  if (state & STATE_CANCELLED$1) {
    return 'cancel';
  } else if (state & STATE_ENDED$1) {
    return 'end';
  } else if (state & STATE_CHANGED$1) {
    return 'move';
  } else if (state & STATE_BEGAN$1) {
    return 'start';
  }

  return '';
}

/**
 * @private
 * Recognizer flow explained; *
 * All recognizers have the initial state of POSSIBLE when a input session starts.
 * The definition of a input session is from the first input until the last input, with all it's movement in it. *
 * Example session for mouse-input: mousedown -> mousemove -> mouseup
 *
 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
 * which determines with state it should be.
 *
 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
 * POSSIBLE to give it another change on the next cycle.
 *
 *               Possible
 *                  |
 *            +-----+---------------+
 *            |                     |
 *      +-----+-----+               |
 *      |           |               |
 *   Failed      Cancelled          |
 *                          +-------+------+
 *                          |              |
 *                      Recognized       Began
 *                                         |
 *                                      Changed
 *                                         |
 *                                  Ended/Recognized
 */

/**
 * @private
 * Recognizer
 * Every recognizer needs to extend from this class.
 * @constructor
 * @param {Object} options
 */

var Recognizer$1 =
/*#__PURE__*/
function () {
  function Recognizer(options) {
    if (options === void 0) {
      options = {};
    }

    this.options = _extends$1({
      enable: true
    }, options);
    this.id = uniqueId$1();
    this.manager = null; // default is enable true

    this.state = STATE_POSSIBLE$1;
    this.simultaneous = {};
    this.requireFail = [];
  }
  /**
   * @private
   * set options
   * @param {Object} options
   * @return {Recognizer}
   */


  var _proto = Recognizer.prototype;

  _proto.set = function set(options) {
    assign$1$1(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state

    this.manager && this.manager.touchAction.update();
    return this;
  };
  /**
   * @private
   * recognize simultaneous with an other recognizer.
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.recognizeWith = function recognizeWith(otherRecognizer) {
    if (invokeArrayArg$1(otherRecognizer, 'recognizeWith', this)) {
      return this;
    }

    var simultaneous = this.simultaneous;
    otherRecognizer = getRecognizerByNameIfManager$1(otherRecognizer, this);

    if (!simultaneous[otherRecognizer.id]) {
      simultaneous[otherRecognizer.id] = otherRecognizer;
      otherRecognizer.recognizeWith(this);
    }

    return this;
  };
  /**
   * @private
   * drop the simultaneous link. it doesnt remove the link on the other recognizer.
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.dropRecognizeWith = function dropRecognizeWith(otherRecognizer) {
    if (invokeArrayArg$1(otherRecognizer, 'dropRecognizeWith', this)) {
      return this;
    }

    otherRecognizer = getRecognizerByNameIfManager$1(otherRecognizer, this);
    delete this.simultaneous[otherRecognizer.id];
    return this;
  };
  /**
   * @private
   * recognizer can only run when an other is failing
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.requireFailure = function requireFailure(otherRecognizer) {
    if (invokeArrayArg$1(otherRecognizer, 'requireFailure', this)) {
      return this;
    }

    var requireFail = this.requireFail;
    otherRecognizer = getRecognizerByNameIfManager$1(otherRecognizer, this);

    if (inArray$1(requireFail, otherRecognizer) === -1) {
      requireFail.push(otherRecognizer);
      otherRecognizer.requireFailure(this);
    }

    return this;
  };
  /**
   * @private
   * drop the requireFailure link. it does not remove the link on the other recognizer.
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.dropRequireFailure = function dropRequireFailure(otherRecognizer) {
    if (invokeArrayArg$1(otherRecognizer, 'dropRequireFailure', this)) {
      return this;
    }

    otherRecognizer = getRecognizerByNameIfManager$1(otherRecognizer, this);
    var index = inArray$1(this.requireFail, otherRecognizer);

    if (index > -1) {
      this.requireFail.splice(index, 1);
    }

    return this;
  };
  /**
   * @private
   * has require failures boolean
   * @returns {boolean}
   */


  _proto.hasRequireFailures = function hasRequireFailures() {
    return this.requireFail.length > 0;
  };
  /**
   * @private
   * if the recognizer can recognize simultaneous with an other recognizer
   * @param {Recognizer} otherRecognizer
   * @returns {Boolean}
   */


  _proto.canRecognizeWith = function canRecognizeWith(otherRecognizer) {
    return !!this.simultaneous[otherRecognizer.id];
  };
  /**
   * @private
   * You should use `tryEmit` instead of `emit` directly to check
   * that all the needed recognizers has failed before emitting.
   * @param {Object} input
   */


  _proto.emit = function emit(input) {
    var self = this;
    var state = this.state;

    function emit(event) {
      self.manager.emit(event, input);
    } // 'panstart' and 'panmove'


    if (state < STATE_ENDED$1) {
      emit(self.options.event + stateStr$1(state));
    }

    emit(self.options.event); // simple 'eventName' events

    if (input.additionalEvent) {
      // additional event(panleft, panright, pinchin, pinchout...)
      emit(input.additionalEvent);
    } // panend and pancancel


    if (state >= STATE_ENDED$1) {
      emit(self.options.event + stateStr$1(state));
    }
  };
  /**
   * @private
   * Check that all the require failure recognizers has failed,
   * if true, it emits a gesture event,
   * otherwise, setup the state to FAILED.
   * @param {Object} input
   */


  _proto.tryEmit = function tryEmit(input) {
    if (this.canEmit()) {
      return this.emit(input);
    } // it's failing anyway


    this.state = STATE_FAILED$1;
  };
  /**
   * @private
   * can we emit?
   * @returns {boolean}
   */


  _proto.canEmit = function canEmit() {
    var i = 0;

    while (i < this.requireFail.length) {
      if (!(this.requireFail[i].state & (STATE_FAILED$1 | STATE_POSSIBLE$1))) {
        return false;
      }

      i++;
    }

    return true;
  };
  /**
   * @private
   * update the recognizer
   * @param {Object} inputData
   */


  _proto.recognize = function recognize(inputData) {
    // make a new copy of the inputData
    // so we can change the inputData without messing up the other recognizers
    var inputDataClone = assign$1$1({}, inputData); // is is enabled and allow recognizing?

    if (!boolOrFn$1(this.options.enable, [this, inputDataClone])) {
      this.reset();
      this.state = STATE_FAILED$1;
      return;
    } // reset when we've reached the end


    if (this.state & (STATE_RECOGNIZED$1 | STATE_CANCELLED$1 | STATE_FAILED$1)) {
      this.state = STATE_POSSIBLE$1;
    }

    this.state = this.process(inputDataClone); // the recognizer has recognized a gesture
    // so trigger an event

    if (this.state & (STATE_BEGAN$1 | STATE_CHANGED$1 | STATE_ENDED$1 | STATE_CANCELLED$1)) {
      this.tryEmit(inputDataClone);
    }
  };
  /**
   * @private
   * return the state of the recognizer
   * the actual recognizing happens in this method
   * @virtual
   * @param {Object} inputData
   * @returns {constant} STATE
   */

  /* jshint ignore:start */


  _proto.process = function process(inputData) {};
  /* jshint ignore:end */

  /**
   * @private
   * return the preferred touch-action
   * @virtual
   * @returns {Array}
   */


  _proto.getTouchAction = function getTouchAction() {};
  /**
   * @private
   * called when the gesture isn't allowed to recognize
   * like when another is being recognized or it is disabled
   * @virtual
   */


  _proto.reset = function reset() {};

  return Recognizer;
}();

/**
 * @private
 * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
 * between the given interval and position. The delay option can be used to recognize multi-taps without firing
 * a single tap.
 *
 * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
 * multi-taps being recognized.
 * @constructor
 * @extends Recognizer
 */

var TapRecognizer$1 =
/*#__PURE__*/
function (_Recognizer) {
  _inheritsLoose$1(TapRecognizer, _Recognizer);

  function TapRecognizer(options) {
    var _this;

    if (options === void 0) {
      options = {};
    }

    _this = _Recognizer.call(this, _extends$1({
      event: 'tap',
      pointers: 1,
      taps: 1,
      interval: 300,
      // max time between the multi-tap taps
      time: 250,
      // max time of the pointer to be down (like finger on the screen)
      threshold: 9,
      // a minimal movement is ok, but keep it low
      posThreshold: 10
    }, options)) || this; // previous time and center,
    // used for tap counting

    _this.pTime = false;
    _this.pCenter = false;
    _this._timer = null;
    _this._input = null;
    _this.count = 0;
    return _this;
  }

  var _proto = TapRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_MANIPULATION$1];
  };

  _proto.process = function process(input) {
    var _this2 = this;

    var options = this.options;
    var validPointers = input.pointers.length === options.pointers;
    var validMovement = input.distance < options.threshold;
    var validTouchTime = input.deltaTime < options.time;
    this.reset();

    if (input.eventType & INPUT_START$1 && this.count === 0) {
      return this.failTimeout();
    } // we only allow little movement
    // and we've reached an end event, so a tap is possible


    if (validMovement && validTouchTime && validPointers) {
      if (input.eventType !== INPUT_END$1) {
        return this.failTimeout();
      }

      var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true;
      var validMultiTap = !this.pCenter || getDistance$1(this.pCenter, input.center) < options.posThreshold;
      this.pTime = input.timeStamp;
      this.pCenter = input.center;

      if (!validMultiTap || !validInterval) {
        this.count = 1;
      } else {
        this.count += 1;
      }

      this._input = input; // if tap count matches we have recognized it,
      // else it has began recognizing...

      var tapCount = this.count % options.taps;

      if (tapCount === 0) {
        // no failing requirements, immediately trigger the tap event
        // or wait as long as the multitap interval to trigger
        if (!this.hasRequireFailures()) {
          return STATE_RECOGNIZED$1;
        } else {
          this._timer = setTimeout(function () {
            _this2.state = STATE_RECOGNIZED$1;

            _this2.tryEmit();
          }, options.interval);
          return STATE_BEGAN$1;
        }
      }
    }

    return STATE_FAILED$1;
  };

  _proto.failTimeout = function failTimeout() {
    var _this3 = this;

    this._timer = setTimeout(function () {
      _this3.state = STATE_FAILED$1;
    }, this.options.interval);
    return STATE_FAILED$1;
  };

  _proto.reset = function reset() {
    clearTimeout(this._timer);
  };

  _proto.emit = function emit() {
    if (this.state === STATE_RECOGNIZED$1) {
      this._input.tapCount = this.count;
      this.manager.emit(this.options.event, this._input);
    }
  };

  return TapRecognizer;
}(Recognizer$1);

/**
 * @private
 * This recognizer is just used as a base for the simple attribute recognizers.
 * @constructor
 * @extends Recognizer
 */

var AttrRecognizer$1 =
/*#__PURE__*/
function (_Recognizer) {
  _inheritsLoose$1(AttrRecognizer, _Recognizer);

  function AttrRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _Recognizer.call(this, _extends$1({
      pointers: 1
    }, options)) || this;
  }
  /**
   * @private
   * Used to check if it the recognizer receives valid input, like input.distance > 10.
   * @memberof AttrRecognizer
   * @param {Object} input
   * @returns {Boolean} recognized
   */


  var _proto = AttrRecognizer.prototype;

  _proto.attrTest = function attrTest(input) {
    var optionPointers = this.options.pointers;
    return optionPointers === 0 || input.pointers.length === optionPointers;
  };
  /**
   * @private
   * Process the input and return the state for the recognizer
   * @memberof AttrRecognizer
   * @param {Object} input
   * @returns {*} State
   */


  _proto.process = function process(input) {
    var state = this.state;
    var eventType = input.eventType;
    var isRecognized = state & (STATE_BEGAN$1 | STATE_CHANGED$1);
    var isValid = this.attrTest(input); // on cancel input and we've recognized before, return STATE_CANCELLED

    if (isRecognized && (eventType & INPUT_CANCEL$1 || !isValid)) {
      return state | STATE_CANCELLED$1;
    } else if (isRecognized || isValid) {
      if (eventType & INPUT_END$1) {
        return state | STATE_ENDED$1;
      } else if (!(state & STATE_BEGAN$1)) {
        return STATE_BEGAN$1;
      }

      return state | STATE_CHANGED$1;
    }

    return STATE_FAILED$1;
  };

  return AttrRecognizer;
}(Recognizer$1);

/**
 * @private
 * direction cons to string
 * @param {constant} direction
 * @returns {String}
 */

function directionStr$1(direction) {
  if (direction === DIRECTION_DOWN$1) {
    return 'down';
  } else if (direction === DIRECTION_UP$1) {
    return 'up';
  } else if (direction === DIRECTION_LEFT$1) {
    return 'left';
  } else if (direction === DIRECTION_RIGHT$1) {
    return 'right';
  }

  return '';
}

/**
 * @private
 * Pan
 * Recognized when the pointer is down and moved in the allowed direction.
 * @constructor
 * @extends AttrRecognizer
 */

var PanRecognizer$1 =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose$1(PanRecognizer, _AttrRecognizer);

  function PanRecognizer(options) {
    var _this;

    if (options === void 0) {
      options = {};
    }

    _this = _AttrRecognizer.call(this, _extends$1({
      event: 'pan',
      threshold: 10,
      pointers: 1,
      direction: DIRECTION_ALL$1
    }, options)) || this;
    _this.pX = null;
    _this.pY = null;
    return _this;
  }

  var _proto = PanRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    var direction = this.options.direction;
    var actions = [];

    if (direction & DIRECTION_HORIZONTAL$1) {
      actions.push(TOUCH_ACTION_PAN_Y$1);
    }

    if (direction & DIRECTION_VERTICAL$1) {
      actions.push(TOUCH_ACTION_PAN_X$1);
    }

    return actions;
  };

  _proto.directionTest = function directionTest(input) {
    var options = this.options;
    var hasMoved = true;
    var distance = input.distance;
    var direction = input.direction;
    var x = input.deltaX;
    var y = input.deltaY; // lock to axis?

    if (!(direction & options.direction)) {
      if (options.direction & DIRECTION_HORIZONTAL$1) {
        direction = x === 0 ? DIRECTION_NONE$1 : x < 0 ? DIRECTION_LEFT$1 : DIRECTION_RIGHT$1;
        hasMoved = x !== this.pX;
        distance = Math.abs(input.deltaX);
      } else {
        direction = y === 0 ? DIRECTION_NONE$1 : y < 0 ? DIRECTION_UP$1 : DIRECTION_DOWN$1;
        hasMoved = y !== this.pY;
        distance = Math.abs(input.deltaY);
      }
    }

    input.direction = direction;
    return hasMoved && distance > options.threshold && direction & options.direction;
  };

  _proto.attrTest = function attrTest(input) {
    return AttrRecognizer$1.prototype.attrTest.call(this, input) && ( // replace with a super call
    this.state & STATE_BEGAN$1 || !(this.state & STATE_BEGAN$1) && this.directionTest(input));
  };

  _proto.emit = function emit(input) {
    this.pX = input.deltaX;
    this.pY = input.deltaY;
    var direction = directionStr$1(input.direction);

    if (direction) {
      input.additionalEvent = this.options.event + direction;
    }

    _AttrRecognizer.prototype.emit.call(this, input);
  };

  return PanRecognizer;
}(AttrRecognizer$1);

/**
 * @private
 * Swipe
 * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
 * @constructor
 * @extends AttrRecognizer
 */

var SwipeRecognizer$1 =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose$1(SwipeRecognizer, _AttrRecognizer);

  function SwipeRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _AttrRecognizer.call(this, _extends$1({
      event: 'swipe',
      threshold: 10,
      velocity: 0.3,
      direction: DIRECTION_HORIZONTAL$1 | DIRECTION_VERTICAL$1,
      pointers: 1
    }, options)) || this;
  }

  var _proto = SwipeRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return PanRecognizer$1.prototype.getTouchAction.call(this);
  };

  _proto.attrTest = function attrTest(input) {
    var direction = this.options.direction;
    var velocity;

    if (direction & (DIRECTION_HORIZONTAL$1 | DIRECTION_VERTICAL$1)) {
      velocity = input.overallVelocity;
    } else if (direction & DIRECTION_HORIZONTAL$1) {
      velocity = input.overallVelocityX;
    } else if (direction & DIRECTION_VERTICAL$1) {
      velocity = input.overallVelocityY;
    }

    return _AttrRecognizer.prototype.attrTest.call(this, input) && direction & input.offsetDirection && input.distance > this.options.threshold && input.maxPointers === this.options.pointers && abs$3(velocity) > this.options.velocity && input.eventType & INPUT_END$1;
  };

  _proto.emit = function emit(input) {
    var direction = directionStr$1(input.offsetDirection);

    if (direction) {
      this.manager.emit(this.options.event + direction, input);
    }

    this.manager.emit(this.options.event, input);
  };

  return SwipeRecognizer;
}(AttrRecognizer$1);

/**
 * @private
 * Pinch
 * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
 * @constructor
 * @extends AttrRecognizer
 */

var PinchRecognizer$1 =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose$1(PinchRecognizer, _AttrRecognizer);

  function PinchRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _AttrRecognizer.call(this, _extends$1({
      event: 'pinch',
      threshold: 0,
      pointers: 2
    }, options)) || this;
  }

  var _proto = PinchRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_NONE$1];
  };

  _proto.attrTest = function attrTest(input) {
    return _AttrRecognizer.prototype.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN$1);
  };

  _proto.emit = function emit(input) {
    if (input.scale !== 1) {
      var inOut = input.scale < 1 ? 'in' : 'out';
      input.additionalEvent = this.options.event + inOut;
    }

    _AttrRecognizer.prototype.emit.call(this, input);
  };

  return PinchRecognizer;
}(AttrRecognizer$1);

/**
 * @private
 * Rotate
 * Recognized when two or more pointer are moving in a circular motion.
 * @constructor
 * @extends AttrRecognizer
 */

var RotateRecognizer$1 =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose$1(RotateRecognizer, _AttrRecognizer);

  function RotateRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _AttrRecognizer.call(this, _extends$1({
      event: 'rotate',
      threshold: 0,
      pointers: 2
    }, options)) || this;
  }

  var _proto = RotateRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_NONE$1];
  };

  _proto.attrTest = function attrTest(input) {
    return _AttrRecognizer.prototype.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN$1);
  };

  return RotateRecognizer;
}(AttrRecognizer$1);

/**
 * @private
 * Press
 * Recognized when the pointer is down for x ms without any movement.
 * @constructor
 * @extends Recognizer
 */

var PressRecognizer$1 =
/*#__PURE__*/
function (_Recognizer) {
  _inheritsLoose$1(PressRecognizer, _Recognizer);

  function PressRecognizer(options) {
    var _this;

    if (options === void 0) {
      options = {};
    }

    _this = _Recognizer.call(this, _extends$1({
      event: 'press',
      pointers: 1,
      time: 251,
      // minimal time of the pointer to be pressed
      threshold: 9
    }, options)) || this;
    _this._timer = null;
    _this._input = null;
    return _this;
  }

  var _proto = PressRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_AUTO$1];
  };

  _proto.process = function process(input) {
    var _this2 = this;

    var options = this.options;
    var validPointers = input.pointers.length === options.pointers;
    var validMovement = input.distance < options.threshold;
    var validTime = input.deltaTime > options.time;
    this._input = input; // we only allow little movement
    // and we've reached an end event, so a tap is possible

    if (!validMovement || !validPointers || input.eventType & (INPUT_END$1 | INPUT_CANCEL$1) && !validTime) {
      this.reset();
    } else if (input.eventType & INPUT_START$1) {
      this.reset();
      this._timer = setTimeout(function () {
        _this2.state = STATE_RECOGNIZED$1;

        _this2.tryEmit();
      }, options.time);
    } else if (input.eventType & INPUT_END$1) {
      return STATE_RECOGNIZED$1;
    }

    return STATE_FAILED$1;
  };

  _proto.reset = function reset() {
    clearTimeout(this._timer);
  };

  _proto.emit = function emit(input) {
    if (this.state !== STATE_RECOGNIZED$1) {
      return;
    }

    if (input && input.eventType & INPUT_END$1) {
      this.manager.emit(this.options.event + "up", input);
    } else {
      this._input.timeStamp = now$4();
      this.manager.emit(this.options.event, this._input);
    }
  };

  return PressRecognizer;
}(Recognizer$1);

var defaults$2 = {
  /**
   * @private
   * set if DOM events are being triggered.
   * But this is slower and unused by simple implementations, so disabled by default.
   * @type {Boolean}
   * @default false
   */
  domEvents: false,

  /**
   * @private
   * The value for the touchAction property/fallback.
   * When set to `compute` it will magically set the correct value based on the added recognizers.
   * @type {String}
   * @default compute
   */
  touchAction: TOUCH_ACTION_COMPUTE$1,

  /**
   * @private
   * @type {Boolean}
   * @default true
   */
  enable: true,

  /**
   * @private
   * EXPERIMENTAL FEATURE -- can be removed/changed
   * Change the parent input target element.
   * If Null, then it is being set the to main element.
   * @type {Null|EventTarget}
   * @default null
   */
  inputTarget: null,

  /**
   * @private
   * force an input class
   * @type {Null|Function}
   * @default null
   */
  inputClass: null,

  /**
   * @private
   * Some CSS properties can be used to improve the working of Hammer.
   * Add them to this method and they will be set when creating a new Manager.
   * @namespace
   */
  cssProps: {
    /**
     * @private
     * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
     * @type {String}
     * @default 'none'
     */
    userSelect: "none",

    /**
     * @private
     * Disable the Windows Phone grippers when pressing an element.
     * @type {String}
     * @default 'none'
     */
    touchSelect: "none",

    /**
     * @private
     * Disables the default callout shown when you touch and hold a touch target.
     * On iOS, when you touch and hold a touch target such as a link, Safari displays
     * a callout containing information about the link. This property allows you to disable that callout.
     * @type {String}
     * @default 'none'
     */
    touchCallout: "none",

    /**
     * @private
     * Specifies whether zooming is enabled. Used by IE10>
     * @type {String}
     * @default 'none'
     */
    contentZooming: "none",

    /**
     * @private
     * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
     * @type {String}
     * @default 'none'
     */
    userDrag: "none",

    /**
     * @private
     * Overrides the highlight color shown when the user taps a link or a JavaScript
     * clickable element in iOS. This property obeys the alpha value, if specified.
     * @type {String}
     * @default 'rgba(0,0,0,0)'
     */
    tapHighlightColor: "rgba(0,0,0,0)"
  }
};
/**
 * @private
 * Default recognizer setup when calling `Hammer()`
 * When creating a new Manager these will be skipped.
 * This is separated with other defaults because of tree-shaking.
 * @type {Array}
 */

var preset$1 = [[RotateRecognizer$1, {
  enable: false
}], [PinchRecognizer$1, {
  enable: false
}, ['rotate']], [SwipeRecognizer$1, {
  direction: DIRECTION_HORIZONTAL$1
}], [PanRecognizer$1, {
  direction: DIRECTION_HORIZONTAL$1
}, ['swipe']], [TapRecognizer$1], [TapRecognizer$1, {
  event: 'doubletap',
  taps: 2
}, ['tap']], [PressRecognizer$1]];

var STOP$1 = 1;
var FORCED_STOP$1 = 2;
/**
 * @private
 * add/remove the css properties as defined in manager.options.cssProps
 * @param {Manager} manager
 * @param {Boolean} add
 */

function toggleCssProps$1(manager, add) {
  var element = manager.element;

  if (!element.style) {
    return;
  }

  var prop;
  each$6(manager.options.cssProps, function (value, name) {
    prop = prefixed$1(element.style, name);

    if (add) {
      manager.oldCssProps[prop] = element.style[prop];
      element.style[prop] = value;
    } else {
      element.style[prop] = manager.oldCssProps[prop] || "";
    }
  });

  if (!add) {
    manager.oldCssProps = {};
  }
}
/**
 * @private
 * trigger dom event
 * @param {String} event
 * @param {Object} data
 */


function triggerDomEvent$1(event, data) {
  var gestureEvent = document.createEvent("Event");
  gestureEvent.initEvent(event, true, true);
  gestureEvent.gesture = data;
  data.target.dispatchEvent(gestureEvent);
}
/**
* @private
 * Manager
 * @param {HTMLElement} element
 * @param {Object} [options]
 * @constructor
 */


var Manager$1 =
/*#__PURE__*/
function () {
  function Manager(element, options) {
    var _this = this;

    this.options = assign$1$1({}, defaults$2, options || {});
    this.options.inputTarget = this.options.inputTarget || element;
    this.handlers = {};
    this.session = {};
    this.recognizers = [];
    this.oldCssProps = {};
    this.element = element;
    this.input = createInputInstance$1(this);
    this.touchAction = new TouchAction$1(this, this.options.touchAction);
    toggleCssProps$1(this, true);
    each$6(this.options.recognizers, function (item) {
      var recognizer = _this.add(new item[0](item[1]));

      item[2] && recognizer.recognizeWith(item[2]);
      item[3] && recognizer.requireFailure(item[3]);
    }, this);
  }
  /**
   * @private
   * set options
   * @param {Object} options
   * @returns {Manager}
   */


  var _proto = Manager.prototype;

  _proto.set = function set(options) {
    assign$1$1(this.options, options); // Options that need a little more setup

    if (options.touchAction) {
      this.touchAction.update();
    }

    if (options.inputTarget) {
      // Clean up existing event listeners and reinitialize
      this.input.destroy();
      this.input.target = options.inputTarget;
      this.input.init();
    }

    return this;
  };
  /**
   * @private
   * stop recognizing for this session.
   * This session will be discarded, when a new [input]start event is fired.
   * When forced, the recognizer cycle is stopped immediately.
   * @param {Boolean} [force]
   */


  _proto.stop = function stop(force) {
    this.session.stopped = force ? FORCED_STOP$1 : STOP$1;
  };
  /**
   * @private
   * run the recognizers!
   * called by the inputHandler function on every movement of the pointers (touches)
   * it walks through all the recognizers and tries to detect the gesture that is being made
   * @param {Object} inputData
   */


  _proto.recognize = function recognize(inputData) {
    var session = this.session;

    if (session.stopped) {
      return;
    } // run the touch-action polyfill


    this.touchAction.preventDefaults(inputData);
    var recognizer;
    var recognizers = this.recognizers; // this holds the recognizer that is being recognized.
    // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
    // if no recognizer is detecting a thing, it is set to `null`

    var curRecognizer = session.curRecognizer; // reset when the last recognizer is recognized
    // or when we're in a new session

    if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED$1) {
      session.curRecognizer = null;
      curRecognizer = null;
    }

    var i = 0;

    while (i < recognizers.length) {
      recognizer = recognizers[i]; // find out if we are allowed try to recognize the input for this one.
      // 1.   allow if the session is NOT forced stopped (see the .stop() method)
      // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
      //      that is being recognized.
      // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
      //      this can be setup with the `recognizeWith()` method on the recognizer.

      if (session.stopped !== FORCED_STOP$1 && ( // 1
      !curRecognizer || recognizer === curRecognizer || // 2
      recognizer.canRecognizeWith(curRecognizer))) {
        // 3
        recognizer.recognize(inputData);
      } else {
        recognizer.reset();
      } // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
      // current active recognizer. but only if we don't already have an active recognizer


      if (!curRecognizer && recognizer.state & (STATE_BEGAN$1 | STATE_CHANGED$1 | STATE_ENDED$1)) {
        session.curRecognizer = recognizer;
        curRecognizer = recognizer;
      }

      i++;
    }
  };
  /**
   * @private
   * get a recognizer by its event name.
   * @param {Recognizer|String} recognizer
   * @returns {Recognizer|Null}
   */


  _proto.get = function get(recognizer) {
    if (recognizer instanceof Recognizer$1) {
      return recognizer;
    }

    var recognizers = this.recognizers;

    for (var i = 0; i < recognizers.length; i++) {
      if (recognizers[i].options.event === recognizer) {
        return recognizers[i];
      }
    }

    return null;
  };
  /**
   * @private add a recognizer to the manager
   * existing recognizers with the same event name will be removed
   * @param {Recognizer} recognizer
   * @returns {Recognizer|Manager}
   */


  _proto.add = function add(recognizer) {
    if (invokeArrayArg$1(recognizer, "add", this)) {
      return this;
    } // remove existing


    var existing = this.get(recognizer.options.event);

    if (existing) {
      this.remove(existing);
    }

    this.recognizers.push(recognizer);
    recognizer.manager = this;
    this.touchAction.update();
    return recognizer;
  };
  /**
   * @private
   * remove a recognizer by name or instance
   * @param {Recognizer|String} recognizer
   * @returns {Manager}
   */


  _proto.remove = function remove(recognizer) {
    if (invokeArrayArg$1(recognizer, "remove", this)) {
      return this;
    }

    var targetRecognizer = this.get(recognizer); // let's make sure this recognizer exists

    if (recognizer) {
      var recognizers = this.recognizers;
      var index = inArray$1(recognizers, targetRecognizer);

      if (index !== -1) {
        recognizers.splice(index, 1);
        this.touchAction.update();
      }
    }

    return this;
  };
  /**
   * @private
   * bind event
   * @param {String} events
   * @param {Function} handler
   * @returns {EventEmitter} this
   */


  _proto.on = function on(events, handler) {
    if (events === undefined || handler === undefined) {
      return this;
    }

    var handlers = this.handlers;
    each$6(splitStr$1(events), function (event) {
      handlers[event] = handlers[event] || [];
      handlers[event].push(handler);
    });
    return this;
  };
  /**
   * @private unbind event, leave emit blank to remove all handlers
   * @param {String} events
   * @param {Function} [handler]
   * @returns {EventEmitter} this
   */


  _proto.off = function off(events, handler) {
    if (events === undefined) {
      return this;
    }

    var handlers = this.handlers;
    each$6(splitStr$1(events), function (event) {
      if (!handler) {
        delete handlers[event];
      } else {
        handlers[event] && handlers[event].splice(inArray$1(handlers[event], handler), 1);
      }
    });
    return this;
  };
  /**
   * @private emit event to the listeners
   * @param {String} event
   * @param {Object} data
   */


  _proto.emit = function emit(event, data) {
    // we also want to trigger dom events
    if (this.options.domEvents) {
      triggerDomEvent$1(event, data);
    } // no handlers, so skip it all


    var handlers = this.handlers[event] && this.handlers[event].slice();

    if (!handlers || !handlers.length) {
      return;
    }

    data.type = event;

    data.preventDefault = function () {
      data.srcEvent.preventDefault();
    };

    var i = 0;

    while (i < handlers.length) {
      handlers[i](data);
      i++;
    }
  };
  /**
   * @private
   * destroy the manager and unbinds all events
   * it doesn't unbind dom events, that is the user own responsibility
   */


  _proto.destroy = function destroy() {
    this.element && toggleCssProps$1(this, false);
    this.handlers = {};
    this.session = {};
    this.input.destroy();
    this.element = null;
  };

  return Manager;
}();

var SINGLE_TOUCH_INPUT_MAP$1 = {
  touchstart: INPUT_START$1,
  touchmove: INPUT_MOVE$1,
  touchend: INPUT_END$1,
  touchcancel: INPUT_CANCEL$1
};
var SINGLE_TOUCH_TARGET_EVENTS$1 = 'touchstart';
var SINGLE_TOUCH_WINDOW_EVENTS$1 = 'touchstart touchmove touchend touchcancel';
/**
 * @private
 * Touch events input
 * @constructor
 * @extends Input
 */

var SingleTouchInput$1 =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose$1(SingleTouchInput, _Input);

  function SingleTouchInput() {
    var _this;

    var proto = SingleTouchInput.prototype;
    proto.evTarget = SINGLE_TOUCH_TARGET_EVENTS$1;
    proto.evWin = SINGLE_TOUCH_WINDOW_EVENTS$1;
    _this = _Input.apply(this, arguments) || this;
    _this.started = false;
    return _this;
  }

  var _proto = SingleTouchInput.prototype;

  _proto.handler = function handler(ev) {
    var type = SINGLE_TOUCH_INPUT_MAP$1[ev.type]; // should we handle the touch events?

    if (type === INPUT_START$1) {
      this.started = true;
    }

    if (!this.started) {
      return;
    }

    var touches = normalizeSingleTouches$1.call(this, ev, type); // when done, reset the started state

    if (type & (INPUT_END$1 | INPUT_CANCEL$1) && touches[0].length - touches[1].length === 0) {
      this.started = false;
    }

    this.callback(this.manager, type, {
      pointers: touches[0],
      changedPointers: touches[1],
      pointerType: INPUT_TYPE_TOUCH$1,
      srcEvent: ev
    });
  };

  return SingleTouchInput;
}(Input$1);

function normalizeSingleTouches$1(ev, type) {
  var all = toArray$1(ev.touches);
  var changed = toArray$1(ev.changedTouches);

  if (type & (INPUT_END$1 | INPUT_CANCEL$1)) {
    all = uniqueArray$1(all.concat(changed), 'identifier', true);
  }

  return [all, changed];
}

/**
 * @private
 * wrap a method with a deprecation warning and stack trace
 * @param {Function} method
 * @param {String} name
 * @param {String} message
 * @returns {Function} A new function wrapping the supplied method.
 */
function deprecate$1(method, name, message) {
  var deprecationMessage = "DEPRECATED METHOD: " + name + "\n" + message + " AT \n";
  return function () {
    var e = new Error('get-stack-trace');
    var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
    var log = window.console && (window.console.warn || window.console.log);

    if (log) {
      log.call(window.console, deprecationMessage, stack);
    }

    return method.apply(this, arguments);
  };
}

/**
 * @private
 * extend object.
 * means that properties in dest will be overwritten by the ones in src.
 * @param {Object} dest
 * @param {Object} src
 * @param {Boolean} [merge=false]
 * @returns {Object} dest
 */

var extend$2 = deprecate$1(function (dest, src, merge) {
  var keys = Object.keys(src);
  var i = 0;

  while (i < keys.length) {
    if (!merge || merge && dest[keys[i]] === undefined) {
      dest[keys[i]] = src[keys[i]];
    }

    i++;
  }

  return dest;
}, 'extend', 'Use `assign`.');

/**
 * @private
 * merge the values from src in the dest.
 * means that properties that exist in dest will not be overwritten by src
 * @param {Object} dest
 * @param {Object} src
 * @returns {Object} dest
 */

var merge$1$1 = deprecate$1(function (dest, src) {
  return extend$2(dest, src, true);
}, 'merge', 'Use `assign`.');

/**
 * @private
 * simple class inheritance
 * @param {Function} child
 * @param {Function} base
 * @param {Object} [properties]
 */

function inherit$1(child, base, properties) {
  var baseP = base.prototype;
  var childP;
  childP = child.prototype = Object.create(baseP);
  childP.constructor = child;
  childP._super = baseP;

  if (properties) {
    assign$1$1(childP, properties);
  }
}

/**
 * @private
 * simple function bind
 * @param {Function} fn
 * @param {Object} context
 * @returns {Function}
 */
function bindFn$1(fn, context) {
  return function boundFn() {
    return fn.apply(context, arguments);
  };
}

/**
 * @private
 * Simple way to create a manager with a default set of recognizers.
 * @param {HTMLElement} element
 * @param {Object} [options]
 * @constructor
 */

var Hammer$3 =
/*#__PURE__*/
function () {
  var Hammer =
  /**
    * @private
    * @const {string}
    */
  function Hammer(element, options) {
    if (options === void 0) {
      options = {};
    }

    return new Manager$1(element, _extends$1({
      recognizers: preset$1.concat()
    }, options));
  };

  Hammer.VERSION = "2.0.17-rc";
  Hammer.DIRECTION_ALL = DIRECTION_ALL$1;
  Hammer.DIRECTION_DOWN = DIRECTION_DOWN$1;
  Hammer.DIRECTION_LEFT = DIRECTION_LEFT$1;
  Hammer.DIRECTION_RIGHT = DIRECTION_RIGHT$1;
  Hammer.DIRECTION_UP = DIRECTION_UP$1;
  Hammer.DIRECTION_HORIZONTAL = DIRECTION_HORIZONTAL$1;
  Hammer.DIRECTION_VERTICAL = DIRECTION_VERTICAL$1;
  Hammer.DIRECTION_NONE = DIRECTION_NONE$1;
  Hammer.DIRECTION_DOWN = DIRECTION_DOWN$1;
  Hammer.INPUT_START = INPUT_START$1;
  Hammer.INPUT_MOVE = INPUT_MOVE$1;
  Hammer.INPUT_END = INPUT_END$1;
  Hammer.INPUT_CANCEL = INPUT_CANCEL$1;
  Hammer.STATE_POSSIBLE = STATE_POSSIBLE$1;
  Hammer.STATE_BEGAN = STATE_BEGAN$1;
  Hammer.STATE_CHANGED = STATE_CHANGED$1;
  Hammer.STATE_ENDED = STATE_ENDED$1;
  Hammer.STATE_RECOGNIZED = STATE_RECOGNIZED$1;
  Hammer.STATE_CANCELLED = STATE_CANCELLED$1;
  Hammer.STATE_FAILED = STATE_FAILED$1;
  Hammer.Manager = Manager$1;
  Hammer.Input = Input$1;
  Hammer.TouchAction = TouchAction$1;
  Hammer.TouchInput = TouchInput$1;
  Hammer.MouseInput = MouseInput$1;
  Hammer.PointerEventInput = PointerEventInput$1;
  Hammer.TouchMouseInput = TouchMouseInput$1;
  Hammer.SingleTouchInput = SingleTouchInput$1;
  Hammer.Recognizer = Recognizer$1;
  Hammer.AttrRecognizer = AttrRecognizer$1;
  Hammer.Tap = TapRecognizer$1;
  Hammer.Pan = PanRecognizer$1;
  Hammer.Swipe = SwipeRecognizer$1;
  Hammer.Pinch = PinchRecognizer$1;
  Hammer.Rotate = RotateRecognizer$1;
  Hammer.Press = PressRecognizer$1;
  Hammer.on = addEventListeners$1;
  Hammer.off = removeEventListeners$1;
  Hammer.each = each$6;
  Hammer.merge = merge$1$1;
  Hammer.extend = extend$2;
  Hammer.bindFn = bindFn$1;
  Hammer.assign = assign$1$1;
  Hammer.inherit = inherit$1;
  Hammer.bindFn = bindFn$1;
  Hammer.prefixed = prefixed$1;
  Hammer.toArray = toArray$1;
  Hammer.inArray = inArray$1;
  Hammer.uniqueArray = uniqueArray$1;
  Hammer.splitStr = splitStr$1;
  Hammer.boolOrFn = boolOrFn$1;
  Hammer.hasParent = hasParent$1;
  Hammer.addEventListeners = addEventListeners$1;
  Hammer.removeEventListeners = removeEventListeners$1;
  Hammer.defaults = assign$1$1({}, defaults$2, {
    preset: preset$1
  });
  return Hammer;
}();

var RealHammer$1 = Hammer$3;

function _createForOfIteratorHelper$3$1(o, allowArrayLike) { var it = typeof _Symbol$2 !== "undefined" && _getIteratorMethod$1(o) || o["@@iterator"]; if (!it) { if (_Array$isArray$2(o) || (it = _unsupportedIterableToArray$3$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$3$1(o, minLen) { var _context21; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$3$1(o, minLen); var n = _sliceInstanceProperty$2(_context21 = Object.prototype.toString.call(o)).call(_context21, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3$1(o, minLen); }
function _arrayLikeToArray$3$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

/**
 * Use this symbol to delete properies in deepObjectAssign.
 */
var DELETE = _Symbol$2("DELETE");
/**
 * Pure version of deepObjectAssign, it doesn't modify any of it's arguments.
 *
 * @param base - The base object that fullfils the whole interface T.
 * @param updates - Updates that may change or delete props.
 * @returns A brand new instance with all the supplied objects deeply merged.
 */
function pureDeepObjectAssign(base) {
  var _context;
  for (var _len = arguments.length, updates = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    updates[_key - 1] = arguments[_key];
  }
  return deepObjectAssign.apply(void 0, _concatInstanceProperty$1(_context = [{}, base]).call(_context, updates));
}
/**
 * Deep version of object assign with additional deleting by the DELETE symbol.
 *
 * @param values - Objects to be deeply merged.
 * @returns The first object from values.
 */
function deepObjectAssign() {
  var merged = deepObjectAssignNonentry.apply(void 0, arguments);
  stripDelete(merged);
  return merged;
}
/**
 * Deep version of object assign with additional deleting by the DELETE symbol.
 *
 * @remarks
 * This doesn't strip the DELETE symbols so they may end up in the final object.
 * @param values - Objects to be deeply merged.
 * @returns The first object from values.
 */
function deepObjectAssignNonentry() {
  for (var _len2 = arguments.length, values = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
    values[_key2] = arguments[_key2];
  }
  if (values.length < 2) {
    return values[0];
  } else if (values.length > 2) {
    var _context2;
    return deepObjectAssignNonentry.apply(void 0, _concatInstanceProperty$1(_context2 = [deepObjectAssign(values[0], values[1])]).call(_context2, _toConsumableArray$1(_sliceInstanceProperty$2(values).call(values, 2))));
  }
  var a = values[0];
  var b = values[1];
  var _iterator = _createForOfIteratorHelper$3$1(_Reflect$ownKeys(b)),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var prop = _step.value;
      if (!Object.prototype.propertyIsEnumerable.call(b, prop)) ;else if (b[prop] === DELETE) {
        delete a[prop];
      } else if (a[prop] !== null && b[prop] !== null && _typeof$1(a[prop]) === "object" && _typeof$1(b[prop]) === "object" && !_Array$isArray$2(a[prop]) && !_Array$isArray$2(b[prop])) {
        a[prop] = deepObjectAssignNonentry(a[prop], b[prop]);
      } else {
        a[prop] = clone$3(b[prop]);
      }
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return a;
}
/**
 * Deep clone given object or array. In case of primitive simply return.
 *
 * @param a - Anything.
 * @returns Deep cloned object/array or unchanged a.
 */
function clone$3(a) {
  if (_Array$isArray$2(a)) {
    return _mapInstanceProperty$1(a).call(a, function (value) {
      return clone$3(value);
    });
  } else if (_typeof$1(a) === "object" && a !== null) {
    return deepObjectAssignNonentry({}, a);
  } else {
    return a;
  }
}
/**
 * Strip DELETE from given object.
 *
 * @param a - Object which may contain DELETE but won't after this is executed.
 */
function stripDelete(a) {
  for (var _i = 0, _Object$keys$1$1 = _Object$keys$1(a); _i < _Object$keys$1$1.length; _i++) {
    var prop = _Object$keys$1$1[_i];
    if (a[prop] === DELETE) {
      delete a[prop];
    } else if (_typeof$1(a[prop]) === "object" && a[prop] !== null) {
      stripDelete(a[prop]);
    }
  }
}

/**
 * Setup a mock hammer.js object, for unit testing.
 *
 * Inspiration: https://github.com/uber/deck.gl/pull/658
 *
 * @returns {{on: noop, off: noop, destroy: noop, emit: noop, get: get}}
 */
function hammerMock$1() {
  var noop = function noop() {};
  return {
    on: noop,
    off: noop,
    destroy: noop,
    emit: noop,
    get: function get() {
      return {
        set: noop
      };
    }
  };
}
var Hammer$1$1 = typeof window !== "undefined" ? window.Hammer || RealHammer$1 : function () {
  // hammer.js is only available in a browser, not in node.js. Replacing it with a mock object.
  return hammerMock$1();
};

/**
 * Turn an element into an clickToUse element.
 * When not active, the element has a transparent overlay. When the overlay is
 * clicked, the mode is changed to active.
 * When active, the element is displayed with a blue border around it, and
 * the interactive contents of the element can be used. When clicked outside
 * the element, the elements mode is changed to inactive.
 *
 * @param {Element} container
 * @class Activator
 */
function Activator$1$1(container) {
  var _this = this,
    _context3;
  this._cleanupQueue = [];
  this.active = false;
  this._dom = {
    container: container,
    overlay: document.createElement("div")
  };
  this._dom.overlay.classList.add("vis-overlay");
  this._dom.container.appendChild(this._dom.overlay);
  this._cleanupQueue.push(function () {
    _this._dom.overlay.parentNode.removeChild(_this._dom.overlay);
  });
  var hammer = Hammer$1$1(this._dom.overlay);
  hammer.on("tap", _bindInstanceProperty$1$1(_context3 = this._onTapOverlay).call(_context3, this));
  this._cleanupQueue.push(function () {
    hammer.destroy();
    // FIXME: cleaning up hammer instances doesn't work (Timeline not removed
    // from memory)
  });

  // block all touch events (except tap)
  var events = ["tap", "doubletap", "press", "pinch", "pan", "panstart", "panmove", "panend"];
  _forEachInstanceProperty$1(events).call(events, function (event) {
    hammer.on(event, function (event) {
      event.srcEvent.stopPropagation();
    });
  });

  // attach a click event to the window, in order to deactivate when clicking outside the timeline
  if (document && document.body) {
    this._onClick = function (event) {
      if (!_hasParent$1(event.target, container)) {
        _this.deactivate();
      }
    };
    document.body.addEventListener("click", this._onClick);
    this._cleanupQueue.push(function () {
      document.body.removeEventListener("click", _this._onClick);
    });
  }

  // prepare escape key listener for deactivating when active
  this._escListener = function (event) {
    if ("key" in event ? event.key === "Escape" : event.keyCode === 27 /* the keyCode is for IE11 */) {
      _this.deactivate();
    }
  };
}

// turn into an event emitter
Emitter$1(Activator$1$1.prototype);

// The currently active activator
Activator$1$1.current = null;

/**
 * Destroy the activator. Cleans up all created DOM and event listeners
 */
Activator$1$1.prototype.destroy = function () {
  var _context4, _context5;
  this.deactivate();
  var _iterator2 = _createForOfIteratorHelper$3$1(_reverseInstanceProperty$1(_context4 = _spliceInstanceProperty$1(_context5 = this._cleanupQueue).call(_context5, 0)).call(_context4)),
    _step2;
  try {
    for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
      var callback = _step2.value;
      callback();
    }
  } catch (err) {
    _iterator2.e(err);
  } finally {
    _iterator2.f();
  }
};

/**
 * Activate the element
 * Overlay is hidden, element is decorated with a blue shadow border
 */
Activator$1$1.prototype.activate = function () {
  // we allow only one active activator at a time
  if (Activator$1$1.current) {
    Activator$1$1.current.deactivate();
  }
  Activator$1$1.current = this;
  this.active = true;
  this._dom.overlay.style.display = "none";
  this._dom.container.classList.add("vis-active");
  this.emit("change");
  this.emit("activate");

  // ugly hack: bind ESC after emitting the events, as the Network rebinds all
  // keyboard events on a 'change' event
  document.body.addEventListener("keydown", this._escListener);
};

/**
 * Deactivate the element
 * Overlay is displayed on top of the element
 */
Activator$1$1.prototype.deactivate = function () {
  this.active = false;
  this._dom.overlay.style.display = "block";
  this._dom.container.classList.remove("vis-active");
  document.body.removeEventListener("keydown", this._escListener);
  this.emit("change");
  this.emit("deactivate");
};

/**
 * Handle a tap event: activate the container
 *
 * @param {Event}  event   The event
 * @private
 */
Activator$1$1.prototype._onTapOverlay = function (event) {
  // activate the container
  this.activate();
  event.srcEvent.stopPropagation();
};

/**
 * Test whether the element has the requested parent element somewhere in
 * its chain of parent nodes.
 *
 * @param {HTMLElement} element
 * @param {HTMLElement} parent
 * @returns {boolean} Returns true when the parent is found somewhere in the
 *                    chain of parent nodes.
 * @private
 */
function _hasParent$1(element, parent) {
  while (element) {
    if (element === parent) {
      return true;
    }
    element = element.parentNode;
  }
  return false;
}

var isConstructor$5 = isConstructor$4$1;
var tryToString$1$1 = tryToString$6$1;

var $TypeError$3$1 = TypeError;

// `Assert: IsConstructor(argument) is true`
var aConstructor$2 = function (argument) {
  if (isConstructor$5(argument)) return argument;
  throw $TypeError$3$1(tryToString$1$1(argument) + ' is not a constructor');
};

var $$g$1 = _export$1;
var getBuiltIn$4$1 = getBuiltIn$f;
var apply$1$1 = functionApply$1;
var bind$9$1 = functionBind$1;
var aConstructor$1$1 = aConstructor$2;
var anObject$3$1 = anObject$d$1;
var isObject$6$1 = isObject$h$1;
var create$6$1 = objectCreate$1;
var fails$8$1 = fails$t$1;

var nativeConstruct$1 = getBuiltIn$4$1('Reflect', 'construct');
var ObjectPrototype$3 = Object.prototype;
var push$2$1 = [].push;

// `Reflect.construct` method
// https://tc39.es/ecma262/#sec-reflect.construct
// MS Edge supports only 2 arguments and argumentsList argument is optional
// FF Nightly sets third argument as `new.target`, but does not create `this` from it
var NEW_TARGET_BUG$1 = fails$8$1(function () {
  function F() { /* empty */ }
  return !(nativeConstruct$1(function () { /* empty */ }, [], F) instanceof F);
});

var ARGS_BUG$1 = !fails$8$1(function () {
  nativeConstruct$1(function () { /* empty */ });
});

var FORCED$1$1 = NEW_TARGET_BUG$1 || ARGS_BUG$1;

$$g$1({ target: 'Reflect', stat: true, forced: FORCED$1$1, sham: FORCED$1$1 }, {
  construct: function construct(Target, args /* , newTarget */) {
    aConstructor$1$1(Target);
    anObject$3$1(args);
    var newTarget = arguments.length < 3 ? Target : aConstructor$1$1(arguments[2]);
    if (ARGS_BUG$1 && !NEW_TARGET_BUG$1) return nativeConstruct$1(Target, args, newTarget);
    if (Target == newTarget) {
      // w/o altered newTarget, optimization for 0-4 arguments
      switch (args.length) {
        case 0: return new Target();
        case 1: return new Target(args[0]);
        case 2: return new Target(args[0], args[1]);
        case 3: return new Target(args[0], args[1], args[2]);
        case 4: return new Target(args[0], args[1], args[2], args[3]);
      }
      // w/o altered newTarget, lot of arguments case
      var $args = [null];
      apply$1$1(push$2$1, $args, args);
      return new (apply$1$1(bind$9$1, Target, $args))();
    }
    // with altered newTarget, not support built-in constructors
    var proto = newTarget.prototype;
    var instance = create$6$1(isObject$6$1(proto) ? proto : ObjectPrototype$3);
    var result = apply$1$1(Target, instance, args);
    return isObject$6$1(result) ? result : instance;
  }
});

var path$4$1 = path$o$1;

var construct$2$1 = path$4$1.Reflect.construct;

var parent$q$1 = construct$2$1;

var construct$1$1 = parent$q$1;

var construct$5 = construct$1$1;

var _Reflect$construct$1 = /*@__PURE__*/getDefaultExportFromCjs$2(construct$5);

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

var parent$p$1 = create$8$1;

var create$5$1 = parent$p$1;

var parent$o$1 = create$5$1;

var create$4$1 = parent$o$1;

var create$3$1 = create$4$1;

var create$2$1 = create$3$1;

var _Object$create$2 = /*@__PURE__*/getDefaultExportFromCjs$2(create$2$1);

var $$f$1 = _export$1;
var setPrototypeOf$7 = objectSetPrototypeOf$1;

// `Object.setPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.setprototypeof
$$f$1({ target: 'Object', stat: true }, {
  setPrototypeOf: setPrototypeOf$7
});

var path$3$1 = path$o$1;

var setPrototypeOf$6$1 = path$3$1.Object.setPrototypeOf;

var parent$n$1 = setPrototypeOf$6$1;

var setPrototypeOf$5$1 = parent$n$1;

var parent$m$1 = setPrototypeOf$5$1;

var setPrototypeOf$4$1 = parent$m$1;

var parent$l$1 = setPrototypeOf$4$1;

var setPrototypeOf$3$1 = parent$l$1;

var setPrototypeOf$2$1 = setPrototypeOf$3$1;

var setPrototypeOf$1$1 = setPrototypeOf$2$1;

var _Object$setPrototypeOf$1 = /*@__PURE__*/getDefaultExportFromCjs$2(setPrototypeOf$1$1);

var parent$k$1 = bind$d$1;

var bind$8$1 = parent$k$1;

var parent$j$1 = bind$8$1;

var bind$7$1 = parent$j$1;

var bind$6$1 = bind$7$1;

var bind$5$1 = bind$6$1;

var _bindInstanceProperty$2 = /*@__PURE__*/getDefaultExportFromCjs$2(bind$5$1);

function _setPrototypeOf$1(o, p) {
  var _context;
  _setPrototypeOf$1 = _Object$setPrototypeOf$1 ? _bindInstanceProperty$2(_context = _Object$setPrototypeOf$1).call(_context) : function _setPrototypeOf(o, p) {
    o.__proto__ = p;
    return o;
  };
  return _setPrototypeOf$1(o, p);
}

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

function _possibleConstructorReturn$1(self, call) {
  if (call && (_typeof$1(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$2(self);
}

var parent$i$1 = getPrototypeOf$5$1;

var getPrototypeOf$4$1 = parent$i$1;

var parent$h$1 = getPrototypeOf$4$1;

var getPrototypeOf$3$1 = parent$h$1;

var getPrototypeOf$2$1 = getPrototypeOf$3$1;

var getPrototypeOf$1$1 = getPrototypeOf$2$1;

var _Object$getPrototypeOf$2 = /*@__PURE__*/getDefaultExportFromCjs$2(getPrototypeOf$1$1);

function _getPrototypeOf$1(o) {
  var _context;
  _getPrototypeOf$1 = _Object$setPrototypeOf$1 ? _bindInstanceProperty$2(_context = _Object$getPrototypeOf$2).call(_context) : function _getPrototypeOf(o) {
    return o.__proto__ || _Object$getPrototypeOf$2(o);
  };
  return _getPrototypeOf$1(o);
}

var regeneratorRuntime$1 = {exports: {}};

var _typeof$2 = {exports: {}};

(function (module) {
	var _Symbol = symbol$1$1;
	var _Symbol$iterator = iterator$1$1;
	function _typeof(obj) {
	  "@babel/helpers - typeof";

	  return (module.exports = _typeof = "function" == typeof _Symbol && "symbol" == typeof _Symbol$iterator ? function (obj) {
	    return typeof obj;
	  } : function (obj) {
	    return obj && "function" == typeof _Symbol && obj.constructor === _Symbol && obj !== _Symbol.prototype ? "symbol" : typeof obj;
	  }, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(obj);
	}
	module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports; 
} (_typeof$2));

var _typeofExports = _typeof$2.exports;

var parent$g$1 = forEach$6$1;

var forEach$4$1 = parent$g$1;

var parent$f$1 = forEach$4$1;

var forEach$3$1 = parent$f$1;

var forEach$2$1 = forEach$3$1;

var forEach$1$1 = forEach$2$1;

var hasOwn$5$1 = hasOwnProperty_1$1;
var ownKeys$1$1 = ownKeys$7$1;
var getOwnPropertyDescriptorModule$3 = objectGetOwnPropertyDescriptor$1;
var definePropertyModule$5 = objectDefineProperty$1;

var copyConstructorProperties$1 = function (target, source, exceptions) {
  var keys = ownKeys$1$1(source);
  var defineProperty = definePropertyModule$5.f;
  var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$3.f;
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    if (!hasOwn$5$1(target, key) && !(exceptions && hasOwn$5$1(exceptions, key))) {
      defineProperty(target, key, getOwnPropertyDescriptor(source, key));
    }
  }
};

var isObject$5$1 = isObject$h$1;
var createNonEnumerableProperty$3$1 = createNonEnumerableProperty$9;

// `InstallErrorCause` abstract operation
// https://tc39.es/proposal-error-cause/#sec-errorobjects-install-error-cause
var installErrorCause$1 = function (O, options) {
  if (isObject$5$1(options) && 'cause' in options) {
    createNonEnumerableProperty$3$1(O, 'cause', options.cause);
  }
};

var uncurryThis$2$1 = functionUncurryThis$1;

var $Error$1 = Error;
var replace$2 = uncurryThis$2$1(''.replace);

var TEST = (function (arg) { return String($Error$1(arg).stack); })('zxcasd');
// eslint-disable-next-line redos/no-vulnerable -- safe
var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/;
var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);

var errorStackClear = function (stack, dropEntries) {
  if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error$1.prepareStackTrace) {
    while (dropEntries--) stack = replace$2(stack, V8_OR_CHAKRA_STACK_ENTRY, '');
  } return stack;
};

var fails$7$1 = fails$t$1;
var createPropertyDescriptor$1$1 = createPropertyDescriptor$7;

var errorStackInstallable = !fails$7$1(function () {
  var error = Error('a');
  if (!('stack' in error)) return true;
  // eslint-disable-next-line es/no-object-defineproperty -- safe
  Object.defineProperty(error, 'stack', createPropertyDescriptor$1$1(1, 7));
  return error.stack !== 7;
});

var createNonEnumerableProperty$2$1 = createNonEnumerableProperty$9;
var clearErrorStack = errorStackClear;
var ERROR_STACK_INSTALLABLE = errorStackInstallable;

// non-standard V8
var captureStackTrace = Error.captureStackTrace;

var errorStackInstall = function (error, C, stack, dropEntries) {
  if (ERROR_STACK_INSTALLABLE) {
    if (captureStackTrace) captureStackTrace(error, C);
    else createNonEnumerableProperty$2$1(error, 'stack', clearErrorStack(stack, dropEntries));
  }
};

var bind$4$1 = functionBindContext$1;
var call$6$1 = functionCall$1;
var anObject$2$1 = anObject$d$1;
var tryToString$7 = tryToString$6$1;
var isArrayIteratorMethod$3 = isArrayIteratorMethod$2$1;
var lengthOfArrayLike$1$1 = lengthOfArrayLike$c;
var isPrototypeOf$7$1 = objectIsPrototypeOf$1;
var getIterator$6 = getIterator$8;
var getIteratorMethod$a = getIteratorMethod$9$1;
var iteratorClose$3 = iteratorClose$2$1;

var $TypeError$2$1 = TypeError;

var Result$1 = function (stopped, result) {
  this.stopped = stopped;
  this.result = result;
};

var ResultPrototype$1 = Result$1.prototype;

var iterate$7 = function (iterable, unboundFunction, options) {
  var that = options && options.that;
  var AS_ENTRIES = !!(options && options.AS_ENTRIES);
  var IS_RECORD = !!(options && options.IS_RECORD);
  var IS_ITERATOR = !!(options && options.IS_ITERATOR);
  var INTERRUPTED = !!(options && options.INTERRUPTED);
  var fn = bind$4$1(unboundFunction, that);
  var iterator, iterFn, index, length, result, next, step;

  var stop = function (condition) {
    if (iterator) iteratorClose$3(iterator, 'normal', condition);
    return new Result$1(true, condition);
  };

  var callFn = function (value) {
    if (AS_ENTRIES) {
      anObject$2$1(value);
      return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
    } return INTERRUPTED ? fn(value, stop) : fn(value);
  };

  if (IS_RECORD) {
    iterator = iterable.iterator;
  } else if (IS_ITERATOR) {
    iterator = iterable;
  } else {
    iterFn = getIteratorMethod$a(iterable);
    if (!iterFn) throw $TypeError$2$1(tryToString$7(iterable) + ' is not iterable');
    // optimisation for array iterators
    if (isArrayIteratorMethod$3(iterFn)) {
      for (index = 0, length = lengthOfArrayLike$1$1(iterable); length > index; index++) {
        result = callFn(iterable[index]);
        if (result && isPrototypeOf$7$1(ResultPrototype$1, result)) return result;
      } return new Result$1(false);
    }
    iterator = getIterator$6(iterable, iterFn);
  }

  next = IS_RECORD ? iterable.next : iterator.next;
  while (!(step = call$6$1(next, iterator)).done) {
    try {
      result = callFn(step.value);
    } catch (error) {
      iteratorClose$3(iterator, 'throw', error);
    }
    if (typeof result == 'object' && result && isPrototypeOf$7$1(ResultPrototype$1, result)) return result;
  } return new Result$1(false);
};

var toString$1$1 = toString$7$1;

var normalizeStringArgument$1 = function (argument, $default) {
  return argument === undefined ? arguments.length < 2 ? '' : $default : toString$1$1(argument);
};

var $$e$1 = _export$1;
var isPrototypeOf$6$1 = objectIsPrototypeOf$1;
var getPrototypeOf$a = objectGetPrototypeOf$1;
var setPrototypeOf$8 = objectSetPrototypeOf$1;
var copyConstructorProperties = copyConstructorProperties$1;
var create$1$2 = objectCreate$1;
var createNonEnumerableProperty$1$1 = createNonEnumerableProperty$9;
var createPropertyDescriptor$8 = createPropertyDescriptor$7;
var installErrorCause = installErrorCause$1;
var installErrorStack = errorStackInstall;
var iterate$6 = iterate$7;
var normalizeStringArgument = normalizeStringArgument$1;
var wellKnownSymbol$3$1 = wellKnownSymbol$m;

var TO_STRING_TAG$5 = wellKnownSymbol$3$1('toStringTag');
var $Error = Error;
var push$1$1 = [].push;

var $AggregateError = function AggregateError(errors, message /* , options */) {
  var isInstance = isPrototypeOf$6$1(AggregateErrorPrototype, this);
  var that;
  if (setPrototypeOf$8) {
    that = setPrototypeOf$8($Error(), isInstance ? getPrototypeOf$a(this) : AggregateErrorPrototype);
  } else {
    that = isInstance ? this : create$1$2(AggregateErrorPrototype);
    createNonEnumerableProperty$1$1(that, TO_STRING_TAG$5, 'Error');
  }
  if (message !== undefined) createNonEnumerableProperty$1$1(that, 'message', normalizeStringArgument(message));
  installErrorStack(that, $AggregateError, that.stack, 1);
  if (arguments.length > 2) installErrorCause(that, arguments[2]);
  var errorsArray = [];
  iterate$6(errors, push$1$1, { that: errorsArray });
  createNonEnumerableProperty$1$1(that, 'errors', errorsArray);
  return that;
};

if (setPrototypeOf$8) setPrototypeOf$8($AggregateError, $Error);
else copyConstructorProperties($AggregateError, $Error, { name: true });

var AggregateErrorPrototype = $AggregateError.prototype = create$1$2($Error.prototype, {
  constructor: createPropertyDescriptor$8(1, $AggregateError),
  message: createPropertyDescriptor$8(1, ''),
  name: createPropertyDescriptor$8(1, 'AggregateError')
});

// `AggregateError` constructor
// https://tc39.es/ecma262/#sec-aggregate-error-constructor
$$e$1({ global: true, constructor: true, arity: 2 }, {
  AggregateError: $AggregateError
});

var getBuiltIn$3$1 = getBuiltIn$f;
var defineBuiltInAccessor$1$1 = defineBuiltInAccessor$3$1;
var wellKnownSymbol$2$1 = wellKnownSymbol$m;
var DESCRIPTORS$2$1 = descriptors$1;

var SPECIES$2$1 = wellKnownSymbol$2$1('species');

var setSpecies$2 = function (CONSTRUCTOR_NAME) {
  var Constructor = getBuiltIn$3$1(CONSTRUCTOR_NAME);

  if (DESCRIPTORS$2$1 && Constructor && !Constructor[SPECIES$2$1]) {
    defineBuiltInAccessor$1$1(Constructor, SPECIES$2$1, {
      configurable: true,
      get: function () { return this; }
    });
  }
};

var isPrototypeOf$5$1 = objectIsPrototypeOf$1;

var $TypeError$1$1 = TypeError;

var anInstance$3$1 = function (it, Prototype) {
  if (isPrototypeOf$5$1(Prototype, it)) return it;
  throw $TypeError$1$1('Incorrect invocation');
};

var anObject$1$1 = anObject$d$1;
var aConstructor$3 = aConstructor$2;
var isNullOrUndefined$1$1 = isNullOrUndefined$5$1;
var wellKnownSymbol$1$1 = wellKnownSymbol$m;

var SPECIES$1$1 = wellKnownSymbol$1$1('species');

// `SpeciesConstructor` abstract operation
// https://tc39.es/ecma262/#sec-speciesconstructor
var speciesConstructor$2 = function (O, defaultConstructor) {
  var C = anObject$1$1(O).constructor;
  var S;
  return C === undefined || isNullOrUndefined$1$1(S = anObject$1$1(C)[SPECIES$1$1]) ? defaultConstructor : aConstructor$3(S);
};

var userAgent$4 = engineUserAgent$1;

// eslint-disable-next-line redos/no-vulnerable -- safe
var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent$4);

var global$6$1 = global$m;
var apply$7 = functionApply$1;
var bind$3$1 = functionBindContext$1;
var isCallable$4$1 = isCallable$m;
var hasOwn$4$1 = hasOwnProperty_1$1;
var fails$6$1 = fails$t$1;
var html$3 = html$2;
var arraySlice$1$1 = arraySlice$5$1;
var createElement$2 = documentCreateElement$1$1;
var validateArgumentsLength$3 = validateArgumentsLength$2;
var IS_IOS$1 = engineIsIos;
var IS_NODE$3 = engineIsNode$1;

var set$3$1 = global$6$1.setImmediate;
var clear$1 = global$6$1.clearImmediate;
var process$3 = global$6$1.process;
var Dispatch = global$6$1.Dispatch;
var Function$1$1 = global$6$1.Function;
var MessageChannel$1 = global$6$1.MessageChannel;
var String$1 = global$6$1.String;
var counter = 0;
var queue$2 = {};
var ONREADYSTATECHANGE = 'onreadystatechange';
var $location, defer, channel, port;

fails$6$1(function () {
  // Deno throws a ReferenceError on `location` access without `--location` flag
  $location = global$6$1.location;
});

var run = function (id) {
  if (hasOwn$4$1(queue$2, id)) {
    var fn = queue$2[id];
    delete queue$2[id];
    fn();
  }
};

var runner = function (id) {
  return function () {
    run(id);
  };
};

var eventListener = function (event) {
  run(event.data);
};

var globalPostMessageDefer = function (id) {
  // old engines have not location.origin
  global$6$1.postMessage(String$1(id), $location.protocol + '//' + $location.host);
};

// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
if (!set$3$1 || !clear$1) {
  set$3$1 = function setImmediate(handler) {
    validateArgumentsLength$3(arguments.length, 1);
    var fn = isCallable$4$1(handler) ? handler : Function$1$1(handler);
    var args = arraySlice$1$1(arguments, 1);
    queue$2[++counter] = function () {
      apply$7(fn, undefined, args);
    };
    defer(counter);
    return counter;
  };
  clear$1 = function clearImmediate(id) {
    delete queue$2[id];
  };
  // Node.js 0.8-
  if (IS_NODE$3) {
    defer = function (id) {
      process$3.nextTick(runner(id));
    };
  // Sphere (JS game engine) Dispatch API
  } else if (Dispatch && Dispatch.now) {
    defer = function (id) {
      Dispatch.now(runner(id));
    };
  // Browsers with MessageChannel, includes WebWorkers
  // except iOS - https://github.com/zloirock/core-js/issues/624
  } else if (MessageChannel$1 && !IS_IOS$1) {
    channel = new MessageChannel$1();
    port = channel.port2;
    channel.port1.onmessage = eventListener;
    defer = bind$3$1(port.postMessage, port);
  // Browsers with postMessage, skip WebWorkers
  // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
  } else if (
    global$6$1.addEventListener &&
    isCallable$4$1(global$6$1.postMessage) &&
    !global$6$1.importScripts &&
    $location && $location.protocol !== 'file:' &&
    !fails$6$1(globalPostMessageDefer)
  ) {
    defer = globalPostMessageDefer;
    global$6$1.addEventListener('message', eventListener, false);
  // IE8-
  } else if (ONREADYSTATECHANGE in createElement$2('script')) {
    defer = function (id) {
      html$3.appendChild(createElement$2('script'))[ONREADYSTATECHANGE] = function () {
        html$3.removeChild(this);
        run(id);
      };
    };
  // Rest old browsers
  } else {
    defer = function (id) {
      setTimeout(runner(id), 0);
    };
  }
}

var task$1 = {
  set: set$3$1,
  clear: clear$1
};

var Queue$3 = function () {
  this.head = null;
  this.tail = null;
};

Queue$3.prototype = {
  add: function (item) {
    var entry = { item: item, next: null };
    var tail = this.tail;
    if (tail) tail.next = entry;
    else this.head = entry;
    this.tail = entry;
  },
  get: function () {
    var entry = this.head;
    if (entry) {
      var next = this.head = entry.next;
      if (next === null) this.tail = null;
      return entry.item;
    }
  }
};

var queue$1 = Queue$3;

var userAgent$3 = engineUserAgent$1;

var engineIsIosPebble = /ipad|iphone|ipod/i.test(userAgent$3) && typeof Pebble != 'undefined';

var userAgent$2$1 = engineUserAgent$1;

var engineIsWebosWebkit = /web0s(?!.*chrome)/i.test(userAgent$2$1);

var global$5$1 = global$m;
var bind$2$1 = functionBindContext$1;
var getOwnPropertyDescriptor$b = objectGetOwnPropertyDescriptor$1.f;
var macrotask = task$1.set;
var Queue$2 = queue$1;
var IS_IOS = engineIsIos;
var IS_IOS_PEBBLE = engineIsIosPebble;
var IS_WEBOS_WEBKIT = engineIsWebosWebkit;
var IS_NODE$2 = engineIsNode$1;

var MutationObserver$1 = global$5$1.MutationObserver || global$5$1.WebKitMutationObserver;
var document$2 = global$5$1.document;
var process$2 = global$5$1.process;
var Promise$1 = global$5$1.Promise;
// Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
var queueMicrotaskDescriptor = getOwnPropertyDescriptor$b(global$5$1, 'queueMicrotask');
var microtask$1 = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
var notify$1, toggle, node, promise$6, then;

// modern engines have queueMicrotask method
if (!microtask$1) {
  var queue = new Queue$2();

  var flush = function () {
    var parent, fn;
    if (IS_NODE$2 && (parent = process$2.domain)) parent.exit();
    while (fn = queue.get()) try {
      fn();
    } catch (error) {
      if (queue.head) notify$1();
      throw error;
    }
    if (parent) parent.enter();
  };

  // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
  // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898
  if (!IS_IOS && !IS_NODE$2 && !IS_WEBOS_WEBKIT && MutationObserver$1 && document$2) {
    toggle = true;
    node = document$2.createTextNode('');
    new MutationObserver$1(flush).observe(node, { characterData: true });
    notify$1 = function () {
      node.data = toggle = !toggle;
    };
  // environments with maybe non-completely correct, but existent Promise
  } else if (!IS_IOS_PEBBLE && Promise$1 && Promise$1.resolve) {
    // Promise.resolve without an argument throws an error in LG WebOS 2
    promise$6 = Promise$1.resolve(undefined);
    // workaround of WebKit ~ iOS Safari 10.1 bug
    promise$6.constructor = Promise$1;
    then = bind$2$1(promise$6.then, promise$6);
    notify$1 = function () {
      then(flush);
    };
  // Node.js without promises
  } else if (IS_NODE$2) {
    notify$1 = function () {
      process$2.nextTick(flush);
    };
  // for other environments - macrotask based on:
  // - setImmediate
  // - MessageChannel
  // - window.postMessage
  // - onreadystatechange
  // - setTimeout
  } else {
    // `webpack` dev server bug on IE global methods - use bind(fn, global)
    macrotask = bind$2$1(macrotask, global$5$1);
    notify$1 = function () {
      macrotask(flush);
    };
  }

  microtask$1 = function (fn) {
    if (!queue.head) notify$1();
    queue.add(fn);
  };
}

var microtask_1 = microtask$1;

var hostReportErrors$1 = function (a, b) {
  try {
    // eslint-disable-next-line no-console -- safe
    arguments.length == 1 ? console.error(a) : console.error(a, b);
  } catch (error) { /* empty */ }
};

var perform$6 = function (exec) {
  try {
    return { error: false, value: exec() };
  } catch (error) {
    return { error: true, value: error };
  }
};

var global$4$1 = global$m;

var promiseNativeConstructor = global$4$1.Promise;

/* global Deno -- Deno case */

var engineIsDeno = typeof Deno == 'object' && Deno && typeof Deno.version == 'object';

var IS_DENO$1 = engineIsDeno;
var IS_NODE$1 = engineIsNode$1;

var engineIsBrowser = !IS_DENO$1 && !IS_NODE$1
  && typeof window == 'object'
  && typeof document == 'object';

var global$3$1 = global$m;
var NativePromiseConstructor$5 = promiseNativeConstructor;
var isCallable$3$1 = isCallable$m;
var isForced$3 = isForced_1$1;
var inspectSource$3 = inspectSource$2;
var wellKnownSymbol$n = wellKnownSymbol$m;
var IS_BROWSER = engineIsBrowser;
var IS_DENO = engineIsDeno;
var V8_VERSION$4 = engineV8Version$1;

var NativePromisePrototype$2 = NativePromiseConstructor$5 && NativePromiseConstructor$5.prototype;
var SPECIES$6 = wellKnownSymbol$n('species');
var SUBCLASSING = false;
var NATIVE_PROMISE_REJECTION_EVENT$1 = isCallable$3$1(global$3$1.PromiseRejectionEvent);

var FORCED_PROMISE_CONSTRUCTOR$5 = isForced$3('Promise', function () {
  var PROMISE_CONSTRUCTOR_SOURCE = inspectSource$3(NativePromiseConstructor$5);
  var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(NativePromiseConstructor$5);
  // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
  // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
  // We can't detect it synchronously, so just check versions
  if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION$4 === 66) return true;
  // We need Promise#{ catch, finally } in the pure version for preventing prototype pollution
  if (!(NativePromisePrototype$2['catch'] && NativePromisePrototype$2['finally'])) return true;
  // We can't use @@species feature detection in V8 since it causes
  // deoptimization and performance degradation
  // https://github.com/zloirock/core-js/issues/679
  if (!V8_VERSION$4 || V8_VERSION$4 < 51 || !/native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) {
    // Detect correctness of subclassing with @@species support
    var promise = new NativePromiseConstructor$5(function (resolve) { resolve(1); });
    var FakePromise = function (exec) {
      exec(function () { /* empty */ }, function () { /* empty */ });
    };
    var constructor = promise.constructor = {};
    constructor[SPECIES$6] = FakePromise;
    SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise;
    if (!SUBCLASSING) return true;
  // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
  } return !GLOBAL_CORE_JS_PROMISE && (IS_BROWSER || IS_DENO) && !NATIVE_PROMISE_REJECTION_EVENT$1;
});

var promiseConstructorDetection = {
  CONSTRUCTOR: FORCED_PROMISE_CONSTRUCTOR$5,
  REJECTION_EVENT: NATIVE_PROMISE_REJECTION_EVENT$1,
  SUBCLASSING: SUBCLASSING
};

var newPromiseCapability$2 = {};

var aCallable$6$1 = aCallable$e;

var $TypeError$h = TypeError;

var PromiseCapability = function (C) {
  var resolve, reject;
  this.promise = new C(function ($$resolve, $$reject) {
    if (resolve !== undefined || reject !== undefined) throw $TypeError$h('Bad Promise constructor');
    resolve = $$resolve;
    reject = $$reject;
  });
  this.resolve = aCallable$6$1(resolve);
  this.reject = aCallable$6$1(reject);
};

// `NewPromiseCapability` abstract operation
// https://tc39.es/ecma262/#sec-newpromisecapability
newPromiseCapability$2.f = function (C) {
  return new PromiseCapability(C);
};

var $$d$1 = _export$1;
var IS_NODE$5 = engineIsNode$1;
var global$2$1 = global$m;
var call$5$1 = functionCall$1;
var defineBuiltIn$1$1 = defineBuiltIn$6;
var setToStringTag$1$1 = setToStringTag$7;
var setSpecies$1$1 = setSpecies$2;
var aCallable$5$1 = aCallable$e;
var isCallable$2$1 = isCallable$m;
var isObject$4$1 = isObject$h$1;
var anInstance$2$1 = anInstance$3$1;
var speciesConstructor$1 = speciesConstructor$2;
var task = task$1.set;
var microtask = microtask_1;
var hostReportErrors = hostReportErrors$1;
var perform$5 = perform$6;
var Queue$1 = queue$1;
var InternalStateModule$2$1 = internalState$1;
var NativePromiseConstructor$4 = promiseNativeConstructor;
var PromiseConstructorDetection = promiseConstructorDetection;
var newPromiseCapabilityModule$6 = newPromiseCapability$2;

var PROMISE = 'Promise';
var FORCED_PROMISE_CONSTRUCTOR$4 = PromiseConstructorDetection.CONSTRUCTOR;
var NATIVE_PROMISE_REJECTION_EVENT = PromiseConstructorDetection.REJECTION_EVENT;
var getInternalPromiseState = InternalStateModule$2$1.getterFor(PROMISE);
var setInternalState$2$1 = InternalStateModule$2$1.set;
var NativePromisePrototype$1 = NativePromiseConstructor$4 && NativePromiseConstructor$4.prototype;
var PromiseConstructor = NativePromiseConstructor$4;
var PromisePrototype = NativePromisePrototype$1;
var TypeError$1$1 = global$2$1.TypeError;
var document$1$1 = global$2$1.document;
var process$1$1 = global$2$1.process;
var newPromiseCapability$1 = newPromiseCapabilityModule$6.f;
var newGenericPromiseCapability = newPromiseCapability$1;

var DISPATCH_EVENT = !!(document$1$1 && document$1$1.createEvent && global$2$1.dispatchEvent);
var UNHANDLED_REJECTION = 'unhandledrejection';
var REJECTION_HANDLED = 'rejectionhandled';
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
var HANDLED = 1;
var UNHANDLED = 2;

var Internal, OwnPromiseCapability, PromiseWrapper;

// helpers
var isThenable = function (it) {
  var then;
  return isObject$4$1(it) && isCallable$2$1(then = it.then) ? then : false;
};

var callReaction = function (reaction, state) {
  var value = state.value;
  var ok = state.state == FULFILLED;
  var handler = ok ? reaction.ok : reaction.fail;
  var resolve = reaction.resolve;
  var reject = reaction.reject;
  var domain = reaction.domain;
  var result, then, exited;
  try {
    if (handler) {
      if (!ok) {
        if (state.rejection === UNHANDLED) onHandleUnhandled(state);
        state.rejection = HANDLED;
      }
      if (handler === true) result = value;
      else {
        if (domain) domain.enter();
        result = handler(value); // can throw
        if (domain) {
          domain.exit();
          exited = true;
        }
      }
      if (result === reaction.promise) {
        reject(TypeError$1$1('Promise-chain cycle'));
      } else if (then = isThenable(result)) {
        call$5$1(then, result, resolve, reject);
      } else resolve(result);
    } else reject(value);
  } catch (error) {
    if (domain && !exited) domain.exit();
    reject(error);
  }
};

var notify = function (state, isReject) {
  if (state.notified) return;
  state.notified = true;
  microtask(function () {
    var reactions = state.reactions;
    var reaction;
    while (reaction = reactions.get()) {
      callReaction(reaction, state);
    }
    state.notified = false;
    if (isReject && !state.rejection) onUnhandled(state);
  });
};

var dispatchEvent = function (name, promise, reason) {
  var event, handler;
  if (DISPATCH_EVENT) {
    event = document$1$1.createEvent('Event');
    event.promise = promise;
    event.reason = reason;
    event.initEvent(name, false, true);
    global$2$1.dispatchEvent(event);
  } else event = { promise: promise, reason: reason };
  if (!NATIVE_PROMISE_REJECTION_EVENT && (handler = global$2$1['on' + name])) handler(event);
  else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
};

var onUnhandled = function (state) {
  call$5$1(task, global$2$1, function () {
    var promise = state.facade;
    var value = state.value;
    var IS_UNHANDLED = isUnhandled(state);
    var result;
    if (IS_UNHANDLED) {
      result = perform$5(function () {
        if (IS_NODE$5) {
          process$1$1.emit('unhandledRejection', value, promise);
        } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
      });
      // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
      state.rejection = IS_NODE$5 || isUnhandled(state) ? UNHANDLED : HANDLED;
      if (result.error) throw result.value;
    }
  });
};

var isUnhandled = function (state) {
  return state.rejection !== HANDLED && !state.parent;
};

var onHandleUnhandled = function (state) {
  call$5$1(task, global$2$1, function () {
    var promise = state.facade;
    if (IS_NODE$5) {
      process$1$1.emit('rejectionHandled', promise);
    } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
  });
};

var bind$1$2 = function (fn, state, unwrap) {
  return function (value) {
    fn(state, value, unwrap);
  };
};

var internalReject = function (state, value, unwrap) {
  if (state.done) return;
  state.done = true;
  if (unwrap) state = unwrap;
  state.value = value;
  state.state = REJECTED;
  notify(state, true);
};

var internalResolve = function (state, value, unwrap) {
  if (state.done) return;
  state.done = true;
  if (unwrap) state = unwrap;
  try {
    if (state.facade === value) throw TypeError$1$1("Promise can't be resolved itself");
    var then = isThenable(value);
    if (then) {
      microtask(function () {
        var wrapper = { done: false };
        try {
          call$5$1(then, value,
            bind$1$2(internalResolve, wrapper, state),
            bind$1$2(internalReject, wrapper, state)
          );
        } catch (error) {
          internalReject(wrapper, error, state);
        }
      });
    } else {
      state.value = value;
      state.state = FULFILLED;
      notify(state, false);
    }
  } catch (error) {
    internalReject({ done: false }, error, state);
  }
};

// constructor polyfill
if (FORCED_PROMISE_CONSTRUCTOR$4) {
  // 25.4.3.1 Promise(executor)
  PromiseConstructor = function Promise(executor) {
    anInstance$2$1(this, PromisePrototype);
    aCallable$5$1(executor);
    call$5$1(Internal, this);
    var state = getInternalPromiseState(this);
    try {
      executor(bind$1$2(internalResolve, state), bind$1$2(internalReject, state));
    } catch (error) {
      internalReject(state, error);
    }
  };

  PromisePrototype = PromiseConstructor.prototype;

  // eslint-disable-next-line no-unused-vars -- required for `.length`
  Internal = function Promise(executor) {
    setInternalState$2$1(this, {
      type: PROMISE,
      done: false,
      notified: false,
      parent: false,
      reactions: new Queue$1(),
      rejection: false,
      state: PENDING,
      value: undefined
    });
  };

  // `Promise.prototype.then` method
  // https://tc39.es/ecma262/#sec-promise.prototype.then
  Internal.prototype = defineBuiltIn$1$1(PromisePrototype, 'then', function then(onFulfilled, onRejected) {
    var state = getInternalPromiseState(this);
    var reaction = newPromiseCapability$1(speciesConstructor$1(this, PromiseConstructor));
    state.parent = true;
    reaction.ok = isCallable$2$1(onFulfilled) ? onFulfilled : true;
    reaction.fail = isCallable$2$1(onRejected) && onRejected;
    reaction.domain = IS_NODE$5 ? process$1$1.domain : undefined;
    if (state.state == PENDING) state.reactions.add(reaction);
    else microtask(function () {
      callReaction(reaction, state);
    });
    return reaction.promise;
  });

  OwnPromiseCapability = function () {
    var promise = new Internal();
    var state = getInternalPromiseState(promise);
    this.promise = promise;
    this.resolve = bind$1$2(internalResolve, state);
    this.reject = bind$1$2(internalReject, state);
  };

  newPromiseCapabilityModule$6.f = newPromiseCapability$1 = function (C) {
    return C === PromiseConstructor || C === PromiseWrapper
      ? new OwnPromiseCapability(C)
      : newGenericPromiseCapability(C);
  };
}

$$d$1({ global: true, constructor: true, wrap: true, forced: FORCED_PROMISE_CONSTRUCTOR$4 }, {
  Promise: PromiseConstructor
});

setToStringTag$1$1(PromiseConstructor, PROMISE, false, true);
setSpecies$1$1(PROMISE);

var NativePromiseConstructor$3 = promiseNativeConstructor;
var checkCorrectnessOfIteration$3 = checkCorrectnessOfIteration$2;
var FORCED_PROMISE_CONSTRUCTOR$3 = promiseConstructorDetection.CONSTRUCTOR;

var promiseStaticsIncorrectIteration = FORCED_PROMISE_CONSTRUCTOR$3 || !checkCorrectnessOfIteration$3(function (iterable) {
  NativePromiseConstructor$3.all(iterable).then(undefined, function () { /* empty */ });
});

var $$c$1 = _export$1;
var call$4$1 = functionCall$1;
var aCallable$4$1 = aCallable$e;
var newPromiseCapabilityModule$5 = newPromiseCapability$2;
var perform$4 = perform$6;
var iterate$5 = iterate$7;
var PROMISE_STATICS_INCORRECT_ITERATION$3 = promiseStaticsIncorrectIteration;

// `Promise.all` method
// https://tc39.es/ecma262/#sec-promise.all
$$c$1({ target: 'Promise', stat: true, forced: PROMISE_STATICS_INCORRECT_ITERATION$3 }, {
  all: function all(iterable) {
    var C = this;
    var capability = newPromiseCapabilityModule$5.f(C);
    var resolve = capability.resolve;
    var reject = capability.reject;
    var result = perform$4(function () {
      var $promiseResolve = aCallable$4$1(C.resolve);
      var values = [];
      var counter = 0;
      var remaining = 1;
      iterate$5(iterable, function (promise) {
        var index = counter++;
        var alreadyCalled = false;
        remaining++;
        call$4$1($promiseResolve, C, promise).then(function (value) {
          if (alreadyCalled) return;
          alreadyCalled = true;
          values[index] = value;
          --remaining || resolve(values);
        }, reject);
      });
      --remaining || resolve(values);
    });
    if (result.error) reject(result.value);
    return capability.promise;
  }
});

var $$b$1 = _export$1;
var FORCED_PROMISE_CONSTRUCTOR$2 = promiseConstructorDetection.CONSTRUCTOR;
var NativePromiseConstructor$2 = promiseNativeConstructor;

NativePromiseConstructor$2 && NativePromiseConstructor$2.prototype;

// `Promise.prototype.catch` method
// https://tc39.es/ecma262/#sec-promise.prototype.catch
$$b$1({ target: 'Promise', proto: true, forced: FORCED_PROMISE_CONSTRUCTOR$2, real: true }, {
  'catch': function (onRejected) {
    return this.then(undefined, onRejected);
  }
});

var $$a$1 = _export$1;
var call$3$1 = functionCall$1;
var aCallable$3$1 = aCallable$e;
var newPromiseCapabilityModule$4 = newPromiseCapability$2;
var perform$3 = perform$6;
var iterate$4 = iterate$7;
var PROMISE_STATICS_INCORRECT_ITERATION$2 = promiseStaticsIncorrectIteration;

// `Promise.race` method
// https://tc39.es/ecma262/#sec-promise.race
$$a$1({ target: 'Promise', stat: true, forced: PROMISE_STATICS_INCORRECT_ITERATION$2 }, {
  race: function race(iterable) {
    var C = this;
    var capability = newPromiseCapabilityModule$4.f(C);
    var reject = capability.reject;
    var result = perform$3(function () {
      var $promiseResolve = aCallable$3$1(C.resolve);
      iterate$4(iterable, function (promise) {
        call$3$1($promiseResolve, C, promise).then(capability.resolve, reject);
      });
    });
    if (result.error) reject(result.value);
    return capability.promise;
  }
});

var $$9$1 = _export$1;
var call$2$1 = functionCall$1;
var newPromiseCapabilityModule$3 = newPromiseCapability$2;
var FORCED_PROMISE_CONSTRUCTOR$1 = promiseConstructorDetection.CONSTRUCTOR;

// `Promise.reject` method
// https://tc39.es/ecma262/#sec-promise.reject
$$9$1({ target: 'Promise', stat: true, forced: FORCED_PROMISE_CONSTRUCTOR$1 }, {
  reject: function reject(r) {
    var capability = newPromiseCapabilityModule$3.f(this);
    call$2$1(capability.reject, undefined, r);
    return capability.promise;
  }
});

var anObject$e = anObject$d$1;
var isObject$3$2 = isObject$h$1;
var newPromiseCapability = newPromiseCapability$2;

var promiseResolve$2 = function (C, x) {
  anObject$e(C);
  if (isObject$3$2(x) && x.constructor === C) return x;
  var promiseCapability = newPromiseCapability.f(C);
  var resolve = promiseCapability.resolve;
  resolve(x);
  return promiseCapability.promise;
};

var $$8$1 = _export$1;
var getBuiltIn$2$1 = getBuiltIn$f;
var IS_PURE = isPure;
var NativePromiseConstructor$1 = promiseNativeConstructor;
var FORCED_PROMISE_CONSTRUCTOR = promiseConstructorDetection.CONSTRUCTOR;
var promiseResolve$1 = promiseResolve$2;

var PromiseConstructorWrapper = getBuiltIn$2$1('Promise');
var CHECK_WRAPPER = !FORCED_PROMISE_CONSTRUCTOR;

// `Promise.resolve` method
// https://tc39.es/ecma262/#sec-promise.resolve
$$8$1({ target: 'Promise', stat: true, forced: IS_PURE  }, {
  resolve: function resolve(x) {
    return promiseResolve$1(CHECK_WRAPPER && this === PromiseConstructorWrapper ? NativePromiseConstructor$1 : this, x);
  }
});

var $$7$1 = _export$1;
var call$1$1 = functionCall$1;
var aCallable$2$1 = aCallable$e;
var newPromiseCapabilityModule$2 = newPromiseCapability$2;
var perform$2 = perform$6;
var iterate$3$1 = iterate$7;
var PROMISE_STATICS_INCORRECT_ITERATION$1 = promiseStaticsIncorrectIteration;

// `Promise.allSettled` method
// https://tc39.es/ecma262/#sec-promise.allsettled
$$7$1({ target: 'Promise', stat: true, forced: PROMISE_STATICS_INCORRECT_ITERATION$1 }, {
  allSettled: function allSettled(iterable) {
    var C = this;
    var capability = newPromiseCapabilityModule$2.f(C);
    var resolve = capability.resolve;
    var reject = capability.reject;
    var result = perform$2(function () {
      var promiseResolve = aCallable$2$1(C.resolve);
      var values = [];
      var counter = 0;
      var remaining = 1;
      iterate$3$1(iterable, function (promise) {
        var index = counter++;
        var alreadyCalled = false;
        remaining++;
        call$1$1(promiseResolve, C, promise).then(function (value) {
          if (alreadyCalled) return;
          alreadyCalled = true;
          values[index] = { status: 'fulfilled', value: value };
          --remaining || resolve(values);
        }, function (error) {
          if (alreadyCalled) return;
          alreadyCalled = true;
          values[index] = { status: 'rejected', reason: error };
          --remaining || resolve(values);
        });
      });
      --remaining || resolve(values);
    });
    if (result.error) reject(result.value);
    return capability.promise;
  }
});

var $$6$1 = _export$1;
var call$l = functionCall$1;
var aCallable$1$1 = aCallable$e;
var getBuiltIn$1$1 = getBuiltIn$f;
var newPromiseCapabilityModule$1 = newPromiseCapability$2;
var perform$1 = perform$6;
var iterate$2$1 = iterate$7;
var PROMISE_STATICS_INCORRECT_ITERATION = promiseStaticsIncorrectIteration;

var PROMISE_ANY_ERROR = 'No one promise resolved';

// `Promise.any` method
// https://tc39.es/ecma262/#sec-promise.any
$$6$1({ target: 'Promise', stat: true, forced: PROMISE_STATICS_INCORRECT_ITERATION }, {
  any: function any(iterable) {
    var C = this;
    var AggregateError = getBuiltIn$1$1('AggregateError');
    var capability = newPromiseCapabilityModule$1.f(C);
    var resolve = capability.resolve;
    var reject = capability.reject;
    var result = perform$1(function () {
      var promiseResolve = aCallable$1$1(C.resolve);
      var errors = [];
      var counter = 0;
      var remaining = 1;
      var alreadyResolved = false;
      iterate$2$1(iterable, function (promise) {
        var index = counter++;
        var alreadyRejected = false;
        remaining++;
        call$l(promiseResolve, C, promise).then(function (value) {
          if (alreadyRejected || alreadyResolved) return;
          alreadyResolved = true;
          resolve(value);
        }, function (error) {
          if (alreadyRejected || alreadyResolved) return;
          alreadyRejected = true;
          errors[index] = error;
          --remaining || reject(new AggregateError(errors, PROMISE_ANY_ERROR));
        });
      });
      --remaining || reject(new AggregateError(errors, PROMISE_ANY_ERROR));
    });
    if (result.error) reject(result.value);
    return capability.promise;
  }
});

var $$5$1 = _export$1;
var NativePromiseConstructor = promiseNativeConstructor;
var fails$5$1 = fails$t$1;
var getBuiltIn$g = getBuiltIn$f;
var isCallable$1$1 = isCallable$m;
var speciesConstructor = speciesConstructor$2;
var promiseResolve = promiseResolve$2;

var NativePromisePrototype = NativePromiseConstructor && NativePromiseConstructor.prototype;

// Safari bug https://bugs.webkit.org/show_bug.cgi?id=200829
var NON_GENERIC = !!NativePromiseConstructor && fails$5$1(function () {
  // eslint-disable-next-line unicorn/no-thenable -- required for testing
  NativePromisePrototype['finally'].call({ then: function () { /* empty */ } }, function () { /* empty */ });
});

// `Promise.prototype.finally` method
// https://tc39.es/ecma262/#sec-promise.prototype.finally
$$5$1({ target: 'Promise', proto: true, real: true, forced: NON_GENERIC }, {
  'finally': function (onFinally) {
    var C = speciesConstructor(this, getBuiltIn$g('Promise'));
    var isFunction = isCallable$1$1(onFinally);
    return this.then(
      isFunction ? function (x) {
        return promiseResolve(C, onFinally()).then(function () { return x; });
      } : onFinally,
      isFunction ? function (e) {
        return promiseResolve(C, onFinally()).then(function () { throw e; });
      } : onFinally
    );
  }
});

var path$2$1 = path$o$1;

var promise$5 = path$2$1.Promise;

var parent$e$1 = promise$5;


var promise$4 = parent$e$1;

var parent$d$1 = promise$4;

var promise$3 = parent$d$1;

// TODO: Remove from `core-js@4`
var $$4$1 = _export$1;
var newPromiseCapabilityModule = newPromiseCapability$2;
var perform = perform$6;

// `Promise.try` method
// https://github.com/tc39/proposal-promise-try
$$4$1({ target: 'Promise', stat: true, forced: true }, {
  'try': function (callbackfn) {
    var promiseCapability = newPromiseCapabilityModule.f(this);
    var result = perform(callbackfn);
    (result.error ? promiseCapability.reject : promiseCapability.resolve)(result.value);
    return promiseCapability.promise;
  }
});

var parent$c$1 = promise$3;

// TODO: Remove from `core-js@4`




var promise$2 = parent$c$1;

var promise$1 = promise$2;

var promise = promise$1;

var parent$b$1 = reverse$5;

var reverse$3$1 = parent$b$1;

var parent$a$1 = reverse$3$1;

var reverse$2$1 = parent$a$1;

var reverse$1$1 = reverse$2$1;

var reverse$8 = reverse$1$1;

(function (module) {
	var _typeof = _typeofExports["default"];
	var _Object$defineProperty = defineProperty$7$1;
	var _Symbol = symbol$1$1;
	var _Object$create = create$2$1;
	var _Object$getPrototypeOf = getPrototypeOf$1$1;
	var _forEachInstanceProperty = forEach$1$1;
	var _Object$setPrototypeOf = setPrototypeOf$1$1;
	var _Promise = promise;
	var _reverseInstanceProperty = reverse$8;
	var _sliceInstanceProperty = slice$1$1;
	function _regeneratorRuntime() {
	  module.exports = _regeneratorRuntime = function _regeneratorRuntime() {
	    return exports;
	  }, module.exports.__esModule = true, module.exports["default"] = module.exports;
	  var exports = {},
	    Op = Object.prototype,
	    hasOwn = Op.hasOwnProperty,
	    defineProperty = _Object$defineProperty || function (obj, key, desc) {
	      obj[key] = desc.value;
	    },
	    $Symbol = "function" == typeof _Symbol ? _Symbol : {},
	    iteratorSymbol = $Symbol.iterator || "@@iterator",
	    asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
	    toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
	  function define(obj, key, value) {
	    return _Object$defineProperty(obj, key, {
	      value: value,
	      enumerable: !0,
	      configurable: !0,
	      writable: !0
	    }), obj[key];
	  }
	  try {
	    define({}, "");
	  } catch (err) {
	    define = function define(obj, key, value) {
	      return obj[key] = value;
	    };
	  }
	  function wrap(innerFn, outerFn, self, tryLocsList) {
	    var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
	      generator = _Object$create(protoGenerator.prototype),
	      context = new Context(tryLocsList || []);
	    return defineProperty(generator, "_invoke", {
	      value: makeInvokeMethod(innerFn, self, context)
	    }), generator;
	  }
	  function tryCatch(fn, obj, arg) {
	    try {
	      return {
	        type: "normal",
	        arg: fn.call(obj, arg)
	      };
	    } catch (err) {
	      return {
	        type: "throw",
	        arg: err
	      };
	    }
	  }
	  exports.wrap = wrap;
	  var ContinueSentinel = {};
	  function Generator() {}
	  function GeneratorFunction() {}
	  function GeneratorFunctionPrototype() {}
	  var IteratorPrototype = {};
	  define(IteratorPrototype, iteratorSymbol, function () {
	    return this;
	  });
	  var getProto = _Object$getPrototypeOf,
	    NativeIteratorPrototype = getProto && getProto(getProto(values([])));
	  NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
	  var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = _Object$create(IteratorPrototype);
	  function defineIteratorMethods(prototype) {
	    var _context;
	    _forEachInstanceProperty(_context = ["next", "throw", "return"]).call(_context, function (method) {
	      define(prototype, method, function (arg) {
	        return this._invoke(method, arg);
	      });
	    });
	  }
	  function AsyncIterator(generator, PromiseImpl) {
	    function invoke(method, arg, resolve, reject) {
	      var record = tryCatch(generator[method], generator, arg);
	      if ("throw" !== record.type) {
	        var result = record.arg,
	          value = result.value;
	        return value && "object" == _typeof(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
	          invoke("next", value, resolve, reject);
	        }, function (err) {
	          invoke("throw", err, resolve, reject);
	        }) : PromiseImpl.resolve(value).then(function (unwrapped) {
	          result.value = unwrapped, resolve(result);
	        }, function (error) {
	          return invoke("throw", error, resolve, reject);
	        });
	      }
	      reject(record.arg);
	    }
	    var previousPromise;
	    defineProperty(this, "_invoke", {
	      value: function value(method, arg) {
	        function callInvokeWithMethodAndArg() {
	          return new PromiseImpl(function (resolve, reject) {
	            invoke(method, arg, resolve, reject);
	          });
	        }
	        return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
	      }
	    });
	  }
	  function makeInvokeMethod(innerFn, self, context) {
	    var state = "suspendedStart";
	    return function (method, arg) {
	      if ("executing" === state) throw new Error("Generator is already running");
	      if ("completed" === state) {
	        if ("throw" === method) throw arg;
	        return doneResult();
	      }
	      for (context.method = method, context.arg = arg;;) {
	        var delegate = context.delegate;
	        if (delegate) {
	          var delegateResult = maybeInvokeDelegate(delegate, context);
	          if (delegateResult) {
	            if (delegateResult === ContinueSentinel) continue;
	            return delegateResult;
	          }
	        }
	        if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
	          if ("suspendedStart" === state) throw state = "completed", context.arg;
	          context.dispatchException(context.arg);
	        } else "return" === context.method && context.abrupt("return", context.arg);
	        state = "executing";
	        var record = tryCatch(innerFn, self, context);
	        if ("normal" === record.type) {
	          if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
	          return {
	            value: record.arg,
	            done: context.done
	          };
	        }
	        "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
	      }
	    };
	  }
	  function maybeInvokeDelegate(delegate, context) {
	    var methodName = context.method,
	      method = delegate.iterator[methodName];
	    if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator["return"] && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
	    var record = tryCatch(method, delegate.iterator, context.arg);
	    if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
	    var info = record.arg;
	    return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
	  }
	  function pushTryEntry(locs) {
	    var entry = {
	      tryLoc: locs[0]
	    };
	    1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
	  }
	  function resetTryEntry(entry) {
	    var record = entry.completion || {};
	    record.type = "normal", delete record.arg, entry.completion = record;
	  }
	  function Context(tryLocsList) {
	    this.tryEntries = [{
	      tryLoc: "root"
	    }], _forEachInstanceProperty(tryLocsList).call(tryLocsList, pushTryEntry, this), this.reset(!0);
	  }
	  function values(iterable) {
	    if (iterable) {
	      var iteratorMethod = iterable[iteratorSymbol];
	      if (iteratorMethod) return iteratorMethod.call(iterable);
	      if ("function" == typeof iterable.next) return iterable;
	      if (!isNaN(iterable.length)) {
	        var i = -1,
	          next = function next() {
	            for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
	            return next.value = undefined, next.done = !0, next;
	          };
	        return next.next = next;
	      }
	    }
	    return {
	      next: doneResult
	    };
	  }
	  function doneResult() {
	    return {
	      value: undefined,
	      done: !0
	    };
	  }
	  return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
	    value: GeneratorFunctionPrototype,
	    configurable: !0
	  }), defineProperty(GeneratorFunctionPrototype, "constructor", {
	    value: GeneratorFunction,
	    configurable: !0
	  }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
	    var ctor = "function" == typeof genFun && genFun.constructor;
	    return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
	  }, exports.mark = function (genFun) {
	    return _Object$setPrototypeOf ? _Object$setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = _Object$create(Gp), genFun;
	  }, exports.awrap = function (arg) {
	    return {
	      __await: arg
	    };
	  }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
	    return this;
	  }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
	    void 0 === PromiseImpl && (PromiseImpl = _Promise);
	    var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
	    return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
	      return result.done ? result.value : iter.next();
	    });
	  }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
	    return this;
	  }), define(Gp, "toString", function () {
	    return "[object Generator]";
	  }), exports.keys = function (val) {
	    var object = Object(val),
	      keys = [];
	    for (var key in object) keys.push(key);
	    return _reverseInstanceProperty(keys).call(keys), function next() {
	      for (; keys.length;) {
	        var key = keys.pop();
	        if (key in object) return next.value = key, next.done = !1, next;
	      }
	      return next.done = !0, next;
	    };
	  }, exports.values = values, Context.prototype = {
	    constructor: Context,
	    reset: function reset(skipTempReset) {
	      var _context2;
	      if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, _forEachInstanceProperty(_context2 = this.tryEntries).call(_context2, resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+_sliceInstanceProperty(name).call(name, 1)) && (this[name] = undefined);
	    },
	    stop: function stop() {
	      this.done = !0;
	      var rootRecord = this.tryEntries[0].completion;
	      if ("throw" === rootRecord.type) throw rootRecord.arg;
	      return this.rval;
	    },
	    dispatchException: function dispatchException(exception) {
	      if (this.done) throw exception;
	      var context = this;
	      function handle(loc, caught) {
	        return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
	      }
	      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	        var entry = this.tryEntries[i],
	          record = entry.completion;
	        if ("root" === entry.tryLoc) return handle("end");
	        if (entry.tryLoc <= this.prev) {
	          var hasCatch = hasOwn.call(entry, "catchLoc"),
	            hasFinally = hasOwn.call(entry, "finallyLoc");
	          if (hasCatch && hasFinally) {
	            if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
	            if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
	          } else if (hasCatch) {
	            if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
	          } else {
	            if (!hasFinally) throw new Error("try statement without catch or finally");
	            if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
	          }
	        }
	      }
	    },
	    abrupt: function abrupt(type, arg) {
	      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	        var entry = this.tryEntries[i];
	        if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
	          var finallyEntry = entry;
	          break;
	        }
	      }
	      finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
	      var record = finallyEntry ? finallyEntry.completion : {};
	      return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
	    },
	    complete: function complete(record, afterLoc) {
	      if ("throw" === record.type) throw record.arg;
	      return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
	    },
	    finish: function finish(finallyLoc) {
	      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	        var entry = this.tryEntries[i];
	        if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
	      }
	    },
	    "catch": function _catch(tryLoc) {
	      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
	        var entry = this.tryEntries[i];
	        if (entry.tryLoc === tryLoc) {
	          var record = entry.completion;
	          if ("throw" === record.type) {
	            var thrown = record.arg;
	            resetTryEntry(entry);
	          }
	          return thrown;
	        }
	      }
	      throw new Error("illegal catch attempt");
	    },
	    delegateYield: function delegateYield(iterable, resultName, nextLoc) {
	      return this.delegate = {
	        iterator: values(iterable),
	        resultName: resultName,
	        nextLoc: nextLoc
	      }, "next" === this.method && (this.arg = undefined), ContinueSentinel;
	    }
	  }, exports;
	}
	module.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports["default"] = module.exports; 
} (regeneratorRuntime$1));

var regeneratorRuntimeExports = regeneratorRuntime$1.exports;

// TODO(Babel 8): Remove this file.

var runtime = regeneratorRuntimeExports();
var regenerator = runtime;

// Copied from https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js#L736=
try {
  regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
  if (typeof globalThis === "object") {
    globalThis.regeneratorRuntime = runtime;
  } else {
    Function("r", "regeneratorRuntime = r")(runtime);
  }
}

var _regeneratorRuntime = /*@__PURE__*/getDefaultExportFromCjs$2(regenerator);

var internalMetadata$1 = {exports: {}};

// FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
var fails$4$1 = fails$t$1;

var arrayBufferNonExtensible$1 = fails$4$1(function () {
  if (typeof ArrayBuffer == 'function') {
    var buffer = new ArrayBuffer(8);
    // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
    if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
  }
});

var fails$3$1 = fails$t$1;
var isObject$2$2 = isObject$h$1;
var classof$3$1 = classofRaw$2$1;
var ARRAY_BUFFER_NON_EXTENSIBLE$1 = arrayBufferNonExtensible$1;

// eslint-disable-next-line es/no-object-isextensible -- safe
var $isExtensible$1 = Object.isExtensible;
var FAILS_ON_PRIMITIVES$4 = fails$3$1(function () { $isExtensible$1(1); });

// `Object.isExtensible` method
// https://tc39.es/ecma262/#sec-object.isextensible
var objectIsExtensible$1 = (FAILS_ON_PRIMITIVES$4 || ARRAY_BUFFER_NON_EXTENSIBLE$1) ? function isExtensible(it) {
  if (!isObject$2$2(it)) return false;
  if (ARRAY_BUFFER_NON_EXTENSIBLE$1 && classof$3$1(it) == 'ArrayBuffer') return false;
  return $isExtensible$1 ? $isExtensible$1(it) : true;
} : $isExtensible$1;

var fails$2$1 = fails$t$1;

var freezing$1 = !fails$2$1(function () {
  // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing
  return Object.isExtensible(Object.preventExtensions({}));
});

var $$3$1 = _export$1;
var uncurryThis$1$1 = functionUncurryThis$1;
var hiddenKeys$7 = hiddenKeys$6$1;
var isObject$1$2 = isObject$h$1;
var hasOwn$3$1 = hasOwnProperty_1$1;
var defineProperty$1$1 = objectDefineProperty$1.f;
var getOwnPropertyNamesModule$3 = objectGetOwnPropertyNames$1;
var getOwnPropertyNamesExternalModule$1 = objectGetOwnPropertyNamesExternal$1;
var isExtensible$2 = objectIsExtensible$1;
var uid$5 = uid$4$1;
var FREEZING$2 = freezing$1;

var REQUIRED$1 = false;
var METADATA$1 = uid$5('meta');
var id$3 = 0;

var setMetadata$1 = function (it) {
  defineProperty$1$1(it, METADATA$1, { value: {
    objectID: 'O' + id$3++, // object ID
    weakData: {}          // weak collections IDs
  } });
};

var fastKey$1$1 = function (it, create) {
  // return a primitive with prefix
  if (!isObject$1$2(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
  if (!hasOwn$3$1(it, METADATA$1)) {
    // can't set metadata to uncaught frozen object
    if (!isExtensible$2(it)) return 'F';
    // not necessary to add metadata
    if (!create) return 'E';
    // add missing metadata
    setMetadata$1(it);
  // return object ID
  } return it[METADATA$1].objectID;
};

var getWeakData$2 = function (it, create) {
  if (!hasOwn$3$1(it, METADATA$1)) {
    // can't set metadata to uncaught frozen object
    if (!isExtensible$2(it)) return true;
    // not necessary to add metadata
    if (!create) return false;
    // add missing metadata
    setMetadata$1(it);
  // return the store of weak collections IDs
  } return it[METADATA$1].weakData;
};

// add metadata on freeze-family methods calling
var onFreeze$1 = function (it) {
  if (FREEZING$2 && REQUIRED$1 && isExtensible$2(it) && !hasOwn$3$1(it, METADATA$1)) setMetadata$1(it);
  return it;
};

var enable$1 = function () {
  meta$2.enable = function () { /* empty */ };
  REQUIRED$1 = true;
  var getOwnPropertyNames = getOwnPropertyNamesModule$3.f;
  var splice = uncurryThis$1$1([].splice);
  var test = {};
  test[METADATA$1] = 1;

  // prevent exposing of metadata key
  if (getOwnPropertyNames(test).length) {
    getOwnPropertyNamesModule$3.f = function (it) {
      var result = getOwnPropertyNames(it);
      for (var i = 0, length = result.length; i < length; i++) {
        if (result[i] === METADATA$1) {
          splice(result, i, 1);
          break;
        }
      } return result;
    };

    $$3$1({ target: 'Object', stat: true, forced: true }, {
      getOwnPropertyNames: getOwnPropertyNamesExternalModule$1.f
    });
  }
};

var meta$2 = internalMetadata$1.exports = {
  enable: enable$1,
  fastKey: fastKey$1$1,
  getWeakData: getWeakData$2,
  onFreeze: onFreeze$1
};

hiddenKeys$7[METADATA$1] = true;

var internalMetadataExports$1 = internalMetadata$1.exports;

var $$2$1 = _export$1;
var global$1$1 = global$m;
var InternalMetadataModule$2 = internalMetadataExports$1;
var fails$1$1 = fails$t$1;
var createNonEnumerableProperty$a = createNonEnumerableProperty$9;
var iterate$1$1 = iterate$7;
var anInstance$1$1 = anInstance$3$1;
var isCallable$n = isCallable$m;
var isObject$l = isObject$h$1;
var setToStringTag$8 = setToStringTag$7;
var defineProperty$g = objectDefineProperty$1.f;
var forEach$a = arrayIteration$1.forEach;
var DESCRIPTORS$1$1 = descriptors$1;
var InternalStateModule$1$1 = internalState$1;

var setInternalState$1$1 = InternalStateModule$1$1.set;
var internalStateGetterFor$1$1 = InternalStateModule$1$1.getterFor;

var collection$2$1 = function (CONSTRUCTOR_NAME, wrapper, common) {
  var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
  var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
  var ADDER = IS_MAP ? 'set' : 'add';
  var NativeConstructor = global$1$1[CONSTRUCTOR_NAME];
  var NativePrototype = NativeConstructor && NativeConstructor.prototype;
  var exported = {};
  var Constructor;

  if (!DESCRIPTORS$1$1 || !isCallable$n(NativeConstructor)
    || !(IS_WEAK || NativePrototype.forEach && !fails$1$1(function () { new NativeConstructor().entries().next(); }))
  ) {
    // create collection constructor
    Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
    InternalMetadataModule$2.enable();
  } else {
    Constructor = wrapper(function (target, iterable) {
      setInternalState$1$1(anInstance$1$1(target, Prototype), {
        type: CONSTRUCTOR_NAME,
        collection: new NativeConstructor()
      });
      if (iterable != undefined) iterate$1$1(iterable, target[ADDER], { that: target, AS_ENTRIES: IS_MAP });
    });

    var Prototype = Constructor.prototype;

    var getInternalState = internalStateGetterFor$1$1(CONSTRUCTOR_NAME);

    forEach$a(['add', 'clear', 'delete', 'forEach', 'get', 'has', 'set', 'keys', 'values', 'entries'], function (KEY) {
      var IS_ADDER = KEY == 'add' || KEY == 'set';
      if (KEY in NativePrototype && !(IS_WEAK && KEY == 'clear')) {
        createNonEnumerableProperty$a(Prototype, KEY, function (a, b) {
          var collection = getInternalState(this).collection;
          if (!IS_ADDER && IS_WEAK && !isObject$l(a)) return KEY == 'get' ? undefined : false;
          var result = collection[KEY](a === 0 ? 0 : a, b);
          return IS_ADDER ? this : result;
        });
      }
    });

    IS_WEAK || defineProperty$g(Prototype, 'size', {
      configurable: true,
      get: function () {
        return getInternalState(this).collection.size;
      }
    });
  }

  setToStringTag$8(Constructor, CONSTRUCTOR_NAME, false, true);

  exported[CONSTRUCTOR_NAME] = Constructor;
  $$2$1({ global: true, forced: true }, exported);

  if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);

  return Constructor;
};

var defineBuiltIn$7 = defineBuiltIn$6;

var defineBuiltIns$1$1 = function (target, src, options) {
  for (var key in src) {
    if (options && options.unsafe && target[key]) target[key] = src[key];
    else defineBuiltIn$7(target, key, src[key], options);
  } return target;
};

var create$d = objectCreate$1;
var defineBuiltInAccessor$4 = defineBuiltInAccessor$3$1;
var defineBuiltIns$4 = defineBuiltIns$1$1;
var bind$k = functionBindContext$1;
var anInstance$4 = anInstance$3$1;
var isNullOrUndefined$6 = isNullOrUndefined$5$1;
var iterate$8 = iterate$7;
var defineIterator$3 = iteratorDefine$1;
var createIterResultObject$4 = createIterResultObject$3$1;
var setSpecies$3 = setSpecies$2;
var DESCRIPTORS$j = descriptors$1;
var fastKey$2 = internalMetadataExports$1.fastKey;
var InternalStateModule$6 = internalState$1;

var setInternalState$6 = InternalStateModule$6.set;
var internalStateGetterFor$3 = InternalStateModule$6.getterFor;

var collectionStrong$2$1 = {
  getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
    var Constructor = wrapper(function (that, iterable) {
      anInstance$4(that, Prototype);
      setInternalState$6(that, {
        type: CONSTRUCTOR_NAME,
        index: create$d(null),
        first: undefined,
        last: undefined,
        size: 0
      });
      if (!DESCRIPTORS$j) that.size = 0;
      if (!isNullOrUndefined$6(iterable)) iterate$8(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
    });

    var Prototype = Constructor.prototype;

    var getInternalState = internalStateGetterFor$3(CONSTRUCTOR_NAME);

    var define = function (that, key, value) {
      var state = getInternalState(that);
      var entry = getEntry(that, key);
      var previous, index;
      // change existing entry
      if (entry) {
        entry.value = value;
      // create new entry
      } else {
        state.last = entry = {
          index: index = fastKey$2(key, true),
          key: key,
          value: value,
          previous: previous = state.last,
          next: undefined,
          removed: false
        };
        if (!state.first) state.first = entry;
        if (previous) previous.next = entry;
        if (DESCRIPTORS$j) state.size++;
        else that.size++;
        // add to index
        if (index !== 'F') state.index[index] = entry;
      } return that;
    };

    var getEntry = function (that, key) {
      var state = getInternalState(that);
      // fast case
      var index = fastKey$2(key);
      var entry;
      if (index !== 'F') return state.index[index];
      // frozen object case
      for (entry = state.first; entry; entry = entry.next) {
        if (entry.key == key) return entry;
      }
    };

    defineBuiltIns$4(Prototype, {
      // `{ Map, Set }.prototype.clear()` methods
      // https://tc39.es/ecma262/#sec-map.prototype.clear
      // https://tc39.es/ecma262/#sec-set.prototype.clear
      clear: function clear() {
        var that = this;
        var state = getInternalState(that);
        var data = state.index;
        var entry = state.first;
        while (entry) {
          entry.removed = true;
          if (entry.previous) entry.previous = entry.previous.next = undefined;
          delete data[entry.index];
          entry = entry.next;
        }
        state.first = state.last = undefined;
        if (DESCRIPTORS$j) state.size = 0;
        else that.size = 0;
      },
      // `{ Map, Set }.prototype.delete(key)` methods
      // https://tc39.es/ecma262/#sec-map.prototype.delete
      // https://tc39.es/ecma262/#sec-set.prototype.delete
      'delete': function (key) {
        var that = this;
        var state = getInternalState(that);
        var entry = getEntry(that, key);
        if (entry) {
          var next = entry.next;
          var prev = entry.previous;
          delete state.index[entry.index];
          entry.removed = true;
          if (prev) prev.next = next;
          if (next) next.previous = prev;
          if (state.first == entry) state.first = next;
          if (state.last == entry) state.last = prev;
          if (DESCRIPTORS$j) state.size--;
          else that.size--;
        } return !!entry;
      },
      // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
      // https://tc39.es/ecma262/#sec-map.prototype.foreach
      // https://tc39.es/ecma262/#sec-set.prototype.foreach
      forEach: function forEach(callbackfn /* , that = undefined */) {
        var state = getInternalState(this);
        var boundFunction = bind$k(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
        var entry;
        while (entry = entry ? entry.next : state.first) {
          boundFunction(entry.value, entry.key, this);
          // revert to the last existing entry
          while (entry && entry.removed) entry = entry.previous;
        }
      },
      // `{ Map, Set}.prototype.has(key)` methods
      // https://tc39.es/ecma262/#sec-map.prototype.has
      // https://tc39.es/ecma262/#sec-set.prototype.has
      has: function has(key) {
        return !!getEntry(this, key);
      }
    });

    defineBuiltIns$4(Prototype, IS_MAP ? {
      // `Map.prototype.get(key)` method
      // https://tc39.es/ecma262/#sec-map.prototype.get
      get: function get(key) {
        var entry = getEntry(this, key);
        return entry && entry.value;
      },
      // `Map.prototype.set(key, value)` method
      // https://tc39.es/ecma262/#sec-map.prototype.set
      set: function set(key, value) {
        return define(this, key === 0 ? 0 : key, value);
      }
    } : {
      // `Set.prototype.add(value)` method
      // https://tc39.es/ecma262/#sec-set.prototype.add
      add: function add(value) {
        return define(this, value = value === 0 ? 0 : value, value);
      }
    });
    if (DESCRIPTORS$j) defineBuiltInAccessor$4(Prototype, 'size', {
      configurable: true,
      get: function () {
        return getInternalState(this).size;
      }
    });
    return Constructor;
  },
  setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
    var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
    var getInternalCollectionState = internalStateGetterFor$3(CONSTRUCTOR_NAME);
    var getInternalIteratorState = internalStateGetterFor$3(ITERATOR_NAME);
    // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
    // https://tc39.es/ecma262/#sec-map.prototype.entries
    // https://tc39.es/ecma262/#sec-map.prototype.keys
    // https://tc39.es/ecma262/#sec-map.prototype.values
    // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
    // https://tc39.es/ecma262/#sec-set.prototype.entries
    // https://tc39.es/ecma262/#sec-set.prototype.keys
    // https://tc39.es/ecma262/#sec-set.prototype.values
    // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
    defineIterator$3(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
      setInternalState$6(this, {
        type: ITERATOR_NAME,
        target: iterated,
        state: getInternalCollectionState(iterated),
        kind: kind,
        last: undefined
      });
    }, function () {
      var state = getInternalIteratorState(this);
      var kind = state.kind;
      var entry = state.last;
      // revert to the last existing entry
      while (entry && entry.removed) entry = entry.previous;
      // get next entry
      if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
        // or finish the iteration
        state.target = undefined;
        return createIterResultObject$4(undefined, true);
      }
      // return step by kind
      if (kind == 'keys') return createIterResultObject$4(entry.key, false);
      if (kind == 'values') return createIterResultObject$4(entry.value, false);
      return createIterResultObject$4([entry.key, entry.value], false);
    }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);

    // `{ Map, Set }.prototype[@@species]` accessors
    // https://tc39.es/ecma262/#sec-get-map-@@species
    // https://tc39.es/ecma262/#sec-get-set-@@species
    setSpecies$3(CONSTRUCTOR_NAME);
  }
};

var collection$1$1 = collection$2$1;
var collectionStrong$1$1 = collectionStrong$2$1;

// `Map` constructor
// https://tc39.es/ecma262/#sec-map-objects
collection$1$1('Map', function (init) {
  return function Map() { return init(this, arguments.length ? arguments[0] : undefined); };
}, collectionStrong$1$1);

var path$1$1 = path$o$1;

var map$2$1 = path$1$1.Map;

var parent$9$1 = map$2$1;


var map$1$2 = parent$9$1;

var map$8 = map$1$2;

var _Map$1 = /*@__PURE__*/getDefaultExportFromCjs$2(map$8);

var $$1$1 = _export$1;
var $some$1 = arrayIteration$1.some;
var arrayMethodIsStrict$1$1 = arrayMethodIsStrict$4$1;

var STRICT_METHOD$1$1 = arrayMethodIsStrict$1$1('some');

// `Array.prototype.some` method
// https://tc39.es/ecma262/#sec-array.prototype.some
$$1$1({ target: 'Array', proto: true, forced: !STRICT_METHOD$1$1 }, {
  some: function some(callbackfn /* , thisArg */) {
    return $some$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$4$1 = entryVirtual$f$1;

var some$3$1 = entryVirtual$4$1('Array').some;

var isPrototypeOf$4$1 = objectIsPrototypeOf$1;
var method$4$1 = some$3$1;

var ArrayPrototype$4$1 = Array.prototype;

var some$2$1 = function (it) {
  var own = it.some;
  return it === ArrayPrototype$4$1 || (isPrototypeOf$4$1(ArrayPrototype$4$1, it) && own === ArrayPrototype$4$1.some) ? method$4$1 : own;
};

var parent$8$1 = some$2$1;

var some$1$1 = parent$8$1;

var some$4 = some$1$1;

var _someInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(some$4);

var entryVirtual$3$1 = entryVirtual$f$1;

var keys$3$1 = entryVirtual$3$1('Array').keys;

var parent$7$1 = keys$3$1;

var keys$2$1 = parent$7$1;

var classof$2$1 = classof$d$1;
var hasOwn$2$1 = hasOwnProperty_1$1;
var isPrototypeOf$3$1 = objectIsPrototypeOf$1;
var method$3$1 = keys$2$1;

var ArrayPrototype$3$1 = Array.prototype;

var DOMIterables$2$1 = {
  DOMTokenList: true,
  NodeList: true
};

var keys$1$1 = function (it) {
  var own = it.keys;
  return it === ArrayPrototype$3$1 || (isPrototypeOf$3$1(ArrayPrototype$3$1, it) && own === ArrayPrototype$3$1.keys)
    || hasOwn$2$1(DOMIterables$2$1, classof$2$1(it)) ? method$3$1 : own;
};

var keys$8 = keys$1$1;

var _keysInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$2(keys$8);

var arraySlice$7 = arraySliceSimple$1;

var floor$2 = Math.floor;

var mergeSort$1 = function (array, comparefn) {
  var length = array.length;
  var middle = floor$2(length / 2);
  return length < 8 ? insertionSort$1(array, comparefn) : merge$4(
    array,
    mergeSort$1(arraySlice$7(array, 0, middle), comparefn),
    mergeSort$1(arraySlice$7(array, middle), comparefn),
    comparefn
  );
};

var insertionSort$1 = function (array, comparefn) {
  var length = array.length;
  var i = 1;
  var element, j;

  while (i < length) {
    j = i;
    element = array[i];
    while (j && comparefn(array[j - 1], element) > 0) {
      array[j] = array[--j];
    }
    if (j !== i++) array[j] = element;
  } return array;
};

var merge$4 = function (array, left, right, comparefn) {
  var llength = left.length;
  var rlength = right.length;
  var lindex = 0;
  var rindex = 0;

  while (lindex < llength || rindex < rlength) {
    array[lindex + rindex] = (lindex < llength && rindex < rlength)
      ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
      : lindex < llength ? left[lindex++] : right[rindex++];
  } return array;
};

var arraySort$1 = mergeSort$1;

var userAgent$1$1 = engineUserAgent$1;

var firefox$1 = userAgent$1$1.match(/firefox\/(\d+)/i);

var engineFfVersion$1 = !!firefox$1 && +firefox$1[1];

var UA$1 = engineUserAgent$1;

var engineIsIeOrEdge$1 = /MSIE|Trident/.test(UA$1);

var userAgent$6 = engineUserAgent$1;

var webkit$1 = userAgent$6.match(/AppleWebKit\/(\d+)\./);

var engineWebkitVersion$1 = !!webkit$1 && +webkit$1[1];

var $$P = _export$1;
var uncurryThis$z = functionUncurryThis$1;
var aCallable$f = aCallable$e;
var toObject$e = toObject$d$1;
var lengthOfArrayLike$d = lengthOfArrayLike$c;
var deletePropertyOrThrow$3 = deletePropertyOrThrow$2$1;
var toString$d = toString$7$1;
var fails$x = fails$t$1;
var internalSort$1 = arraySort$1;
var arrayMethodIsStrict$7 = arrayMethodIsStrict$4$1;
var FF$1 = engineFfVersion$1;
var IE_OR_EDGE$1 = engineIsIeOrEdge$1;
var V8$1 = engineV8Version$1;
var WEBKIT$1 = engineWebkitVersion$1;

var test$3 = [];
var nativeSort$1 = uncurryThis$z(test$3.sort);
var push$7 = uncurryThis$z(test$3.push);

// IE8-
var FAILS_ON_UNDEFINED$1 = fails$x(function () {
  test$3.sort(undefined);
});
// V8 bug
var FAILS_ON_NULL$1 = fails$x(function () {
  test$3.sort(null);
});
// Old WebKit
var STRICT_METHOD$4 = arrayMethodIsStrict$7('sort');

var STABLE_SORT$1 = !fails$x(function () {
  // feature detection can be too slow, so check engines versions
  if (V8$1) return V8$1 < 70;
  if (FF$1 && FF$1 > 3) return;
  if (IE_OR_EDGE$1) return true;
  if (WEBKIT$1) return WEBKIT$1 < 603;

  var result = '';
  var code, chr, value, index;

  // generate an array with more 512 elements (Chakra and old V8 fails only in this case)
  for (code = 65; code < 76; code++) {
    chr = String.fromCharCode(code);

    switch (code) {
      case 66: case 69: case 70: case 72: value = 3; break;
      case 68: case 71: value = 4; break;
      default: value = 2;
    }

    for (index = 0; index < 47; index++) {
      test$3.push({ k: chr + index, v: value });
    }
  }

  test$3.sort(function (a, b) { return b.v - a.v; });

  for (index = 0; index < test$3.length; index++) {
    chr = test$3[index].k.charAt(0);
    if (result.charAt(result.length - 1) !== chr) result += chr;
  }

  return result !== 'DGBEFHACIJK';
});

var FORCED$a = FAILS_ON_UNDEFINED$1 || !FAILS_ON_NULL$1 || !STRICT_METHOD$4 || !STABLE_SORT$1;

var getSortCompare$1 = function (comparefn) {
  return function (x, y) {
    if (y === undefined) return -1;
    if (x === undefined) return 1;
    if (comparefn !== undefined) return +comparefn(x, y) || 0;
    return toString$d(x) > toString$d(y) ? 1 : -1;
  };
};

// `Array.prototype.sort` method
// https://tc39.es/ecma262/#sec-array.prototype.sort
$$P({ target: 'Array', proto: true, forced: FORCED$a }, {
  sort: function sort(comparefn) {
    if (comparefn !== undefined) aCallable$f(comparefn);

    var array = toObject$e(this);

    if (STABLE_SORT$1) return comparefn === undefined ? nativeSort$1(array) : nativeSort$1(array, comparefn);

    var items = [];
    var arrayLength = lengthOfArrayLike$d(array);
    var itemsLength, index;

    for (index = 0; index < arrayLength; index++) {
      if (index in array) push$7(items, array[index]);
    }

    internalSort$1(items, getSortCompare$1(comparefn));

    itemsLength = lengthOfArrayLike$d(items);
    index = 0;

    while (index < itemsLength) array[index] = items[index++];
    while (index < arrayLength) deletePropertyOrThrow$3(array, index++);

    return array;
  }
});

var entryVirtual$2$1 = entryVirtual$f$1;

var sort$3$1 = entryVirtual$2$1('Array').sort;

var isPrototypeOf$2$1 = objectIsPrototypeOf$1;
var method$2$1 = sort$3$1;

var ArrayPrototype$2$1 = Array.prototype;

var sort$2$1 = function (it) {
  var own = it.sort;
  return it === ArrayPrototype$2$1 || (isPrototypeOf$2$1(ArrayPrototype$2$1, it) && own === ArrayPrototype$2$1.sort) ? method$2$1 : own;
};

var parent$6$1 = sort$2$1;

var sort$1$1 = parent$6$1;

var sort$5 = sort$1$1;

var _sortInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(sort$5);

var entryVirtual$1$1 = entryVirtual$f$1;

var values$3$1 = entryVirtual$1$1('Array').values;

var parent$5$1 = values$3$1;

var values$2$1 = parent$5$1;

var classof$1$1 = classof$d$1;
var hasOwn$1$1 = hasOwnProperty_1$1;
var isPrototypeOf$1$1 = objectIsPrototypeOf$1;
var method$1$1 = values$2$1;

var ArrayPrototype$1$1 = Array.prototype;

var DOMIterables$1$1 = {
  DOMTokenList: true,
  NodeList: true
};

var values$1$1 = function (it) {
  var own = it.values;
  return it === ArrayPrototype$1$1 || (isPrototypeOf$1$1(ArrayPrototype$1$1, it) && own === ArrayPrototype$1$1.values)
    || hasOwn$1$1(DOMIterables$1$1, classof$1$1(it)) ? method$1$1 : own;
};

var values$7 = values$1$1;

var _valuesInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$2(values$7);

var iterator$7 = iterator$5$1;

var _Symbol$iterator$1 = /*@__PURE__*/getDefaultExportFromCjs$2(iterator$7);

var entryVirtual$j = entryVirtual$f$1;

var entries$3 = entryVirtual$j('Array').entries;

var parent$4$1 = entries$3;

var entries$2 = parent$4$1;

var classof$g = classof$d$1;
var hasOwn$k = hasOwnProperty_1$1;
var isPrototypeOf$l = objectIsPrototypeOf$1;
var method$g = entries$2;

var ArrayPrototype$g = Array.prototype;

var DOMIterables$5 = {
  DOMTokenList: true,
  NodeList: true
};

var entries$1 = function (it) {
  var own = it.entries;
  return it === ArrayPrototype$g || (isPrototypeOf$l(ArrayPrototype$g, it) && own === ArrayPrototype$g.entries)
    || hasOwn$k(DOMIterables$5, classof$g(it)) ? method$g : own;
};

var entries = entries$1;

var _entriesInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$2(entries);

// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
let getRandomValues$1;
const rnds8$1 = new Uint8Array(16);
function rng$1() {
  // lazy load so that environments that need to polyfill have a chance to do so
  if (!getRandomValues$1) {
    // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
    getRandomValues$1 = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);

    if (!getRandomValues$1) {
      throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
    }
  }

  return getRandomValues$1(rnds8$1);
}

/**
 * Convert array of 16 byte values to UUID string format of the form:
 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 */

const byteToHex$1 = [];

for (let i = 0; i < 256; ++i) {
  byteToHex$1.push((i + 0x100).toString(16).slice(1));
}

function unsafeStringify$1(arr, offset = 0) {
  // Note: Be careful editing this code!  It's been tuned for performance
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
  return byteToHex$1[arr[offset + 0]] + byteToHex$1[arr[offset + 1]] + byteToHex$1[arr[offset + 2]] + byteToHex$1[arr[offset + 3]] + '-' + byteToHex$1[arr[offset + 4]] + byteToHex$1[arr[offset + 5]] + '-' + byteToHex$1[arr[offset + 6]] + byteToHex$1[arr[offset + 7]] + '-' + byteToHex$1[arr[offset + 8]] + byteToHex$1[arr[offset + 9]] + '-' + byteToHex$1[arr[offset + 10]] + byteToHex$1[arr[offset + 11]] + byteToHex$1[arr[offset + 12]] + byteToHex$1[arr[offset + 13]] + byteToHex$1[arr[offset + 14]] + byteToHex$1[arr[offset + 15]];
}

const randomUUID$1 = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
var native$1 = {
  randomUUID: randomUUID$1
};

function v4$1(options, buf, offset) {
  if (native$1.randomUUID && !buf && !options) {
    return native$1.randomUUID();
  }

  options = options || {};
  const rnds = options.random || (options.rng || rng$1)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`

  rnds[6] = rnds[6] & 0x0f | 0x40;
  rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided

  if (buf) {
    offset = offset || 0;

    for (let i = 0; i < 16; ++i) {
      buf[offset + i] = rnds[i];
    }

    return buf;
  }

  return unsafeStringify$1(rnds);
}

/**
 * Determine whether a value can be used as an id.
 *
 * @param value - Input value of unknown type.
 * @returns True if the value is valid id, false otherwise.
 */
function isId(value) {
  return typeof value === "string" || typeof value === "number";
}

/**
 * A queue.
 *
 * @typeParam T - The type of method names to be replaced by queued versions.
 */
var Queue = /*#__PURE__*/function () {
  /** Delay in milliseconds. If defined the queue will be periodically flushed. */

  /** Maximum number of entries in the queue before it will be flushed. */

  /**
   * Construct a new Queue.
   *
   * @param options - Queue configuration.
   */
  function Queue(options) {
    _classCallCheck$1(this, Queue);
    _defineProperty$1(this, "delay", void 0);
    _defineProperty$1(this, "max", void 0);
    _defineProperty$1(this, "_queue", []);
    _defineProperty$1(this, "_timeout", null);
    _defineProperty$1(this, "_extended", null);
    // options
    this.delay = null;
    this.max = Infinity;
    this.setOptions(options);
  }
  /**
   * Update the configuration of the queue.
   *
   * @param options - Queue configuration.
   */
  _createClass$1(Queue, [{
    key: "setOptions",
    value: function setOptions(options) {
      if (options && typeof options.delay !== "undefined") {
        this.delay = options.delay;
      }
      if (options && typeof options.max !== "undefined") {
        this.max = options.max;
      }
      this._flushIfNeeded();
    }
    /**
     * Extend an object with queuing functionality.
     * The object will be extended with a function flush, and the methods provided in options.replace will be replaced with queued ones.
     *
     * @param object - The object to be extended.
     * @param options - Additional options.
     * @returns The created queue.
     */
  }, {
    key: "destroy",
    value:
    /**
     * Destroy the queue. The queue will first flush all queued actions, and in case it has extended an object, will restore the original object.
     */
    function destroy() {
      this.flush();
      if (this._extended) {
        var object = this._extended.object;
        var methods = this._extended.methods;
        for (var i = 0; i < methods.length; i++) {
          var method = methods[i];
          if (method.original) {
            // @TODO: better solution?
            object[method.name] = method.original;
          } else {
            // @TODO: better solution?
            delete object[method.name];
          }
        }
        this._extended = null;
      }
    }
    /**
     * Replace a method on an object with a queued version.
     *
     * @param object - Object having the method.
     * @param method - The method name.
     */
  }, {
    key: "replace",
    value: function replace(object, method) {
      /* eslint-disable-next-line @typescript-eslint/no-this-alias -- Function this is necessary in the function bellow, so class this has to be saved into a variable here. */
      var me = this;
      var original = object[method];
      if (!original) {
        throw new Error("Method " + method + " undefined");
      }
      object[method] = function () {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }
        // add this call to the queue
        me.queue({
          args: args,
          fn: original,
          context: this
        });
      };
    }
    /**
     * Queue a call.
     *
     * @param entry - The function or entry to be queued.
     */
  }, {
    key: "queue",
    value: function queue(entry) {
      if (typeof entry === "function") {
        this._queue.push({
          fn: entry
        });
      } else {
        this._queue.push(entry);
      }
      this._flushIfNeeded();
    }
    /**
     * Check whether the queue needs to be flushed.
     */
  }, {
    key: "_flushIfNeeded",
    value: function _flushIfNeeded() {
      var _this = this;
      // flush when the maximum is exceeded.
      if (this._queue.length > this.max) {
        this.flush();
      }
      // flush after a period of inactivity when a delay is configured
      if (this._timeout != null) {
        clearTimeout(this._timeout);
        this._timeout = null;
      }
      if (this.queue.length > 0 && typeof this.delay === "number") {
        this._timeout = _setTimeout$1(function () {
          _this.flush();
        }, this.delay);
      }
    }
    /**
     * Flush all queued calls
     */
  }, {
    key: "flush",
    value: function flush() {
      var _context, _context2;
      _forEachInstanceProperty$1(_context = _spliceInstanceProperty$1(_context2 = this._queue).call(_context2, 0)).call(_context, function (entry) {
        entry.fn.apply(entry.context || entry.fn, entry.args || []);
      });
    }
  }], [{
    key: "extend",
    value: function extend(object, options) {
      var queue = new Queue(options);
      if (object.flush !== undefined) {
        throw new Error("Target object already has a property flush");
      }
      object.flush = function () {
        queue.flush();
      };
      var methods = [{
        name: "flush",
        original: undefined
      }];
      if (options && options.replace) {
        for (var i = 0; i < options.replace.length; i++) {
          var name = options.replace[i];
          methods.push({
            name: name,
            // @TODO: better solution?
            original: object[name]
          });
          // @TODO: better solution?
          queue.replace(object, name);
        }
      }
      queue._extended = {
        object: object,
        methods: methods
      };
      return queue;
    }
  }]);
  return Queue;
}();

/**
 * {@link DataSet} code that can be reused in {@link DataView} or other similar implementations of {@link DataInterface}.
 *
 * @typeParam Item - Item type that may or may not have an id.
 * @typeParam IdProp - Name of the property that contains the id.
 */
var DataSetPart = /*#__PURE__*/function () {
  function DataSetPart() {
    _classCallCheck$1(this, DataSetPart);
    _defineProperty$1(this, "_subscribers", {
      "*": [],
      add: [],
      remove: [],
      update: []
    });
    /**
     * @deprecated Use on instead (PS: DataView.subscribe === DataView.on).
     */
    _defineProperty$1(this, "subscribe", DataSetPart.prototype.on);
    /**
     * @deprecated Use off instead (PS: DataView.unsubscribe === DataView.off).
     */
    _defineProperty$1(this, "unsubscribe", DataSetPart.prototype.off);
  }
  _createClass$1(DataSetPart, [{
    key: "_trigger",
    value:
    /**
     * Trigger an event
     *
     * @param event - Event name.
     * @param payload - Event payload.
     * @param senderId - Id of the sender.
     */
    function _trigger(event, payload, senderId) {
      var _context, _context2;
      if (event === "*") {
        throw new Error("Cannot trigger event *");
      }
      _forEachInstanceProperty$1(_context = _concatInstanceProperty$1(_context2 = []).call(_context2, _toConsumableArray$1(this._subscribers[event]), _toConsumableArray$1(this._subscribers["*"]))).call(_context, function (subscriber) {
        subscriber(event, payload, senderId != null ? senderId : null);
      });
    }
    /**
     * Subscribe to an event, add an event listener.
     *
     * @remarks Non-function callbacks are ignored.
     * @param event - Event name.
     * @param callback - Callback method.
     */
  }, {
    key: "on",
    value: function on(event, callback) {
      if (typeof callback === "function") {
        this._subscribers[event].push(callback);
      }
      // @TODO: Maybe throw for invalid callbacks?
    }
    /**
     * Unsubscribe from an event, remove an event listener.
     *
     * @remarks If the same callback was subscribed more than once **all** occurences will be removed.
     * @param event - Event name.
     * @param callback - Callback method.
     */
  }, {
    key: "off",
    value: function off(event, callback) {
      var _context3;
      this._subscribers[event] = _filterInstanceProperty$1(_context3 = this._subscribers[event]).call(_context3, function (subscriber) {
        return subscriber !== callback;
      });
    }
  }]);
  return DataSetPart;
}();

var collection$4 = collection$2$1;
var collectionStrong$3 = collectionStrong$2$1;

// `Set` constructor
// https://tc39.es/ecma262/#sec-set-objects
collection$4('Set', function (init) {
  return function Set() { return init(this, arguments.length ? arguments[0] : undefined); };
}, collectionStrong$3);

var path$z = path$o$1;

var set$2$1 = path$z.Set;

var parent$3$1 = set$2$1;


var set$1$1 = parent$3$1;

var set$5 = set$1$1;

var _Set$1 = /*@__PURE__*/getDefaultExportFromCjs$2(set$5);

var getIterator$5 = getIterator$8;

var getIterator_1 = getIterator$5;

var parent$2$1 = getIterator_1;


var getIterator$4 = parent$2$1;

var parent$1$1 = getIterator$4;

var getIterator$3 = parent$1$1;

var parent$1c = getIterator$3;

var getIterator$2$1 = parent$1c;

var getIterator$1$1 = getIterator$2$1;

var getIterator$9 = getIterator$1$1;

var _getIterator = /*@__PURE__*/getDefaultExportFromCjs$2(getIterator$9);

var _Symbol$iterator$3;
function _createForOfIteratorHelper$2$1(o, allowArrayLike) { var it = typeof _Symbol$2 !== "undefined" && _getIteratorMethod$1(o) || o["@@iterator"]; if (!it) { if (_Array$isArray$2(o) || (it = _unsupportedIterableToArray$2$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$2$1(o, minLen) { var _context10; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$2$1(o, minLen); var n = _sliceInstanceProperty$2(_context10 = Object.prototype.toString.call(o)).call(_context10, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2$1(o, minLen); }
function _arrayLikeToArray$2$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
_Symbol$iterator$3 = _Symbol$iterator$1;
/**
 * Data stream
 *
 * @remarks
 * {@link DataStream} offers an always up to date stream of items from a {@link DataSet} or {@link DataView}.
 * That means that the stream is evaluated at the time of iteration, conversion to another data type or when {@link cache} is called, not when the {@link DataStream} was created.
 * Multiple invocations of for example {@link toItemArray} may yield different results (if the data source like for example {@link DataSet} gets modified).
 * @typeParam Item - The item type this stream is going to work with.
 */
var DataStream = /*#__PURE__*/function () {
  /**
   * Create a new data stream.
   *
   * @param pairs - The id, item pairs.
   */
  function DataStream(pairs) {
    _classCallCheck$1(this, DataStream);
    _defineProperty$1(this, "_pairs", void 0);
    this._pairs = pairs;
  }
  /**
   * Return an iterable of key, value pairs for every entry in the stream.
   */
  _createClass$1(DataStream, [{
    key: _Symbol$iterator$3,
    value:
    /*#__PURE__*/
    _regeneratorRuntime.mark(function value() {
      var _iterator, _step, _step$value, id, item;
      return _regeneratorRuntime.wrap(function value$(_context) {
        while (1) switch (_context.prev = _context.next) {
          case 0:
            _iterator = _createForOfIteratorHelper$2$1(this._pairs);
            _context.prev = 1;
            _iterator.s();
          case 3:
            if ((_step = _iterator.n()).done) {
              _context.next = 9;
              break;
            }
            _step$value = _slicedToArray$1(_step.value, 2), id = _step$value[0], item = _step$value[1];
            _context.next = 7;
            return [id, item];
          case 7:
            _context.next = 3;
            break;
          case 9:
            _context.next = 14;
            break;
          case 11:
            _context.prev = 11;
            _context.t0 = _context["catch"](1);
            _iterator.e(_context.t0);
          case 14:
            _context.prev = 14;
            _iterator.f();
            return _context.finish(14);
          case 17:
          case "end":
            return _context.stop();
        }
      }, value, this, [[1, 11, 14, 17]]);
    })
    /**
     * Return an iterable of key, value pairs for every entry in the stream.
     */
  }, {
    key: "entries",
    value:
    /*#__PURE__*/
    _regeneratorRuntime.mark(function entries() {
      var _iterator2, _step2, _step2$value, id, item;
      return _regeneratorRuntime.wrap(function entries$(_context2) {
        while (1) switch (_context2.prev = _context2.next) {
          case 0:
            _iterator2 = _createForOfIteratorHelper$2$1(this._pairs);
            _context2.prev = 1;
            _iterator2.s();
          case 3:
            if ((_step2 = _iterator2.n()).done) {
              _context2.next = 9;
              break;
            }
            _step2$value = _slicedToArray$1(_step2.value, 2), id = _step2$value[0], item = _step2$value[1];
            _context2.next = 7;
            return [id, item];
          case 7:
            _context2.next = 3;
            break;
          case 9:
            _context2.next = 14;
            break;
          case 11:
            _context2.prev = 11;
            _context2.t0 = _context2["catch"](1);
            _iterator2.e(_context2.t0);
          case 14:
            _context2.prev = 14;
            _iterator2.f();
            return _context2.finish(14);
          case 17:
          case "end":
            return _context2.stop();
        }
      }, entries, this, [[1, 11, 14, 17]]);
    })
    /**
     * Return an iterable of keys in the stream.
     */
  }, {
    key: "keys",
    value:
    /*#__PURE__*/
    _regeneratorRuntime.mark(function keys() {
      var _iterator3, _step3, _step3$value, id;
      return _regeneratorRuntime.wrap(function keys$(_context3) {
        while (1) switch (_context3.prev = _context3.next) {
          case 0:
            _iterator3 = _createForOfIteratorHelper$2$1(this._pairs);
            _context3.prev = 1;
            _iterator3.s();
          case 3:
            if ((_step3 = _iterator3.n()).done) {
              _context3.next = 9;
              break;
            }
            _step3$value = _slicedToArray$1(_step3.value, 1), id = _step3$value[0];
            _context3.next = 7;
            return id;
          case 7:
            _context3.next = 3;
            break;
          case 9:
            _context3.next = 14;
            break;
          case 11:
            _context3.prev = 11;
            _context3.t0 = _context3["catch"](1);
            _iterator3.e(_context3.t0);
          case 14:
            _context3.prev = 14;
            _iterator3.f();
            return _context3.finish(14);
          case 17:
          case "end":
            return _context3.stop();
        }
      }, keys, this, [[1, 11, 14, 17]]);
    })
    /**
     * Return an iterable of values in the stream.
     */
  }, {
    key: "values",
    value:
    /*#__PURE__*/
    _regeneratorRuntime.mark(function values() {
      var _iterator4, _step4, _step4$value, item;
      return _regeneratorRuntime.wrap(function values$(_context4) {
        while (1) switch (_context4.prev = _context4.next) {
          case 0:
            _iterator4 = _createForOfIteratorHelper$2$1(this._pairs);
            _context4.prev = 1;
            _iterator4.s();
          case 3:
            if ((_step4 = _iterator4.n()).done) {
              _context4.next = 9;
              break;
            }
            _step4$value = _slicedToArray$1(_step4.value, 2), item = _step4$value[1];
            _context4.next = 7;
            return item;
          case 7:
            _context4.next = 3;
            break;
          case 9:
            _context4.next = 14;
            break;
          case 11:
            _context4.prev = 11;
            _context4.t0 = _context4["catch"](1);
            _iterator4.e(_context4.t0);
          case 14:
            _context4.prev = 14;
            _iterator4.f();
            return _context4.finish(14);
          case 17:
          case "end":
            return _context4.stop();
        }
      }, values, this, [[1, 11, 14, 17]]);
    })
    /**
     * Return an array containing all the ids in this stream.
     *
     * @remarks
     * The array may contain duplicities.
     * @returns The array with all ids from this stream.
     */
  }, {
    key: "toIdArray",
    value: function toIdArray() {
      var _context5;
      return _mapInstanceProperty$1(_context5 = _toConsumableArray$1(this._pairs)).call(_context5, function (pair) {
        return pair[0];
      });
    }
    /**
     * Return an array containing all the items in this stream.
     *
     * @remarks
     * The array may contain duplicities.
     * @returns The array with all items from this stream.
     */
  }, {
    key: "toItemArray",
    value: function toItemArray() {
      var _context6;
      return _mapInstanceProperty$1(_context6 = _toConsumableArray$1(this._pairs)).call(_context6, function (pair) {
        return pair[1];
      });
    }
    /**
     * Return an array containing all the entries in this stream.
     *
     * @remarks
     * The array may contain duplicities.
     * @returns The array with all entries from this stream.
     */
  }, {
    key: "toEntryArray",
    value: function toEntryArray() {
      return _toConsumableArray$1(this._pairs);
    }
    /**
     * Return an object map containing all the items in this stream accessible by ids.
     *
     * @remarks
     * In case of duplicate ids (coerced to string so `7 == '7'`) the last encoutered appears in the returned object.
     * @returns The object map of all id → item pairs from this stream.
     */
  }, {
    key: "toObjectMap",
    value: function toObjectMap() {
      var map = _Object$create$1$1(null);
      var _iterator5 = _createForOfIteratorHelper$2$1(this._pairs),
        _step5;
      try {
        for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
          var _step5$value = _slicedToArray$1(_step5.value, 2),
            id = _step5$value[0],
            item = _step5$value[1];
          map[id] = item;
        }
      } catch (err) {
        _iterator5.e(err);
      } finally {
        _iterator5.f();
      }
      return map;
    }
    /**
     * Return a map containing all the items in this stream accessible by ids.
     *
     * @returns The map of all id → item pairs from this stream.
     */
  }, {
    key: "toMap",
    value: function toMap() {
      return new _Map$1(this._pairs);
    }
    /**
     * Return a set containing all the (unique) ids in this stream.
     *
     * @returns The set of all ids from this stream.
     */
  }, {
    key: "toIdSet",
    value: function toIdSet() {
      return new _Set$1(this.toIdArray());
    }
    /**
     * Return a set containing all the (unique) items in this stream.
     *
     * @returns The set of all items from this stream.
     */
  }, {
    key: "toItemSet",
    value: function toItemSet() {
      return new _Set$1(this.toItemArray());
    }
    /**
     * Cache the items from this stream.
     *
     * @remarks
     * This method allows for items to be fetched immediatelly and used (possibly multiple times) later.
     * It can also be used to optimize performance as {@link DataStream} would otherwise reevaluate everything upon each iteration.
     *
     * ## Example
     * ```javascript
     * const ds = new DataSet([…])
     *
     * const cachedStream = ds.stream()
     *   .filter(…)
     *   .sort(…)
     *   .map(…)
     *   .cached(…) // Data are fetched, processed and cached here.
     *
     * ds.clear()
     * chachedStream // Still has all the items.
     * ```
     * @returns A new {@link DataStream} with cached items (detached from the original {@link DataSet}).
     */
  }, {
    key: "cache",
    value: function cache() {
      return new DataStream(_toConsumableArray$1(this._pairs));
    }
    /**
     * Get the distinct values of given property.
     *
     * @param callback - The function that picks and possibly converts the property.
     * @typeParam T - The type of the distinct value.
     * @returns A set of all distinct properties.
     */
  }, {
    key: "distinct",
    value: function distinct(callback) {
      var set = new _Set$1();
      var _iterator6 = _createForOfIteratorHelper$2$1(this._pairs),
        _step6;
      try {
        for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
          var _step6$value = _slicedToArray$1(_step6.value, 2),
            id = _step6$value[0],
            item = _step6$value[1];
          set.add(callback(item, id));
        }
      } catch (err) {
        _iterator6.e(err);
      } finally {
        _iterator6.f();
      }
      return set;
    }
    /**
     * Filter the items of the stream.
     *
     * @param callback - The function that decides whether an item will be included.
     * @returns A new data stream with the filtered items.
     */
  }, {
    key: "filter",
    value: function filter(callback) {
      var pairs = this._pairs;
      return new DataStream(_defineProperty$1({}, _Symbol$iterator$1, /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
        var _iterator7, _step7, _step7$value, id, item;
        return _regeneratorRuntime.wrap(function _callee$(_context7) {
          while (1) switch (_context7.prev = _context7.next) {
            case 0:
              _iterator7 = _createForOfIteratorHelper$2$1(pairs);
              _context7.prev = 1;
              _iterator7.s();
            case 3:
              if ((_step7 = _iterator7.n()).done) {
                _context7.next = 10;
                break;
              }
              _step7$value = _slicedToArray$1(_step7.value, 2), id = _step7$value[0], item = _step7$value[1];
              if (!callback(item, id)) {
                _context7.next = 8;
                break;
              }
              _context7.next = 8;
              return [id, item];
            case 8:
              _context7.next = 3;
              break;
            case 10:
              _context7.next = 15;
              break;
            case 12:
              _context7.prev = 12;
              _context7.t0 = _context7["catch"](1);
              _iterator7.e(_context7.t0);
            case 15:
              _context7.prev = 15;
              _iterator7.f();
              return _context7.finish(15);
            case 18:
            case "end":
              return _context7.stop();
          }
        }, _callee, null, [[1, 12, 15, 18]]);
      })));
    }
    /**
     * Execute a callback for each item of the stream.
     *
     * @param callback - The function that will be invoked for each item.
     */
  }, {
    key: "forEach",
    value: function forEach(callback) {
      var _iterator8 = _createForOfIteratorHelper$2$1(this._pairs),
        _step8;
      try {
        for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
          var _step8$value = _slicedToArray$1(_step8.value, 2),
            id = _step8$value[0],
            item = _step8$value[1];
          callback(item, id);
        }
      } catch (err) {
        _iterator8.e(err);
      } finally {
        _iterator8.f();
      }
    }
    /**
     * Map the items into a different type.
     *
     * @param callback - The function that does the conversion.
     * @typeParam Mapped - The type of the item after mapping.
     * @returns A new data stream with the mapped items.
     */
  }, {
    key: "map",
    value: function map(callback) {
      var pairs = this._pairs;
      return new DataStream(_defineProperty$1({}, _Symbol$iterator$1, /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
        var _iterator9, _step9, _step9$value, id, item;
        return _regeneratorRuntime.wrap(function _callee2$(_context8) {
          while (1) switch (_context8.prev = _context8.next) {
            case 0:
              _iterator9 = _createForOfIteratorHelper$2$1(pairs);
              _context8.prev = 1;
              _iterator9.s();
            case 3:
              if ((_step9 = _iterator9.n()).done) {
                _context8.next = 9;
                break;
              }
              _step9$value = _slicedToArray$1(_step9.value, 2), id = _step9$value[0], item = _step9$value[1];
              _context8.next = 7;
              return [id, callback(item, id)];
            case 7:
              _context8.next = 3;
              break;
            case 9:
              _context8.next = 14;
              break;
            case 11:
              _context8.prev = 11;
              _context8.t0 = _context8["catch"](1);
              _iterator9.e(_context8.t0);
            case 14:
              _context8.prev = 14;
              _iterator9.f();
              return _context8.finish(14);
            case 17:
            case "end":
              return _context8.stop();
          }
        }, _callee2, null, [[1, 11, 14, 17]]);
      })));
    }
    /**
     * Get the item with the maximum value of given property.
     *
     * @param callback - The function that picks and possibly converts the property.
     * @returns The item with the maximum if found otherwise null.
     */
  }, {
    key: "max",
    value: function max(callback) {
      var iter = _getIterator(this._pairs);
      var curr = iter.next();
      if (curr.done) {
        return null;
      }
      var maxItem = curr.value[1];
      var maxValue = callback(curr.value[1], curr.value[0]);
      while (!(curr = iter.next()).done) {
        var _curr$value = _slicedToArray$1(curr.value, 2),
          id = _curr$value[0],
          item = _curr$value[1];
        var _value = callback(item, id);
        if (_value > maxValue) {
          maxValue = _value;
          maxItem = item;
        }
      }
      return maxItem;
    }
    /**
     * Get the item with the minimum value of given property.
     *
     * @param callback - The function that picks and possibly converts the property.
     * @returns The item with the minimum if found otherwise null.
     */
  }, {
    key: "min",
    value: function min(callback) {
      var iter = _getIterator(this._pairs);
      var curr = iter.next();
      if (curr.done) {
        return null;
      }
      var minItem = curr.value[1];
      var minValue = callback(curr.value[1], curr.value[0]);
      while (!(curr = iter.next()).done) {
        var _curr$value2 = _slicedToArray$1(curr.value, 2),
          id = _curr$value2[0],
          item = _curr$value2[1];
        var _value2 = callback(item, id);
        if (_value2 < minValue) {
          minValue = _value2;
          minItem = item;
        }
      }
      return minItem;
    }
    /**
     * Reduce the items into a single value.
     *
     * @param callback - The function that does the reduction.
     * @param accumulator - The initial value of the accumulator.
     * @typeParam T - The type of the accumulated value.
     * @returns The reduced value.
     */
  }, {
    key: "reduce",
    value: function reduce(callback, accumulator) {
      var _iterator10 = _createForOfIteratorHelper$2$1(this._pairs),
        _step10;
      try {
        for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
          var _step10$value = _slicedToArray$1(_step10.value, 2),
            id = _step10$value[0],
            item = _step10$value[1];
          accumulator = callback(accumulator, item, id);
        }
      } catch (err) {
        _iterator10.e(err);
      } finally {
        _iterator10.f();
      }
      return accumulator;
    }
    /**
     * Sort the items.
     *
     * @param callback - Item comparator.
     * @returns A new stream with sorted items.
     */
  }, {
    key: "sort",
    value: function sort(callback) {
      var _this = this;
      return new DataStream(_defineProperty$1({}, _Symbol$iterator$1, function () {
        var _context9;
        return _getIterator(_sortInstanceProperty$1(_context9 = _toConsumableArray$1(_this._pairs)).call(_context9, function (_ref, _ref2) {
          var _ref3 = _slicedToArray$1(_ref, 2),
            idA = _ref3[0],
            itemA = _ref3[1];
          var _ref4 = _slicedToArray$1(_ref2, 2),
            idB = _ref4[0],
            itemB = _ref4[1];
          return callback(itemA, itemB, idA, idB);
        }));
      }));
    }
  }]);
  return DataStream;
}();

function ownKeys$a(e, r) { var t = _Object$keys$1(e); if (_Object$getOwnPropertySymbols$1) { var o = _Object$getOwnPropertySymbols$1(e); r && (o = _filterInstanceProperty$1(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor$2(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread$4(e) { for (var r = 1; r < arguments.length; r++) { var _context10, _context11; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty$1(_context10 = ownKeys$a(Object(t), !0)).call(_context10, function (r) { _defineProperty$1(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors$1 ? _Object$defineProperties$1(e, _Object$getOwnPropertyDescriptors$1(t)) : _forEachInstanceProperty$1(_context11 = ownKeys$a(Object(t))).call(_context11, function (r) { _Object$defineProperty$2(e, r, _Object$getOwnPropertyDescriptor$2(t, r)); }); } return e; }
function _createForOfIteratorHelper$1$1(o, allowArrayLike) { var it = typeof _Symbol$2 !== "undefined" && _getIteratorMethod$1(o) || o["@@iterator"]; if (!it) { if (_Array$isArray$2(o) || (it = _unsupportedIterableToArray$1$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$1$1(o, minLen) { var _context9; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1$1(o, minLen); var n = _sliceInstanceProperty$2(_context9 = Object.prototype.toString.call(o)).call(_context9, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1$1(o, minLen); }
function _arrayLikeToArray$1$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _createSuper$1$1(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$1$1(); return function _createSuperInternal() { var Super = _getPrototypeOf$1(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf$1(this).constructor; result = _Reflect$construct$1(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn$1(this, result); }; }
function _isNativeReflectConstruct$1$1() { if (typeof Reflect === "undefined" || !_Reflect$construct$1) return false; if (_Reflect$construct$1.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct$1(Boolean, [], function () {})); return true; } catch (e) { return false; } }
/**
 * Add an id to given item if it doesn't have one already.
 *
 * @remarks
 * The item will be modified.
 * @param item - The item that will have an id after a call to this function.
 * @param idProp - The key of the id property.
 * @typeParam Item - Item type that may or may not have an id.
 * @typeParam IdProp - Name of the property that contains the id.
 * @returns true
 */
function ensureFullItem(item, idProp) {
  if (item[idProp] == null) {
    // generate an id
    item[idProp] = v4$1();
  }
  return item;
}
/**
 * # DataSet
 *
 * Vis.js comes with a flexible DataSet, which can be used to hold and
 * manipulate unstructured data and listen for changes in the data. The DataSet
 * is key/value based. Data items can be added, updated and removed from the
 * DataSet, and one can subscribe to changes in the DataSet. The data in the
 * DataSet can be filtered and ordered. Data can be normalized when appending it
 * to the DataSet as well.
 *
 * ## Example
 *
 * The following example shows how to use a DataSet.
 *
 * ```javascript
 * // create a DataSet
 * var options = {};
 * var data = new vis.DataSet(options);
 *
 * // add items
 * // note that the data items can contain different properties and data formats
 * data.add([
 *   {id: 1, text: 'item 1', date: new Date(2013, 6, 20), group: 1, first: true},
 *   {id: 2, text: 'item 2', date: '2013-06-23', group: 2},
 *   {id: 3, text: 'item 3', date: '2013-06-25', group: 2},
 *   {id: 4, text: 'item 4'}
 * ]);
 *
 * // subscribe to any change in the DataSet
 * data.on('*', function (event, properties, senderId) {
 *   console.log('event', event, properties);
 * });
 *
 * // update an existing item
 * data.update({id: 2, group: 1});
 *
 * // remove an item
 * data.remove(4);
 *
 * // get all ids
 * var ids = data.getIds();
 * console.log('ids', ids);
 *
 * // get a specific item
 * var item1 = data.get(1);
 * console.log('item1', item1);
 *
 * // retrieve a filtered subset of the data
 * var items = data.get({
 *   filter: function (item) {
 *     return item.group == 1;
 *   }
 * });
 * console.log('filtered items', items);
 * ```
 *
 * @typeParam Item - Item type that may or may not have an id.
 * @typeParam IdProp - Name of the property that contains the id.
 */
var DataSet = /*#__PURE__*/function (_DataSetPart) {
  _inherits$1(DataSet, _DataSetPart);
  var _super = _createSuper$1$1(DataSet);
  /**
   * Construct a new DataSet.
   *
   * @param data - Initial data or options.
   * @param options - Options (type error if data is also options).
   */
  function DataSet(data, options) {
    var _this;
    _classCallCheck$1(this, DataSet);
    _this = _super.call(this);
    // correctly read optional arguments
    /** Flush all queued calls. */
    _defineProperty$1(_assertThisInitialized$2(_this), "flush", void 0);
    /** @inheritDoc */
    _defineProperty$1(_assertThisInitialized$2(_this), "length", void 0);
    _defineProperty$1(_assertThisInitialized$2(_this), "_options", void 0);
    _defineProperty$1(_assertThisInitialized$2(_this), "_data", void 0);
    _defineProperty$1(_assertThisInitialized$2(_this), "_idProp", void 0);
    _defineProperty$1(_assertThisInitialized$2(_this), "_queue", null);
    if (data && !_Array$isArray$2(data)) {
      options = data;
      data = [];
    }
    _this._options = options || {};
    _this._data = new _Map$1(); // map with data indexed by id
    _this.length = 0; // number of items in the DataSet
    _this._idProp = _this._options.fieldId || "id"; // name of the field containing id
    // add initial data when provided
    if (data && data.length) {
      _this.add(data);
    }
    _this.setOptions(options);
    return _this;
  }
  /**
   * Set new options.
   *
   * @param options - The new options.
   */
  _createClass$1(DataSet, [{
    key: "idProp",
    get:
    /** @inheritDoc */
    function get() {
      return this._idProp;
    }
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      if (options && options.queue !== undefined) {
        if (options.queue === false) {
          // delete queue if loaded
          if (this._queue) {
            this._queue.destroy();
            this._queue = null;
          }
        } else {
          // create queue and update its options
          if (!this._queue) {
            this._queue = Queue.extend(this, {
              replace: ["add", "update", "remove"]
            });
          }
          if (options.queue && _typeof$1(options.queue) === "object") {
            this._queue.setOptions(options.queue);
          }
        }
      }
    }
    /**
     * Add a data item or an array with items.
     *
     * After the items are added to the DataSet, the DataSet will trigger an event `add`. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
     *
     * ## Example
     *
     * ```javascript
     * // create a DataSet
     * const data = new vis.DataSet()
     *
     * // add items
     * const ids = data.add([
     *   { id: 1, text: 'item 1' },
     *   { id: 2, text: 'item 2' },
     *   { text: 'item without an id' }
     * ])
     *
     * console.log(ids) // [1, 2, '<UUIDv4>']
     * ```
     *
     * @param data - Items to be added (ids will be generated if missing).
     * @param senderId - Sender id.
     * @returns addedIds - Array with the ids (generated if not present) of the added items.
     * @throws When an item with the same id as any of the added items already exists.
     */
  }, {
    key: "add",
    value: function add(data, senderId) {
      var _this2 = this;
      var addedIds = [];
      var id;
      if (_Array$isArray$2(data)) {
        // Array
        var idsToAdd = _mapInstanceProperty$1(data).call(data, function (d) {
          return d[_this2._idProp];
        });
        if (_someInstanceProperty$1(idsToAdd).call(idsToAdd, function (id) {
          return _this2._data.has(id);
        })) {
          throw new Error("A duplicate id was found in the parameter array.");
        }
        for (var i = 0, len = data.length; i < len; i++) {
          id = this._addItem(data[i]);
          addedIds.push(id);
        }
      } else if (data && _typeof$1(data) === "object") {
        // Single item
        id = this._addItem(data);
        addedIds.push(id);
      } else {
        throw new Error("Unknown dataType");
      }
      if (addedIds.length) {
        this._trigger("add", {
          items: addedIds
        }, senderId);
      }
      return addedIds;
    }
    /**
     * Update existing items. When an item does not exist, it will be created.
     *
     * @remarks
     * The provided properties will be merged in the existing item. When an item does not exist, it will be created.
     *
     * After the items are updated, the DataSet will trigger an event `add` for the added items, and an event `update`. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
     *
     * ## Example
     *
     * ```javascript
     * // create a DataSet
     * const data = new vis.DataSet([
     *   { id: 1, text: 'item 1' },
     *   { id: 2, text: 'item 2' },
     *   { id: 3, text: 'item 3' }
     * ])
     *
     * // update items
     * const ids = data.update([
     *   { id: 2, text: 'item 2 (updated)' },
     *   { id: 4, text: 'item 4 (new)' }
     * ])
     *
     * console.log(ids) // [2, 4]
     * ```
     *
     * ## Warning for TypeScript users
     * This method may introduce partial items into the data set. Use add or updateOnly instead for better type safety.
     * @param data - Items to be updated (if the id is already present) or added (if the id is missing).
     * @param senderId - Sender id.
     * @returns updatedIds - The ids of the added (these may be newly generated if there was no id in the item from the data) or updated items.
     * @throws When the supplied data is neither an item nor an array of items.
     */
  }, {
    key: "update",
    value: function update(data, senderId) {
      var _this3 = this;
      var addedIds = [];
      var updatedIds = [];
      var oldData = [];
      var updatedData = [];
      var idProp = this._idProp;
      var addOrUpdate = function addOrUpdate(item) {
        var origId = item[idProp];
        if (origId != null && _this3._data.has(origId)) {
          var fullItem = item; // it has an id, therefore it is a fullitem
          var oldItem = _Object$assign$1({}, _this3._data.get(origId));
          // update item
          var id = _this3._updateItem(fullItem);
          updatedIds.push(id);
          updatedData.push(fullItem);
          oldData.push(oldItem);
        } else {
          // add new item
          var _id = _this3._addItem(item);
          addedIds.push(_id);
        }
      };
      if (_Array$isArray$2(data)) {
        // Array
        for (var i = 0, len = data.length; i < len; i++) {
          if (data[i] && _typeof$1(data[i]) === "object") {
            addOrUpdate(data[i]);
          } else {
            console.warn("Ignoring input item, which is not an object at index " + i);
          }
        }
      } else if (data && _typeof$1(data) === "object") {
        // Single item
        addOrUpdate(data);
      } else {
        throw new Error("Unknown dataType");
      }
      if (addedIds.length) {
        this._trigger("add", {
          items: addedIds
        }, senderId);
      }
      if (updatedIds.length) {
        var props = {
          items: updatedIds,
          oldData: oldData,
          data: updatedData
        };
        // TODO: remove deprecated property 'data' some day
        //Object.defineProperty(props, 'data', {
        //  'get': (function() {
        //    console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data');
        //    return updatedData;
        //  }).bind(this)
        //});
        this._trigger("update", props, senderId);
      }
      return _concatInstanceProperty$1(addedIds).call(addedIds, updatedIds);
    }
    /**
     * Update existing items. When an item does not exist, an error will be thrown.
     *
     * @remarks
     * The provided properties will be deeply merged into the existing item.
     * When an item does not exist (id not present in the data set or absent), an error will be thrown and nothing will be changed.
     *
     * After the items are updated, the DataSet will trigger an event `update`.
     * When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
     *
     * ## Example
     *
     * ```javascript
     * // create a DataSet
     * const data = new vis.DataSet([
     *   { id: 1, text: 'item 1' },
     *   { id: 2, text: 'item 2' },
     *   { id: 3, text: 'item 3' },
     * ])
     *
     * // update items
     * const ids = data.update([
     *   { id: 2, text: 'item 2 (updated)' }, // works
     *   // { id: 4, text: 'item 4 (new)' }, // would throw
     *   // { text: 'item 4 (new)' }, // would also throw
     * ])
     *
     * console.log(ids) // [2]
     * ```
     * @param data - Updates (the id and optionally other props) to the items in this data set.
     * @param senderId - Sender id.
     * @returns updatedIds - The ids of the updated items.
     * @throws When the supplied data is neither an item nor an array of items, when the ids are missing.
     */
  }, {
    key: "updateOnly",
    value: function updateOnly(data, senderId) {
      var _context,
        _this4 = this;
      if (!_Array$isArray$2(data)) {
        data = [data];
      }
      var updateEventData = _mapInstanceProperty$1(_context = _mapInstanceProperty$1(data).call(data, function (update) {
        var oldData = _this4._data.get(update[_this4._idProp]);
        if (oldData == null) {
          throw new Error("Updating non-existent items is not allowed.");
        }
        return {
          oldData: oldData,
          update: update
        };
      })).call(_context, function (_ref) {
        var oldData = _ref.oldData,
          update = _ref.update;
        var id = oldData[_this4._idProp];
        var updatedData = pureDeepObjectAssign(oldData, update);
        _this4._data.set(id, updatedData);
        return {
          id: id,
          oldData: oldData,
          updatedData: updatedData
        };
      });
      if (updateEventData.length) {
        var props = {
          items: _mapInstanceProperty$1(updateEventData).call(updateEventData, function (value) {
            return value.id;
          }),
          oldData: _mapInstanceProperty$1(updateEventData).call(updateEventData, function (value) {
            return value.oldData;
          }),
          data: _mapInstanceProperty$1(updateEventData).call(updateEventData, function (value) {
            return value.updatedData;
          })
        };
        // TODO: remove deprecated property 'data' some day
        //Object.defineProperty(props, 'data', {
        //  'get': (function() {
        //    console.warn('Property data is deprecated. Use DataSet.get(ids) to retrieve the new data, use the oldData property on this object to get the old data');
        //    return updatedData;
        //  }).bind(this)
        //});
        this._trigger("update", props, senderId);
        return props.items;
      } else {
        return [];
      }
    }
    /** @inheritDoc */
  }, {
    key: "get",
    value: function get(first, second) {
      // @TODO: Woudn't it be better to split this into multiple methods?
      // parse the arguments
      var id = undefined;
      var ids = undefined;
      var options = undefined;
      if (isId(first)) {
        // get(id [, options])
        id = first;
        options = second;
      } else if (_Array$isArray$2(first)) {
        // get(ids [, options])
        ids = first;
        options = second;
      } else {
        // get([, options])
        options = first;
      }
      // determine the return type
      var returnType = options && options.returnType === "Object" ? "Object" : "Array";
      // @TODO: WTF is this? Or am I missing something?
      // var returnType
      // if (options && options.returnType) {
      //   var allowedValues = ['Array', 'Object']
      //   returnType =
      //     allowedValues.indexOf(options.returnType) == -1
      //       ? 'Array'
      //       : options.returnType
      // } else {
      //   returnType = 'Array'
      // }
      // build options
      var filter = options && _filterInstanceProperty$1(options);
      var items = [];
      var item = undefined;
      var itemIds = undefined;
      var itemId = undefined;
      // convert items
      if (id != null) {
        // return a single item
        item = this._data.get(id);
        if (item && filter && !filter(item)) {
          item = undefined;
        }
      } else if (ids != null) {
        // return a subset of items
        for (var i = 0, len = ids.length; i < len; i++) {
          item = this._data.get(ids[i]);
          if (item != null && (!filter || filter(item))) {
            items.push(item);
          }
        }
      } else {
        var _context2;
        // return all items
        itemIds = _toConsumableArray$1(_keysInstanceProperty(_context2 = this._data).call(_context2));
        for (var _i = 0, _len = itemIds.length; _i < _len; _i++) {
          itemId = itemIds[_i];
          item = this._data.get(itemId);
          if (item != null && (!filter || filter(item))) {
            items.push(item);
          }
        }
      }
      // order the results
      if (options && options.order && id == undefined) {
        this._sort(items, options.order);
      }
      // filter fields of the items
      if (options && options.fields) {
        var fields = options.fields;
        if (id != undefined && item != null) {
          item = this._filterFields(item, fields);
        } else {
          for (var _i2 = 0, _len2 = items.length; _i2 < _len2; _i2++) {
            items[_i2] = this._filterFields(items[_i2], fields);
          }
        }
      }
      // return the results
      if (returnType == "Object") {
        var result = {};
        for (var _i3 = 0, _len3 = items.length; _i3 < _len3; _i3++) {
          var resultant = items[_i3];
          // @TODO: Shoudn't this be this._fieldId?
          // result[resultant.id] = resultant
          var _id2 = resultant[this._idProp];
          result[_id2] = resultant;
        }
        return result;
      } else {
        if (id != null) {
          var _item;
          // a single item
          return (_item = item) !== null && _item !== void 0 ? _item : null;
        } else {
          // just return our array
          return items;
        }
      }
    }
    /** @inheritDoc */
  }, {
    key: "getIds",
    value: function getIds(options) {
      var data = this._data;
      var filter = options && _filterInstanceProperty$1(options);
      var order = options && options.order;
      var itemIds = _toConsumableArray$1(_keysInstanceProperty(data).call(data));
      var ids = [];
      if (filter) {
        // get filtered items
        if (order) {
          // create ordered list
          var items = [];
          for (var i = 0, len = itemIds.length; i < len; i++) {
            var id = itemIds[i];
            var item = this._data.get(id);
            if (item != null && filter(item)) {
              items.push(item);
            }
          }
          this._sort(items, order);
          for (var _i4 = 0, _len4 = items.length; _i4 < _len4; _i4++) {
            ids.push(items[_i4][this._idProp]);
          }
        } else {
          // create unordered list
          for (var _i5 = 0, _len5 = itemIds.length; _i5 < _len5; _i5++) {
            var _id3 = itemIds[_i5];
            var _item2 = this._data.get(_id3);
            if (_item2 != null && filter(_item2)) {
              ids.push(_item2[this._idProp]);
            }
          }
        }
      } else {
        // get all items
        if (order) {
          // create an ordered list
          var _items = [];
          for (var _i6 = 0, _len6 = itemIds.length; _i6 < _len6; _i6++) {
            var _id4 = itemIds[_i6];
            _items.push(data.get(_id4));
          }
          this._sort(_items, order);
          for (var _i7 = 0, _len7 = _items.length; _i7 < _len7; _i7++) {
            ids.push(_items[_i7][this._idProp]);
          }
        } else {
          // create unordered list
          for (var _i8 = 0, _len8 = itemIds.length; _i8 < _len8; _i8++) {
            var _id5 = itemIds[_i8];
            var _item3 = data.get(_id5);
            if (_item3 != null) {
              ids.push(_item3[this._idProp]);
            }
          }
        }
      }
      return ids;
    }
    /** @inheritDoc */
  }, {
    key: "getDataSet",
    value: function getDataSet() {
      return this;
    }
    /** @inheritDoc */
  }, {
    key: "forEach",
    value: function forEach(callback, options) {
      var filter = options && _filterInstanceProperty$1(options);
      var data = this._data;
      var itemIds = _toConsumableArray$1(_keysInstanceProperty(data).call(data));
      if (options && options.order) {
        // execute forEach on ordered list
        var items = this.get(options);
        for (var i = 0, len = items.length; i < len; i++) {
          var item = items[i];
          var id = item[this._idProp];
          callback(item, id);
        }
      } else {
        // unordered
        for (var _i9 = 0, _len9 = itemIds.length; _i9 < _len9; _i9++) {
          var _id6 = itemIds[_i9];
          var _item4 = this._data.get(_id6);
          if (_item4 != null && (!filter || filter(_item4))) {
            callback(_item4, _id6);
          }
        }
      }
    }
    /** @inheritDoc */
  }, {
    key: "map",
    value: function map(callback, options) {
      var filter = options && _filterInstanceProperty$1(options);
      var mappedItems = [];
      var data = this._data;
      var itemIds = _toConsumableArray$1(_keysInstanceProperty(data).call(data));
      // convert and filter items
      for (var i = 0, len = itemIds.length; i < len; i++) {
        var id = itemIds[i];
        var item = this._data.get(id);
        if (item != null && (!filter || filter(item))) {
          mappedItems.push(callback(item, id));
        }
      }
      // order items
      if (options && options.order) {
        this._sort(mappedItems, options.order);
      }
      return mappedItems;
    }
    /**
     * Filter the fields of an item.
     *
     * @param item - The item whose fields should be filtered.
     * @param fields - The names of the fields that will be kept.
     * @typeParam K - Field name type.
     * @returns The item without any additional fields.
     */
  }, {
    key: "_filterFields",
    value: function _filterFields(item, fields) {
      var _context3;
      if (!item) {
        // item is null
        return item;
      }
      return _reduceInstanceProperty$1(_context3 = _Array$isArray$2(fields) ?
      // Use the supplied array
      fields :
      // Use the keys of the supplied object
      _Object$keys$1(fields)).call(_context3, function (filteredItem, field) {
        filteredItem[field] = item[field];
        return filteredItem;
      }, {});
    }
    /**
     * Sort the provided array with items.
     *
     * @param items - Items to be sorted in place.
     * @param order - A field name or custom sort function.
     * @typeParam T - The type of the items in the items array.
     */
  }, {
    key: "_sort",
    value: function _sort(items, order) {
      if (typeof order === "string") {
        // order by provided field name
        var name = order; // field name
        _sortInstanceProperty$1(items).call(items, function (a, b) {
          // @TODO: How to treat missing properties?
          var av = a[name];
          var bv = b[name];
          return av > bv ? 1 : av < bv ? -1 : 0;
        });
      } else if (typeof order === "function") {
        // order by sort function
        _sortInstanceProperty$1(items).call(items, order);
      } else {
        // TODO: extend order by an Object {field:string, direction:string}
        //       where direction can be 'asc' or 'desc'
        throw new TypeError("Order must be a function or a string");
      }
    }
    /**
     * Remove an item or multiple items by “reference” (only the id is used) or by id.
     *
     * The method ignores removal of non-existing items, and returns an array containing the ids of the items which are actually removed from the DataSet.
     *
     * After the items are removed, the DataSet will trigger an event `remove` for the removed items. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
     *
     * ## Example
     * ```javascript
     * // create a DataSet
     * const data = new vis.DataSet([
     *   { id: 1, text: 'item 1' },
     *   { id: 2, text: 'item 2' },
     *   { id: 3, text: 'item 3' }
     * ])
     *
     * // remove items
     * const ids = data.remove([2, { id: 3 }, 4])
     *
     * console.log(ids) // [2, 3]
     * ```
     *
     * @param id - One or more items or ids of items to be removed.
     * @param senderId - Sender id.
     * @returns The ids of the removed items.
     */
  }, {
    key: "remove",
    value: function remove(id, senderId) {
      var removedIds = [];
      var removedItems = [];
      // force everything to be an array for simplicity
      var ids = _Array$isArray$2(id) ? id : [id];
      for (var i = 0, len = ids.length; i < len; i++) {
        var item = this._remove(ids[i]);
        if (item) {
          var itemId = item[this._idProp];
          if (itemId != null) {
            removedIds.push(itemId);
            removedItems.push(item);
          }
        }
      }
      if (removedIds.length) {
        this._trigger("remove", {
          items: removedIds,
          oldData: removedItems
        }, senderId);
      }
      return removedIds;
    }
    /**
     * Remove an item by its id or reference.
     *
     * @param id - Id of an item or the item itself.
     * @returns The removed item if removed, null otherwise.
     */
  }, {
    key: "_remove",
    value: function _remove(id) {
      // @TODO: It origianlly returned the item although the docs say id.
      // The code expects the item, so probably an error in the docs.
      var ident;
      // confirm the id to use based on the args type
      if (isId(id)) {
        ident = id;
      } else if (id && _typeof$1(id) === "object") {
        ident = id[this._idProp]; // look for the identifier field using ._idProp
      }
      // do the removing if the item is found
      if (ident != null && this._data.has(ident)) {
        var item = this._data.get(ident) || null;
        this._data.delete(ident);
        --this.length;
        return item;
      }
      return null;
    }
    /**
     * Clear the entire data set.
     *
     * After the items are removed, the {@link DataSet} will trigger an event `remove` for all removed items. When a `senderId` is provided, this id will be passed with the triggered event to all subscribers.
     *
     * @param senderId - Sender id.
     * @returns removedIds - The ids of all removed items.
     */
  }, {
    key: "clear",
    value: function clear(senderId) {
      var _context4;
      var ids = _toConsumableArray$1(_keysInstanceProperty(_context4 = this._data).call(_context4));
      var items = [];
      for (var i = 0, len = ids.length; i < len; i++) {
        items.push(this._data.get(ids[i]));
      }
      this._data.clear();
      this.length = 0;
      this._trigger("remove", {
        items: ids,
        oldData: items
      }, senderId);
      return ids;
    }
    /**
     * Find the item with maximum value of a specified field.
     *
     * @param field - Name of the property that should be searched for max value.
     * @returns Item containing max value, or null if no items.
     */
  }, {
    key: "max",
    value: function max(field) {
      var _context5;
      var max = null;
      var maxField = null;
      var _iterator = _createForOfIteratorHelper$1$1(_valuesInstanceProperty$1(_context5 = this._data).call(_context5)),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var item = _step.value;
          var itemField = item[field];
          if (typeof itemField === "number" && (maxField == null || itemField > maxField)) {
            max = item;
            maxField = itemField;
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
      return max || null;
    }
    /**
     * Find the item with minimum value of a specified field.
     *
     * @param field - Name of the property that should be searched for min value.
     * @returns Item containing min value, or null if no items.
     */
  }, {
    key: "min",
    value: function min(field) {
      var _context6;
      var min = null;
      var minField = null;
      var _iterator2 = _createForOfIteratorHelper$1$1(_valuesInstanceProperty$1(_context6 = this._data).call(_context6)),
        _step2;
      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var item = _step2.value;
          var itemField = item[field];
          if (typeof itemField === "number" && (minField == null || itemField < minField)) {
            min = item;
            minField = itemField;
          }
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }
      return min || null;
    }
    /**
     * Find all distinct values of a specified field
     *
     * @param prop - The property name whose distinct values should be returned.
     * @returns Unordered array containing all distinct values. Items without specified property are ignored.
     */
  }, {
    key: "distinct",
    value: function distinct(prop) {
      var data = this._data;
      var itemIds = _toConsumableArray$1(_keysInstanceProperty(data).call(data));
      var values = [];
      var count = 0;
      for (var i = 0, len = itemIds.length; i < len; i++) {
        var id = itemIds[i];
        var item = data.get(id);
        var value = item[prop];
        var exists = false;
        for (var j = 0; j < count; j++) {
          if (values[j] == value) {
            exists = true;
            break;
          }
        }
        if (!exists && value !== undefined) {
          values[count] = value;
          count++;
        }
      }
      return values;
    }
    /**
     * Add a single item. Will fail when an item with the same id already exists.
     *
     * @param item - A new item to be added.
     * @returns Added item's id. An id is generated when it is not present in the item.
     */
  }, {
    key: "_addItem",
    value: function _addItem(item) {
      var fullItem = ensureFullItem(item, this._idProp);
      var id = fullItem[this._idProp];
      // check whether this id is already taken
      if (this._data.has(id)) {
        // item already exists
        throw new Error("Cannot add item: item with id " + id + " already exists");
      }
      this._data.set(id, fullItem);
      ++this.length;
      return id;
    }
    /**
     * Update a single item: merge with existing item.
     * Will fail when the item has no id, or when there does not exist an item with the same id.
     *
     * @param update - The new item
     * @returns The id of the updated item.
     */
  }, {
    key: "_updateItem",
    value: function _updateItem(update) {
      var id = update[this._idProp];
      if (id == null) {
        throw new Error("Cannot update item: item has no id (item: " + _JSON$stringify$1(update) + ")");
      }
      var item = this._data.get(id);
      if (!item) {
        // item doesn't exist
        throw new Error("Cannot update item: no item with id " + id + " found");
      }
      this._data.set(id, _objectSpread$4(_objectSpread$4({}, item), update));
      return id;
    }
    /** @inheritDoc */
  }, {
    key: "stream",
    value: function stream(ids) {
      if (ids) {
        var data = this._data;
        return new DataStream(_defineProperty$1({}, _Symbol$iterator$1, /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
          var _iterator3, _step3, id, item;
          return _regeneratorRuntime.wrap(function _callee$(_context7) {
            while (1) switch (_context7.prev = _context7.next) {
              case 0:
                _iterator3 = _createForOfIteratorHelper$1$1(ids);
                _context7.prev = 1;
                _iterator3.s();
              case 3:
                if ((_step3 = _iterator3.n()).done) {
                  _context7.next = 11;
                  break;
                }
                id = _step3.value;
                item = data.get(id);
                if (!(item != null)) {
                  _context7.next = 9;
                  break;
                }
                _context7.next = 9;
                return [id, item];
              case 9:
                _context7.next = 3;
                break;
              case 11:
                _context7.next = 16;
                break;
              case 13:
                _context7.prev = 13;
                _context7.t0 = _context7["catch"](1);
                _iterator3.e(_context7.t0);
              case 16:
                _context7.prev = 16;
                _iterator3.f();
                return _context7.finish(16);
              case 19:
              case "end":
                return _context7.stop();
            }
          }, _callee, null, [[1, 13, 16, 19]]);
        })));
      } else {
        var _context8;
        return new DataStream(_defineProperty$1({}, _Symbol$iterator$1, _bindInstanceProperty$1$1(_context8 = _entriesInstanceProperty(this._data)).call(_context8, this._data)));
      }
    }
  }]);
  return DataSet;
}(DataSetPart);

/**
 * Check that given value is compatible with Vis Data Set interface.
 *
 * @param idProp - The expected property to contain item id.
 * @param v - The value to be tested.
 * @returns True if all expected values and methods match, false otherwise.
 */
function isDataSetLike(idProp, v) {
  return _typeof$1(v) === "object" && v !== null && idProp === v.idProp && typeof v.add === "function" && typeof v.clear === "function" && typeof v.distinct === "function" && typeof _forEachInstanceProperty$1(v) === "function" && typeof v.get === "function" && typeof v.getDataSet === "function" && typeof v.getIds === "function" && typeof v.length === "number" && typeof _mapInstanceProperty$1(v) === "function" && typeof v.max === "function" && typeof v.min === "function" && typeof v.off === "function" && typeof v.on === "function" && typeof v.remove === "function" && typeof v.setOptions === "function" && typeof v.stream === "function" && typeof v.update === "function" && typeof v.updateOnly === "function";
}

/**
 * Check that given value is compatible with Vis Data View interface.
 *
 * @param idProp - The expected property to contain item id.
 * @param v - The value to be tested.
 * @returns True if all expected values and methods match, false otherwise.
 */
function isDataViewLike(idProp, v) {
  return _typeof$1(v) === "object" && v !== null && idProp === v.idProp && typeof _forEachInstanceProperty$1(v) === "function" && typeof v.get === "function" && typeof v.getDataSet === "function" && typeof v.getIds === "function" && typeof v.length === "number" && typeof _mapInstanceProperty$1(v) === "function" && typeof v.off === "function" && typeof v.on === "function" && typeof v.stream === "function" && isDataSetLike(idProp, v.getDataSet());
}


/* Injected with object hook! */

/**
 * vis-network
 * https://visjs.github.io/vis-network/
 *
 * A dynamic, browser-based visualization library.
 *
 * @version 9.1.6
 * @date    2023-03-23T21:31:19.223Z
 *
 * @copyright (c) 2011-2017 Almende B.V, http://almende.com
 * @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs
 *
 * @license
 * vis.js is dual licensed under both
 *
 *   1. The Apache 2.0 License
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   and
 *
 *   2. The MIT License
 *      http://opensource.org/licenses/MIT
 *
 * vis.js may be distributed under either license.
 */


var commonjsGlobal$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function getDefaultExportFromCjs$1 (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

var assignExports = {};
var assign$5 = {
  get exports(){ return assignExports; },
  set exports(v){ assignExports = v; },
};

var check = function (it) {
  return it && it.Math == Math && it;
};

// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global$l =
  // eslint-disable-next-line es/no-global-this -- safe
  check(typeof globalThis == 'object' && globalThis) ||
  check(typeof window == 'object' && window) ||
  // eslint-disable-next-line no-restricted-globals -- safe
  check(typeof self == 'object' && self) ||
  check(typeof commonjsGlobal$1 == 'object' && commonjsGlobal$1) ||
  // eslint-disable-next-line no-new-func -- fallback
  (function () { return this; })() || Function('return this')();

var fails$w = function (exec) {
  try {
    return !!exec();
  } catch (error) {
    return true;
  }
};

var fails$v = fails$w;

var functionBindNative = !fails$v(function () {
  // eslint-disable-next-line es/no-function-prototype-bind -- safe
  var test = (function () { /* empty */ }).bind();
  // eslint-disable-next-line no-prototype-builtins -- safe
  return typeof test != 'function' || test.hasOwnProperty('prototype');
});

var NATIVE_BIND$4 = functionBindNative;

var FunctionPrototype$3 = Function.prototype;
var apply$5 = FunctionPrototype$3.apply;
var call$f = FunctionPrototype$3.call;

// eslint-disable-next-line es/no-reflect -- safe
var functionApply = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND$4 ? call$f.bind(apply$5) : function () {
  return call$f.apply(apply$5, arguments);
});

var NATIVE_BIND$3 = functionBindNative;

var FunctionPrototype$2 = Function.prototype;
var call$e = FunctionPrototype$2.call;
var uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$2.bind.bind(call$e, call$e);

var functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function (fn) {
  return function () {
    return call$e.apply(fn, arguments);
  };
};

var uncurryThis$y = functionUncurryThis;

var toString$c = uncurryThis$y({}.toString);
var stringSlice$1 = uncurryThis$y(''.slice);

var classofRaw$2 = function (it) {
  return stringSlice$1(toString$c(it), 8, -1);
};

var classofRaw$1 = classofRaw$2;
var uncurryThis$x = functionUncurryThis;

var functionUncurryThisClause = function (fn) {
  // Nashorn bug:
  //   https://github.com/zloirock/core-js/issues/1128
  //   https://github.com/zloirock/core-js/issues/1130
  if (classofRaw$1(fn) === 'Function') return uncurryThis$x(fn);
};

var documentAll$2 = typeof document == 'object' && document.all;

// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
// eslint-disable-next-line unicorn/no-typeof-undefined -- required for testing
var IS_HTMLDDA = typeof documentAll$2 == 'undefined' && documentAll$2 !== undefined;

var documentAll_1 = {
  all: documentAll$2,
  IS_HTMLDDA: IS_HTMLDDA
};

var $documentAll$1 = documentAll_1;

var documentAll$1 = $documentAll$1.all;

// `IsCallable` abstract operation
// https://tc39.es/ecma262/#sec-iscallable
var isCallable$i = $documentAll$1.IS_HTMLDDA ? function (argument) {
  return typeof argument == 'function' || argument === documentAll$1;
} : function (argument) {
  return typeof argument == 'function';
};

var objectGetOwnPropertyDescriptor = {};

var fails$u = fails$w;

// Detect IE8's incomplete defineProperty implementation
var descriptors = !fails$u(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
});

var NATIVE_BIND$2 = functionBindNative;

var call$d = Function.prototype.call;

var functionCall = NATIVE_BIND$2 ? call$d.bind(call$d) : function () {
  return call$d.apply(call$d, arguments);
};

var objectPropertyIsEnumerable = {};

var $propertyIsEnumerable$2 = {}.propertyIsEnumerable;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor$a = Object.getOwnPropertyDescriptor;

// Nashorn ~ JDK8 bug
var NASHORN_BUG = getOwnPropertyDescriptor$a && !$propertyIsEnumerable$2.call({ 1: 2 }, 1);

// `Object.prototype.propertyIsEnumerable` method implementation
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
objectPropertyIsEnumerable.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
  var descriptor = getOwnPropertyDescriptor$a(this, V);
  return !!descriptor && descriptor.enumerable;
} : $propertyIsEnumerable$2;

var createPropertyDescriptor$5 = function (bitmap, value) {
  return {
    enumerable: !(bitmap & 1),
    configurable: !(bitmap & 2),
    writable: !(bitmap & 4),
    value: value
  };
};

var uncurryThis$w = functionUncurryThis;
var fails$t = fails$w;
var classof$e = classofRaw$2;

var $Object$5 = Object;
var split = uncurryThis$w(''.split);

// fallback for non-array-like ES3 and non-enumerable old V8 strings
var indexedObject = fails$t(function () {
  // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
  // eslint-disable-next-line no-prototype-builtins -- safe
  return !$Object$5('z').propertyIsEnumerable(0);
}) ? function (it) {
  return classof$e(it) == 'String' ? split(it, '') : $Object$5(it);
} : $Object$5;

// we can't use just `it == null` since of `document.all` special case
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
var isNullOrUndefined$5 = function (it) {
  return it === null || it === undefined;
};

var isNullOrUndefined$4 = isNullOrUndefined$5;

var $TypeError$g = TypeError;

// `RequireObjectCoercible` abstract operation
// https://tc39.es/ecma262/#sec-requireobjectcoercible
var requireObjectCoercible$5 = function (it) {
  if (isNullOrUndefined$4(it)) throw $TypeError$g("Can't call method on " + it);
  return it;
};

// toObject with fallback for non-array-like ES3 strings
var IndexedObject$3 = indexedObject;
var requireObjectCoercible$4 = requireObjectCoercible$5;

var toIndexedObject$b = function (it) {
  return IndexedObject$3(requireObjectCoercible$4(it));
};

var isCallable$h = isCallable$i;
var $documentAll = documentAll_1;

var documentAll = $documentAll.all;

var isObject$j = $documentAll.IS_HTMLDDA ? function (it) {
  return typeof it == 'object' ? it !== null : isCallable$h(it) || it === documentAll;
} : function (it) {
  return typeof it == 'object' ? it !== null : isCallable$h(it);
};

var path$y = {};

var path$x = path$y;
var global$k = global$l;
var isCallable$g = isCallable$i;

var aFunction = function (variable) {
  return isCallable$g(variable) ? variable : undefined;
};

var getBuiltIn$c = function (namespace, method) {
  return arguments.length < 2 ? aFunction(path$x[namespace]) || aFunction(global$k[namespace])
    : path$x[namespace] && path$x[namespace][method] || global$k[namespace] && global$k[namespace][method];
};

var uncurryThis$v = functionUncurryThis;

var objectIsPrototypeOf = uncurryThis$v({}.isPrototypeOf);

var engineUserAgent = typeof navigator != 'undefined' && String(navigator.userAgent) || '';

var global$j = global$l;
var userAgent$2 = engineUserAgent;

var process$1 = global$j.process;
var Deno$1 = global$j.Deno;
var versions = process$1 && process$1.versions || Deno$1 && Deno$1.version;
var v8 = versions && versions.v8;
var match, version;

if (v8) {
  match = v8.split('.');
  // in old Chrome, versions of V8 isn't V8 = Chrome / 10
  // but their correct versions are not interesting for us
  version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
}

// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
// so check `userAgent` even if `.v8` exists, but 0
if (!version && userAgent$2) {
  match = userAgent$2.match(/Edge\/(\d+)/);
  if (!match || match[1] >= 74) {
    match = userAgent$2.match(/Chrome\/(\d+)/);
    if (match) version = +match[1];
  }
}

var engineV8Version = version;

/* eslint-disable es/no-symbol -- required for testing */

var V8_VERSION$2 = engineV8Version;
var fails$s = fails$w;

// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
var symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$s(function () {
  var symbol = Symbol();
  // Chrome 38 Symbol has incorrect toString conversion
  // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
  return !String(symbol) || !(Object(symbol) instanceof Symbol) ||
    // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
    !Symbol.sham && V8_VERSION$2 && V8_VERSION$2 < 41;
});

/* eslint-disable es/no-symbol -- required for testing */

var NATIVE_SYMBOL$5 = symbolConstructorDetection;

var useSymbolAsUid = NATIVE_SYMBOL$5
  && !Symbol.sham
  && typeof Symbol.iterator == 'symbol';

var getBuiltIn$b = getBuiltIn$c;
var isCallable$f = isCallable$i;
var isPrototypeOf$k = objectIsPrototypeOf;
var USE_SYMBOL_AS_UID$1 = useSymbolAsUid;

var $Object$4 = Object;

var isSymbol$5 = USE_SYMBOL_AS_UID$1 ? function (it) {
  return typeof it == 'symbol';
} : function (it) {
  var $Symbol = getBuiltIn$b('Symbol');
  return isCallable$f($Symbol) && isPrototypeOf$k($Symbol.prototype, $Object$4(it));
};

var $String$4 = String;

var tryToString$6 = function (argument) {
  try {
    return $String$4(argument);
  } catch (error) {
    return 'Object';
  }
};

var isCallable$e = isCallable$i;
var tryToString$5 = tryToString$6;

var $TypeError$f = TypeError;

// `Assert: IsCallable(argument) is true`
var aCallable$7 = function (argument) {
  if (isCallable$e(argument)) return argument;
  throw $TypeError$f(tryToString$5(argument) + ' is not a function');
};

var aCallable$6 = aCallable$7;
var isNullOrUndefined$3 = isNullOrUndefined$5;

// `GetMethod` abstract operation
// https://tc39.es/ecma262/#sec-getmethod
var getMethod$3 = function (V, P) {
  var func = V[P];
  return isNullOrUndefined$3(func) ? undefined : aCallable$6(func);
};

var call$c = functionCall;
var isCallable$d = isCallable$i;
var isObject$i = isObject$j;

var $TypeError$e = TypeError;

// `OrdinaryToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-ordinarytoprimitive
var ordinaryToPrimitive$1 = function (input, pref) {
  var fn, val;
  if (pref === 'string' && isCallable$d(fn = input.toString) && !isObject$i(val = call$c(fn, input))) return val;
  if (isCallable$d(fn = input.valueOf) && !isObject$i(val = call$c(fn, input))) return val;
  if (pref !== 'string' && isCallable$d(fn = input.toString) && !isObject$i(val = call$c(fn, input))) return val;
  throw $TypeError$e("Can't convert object to primitive value");
};

var sharedExports = {};
var shared$7 = {
  get exports(){ return sharedExports; },
  set exports(v){ sharedExports = v; },
};

var global$i = global$l;

// eslint-disable-next-line es/no-object-defineproperty -- safe
var defineProperty$f = Object.defineProperty;

var defineGlobalProperty$1 = function (key, value) {
  try {
    defineProperty$f(global$i, key, { value: value, configurable: true, writable: true });
  } catch (error) {
    global$i[key] = value;
  } return value;
};

var global$h = global$l;
var defineGlobalProperty = defineGlobalProperty$1;

var SHARED = '__core-js_shared__';
var store$3 = global$h[SHARED] || defineGlobalProperty(SHARED, {});

var sharedStore = store$3;

var store$2 = sharedStore;

(shared$7.exports = function (key, value) {
  return store$2[key] || (store$2[key] = value !== undefined ? value : {});
})('versions', []).push({
  version: '3.29.0',
  mode: 'pure' ,
  copyright: '© 2014-2023 Denis Pushkarev (zloirock.ru)',
  license: 'https://github.com/zloirock/core-js/blob/v3.29.0/LICENSE',
  source: 'https://github.com/zloirock/core-js'
});

var requireObjectCoercible$3 = requireObjectCoercible$5;

var $Object$3 = Object;

// `ToObject` abstract operation
// https://tc39.es/ecma262/#sec-toobject
var toObject$d = function (argument) {
  return $Object$3(requireObjectCoercible$3(argument));
};

var uncurryThis$u = functionUncurryThis;
var toObject$c = toObject$d;

var hasOwnProperty = uncurryThis$u({}.hasOwnProperty);

// `HasOwnProperty` abstract operation
// https://tc39.es/ecma262/#sec-hasownproperty
// eslint-disable-next-line es/no-object-hasown -- safe
var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
  return hasOwnProperty(toObject$c(it), key);
};

var uncurryThis$t = functionUncurryThis;

var id$2 = 0;
var postfix = Math.random();
var toString$b = uncurryThis$t(1.0.toString);

var uid$4 = function (key) {
  return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$b(++id$2 + postfix, 36);
};

var global$g = global$l;
var shared$6 = sharedExports;
var hasOwn$h = hasOwnProperty_1;
var uid$3 = uid$4;
var NATIVE_SYMBOL$4 = symbolConstructorDetection;
var USE_SYMBOL_AS_UID = useSymbolAsUid;

var Symbol$5 = global$g.Symbol;
var WellKnownSymbolsStore$2 = shared$6('wks');
var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$5['for'] || Symbol$5 : Symbol$5 && Symbol$5.withoutSetter || uid$3;

var wellKnownSymbol$l = function (name) {
  if (!hasOwn$h(WellKnownSymbolsStore$2, name)) {
    WellKnownSymbolsStore$2[name] = NATIVE_SYMBOL$4 && hasOwn$h(Symbol$5, name)
      ? Symbol$5[name]
      : createWellKnownSymbol('Symbol.' + name);
  } return WellKnownSymbolsStore$2[name];
};

var call$b = functionCall;
var isObject$h = isObject$j;
var isSymbol$4 = isSymbol$5;
var getMethod$2 = getMethod$3;
var ordinaryToPrimitive = ordinaryToPrimitive$1;
var wellKnownSymbol$k = wellKnownSymbol$l;

var $TypeError$d = TypeError;
var TO_PRIMITIVE = wellKnownSymbol$k('toPrimitive');

// `ToPrimitive` abstract operation
// https://tc39.es/ecma262/#sec-toprimitive
var toPrimitive$7 = function (input, pref) {
  if (!isObject$h(input) || isSymbol$4(input)) return input;
  var exoticToPrim = getMethod$2(input, TO_PRIMITIVE);
  var result;
  if (exoticToPrim) {
    if (pref === undefined) pref = 'default';
    result = call$b(exoticToPrim, input, pref);
    if (!isObject$h(result) || isSymbol$4(result)) return result;
    throw $TypeError$d("Can't convert object to primitive value");
  }
  if (pref === undefined) pref = 'number';
  return ordinaryToPrimitive(input, pref);
};

var toPrimitive$6 = toPrimitive$7;
var isSymbol$3 = isSymbol$5;

// `ToPropertyKey` abstract operation
// https://tc39.es/ecma262/#sec-topropertykey
var toPropertyKey$4 = function (argument) {
  var key = toPrimitive$6(argument, 'string');
  return isSymbol$3(key) ? key : key + '';
};

var global$f = global$l;
var isObject$g = isObject$j;

var document$1 = global$f.document;
// typeof document.createElement is 'object' in old IE
var EXISTS$1 = isObject$g(document$1) && isObject$g(document$1.createElement);

var documentCreateElement$1 = function (it) {
  return EXISTS$1 ? document$1.createElement(it) : {};
};

var DESCRIPTORS$i = descriptors;
var fails$r = fails$w;
var createElement$1 = documentCreateElement$1;

// Thanks to IE8 for its funny defineProperty
var ie8DomDefine = !DESCRIPTORS$i && !fails$r(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty(createElement$1('div'), 'a', {
    get: function () { return 7; }
  }).a != 7;
});

var DESCRIPTORS$h = descriptors;
var call$a = functionCall;
var propertyIsEnumerableModule$2 = objectPropertyIsEnumerable;
var createPropertyDescriptor$4 = createPropertyDescriptor$5;
var toIndexedObject$a = toIndexedObject$b;
var toPropertyKey$3 = toPropertyKey$4;
var hasOwn$g = hasOwnProperty_1;
var IE8_DOM_DEFINE$1 = ie8DomDefine;

// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor$2 = Object.getOwnPropertyDescriptor;

// `Object.getOwnPropertyDescriptor` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$h ? $getOwnPropertyDescriptor$2 : function getOwnPropertyDescriptor(O, P) {
  O = toIndexedObject$a(O);
  P = toPropertyKey$3(P);
  if (IE8_DOM_DEFINE$1) try {
    return $getOwnPropertyDescriptor$2(O, P);
  } catch (error) { /* empty */ }
  if (hasOwn$g(O, P)) return createPropertyDescriptor$4(!call$a(propertyIsEnumerableModule$2.f, O, P), O[P]);
};

var fails$q = fails$w;
var isCallable$c = isCallable$i;

var replacement = /#|\.prototype\./;

var isForced$1 = function (feature, detection) {
  var value = data[normalize$2(feature)];
  return value == POLYFILL ? true
    : value == NATIVE ? false
    : isCallable$c(detection) ? fails$q(detection)
    : !!detection;
};

var normalize$2 = isForced$1.normalize = function (string) {
  return String(string).replace(replacement, '.').toLowerCase();
};

var data = isForced$1.data = {};
var NATIVE = isForced$1.NATIVE = 'N';
var POLYFILL = isForced$1.POLYFILL = 'P';

var isForced_1 = isForced$1;

var uncurryThis$s = functionUncurryThisClause;
var aCallable$5 = aCallable$7;
var NATIVE_BIND$1 = functionBindNative;

var bind$f = uncurryThis$s(uncurryThis$s.bind);

// optional / simple context binding
var functionBindContext = function (fn, that) {
  aCallable$5(fn);
  return that === undefined ? fn : NATIVE_BIND$1 ? bind$f(fn, that) : function (/* ...args */) {
    return fn.apply(that, arguments);
  };
};

var objectDefineProperty = {};

var DESCRIPTORS$g = descriptors;
var fails$p = fails$w;

// V8 ~ Chrome 36-
// https://bugs.chromium.org/p/v8/issues/detail?id=3334
var v8PrototypeDefineBug = DESCRIPTORS$g && fails$p(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty(function () { /* empty */ }, 'prototype', {
    value: 42,
    writable: false
  }).prototype != 42;
});

var isObject$f = isObject$j;

var $String$3 = String;
var $TypeError$c = TypeError;

// `Assert: Type(argument) is Object`
var anObject$d = function (argument) {
  if (isObject$f(argument)) return argument;
  throw $TypeError$c($String$3(argument) + ' is not an object');
};

var DESCRIPTORS$f = descriptors;
var IE8_DOM_DEFINE = ie8DomDefine;
var V8_PROTOTYPE_DEFINE_BUG$1 = v8PrototypeDefineBug;
var anObject$c = anObject$d;
var toPropertyKey$2 = toPropertyKey$4;

var $TypeError$b = TypeError;
// eslint-disable-next-line es/no-object-defineproperty -- safe
var $defineProperty$1 = Object.defineProperty;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
var ENUMERABLE = 'enumerable';
var CONFIGURABLE$1 = 'configurable';
var WRITABLE = 'writable';

// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
objectDefineProperty.f = DESCRIPTORS$f ? V8_PROTOTYPE_DEFINE_BUG$1 ? function defineProperty(O, P, Attributes) {
  anObject$c(O);
  P = toPropertyKey$2(P);
  anObject$c(Attributes);
  if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
    var current = $getOwnPropertyDescriptor$1(O, P);
    if (current && current[WRITABLE]) {
      O[P] = Attributes.value;
      Attributes = {
        configurable: CONFIGURABLE$1 in Attributes ? Attributes[CONFIGURABLE$1] : current[CONFIGURABLE$1],
        enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
        writable: false
      };
    }
  } return $defineProperty$1(O, P, Attributes);
} : $defineProperty$1 : function defineProperty(O, P, Attributes) {
  anObject$c(O);
  P = toPropertyKey$2(P);
  anObject$c(Attributes);
  if (IE8_DOM_DEFINE) try {
    return $defineProperty$1(O, P, Attributes);
  } catch (error) { /* empty */ }
  if ('get' in Attributes || 'set' in Attributes) throw $TypeError$b('Accessors not supported');
  if ('value' in Attributes) O[P] = Attributes.value;
  return O;
};

var DESCRIPTORS$e = descriptors;
var definePropertyModule$3 = objectDefineProperty;
var createPropertyDescriptor$3 = createPropertyDescriptor$5;

var createNonEnumerableProperty$6 = DESCRIPTORS$e ? function (object, key, value) {
  return definePropertyModule$3.f(object, key, createPropertyDescriptor$3(1, value));
} : function (object, key, value) {
  object[key] = value;
  return object;
};

var global$e = global$l;
var apply$4 = functionApply;
var uncurryThis$r = functionUncurryThisClause;
var isCallable$b = isCallable$i;
var getOwnPropertyDescriptor$9 = objectGetOwnPropertyDescriptor.f;
var isForced = isForced_1;
var path$w = path$y;
var bind$e = functionBindContext;
var createNonEnumerableProperty$5 = createNonEnumerableProperty$6;
var hasOwn$f = hasOwnProperty_1;

var wrapConstructor = function (NativeConstructor) {
  var Wrapper = function (a, b, c) {
    if (this instanceof Wrapper) {
      switch (arguments.length) {
        case 0: return new NativeConstructor();
        case 1: return new NativeConstructor(a);
        case 2: return new NativeConstructor(a, b);
      } return new NativeConstructor(a, b, c);
    } return apply$4(NativeConstructor, this, arguments);
  };
  Wrapper.prototype = NativeConstructor.prototype;
  return Wrapper;
};

/*
  options.target         - name of the target object
  options.global         - target is the global object
  options.stat           - export as static methods of target
  options.proto          - export as prototype methods of target
  options.real           - real prototype method for the `pure` version
  options.forced         - export even if the native feature is available
  options.bind           - bind methods to the target, required for the `pure` version
  options.wrap           - wrap constructors to preventing global pollution, required for the `pure` version
  options.unsafe         - use the simple assignment of property instead of delete + defineProperty
  options.sham           - add a flag to not completely full polyfills
  options.enumerable     - export as enumerable property
  options.dontCallGetSet - prevent calling a getter on target
  options.name           - the .name of the function if it does not match the key
*/
var _export = function (options, source) {
  var TARGET = options.target;
  var GLOBAL = options.global;
  var STATIC = options.stat;
  var PROTO = options.proto;

  var nativeSource = GLOBAL ? global$e : STATIC ? global$e[TARGET] : (global$e[TARGET] || {}).prototype;

  var target = GLOBAL ? path$w : path$w[TARGET] || createNonEnumerableProperty$5(path$w, TARGET, {})[TARGET];
  var targetPrototype = target.prototype;

  var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE;
  var key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor;

  for (key in source) {
    FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
    // contains in native
    USE_NATIVE = !FORCED && nativeSource && hasOwn$f(nativeSource, key);

    targetProperty = target[key];

    if (USE_NATIVE) if (options.dontCallGetSet) {
      descriptor = getOwnPropertyDescriptor$9(nativeSource, key);
      nativeProperty = descriptor && descriptor.value;
    } else nativeProperty = nativeSource[key];

    // export native or implementation
    sourceProperty = (USE_NATIVE && nativeProperty) ? nativeProperty : source[key];

    if (USE_NATIVE && typeof targetProperty == typeof sourceProperty) continue;

    // bind methods to global for calling from export context
    if (options.bind && USE_NATIVE) resultProperty = bind$e(sourceProperty, global$e);
    // wrap global constructors for prevent changes in this version
    else if (options.wrap && USE_NATIVE) resultProperty = wrapConstructor(sourceProperty);
    // make static versions for prototype methods
    else if (PROTO && isCallable$b(sourceProperty)) resultProperty = uncurryThis$r(sourceProperty);
    // default case
    else resultProperty = sourceProperty;

    // add a flag to not completely full polyfills
    if (options.sham || (sourceProperty && sourceProperty.sham) || (targetProperty && targetProperty.sham)) {
      createNonEnumerableProperty$5(resultProperty, 'sham', true);
    }

    createNonEnumerableProperty$5(target, key, resultProperty);

    if (PROTO) {
      VIRTUAL_PROTOTYPE = TARGET + 'Prototype';
      if (!hasOwn$f(path$w, VIRTUAL_PROTOTYPE)) {
        createNonEnumerableProperty$5(path$w, VIRTUAL_PROTOTYPE, {});
      }
      // export virtual prototype methods
      createNonEnumerableProperty$5(path$w[VIRTUAL_PROTOTYPE], key, sourceProperty);
      // export real prototype methods
      if (options.real && targetPrototype && (FORCED || !targetPrototype[key])) {
        createNonEnumerableProperty$5(targetPrototype, key, sourceProperty);
      }
    }
  }
};

var ceil = Math.ceil;
var floor$1 = Math.floor;

// `Math.trunc` method
// https://tc39.es/ecma262/#sec-math.trunc
// eslint-disable-next-line es/no-math-trunc -- safe
var mathTrunc = Math.trunc || function trunc(x) {
  var n = +x;
  return (n > 0 ? floor$1 : ceil)(n);
};

var trunc = mathTrunc;

// `ToIntegerOrInfinity` abstract operation
// https://tc39.es/ecma262/#sec-tointegerorinfinity
var toIntegerOrInfinity$4 = function (argument) {
  var number = +argument;
  // eslint-disable-next-line no-self-compare -- NaN check
  return number !== number || number === 0 ? 0 : trunc(number);
};

var toIntegerOrInfinity$3 = toIntegerOrInfinity$4;

var max$3 = Math.max;
var min$2 = Math.min;

// Helper for a popular repeating case of the spec:
// Let integer be ? ToInteger(index).
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
var toAbsoluteIndex$5 = function (index, length) {
  var integer = toIntegerOrInfinity$3(index);
  return integer < 0 ? max$3(integer + length, 0) : min$2(integer, length);
};

var toIntegerOrInfinity$2 = toIntegerOrInfinity$4;

var min$1$1 = Math.min;

// `ToLength` abstract operation
// https://tc39.es/ecma262/#sec-tolength
var toLength$1 = function (argument) {
  return argument > 0 ? min$1$1(toIntegerOrInfinity$2(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
};

var toLength = toLength$1;

// `LengthOfArrayLike` abstract operation
// https://tc39.es/ecma262/#sec-lengthofarraylike
var lengthOfArrayLike$b = function (obj) {
  return toLength(obj.length);
};

var toIndexedObject$9 = toIndexedObject$b;
var toAbsoluteIndex$4 = toAbsoluteIndex$5;
var lengthOfArrayLike$a = lengthOfArrayLike$b;

// `Array.prototype.{ indexOf, includes }` methods implementation
var createMethod$5 = function (IS_INCLUDES) {
  return function ($this, el, fromIndex) {
    var O = toIndexedObject$9($this);
    var length = lengthOfArrayLike$a(O);
    var index = toAbsoluteIndex$4(fromIndex, length);
    var value;
    // Array#includes uses SameValueZero equality algorithm
    // eslint-disable-next-line no-self-compare -- NaN check
    if (IS_INCLUDES && el != el) while (length > index) {
      value = O[index++];
      // eslint-disable-next-line no-self-compare -- NaN check
      if (value != value) return true;
    // Array#indexOf ignores holes, Array#includes - not
    } else for (;length > index; index++) {
      if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
    } return !IS_INCLUDES && -1;
  };
};

var arrayIncludes = {
  // `Array.prototype.includes` method
  // https://tc39.es/ecma262/#sec-array.prototype.includes
  includes: createMethod$5(true),
  // `Array.prototype.indexOf` method
  // https://tc39.es/ecma262/#sec-array.prototype.indexof
  indexOf: createMethod$5(false)
};

var hiddenKeys$6 = {};

var uncurryThis$q = functionUncurryThis;
var hasOwn$e = hasOwnProperty_1;
var toIndexedObject$8 = toIndexedObject$b;
var indexOf$4 = arrayIncludes.indexOf;
var hiddenKeys$5 = hiddenKeys$6;

var push$6 = uncurryThis$q([].push);

var objectKeysInternal = function (object, names) {
  var O = toIndexedObject$8(object);
  var i = 0;
  var result = [];
  var key;
  for (key in O) !hasOwn$e(hiddenKeys$5, key) && hasOwn$e(O, key) && push$6(result, key);
  // Don't enum bug & hidden keys
  while (names.length > i) if (hasOwn$e(O, key = names[i++])) {
    ~indexOf$4(result, key) || push$6(result, key);
  }
  return result;
};

// IE8- don't enum bug keys
var enumBugKeys$3 = [
  'constructor',
  'hasOwnProperty',
  'isPrototypeOf',
  'propertyIsEnumerable',
  'toLocaleString',
  'toString',
  'valueOf'
];

var internalObjectKeys$1 = objectKeysInternal;
var enumBugKeys$2 = enumBugKeys$3;

// `Object.keys` method
// https://tc39.es/ecma262/#sec-object.keys
// eslint-disable-next-line es/no-object-keys -- safe
var objectKeys$4 = Object.keys || function keys(O) {
  return internalObjectKeys$1(O, enumBugKeys$2);
};

var objectGetOwnPropertySymbols = {};

// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
objectGetOwnPropertySymbols.f = Object.getOwnPropertySymbols;

var DESCRIPTORS$d = descriptors;
var uncurryThis$p = functionUncurryThis;
var call$9 = functionCall;
var fails$o = fails$w;
var objectKeys$3 = objectKeys$4;
var getOwnPropertySymbolsModule$3 = objectGetOwnPropertySymbols;
var propertyIsEnumerableModule$1 = objectPropertyIsEnumerable;
var toObject$b = toObject$d;
var IndexedObject$2 = indexedObject;

// eslint-disable-next-line es/no-object-assign -- safe
var $assign = Object.assign;
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
var defineProperty$e = Object.defineProperty;
var concat$6 = uncurryThis$p([].concat);

// `Object.assign` method
// https://tc39.es/ecma262/#sec-object.assign
var objectAssign = !$assign || fails$o(function () {
  // should have correct order of operations (Edge bug)
  if (DESCRIPTORS$d && $assign({ b: 1 }, $assign(defineProperty$e({}, 'a', {
    enumerable: true,
    get: function () {
      defineProperty$e(this, 'b', {
        value: 3,
        enumerable: false
      });
    }
  }), { b: 2 })).b !== 1) return true;
  // should work with symbols and should have deterministic property order (V8 bug)
  var A = {};
  var B = {};
  // eslint-disable-next-line es/no-symbol -- safe
  var symbol = Symbol();
  var alphabet = 'abcdefghijklmnopqrst';
  A[symbol] = 7;
  alphabet.split('').forEach(function (chr) { B[chr] = chr; });
  return $assign({}, A)[symbol] != 7 || objectKeys$3($assign({}, B)).join('') != alphabet;
}) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
  var T = toObject$b(target);
  var argumentsLength = arguments.length;
  var index = 1;
  var getOwnPropertySymbols = getOwnPropertySymbolsModule$3.f;
  var propertyIsEnumerable = propertyIsEnumerableModule$1.f;
  while (argumentsLength > index) {
    var S = IndexedObject$2(arguments[index++]);
    var keys = getOwnPropertySymbols ? concat$6(objectKeys$3(S), getOwnPropertySymbols(S)) : objectKeys$3(S);
    var length = keys.length;
    var j = 0;
    var key;
    while (length > j) {
      key = keys[j++];
      if (!DESCRIPTORS$d || call$9(propertyIsEnumerable, S, key)) T[key] = S[key];
    }
  } return T;
} : $assign;

var $$O = _export;
var assign$4 = objectAssign;

// `Object.assign` method
// https://tc39.es/ecma262/#sec-object.assign
// eslint-disable-next-line es/no-object-assign -- required for testing
$$O({ target: 'Object', stat: true, arity: 2, forced: Object.assign !== assign$4 }, {
  assign: assign$4
});

var path$v = path$y;

var assign$3 = path$v.Object.assign;

var parent$1b = assign$3;

var assign$2 = parent$1b;

(function (module) {
	module.exports = assign$2;
} (assign$5));

var _Object$assign = /*@__PURE__*/getDefaultExportFromCjs$1(assignExports);

var bindExports$2 = {};
var bind$d = {
  get exports(){ return bindExports$2; },
  set exports(v){ bindExports$2 = v; },
};

var uncurryThis$o = functionUncurryThis;

var arraySlice$5 = uncurryThis$o([].slice);

var uncurryThis$n = functionUncurryThis;
var aCallable$4 = aCallable$7;
var isObject$e = isObject$j;
var hasOwn$d = hasOwnProperty_1;
var arraySlice$4 = arraySlice$5;
var NATIVE_BIND = functionBindNative;

var $Function = Function;
var concat$5 = uncurryThis$n([].concat);
var join = uncurryThis$n([].join);
var factories = {};

var construct$4 = function (C, argsLength, args) {
  if (!hasOwn$d(factories, argsLength)) {
    for (var list = [], i = 0; i < argsLength; i++) list[i] = 'a[' + i + ']';
    factories[argsLength] = $Function('C,a', 'return new C(' + join(list, ',') + ')');
  } return factories[argsLength](C, args);
};

// `Function.prototype.bind` method implementation
// https://tc39.es/ecma262/#sec-function.prototype.bind
// eslint-disable-next-line es/no-function-prototype-bind -- detection
var functionBind = NATIVE_BIND ? $Function.bind : function bind(that /* , ...args */) {
  var F = aCallable$4(this);
  var Prototype = F.prototype;
  var partArgs = arraySlice$4(arguments, 1);
  var boundFunction = function bound(/* args... */) {
    var args = concat$5(partArgs, arraySlice$4(arguments));
    return this instanceof boundFunction ? construct$4(F, args.length, args) : F.apply(that, args);
  };
  if (isObject$e(Prototype)) boundFunction.prototype = Prototype;
  return boundFunction;
};

// TODO: Remove from `core-js@4`
var $$N = _export;
var bind$c = functionBind;

// `Function.prototype.bind` method
// https://tc39.es/ecma262/#sec-function.prototype.bind
// eslint-disable-next-line es/no-function-prototype-bind -- detection
$$N({ target: 'Function', proto: true, forced: Function.bind !== bind$c }, {
  bind: bind$c
});

var path$u = path$y;

var entryVirtual$i = function (CONSTRUCTOR) {
  return path$u[CONSTRUCTOR + 'Prototype'];
};

var entryVirtual$h = entryVirtual$i;

var bind$b = entryVirtual$h('Function').bind;

var isPrototypeOf$j = objectIsPrototypeOf;
var method$f = bind$b;

var FunctionPrototype$1 = Function.prototype;

var bind$a = function (it) {
  var own = it.bind;
  return it === FunctionPrototype$1 || (isPrototypeOf$j(FunctionPrototype$1, it) && own === FunctionPrototype$1.bind) ? method$f : own;
};

var parent$1a = bind$a;

var bind$9 = parent$1a;

(function (module) {
	module.exports = bind$9;
} (bind$d));

var _bindInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$1(bindExports$2);

/**
 * Draw a circle.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - The radius of the circle.
 */
function drawCircle(ctx, x, y, r) {
  ctx.beginPath();
  ctx.arc(x, y, r, 0, 2 * Math.PI, false);
  ctx.closePath();
}
/**
 * Draw a square.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - Half of the width and height of the square.
 */
function drawSquare(ctx, x, y, r) {
  ctx.beginPath();
  ctx.rect(x - r, y - r, r * 2, r * 2);
  ctx.closePath();
}
/**
 * Draw an equilateral triangle standing on a side.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - Half of the length of the sides.
 * @remarks
 * http://en.wikipedia.org/wiki/Equilateral_triangle
 */
function drawTriangle(ctx, x, y, r) {
  ctx.beginPath();
  // the change in radius and the offset is here to center the shape
  r *= 1.15;
  y += 0.275 * r;
  var s = r * 2;
  var s2 = s / 2;
  var ir = Math.sqrt(3) / 6 * s; // radius of inner circle
  var h = Math.sqrt(s * s - s2 * s2); // height
  ctx.moveTo(x, y - (h - ir));
  ctx.lineTo(x + s2, y + ir);
  ctx.lineTo(x - s2, y + ir);
  ctx.lineTo(x, y - (h - ir));
  ctx.closePath();
}
/**
 * Draw an equilateral triangle standing on a vertex.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - Half of the length of the sides.
 * @remarks
 * http://en.wikipedia.org/wiki/Equilateral_triangle
 */
function drawTriangleDown(ctx, x, y, r) {
  ctx.beginPath();
  // the change in radius and the offset is here to center the shape
  r *= 1.15;
  y -= 0.275 * r;
  var s = r * 2;
  var s2 = s / 2;
  var ir = Math.sqrt(3) / 6 * s; // radius of inner circle
  var h = Math.sqrt(s * s - s2 * s2); // height
  ctx.moveTo(x, y + (h - ir));
  ctx.lineTo(x + s2, y - ir);
  ctx.lineTo(x - s2, y - ir);
  ctx.lineTo(x, y + (h - ir));
  ctx.closePath();
}
/**
 * Draw a star.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - The outer radius of the star.
 */
function drawStar(ctx, x, y, r) {
  // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/
  ctx.beginPath();
  // the change in radius and the offset is here to center the shape
  r *= 0.82;
  y += 0.1 * r;
  for (var n = 0; n < 10; n++) {
    var radius = n % 2 === 0 ? r * 1.3 : r * 0.5;
    ctx.lineTo(x + radius * Math.sin(n * 2 * Math.PI / 10), y - radius * Math.cos(n * 2 * Math.PI / 10));
  }
  ctx.closePath();
}
/**
 * Draw a diamond.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - Half of the width and height of the diamond.
 * @remarks
 * http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/
 */
function drawDiamond(ctx, x, y, r) {
  ctx.beginPath();
  ctx.lineTo(x, y + r);
  ctx.lineTo(x + r, y);
  ctx.lineTo(x, y - r);
  ctx.lineTo(x - r, y);
  ctx.closePath();
}
/**
 * Draw a rectangle with rounded corners.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param w - The width of the rectangle.
 * @param h - The height of the rectangle.
 * @param r - The radius of the corners.
 * @remarks
 * http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas
 */
function drawRoundRect(ctx, x, y, w, h, r) {
  var r2d = Math.PI / 180;
  if (w - 2 * r < 0) {
    r = w / 2;
  } //ensure that the radius isn't too large for x
  if (h - 2 * r < 0) {
    r = h / 2;
  } //ensure that the radius isn't too large for y
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.lineTo(x + w - r, y);
  ctx.arc(x + w - r, y + r, r, r2d * 270, r2d * 360, false);
  ctx.lineTo(x + w, y + h - r);
  ctx.arc(x + w - r, y + h - r, r, 0, r2d * 90, false);
  ctx.lineTo(x + r, y + h);
  ctx.arc(x + r, y + h - r, r, r2d * 90, r2d * 180, false);
  ctx.lineTo(x, y + r);
  ctx.arc(x + r, y + r, r, r2d * 180, r2d * 270, false);
  ctx.closePath();
}
/**
 * Draw an ellipse.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param w - The width of the ellipse.
 * @param h - The height of the ellipse.
 * @remarks
 * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
 *
 * Postfix '_vis' added to discern it from standard method ellipse().
 */
function drawEllipse(ctx, x, y, w, h) {
  var kappa = 0.5522848,
    ox = w / 2 * kappa,
    // control point offset horizontal
    oy = h / 2 * kappa,
    // control point offset vertical
    xe = x + w,
    // x-end
    ye = y + h,
    // y-end
    xm = x + w / 2,
    // x-middle
    ym = y + h / 2; // y-middle
  ctx.beginPath();
  ctx.moveTo(x, ym);
  ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  ctx.closePath();
}
/**
 * Draw an isometric cylinder.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param w - The width of the database.
 * @param h - The height of the database.
 * @remarks
 * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
 */
function drawDatabase(ctx, x, y, w, h) {
  var f = 1 / 3;
  var wEllipse = w;
  var hEllipse = h * f;
  var kappa = 0.5522848,
    ox = wEllipse / 2 * kappa,
    // control point offset horizontal
    oy = hEllipse / 2 * kappa,
    // control point offset vertical
    xe = x + wEllipse,
    // x-end
    ye = y + hEllipse,
    // y-end
    xm = x + wEllipse / 2,
    // x-middle
    ym = y + hEllipse / 2,
    // y-middle
    ymb = y + (h - hEllipse / 2),
    // y-midlle, bottom ellipse
    yeb = y + h; // y-end, bottom ellipse
  ctx.beginPath();
  ctx.moveTo(xe, ym);
  ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  ctx.lineTo(xe, ymb);
  ctx.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb);
  ctx.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb);
  ctx.lineTo(x, ym);
}
/**
 * Draw a dashed line.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The start position on the x axis.
 * @param y - The start position on the y axis.
 * @param x2 - The end position on the x axis.
 * @param y2 - The end position on the y axis.
 * @param pattern - List of lengths starting with line and then alternating between space and line.
 * @author David Jordan
 * @remarks
 * date 2012-08-08
 * http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas
 */
function drawDashedLine(ctx, x, y, x2, y2, pattern) {
  ctx.beginPath();
  ctx.moveTo(x, y);
  var patternLength = pattern.length;
  var dx = x2 - x;
  var dy = y2 - y;
  var slope = dy / dx;
  var distRemaining = Math.sqrt(dx * dx + dy * dy);
  var patternIndex = 0;
  var draw = true;
  var xStep = 0;
  var dashLength = +pattern[0];
  while (distRemaining >= 0.1) {
    dashLength = +pattern[patternIndex++ % patternLength];
    if (dashLength > distRemaining) {
      dashLength = distRemaining;
    }
    xStep = Math.sqrt(dashLength * dashLength / (1 + slope * slope));
    xStep = dx < 0 ? -xStep : xStep;
    x += xStep;
    y += slope * xStep;
    if (draw === true) {
      ctx.lineTo(x, y);
    } else {
      ctx.moveTo(x, y);
    }
    distRemaining -= dashLength;
    draw = !draw;
  }
}
/**
 * Draw a hexagon.
 *
 * @param ctx - The context this shape will be rendered to.
 * @param x - The position of the center on the x axis.
 * @param y - The position of the center on the y axis.
 * @param r - The radius of the hexagon.
 */
function drawHexagon(ctx, x, y, r) {
  ctx.beginPath();
  var sides = 6;
  var a = Math.PI * 2 / sides;
  ctx.moveTo(x + r, y);
  for (var i = 1; i < sides; i++) {
    ctx.lineTo(x + r * Math.cos(a * i), y + r * Math.sin(a * i));
  }
  ctx.closePath();
}
var shapeMap = {
  circle: drawCircle,
  dashedLine: drawDashedLine,
  database: drawDatabase,
  diamond: drawDiamond,
  ellipse: drawEllipse,
  ellipse_vis: drawEllipse,
  hexagon: drawHexagon,
  roundRect: drawRoundRect,
  square: drawSquare,
  star: drawStar,
  triangle: drawTriangle,
  triangleDown: drawTriangleDown
};
/**
 * Returns either custom or native drawing function base on supplied name.
 *
 * @param name - The name of the function. Either the name of a
 * CanvasRenderingContext2D property or an export from shapes.ts without the
 * draw prefix.
 * @returns The function that can be used for rendering. In case of native
 * CanvasRenderingContext2D function the API is normalized to
 * `(ctx: CanvasRenderingContext2D, ...originalArgs) => void`.
 */
function getShape(name) {
  if (Object.prototype.hasOwnProperty.call(shapeMap, name)) {
    return shapeMap[name];
  } else {
    return function (ctx) {
      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }
      CanvasRenderingContext2D.prototype[name].call(ctx, args);
    };
  }
}

var componentEmitterExports = {};
var componentEmitter = {
  get exports(){ return componentEmitterExports; },
  set exports(v){ componentEmitterExports = v; },
};

(function (module) {
	/**
	 * Expose `Emitter`.
	 */

	{
	  module.exports = Emitter;
	}

	/**
	 * Initialize a new `Emitter`.
	 *
	 * @api public
	 */

	function Emitter(obj) {
	  if (obj) return mixin(obj);
	}
	/**
	 * Mixin the emitter properties.
	 *
	 * @param {Object} obj
	 * @return {Object}
	 * @api private
	 */

	function mixin(obj) {
	  for (var key in Emitter.prototype) {
	    obj[key] = Emitter.prototype[key];
	  }
	  return obj;
	}

	/**
	 * Listen on the given `event` with `fn`.
	 *
	 * @param {String} event
	 * @param {Function} fn
	 * @return {Emitter}
	 * @api public
	 */

	Emitter.prototype.on =
	Emitter.prototype.addEventListener = function(event, fn){
	  this._callbacks = this._callbacks || {};
	  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
	    .push(fn);
	  return this;
	};

	/**
	 * Adds an `event` listener that will be invoked a single
	 * time then automatically removed.
	 *
	 * @param {String} event
	 * @param {Function} fn
	 * @return {Emitter}
	 * @api public
	 */

	Emitter.prototype.once = function(event, fn){
	  function on() {
	    this.off(event, on);
	    fn.apply(this, arguments);
	  }

	  on.fn = fn;
	  this.on(event, on);
	  return this;
	};

	/**
	 * Remove the given callback for `event` or all
	 * registered callbacks.
	 *
	 * @param {String} event
	 * @param {Function} fn
	 * @return {Emitter}
	 * @api public
	 */

	Emitter.prototype.off =
	Emitter.prototype.removeListener =
	Emitter.prototype.removeAllListeners =
	Emitter.prototype.removeEventListener = function(event, fn){
	  this._callbacks = this._callbacks || {};

	  // all
	  if (0 == arguments.length) {
	    this._callbacks = {};
	    return this;
	  }

	  // specific event
	  var callbacks = this._callbacks['$' + event];
	  if (!callbacks) return this;

	  // remove all handlers
	  if (1 == arguments.length) {
	    delete this._callbacks['$' + event];
	    return this;
	  }

	  // remove specific handler
	  var cb;
	  for (var i = 0; i < callbacks.length; i++) {
	    cb = callbacks[i];
	    if (cb === fn || cb.fn === fn) {
	      callbacks.splice(i, 1);
	      break;
	    }
	  }

	  // Remove event specific arrays for event types that no
	  // one is subscribed for to avoid memory leak.
	  if (callbacks.length === 0) {
	    delete this._callbacks['$' + event];
	  }

	  return this;
	};

	/**
	 * Emit `event` with the given args.
	 *
	 * @param {String} event
	 * @param {Mixed} ...
	 * @return {Emitter}
	 */

	Emitter.prototype.emit = function(event){
	  this._callbacks = this._callbacks || {};

	  var args = new Array(arguments.length - 1)
	    , callbacks = this._callbacks['$' + event];

	  for (var i = 1; i < arguments.length; i++) {
	    args[i - 1] = arguments[i];
	  }

	  if (callbacks) {
	    callbacks = callbacks.slice(0);
	    for (var i = 0, len = callbacks.length; i < len; ++i) {
	      callbacks[i].apply(this, args);
	    }
	  }

	  return this;
	};

	/**
	 * Return array of callbacks for `event`.
	 *
	 * @param {String} event
	 * @return {Array}
	 * @api public
	 */

	Emitter.prototype.listeners = function(event){
	  this._callbacks = this._callbacks || {};
	  return this._callbacks['$' + event] || [];
	};

	/**
	 * Check if this emitter has `event` handlers.
	 *
	 * @param {String} event
	 * @return {Boolean}
	 * @api public
	 */

	Emitter.prototype.hasListeners = function(event){
	  return !! this.listeners(event).length;
	};
} (componentEmitter));

var Emitter = componentEmitterExports;

var fromExports$2 = {};
var from$7 = {
  get exports(){ return fromExports$2; },
  set exports(v){ fromExports$2 = v; },
};

var wellKnownSymbol$j = wellKnownSymbol$l;

var TO_STRING_TAG$3 = wellKnownSymbol$j('toStringTag');
var test$2 = {};

test$2[TO_STRING_TAG$3] = 'z';

var toStringTagSupport = String(test$2) === '[object z]';

var TO_STRING_TAG_SUPPORT$2 = toStringTagSupport;
var isCallable$a = isCallable$i;
var classofRaw = classofRaw$2;
var wellKnownSymbol$i = wellKnownSymbol$l;

var TO_STRING_TAG$2 = wellKnownSymbol$i('toStringTag');
var $Object$2 = Object;

// ES3 wrong here
var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';

// fallback for IE11 Script Access Denied error
var tryGet = function (it, key) {
  try {
    return it[key];
  } catch (error) { /* empty */ }
};

// getting tag from ES6+ `Object.prototype.toString`
var classof$d = TO_STRING_TAG_SUPPORT$2 ? classofRaw : function (it) {
  var O, tag, result;
  return it === undefined ? 'Undefined' : it === null ? 'Null'
    // @@toStringTag case
    : typeof (tag = tryGet(O = $Object$2(it), TO_STRING_TAG$2)) == 'string' ? tag
    // builtinTag case
    : CORRECT_ARGUMENTS ? classofRaw(O)
    // ES3 arguments fallback
    : (result = classofRaw(O)) == 'Object' && isCallable$a(O.callee) ? 'Arguments' : result;
};

var classof$c = classof$d;

var $String$2 = String;

var toString$a = function (argument) {
  if (classof$c(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
  return $String$2(argument);
};

var uncurryThis$m = functionUncurryThis;
var toIntegerOrInfinity$1 = toIntegerOrInfinity$4;
var toString$9 = toString$a;
var requireObjectCoercible$2 = requireObjectCoercible$5;

var charAt$3 = uncurryThis$m(''.charAt);
var charCodeAt$1 = uncurryThis$m(''.charCodeAt);
var stringSlice = uncurryThis$m(''.slice);

var createMethod$4 = function (CONVERT_TO_STRING) {
  return function ($this, pos) {
    var S = toString$9(requireObjectCoercible$2($this));
    var position = toIntegerOrInfinity$1(pos);
    var size = S.length;
    var first, second;
    if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
    first = charCodeAt$1(S, position);
    return first < 0xD800 || first > 0xDBFF || position + 1 === size
      || (second = charCodeAt$1(S, position + 1)) < 0xDC00 || second > 0xDFFF
        ? CONVERT_TO_STRING
          ? charAt$3(S, position)
          : first
        : CONVERT_TO_STRING
          ? stringSlice(S, position, position + 2)
          : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
  };
};

var stringMultibyte = {
  // `String.prototype.codePointAt` method
  // https://tc39.es/ecma262/#sec-string.prototype.codepointat
  codeAt: createMethod$4(false),
  // `String.prototype.at` method
  // https://github.com/mathiasbynens/String.prototype.at
  charAt: createMethod$4(true)
};

var global$d = global$l;
var isCallable$9 = isCallable$i;

var WeakMap$1$1 = global$d.WeakMap;

var weakMapBasicDetection = isCallable$9(WeakMap$1$1) && /native code/.test(String(WeakMap$1$1));

var shared$5 = sharedExports;
var uid$2 = uid$4;

var keys$3 = shared$5('keys');

var sharedKey$4 = function (key) {
  return keys$3[key] || (keys$3[key] = uid$2(key));
};

var NATIVE_WEAK_MAP$1 = weakMapBasicDetection;
var global$c = global$l;
var isObject$d = isObject$j;
var createNonEnumerableProperty$4 = createNonEnumerableProperty$6;
var hasOwn$c = hasOwnProperty_1;
var shared$4 = sharedStore;
var sharedKey$3 = sharedKey$4;
var hiddenKeys$4 = hiddenKeys$6;

var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
var TypeError$2 = global$c.TypeError;
var WeakMap$3 = global$c.WeakMap;
var set$3, get$7, has;

var enforce = function (it) {
  return has(it) ? get$7(it) : set$3(it, {});
};

var getterFor = function (TYPE) {
  return function (it) {
    var state;
    if (!isObject$d(it) || (state = get$7(it)).type !== TYPE) {
      throw TypeError$2('Incompatible receiver, ' + TYPE + ' required');
    } return state;
  };
};

if (NATIVE_WEAK_MAP$1 || shared$4.state) {
  var store$1 = shared$4.state || (shared$4.state = new WeakMap$3());
  /* eslint-disable no-self-assign -- prototype methods protection */
  store$1.get = store$1.get;
  store$1.has = store$1.has;
  store$1.set = store$1.set;
  /* eslint-enable no-self-assign -- prototype methods protection */
  set$3 = function (it, metadata) {
    if (store$1.has(it)) throw TypeError$2(OBJECT_ALREADY_INITIALIZED);
    metadata.facade = it;
    store$1.set(it, metadata);
    return metadata;
  };
  get$7 = function (it) {
    return store$1.get(it) || {};
  };
  has = function (it) {
    return store$1.has(it);
  };
} else {
  var STATE = sharedKey$3('state');
  hiddenKeys$4[STATE] = true;
  set$3 = function (it, metadata) {
    if (hasOwn$c(it, STATE)) throw TypeError$2(OBJECT_ALREADY_INITIALIZED);
    metadata.facade = it;
    createNonEnumerableProperty$4(it, STATE, metadata);
    return metadata;
  };
  get$7 = function (it) {
    return hasOwn$c(it, STATE) ? it[STATE] : {};
  };
  has = function (it) {
    return hasOwn$c(it, STATE);
  };
}

var internalState = {
  set: set$3,
  get: get$7,
  has: has,
  enforce: enforce,
  getterFor: getterFor
};

var DESCRIPTORS$c = descriptors;
var hasOwn$b = hasOwnProperty_1;

var FunctionPrototype = Function.prototype;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getDescriptor = DESCRIPTORS$c && Object.getOwnPropertyDescriptor;

var EXISTS = hasOwn$b(FunctionPrototype, 'name');
// additional protection from minified / mangled / dropped function names
var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
var CONFIGURABLE = EXISTS && (!DESCRIPTORS$c || (DESCRIPTORS$c && getDescriptor(FunctionPrototype, 'name').configurable));

var functionName = {
  EXISTS: EXISTS,
  PROPER: PROPER,
  CONFIGURABLE: CONFIGURABLE
};

var objectDefineProperties = {};

var DESCRIPTORS$b = descriptors;
var V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug;
var definePropertyModule$2 = objectDefineProperty;
var anObject$b = anObject$d;
var toIndexedObject$7 = toIndexedObject$b;
var objectKeys$2 = objectKeys$4;

// `Object.defineProperties` method
// https://tc39.es/ecma262/#sec-object.defineproperties
// eslint-disable-next-line es/no-object-defineproperties -- safe
objectDefineProperties.f = DESCRIPTORS$b && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
  anObject$b(O);
  var props = toIndexedObject$7(Properties);
  var keys = objectKeys$2(Properties);
  var length = keys.length;
  var index = 0;
  var key;
  while (length > index) definePropertyModule$2.f(O, key = keys[index++], props[key]);
  return O;
};

var getBuiltIn$a = getBuiltIn$c;

var html$1 = getBuiltIn$a('document', 'documentElement');

/* global ActiveXObject -- old IE, WSH */

var anObject$a = anObject$d;
var definePropertiesModule$1 = objectDefineProperties;
var enumBugKeys$1 = enumBugKeys$3;
var hiddenKeys$3 = hiddenKeys$6;
var html = html$1;
var documentCreateElement = documentCreateElement$1;
var sharedKey$2 = sharedKey$4;

var GT = '>';
var LT = '<';
var PROTOTYPE$1 = 'prototype';
var SCRIPT = 'script';
var IE_PROTO$1 = sharedKey$2('IE_PROTO');

var EmptyConstructor = function () { /* empty */ };

var scriptTag = function (content) {
  return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
};

// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
var NullProtoObjectViaActiveX = function (activeXDocument) {
  activeXDocument.write(scriptTag(''));
  activeXDocument.close();
  var temp = activeXDocument.parentWindow.Object;
  activeXDocument = null; // avoid memory leak
  return temp;
};

// Create object with fake `null` prototype: use iframe Object with cleared prototype
var NullProtoObjectViaIFrame = function () {
  // Thrash, waste and sodomy: IE GC bug
  var iframe = documentCreateElement('iframe');
  var JS = 'java' + SCRIPT + ':';
  var iframeDocument;
  iframe.style.display = 'none';
  html.appendChild(iframe);
  // https://github.com/zloirock/core-js/issues/475
  iframe.src = String(JS);
  iframeDocument = iframe.contentWindow.document;
  iframeDocument.open();
  iframeDocument.write(scriptTag('document.F=Object'));
  iframeDocument.close();
  return iframeDocument.F;
};

// Check for document.domain and active x support
// No need to use active x approach when document.domain is not set
// see https://github.com/es-shims/es5-shim/issues/150
// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
// avoid IE GC bug
var activeXDocument;
var NullProtoObject = function () {
  try {
    activeXDocument = new ActiveXObject('htmlfile');
  } catch (error) { /* ignore */ }
  NullProtoObject = typeof document != 'undefined'
    ? document.domain && activeXDocument
      ? NullProtoObjectViaActiveX(activeXDocument) // old IE
      : NullProtoObjectViaIFrame()
    : NullProtoObjectViaActiveX(activeXDocument); // WSH
  var length = enumBugKeys$1.length;
  while (length--) delete NullProtoObject[PROTOTYPE$1][enumBugKeys$1[length]];
  return NullProtoObject();
};

hiddenKeys$3[IE_PROTO$1] = true;

// `Object.create` method
// https://tc39.es/ecma262/#sec-object.create
// eslint-disable-next-line es/no-object-create -- safe
var objectCreate = Object.create || function create(O, Properties) {
  var result;
  if (O !== null) {
    EmptyConstructor[PROTOTYPE$1] = anObject$a(O);
    result = new EmptyConstructor();
    EmptyConstructor[PROTOTYPE$1] = null;
    // add "__proto__" for Object.getPrototypeOf polyfill
    result[IE_PROTO$1] = O;
  } else result = NullProtoObject();
  return Properties === undefined ? result : definePropertiesModule$1.f(result, Properties);
};

var fails$n = fails$w;

var correctPrototypeGetter = !fails$n(function () {
  function F() { /* empty */ }
  F.prototype.constructor = null;
  // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
  return Object.getPrototypeOf(new F()) !== F.prototype;
});

var hasOwn$a = hasOwnProperty_1;
var isCallable$8 = isCallable$i;
var toObject$a = toObject$d;
var sharedKey$1 = sharedKey$4;
var CORRECT_PROTOTYPE_GETTER$1 = correctPrototypeGetter;

var IE_PROTO = sharedKey$1('IE_PROTO');
var $Object$1 = Object;
var ObjectPrototype$2 = $Object$1.prototype;

// `Object.getPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.getprototypeof
// eslint-disable-next-line es/no-object-getprototypeof -- safe
var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER$1 ? $Object$1.getPrototypeOf : function (O) {
  var object = toObject$a(O);
  if (hasOwn$a(object, IE_PROTO)) return object[IE_PROTO];
  var constructor = object.constructor;
  if (isCallable$8(constructor) && object instanceof constructor) {
    return constructor.prototype;
  } return object instanceof $Object$1 ? ObjectPrototype$2 : null;
};

var createNonEnumerableProperty$3 = createNonEnumerableProperty$6;

var defineBuiltIn$5 = function (target, key, value, options) {
  if (options && options.enumerable) target[key] = value;
  else createNonEnumerableProperty$3(target, key, value);
  return target;
};

var fails$m = fails$w;
var isCallable$7 = isCallable$i;
var isObject$c = isObject$j;
var create$b = objectCreate;
var getPrototypeOf$9 = objectGetPrototypeOf;
var defineBuiltIn$4 = defineBuiltIn$5;
var wellKnownSymbol$h = wellKnownSymbol$l;

var ITERATOR$6 = wellKnownSymbol$h('iterator');
var BUGGY_SAFARI_ITERATORS$1 = false;

// `%IteratorPrototype%` object
// https://tc39.es/ecma262/#sec-%iteratorprototype%-object
var IteratorPrototype$1, PrototypeOfArrayIteratorPrototype, arrayIterator;

/* eslint-disable es/no-array-prototype-keys -- safe */
if ([].keys) {
  arrayIterator = [].keys();
  // Safari 8 has buggy iterators w/o `next`
  if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS$1 = true;
  else {
    PrototypeOfArrayIteratorPrototype = getPrototypeOf$9(getPrototypeOf$9(arrayIterator));
    if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$1 = PrototypeOfArrayIteratorPrototype;
  }
}

var NEW_ITERATOR_PROTOTYPE = !isObject$c(IteratorPrototype$1) || fails$m(function () {
  var test = {};
  // FF44- legacy iterators case
  return IteratorPrototype$1[ITERATOR$6].call(test) !== test;
});

if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype$1 = {};
else IteratorPrototype$1 = create$b(IteratorPrototype$1);

// `%IteratorPrototype%[@@iterator]()` method
// https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
if (!isCallable$7(IteratorPrototype$1[ITERATOR$6])) {
  defineBuiltIn$4(IteratorPrototype$1, ITERATOR$6, function () {
    return this;
  });
}

var iteratorsCore = {
  IteratorPrototype: IteratorPrototype$1,
  BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1
};

var TO_STRING_TAG_SUPPORT$1 = toStringTagSupport;
var classof$b = classof$d;

// `Object.prototype.toString` method implementation
// https://tc39.es/ecma262/#sec-object.prototype.tostring
var objectToString = TO_STRING_TAG_SUPPORT$1 ? {}.toString : function toString() {
  return '[object ' + classof$b(this) + ']';
};

var TO_STRING_TAG_SUPPORT = toStringTagSupport;
var defineProperty$d = objectDefineProperty.f;
var createNonEnumerableProperty$2 = createNonEnumerableProperty$6;
var hasOwn$9 = hasOwnProperty_1;
var toString$8 = objectToString;
var wellKnownSymbol$g = wellKnownSymbol$l;

var TO_STRING_TAG$1 = wellKnownSymbol$g('toStringTag');

var setToStringTag$6 = function (it, TAG, STATIC, SET_METHOD) {
  if (it) {
    var target = STATIC ? it : it.prototype;
    if (!hasOwn$9(target, TO_STRING_TAG$1)) {
      defineProperty$d(target, TO_STRING_TAG$1, { configurable: true, value: TAG });
    }
    if (SET_METHOD && !TO_STRING_TAG_SUPPORT) {
      createNonEnumerableProperty$2(target, 'toString', toString$8);
    }
  }
};

var iterators = {};

var IteratorPrototype = iteratorsCore.IteratorPrototype;
var create$a = objectCreate;
var createPropertyDescriptor$2 = createPropertyDescriptor$5;
var setToStringTag$5 = setToStringTag$6;
var Iterators$5 = iterators;

var returnThis$1 = function () { return this; };

var iteratorCreateConstructor = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
  var TO_STRING_TAG = NAME + ' Iterator';
  IteratorConstructor.prototype = create$a(IteratorPrototype, { next: createPropertyDescriptor$2(+!ENUMERABLE_NEXT, next) });
  setToStringTag$5(IteratorConstructor, TO_STRING_TAG, false, true);
  Iterators$5[TO_STRING_TAG] = returnThis$1;
  return IteratorConstructor;
};

var uncurryThis$l = functionUncurryThis;
var aCallable$3 = aCallable$7;

var functionUncurryThisAccessor = function (object, key, method) {
  try {
    // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
    return uncurryThis$l(aCallable$3(Object.getOwnPropertyDescriptor(object, key)[method]));
  } catch (error) { /* empty */ }
};

var isCallable$6 = isCallable$i;

var $String$1 = String;
var $TypeError$a = TypeError;

var aPossiblePrototype$1 = function (argument) {
  if (typeof argument == 'object' || isCallable$6(argument)) return argument;
  throw $TypeError$a("Can't set " + $String$1(argument) + ' as a prototype');
};

/* eslint-disable no-proto -- safe */

var uncurryThisAccessor = functionUncurryThisAccessor;
var anObject$9 = anObject$d;
var aPossiblePrototype = aPossiblePrototype$1;

// `Object.setPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.setprototypeof
// Works with __proto__ only. Old v8 can't work with null proto objects.
// eslint-disable-next-line es/no-object-setprototypeof -- safe
var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
  var CORRECT_SETTER = false;
  var test = {};
  var setter;
  try {
    setter = uncurryThisAccessor(Object.prototype, '__proto__', 'set');
    setter(test, []);
    CORRECT_SETTER = test instanceof Array;
  } catch (error) { /* empty */ }
  return function setPrototypeOf(O, proto) {
    anObject$9(O);
    aPossiblePrototype(proto);
    if (CORRECT_SETTER) setter(O, proto);
    else O.__proto__ = proto;
    return O;
  };
}() : undefined);

var $$M = _export;
var call$8 = functionCall;
var FunctionName = functionName;
var createIteratorConstructor = iteratorCreateConstructor;
var getPrototypeOf$8 = objectGetPrototypeOf;
var setToStringTag$4 = setToStringTag$6;
var defineBuiltIn$3 = defineBuiltIn$5;
var wellKnownSymbol$f = wellKnownSymbol$l;
var Iterators$4 = iterators;
var IteratorsCore = iteratorsCore;

var PROPER_FUNCTION_NAME$1 = FunctionName.PROPER;
var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
var ITERATOR$5 = wellKnownSymbol$f('iterator');
var KEYS = 'keys';
var VALUES = 'values';
var ENTRIES = 'entries';

var returnThis = function () { return this; };

var iteratorDefine = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
  createIteratorConstructor(IteratorConstructor, NAME, next);

  var getIterationMethod = function (KIND) {
    if (KIND === DEFAULT && defaultIterator) return defaultIterator;
    if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
    switch (KIND) {
      case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
      case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
      case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
    } return function () { return new IteratorConstructor(this); };
  };

  var TO_STRING_TAG = NAME + ' Iterator';
  var INCORRECT_VALUES_NAME = false;
  var IterablePrototype = Iterable.prototype;
  var nativeIterator = IterablePrototype[ITERATOR$5]
    || IterablePrototype['@@iterator']
    || DEFAULT && IterablePrototype[DEFAULT];
  var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
  var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
  var CurrentIteratorPrototype, methods, KEY;

  // fix native
  if (anyNativeIterator) {
    CurrentIteratorPrototype = getPrototypeOf$8(anyNativeIterator.call(new Iterable()));
    if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
      // Set @@toStringTag to native iterators
      setToStringTag$4(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
      Iterators$4[TO_STRING_TAG] = returnThis;
    }
  }

  // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
  if (PROPER_FUNCTION_NAME$1 && DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
    {
      INCORRECT_VALUES_NAME = true;
      defaultIterator = function values() { return call$8(nativeIterator, this); };
    }
  }

  // export additional methods
  if (DEFAULT) {
    methods = {
      values: getIterationMethod(VALUES),
      keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
      entries: getIterationMethod(ENTRIES)
    };
    if (FORCED) for (KEY in methods) {
      if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
        defineBuiltIn$3(IterablePrototype, KEY, methods[KEY]);
      }
    } else $$M({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
  }

  // define iterator
  if ((FORCED) && IterablePrototype[ITERATOR$5] !== defaultIterator) {
    defineBuiltIn$3(IterablePrototype, ITERATOR$5, defaultIterator, { name: DEFAULT });
  }
  Iterators$4[NAME] = defaultIterator;

  return methods;
};

// `CreateIterResultObject` abstract operation
// https://tc39.es/ecma262/#sec-createiterresultobject
var createIterResultObject$3 = function (value, done) {
  return { value: value, done: done };
};

var charAt$2 = stringMultibyte.charAt;
var toString$7 = toString$a;
var InternalStateModule$5 = internalState;
var defineIterator$2 = iteratorDefine;
var createIterResultObject$2 = createIterResultObject$3;

var STRING_ITERATOR = 'String Iterator';
var setInternalState$5 = InternalStateModule$5.set;
var getInternalState$2 = InternalStateModule$5.getterFor(STRING_ITERATOR);

// `String.prototype[@@iterator]` method
// https://tc39.es/ecma262/#sec-string.prototype-@@iterator
defineIterator$2(String, 'String', function (iterated) {
  setInternalState$5(this, {
    type: STRING_ITERATOR,
    string: toString$7(iterated),
    index: 0
  });
// `%StringIteratorPrototype%.next` method
// https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next
}, function next() {
  var state = getInternalState$2(this);
  var string = state.string;
  var index = state.index;
  var point;
  if (index >= string.length) return createIterResultObject$2(undefined, true);
  point = charAt$2(string, index);
  state.index += point.length;
  return createIterResultObject$2(point, false);
});

var call$7 = functionCall;
var anObject$8 = anObject$d;
var getMethod$1 = getMethod$3;

var iteratorClose$2 = function (iterator, kind, value) {
  var innerResult, innerError;
  anObject$8(iterator);
  try {
    innerResult = getMethod$1(iterator, 'return');
    if (!innerResult) {
      if (kind === 'throw') throw value;
      return value;
    }
    innerResult = call$7(innerResult, iterator);
  } catch (error) {
    innerError = true;
    innerResult = error;
  }
  if (kind === 'throw') throw value;
  if (innerError) throw innerResult;
  anObject$8(innerResult);
  return value;
};

var anObject$7 = anObject$d;
var iteratorClose$1 = iteratorClose$2;

// call something on iterator step with safe closing on error
var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) {
  try {
    return ENTRIES ? fn(anObject$7(value)[0], value[1]) : fn(value);
  } catch (error) {
    iteratorClose$1(iterator, 'throw', error);
  }
};

var wellKnownSymbol$e = wellKnownSymbol$l;
var Iterators$3 = iterators;

var ITERATOR$4 = wellKnownSymbol$e('iterator');
var ArrayPrototype$f = Array.prototype;

// check on default Array iterator
var isArrayIteratorMethod$2 = function (it) {
  return it !== undefined && (Iterators$3.Array === it || ArrayPrototype$f[ITERATOR$4] === it);
};

var uncurryThis$k = functionUncurryThis;
var isCallable$5 = isCallable$i;
var store = sharedStore;

var functionToString = uncurryThis$k(Function.toString);

// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
if (!isCallable$5(store.inspectSource)) {
  store.inspectSource = function (it) {
    return functionToString(it);
  };
}

var inspectSource$1 = store.inspectSource;

var uncurryThis$j = functionUncurryThis;
var fails$l = fails$w;
var isCallable$4 = isCallable$i;
var classof$a = classof$d;
var getBuiltIn$9 = getBuiltIn$c;
var inspectSource = inspectSource$1;

var noop$1 = function () { /* empty */ };
var empty = [];
var construct$3 = getBuiltIn$9('Reflect', 'construct');
var constructorRegExp = /^\s*(?:class|function)\b/;
var exec$2 = uncurryThis$j(constructorRegExp.exec);
var INCORRECT_TO_STRING = !constructorRegExp.exec(noop$1);

var isConstructorModern = function isConstructor(argument) {
  if (!isCallable$4(argument)) return false;
  try {
    construct$3(noop$1, empty, argument);
    return true;
  } catch (error) {
    return false;
  }
};

var isConstructorLegacy = function isConstructor(argument) {
  if (!isCallable$4(argument)) return false;
  switch (classof$a(argument)) {
    case 'AsyncFunction':
    case 'GeneratorFunction':
    case 'AsyncGeneratorFunction': return false;
  }
  try {
    // we can't check .prototype since constructors produced by .bind haven't it
    // `Function#toString` throws on some built-it function in some legacy engines
    // (for example, `DOMQuad` and similar in FF41-)
    return INCORRECT_TO_STRING || !!exec$2(constructorRegExp, inspectSource(argument));
  } catch (error) {
    return true;
  }
};

isConstructorLegacy.sham = true;

// `IsConstructor` abstract operation
// https://tc39.es/ecma262/#sec-isconstructor
var isConstructor$4 = !construct$3 || fails$l(function () {
  var called;
  return isConstructorModern(isConstructorModern.call)
    || !isConstructorModern(Object)
    || !isConstructorModern(function () { called = true; })
    || called;
}) ? isConstructorLegacy : isConstructorModern;

var toPropertyKey$1 = toPropertyKey$4;
var definePropertyModule$1 = objectDefineProperty;
var createPropertyDescriptor$1 = createPropertyDescriptor$5;

var createProperty$6 = function (object, key, value) {
  var propertyKey = toPropertyKey$1(key);
  if (propertyKey in object) definePropertyModule$1.f(object, propertyKey, createPropertyDescriptor$1(0, value));
  else object[propertyKey] = value;
};

var classof$9 = classof$d;
var getMethod = getMethod$3;
var isNullOrUndefined$2 = isNullOrUndefined$5;
var Iterators$2 = iterators;
var wellKnownSymbol$d = wellKnownSymbol$l;

var ITERATOR$3 = wellKnownSymbol$d('iterator');

var getIteratorMethod$9 = function (it) {
  if (!isNullOrUndefined$2(it)) return getMethod(it, ITERATOR$3)
    || getMethod(it, '@@iterator')
    || Iterators$2[classof$9(it)];
};

var call$6 = functionCall;
var aCallable$2 = aCallable$7;
var anObject$6 = anObject$d;
var tryToString$4 = tryToString$6;
var getIteratorMethod$8 = getIteratorMethod$9;

var $TypeError$9 = TypeError;

var getIterator$2 = function (argument, usingIterator) {
  var iteratorMethod = arguments.length < 2 ? getIteratorMethod$8(argument) : usingIterator;
  if (aCallable$2(iteratorMethod)) return anObject$6(call$6(iteratorMethod, argument));
  throw $TypeError$9(tryToString$4(argument) + ' is not iterable');
};

var bind$8 = functionBindContext;
var call$5 = functionCall;
var toObject$9 = toObject$d;
var callWithSafeIterationClosing = callWithSafeIterationClosing$1;
var isArrayIteratorMethod$1 = isArrayIteratorMethod$2;
var isConstructor$3 = isConstructor$4;
var lengthOfArrayLike$9 = lengthOfArrayLike$b;
var createProperty$5 = createProperty$6;
var getIterator$1 = getIterator$2;
var getIteratorMethod$7 = getIteratorMethod$9;

var $Array$3 = Array;

// `Array.from` method implementation
// https://tc39.es/ecma262/#sec-array.from
var arrayFrom = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
  var O = toObject$9(arrayLike);
  var IS_CONSTRUCTOR = isConstructor$3(this);
  var argumentsLength = arguments.length;
  var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
  var mapping = mapfn !== undefined;
  if (mapping) mapfn = bind$8(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
  var iteratorMethod = getIteratorMethod$7(O);
  var index = 0;
  var length, result, step, iterator, next, value;
  // if the target is not iterable or it's an array with the default iterator - use a simple case
  if (iteratorMethod && !(this === $Array$3 && isArrayIteratorMethod$1(iteratorMethod))) {
    iterator = getIterator$1(O, iteratorMethod);
    next = iterator.next;
    result = IS_CONSTRUCTOR ? new this() : [];
    for (;!(step = call$5(next, iterator)).done; index++) {
      value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
      createProperty$5(result, index, value);
    }
  } else {
    length = lengthOfArrayLike$9(O);
    result = IS_CONSTRUCTOR ? new this(length) : $Array$3(length);
    for (;length > index; index++) {
      value = mapping ? mapfn(O[index], index) : O[index];
      createProperty$5(result, index, value);
    }
  }
  result.length = index;
  return result;
};

var wellKnownSymbol$c = wellKnownSymbol$l;

var ITERATOR$2 = wellKnownSymbol$c('iterator');
var SAFE_CLOSING = false;

try {
  var called = 0;
  var iteratorWithReturn = {
    next: function () {
      return { done: !!called++ };
    },
    'return': function () {
      SAFE_CLOSING = true;
    }
  };
  iteratorWithReturn[ITERATOR$2] = function () {
    return this;
  };
  // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
  Array.from(iteratorWithReturn, function () { throw 2; });
} catch (error) { /* empty */ }

var checkCorrectnessOfIteration$1 = function (exec, SKIP_CLOSING) {
  if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
  var ITERATION_SUPPORT = false;
  try {
    var object = {};
    object[ITERATOR$2] = function () {
      return {
        next: function () {
          return { done: ITERATION_SUPPORT = true };
        }
      };
    };
    exec(object);
  } catch (error) { /* empty */ }
  return ITERATION_SUPPORT;
};

var $$L = _export;
var from$6 = arrayFrom;
var checkCorrectnessOfIteration = checkCorrectnessOfIteration$1;

var INCORRECT_ITERATION = !checkCorrectnessOfIteration(function (iterable) {
  // eslint-disable-next-line es/no-array-from -- required for testing
  Array.from(iterable);
});

// `Array.from` method
// https://tc39.es/ecma262/#sec-array.from
$$L({ target: 'Array', stat: true, forced: INCORRECT_ITERATION }, {
  from: from$6
});

var path$t = path$y;

var from$5 = path$t.Array.from;

var parent$19 = from$5;

var from$4 = parent$19;

(function (module) {
	module.exports = from$4;
} (from$7));

var _Array$from$1 = /*@__PURE__*/getDefaultExportFromCjs$1(fromExports$2);

var getIteratorMethodExports$1 = {};
var getIteratorMethod$6 = {
  get exports(){ return getIteratorMethodExports$1; },
  set exports(v){ getIteratorMethodExports$1 = v; },
};

var getIteratorMethodExports = {};
var getIteratorMethod$5 = {
  get exports(){ return getIteratorMethodExports; },
  set exports(v){ getIteratorMethodExports = v; },
};

var toIndexedObject$6 = toIndexedObject$b;
var Iterators$1 = iterators;
var InternalStateModule$4 = internalState;
objectDefineProperty.f;
var defineIterator$1 = iteratorDefine;
var createIterResultObject$1 = createIterResultObject$3;

var ARRAY_ITERATOR = 'Array Iterator';
var setInternalState$4 = InternalStateModule$4.set;
var getInternalState$1 = InternalStateModule$4.getterFor(ARRAY_ITERATOR);

// `Array.prototype.entries` method
// https://tc39.es/ecma262/#sec-array.prototype.entries
// `Array.prototype.keys` method
// https://tc39.es/ecma262/#sec-array.prototype.keys
// `Array.prototype.values` method
// https://tc39.es/ecma262/#sec-array.prototype.values
// `Array.prototype[@@iterator]` method
// https://tc39.es/ecma262/#sec-array.prototype-@@iterator
// `CreateArrayIterator` internal method
// https://tc39.es/ecma262/#sec-createarrayiterator
defineIterator$1(Array, 'Array', function (iterated, kind) {
  setInternalState$4(this, {
    type: ARRAY_ITERATOR,
    target: toIndexedObject$6(iterated), // target
    index: 0,                          // next index
    kind: kind                         // kind
  });
// `%ArrayIteratorPrototype%.next` method
// https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
}, function () {
  var state = getInternalState$1(this);
  var target = state.target;
  var kind = state.kind;
  var index = state.index++;
  if (!target || index >= target.length) {
    state.target = undefined;
    return createIterResultObject$1(undefined, true);
  }
  if (kind == 'keys') return createIterResultObject$1(index, false);
  if (kind == 'values') return createIterResultObject$1(target[index], false);
  return createIterResultObject$1([index, target[index]], false);
}, 'values');

// argumentsList[@@iterator] is %ArrayProto_values%
// https://tc39.es/ecma262/#sec-createunmappedargumentsobject
// https://tc39.es/ecma262/#sec-createmappedargumentsobject
Iterators$1.Arguments = Iterators$1.Array;

var getIteratorMethod$4 = getIteratorMethod$9;

var getIteratorMethod_1 = getIteratorMethod$4;

// iterable DOM collections
// flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
var domIterables = {
  CSSRuleList: 0,
  CSSStyleDeclaration: 0,
  CSSValueList: 0,
  ClientRectList: 0,
  DOMRectList: 0,
  DOMStringList: 0,
  DOMTokenList: 1,
  DataTransferItemList: 0,
  FileList: 0,
  HTMLAllCollection: 0,
  HTMLCollection: 0,
  HTMLFormElement: 0,
  HTMLSelectElement: 0,
  MediaList: 0,
  MimeTypeArray: 0,
  NamedNodeMap: 0,
  NodeList: 1,
  PaintRequestList: 0,
  Plugin: 0,
  PluginArray: 0,
  SVGLengthList: 0,
  SVGNumberList: 0,
  SVGPathSegList: 0,
  SVGPointList: 0,
  SVGStringList: 0,
  SVGTransformList: 0,
  SourceBufferList: 0,
  StyleSheetList: 0,
  TextTrackCueList: 0,
  TextTrackList: 0,
  TouchList: 0
};

var DOMIterables$2 = domIterables;
var global$b = global$l;
var classof$8 = classof$d;
var createNonEnumerableProperty$1 = createNonEnumerableProperty$6;
var Iterators = iterators;
var wellKnownSymbol$b = wellKnownSymbol$l;

var TO_STRING_TAG = wellKnownSymbol$b('toStringTag');

for (var COLLECTION_NAME in DOMIterables$2) {
  var Collection = global$b[COLLECTION_NAME];
  var CollectionPrototype = Collection && Collection.prototype;
  if (CollectionPrototype && classof$8(CollectionPrototype) !== TO_STRING_TAG) {
    createNonEnumerableProperty$1(CollectionPrototype, TO_STRING_TAG, COLLECTION_NAME);
  }
  Iterators[COLLECTION_NAME] = Iterators.Array;
}

var parent$18 = getIteratorMethod_1;


var getIteratorMethod$3 = parent$18;

var parent$17 = getIteratorMethod$3;

var getIteratorMethod$2 = parent$17;

var parent$16 = getIteratorMethod$2;

var getIteratorMethod$1 = parent$16;

(function (module) {
	module.exports = getIteratorMethod$1;
} (getIteratorMethod$5));

(function (module) {
	module.exports = getIteratorMethodExports;
} (getIteratorMethod$6));

var _getIteratorMethod = /*@__PURE__*/getDefaultExportFromCjs$1(getIteratorMethodExports$1);

var getOwnPropertySymbolsExports = {};
var getOwnPropertySymbols$2 = {
  get exports(){ return getOwnPropertySymbolsExports; },
  set exports(v){ getOwnPropertySymbolsExports = v; },
};

var objectGetOwnPropertyNames = {};

var internalObjectKeys = objectKeysInternal;
var enumBugKeys = enumBugKeys$3;

var hiddenKeys$2 = enumBugKeys.concat('length', 'prototype');

// `Object.getOwnPropertyNames` method
// https://tc39.es/ecma262/#sec-object.getownpropertynames
// eslint-disable-next-line es/no-object-getownpropertynames -- safe
objectGetOwnPropertyNames.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
  return internalObjectKeys(O, hiddenKeys$2);
};

var objectGetOwnPropertyNamesExternal = {};

var toAbsoluteIndex$3 = toAbsoluteIndex$5;
var lengthOfArrayLike$8 = lengthOfArrayLike$b;
var createProperty$4 = createProperty$6;

var $Array$2 = Array;
var max$2 = Math.max;

var arraySliceSimple = function (O, start, end) {
  var length = lengthOfArrayLike$8(O);
  var k = toAbsoluteIndex$3(start, length);
  var fin = toAbsoluteIndex$3(end === undefined ? length : end, length);
  var result = $Array$2(max$2(fin - k, 0));
  for (var n = 0; k < fin; k++, n++) createProperty$4(result, n, O[k]);
  result.length = n;
  return result;
};

/* eslint-disable es/no-object-getownpropertynames -- safe */

var classof$7 = classofRaw$2;
var toIndexedObject$5 = toIndexedObject$b;
var $getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
var arraySlice$3 = arraySliceSimple;

var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
  ? Object.getOwnPropertyNames(window) : [];

var getWindowNames = function (it) {
  try {
    return $getOwnPropertyNames$1(it);
  } catch (error) {
    return arraySlice$3(windowNames);
  }
};

// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
objectGetOwnPropertyNamesExternal.f = function getOwnPropertyNames(it) {
  return windowNames && classof$7(it) == 'Window'
    ? getWindowNames(it)
    : $getOwnPropertyNames$1(toIndexedObject$5(it));
};

var defineProperty$c = objectDefineProperty;

var defineBuiltInAccessor$3 = function (target, name, descriptor) {
  return defineProperty$c.f(target, name, descriptor);
};

var wellKnownSymbolWrapped = {};

var wellKnownSymbol$a = wellKnownSymbol$l;

wellKnownSymbolWrapped.f = wellKnownSymbol$a;

var path$s = path$y;
var hasOwn$8 = hasOwnProperty_1;
var wrappedWellKnownSymbolModule$1 = wellKnownSymbolWrapped;
var defineProperty$b = objectDefineProperty.f;

var wellKnownSymbolDefine = function (NAME) {
  var Symbol = path$s.Symbol || (path$s.Symbol = {});
  if (!hasOwn$8(Symbol, NAME)) defineProperty$b(Symbol, NAME, {
    value: wrappedWellKnownSymbolModule$1.f(NAME)
  });
};

var call$4 = functionCall;
var getBuiltIn$8 = getBuiltIn$c;
var wellKnownSymbol$9 = wellKnownSymbol$l;
var defineBuiltIn$2 = defineBuiltIn$5;

var symbolDefineToPrimitive = function () {
  var Symbol = getBuiltIn$8('Symbol');
  var SymbolPrototype = Symbol && Symbol.prototype;
  var valueOf = SymbolPrototype && SymbolPrototype.valueOf;
  var TO_PRIMITIVE = wellKnownSymbol$9('toPrimitive');

  if (SymbolPrototype && !SymbolPrototype[TO_PRIMITIVE]) {
    // `Symbol.prototype[@@toPrimitive]` method
    // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
    // eslint-disable-next-line no-unused-vars -- required for .length
    defineBuiltIn$2(SymbolPrototype, TO_PRIMITIVE, function (hint) {
      return call$4(valueOf, this);
    }, { arity: 1 });
  }
};

var classof$6 = classofRaw$2;

// `IsArray` abstract operation
// https://tc39.es/ecma262/#sec-isarray
// eslint-disable-next-line es/no-array-isarray -- safe
var isArray$f = Array.isArray || function isArray(argument) {
  return classof$6(argument) == 'Array';
};

var isArray$e = isArray$f;
var isConstructor$2 = isConstructor$4;
var isObject$b = isObject$j;
var wellKnownSymbol$8 = wellKnownSymbol$l;

var SPECIES$3 = wellKnownSymbol$8('species');
var $Array$1 = Array;

// a part of `ArraySpeciesCreate` abstract operation
// https://tc39.es/ecma262/#sec-arrayspeciescreate
var arraySpeciesConstructor$1 = function (originalArray) {
  var C;
  if (isArray$e(originalArray)) {
    C = originalArray.constructor;
    // cross-realm fallback
    if (isConstructor$2(C) && (C === $Array$1 || isArray$e(C.prototype))) C = undefined;
    else if (isObject$b(C)) {
      C = C[SPECIES$3];
      if (C === null) C = undefined;
    }
  } return C === undefined ? $Array$1 : C;
};

var arraySpeciesConstructor = arraySpeciesConstructor$1;

// `ArraySpeciesCreate` abstract operation
// https://tc39.es/ecma262/#sec-arrayspeciescreate
var arraySpeciesCreate$3 = function (originalArray, length) {
  return new (arraySpeciesConstructor(originalArray))(length === 0 ? 0 : length);
};

var bind$7 = functionBindContext;
var uncurryThis$i = functionUncurryThis;
var IndexedObject$1 = indexedObject;
var toObject$8 = toObject$d;
var lengthOfArrayLike$7 = lengthOfArrayLike$b;
var arraySpeciesCreate$2 = arraySpeciesCreate$3;

var push$5 = uncurryThis$i([].push);

// `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterReject }` methods implementation
var createMethod$3 = function (TYPE) {
  var IS_MAP = TYPE == 1;
  var IS_FILTER = TYPE == 2;
  var IS_SOME = TYPE == 3;
  var IS_EVERY = TYPE == 4;
  var IS_FIND_INDEX = TYPE == 6;
  var IS_FILTER_REJECT = TYPE == 7;
  var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
  return function ($this, callbackfn, that, specificCreate) {
    var O = toObject$8($this);
    var self = IndexedObject$1(O);
    var boundFunction = bind$7(callbackfn, that);
    var length = lengthOfArrayLike$7(self);
    var index = 0;
    var create = specificCreate || arraySpeciesCreate$2;
    var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_REJECT ? create($this, 0) : undefined;
    var value, result;
    for (;length > index; index++) if (NO_HOLES || index in self) {
      value = self[index];
      result = boundFunction(value, index, O);
      if (TYPE) {
        if (IS_MAP) target[index] = result; // map
        else if (result) switch (TYPE) {
          case 3: return true;              // some
          case 5: return value;             // find
          case 6: return index;             // findIndex
          case 2: push$5(target, value);      // filter
        } else switch (TYPE) {
          case 4: return false;             // every
          case 7: push$5(target, value);      // filterReject
        }
      }
    }
    return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
  };
};

var arrayIteration = {
  // `Array.prototype.forEach` method
  // https://tc39.es/ecma262/#sec-array.prototype.foreach
  forEach: createMethod$3(0),
  // `Array.prototype.map` method
  // https://tc39.es/ecma262/#sec-array.prototype.map
  map: createMethod$3(1),
  // `Array.prototype.filter` method
  // https://tc39.es/ecma262/#sec-array.prototype.filter
  filter: createMethod$3(2),
  // `Array.prototype.some` method
  // https://tc39.es/ecma262/#sec-array.prototype.some
  some: createMethod$3(3),
  // `Array.prototype.every` method
  // https://tc39.es/ecma262/#sec-array.prototype.every
  every: createMethod$3(4),
  // `Array.prototype.find` method
  // https://tc39.es/ecma262/#sec-array.prototype.find
  find: createMethod$3(5),
  // `Array.prototype.findIndex` method
  // https://tc39.es/ecma262/#sec-array.prototype.findIndex
  findIndex: createMethod$3(6),
  // `Array.prototype.filterReject` method
  // https://github.com/tc39/proposal-array-filtering
  filterReject: createMethod$3(7)
};

var $$K = _export;
var global$a = global$l;
var call$3 = functionCall;
var uncurryThis$h = functionUncurryThis;
var DESCRIPTORS$a = descriptors;
var NATIVE_SYMBOL$3 = symbolConstructorDetection;
var fails$k = fails$w;
var hasOwn$7 = hasOwnProperty_1;
var isPrototypeOf$i = objectIsPrototypeOf;
var anObject$5 = anObject$d;
var toIndexedObject$4 = toIndexedObject$b;
var toPropertyKey = toPropertyKey$4;
var $toString = toString$a;
var createPropertyDescriptor = createPropertyDescriptor$5;
var nativeObjectCreate = objectCreate;
var objectKeys$1 = objectKeys$4;
var getOwnPropertyNamesModule$2 = objectGetOwnPropertyNames;
var getOwnPropertyNamesExternal = objectGetOwnPropertyNamesExternal;
var getOwnPropertySymbolsModule$2 = objectGetOwnPropertySymbols;
var getOwnPropertyDescriptorModule$2 = objectGetOwnPropertyDescriptor;
var definePropertyModule = objectDefineProperty;
var definePropertiesModule = objectDefineProperties;
var propertyIsEnumerableModule = objectPropertyIsEnumerable;
var defineBuiltIn$1 = defineBuiltIn$5;
var defineBuiltInAccessor$2 = defineBuiltInAccessor$3;
var shared$3 = sharedExports;
var sharedKey = sharedKey$4;
var hiddenKeys$1 = hiddenKeys$6;
var uid$1 = uid$4;
var wellKnownSymbol$7 = wellKnownSymbol$l;
var wrappedWellKnownSymbolModule = wellKnownSymbolWrapped;
var defineWellKnownSymbol$l = wellKnownSymbolDefine;
var defineSymbolToPrimitive$1 = symbolDefineToPrimitive;
var setToStringTag$3 = setToStringTag$6;
var InternalStateModule$3 = internalState;
var $forEach$1 = arrayIteration.forEach;

var HIDDEN = sharedKey('hidden');
var SYMBOL = 'Symbol';
var PROTOTYPE = 'prototype';

var setInternalState$3 = InternalStateModule$3.set;
var getInternalState = InternalStateModule$3.getterFor(SYMBOL);

var ObjectPrototype$1 = Object[PROTOTYPE];
var $Symbol = global$a.Symbol;
var SymbolPrototype = $Symbol && $Symbol[PROTOTYPE];
var TypeError$1 = global$a.TypeError;
var QObject = global$a.QObject;
var nativeGetOwnPropertyDescriptor$1 = getOwnPropertyDescriptorModule$2.f;
var nativeDefineProperty = definePropertyModule.f;
var nativeGetOwnPropertyNames = getOwnPropertyNamesExternal.f;
var nativePropertyIsEnumerable = propertyIsEnumerableModule.f;
var push$4 = uncurryThis$h([].push);

var AllSymbols = shared$3('symbols');
var ObjectPrototypeSymbols = shared$3('op-symbols');
var WellKnownSymbolsStore$1 = shared$3('wks');

// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
var USE_SETTER = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;

// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
var setSymbolDescriptor = DESCRIPTORS$a && fails$k(function () {
  return nativeObjectCreate(nativeDefineProperty({}, 'a', {
    get: function () { return nativeDefineProperty(this, 'a', { value: 7 }).a; }
  })).a != 7;
}) ? function (O, P, Attributes) {
  var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$1(ObjectPrototype$1, P);
  if (ObjectPrototypeDescriptor) delete ObjectPrototype$1[P];
  nativeDefineProperty(O, P, Attributes);
  if (ObjectPrototypeDescriptor && O !== ObjectPrototype$1) {
    nativeDefineProperty(ObjectPrototype$1, P, ObjectPrototypeDescriptor);
  }
} : nativeDefineProperty;

var wrap$1 = function (tag, description) {
  var symbol = AllSymbols[tag] = nativeObjectCreate(SymbolPrototype);
  setInternalState$3(symbol, {
    type: SYMBOL,
    tag: tag,
    description: description
  });
  if (!DESCRIPTORS$a) symbol.description = description;
  return symbol;
};

var $defineProperty = function defineProperty(O, P, Attributes) {
  if (O === ObjectPrototype$1) $defineProperty(ObjectPrototypeSymbols, P, Attributes);
  anObject$5(O);
  var key = toPropertyKey(P);
  anObject$5(Attributes);
  if (hasOwn$7(AllSymbols, key)) {
    if (!Attributes.enumerable) {
      if (!hasOwn$7(O, HIDDEN)) nativeDefineProperty(O, HIDDEN, createPropertyDescriptor(1, {}));
      O[HIDDEN][key] = true;
    } else {
      if (hasOwn$7(O, HIDDEN) && O[HIDDEN][key]) O[HIDDEN][key] = false;
      Attributes = nativeObjectCreate(Attributes, { enumerable: createPropertyDescriptor(0, false) });
    } return setSymbolDescriptor(O, key, Attributes);
  } return nativeDefineProperty(O, key, Attributes);
};

var $defineProperties = function defineProperties(O, Properties) {
  anObject$5(O);
  var properties = toIndexedObject$4(Properties);
  var keys = objectKeys$1(properties).concat($getOwnPropertySymbols(properties));
  $forEach$1(keys, function (key) {
    if (!DESCRIPTORS$a || call$3($propertyIsEnumerable$1, properties, key)) $defineProperty(O, key, properties[key]);
  });
  return O;
};

var $create = function create(O, Properties) {
  return Properties === undefined ? nativeObjectCreate(O) : $defineProperties(nativeObjectCreate(O), Properties);
};

var $propertyIsEnumerable$1 = function propertyIsEnumerable(V) {
  var P = toPropertyKey(V);
  var enumerable = call$3(nativePropertyIsEnumerable, this, P);
  if (this === ObjectPrototype$1 && hasOwn$7(AllSymbols, P) && !hasOwn$7(ObjectPrototypeSymbols, P)) return false;
  return enumerable || !hasOwn$7(this, P) || !hasOwn$7(AllSymbols, P) || hasOwn$7(this, HIDDEN) && this[HIDDEN][P]
    ? enumerable : true;
};

var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(O, P) {
  var it = toIndexedObject$4(O);
  var key = toPropertyKey(P);
  if (it === ObjectPrototype$1 && hasOwn$7(AllSymbols, key) && !hasOwn$7(ObjectPrototypeSymbols, key)) return;
  var descriptor = nativeGetOwnPropertyDescriptor$1(it, key);
  if (descriptor && hasOwn$7(AllSymbols, key) && !(hasOwn$7(it, HIDDEN) && it[HIDDEN][key])) {
    descriptor.enumerable = true;
  }
  return descriptor;
};

var $getOwnPropertyNames = function getOwnPropertyNames(O) {
  var names = nativeGetOwnPropertyNames(toIndexedObject$4(O));
  var result = [];
  $forEach$1(names, function (key) {
    if (!hasOwn$7(AllSymbols, key) && !hasOwn$7(hiddenKeys$1, key)) push$4(result, key);
  });
  return result;
};

var $getOwnPropertySymbols = function (O) {
  var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$1;
  var names = nativeGetOwnPropertyNames(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols : toIndexedObject$4(O));
  var result = [];
  $forEach$1(names, function (key) {
    if (hasOwn$7(AllSymbols, key) && (!IS_OBJECT_PROTOTYPE || hasOwn$7(ObjectPrototype$1, key))) {
      push$4(result, AllSymbols[key]);
    }
  });
  return result;
};

// `Symbol` constructor
// https://tc39.es/ecma262/#sec-symbol-constructor
if (!NATIVE_SYMBOL$3) {
  $Symbol = function Symbol() {
    if (isPrototypeOf$i(SymbolPrototype, this)) throw TypeError$1('Symbol is not a constructor');
    var description = !arguments.length || arguments[0] === undefined ? undefined : $toString(arguments[0]);
    var tag = uid$1(description);
    var setter = function (value) {
      if (this === ObjectPrototype$1) call$3(setter, ObjectPrototypeSymbols, value);
      if (hasOwn$7(this, HIDDEN) && hasOwn$7(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
      setSymbolDescriptor(this, tag, createPropertyDescriptor(1, value));
    };
    if (DESCRIPTORS$a && USE_SETTER) setSymbolDescriptor(ObjectPrototype$1, tag, { configurable: true, set: setter });
    return wrap$1(tag, description);
  };

  SymbolPrototype = $Symbol[PROTOTYPE];

  defineBuiltIn$1(SymbolPrototype, 'toString', function toString() {
    return getInternalState(this).tag;
  });

  defineBuiltIn$1($Symbol, 'withoutSetter', function (description) {
    return wrap$1(uid$1(description), description);
  });

  propertyIsEnumerableModule.f = $propertyIsEnumerable$1;
  definePropertyModule.f = $defineProperty;
  definePropertiesModule.f = $defineProperties;
  getOwnPropertyDescriptorModule$2.f = $getOwnPropertyDescriptor;
  getOwnPropertyNamesModule$2.f = getOwnPropertyNamesExternal.f = $getOwnPropertyNames;
  getOwnPropertySymbolsModule$2.f = $getOwnPropertySymbols;

  wrappedWellKnownSymbolModule.f = function (name) {
    return wrap$1(wellKnownSymbol$7(name), name);
  };

  if (DESCRIPTORS$a) {
    // https://github.com/tc39/proposal-Symbol-description
    defineBuiltInAccessor$2(SymbolPrototype, 'description', {
      configurable: true,
      get: function description() {
        return getInternalState(this).description;
      }
    });
  }
}

$$K({ global: true, constructor: true, wrap: true, forced: !NATIVE_SYMBOL$3, sham: !NATIVE_SYMBOL$3 }, {
  Symbol: $Symbol
});

$forEach$1(objectKeys$1(WellKnownSymbolsStore$1), function (name) {
  defineWellKnownSymbol$l(name);
});

$$K({ target: SYMBOL, stat: true, forced: !NATIVE_SYMBOL$3 }, {
  useSetter: function () { USE_SETTER = true; },
  useSimple: function () { USE_SETTER = false; }
});

$$K({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$3, sham: !DESCRIPTORS$a }, {
  // `Object.create` method
  // https://tc39.es/ecma262/#sec-object.create
  create: $create,
  // `Object.defineProperty` method
  // https://tc39.es/ecma262/#sec-object.defineproperty
  defineProperty: $defineProperty,
  // `Object.defineProperties` method
  // https://tc39.es/ecma262/#sec-object.defineproperties
  defineProperties: $defineProperties,
  // `Object.getOwnPropertyDescriptor` method
  // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
  getOwnPropertyDescriptor: $getOwnPropertyDescriptor
});

$$K({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$3 }, {
  // `Object.getOwnPropertyNames` method
  // https://tc39.es/ecma262/#sec-object.getownpropertynames
  getOwnPropertyNames: $getOwnPropertyNames
});

// `Symbol.prototype[@@toPrimitive]` method
// https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
defineSymbolToPrimitive$1();

// `Symbol.prototype[@@toStringTag]` property
// https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
setToStringTag$3($Symbol, SYMBOL);

hiddenKeys$1[HIDDEN] = true;

var NATIVE_SYMBOL$2 = symbolConstructorDetection;

/* eslint-disable es/no-symbol -- safe */
var symbolRegistryDetection = NATIVE_SYMBOL$2 && !!Symbol['for'] && !!Symbol.keyFor;

var $$J = _export;
var getBuiltIn$7 = getBuiltIn$c;
var hasOwn$6 = hasOwnProperty_1;
var toString$6 = toString$a;
var shared$2 = sharedExports;
var NATIVE_SYMBOL_REGISTRY$1 = symbolRegistryDetection;

var StringToSymbolRegistry = shared$2('string-to-symbol-registry');
var SymbolToStringRegistry$1 = shared$2('symbol-to-string-registry');

// `Symbol.for` method
// https://tc39.es/ecma262/#sec-symbol.for
$$J({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY$1 }, {
  'for': function (key) {
    var string = toString$6(key);
    if (hasOwn$6(StringToSymbolRegistry, string)) return StringToSymbolRegistry[string];
    var symbol = getBuiltIn$7('Symbol')(string);
    StringToSymbolRegistry[string] = symbol;
    SymbolToStringRegistry$1[symbol] = string;
    return symbol;
  }
});

var $$I = _export;
var hasOwn$5 = hasOwnProperty_1;
var isSymbol$2 = isSymbol$5;
var tryToString$3 = tryToString$6;
var shared$1 = sharedExports;
var NATIVE_SYMBOL_REGISTRY = symbolRegistryDetection;

var SymbolToStringRegistry = shared$1('symbol-to-string-registry');

// `Symbol.keyFor` method
// https://tc39.es/ecma262/#sec-symbol.keyfor
$$I({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY }, {
  keyFor: function keyFor(sym) {
    if (!isSymbol$2(sym)) throw TypeError(tryToString$3(sym) + ' is not a symbol');
    if (hasOwn$5(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym];
  }
});

var uncurryThis$g = functionUncurryThis;
var isArray$d = isArray$f;
var isCallable$3 = isCallable$i;
var classof$5 = classofRaw$2;
var toString$5 = toString$a;

var push$3 = uncurryThis$g([].push);

var getJsonReplacerFunction = function (replacer) {
  if (isCallable$3(replacer)) return replacer;
  if (!isArray$d(replacer)) return;
  var rawLength = replacer.length;
  var keys = [];
  for (var i = 0; i < rawLength; i++) {
    var element = replacer[i];
    if (typeof element == 'string') push$3(keys, element);
    else if (typeof element == 'number' || classof$5(element) == 'Number' || classof$5(element) == 'String') push$3(keys, toString$5(element));
  }
  var keysLength = keys.length;
  var root = true;
  return function (key, value) {
    if (root) {
      root = false;
      return value;
    }
    if (isArray$d(this)) return value;
    for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value;
  };
};

var $$H = _export;
var getBuiltIn$6 = getBuiltIn$c;
var apply$3 = functionApply;
var call$2 = functionCall;
var uncurryThis$f = functionUncurryThis;
var fails$j = fails$w;
var isCallable$2 = isCallable$i;
var isSymbol$1 = isSymbol$5;
var arraySlice$2 = arraySlice$5;
var getReplacerFunction = getJsonReplacerFunction;
var NATIVE_SYMBOL$1 = symbolConstructorDetection;

var $String = String;
var $stringify = getBuiltIn$6('JSON', 'stringify');
var exec$1 = uncurryThis$f(/./.exec);
var charAt$1 = uncurryThis$f(''.charAt);
var charCodeAt = uncurryThis$f(''.charCodeAt);
var replace$1 = uncurryThis$f(''.replace);
var numberToString = uncurryThis$f(1.0.toString);

var tester = /[\uD800-\uDFFF]/g;
var low = /^[\uD800-\uDBFF]$/;
var hi = /^[\uDC00-\uDFFF]$/;

var WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL$1 || fails$j(function () {
  var symbol = getBuiltIn$6('Symbol')();
  // MS Edge converts symbol values to JSON as {}
  return $stringify([symbol]) != '[null]'
    // WebKit converts symbol values to JSON as null
    || $stringify({ a: symbol }) != '{}'
    // V8 throws on boxed symbols
    || $stringify(Object(symbol)) != '{}';
});

// https://github.com/tc39/proposal-well-formed-stringify
var ILL_FORMED_UNICODE = fails$j(function () {
  return $stringify('\uDF06\uD834') !== '"\\udf06\\ud834"'
    || $stringify('\uDEAD') !== '"\\udead"';
});

var stringifyWithSymbolsFix = function (it, replacer) {
  var args = arraySlice$2(arguments);
  var $replacer = getReplacerFunction(replacer);
  if (!isCallable$2($replacer) && (it === undefined || isSymbol$1(it))) return; // IE8 returns string on undefined
  args[1] = function (key, value) {
    // some old implementations (like WebKit) could pass numbers as keys
    if (isCallable$2($replacer)) value = call$2($replacer, this, $String(key), value);
    if (!isSymbol$1(value)) return value;
  };
  return apply$3($stringify, null, args);
};

var fixIllFormed = function (match, offset, string) {
  var prev = charAt$1(string, offset - 1);
  var next = charAt$1(string, offset + 1);
  if ((exec$1(low, match) && !exec$1(hi, next)) || (exec$1(hi, match) && !exec$1(low, prev))) {
    return '\\u' + numberToString(charCodeAt(match, 0), 16);
  } return match;
};

if ($stringify) {
  // `JSON.stringify` method
  // https://tc39.es/ecma262/#sec-json.stringify
  $$H({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE }, {
    // eslint-disable-next-line no-unused-vars -- required for `.length`
    stringify: function stringify(it, replacer, space) {
      var args = arraySlice$2(arguments);
      var result = apply$3(WRONG_SYMBOLS_CONVERSION ? stringifyWithSymbolsFix : $stringify, null, args);
      return ILL_FORMED_UNICODE && typeof result == 'string' ? replace$1(result, tester, fixIllFormed) : result;
    }
  });
}

var $$G = _export;
var NATIVE_SYMBOL = symbolConstructorDetection;
var fails$i = fails$w;
var getOwnPropertySymbolsModule$1 = objectGetOwnPropertySymbols;
var toObject$7 = toObject$d;

// V8 ~ Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
// https://bugs.chromium.org/p/v8/issues/detail?id=3443
var FORCED$9 = !NATIVE_SYMBOL || fails$i(function () { getOwnPropertySymbolsModule$1.f(1); });

// `Object.getOwnPropertySymbols` method
// https://tc39.es/ecma262/#sec-object.getownpropertysymbols
$$G({ target: 'Object', stat: true, forced: FORCED$9 }, {
  getOwnPropertySymbols: function getOwnPropertySymbols(it) {
    var $getOwnPropertySymbols = getOwnPropertySymbolsModule$1.f;
    return $getOwnPropertySymbols ? $getOwnPropertySymbols(toObject$7(it)) : [];
  }
});

var path$r = path$y;

var getOwnPropertySymbols$1 = path$r.Object.getOwnPropertySymbols;

var parent$15 = getOwnPropertySymbols$1;

var getOwnPropertySymbols = parent$15;

(function (module) {
	module.exports = getOwnPropertySymbols;
} (getOwnPropertySymbols$2));

var _Object$getOwnPropertySymbols = /*@__PURE__*/getDefaultExportFromCjs$1(getOwnPropertySymbolsExports);

var getOwnPropertyDescriptorExports$3 = {};
var getOwnPropertyDescriptor$8 = {
  get exports(){ return getOwnPropertyDescriptorExports$3; },
  set exports(v){ getOwnPropertyDescriptorExports$3 = v; },
};

var getOwnPropertyDescriptorExports$2 = {};
var getOwnPropertyDescriptor$7 = {
  get exports(){ return getOwnPropertyDescriptorExports$2; },
  set exports(v){ getOwnPropertyDescriptorExports$2 = v; },
};

var $$F = _export;
var fails$h = fails$w;
var toIndexedObject$3 = toIndexedObject$b;
var nativeGetOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
var DESCRIPTORS$9 = descriptors;

var FORCED$8 = !DESCRIPTORS$9 || fails$h(function () { nativeGetOwnPropertyDescriptor(1); });

// `Object.getOwnPropertyDescriptor` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
$$F({ target: 'Object', stat: true, forced: FORCED$8, sham: !DESCRIPTORS$9 }, {
  getOwnPropertyDescriptor: function getOwnPropertyDescriptor(it, key) {
    return nativeGetOwnPropertyDescriptor(toIndexedObject$3(it), key);
  }
});

var path$q = path$y;

var Object$5 = path$q.Object;

var getOwnPropertyDescriptor$6 = getOwnPropertyDescriptor$7.exports = function getOwnPropertyDescriptor(it, key) {
  return Object$5.getOwnPropertyDescriptor(it, key);
};

if (Object$5.getOwnPropertyDescriptor.sham) getOwnPropertyDescriptor$6.sham = true;

var parent$14 = getOwnPropertyDescriptorExports$2;

var getOwnPropertyDescriptor$5 = parent$14;

(function (module) {
	module.exports = getOwnPropertyDescriptor$5;
} (getOwnPropertyDescriptor$8));

var _Object$getOwnPropertyDescriptor$1 = /*@__PURE__*/getDefaultExportFromCjs$1(getOwnPropertyDescriptorExports$3);

var getOwnPropertyDescriptorsExports = {};
var getOwnPropertyDescriptors$2 = {
  get exports(){ return getOwnPropertyDescriptorsExports; },
  set exports(v){ getOwnPropertyDescriptorsExports = v; },
};

var getBuiltIn$5 = getBuiltIn$c;
var uncurryThis$e = functionUncurryThis;
var getOwnPropertyNamesModule$1 = objectGetOwnPropertyNames;
var getOwnPropertySymbolsModule = objectGetOwnPropertySymbols;
var anObject$4 = anObject$d;

var concat$4 = uncurryThis$e([].concat);

// all object keys, includes non-enumerable and symbols
var ownKeys$9 = getBuiltIn$5('Reflect', 'ownKeys') || function ownKeys(it) {
  var keys = getOwnPropertyNamesModule$1.f(anObject$4(it));
  var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
  return getOwnPropertySymbols ? concat$4(keys, getOwnPropertySymbols(it)) : keys;
};

var $$E = _export;
var DESCRIPTORS$8 = descriptors;
var ownKeys$8 = ownKeys$9;
var toIndexedObject$2 = toIndexedObject$b;
var getOwnPropertyDescriptorModule$1 = objectGetOwnPropertyDescriptor;
var createProperty$3 = createProperty$6;

// `Object.getOwnPropertyDescriptors` method
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
$$E({ target: 'Object', stat: true, sham: !DESCRIPTORS$8 }, {
  getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) {
    var O = toIndexedObject$2(object);
    var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$1.f;
    var keys = ownKeys$8(O);
    var result = {};
    var index = 0;
    var key, descriptor;
    while (keys.length > index) {
      descriptor = getOwnPropertyDescriptor(O, key = keys[index++]);
      if (descriptor !== undefined) createProperty$3(result, key, descriptor);
    }
    return result;
  }
});

var path$p = path$y;

var getOwnPropertyDescriptors$1 = path$p.Object.getOwnPropertyDescriptors;

var parent$13 = getOwnPropertyDescriptors$1;

var getOwnPropertyDescriptors = parent$13;

(function (module) {
	module.exports = getOwnPropertyDescriptors;
} (getOwnPropertyDescriptors$2));

var _Object$getOwnPropertyDescriptors = /*@__PURE__*/getDefaultExportFromCjs$1(getOwnPropertyDescriptorsExports);

var definePropertiesExports$1 = {};
var defineProperties$4 = {
  get exports(){ return definePropertiesExports$1; },
  set exports(v){ definePropertiesExports$1 = v; },
};

var definePropertiesExports = {};
var defineProperties$3 = {
  get exports(){ return definePropertiesExports; },
  set exports(v){ definePropertiesExports = v; },
};

var $$D = _export;
var DESCRIPTORS$7 = descriptors;
var defineProperties$2 = objectDefineProperties.f;

// `Object.defineProperties` method
// https://tc39.es/ecma262/#sec-object.defineproperties
// eslint-disable-next-line es/no-object-defineproperties -- safe
$$D({ target: 'Object', stat: true, forced: Object.defineProperties !== defineProperties$2, sham: !DESCRIPTORS$7 }, {
  defineProperties: defineProperties$2
});

var path$o = path$y;

var Object$4 = path$o.Object;

var defineProperties$1 = defineProperties$3.exports = function defineProperties(T, D) {
  return Object$4.defineProperties(T, D);
};

if (Object$4.defineProperties.sham) defineProperties$1.sham = true;

var parent$12 = definePropertiesExports;

var defineProperties = parent$12;

(function (module) {
	module.exports = defineProperties;
} (defineProperties$4));

var _Object$defineProperties = /*@__PURE__*/getDefaultExportFromCjs$1(definePropertiesExports$1);

var definePropertyExports$3 = {};
var defineProperty$a = {
  get exports(){ return definePropertyExports$3; },
  set exports(v){ definePropertyExports$3 = v; },
};

var definePropertyExports$2 = {};
var defineProperty$9 = {
  get exports(){ return definePropertyExports$2; },
  set exports(v){ definePropertyExports$2 = v; },
};

var $$C = _export;
var DESCRIPTORS$6 = descriptors;
var defineProperty$8 = objectDefineProperty.f;

// `Object.defineProperty` method
// https://tc39.es/ecma262/#sec-object.defineproperty
// eslint-disable-next-line es/no-object-defineproperty -- safe
$$C({ target: 'Object', stat: true, forced: Object.defineProperty !== defineProperty$8, sham: !DESCRIPTORS$6 }, {
  defineProperty: defineProperty$8
});

var path$n = path$y;

var Object$3 = path$n.Object;

var defineProperty$7 = defineProperty$9.exports = function defineProperty(it, key, desc) {
  return Object$3.defineProperty(it, key, desc);
};

if (Object$3.defineProperty.sham) defineProperty$7.sham = true;

var parent$11 = definePropertyExports$2;

var defineProperty$6 = parent$11;

(function (module) {
	module.exports = defineProperty$6;
} (defineProperty$a));

var _Object$defineProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$1(definePropertyExports$3);

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

var definePropertyExports$1 = {};
var defineProperty$5 = {
  get exports(){ return definePropertyExports$1; },
  set exports(v){ definePropertyExports$1 = v; },
};

var definePropertyExports = {};
var defineProperty$4 = {
  get exports(){ return definePropertyExports; },
  set exports(v){ definePropertyExports = v; },
};

var parent$10 = defineProperty$6;

var defineProperty$3 = parent$10;

var parent$$ = defineProperty$3;

var defineProperty$2 = parent$$;

(function (module) {
	module.exports = defineProperty$2;
} (defineProperty$4));

(function (module) {
	module.exports = definePropertyExports;
} (defineProperty$5));

var _Object$defineProperty = /*@__PURE__*/getDefaultExportFromCjs$1(definePropertyExports$1);

var symbolExports$2 = {};
var symbol$6 = {
  get exports(){ return symbolExports$2; },
  set exports(v){ symbolExports$2 = v; },
};

var symbolExports$1 = {};
var symbol$5 = {
  get exports(){ return symbolExports$1; },
  set exports(v){ symbolExports$1 = v; },
};

var $TypeError$8 = TypeError;
var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991

var doesNotExceedSafeInteger$2 = function (it) {
  if (it > MAX_SAFE_INTEGER) throw $TypeError$8('Maximum allowed index exceeded');
  return it;
};

var fails$g = fails$w;
var wellKnownSymbol$6 = wellKnownSymbol$l;
var V8_VERSION$1 = engineV8Version;

var SPECIES$2 = wellKnownSymbol$6('species');

var arrayMethodHasSpeciesSupport$5 = function (METHOD_NAME) {
  // We can't use this feature detection in V8 since it causes
  // deoptimization and serious performance degradation
  // https://github.com/zloirock/core-js/issues/677
  return V8_VERSION$1 >= 51 || !fails$g(function () {
    var array = [];
    var constructor = array.constructor = {};
    constructor[SPECIES$2] = function () {
      return { foo: 1 };
    };
    return array[METHOD_NAME](Boolean).foo !== 1;
  });
};

var $$B = _export;
var fails$f = fails$w;
var isArray$c = isArray$f;
var isObject$a = isObject$j;
var toObject$6 = toObject$d;
var lengthOfArrayLike$6 = lengthOfArrayLike$b;
var doesNotExceedSafeInteger$1 = doesNotExceedSafeInteger$2;
var createProperty$2 = createProperty$6;
var arraySpeciesCreate$1 = arraySpeciesCreate$3;
var arrayMethodHasSpeciesSupport$4 = arrayMethodHasSpeciesSupport$5;
var wellKnownSymbol$5 = wellKnownSymbol$l;
var V8_VERSION = engineV8Version;

var IS_CONCAT_SPREADABLE = wellKnownSymbol$5('isConcatSpreadable');

// We can't use this feature detection in V8 since it causes
// deoptimization and serious performance degradation
// https://github.com/zloirock/core-js/issues/679
var IS_CONCAT_SPREADABLE_SUPPORT = V8_VERSION >= 51 || !fails$f(function () {
  var array = [];
  array[IS_CONCAT_SPREADABLE] = false;
  return array.concat()[0] !== array;
});

var isConcatSpreadable = function (O) {
  if (!isObject$a(O)) return false;
  var spreadable = O[IS_CONCAT_SPREADABLE];
  return spreadable !== undefined ? !!spreadable : isArray$c(O);
};

var FORCED$7 = !IS_CONCAT_SPREADABLE_SUPPORT || !arrayMethodHasSpeciesSupport$4('concat');

// `Array.prototype.concat` method
// https://tc39.es/ecma262/#sec-array.prototype.concat
// with adding support of @@isConcatSpreadable and @@species
$$B({ target: 'Array', proto: true, arity: 1, forced: FORCED$7 }, {
  // eslint-disable-next-line no-unused-vars -- required for `.length`
  concat: function concat(arg) {
    var O = toObject$6(this);
    var A = arraySpeciesCreate$1(O, 0);
    var n = 0;
    var i, k, length, len, E;
    for (i = -1, length = arguments.length; i < length; i++) {
      E = i === -1 ? O : arguments[i];
      if (isConcatSpreadable(E)) {
        len = lengthOfArrayLike$6(E);
        doesNotExceedSafeInteger$1(n + len);
        for (k = 0; k < len; k++, n++) if (k in E) createProperty$2(A, n, E[k]);
      } else {
        doesNotExceedSafeInteger$1(n + 1);
        createProperty$2(A, n++, E);
      }
    }
    A.length = n;
    return A;
  }
});

var defineWellKnownSymbol$k = wellKnownSymbolDefine;

// `Symbol.asyncIterator` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.asynciterator
defineWellKnownSymbol$k('asyncIterator');

var defineWellKnownSymbol$j = wellKnownSymbolDefine;

// `Symbol.hasInstance` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.hasinstance
defineWellKnownSymbol$j('hasInstance');

var defineWellKnownSymbol$i = wellKnownSymbolDefine;

// `Symbol.isConcatSpreadable` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.isconcatspreadable
defineWellKnownSymbol$i('isConcatSpreadable');

var defineWellKnownSymbol$h = wellKnownSymbolDefine;

// `Symbol.iterator` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.iterator
defineWellKnownSymbol$h('iterator');

var defineWellKnownSymbol$g = wellKnownSymbolDefine;

// `Symbol.match` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.match
defineWellKnownSymbol$g('match');

var defineWellKnownSymbol$f = wellKnownSymbolDefine;

// `Symbol.matchAll` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.matchall
defineWellKnownSymbol$f('matchAll');

var defineWellKnownSymbol$e = wellKnownSymbolDefine;

// `Symbol.replace` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.replace
defineWellKnownSymbol$e('replace');

var defineWellKnownSymbol$d = wellKnownSymbolDefine;

// `Symbol.search` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.search
defineWellKnownSymbol$d('search');

var defineWellKnownSymbol$c = wellKnownSymbolDefine;

// `Symbol.species` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.species
defineWellKnownSymbol$c('species');

var defineWellKnownSymbol$b = wellKnownSymbolDefine;

// `Symbol.split` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.split
defineWellKnownSymbol$b('split');

var defineWellKnownSymbol$a = wellKnownSymbolDefine;
var defineSymbolToPrimitive = symbolDefineToPrimitive;

// `Symbol.toPrimitive` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.toprimitive
defineWellKnownSymbol$a('toPrimitive');

// `Symbol.prototype[@@toPrimitive]` method
// https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
defineSymbolToPrimitive();

var getBuiltIn$4 = getBuiltIn$c;
var defineWellKnownSymbol$9 = wellKnownSymbolDefine;
var setToStringTag$2 = setToStringTag$6;

// `Symbol.toStringTag` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.tostringtag
defineWellKnownSymbol$9('toStringTag');

// `Symbol.prototype[@@toStringTag]` property
// https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
setToStringTag$2(getBuiltIn$4('Symbol'), 'Symbol');

var defineWellKnownSymbol$8 = wellKnownSymbolDefine;

// `Symbol.unscopables` well-known symbol
// https://tc39.es/ecma262/#sec-symbol.unscopables
defineWellKnownSymbol$8('unscopables');

var global$9 = global$l;
var setToStringTag$1 = setToStringTag$6;

// JSON[@@toStringTag] property
// https://tc39.es/ecma262/#sec-json-@@tostringtag
setToStringTag$1(global$9.JSON, 'JSON', true);

var path$m = path$y;

var symbol$4 = path$m.Symbol;

var parent$_ = symbol$4;


var symbol$3 = parent$_;

var defineWellKnownSymbol$7 = wellKnownSymbolDefine;

// `Symbol.dispose` well-known symbol
// https://github.com/tc39/proposal-explicit-resource-management
defineWellKnownSymbol$7('dispose');

var parent$Z = symbol$3;



var symbol$2 = parent$Z;

var defineWellKnownSymbol$6 = wellKnownSymbolDefine;

// `Symbol.asyncDispose` well-known symbol
// https://github.com/tc39/proposal-async-explicit-resource-management
defineWellKnownSymbol$6('asyncDispose');

var $$A = _export;
var getBuiltIn$3 = getBuiltIn$c;
var uncurryThis$d = functionUncurryThis;

var Symbol$4 = getBuiltIn$3('Symbol');
var keyFor = Symbol$4.keyFor;
var thisSymbolValue$1 = uncurryThis$d(Symbol$4.prototype.valueOf);

// `Symbol.isRegistered` method
// https://tc39.es/proposal-symbol-predicates/#sec-symbol-isregistered
$$A({ target: 'Symbol', stat: true }, {
  isRegistered: function isRegistered(value) {
    try {
      return keyFor(thisSymbolValue$1(value)) !== undefined;
    } catch (error) {
      return false;
    }
  }
});

var $$z = _export;
var shared = sharedExports;
var getBuiltIn$2 = getBuiltIn$c;
var uncurryThis$c = functionUncurryThis;
var isSymbol = isSymbol$5;
var wellKnownSymbol$4 = wellKnownSymbol$l;

var Symbol$3 = getBuiltIn$2('Symbol');
var $isWellKnown = Symbol$3.isWellKnown;
var getOwnPropertyNames$4 = getBuiltIn$2('Object', 'getOwnPropertyNames');
var thisSymbolValue = uncurryThis$c(Symbol$3.prototype.valueOf);
var WellKnownSymbolsStore = shared('wks');

for (var i = 0, symbolKeys = getOwnPropertyNames$4(Symbol$3), symbolKeysLength = symbolKeys.length; i < symbolKeysLength; i++) {
  // some old engines throws on access to some keys like `arguments` or `caller`
  try {
    var symbolKey = symbolKeys[i];
    if (isSymbol(Symbol$3[symbolKey])) wellKnownSymbol$4(symbolKey);
  } catch (error) { /* empty */ }
}

// `Symbol.isWellKnown` method
// https://tc39.es/proposal-symbol-predicates/#sec-symbol-iswellknown
// We should patch it for newly added well-known symbols. If it's not required, this module just will not be injected
$$z({ target: 'Symbol', stat: true, forced: true }, {
  isWellKnown: function isWellKnown(value) {
    if ($isWellKnown && $isWellKnown(value)) return true;
    try {
      var symbol = thisSymbolValue(value);
      for (var j = 0, keys = getOwnPropertyNames$4(WellKnownSymbolsStore), keysLength = keys.length; j < keysLength; j++) {
        if (WellKnownSymbolsStore[keys[j]] == symbol) return true;
      }
    } catch (error) { /* empty */ }
    return false;
  }
});

var defineWellKnownSymbol$5 = wellKnownSymbolDefine;

// `Symbol.matcher` well-known symbol
// https://github.com/tc39/proposal-pattern-matching
defineWellKnownSymbol$5('matcher');

var defineWellKnownSymbol$4 = wellKnownSymbolDefine;

// `Symbol.metadataKey` well-known symbol
// https://github.com/tc39/proposal-decorator-metadata
defineWellKnownSymbol$4('metadataKey');

var defineWellKnownSymbol$3 = wellKnownSymbolDefine;

// `Symbol.observable` well-known symbol
// https://github.com/tc39/proposal-observable
defineWellKnownSymbol$3('observable');

// TODO: Remove from `core-js@4`
var defineWellKnownSymbol$2 = wellKnownSymbolDefine;

// `Symbol.metadata` well-known symbol
// https://github.com/tc39/proposal-decorators
defineWellKnownSymbol$2('metadata');

// TODO: remove from `core-js@4`
var defineWellKnownSymbol$1 = wellKnownSymbolDefine;

// `Symbol.patternMatch` well-known symbol
// https://github.com/tc39/proposal-pattern-matching
defineWellKnownSymbol$1('patternMatch');

// TODO: remove from `core-js@4`
var defineWellKnownSymbol = wellKnownSymbolDefine;

defineWellKnownSymbol('replaceAll');

var parent$Y = symbol$2;






// TODO: Remove from `core-js@4`




var symbol$1 = parent$Y;

(function (module) {
	module.exports = symbol$1;
} (symbol$5));

(function (module) {
	module.exports = symbolExports$1;
} (symbol$6));

var _Symbol$1 = /*@__PURE__*/getDefaultExportFromCjs$1(symbolExports$2);

var iteratorExports$1 = {};
var iterator$5 = {
  get exports(){ return iteratorExports$1; },
  set exports(v){ iteratorExports$1 = v; },
};

var iteratorExports = {};
var iterator$4 = {
  get exports(){ return iteratorExports; },
  set exports(v){ iteratorExports = v; },
};

var WrappedWellKnownSymbolModule$1 = wellKnownSymbolWrapped;

var iterator$3 = WrappedWellKnownSymbolModule$1.f('iterator');

var parent$X = iterator$3;


var iterator$2 = parent$X;

var parent$W = iterator$2;

var iterator$1 = parent$W;

var parent$V = iterator$1;

var iterator$6 = parent$V;

(function (module) {
	module.exports = iterator$6;
} (iterator$4));

(function (module) {
	module.exports = iteratorExports;
} (iterator$5));

var _Symbol$iterator = /*@__PURE__*/getDefaultExportFromCjs$1(iteratorExports$1);

function _typeof(obj) {
  "@babel/helpers - typeof";

  return _typeof = "function" == typeof _Symbol$1 && "symbol" == typeof _Symbol$iterator ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && "function" == typeof _Symbol$1 && obj.constructor === _Symbol$1 && obj !== _Symbol$1.prototype ? "symbol" : typeof obj;
  }, _typeof(obj);
}

var toPrimitiveExports$1 = {};
var toPrimitive$5 = {
  get exports(){ return toPrimitiveExports$1; },
  set exports(v){ toPrimitiveExports$1 = v; },
};

var toPrimitiveExports = {};
var toPrimitive$4 = {
  get exports(){ return toPrimitiveExports; },
  set exports(v){ toPrimitiveExports = v; },
};

var WrappedWellKnownSymbolModule = wellKnownSymbolWrapped;

var toPrimitive$3 = WrappedWellKnownSymbolModule.f('toPrimitive');

var parent$U = toPrimitive$3;

var toPrimitive$2 = parent$U;

var parent$T = toPrimitive$2;

var toPrimitive$1 = parent$T;

var parent$S = toPrimitive$1;

var toPrimitive = parent$S;

(function (module) {
	module.exports = toPrimitive;
} (toPrimitive$4));

(function (module) {
	module.exports = toPrimitiveExports;
} (toPrimitive$5));

var _Symbol$toPrimitive = /*@__PURE__*/getDefaultExportFromCjs$1(toPrimitiveExports$1);

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);
}

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;
}

var isArrayExports$2 = {};
var isArray$b = {
  get exports(){ return isArrayExports$2; },
  set exports(v){ isArrayExports$2 = v; },
};

var isArrayExports$1 = {};
var isArray$a = {
  get exports(){ return isArrayExports$1; },
  set exports(v){ isArrayExports$1 = v; },
};

var $$y = _export;
var isArray$9 = isArray$f;

// `Array.isArray` method
// https://tc39.es/ecma262/#sec-array.isarray
$$y({ target: 'Array', stat: true }, {
  isArray: isArray$9
});

var path$l = path$y;

var isArray$8 = path$l.Array.isArray;

var parent$R = isArray$8;

var isArray$7 = parent$R;

var parent$Q = isArray$7;

var isArray$6 = parent$Q;

var parent$P = isArray$6;

var isArray$5 = parent$P;

(function (module) {
	module.exports = isArray$5;
} (isArray$a));

(function (module) {
	module.exports = isArrayExports$1;
} (isArray$b));

var _Array$isArray$1 = /*@__PURE__*/getDefaultExportFromCjs$1(isArrayExports$2);

function _arrayWithHoles(arr) {
  if (_Array$isArray$1(arr)) return arr;
}

function _iterableToArrayLimit(arr, i) {
  var _i = null == arr ? null : "undefined" != typeof _Symbol$1 && _getIteratorMethod(arr) || arr["@@iterator"];
  if (null != _i) {
    var _s,
      _e,
      _x,
      _r,
      _arr = [],
      _n = !0,
      _d = !1;
    try {
      if (_x = (_i = _i.call(arr)).next, 0 === i) {
        if (Object(_i) !== _i) return;
        _n = !1;
      } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
    } catch (err) {
      _d = !0, _e = err;
    } finally {
      try {
        if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return;
      } finally {
        if (_d) throw _e;
      }
    }
    return _arr;
  }
}

var sliceExports$2 = {};
var slice$7 = {
  get exports(){ return sliceExports$2; },
  set exports(v){ sliceExports$2 = v; },
};

var sliceExports$1 = {};
var slice$6 = {
  get exports(){ return sliceExports$1; },
  set exports(v){ sliceExports$1 = v; },
};

var $$x = _export;
var isArray$4 = isArray$f;
var isConstructor$1 = isConstructor$4;
var isObject$9 = isObject$j;
var toAbsoluteIndex$2 = toAbsoluteIndex$5;
var lengthOfArrayLike$5 = lengthOfArrayLike$b;
var toIndexedObject$1 = toIndexedObject$b;
var createProperty$1 = createProperty$6;
var wellKnownSymbol$3 = wellKnownSymbol$l;
var arrayMethodHasSpeciesSupport$3 = arrayMethodHasSpeciesSupport$5;
var nativeSlice$1 = arraySlice$5;

var HAS_SPECIES_SUPPORT$3 = arrayMethodHasSpeciesSupport$3('slice');

var SPECIES$1 = wellKnownSymbol$3('species');
var $Array = Array;
var max$1$1 = Math.max;

// `Array.prototype.slice` method
// https://tc39.es/ecma262/#sec-array.prototype.slice
// fallback for not array-like ES3 strings and DOM objects
$$x({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3 }, {
  slice: function slice(start, end) {
    var O = toIndexedObject$1(this);
    var length = lengthOfArrayLike$5(O);
    var k = toAbsoluteIndex$2(start, length);
    var fin = toAbsoluteIndex$2(end === undefined ? length : end, length);
    // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
    var Constructor, result, n;
    if (isArray$4(O)) {
      Constructor = O.constructor;
      // cross-realm fallback
      if (isConstructor$1(Constructor) && (Constructor === $Array || isArray$4(Constructor.prototype))) {
        Constructor = undefined;
      } else if (isObject$9(Constructor)) {
        Constructor = Constructor[SPECIES$1];
        if (Constructor === null) Constructor = undefined;
      }
      if (Constructor === $Array || Constructor === undefined) {
        return nativeSlice$1(O, k, fin);
      }
    }
    result = new (Constructor === undefined ? $Array : Constructor)(max$1$1(fin - k, 0));
    for (n = 0; k < fin; k++, n++) if (k in O) createProperty$1(result, n, O[k]);
    result.length = n;
    return result;
  }
});

var entryVirtual$g = entryVirtual$i;

var slice$5 = entryVirtual$g('Array').slice;

var isPrototypeOf$h = objectIsPrototypeOf;
var method$e = slice$5;

var ArrayPrototype$e = Array.prototype;

var slice$4 = function (it) {
  var own = it.slice;
  return it === ArrayPrototype$e || (isPrototypeOf$h(ArrayPrototype$e, it) && own === ArrayPrototype$e.slice) ? method$e : own;
};

var parent$O = slice$4;

var slice$3 = parent$O;

var parent$N = slice$3;

var slice$2 = parent$N;

var parent$M = slice$2;

var slice$1 = parent$M;

(function (module) {
	module.exports = slice$1;
} (slice$6));

(function (module) {
	module.exports = sliceExports$1;
} (slice$7));

var _sliceInstanceProperty$1 = /*@__PURE__*/getDefaultExportFromCjs$1(sliceExports$2);

var fromExports$1 = {};
var from$3 = {
  get exports(){ return fromExports$1; },
  set exports(v){ fromExports$1 = v; },
};

var fromExports = {};
var from$2 = {
  get exports(){ return fromExports; },
  set exports(v){ fromExports = v; },
};

var parent$L = from$4;

var from$1 = parent$L;

var parent$K = from$1;

var from = parent$K;

(function (module) {
	module.exports = from;
} (from$2));

(function (module) {
	module.exports = fromExports;
} (from$3));

var _Array$from = /*@__PURE__*/getDefaultExportFromCjs$1(fromExports$1);

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

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

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

function _slicedToArray(arr, i) {
  return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray$7(arr, i) || _nonIterableRest();
}

function _arrayWithoutHoles(arr) {
  if (_Array$isArray$1(arr)) return _arrayLikeToArray$7(arr);
}

function _iterableToArray(iter) {
  if (typeof _Symbol$1 !== "undefined" && _getIteratorMethod(iter) != null || iter["@@iterator"] != null) return _Array$from(iter);
}

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

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

var symbolExports = {};
var symbol = {
  get exports(){ return symbolExports; },
  set exports(v){ symbolExports = v; },
};

(function (module) {
	module.exports = symbol$3;
} (symbol));

var _Symbol = /*@__PURE__*/getDefaultExportFromCjs$1(symbolExports);

var concatExports = {};
var concat$3 = {
  get exports(){ return concatExports; },
  set exports(v){ concatExports = v; },
};

var entryVirtual$f = entryVirtual$i;

var concat$2 = entryVirtual$f('Array').concat;

var isPrototypeOf$g = objectIsPrototypeOf;
var method$d = concat$2;

var ArrayPrototype$d = Array.prototype;

var concat$1 = function (it) {
  var own = it.concat;
  return it === ArrayPrototype$d || (isPrototypeOf$g(ArrayPrototype$d, it) && own === ArrayPrototype$d.concat) ? method$d : own;
};

var parent$J = concat$1;

var concat = parent$J;

(function (module) {
	module.exports = concat;
} (concat$3));

var _concatInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(concatExports);

var sliceExports = {};
var slice$8 = {
  get exports(){ return sliceExports; },
  set exports(v){ sliceExports = v; },
};

(function (module) {
	module.exports = slice$3;
} (slice$8));

var _sliceInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(sliceExports);

var ownKeysExports = {};
var ownKeys$7 = {
  get exports(){ return ownKeysExports; },
  set exports(v){ ownKeysExports = v; },
};

var $$w = _export;
var ownKeys$6 = ownKeys$9;

// `Reflect.ownKeys` method
// https://tc39.es/ecma262/#sec-reflect.ownkeys
$$w({ target: 'Reflect', stat: true }, {
  ownKeys: ownKeys$6
});

var path$k = path$y;

var ownKeys$5 = path$k.Reflect.ownKeys;

var parent$I = ownKeys$5;

var ownKeys$4 = parent$I;

(function (module) {
	module.exports = ownKeys$4;
} (ownKeys$7));

var isArrayExports = {};
var isArray$3 = {
  get exports(){ return isArrayExports; },
  set exports(v){ isArrayExports = v; },
};

(function (module) {
	module.exports = isArray$7;
} (isArray$3));

var _Array$isArray = /*@__PURE__*/getDefaultExportFromCjs$1(isArrayExports);

var mapExports$1 = {};
var map$6 = {
  get exports(){ return mapExports$1; },
  set exports(v){ mapExports$1 = v; },
};

var $$v = _export;
var $map = arrayIteration.map;
var arrayMethodHasSpeciesSupport$2 = arrayMethodHasSpeciesSupport$5;

var HAS_SPECIES_SUPPORT$2 = arrayMethodHasSpeciesSupport$2('map');

// `Array.prototype.map` method
// https://tc39.es/ecma262/#sec-array.prototype.map
// with adding support of @@species
$$v({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2 }, {
  map: function map(callbackfn /* , thisArg */) {
    return $map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$e = entryVirtual$i;

var map$5 = entryVirtual$e('Array').map;

var isPrototypeOf$f = objectIsPrototypeOf;
var method$c = map$5;

var ArrayPrototype$c = Array.prototype;

var map$4 = function (it) {
  var own = it.map;
  return it === ArrayPrototype$c || (isPrototypeOf$f(ArrayPrototype$c, it) && own === ArrayPrototype$c.map) ? method$c : own;
};

var parent$H = map$4;

var map$3 = parent$H;

(function (module) {
	module.exports = map$3;
} (map$6));

var _mapInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(mapExports$1);

var keysExports = {};
var keys$2 = {
  get exports(){ return keysExports; },
  set exports(v){ keysExports = v; },
};

var $$u = _export;
var toObject$5 = toObject$d;
var nativeKeys = objectKeys$4;
var fails$e = fails$w;

var FAILS_ON_PRIMITIVES$3 = fails$e(function () { nativeKeys(1); });

// `Object.keys` method
// https://tc39.es/ecma262/#sec-object.keys
$$u({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$3 }, {
  keys: function keys(it) {
    return nativeKeys(toObject$5(it));
  }
});

var path$j = path$y;

var keys$1 = path$j.Object.keys;

var parent$G = keys$1;

var keys$4 = parent$G;

(function (module) {
	module.exports = keys$4;
} (keys$2));

var _Object$keys = /*@__PURE__*/getDefaultExportFromCjs$1(keysExports);

var nowExports = {};
var now$3 = {
  get exports(){ return nowExports; },
  set exports(v){ nowExports = v; },
};

// TODO: Remove from `core-js@4`
var $$t = _export;
var uncurryThis$b = functionUncurryThis;

var $Date = Date;
var thisTimeValue = uncurryThis$b($Date.prototype.getTime);

// `Date.now` method
// https://tc39.es/ecma262/#sec-date.now
$$t({ target: 'Date', stat: true }, {
  now: function now() {
    return thisTimeValue(new $Date());
  }
});

var path$i = path$y;

var now$2 = path$i.Date.now;

var parent$F = now$2;

var now$1 = parent$F;

(function (module) {
	module.exports = now$1;
} (now$3));

var _Date$now = /*@__PURE__*/getDefaultExportFromCjs$1(nowExports);

var forEachExports = {};
var forEach$6 = {
  get exports(){ return forEachExports; },
  set exports(v){ forEachExports = v; },
};

var fails$d = fails$w;

var arrayMethodIsStrict$6 = function (METHOD_NAME, argument) {
  var method = [][METHOD_NAME];
  return !!method && fails$d(function () {
    // eslint-disable-next-line no-useless-call -- required for testing
    method.call(null, argument || function () { return 1; }, 1);
  });
};

var $forEach = arrayIteration.forEach;
var arrayMethodIsStrict$5 = arrayMethodIsStrict$6;

var STRICT_METHOD$3 = arrayMethodIsStrict$5('forEach');

// `Array.prototype.forEach` method implementation
// https://tc39.es/ecma262/#sec-array.prototype.foreach
var arrayForEach = !STRICT_METHOD$3 ? function forEach(callbackfn /* , thisArg */) {
  return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
// eslint-disable-next-line es/no-array-prototype-foreach -- safe
} : [].forEach;

var $$s = _export;
var forEach$5 = arrayForEach;

// `Array.prototype.forEach` method
// https://tc39.es/ecma262/#sec-array.prototype.foreach
// eslint-disable-next-line es/no-array-prototype-foreach -- safe
$$s({ target: 'Array', proto: true, forced: [].forEach != forEach$5 }, {
  forEach: forEach$5
});

var entryVirtual$d = entryVirtual$i;

var forEach$4 = entryVirtual$d('Array').forEach;

var parent$E = forEach$4;

var forEach$3 = parent$E;

var classof$4 = classof$d;
var hasOwn$4 = hasOwnProperty_1;
var isPrototypeOf$e = objectIsPrototypeOf;
var method$b = forEach$3;

var ArrayPrototype$b = Array.prototype;

var DOMIterables$1 = {
  DOMTokenList: true,
  NodeList: true
};

var forEach$2 = function (it) {
  var own = it.forEach;
  return it === ArrayPrototype$b || (isPrototypeOf$e(ArrayPrototype$b, it) && own === ArrayPrototype$b.forEach)
    || hasOwn$4(DOMIterables$1, classof$4(it)) ? method$b : own;
};

(function (module) {
	module.exports = forEach$2;
} (forEach$6));

var _forEachInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(forEachExports);

var reverseExports = {};
var reverse$3 = {
  get exports(){ return reverseExports; },
  set exports(v){ reverseExports = v; },
};

var $$r = _export;
var uncurryThis$a = functionUncurryThis;
var isArray$2 = isArray$f;

var nativeReverse = uncurryThis$a([].reverse);
var test$1 = [1, 2];

// `Array.prototype.reverse` method
// https://tc39.es/ecma262/#sec-array.prototype.reverse
// fix for Safari 12.0 bug
// https://bugs.webkit.org/show_bug.cgi?id=188794
$$r({ target: 'Array', proto: true, forced: String(test$1) === String(test$1.reverse()) }, {
  reverse: function reverse() {
    // eslint-disable-next-line no-self-assign -- dirty hack
    if (isArray$2(this)) this.length = this.length;
    return nativeReverse(this);
  }
});

var entryVirtual$c = entryVirtual$i;

var reverse$2 = entryVirtual$c('Array').reverse;

var isPrototypeOf$d = objectIsPrototypeOf;
var method$a = reverse$2;

var ArrayPrototype$a = Array.prototype;

var reverse$1 = function (it) {
  var own = it.reverse;
  return it === ArrayPrototype$a || (isPrototypeOf$d(ArrayPrototype$a, it) && own === ArrayPrototype$a.reverse) ? method$a : own;
};

var parent$D = reverse$1;

var reverse = parent$D;

(function (module) {
	module.exports = reverse;
} (reverse$3));

var _reverseInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(reverseExports);

var spliceExports = {};
var splice$4 = {
  get exports(){ return spliceExports; },
  set exports(v){ spliceExports = v; },
};

var DESCRIPTORS$5 = descriptors;
var isArray$1 = isArray$f;

var $TypeError$7 = TypeError;
// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
var getOwnPropertyDescriptor$4 = Object.getOwnPropertyDescriptor;

// Safari < 13 does not throw an error in this case
var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS$5 && !function () {
  // makes no sense without proper strict mode support
  if (this !== undefined) return true;
  try {
    // eslint-disable-next-line es/no-object-defineproperty -- safe
    Object.defineProperty([], 'length', { writable: false }).length = 1;
  } catch (error) {
    return error instanceof TypeError;
  }
}();

var arraySetLength = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {
  if (isArray$1(O) && !getOwnPropertyDescriptor$4(O, 'length').writable) {
    throw $TypeError$7('Cannot set read only .length');
  } return O.length = length;
} : function (O, length) {
  return O.length = length;
};

var tryToString$2 = tryToString$6;

var $TypeError$6 = TypeError;

var deletePropertyOrThrow$2 = function (O, P) {
  if (!delete O[P]) throw $TypeError$6('Cannot delete property ' + tryToString$2(P) + ' of ' + tryToString$2(O));
};

var $$q = _export;
var toObject$4 = toObject$d;
var toAbsoluteIndex$1 = toAbsoluteIndex$5;
var toIntegerOrInfinity = toIntegerOrInfinity$4;
var lengthOfArrayLike$4 = lengthOfArrayLike$b;
var setArrayLength = arraySetLength;
var doesNotExceedSafeInteger = doesNotExceedSafeInteger$2;
var arraySpeciesCreate = arraySpeciesCreate$3;
var createProperty = createProperty$6;
var deletePropertyOrThrow$1 = deletePropertyOrThrow$2;
var arrayMethodHasSpeciesSupport$1 = arrayMethodHasSpeciesSupport$5;

var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport$1('splice');

var max$4 = Math.max;
var min$3 = Math.min;

// `Array.prototype.splice` method
// https://tc39.es/ecma262/#sec-array.prototype.splice
// with adding support of @@species
$$q({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, {
  splice: function splice(start, deleteCount /* , ...items */) {
    var O = toObject$4(this);
    var len = lengthOfArrayLike$4(O);
    var actualStart = toAbsoluteIndex$1(start, len);
    var argumentsLength = arguments.length;
    var insertCount, actualDeleteCount, A, k, from, to;
    if (argumentsLength === 0) {
      insertCount = actualDeleteCount = 0;
    } else if (argumentsLength === 1) {
      insertCount = 0;
      actualDeleteCount = len - actualStart;
    } else {
      insertCount = argumentsLength - 2;
      actualDeleteCount = min$3(max$4(toIntegerOrInfinity(deleteCount), 0), len - actualStart);
    }
    doesNotExceedSafeInteger(len + insertCount - actualDeleteCount);
    A = arraySpeciesCreate(O, actualDeleteCount);
    for (k = 0; k < actualDeleteCount; k++) {
      from = actualStart + k;
      if (from in O) createProperty(A, k, O[from]);
    }
    A.length = actualDeleteCount;
    if (insertCount < actualDeleteCount) {
      for (k = actualStart; k < len - actualDeleteCount; k++) {
        from = k + actualDeleteCount;
        to = k + insertCount;
        if (from in O) O[to] = O[from];
        else deletePropertyOrThrow$1(O, to);
      }
      for (k = len; k > len - actualDeleteCount + insertCount; k--) deletePropertyOrThrow$1(O, k - 1);
    } else if (insertCount > actualDeleteCount) {
      for (k = len - actualDeleteCount; k > actualStart; k--) {
        from = k + actualDeleteCount - 1;
        to = k + insertCount - 1;
        if (from in O) O[to] = O[from];
        else deletePropertyOrThrow$1(O, to);
      }
    }
    for (k = 0; k < insertCount; k++) {
      O[k + actualStart] = arguments[k + 2];
    }
    setArrayLength(O, len - actualDeleteCount + insertCount);
    return A;
  }
});

var entryVirtual$b = entryVirtual$i;

var splice$3 = entryVirtual$b('Array').splice;

var isPrototypeOf$c = objectIsPrototypeOf;
var method$9 = splice$3;

var ArrayPrototype$9 = Array.prototype;

var splice$2 = function (it) {
  var own = it.splice;
  return it === ArrayPrototype$9 || (isPrototypeOf$c(ArrayPrototype$9, it) && own === ArrayPrototype$9.splice) ? method$9 : own;
};

var parent$C = splice$2;

var splice$1 = parent$C;

(function (module) {
	module.exports = splice$1;
} (splice$4));

var _spliceInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(spliceExports);

var includesExports = {};
var includes$4 = {
  get exports(){ return includesExports; },
  set exports(v){ includesExports = v; },
};

var $$p = _export;
var $includes = arrayIncludes.includes;
var fails$c = fails$w;

// FF99+ bug
var BROKEN_ON_SPARSE = fails$c(function () {
  // eslint-disable-next-line es/no-array-prototype-includes -- detection
  return !Array(1).includes();
});

// `Array.prototype.includes` method
// https://tc39.es/ecma262/#sec-array.prototype.includes
$$p({ target: 'Array', proto: true, forced: BROKEN_ON_SPARSE }, {
  includes: function includes(el /* , fromIndex = 0 */) {
    return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$a = entryVirtual$i;

var includes$3 = entryVirtual$a('Array').includes;

var isObject$8 = isObject$j;
var classof$3 = classofRaw$2;
var wellKnownSymbol$2 = wellKnownSymbol$l;

var MATCH$1 = wellKnownSymbol$2('match');

// `IsRegExp` abstract operation
// https://tc39.es/ecma262/#sec-isregexp
var isRegexp = function (it) {
  var isRegExp;
  return isObject$8(it) && ((isRegExp = it[MATCH$1]) !== undefined ? !!isRegExp : classof$3(it) == 'RegExp');
};

var isRegExp = isRegexp;

var $TypeError$5 = TypeError;

var notARegexp = function (it) {
  if (isRegExp(it)) {
    throw $TypeError$5("The method doesn't accept regular expressions");
  } return it;
};

var wellKnownSymbol$1 = wellKnownSymbol$l;

var MATCH = wellKnownSymbol$1('match');

var correctIsRegexpLogic = function (METHOD_NAME) {
  var regexp = /./;
  try {
    '/./'[METHOD_NAME](regexp);
  } catch (error1) {
    try {
      regexp[MATCH] = false;
      return '/./'[METHOD_NAME](regexp);
    } catch (error2) { /* empty */ }
  } return false;
};

var $$o = _export;
var uncurryThis$9 = functionUncurryThis;
var notARegExp = notARegexp;
var requireObjectCoercible$1 = requireObjectCoercible$5;
var toString$4 = toString$a;
var correctIsRegExpLogic = correctIsRegexpLogic;

var stringIndexOf = uncurryThis$9(''.indexOf);

// `String.prototype.includes` method
// https://tc39.es/ecma262/#sec-string.prototype.includes
$$o({ target: 'String', proto: true, forced: !correctIsRegExpLogic('includes') }, {
  includes: function includes(searchString /* , position = 0 */) {
    return !!~stringIndexOf(
      toString$4(requireObjectCoercible$1(this)),
      toString$4(notARegExp(searchString)),
      arguments.length > 1 ? arguments[1] : undefined
    );
  }
});

var entryVirtual$9 = entryVirtual$i;

var includes$2 = entryVirtual$9('String').includes;

var isPrototypeOf$b = objectIsPrototypeOf;
var arrayMethod = includes$3;
var stringMethod = includes$2;

var ArrayPrototype$8 = Array.prototype;
var StringPrototype$1 = String.prototype;

var includes$1 = function (it) {
  var own = it.includes;
  if (it === ArrayPrototype$8 || (isPrototypeOf$b(ArrayPrototype$8, it) && own === ArrayPrototype$8.includes)) return arrayMethod;
  if (typeof it == 'string' || it === StringPrototype$1 || (isPrototypeOf$b(StringPrototype$1, it) && own === StringPrototype$1.includes)) {
    return stringMethod;
  } return own;
};

var parent$B = includes$1;

var includes = parent$B;

(function (module) {
	module.exports = includes;
} (includes$4));

var _includesInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(includesExports);

var getPrototypeOfExports$2 = {};
var getPrototypeOf$7 = {
  get exports(){ return getPrototypeOfExports$2; },
  set exports(v){ getPrototypeOfExports$2 = v; },
};

var $$n = _export;
var fails$b = fails$w;
var toObject$3 = toObject$d;
var nativeGetPrototypeOf = objectGetPrototypeOf;
var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter;

var FAILS_ON_PRIMITIVES$2 = fails$b(function () { nativeGetPrototypeOf(1); });

// `Object.getPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.getprototypeof
$$n({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$2, sham: !CORRECT_PROTOTYPE_GETTER }, {
  getPrototypeOf: function getPrototypeOf(it) {
    return nativeGetPrototypeOf(toObject$3(it));
  }
});

var path$h = path$y;

var getPrototypeOf$6 = path$h.Object.getPrototypeOf;

var parent$A = getPrototypeOf$6;

var getPrototypeOf$5 = parent$A;

(function (module) {
	module.exports = getPrototypeOf$5;
} (getPrototypeOf$7));

var _Object$getPrototypeOf$1 = /*@__PURE__*/getDefaultExportFromCjs$1(getPrototypeOfExports$2);

var filterExports = {};
var filter$3 = {
  get exports(){ return filterExports; },
  set exports(v){ filterExports = v; },
};

var $$m = _export;
var $filter = arrayIteration.filter;
var arrayMethodHasSpeciesSupport = arrayMethodHasSpeciesSupport$5;

var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('filter');

// `Array.prototype.filter` method
// https://tc39.es/ecma262/#sec-array.prototype.filter
// with adding support of @@species
$$m({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
  filter: function filter(callbackfn /* , thisArg */) {
    return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$8 = entryVirtual$i;

var filter$2 = entryVirtual$8('Array').filter;

var isPrototypeOf$a = objectIsPrototypeOf;
var method$8 = filter$2;

var ArrayPrototype$7 = Array.prototype;

var filter$1 = function (it) {
  var own = it.filter;
  return it === ArrayPrototype$7 || (isPrototypeOf$a(ArrayPrototype$7, it) && own === ArrayPrototype$7.filter) ? method$8 : own;
};

var parent$z = filter$1;

var filter$4 = parent$z;

(function (module) {
	module.exports = filter$4;
} (filter$3));

var _filterInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(filterExports);

var valuesExports$1 = {};
var values$6 = {
  get exports(){ return valuesExports$1; },
  set exports(v){ valuesExports$1 = v; },
};

var DESCRIPTORS$4 = descriptors;
var uncurryThis$8 = functionUncurryThis;
var objectKeys = objectKeys$4;
var toIndexedObject = toIndexedObject$b;
var $propertyIsEnumerable = objectPropertyIsEnumerable.f;

var propertyIsEnumerable = uncurryThis$8($propertyIsEnumerable);
var push$2 = uncurryThis$8([].push);

// `Object.{ entries, values }` methods implementation
var createMethod$2 = function (TO_ENTRIES) {
  return function (it) {
    var O = toIndexedObject(it);
    var keys = objectKeys(O);
    var length = keys.length;
    var i = 0;
    var result = [];
    var key;
    while (length > i) {
      key = keys[i++];
      if (!DESCRIPTORS$4 || propertyIsEnumerable(O, key)) {
        push$2(result, TO_ENTRIES ? [key, O[key]] : O[key]);
      }
    }
    return result;
  };
};

var objectToArray = {
  // `Object.entries` method
  // https://tc39.es/ecma262/#sec-object.entries
  entries: createMethod$2(true),
  // `Object.values` method
  // https://tc39.es/ecma262/#sec-object.values
  values: createMethod$2(false)
};

var $$l = _export;
var $values = objectToArray.values;

// `Object.values` method
// https://tc39.es/ecma262/#sec-object.values
$$l({ target: 'Object', stat: true }, {
  values: function values(O) {
    return $values(O);
  }
});

var path$g = path$y;

var values$5 = path$g.Object.values;

var parent$y = values$5;

var values$4 = parent$y;

(function (module) {
	module.exports = values$4;
} (values$6));

var _parseIntExports = {};
var _parseInt$3 = {
  get exports(){ return _parseIntExports; },
  set exports(v){ _parseIntExports = v; },
};

// a string of all valid unicode whitespaces
var whitespaces$4 = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
  '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';

var uncurryThis$7 = functionUncurryThis;
var requireObjectCoercible = requireObjectCoercible$5;
var toString$3 = toString$a;
var whitespaces$3 = whitespaces$4;

var replace = uncurryThis$7(''.replace);
var ltrim = RegExp('^[' + whitespaces$3 + ']+');
var rtrim = RegExp('(^|[^' + whitespaces$3 + '])[' + whitespaces$3 + ']+$');

// `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
var createMethod$1 = function (TYPE) {
  return function ($this) {
    var string = toString$3(requireObjectCoercible($this));
    if (TYPE & 1) string = replace(string, ltrim, '');
    if (TYPE & 2) string = replace(string, rtrim, '$1');
    return string;
  };
};

var stringTrim = {
  // `String.prototype.{ trimLeft, trimStart }` methods
  // https://tc39.es/ecma262/#sec-string.prototype.trimstart
  start: createMethod$1(1),
  // `String.prototype.{ trimRight, trimEnd }` methods
  // https://tc39.es/ecma262/#sec-string.prototype.trimend
  end: createMethod$1(2),
  // `String.prototype.trim` method
  // https://tc39.es/ecma262/#sec-string.prototype.trim
  trim: createMethod$1(3)
};

var global$8 = global$l;
var fails$a = fails$w;
var uncurryThis$6 = functionUncurryThis;
var toString$2 = toString$a;
var trim$5 = stringTrim.trim;
var whitespaces$2 = whitespaces$4;

var $parseInt$1 = global$8.parseInt;
var Symbol$2 = global$8.Symbol;
var ITERATOR$1 = Symbol$2 && Symbol$2.iterator;
var hex = /^[+-]?0x/i;
var exec = uncurryThis$6(hex.exec);
var FORCED$6 = $parseInt$1(whitespaces$2 + '08') !== 8 || $parseInt$1(whitespaces$2 + '0x16') !== 22
  // MS Edge 18- broken with boxed symbols
  || (ITERATOR$1 && !fails$a(function () { $parseInt$1(Object(ITERATOR$1)); }));

// `parseInt` method
// https://tc39.es/ecma262/#sec-parseint-string-radix
var numberParseInt = FORCED$6 ? function parseInt(string, radix) {
  var S = trim$5(toString$2(string));
  return $parseInt$1(S, (radix >>> 0) || (exec(hex, S) ? 16 : 10));
} : $parseInt$1;

var $$k = _export;
var $parseInt = numberParseInt;

// `parseInt` method
// https://tc39.es/ecma262/#sec-parseint-string-radix
$$k({ global: true, forced: parseInt != $parseInt }, {
  parseInt: $parseInt
});

var path$f = path$y;

var _parseInt$2 = path$f.parseInt;

var parent$x = _parseInt$2;

var _parseInt$1 = parent$x;

(function (module) {
	module.exports = _parseInt$1;
} (_parseInt$3));

var _parseInt = /*@__PURE__*/getDefaultExportFromCjs$1(_parseIntExports);

var indexOfExports = {};
var indexOf$3 = {
  get exports(){ return indexOfExports; },
  set exports(v){ indexOfExports = v; },
};

/* eslint-disable es/no-array-prototype-indexof -- required for testing */
var $$j = _export;
var uncurryThis$5 = functionUncurryThisClause;
var $indexOf = arrayIncludes.indexOf;
var arrayMethodIsStrict$4 = arrayMethodIsStrict$6;

var nativeIndexOf = uncurryThis$5([].indexOf);

var NEGATIVE_ZERO = !!nativeIndexOf && 1 / nativeIndexOf([1], 1, -0) < 0;
var FORCED$5 = NEGATIVE_ZERO || !arrayMethodIsStrict$4('indexOf');

// `Array.prototype.indexOf` method
// https://tc39.es/ecma262/#sec-array.prototype.indexof
$$j({ target: 'Array', proto: true, forced: FORCED$5 }, {
  indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
    var fromIndex = arguments.length > 1 ? arguments[1] : undefined;
    return NEGATIVE_ZERO
      // convert -0 to +0
      ? nativeIndexOf(this, searchElement, fromIndex) || 0
      : $indexOf(this, searchElement, fromIndex);
  }
});

var entryVirtual$7 = entryVirtual$i;

var indexOf$2 = entryVirtual$7('Array').indexOf;

var isPrototypeOf$9 = objectIsPrototypeOf;
var method$7 = indexOf$2;

var ArrayPrototype$6 = Array.prototype;

var indexOf$1 = function (it) {
  var own = it.indexOf;
  return it === ArrayPrototype$6 || (isPrototypeOf$9(ArrayPrototype$6, it) && own === ArrayPrototype$6.indexOf) ? method$7 : own;
};

var parent$w = indexOf$1;

var indexOf$5 = parent$w;

(function (module) {
	module.exports = indexOf$5;
} (indexOf$3));

var _indexOfInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(indexOfExports);

var trimExports = {};
var trim$4 = {
  get exports(){ return trimExports; },
  set exports(v){ trimExports = v; },
};

var PROPER_FUNCTION_NAME = functionName.PROPER;
var fails$9 = fails$w;
var whitespaces$1 = whitespaces$4;

var non = '\u200B\u0085\u180E';

// check that a method works with the correct list
// of whitespaces and has a correct name
var stringTrimForced = function (METHOD_NAME) {
  return fails$9(function () {
    return !!whitespaces$1[METHOD_NAME]()
      || non[METHOD_NAME]() !== non
      || (PROPER_FUNCTION_NAME && whitespaces$1[METHOD_NAME].name !== METHOD_NAME);
  });
};

var $$i = _export;
var $trim = stringTrim.trim;
var forcedStringTrimMethod = stringTrimForced;

// `String.prototype.trim` method
// https://tc39.es/ecma262/#sec-string.prototype.trim
$$i({ target: 'String', proto: true, forced: forcedStringTrimMethod('trim') }, {
  trim: function trim() {
    return $trim(this);
  }
});

var entryVirtual$6 = entryVirtual$i;

var trim$3 = entryVirtual$6('String').trim;

var isPrototypeOf$8 = objectIsPrototypeOf;
var method$6 = trim$3;

var StringPrototype = String.prototype;

var trim$2 = function (it) {
  var own = it.trim;
  return typeof it == 'string' || it === StringPrototype
    || (isPrototypeOf$8(StringPrototype, it) && own === StringPrototype.trim) ? method$6 : own;
};

var parent$v = trim$2;

var trim$1 = parent$v;

(function (module) {
	module.exports = trim$1;
} (trim$4));

var createExports$2 = {};
var create$9 = {
  get exports(){ return createExports$2; },
  set exports(v){ createExports$2 = v; },
};

// TODO: Remove from `core-js@4`
var $$h = _export;
var DESCRIPTORS$3 = descriptors;
var create$8 = objectCreate;

// `Object.create` method
// https://tc39.es/ecma262/#sec-object.create
$$h({ target: 'Object', stat: true, sham: !DESCRIPTORS$3 }, {
  create: create$8
});

var path$e = path$y;

var Object$2 = path$e.Object;

var create$7 = function create(P, D) {
  return Object$2.create(P, D);
};

var parent$u = create$7;

var create$6 = parent$u;

(function (module) {
	module.exports = create$6;
} (create$9));

var _Object$create$1 = /*@__PURE__*/getDefaultExportFromCjs$1(createExports$2);

var stringifyExports = {};
var stringify$2 = {
  get exports(){ return stringifyExports; },
  set exports(v){ stringifyExports = v; },
};

var path$d = path$y;
var apply$2 = functionApply;

// eslint-disable-next-line es/no-json -- safe
if (!path$d.JSON) path$d.JSON = { stringify: JSON.stringify };

// eslint-disable-next-line no-unused-vars -- required for `.length`
var stringify$1 = function stringify(it, replacer, space) {
  return apply$2(path$d.JSON.stringify, null, arguments);
};

var parent$t = stringify$1;

var stringify$3 = parent$t;

(function (module) {
	module.exports = stringify$3;
} (stringify$2));

var _JSON$stringify = /*@__PURE__*/getDefaultExportFromCjs$1(stringifyExports);

var setTimeoutExports = {};
var setTimeout$3 = {
  get exports(){ return setTimeoutExports; },
  set exports(v){ setTimeoutExports = v; },
};

/* global Bun -- Deno case */

var engineIsBun = typeof Bun == 'function' && Bun && typeof Bun.version == 'string';

var $TypeError$4 = TypeError;

var validateArgumentsLength$1 = function (passed, required) {
  if (passed < required) throw $TypeError$4('Not enough arguments');
  return passed;
};

var global$7 = global$l;
var apply$1 = functionApply;
var isCallable$1 = isCallable$i;
var ENGINE_IS_BUN = engineIsBun;
var USER_AGENT = engineUserAgent;
var arraySlice$1 = arraySlice$5;
var validateArgumentsLength = validateArgumentsLength$1;

var Function$1 = global$7.Function;
// dirty IE9- and Bun 0.3.0- checks
var WRAP = /MSIE .\./.test(USER_AGENT) || ENGINE_IS_BUN && (function () {
  var version = global$7.Bun.version.split('.');
  return version.length < 3 || version[0] == 0 && (version[1] < 3 || version[1] == 3 && version[2] == 0);
})();

// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
// https://github.com/oven-sh/bun/issues/1633
var schedulersFix$2 = function (scheduler, hasTimeArg) {
  var firstParamIndex = hasTimeArg ? 2 : 1;
  return WRAP ? function (handler, timeout /* , ...arguments */) {
    var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;
    var fn = isCallable$1(handler) ? handler : Function$1(handler);
    var params = boundArgs ? arraySlice$1(arguments, firstParamIndex) : [];
    var callback = boundArgs ? function () {
      apply$1(fn, this, params);
    } : fn;
    return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);
  } : scheduler;
};

var $$g = _export;
var global$6 = global$l;
var schedulersFix$1 = schedulersFix$2;

var setInterval$2 = schedulersFix$1(global$6.setInterval, true);

// Bun / IE9- setInterval additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
$$g({ global: true, bind: true, forced: global$6.setInterval !== setInterval$2 }, {
  setInterval: setInterval$2
});

var $$f = _export;
var global$5 = global$l;
var schedulersFix = schedulersFix$2;

var setTimeout$2 = schedulersFix(global$5.setTimeout, true);

// Bun / IE9- setTimeout additional parameters fix
// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
$$f({ global: true, bind: true, forced: global$5.setTimeout !== setTimeout$2 }, {
  setTimeout: setTimeout$2
});

var path$c = path$y;

var setTimeout$1 = path$c.setTimeout;

(function (module) {
	module.exports = setTimeout$1;
} (setTimeout$3));

var _setTimeout = /*@__PURE__*/getDefaultExportFromCjs$1(setTimeoutExports);

var fillExports = {};
var fill$4 = {
  get exports(){ return fillExports; },
  set exports(v){ fillExports = v; },
};

var toObject$2 = toObject$d;
var toAbsoluteIndex = toAbsoluteIndex$5;
var lengthOfArrayLike$3 = lengthOfArrayLike$b;

// `Array.prototype.fill` method implementation
// https://tc39.es/ecma262/#sec-array.prototype.fill
var arrayFill = function fill(value /* , start = 0, end = @length */) {
  var O = toObject$2(this);
  var length = lengthOfArrayLike$3(O);
  var argumentsLength = arguments.length;
  var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);
  var end = argumentsLength > 2 ? arguments[2] : undefined;
  var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
  while (endPos > index) O[index++] = value;
  return O;
};

var $$e = _export;
var fill$3 = arrayFill;

// `Array.prototype.fill` method
// https://tc39.es/ecma262/#sec-array.prototype.fill
$$e({ target: 'Array', proto: true }, {
  fill: fill$3
});

var entryVirtual$5 = entryVirtual$i;

var fill$2 = entryVirtual$5('Array').fill;

var isPrototypeOf$7 = objectIsPrototypeOf;
var method$5 = fill$2;

var ArrayPrototype$5 = Array.prototype;

var fill$1 = function (it) {
  var own = it.fill;
  return it === ArrayPrototype$5 || (isPrototypeOf$7(ArrayPrototype$5, it) && own === ArrayPrototype$5.fill) ? method$5 : own;
};

var parent$s = fill$1;

var fill = parent$s;

(function (module) {
	module.exports = fill;
} (fill$4));

var _fillInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(fillExports);

/*! Hammer.JS - v2.0.17-rc - 2019-12-16
 * http://naver.github.io/egjs
 *
 * Forked By Naver egjs
 * Copyright (c) hammerjs
 * Licensed under the MIT license */
function _extends() {
  _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  return _extends.apply(this, arguments);
}

function _inheritsLoose(subClass, superClass) {
  subClass.prototype = Object.create(superClass.prototype);
  subClass.prototype.constructor = subClass;
  subClass.__proto__ = superClass;
}

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

  return self;
}

/**
 * @private
 * extend object.
 * means that properties in dest will be overwritten by the ones in src.
 * @param {Object} target
 * @param {...Object} objects_to_assign
 * @returns {Object} target
 */
var assign;

if (typeof Object.assign !== 'function') {
  assign = function assign(target) {
    if (target === undefined || target === null) {
      throw new TypeError('Cannot convert undefined or null to object');
    }

    var output = Object(target);

    for (var index = 1; index < arguments.length; index++) {
      var source = arguments[index];

      if (source !== undefined && source !== null) {
        for (var nextKey in source) {
          if (source.hasOwnProperty(nextKey)) {
            output[nextKey] = source[nextKey];
          }
        }
      }
    }

    return output;
  };
} else {
  assign = Object.assign;
}

var assign$1 = assign;

var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
var TEST_ELEMENT = typeof document === "undefined" ? {
  style: {}
} : document.createElement('div');
var TYPE_FUNCTION = 'function';
var round$2 = Math.round,
    abs$1 = Math.abs;
var now = Date.now;

/**
 * @private
 * get the prefixed property
 * @param {Object} obj
 * @param {String} property
 * @returns {String|Undefined} prefixed
 */

function prefixed(obj, property) {
  var prefix;
  var prop;
  var camelProp = property[0].toUpperCase() + property.slice(1);
  var i = 0;

  while (i < VENDOR_PREFIXES.length) {
    prefix = VENDOR_PREFIXES[i];
    prop = prefix ? prefix + camelProp : property;

    if (prop in obj) {
      return prop;
    }

    i++;
  }

  return undefined;
}

/* eslint-disable no-new-func, no-nested-ternary */
var win;

if (typeof window === "undefined") {
  // window is undefined in node.js
  win = {};
} else {
  win = window;
}

var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
function getTouchActionProps() {
  if (!NATIVE_TOUCH_ACTION) {
    return false;
  }

  var touchMap = {};
  var cssSupports = win.CSS && win.CSS.supports;
  ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) {
    // If css.supports is not supported but there is native touch-action assume it supports
    // all values. This is the case for IE 10 and 11.
    return touchMap[val] = cssSupports ? win.CSS.supports('touch-action', val) : true;
  });
  return touchMap;
}

var TOUCH_ACTION_COMPUTE = 'compute';
var TOUCH_ACTION_AUTO = 'auto';
var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented

var TOUCH_ACTION_NONE = 'none';
var TOUCH_ACTION_PAN_X = 'pan-x';
var TOUCH_ACTION_PAN_Y = 'pan-y';
var TOUCH_ACTION_MAP = getTouchActionProps();

var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
var SUPPORT_TOUCH = 'ontouchstart' in win;
var SUPPORT_POINTER_EVENTS = prefixed(win, 'PointerEvent') !== undefined;
var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
var INPUT_TYPE_TOUCH = 'touch';
var INPUT_TYPE_PEN = 'pen';
var INPUT_TYPE_MOUSE = 'mouse';
var INPUT_TYPE_KINECT = 'kinect';
var COMPUTE_INTERVAL = 25;
var INPUT_START = 1;
var INPUT_MOVE = 2;
var INPUT_END = 4;
var INPUT_CANCEL = 8;
var DIRECTION_NONE = 1;
var DIRECTION_LEFT = 2;
var DIRECTION_RIGHT = 4;
var DIRECTION_UP = 8;
var DIRECTION_DOWN = 16;
var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
var PROPS_XY = ['x', 'y'];
var PROPS_CLIENT_XY = ['clientX', 'clientY'];

/**
 * @private
 * walk objects and arrays
 * @param {Object} obj
 * @param {Function} iterator
 * @param {Object} context
 */
function each$5(obj, iterator, context) {
  var i;

  if (!obj) {
    return;
  }

  if (obj.forEach) {
    obj.forEach(iterator, context);
  } else if (obj.length !== undefined) {
    i = 0;

    while (i < obj.length) {
      iterator.call(context, obj[i], i, obj);
      i++;
    }
  } else {
    for (i in obj) {
      obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
    }
  }
}

/**
 * @private
 * let a boolean value also be a function that must return a boolean
 * this first item in args will be used as the context
 * @param {Boolean|Function} val
 * @param {Array} [args]
 * @returns {Boolean}
 */

function boolOrFn(val, args) {
  if (typeof val === TYPE_FUNCTION) {
    return val.apply(args ? args[0] || undefined : undefined, args);
  }

  return val;
}

/**
 * @private
 * small indexOf wrapper
 * @param {String} str
 * @param {String} find
 * @returns {Boolean} found
 */
function inStr(str, find) {
  return str.indexOf(find) > -1;
}

/**
 * @private
 * when the touchActions are collected they are not a valid value, so we need to clean things up. *
 * @param {String} actions
 * @returns {*}
 */

function cleanTouchActions(actions) {
  // none
  if (inStr(actions, TOUCH_ACTION_NONE)) {
    return TOUCH_ACTION_NONE;
  }

  var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
  var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); // if both pan-x and pan-y are set (different recognizers
  // for different directions, e.g. horizontal pan but vertical swipe?)
  // we need none (as otherwise with pan-x pan-y combined none of these
  // recognizers will work, since the browser would handle all panning

  if (hasPanX && hasPanY) {
    return TOUCH_ACTION_NONE;
  } // pan-x OR pan-y


  if (hasPanX || hasPanY) {
    return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
  } // manipulation


  if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
    return TOUCH_ACTION_MANIPULATION;
  }

  return TOUCH_ACTION_AUTO;
}

/**
 * @private
 * Touch Action
 * sets the touchAction property or uses the js alternative
 * @param {Manager} manager
 * @param {String} value
 * @constructor
 */

var TouchAction =
/*#__PURE__*/
function () {
  function TouchAction(manager, value) {
    this.manager = manager;
    this.set(value);
  }
  /**
   * @private
   * set the touchAction value on the element or enable the polyfill
   * @param {String} value
   */


  var _proto = TouchAction.prototype;

  _proto.set = function set(value) {
    // find out the touch-action by the event handlers
    if (value === TOUCH_ACTION_COMPUTE) {
      value = this.compute();
    }

    if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
      this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
    }

    this.actions = value.toLowerCase().trim();
  };
  /**
   * @private
   * just re-set the touchAction value
   */


  _proto.update = function update() {
    this.set(this.manager.options.touchAction);
  };
  /**
   * @private
   * compute the value for the touchAction property based on the recognizer's settings
   * @returns {String} value
   */


  _proto.compute = function compute() {
    var actions = [];
    each$5(this.manager.recognizers, function (recognizer) {
      if (boolOrFn(recognizer.options.enable, [recognizer])) {
        actions = actions.concat(recognizer.getTouchAction());
      }
    });
    return cleanTouchActions(actions.join(' '));
  };
  /**
   * @private
   * this method is called on each input cycle and provides the preventing of the browser behavior
   * @param {Object} input
   */


  _proto.preventDefaults = function preventDefaults(input) {
    var srcEvent = input.srcEvent;
    var direction = input.offsetDirection; // if the touch action did prevented once this session

    if (this.manager.session.prevented) {
      srcEvent.preventDefault();
      return;
    }

    var actions = this.actions;
    var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];

    if (hasNone) {
      // do not prevent defaults if this is a tap gesture
      var isTapPointer = input.pointers.length === 1;
      var isTapMovement = input.distance < 2;
      var isTapTouchTime = input.deltaTime < 250;

      if (isTapPointer && isTapMovement && isTapTouchTime) {
        return;
      }
    }

    if (hasPanX && hasPanY) {
      // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
      return;
    }

    if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) {
      return this.preventSrc(srcEvent);
    }
  };
  /**
   * @private
   * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
   * @param {Object} srcEvent
   */


  _proto.preventSrc = function preventSrc(srcEvent) {
    this.manager.session.prevented = true;
    srcEvent.preventDefault();
  };

  return TouchAction;
}();

/**
 * @private
 * find if a node is in the given parent
 * @method hasParent
 * @param {HTMLElement} node
 * @param {HTMLElement} parent
 * @return {Boolean} found
 */
function hasParent(node, parent) {
  while (node) {
    if (node === parent) {
      return true;
    }

    node = node.parentNode;
  }

  return false;
}

/**
 * @private
 * get the center of all the pointers
 * @param {Array} pointers
 * @return {Object} center contains `x` and `y` properties
 */

function getCenter(pointers) {
  var pointersLength = pointers.length; // no need to loop when only one touch

  if (pointersLength === 1) {
    return {
      x: round$2(pointers[0].clientX),
      y: round$2(pointers[0].clientY)
    };
  }

  var x = 0;
  var y = 0;
  var i = 0;

  while (i < pointersLength) {
    x += pointers[i].clientX;
    y += pointers[i].clientY;
    i++;
  }

  return {
    x: round$2(x / pointersLength),
    y: round$2(y / pointersLength)
  };
}

/**
 * @private
 * create a simple clone from the input used for storage of firstInput and firstMultiple
 * @param {Object} input
 * @returns {Object} clonedInputData
 */

function simpleCloneInputData(input) {
  // make a simple copy of the pointers because we will get a reference if we don't
  // we only need clientXY for the calculations
  var pointers = [];
  var i = 0;

  while (i < input.pointers.length) {
    pointers[i] = {
      clientX: round$2(input.pointers[i].clientX),
      clientY: round$2(input.pointers[i].clientY)
    };
    i++;
  }

  return {
    timeStamp: now(),
    pointers: pointers,
    center: getCenter(pointers),
    deltaX: input.deltaX,
    deltaY: input.deltaY
  };
}

/**
 * @private
 * calculate the absolute distance between two points
 * @param {Object} p1 {x, y}
 * @param {Object} p2 {x, y}
 * @param {Array} [props] containing x and y keys
 * @return {Number} distance
 */

function getDistance(p1, p2, props) {
  if (!props) {
    props = PROPS_XY;
  }

  var x = p2[props[0]] - p1[props[0]];
  var y = p2[props[1]] - p1[props[1]];
  return Math.sqrt(x * x + y * y);
}

/**
 * @private
 * calculate the angle between two coordinates
 * @param {Object} p1
 * @param {Object} p2
 * @param {Array} [props] containing x and y keys
 * @return {Number} angle
 */

function getAngle(p1, p2, props) {
  if (!props) {
    props = PROPS_XY;
  }

  var x = p2[props[0]] - p1[props[0]];
  var y = p2[props[1]] - p1[props[1]];
  return Math.atan2(y, x) * 180 / Math.PI;
}

/**
 * @private
 * get the direction between two points
 * @param {Number} x
 * @param {Number} y
 * @return {Number} direction
 */

function getDirection(x, y) {
  if (x === y) {
    return DIRECTION_NONE;
  }

  if (abs$1(x) >= abs$1(y)) {
    return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
  }

  return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
}

function computeDeltaXY(session, input) {
  var center = input.center; // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;
  // jscs throwing error on defalut destructured values and without defaults tests fail

  var offset = session.offsetDelta || {};
  var prevDelta = session.prevDelta || {};
  var prevInput = session.prevInput || {};

  if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
    prevDelta = session.prevDelta = {
      x: prevInput.deltaX || 0,
      y: prevInput.deltaY || 0
    };
    offset = session.offsetDelta = {
      x: center.x,
      y: center.y
    };
  }

  input.deltaX = prevDelta.x + (center.x - offset.x);
  input.deltaY = prevDelta.y + (center.y - offset.y);
}

/**
 * @private
 * calculate the velocity between two points. unit is in px per ms.
 * @param {Number} deltaTime
 * @param {Number} x
 * @param {Number} y
 * @return {Object} velocity `x` and `y`
 */
function getVelocity(deltaTime, x, y) {
  return {
    x: x / deltaTime || 0,
    y: y / deltaTime || 0
  };
}

/**
 * @private
 * calculate the scale factor between two pointersets
 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} scale
 */

function getScale(start, end) {
  return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
}

/**
 * @private
 * calculate the rotation degrees between two pointersets
 * @param {Array} start array of pointers
 * @param {Array} end array of pointers
 * @return {Number} rotation
 */

function getRotation(start, end) {
  return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
}

/**
 * @private
 * velocity is calculated every x ms
 * @param {Object} session
 * @param {Object} input
 */

function computeIntervalInputData(session, input) {
  var last = session.lastInterval || input;
  var deltaTime = input.timeStamp - last.timeStamp;
  var velocity;
  var velocityX;
  var velocityY;
  var direction;

  if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
    var deltaX = input.deltaX - last.deltaX;
    var deltaY = input.deltaY - last.deltaY;
    var v = getVelocity(deltaTime, deltaX, deltaY);
    velocityX = v.x;
    velocityY = v.y;
    velocity = abs$1(v.x) > abs$1(v.y) ? v.x : v.y;
    direction = getDirection(deltaX, deltaY);
    session.lastInterval = input;
  } else {
    // use latest velocity info if it doesn't overtake a minimum period
    velocity = last.velocity;
    velocityX = last.velocityX;
    velocityY = last.velocityY;
    direction = last.direction;
  }

  input.velocity = velocity;
  input.velocityX = velocityX;
  input.velocityY = velocityY;
  input.direction = direction;
}

/**
* @private
 * extend the data with some usable properties like scale, rotate, velocity etc
 * @param {Object} manager
 * @param {Object} input
 */

function computeInputData(manager, input) {
  var session = manager.session;
  var pointers = input.pointers;
  var pointersLength = pointers.length; // store the first input to calculate the distance and direction

  if (!session.firstInput) {
    session.firstInput = simpleCloneInputData(input);
  } // to compute scale and rotation we need to store the multiple touches


  if (pointersLength > 1 && !session.firstMultiple) {
    session.firstMultiple = simpleCloneInputData(input);
  } else if (pointersLength === 1) {
    session.firstMultiple = false;
  }

  var firstInput = session.firstInput,
      firstMultiple = session.firstMultiple;
  var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
  var center = input.center = getCenter(pointers);
  input.timeStamp = now();
  input.deltaTime = input.timeStamp - firstInput.timeStamp;
  input.angle = getAngle(offsetCenter, center);
  input.distance = getDistance(offsetCenter, center);
  computeDeltaXY(session, input);
  input.offsetDirection = getDirection(input.deltaX, input.deltaY);
  var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
  input.overallVelocityX = overallVelocity.x;
  input.overallVelocityY = overallVelocity.y;
  input.overallVelocity = abs$1(overallVelocity.x) > abs$1(overallVelocity.y) ? overallVelocity.x : overallVelocity.y;
  input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
  input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
  input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers;
  computeIntervalInputData(session, input); // find the correct target

  var target = manager.element;
  var srcEvent = input.srcEvent;
  var srcEventTarget;

  if (srcEvent.composedPath) {
    srcEventTarget = srcEvent.composedPath()[0];
  } else if (srcEvent.path) {
    srcEventTarget = srcEvent.path[0];
  } else {
    srcEventTarget = srcEvent.target;
  }

  if (hasParent(srcEventTarget, target)) {
    target = srcEventTarget;
  }

  input.target = target;
}

/**
 * @private
 * handle input events
 * @param {Manager} manager
 * @param {String} eventType
 * @param {Object} input
 */

function inputHandler(manager, eventType, input) {
  var pointersLen = input.pointers.length;
  var changedPointersLen = input.changedPointers.length;
  var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0;
  var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0;
  input.isFirst = !!isFirst;
  input.isFinal = !!isFinal;

  if (isFirst) {
    manager.session = {};
  } // source event is the normalized value of the domEvents
  // like 'touchstart, mouseup, pointerdown'


  input.eventType = eventType; // compute scale, rotation etc

  computeInputData(manager, input); // emit secret event

  manager.emit('hammer.input', input);
  manager.recognize(input);
  manager.session.prevInput = input;
}

/**
 * @private
 * split string on whitespace
 * @param {String} str
 * @returns {Array} words
 */
function splitStr(str) {
  return str.trim().split(/\s+/g);
}

/**
 * @private
 * addEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */

function addEventListeners(target, types, handler) {
  each$5(splitStr(types), function (type) {
    target.addEventListener(type, handler, false);
  });
}

/**
 * @private
 * removeEventListener with multiple events at once
 * @param {EventTarget} target
 * @param {String} types
 * @param {Function} handler
 */

function removeEventListeners(target, types, handler) {
  each$5(splitStr(types), function (type) {
    target.removeEventListener(type, handler, false);
  });
}

/**
 * @private
 * get the window object of an element
 * @param {HTMLElement} element
 * @returns {DocumentView|Window}
 */
function getWindowForElement(element) {
  var doc = element.ownerDocument || element;
  return doc.defaultView || doc.parentWindow || window;
}

/**
 * @private
 * create new input type manager
 * @param {Manager} manager
 * @param {Function} callback
 * @returns {Input}
 * @constructor
 */

var Input =
/*#__PURE__*/
function () {
  function Input(manager, callback) {
    var self = this;
    this.manager = manager;
    this.callback = callback;
    this.element = manager.element;
    this.target = manager.options.inputTarget; // smaller wrapper around the handler, for the scope and the enabled state of the manager,
    // so when disabled the input events are completely bypassed.

    this.domHandler = function (ev) {
      if (boolOrFn(manager.options.enable, [manager])) {
        self.handler(ev);
      }
    };

    this.init();
  }
  /**
   * @private
   * should handle the inputEvent data and trigger the callback
   * @virtual
   */


  var _proto = Input.prototype;

  _proto.handler = function handler() {};
  /**
   * @private
   * bind the events
   */


  _proto.init = function init() {
    this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
    this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
    this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
  };
  /**
   * @private
   * unbind the events
   */


  _proto.destroy = function destroy() {
    this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
    this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
    this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
  };

  return Input;
}();

/**
 * @private
 * find if a array contains the object using indexOf or a simple polyFill
 * @param {Array} src
 * @param {String} find
 * @param {String} [findByKey]
 * @return {Boolean|Number} false when not found, or the index
 */
function inArray(src, find, findByKey) {
  if (src.indexOf && !findByKey) {
    return src.indexOf(find);
  } else {
    var i = 0;

    while (i < src.length) {
      if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) {
        // do not use === here, test fails
        return i;
      }

      i++;
    }

    return -1;
  }
}

var POINTER_INPUT_MAP = {
  pointerdown: INPUT_START,
  pointermove: INPUT_MOVE,
  pointerup: INPUT_END,
  pointercancel: INPUT_CANCEL,
  pointerout: INPUT_CANCEL
}; // in IE10 the pointer types is defined as an enum

var IE10_POINTER_TYPE_ENUM = {
  2: INPUT_TYPE_TOUCH,
  3: INPUT_TYPE_PEN,
  4: INPUT_TYPE_MOUSE,
  5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816

};
var POINTER_ELEMENT_EVENTS = 'pointerdown';
var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive

if (win.MSPointerEvent && !win.PointerEvent) {
  POINTER_ELEMENT_EVENTS = 'MSPointerDown';
  POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
}
/**
 * @private
 * Pointer events input
 * @constructor
 * @extends Input
 */


var PointerEventInput =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose(PointerEventInput, _Input);

  function PointerEventInput() {
    var _this;

    var proto = PointerEventInput.prototype;
    proto.evEl = POINTER_ELEMENT_EVENTS;
    proto.evWin = POINTER_WINDOW_EVENTS;
    _this = _Input.apply(this, arguments) || this;
    _this.store = _this.manager.session.pointerEvents = [];
    return _this;
  }
  /**
   * @private
   * handle mouse events
   * @param {Object} ev
   */


  var _proto = PointerEventInput.prototype;

  _proto.handler = function handler(ev) {
    var store = this.store;
    var removePointer = false;
    var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
    var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
    var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
    var isTouch = pointerType === INPUT_TYPE_TOUCH; // get index of the event in the store

    var storeIndex = inArray(store, ev.pointerId, 'pointerId'); // start and mouse must be down

    if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
      if (storeIndex < 0) {
        store.push(ev);
        storeIndex = store.length - 1;
      }
    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
      removePointer = true;
    } // it not found, so the pointer hasn't been down (so it's probably a hover)


    if (storeIndex < 0) {
      return;
    } // update the event in the store


    store[storeIndex] = ev;
    this.callback(this.manager, eventType, {
      pointers: store,
      changedPointers: [ev],
      pointerType: pointerType,
      srcEvent: ev
    });

    if (removePointer) {
      // remove from the store
      store.splice(storeIndex, 1);
    }
  };

  return PointerEventInput;
}(Input);

/**
 * @private
 * convert array-like objects to real arrays
 * @param {Object} obj
 * @returns {Array}
 */
function toArray(obj) {
  return Array.prototype.slice.call(obj, 0);
}

/**
 * @private
 * unique array with objects based on a key (like 'id') or just by the array's value
 * @param {Array} src [{id:1},{id:2},{id:1}]
 * @param {String} [key]
 * @param {Boolean} [sort=False]
 * @returns {Array} [{id:1},{id:2}]
 */

function uniqueArray(src, key, sort) {
  var results = [];
  var values = [];
  var i = 0;

  while (i < src.length) {
    var val = key ? src[i][key] : src[i];

    if (inArray(values, val) < 0) {
      results.push(src[i]);
    }

    values[i] = val;
    i++;
  }

  if (sort) {
    if (!key) {
      results = results.sort();
    } else {
      results = results.sort(function (a, b) {
        return a[key] > b[key];
      });
    }
  }

  return results;
}

var TOUCH_INPUT_MAP = {
  touchstart: INPUT_START,
  touchmove: INPUT_MOVE,
  touchend: INPUT_END,
  touchcancel: INPUT_CANCEL
};
var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
/**
 * @private
 * Multi-user touch events input
 * @constructor
 * @extends Input
 */

var TouchInput =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose(TouchInput, _Input);

  function TouchInput() {
    var _this;

    TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;
    _this = _Input.apply(this, arguments) || this;
    _this.targetIds = {}; // this.evTarget = TOUCH_TARGET_EVENTS;

    return _this;
  }

  var _proto = TouchInput.prototype;

  _proto.handler = function handler(ev) {
    var type = TOUCH_INPUT_MAP[ev.type];
    var touches = getTouches.call(this, ev, type);

    if (!touches) {
      return;
    }

    this.callback(this.manager, type, {
      pointers: touches[0],
      changedPointers: touches[1],
      pointerType: INPUT_TYPE_TOUCH,
      srcEvent: ev
    });
  };

  return TouchInput;
}(Input);

function getTouches(ev, type) {
  var allTouches = toArray(ev.touches);
  var targetIds = this.targetIds; // when there is only one touch, the process can be simplified

  if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
    targetIds[allTouches[0].identifier] = true;
    return [allTouches, allTouches];
  }

  var i;
  var targetTouches;
  var changedTouches = toArray(ev.changedTouches);
  var changedTargetTouches = [];
  var target = this.target; // get target touches from touches

  targetTouches = allTouches.filter(function (touch) {
    return hasParent(touch.target, target);
  }); // collect touches

  if (type === INPUT_START) {
    i = 0;

    while (i < targetTouches.length) {
      targetIds[targetTouches[i].identifier] = true;
      i++;
    }
  } // filter changed touches to only contain touches that exist in the collected target ids


  i = 0;

  while (i < changedTouches.length) {
    if (targetIds[changedTouches[i].identifier]) {
      changedTargetTouches.push(changedTouches[i]);
    } // cleanup removed touches


    if (type & (INPUT_END | INPUT_CANCEL)) {
      delete targetIds[changedTouches[i].identifier];
    }

    i++;
  }

  if (!changedTargetTouches.length) {
    return;
  }

  return [// merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
  uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches];
}

var MOUSE_INPUT_MAP = {
  mousedown: INPUT_START,
  mousemove: INPUT_MOVE,
  mouseup: INPUT_END
};
var MOUSE_ELEMENT_EVENTS = 'mousedown';
var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
/**
 * @private
 * Mouse events input
 * @constructor
 * @extends Input
 */

var MouseInput =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose(MouseInput, _Input);

  function MouseInput() {
    var _this;

    var proto = MouseInput.prototype;
    proto.evEl = MOUSE_ELEMENT_EVENTS;
    proto.evWin = MOUSE_WINDOW_EVENTS;
    _this = _Input.apply(this, arguments) || this;
    _this.pressed = false; // mousedown state

    return _this;
  }
  /**
   * @private
   * handle mouse events
   * @param {Object} ev
   */


  var _proto = MouseInput.prototype;

  _proto.handler = function handler(ev) {
    var eventType = MOUSE_INPUT_MAP[ev.type]; // on start we want to have the left mouse button down

    if (eventType & INPUT_START && ev.button === 0) {
      this.pressed = true;
    }

    if (eventType & INPUT_MOVE && ev.which !== 1) {
      eventType = INPUT_END;
    } // mouse must be down


    if (!this.pressed) {
      return;
    }

    if (eventType & INPUT_END) {
      this.pressed = false;
    }

    this.callback(this.manager, eventType, {
      pointers: [ev],
      changedPointers: [ev],
      pointerType: INPUT_TYPE_MOUSE,
      srcEvent: ev
    });
  };

  return MouseInput;
}(Input);

/**
 * @private
 * Combined touch and mouse input
 *
 * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
 * This because touch devices also emit mouse events while doing a touch.
 *
 * @constructor
 * @extends Input
 */

var DEDUP_TIMEOUT = 2500;
var DEDUP_DISTANCE = 25;

function setLastTouch(eventData) {
  var _eventData$changedPoi = eventData.changedPointers,
      touch = _eventData$changedPoi[0];

  if (touch.identifier === this.primaryTouch) {
    var lastTouch = {
      x: touch.clientX,
      y: touch.clientY
    };
    var lts = this.lastTouches;
    this.lastTouches.push(lastTouch);

    var removeLastTouch = function removeLastTouch() {
      var i = lts.indexOf(lastTouch);

      if (i > -1) {
        lts.splice(i, 1);
      }
    };

    setTimeout(removeLastTouch, DEDUP_TIMEOUT);
  }
}

function recordTouches(eventType, eventData) {
  if (eventType & INPUT_START) {
    this.primaryTouch = eventData.changedPointers[0].identifier;
    setLastTouch.call(this, eventData);
  } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
    setLastTouch.call(this, eventData);
  }
}

function isSyntheticEvent(eventData) {
  var x = eventData.srcEvent.clientX;
  var y = eventData.srcEvent.clientY;

  for (var i = 0; i < this.lastTouches.length; i++) {
    var t = this.lastTouches[i];
    var dx = Math.abs(x - t.x);
    var dy = Math.abs(y - t.y);

    if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
      return true;
    }
  }

  return false;
}

var TouchMouseInput =
/*#__PURE__*/
function () {
  var TouchMouseInput =
  /*#__PURE__*/
  function (_Input) {
    _inheritsLoose(TouchMouseInput, _Input);

    function TouchMouseInput(_manager, callback) {
      var _this;

      _this = _Input.call(this, _manager, callback) || this;

      _this.handler = function (manager, inputEvent, inputData) {
        var isTouch = inputData.pointerType === INPUT_TYPE_TOUCH;
        var isMouse = inputData.pointerType === INPUT_TYPE_MOUSE;

        if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
          return;
        } // when we're in a touch event, record touches to  de-dupe synthetic mouse event


        if (isTouch) {
          recordTouches.call(_assertThisInitialized$1(_assertThisInitialized$1(_this)), inputEvent, inputData);
        } else if (isMouse && isSyntheticEvent.call(_assertThisInitialized$1(_assertThisInitialized$1(_this)), inputData)) {
          return;
        }

        _this.callback(manager, inputEvent, inputData);
      };

      _this.touch = new TouchInput(_this.manager, _this.handler);
      _this.mouse = new MouseInput(_this.manager, _this.handler);
      _this.primaryTouch = null;
      _this.lastTouches = [];
      return _this;
    }
    /**
     * @private
     * handle mouse and touch events
     * @param {Hammer} manager
     * @param {String} inputEvent
     * @param {Object} inputData
     */


    var _proto = TouchMouseInput.prototype;

    /**
     * @private
     * remove the event listeners
     */
    _proto.destroy = function destroy() {
      this.touch.destroy();
      this.mouse.destroy();
    };

    return TouchMouseInput;
  }(Input);

  return TouchMouseInput;
}();

/**
 * @private
 * create new input type manager
 * called by the Manager constructor
 * @param {Hammer} manager
 * @returns {Input}
 */

function createInputInstance(manager) {
  var Type; // let inputClass = manager.options.inputClass;

  var inputClass = manager.options.inputClass;

  if (inputClass) {
    Type = inputClass;
  } else if (SUPPORT_POINTER_EVENTS) {
    Type = PointerEventInput;
  } else if (SUPPORT_ONLY_TOUCH) {
    Type = TouchInput;
  } else if (!SUPPORT_TOUCH) {
    Type = MouseInput;
  } else {
    Type = TouchMouseInput;
  }

  return new Type(manager, inputHandler);
}

/**
 * @private
 * if the argument is an array, we want to execute the fn on each entry
 * if it aint an array we don't want to do a thing.
 * this is used by all the methods that accept a single and array argument.
 * @param {*|Array} arg
 * @param {String} fn
 * @param {Object} [context]
 * @returns {Boolean}
 */

function invokeArrayArg(arg, fn, context) {
  if (Array.isArray(arg)) {
    each$5(arg, context[fn], context);
    return true;
  }

  return false;
}

var STATE_POSSIBLE = 1;
var STATE_BEGAN = 2;
var STATE_CHANGED = 4;
var STATE_ENDED = 8;
var STATE_RECOGNIZED = STATE_ENDED;
var STATE_CANCELLED = 16;
var STATE_FAILED = 32;

/**
 * @private
 * get a unique id
 * @returns {number} uniqueId
 */
var _uniqueId = 1;
function uniqueId() {
  return _uniqueId++;
}

/**
 * @private
 * get a recognizer by name if it is bound to a manager
 * @param {Recognizer|String} otherRecognizer
 * @param {Recognizer} recognizer
 * @returns {Recognizer}
 */
function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
  var manager = recognizer.manager;

  if (manager) {
    return manager.get(otherRecognizer);
  }

  return otherRecognizer;
}

/**
 * @private
 * get a usable string, used as event postfix
 * @param {constant} state
 * @returns {String} state
 */

function stateStr(state) {
  if (state & STATE_CANCELLED) {
    return 'cancel';
  } else if (state & STATE_ENDED) {
    return 'end';
  } else if (state & STATE_CHANGED) {
    return 'move';
  } else if (state & STATE_BEGAN) {
    return 'start';
  }

  return '';
}

/**
 * @private
 * Recognizer flow explained; *
 * All recognizers have the initial state of POSSIBLE when a input session starts.
 * The definition of a input session is from the first input until the last input, with all it's movement in it. *
 * Example session for mouse-input: mousedown -> mousemove -> mouseup
 *
 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
 * which determines with state it should be.
 *
 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
 * POSSIBLE to give it another change on the next cycle.
 *
 *               Possible
 *                  |
 *            +-----+---------------+
 *            |                     |
 *      +-----+-----+               |
 *      |           |               |
 *   Failed      Cancelled          |
 *                          +-------+------+
 *                          |              |
 *                      Recognized       Began
 *                                         |
 *                                      Changed
 *                                         |
 *                                  Ended/Recognized
 */

/**
 * @private
 * Recognizer
 * Every recognizer needs to extend from this class.
 * @constructor
 * @param {Object} options
 */

var Recognizer =
/*#__PURE__*/
function () {
  function Recognizer(options) {
    if (options === void 0) {
      options = {};
    }

    this.options = _extends({
      enable: true
    }, options);
    this.id = uniqueId();
    this.manager = null; // default is enable true

    this.state = STATE_POSSIBLE;
    this.simultaneous = {};
    this.requireFail = [];
  }
  /**
   * @private
   * set options
   * @param {Object} options
   * @return {Recognizer}
   */


  var _proto = Recognizer.prototype;

  _proto.set = function set(options) {
    assign$1(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state

    this.manager && this.manager.touchAction.update();
    return this;
  };
  /**
   * @private
   * recognize simultaneous with an other recognizer.
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.recognizeWith = function recognizeWith(otherRecognizer) {
    if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
      return this;
    }

    var simultaneous = this.simultaneous;
    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);

    if (!simultaneous[otherRecognizer.id]) {
      simultaneous[otherRecognizer.id] = otherRecognizer;
      otherRecognizer.recognizeWith(this);
    }

    return this;
  };
  /**
   * @private
   * drop the simultaneous link. it doesnt remove the link on the other recognizer.
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.dropRecognizeWith = function dropRecognizeWith(otherRecognizer) {
    if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
      return this;
    }

    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
    delete this.simultaneous[otherRecognizer.id];
    return this;
  };
  /**
   * @private
   * recognizer can only run when an other is failing
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.requireFailure = function requireFailure(otherRecognizer) {
    if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
      return this;
    }

    var requireFail = this.requireFail;
    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);

    if (inArray(requireFail, otherRecognizer) === -1) {
      requireFail.push(otherRecognizer);
      otherRecognizer.requireFailure(this);
    }

    return this;
  };
  /**
   * @private
   * drop the requireFailure link. it does not remove the link on the other recognizer.
   * @param {Recognizer} otherRecognizer
   * @returns {Recognizer} this
   */


  _proto.dropRequireFailure = function dropRequireFailure(otherRecognizer) {
    if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
      return this;
    }

    otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
    var index = inArray(this.requireFail, otherRecognizer);

    if (index > -1) {
      this.requireFail.splice(index, 1);
    }

    return this;
  };
  /**
   * @private
   * has require failures boolean
   * @returns {boolean}
   */


  _proto.hasRequireFailures = function hasRequireFailures() {
    return this.requireFail.length > 0;
  };
  /**
   * @private
   * if the recognizer can recognize simultaneous with an other recognizer
   * @param {Recognizer} otherRecognizer
   * @returns {Boolean}
   */


  _proto.canRecognizeWith = function canRecognizeWith(otherRecognizer) {
    return !!this.simultaneous[otherRecognizer.id];
  };
  /**
   * @private
   * You should use `tryEmit` instead of `emit` directly to check
   * that all the needed recognizers has failed before emitting.
   * @param {Object} input
   */


  _proto.emit = function emit(input) {
    var self = this;
    var state = this.state;

    function emit(event) {
      self.manager.emit(event, input);
    } // 'panstart' and 'panmove'


    if (state < STATE_ENDED) {
      emit(self.options.event + stateStr(state));
    }

    emit(self.options.event); // simple 'eventName' events

    if (input.additionalEvent) {
      // additional event(panleft, panright, pinchin, pinchout...)
      emit(input.additionalEvent);
    } // panend and pancancel


    if (state >= STATE_ENDED) {
      emit(self.options.event + stateStr(state));
    }
  };
  /**
   * @private
   * Check that all the require failure recognizers has failed,
   * if true, it emits a gesture event,
   * otherwise, setup the state to FAILED.
   * @param {Object} input
   */


  _proto.tryEmit = function tryEmit(input) {
    if (this.canEmit()) {
      return this.emit(input);
    } // it's failing anyway


    this.state = STATE_FAILED;
  };
  /**
   * @private
   * can we emit?
   * @returns {boolean}
   */


  _proto.canEmit = function canEmit() {
    var i = 0;

    while (i < this.requireFail.length) {
      if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
        return false;
      }

      i++;
    }

    return true;
  };
  /**
   * @private
   * update the recognizer
   * @param {Object} inputData
   */


  _proto.recognize = function recognize(inputData) {
    // make a new copy of the inputData
    // so we can change the inputData without messing up the other recognizers
    var inputDataClone = assign$1({}, inputData); // is is enabled and allow recognizing?

    if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
      this.reset();
      this.state = STATE_FAILED;
      return;
    } // reset when we've reached the end


    if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
      this.state = STATE_POSSIBLE;
    }

    this.state = this.process(inputDataClone); // the recognizer has recognized a gesture
    // so trigger an event

    if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
      this.tryEmit(inputDataClone);
    }
  };
  /**
   * @private
   * return the state of the recognizer
   * the actual recognizing happens in this method
   * @virtual
   * @param {Object} inputData
   * @returns {constant} STATE
   */

  /* jshint ignore:start */


  _proto.process = function process(inputData) {};
  /* jshint ignore:end */

  /**
   * @private
   * return the preferred touch-action
   * @virtual
   * @returns {Array}
   */


  _proto.getTouchAction = function getTouchAction() {};
  /**
   * @private
   * called when the gesture isn't allowed to recognize
   * like when another is being recognized or it is disabled
   * @virtual
   */


  _proto.reset = function reset() {};

  return Recognizer;
}();

/**
 * @private
 * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
 * between the given interval and position. The delay option can be used to recognize multi-taps without firing
 * a single tap.
 *
 * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
 * multi-taps being recognized.
 * @constructor
 * @extends Recognizer
 */

var TapRecognizer =
/*#__PURE__*/
function (_Recognizer) {
  _inheritsLoose(TapRecognizer, _Recognizer);

  function TapRecognizer(options) {
    var _this;

    if (options === void 0) {
      options = {};
    }

    _this = _Recognizer.call(this, _extends({
      event: 'tap',
      pointers: 1,
      taps: 1,
      interval: 300,
      // max time between the multi-tap taps
      time: 250,
      // max time of the pointer to be down (like finger on the screen)
      threshold: 9,
      // a minimal movement is ok, but keep it low
      posThreshold: 10
    }, options)) || this; // previous time and center,
    // used for tap counting

    _this.pTime = false;
    _this.pCenter = false;
    _this._timer = null;
    _this._input = null;
    _this.count = 0;
    return _this;
  }

  var _proto = TapRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_MANIPULATION];
  };

  _proto.process = function process(input) {
    var _this2 = this;

    var options = this.options;
    var validPointers = input.pointers.length === options.pointers;
    var validMovement = input.distance < options.threshold;
    var validTouchTime = input.deltaTime < options.time;
    this.reset();

    if (input.eventType & INPUT_START && this.count === 0) {
      return this.failTimeout();
    } // we only allow little movement
    // and we've reached an end event, so a tap is possible


    if (validMovement && validTouchTime && validPointers) {
      if (input.eventType !== INPUT_END) {
        return this.failTimeout();
      }

      var validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true;
      var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
      this.pTime = input.timeStamp;
      this.pCenter = input.center;

      if (!validMultiTap || !validInterval) {
        this.count = 1;
      } else {
        this.count += 1;
      }

      this._input = input; // if tap count matches we have recognized it,
      // else it has began recognizing...

      var tapCount = this.count % options.taps;

      if (tapCount === 0) {
        // no failing requirements, immediately trigger the tap event
        // or wait as long as the multitap interval to trigger
        if (!this.hasRequireFailures()) {
          return STATE_RECOGNIZED;
        } else {
          this._timer = setTimeout(function () {
            _this2.state = STATE_RECOGNIZED;

            _this2.tryEmit();
          }, options.interval);
          return STATE_BEGAN;
        }
      }
    }

    return STATE_FAILED;
  };

  _proto.failTimeout = function failTimeout() {
    var _this3 = this;

    this._timer = setTimeout(function () {
      _this3.state = STATE_FAILED;
    }, this.options.interval);
    return STATE_FAILED;
  };

  _proto.reset = function reset() {
    clearTimeout(this._timer);
  };

  _proto.emit = function emit() {
    if (this.state === STATE_RECOGNIZED) {
      this._input.tapCount = this.count;
      this.manager.emit(this.options.event, this._input);
    }
  };

  return TapRecognizer;
}(Recognizer);

/**
 * @private
 * This recognizer is just used as a base for the simple attribute recognizers.
 * @constructor
 * @extends Recognizer
 */

var AttrRecognizer =
/*#__PURE__*/
function (_Recognizer) {
  _inheritsLoose(AttrRecognizer, _Recognizer);

  function AttrRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _Recognizer.call(this, _extends({
      pointers: 1
    }, options)) || this;
  }
  /**
   * @private
   * Used to check if it the recognizer receives valid input, like input.distance > 10.
   * @memberof AttrRecognizer
   * @param {Object} input
   * @returns {Boolean} recognized
   */


  var _proto = AttrRecognizer.prototype;

  _proto.attrTest = function attrTest(input) {
    var optionPointers = this.options.pointers;
    return optionPointers === 0 || input.pointers.length === optionPointers;
  };
  /**
   * @private
   * Process the input and return the state for the recognizer
   * @memberof AttrRecognizer
   * @param {Object} input
   * @returns {*} State
   */


  _proto.process = function process(input) {
    var state = this.state;
    var eventType = input.eventType;
    var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
    var isValid = this.attrTest(input); // on cancel input and we've recognized before, return STATE_CANCELLED

    if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
      return state | STATE_CANCELLED;
    } else if (isRecognized || isValid) {
      if (eventType & INPUT_END) {
        return state | STATE_ENDED;
      } else if (!(state & STATE_BEGAN)) {
        return STATE_BEGAN;
      }

      return state | STATE_CHANGED;
    }

    return STATE_FAILED;
  };

  return AttrRecognizer;
}(Recognizer);

/**
 * @private
 * direction cons to string
 * @param {constant} direction
 * @returns {String}
 */

function directionStr(direction) {
  if (direction === DIRECTION_DOWN) {
    return 'down';
  } else if (direction === DIRECTION_UP) {
    return 'up';
  } else if (direction === DIRECTION_LEFT) {
    return 'left';
  } else if (direction === DIRECTION_RIGHT) {
    return 'right';
  }

  return '';
}

/**
 * @private
 * Pan
 * Recognized when the pointer is down and moved in the allowed direction.
 * @constructor
 * @extends AttrRecognizer
 */

var PanRecognizer =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose(PanRecognizer, _AttrRecognizer);

  function PanRecognizer(options) {
    var _this;

    if (options === void 0) {
      options = {};
    }

    _this = _AttrRecognizer.call(this, _extends({
      event: 'pan',
      threshold: 10,
      pointers: 1,
      direction: DIRECTION_ALL
    }, options)) || this;
    _this.pX = null;
    _this.pY = null;
    return _this;
  }

  var _proto = PanRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    var direction = this.options.direction;
    var actions = [];

    if (direction & DIRECTION_HORIZONTAL) {
      actions.push(TOUCH_ACTION_PAN_Y);
    }

    if (direction & DIRECTION_VERTICAL) {
      actions.push(TOUCH_ACTION_PAN_X);
    }

    return actions;
  };

  _proto.directionTest = function directionTest(input) {
    var options = this.options;
    var hasMoved = true;
    var distance = input.distance;
    var direction = input.direction;
    var x = input.deltaX;
    var y = input.deltaY; // lock to axis?

    if (!(direction & options.direction)) {
      if (options.direction & DIRECTION_HORIZONTAL) {
        direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
        hasMoved = x !== this.pX;
        distance = Math.abs(input.deltaX);
      } else {
        direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
        hasMoved = y !== this.pY;
        distance = Math.abs(input.deltaY);
      }
    }

    input.direction = direction;
    return hasMoved && distance > options.threshold && direction & options.direction;
  };

  _proto.attrTest = function attrTest(input) {
    return AttrRecognizer.prototype.attrTest.call(this, input) && ( // replace with a super call
    this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input));
  };

  _proto.emit = function emit(input) {
    this.pX = input.deltaX;
    this.pY = input.deltaY;
    var direction = directionStr(input.direction);

    if (direction) {
      input.additionalEvent = this.options.event + direction;
    }

    _AttrRecognizer.prototype.emit.call(this, input);
  };

  return PanRecognizer;
}(AttrRecognizer);

/**
 * @private
 * Swipe
 * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
 * @constructor
 * @extends AttrRecognizer
 */

var SwipeRecognizer =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose(SwipeRecognizer, _AttrRecognizer);

  function SwipeRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _AttrRecognizer.call(this, _extends({
      event: 'swipe',
      threshold: 10,
      velocity: 0.3,
      direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
      pointers: 1
    }, options)) || this;
  }

  var _proto = SwipeRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return PanRecognizer.prototype.getTouchAction.call(this);
  };

  _proto.attrTest = function attrTest(input) {
    var direction = this.options.direction;
    var velocity;

    if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
      velocity = input.overallVelocity;
    } else if (direction & DIRECTION_HORIZONTAL) {
      velocity = input.overallVelocityX;
    } else if (direction & DIRECTION_VERTICAL) {
      velocity = input.overallVelocityY;
    }

    return _AttrRecognizer.prototype.attrTest.call(this, input) && direction & input.offsetDirection && input.distance > this.options.threshold && input.maxPointers === this.options.pointers && abs$1(velocity) > this.options.velocity && input.eventType & INPUT_END;
  };

  _proto.emit = function emit(input) {
    var direction = directionStr(input.offsetDirection);

    if (direction) {
      this.manager.emit(this.options.event + direction, input);
    }

    this.manager.emit(this.options.event, input);
  };

  return SwipeRecognizer;
}(AttrRecognizer);

/**
 * @private
 * Pinch
 * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
 * @constructor
 * @extends AttrRecognizer
 */

var PinchRecognizer =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose(PinchRecognizer, _AttrRecognizer);

  function PinchRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _AttrRecognizer.call(this, _extends({
      event: 'pinch',
      threshold: 0,
      pointers: 2
    }, options)) || this;
  }

  var _proto = PinchRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_NONE];
  };

  _proto.attrTest = function attrTest(input) {
    return _AttrRecognizer.prototype.attrTest.call(this, input) && (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
  };

  _proto.emit = function emit(input) {
    if (input.scale !== 1) {
      var inOut = input.scale < 1 ? 'in' : 'out';
      input.additionalEvent = this.options.event + inOut;
    }

    _AttrRecognizer.prototype.emit.call(this, input);
  };

  return PinchRecognizer;
}(AttrRecognizer);

/**
 * @private
 * Rotate
 * Recognized when two or more pointer are moving in a circular motion.
 * @constructor
 * @extends AttrRecognizer
 */

var RotateRecognizer =
/*#__PURE__*/
function (_AttrRecognizer) {
  _inheritsLoose(RotateRecognizer, _AttrRecognizer);

  function RotateRecognizer(options) {
    if (options === void 0) {
      options = {};
    }

    return _AttrRecognizer.call(this, _extends({
      event: 'rotate',
      threshold: 0,
      pointers: 2
    }, options)) || this;
  }

  var _proto = RotateRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_NONE];
  };

  _proto.attrTest = function attrTest(input) {
    return _AttrRecognizer.prototype.attrTest.call(this, input) && (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
  };

  return RotateRecognizer;
}(AttrRecognizer);

/**
 * @private
 * Press
 * Recognized when the pointer is down for x ms without any movement.
 * @constructor
 * @extends Recognizer
 */

var PressRecognizer =
/*#__PURE__*/
function (_Recognizer) {
  _inheritsLoose(PressRecognizer, _Recognizer);

  function PressRecognizer(options) {
    var _this;

    if (options === void 0) {
      options = {};
    }

    _this = _Recognizer.call(this, _extends({
      event: 'press',
      pointers: 1,
      time: 251,
      // minimal time of the pointer to be pressed
      threshold: 9
    }, options)) || this;
    _this._timer = null;
    _this._input = null;
    return _this;
  }

  var _proto = PressRecognizer.prototype;

  _proto.getTouchAction = function getTouchAction() {
    return [TOUCH_ACTION_AUTO];
  };

  _proto.process = function process(input) {
    var _this2 = this;

    var options = this.options;
    var validPointers = input.pointers.length === options.pointers;
    var validMovement = input.distance < options.threshold;
    var validTime = input.deltaTime > options.time;
    this._input = input; // we only allow little movement
    // and we've reached an end event, so a tap is possible

    if (!validMovement || !validPointers || input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime) {
      this.reset();
    } else if (input.eventType & INPUT_START) {
      this.reset();
      this._timer = setTimeout(function () {
        _this2.state = STATE_RECOGNIZED;

        _this2.tryEmit();
      }, options.time);
    } else if (input.eventType & INPUT_END) {
      return STATE_RECOGNIZED;
    }

    return STATE_FAILED;
  };

  _proto.reset = function reset() {
    clearTimeout(this._timer);
  };

  _proto.emit = function emit(input) {
    if (this.state !== STATE_RECOGNIZED) {
      return;
    }

    if (input && input.eventType & INPUT_END) {
      this.manager.emit(this.options.event + "up", input);
    } else {
      this._input.timeStamp = now();
      this.manager.emit(this.options.event, this._input);
    }
  };

  return PressRecognizer;
}(Recognizer);

var defaults$1 = {
  /**
   * @private
   * set if DOM events are being triggered.
   * But this is slower and unused by simple implementations, so disabled by default.
   * @type {Boolean}
   * @default false
   */
  domEvents: false,

  /**
   * @private
   * The value for the touchAction property/fallback.
   * When set to `compute` it will magically set the correct value based on the added recognizers.
   * @type {String}
   * @default compute
   */
  touchAction: TOUCH_ACTION_COMPUTE,

  /**
   * @private
   * @type {Boolean}
   * @default true
   */
  enable: true,

  /**
   * @private
   * EXPERIMENTAL FEATURE -- can be removed/changed
   * Change the parent input target element.
   * If Null, then it is being set the to main element.
   * @type {Null|EventTarget}
   * @default null
   */
  inputTarget: null,

  /**
   * @private
   * force an input class
   * @type {Null|Function}
   * @default null
   */
  inputClass: null,

  /**
   * @private
   * Some CSS properties can be used to improve the working of Hammer.
   * Add them to this method and they will be set when creating a new Manager.
   * @namespace
   */
  cssProps: {
    /**
     * @private
     * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
     * @type {String}
     * @default 'none'
     */
    userSelect: "none",

    /**
     * @private
     * Disable the Windows Phone grippers when pressing an element.
     * @type {String}
     * @default 'none'
     */
    touchSelect: "none",

    /**
     * @private
     * Disables the default callout shown when you touch and hold a touch target.
     * On iOS, when you touch and hold a touch target such as a link, Safari displays
     * a callout containing information about the link. This property allows you to disable that callout.
     * @type {String}
     * @default 'none'
     */
    touchCallout: "none",

    /**
     * @private
     * Specifies whether zooming is enabled. Used by IE10>
     * @type {String}
     * @default 'none'
     */
    contentZooming: "none",

    /**
     * @private
     * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
     * @type {String}
     * @default 'none'
     */
    userDrag: "none",

    /**
     * @private
     * Overrides the highlight color shown when the user taps a link or a JavaScript
     * clickable element in iOS. This property obeys the alpha value, if specified.
     * @type {String}
     * @default 'rgba(0,0,0,0)'
     */
    tapHighlightColor: "rgba(0,0,0,0)"
  }
};
/**
 * @private
 * Default recognizer setup when calling `Hammer()`
 * When creating a new Manager these will be skipped.
 * This is separated with other defaults because of tree-shaking.
 * @type {Array}
 */

var preset = [[RotateRecognizer, {
  enable: false
}], [PinchRecognizer, {
  enable: false
}, ['rotate']], [SwipeRecognizer, {
  direction: DIRECTION_HORIZONTAL
}], [PanRecognizer, {
  direction: DIRECTION_HORIZONTAL
}, ['swipe']], [TapRecognizer], [TapRecognizer, {
  event: 'doubletap',
  taps: 2
}, ['tap']], [PressRecognizer]];

var STOP = 1;
var FORCED_STOP = 2;
/**
 * @private
 * add/remove the css properties as defined in manager.options.cssProps
 * @param {Manager} manager
 * @param {Boolean} add
 */

function toggleCssProps(manager, add) {
  var element = manager.element;

  if (!element.style) {
    return;
  }

  var prop;
  each$5(manager.options.cssProps, function (value, name) {
    prop = prefixed(element.style, name);

    if (add) {
      manager.oldCssProps[prop] = element.style[prop];
      element.style[prop] = value;
    } else {
      element.style[prop] = manager.oldCssProps[prop] || "";
    }
  });

  if (!add) {
    manager.oldCssProps = {};
  }
}
/**
 * @private
 * trigger dom event
 * @param {String} event
 * @param {Object} data
 */


function triggerDomEvent(event, data) {
  var gestureEvent = document.createEvent("Event");
  gestureEvent.initEvent(event, true, true);
  gestureEvent.gesture = data;
  data.target.dispatchEvent(gestureEvent);
}
/**
* @private
 * Manager
 * @param {HTMLElement} element
 * @param {Object} [options]
 * @constructor
 */


var Manager =
/*#__PURE__*/
function () {
  function Manager(element, options) {
    var _this = this;

    this.options = assign$1({}, defaults$1, options || {});
    this.options.inputTarget = this.options.inputTarget || element;
    this.handlers = {};
    this.session = {};
    this.recognizers = [];
    this.oldCssProps = {};
    this.element = element;
    this.input = createInputInstance(this);
    this.touchAction = new TouchAction(this, this.options.touchAction);
    toggleCssProps(this, true);
    each$5(this.options.recognizers, function (item) {
      var recognizer = _this.add(new item[0](item[1]));

      item[2] && recognizer.recognizeWith(item[2]);
      item[3] && recognizer.requireFailure(item[3]);
    }, this);
  }
  /**
   * @private
   * set options
   * @param {Object} options
   * @returns {Manager}
   */


  var _proto = Manager.prototype;

  _proto.set = function set(options) {
    assign$1(this.options, options); // Options that need a little more setup

    if (options.touchAction) {
      this.touchAction.update();
    }

    if (options.inputTarget) {
      // Clean up existing event listeners and reinitialize
      this.input.destroy();
      this.input.target = options.inputTarget;
      this.input.init();
    }

    return this;
  };
  /**
   * @private
   * stop recognizing for this session.
   * This session will be discarded, when a new [input]start event is fired.
   * When forced, the recognizer cycle is stopped immediately.
   * @param {Boolean} [force]
   */


  _proto.stop = function stop(force) {
    this.session.stopped = force ? FORCED_STOP : STOP;
  };
  /**
   * @private
   * run the recognizers!
   * called by the inputHandler function on every movement of the pointers (touches)
   * it walks through all the recognizers and tries to detect the gesture that is being made
   * @param {Object} inputData
   */


  _proto.recognize = function recognize(inputData) {
    var session = this.session;

    if (session.stopped) {
      return;
    } // run the touch-action polyfill


    this.touchAction.preventDefaults(inputData);
    var recognizer;
    var recognizers = this.recognizers; // this holds the recognizer that is being recognized.
    // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
    // if no recognizer is detecting a thing, it is set to `null`

    var curRecognizer = session.curRecognizer; // reset when the last recognizer is recognized
    // or when we're in a new session

    if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) {
      session.curRecognizer = null;
      curRecognizer = null;
    }

    var i = 0;

    while (i < recognizers.length) {
      recognizer = recognizers[i]; // find out if we are allowed try to recognize the input for this one.
      // 1.   allow if the session is NOT forced stopped (see the .stop() method)
      // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
      //      that is being recognized.
      // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
      //      this can be setup with the `recognizeWith()` method on the recognizer.

      if (session.stopped !== FORCED_STOP && ( // 1
      !curRecognizer || recognizer === curRecognizer || // 2
      recognizer.canRecognizeWith(curRecognizer))) {
        // 3
        recognizer.recognize(inputData);
      } else {
        recognizer.reset();
      } // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
      // current active recognizer. but only if we don't already have an active recognizer


      if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
        session.curRecognizer = recognizer;
        curRecognizer = recognizer;
      }

      i++;
    }
  };
  /**
   * @private
   * get a recognizer by its event name.
   * @param {Recognizer|String} recognizer
   * @returns {Recognizer|Null}
   */


  _proto.get = function get(recognizer) {
    if (recognizer instanceof Recognizer) {
      return recognizer;
    }

    var recognizers = this.recognizers;

    for (var i = 0; i < recognizers.length; i++) {
      if (recognizers[i].options.event === recognizer) {
        return recognizers[i];
      }
    }

    return null;
  };
  /**
   * @private add a recognizer to the manager
   * existing recognizers with the same event name will be removed
   * @param {Recognizer} recognizer
   * @returns {Recognizer|Manager}
   */


  _proto.add = function add(recognizer) {
    if (invokeArrayArg(recognizer, "add", this)) {
      return this;
    } // remove existing


    var existing = this.get(recognizer.options.event);

    if (existing) {
      this.remove(existing);
    }

    this.recognizers.push(recognizer);
    recognizer.manager = this;
    this.touchAction.update();
    return recognizer;
  };
  /**
   * @private
   * remove a recognizer by name or instance
   * @param {Recognizer|String} recognizer
   * @returns {Manager}
   */


  _proto.remove = function remove(recognizer) {
    if (invokeArrayArg(recognizer, "remove", this)) {
      return this;
    }

    var targetRecognizer = this.get(recognizer); // let's make sure this recognizer exists

    if (recognizer) {
      var recognizers = this.recognizers;
      var index = inArray(recognizers, targetRecognizer);

      if (index !== -1) {
        recognizers.splice(index, 1);
        this.touchAction.update();
      }
    }

    return this;
  };
  /**
   * @private
   * bind event
   * @param {String} events
   * @param {Function} handler
   * @returns {EventEmitter} this
   */


  _proto.on = function on(events, handler) {
    if (events === undefined || handler === undefined) {
      return this;
    }

    var handlers = this.handlers;
    each$5(splitStr(events), function (event) {
      handlers[event] = handlers[event] || [];
      handlers[event].push(handler);
    });
    return this;
  };
  /**
   * @private unbind event, leave emit blank to remove all handlers
   * @param {String} events
   * @param {Function} [handler]
   * @returns {EventEmitter} this
   */


  _proto.off = function off(events, handler) {
    if (events === undefined) {
      return this;
    }

    var handlers = this.handlers;
    each$5(splitStr(events), function (event) {
      if (!handler) {
        delete handlers[event];
      } else {
        handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
      }
    });
    return this;
  };
  /**
   * @private emit event to the listeners
   * @param {String} event
   * @param {Object} data
   */


  _proto.emit = function emit(event, data) {
    // we also want to trigger dom events
    if (this.options.domEvents) {
      triggerDomEvent(event, data);
    } // no handlers, so skip it all


    var handlers = this.handlers[event] && this.handlers[event].slice();

    if (!handlers || !handlers.length) {
      return;
    }

    data.type = event;

    data.preventDefault = function () {
      data.srcEvent.preventDefault();
    };

    var i = 0;

    while (i < handlers.length) {
      handlers[i](data);
      i++;
    }
  };
  /**
   * @private
   * destroy the manager and unbinds all events
   * it doesn't unbind dom events, that is the user own responsibility
   */


  _proto.destroy = function destroy() {
    this.element && toggleCssProps(this, false);
    this.handlers = {};
    this.session = {};
    this.input.destroy();
    this.element = null;
  };

  return Manager;
}();

var SINGLE_TOUCH_INPUT_MAP = {
  touchstart: INPUT_START,
  touchmove: INPUT_MOVE,
  touchend: INPUT_END,
  touchcancel: INPUT_CANCEL
};
var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
/**
 * @private
 * Touch events input
 * @constructor
 * @extends Input
 */

var SingleTouchInput =
/*#__PURE__*/
function (_Input) {
  _inheritsLoose(SingleTouchInput, _Input);

  function SingleTouchInput() {
    var _this;

    var proto = SingleTouchInput.prototype;
    proto.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
    proto.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
    _this = _Input.apply(this, arguments) || this;
    _this.started = false;
    return _this;
  }

  var _proto = SingleTouchInput.prototype;

  _proto.handler = function handler(ev) {
    var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; // should we handle the touch events?

    if (type === INPUT_START) {
      this.started = true;
    }

    if (!this.started) {
      return;
    }

    var touches = normalizeSingleTouches.call(this, ev, type); // when done, reset the started state

    if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
      this.started = false;
    }

    this.callback(this.manager, type, {
      pointers: touches[0],
      changedPointers: touches[1],
      pointerType: INPUT_TYPE_TOUCH,
      srcEvent: ev
    });
  };

  return SingleTouchInput;
}(Input);

function normalizeSingleTouches(ev, type) {
  var all = toArray(ev.touches);
  var changed = toArray(ev.changedTouches);

  if (type & (INPUT_END | INPUT_CANCEL)) {
    all = uniqueArray(all.concat(changed), 'identifier', true);
  }

  return [all, changed];
}

/**
 * @private
 * wrap a method with a deprecation warning and stack trace
 * @param {Function} method
 * @param {String} name
 * @param {String} message
 * @returns {Function} A new function wrapping the supplied method.
 */
function deprecate(method, name, message) {
  var deprecationMessage = "DEPRECATED METHOD: " + name + "\n" + message + " AT \n";
  return function () {
    var e = new Error('get-stack-trace');
    var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '').replace(/^\s+at\s+/gm, '').replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
    var log = window.console && (window.console.warn || window.console.log);

    if (log) {
      log.call(window.console, deprecationMessage, stack);
    }

    return method.apply(this, arguments);
  };
}

/**
 * @private
 * extend object.
 * means that properties in dest will be overwritten by the ones in src.
 * @param {Object} dest
 * @param {Object} src
 * @param {Boolean} [merge=false]
 * @returns {Object} dest
 */

var extend$1 = deprecate(function (dest, src, merge) {
  var keys = Object.keys(src);
  var i = 0;

  while (i < keys.length) {
    if (!merge || merge && dest[keys[i]] === undefined) {
      dest[keys[i]] = src[keys[i]];
    }

    i++;
  }

  return dest;
}, 'extend', 'Use `assign`.');

/**
 * @private
 * merge the values from src in the dest.
 * means that properties that exist in dest will not be overwritten by src
 * @param {Object} dest
 * @param {Object} src
 * @returns {Object} dest
 */

var merge$2 = deprecate(function (dest, src) {
  return extend$1(dest, src, true);
}, 'merge', 'Use `assign`.');

/**
 * @private
 * simple class inheritance
 * @param {Function} child
 * @param {Function} base
 * @param {Object} [properties]
 */

function inherit(child, base, properties) {
  var baseP = base.prototype;
  var childP;
  childP = child.prototype = Object.create(baseP);
  childP.constructor = child;
  childP._super = baseP;

  if (properties) {
    assign$1(childP, properties);
  }
}

/**
 * @private
 * simple function bind
 * @param {Function} fn
 * @param {Object} context
 * @returns {Function}
 */
function bindFn(fn, context) {
  return function boundFn() {
    return fn.apply(context, arguments);
  };
}

/**
 * @private
 * Simple way to create a manager with a default set of recognizers.
 * @param {HTMLElement} element
 * @param {Object} [options]
 * @constructor
 */

var Hammer$2 =
/*#__PURE__*/
function () {
  var Hammer =
  /**
    * @private
    * @const {string}
    */
  function Hammer(element, options) {
    if (options === void 0) {
      options = {};
    }

    return new Manager(element, _extends({
      recognizers: preset.concat()
    }, options));
  };

  Hammer.VERSION = "2.0.17-rc";
  Hammer.DIRECTION_ALL = DIRECTION_ALL;
  Hammer.DIRECTION_DOWN = DIRECTION_DOWN;
  Hammer.DIRECTION_LEFT = DIRECTION_LEFT;
  Hammer.DIRECTION_RIGHT = DIRECTION_RIGHT;
  Hammer.DIRECTION_UP = DIRECTION_UP;
  Hammer.DIRECTION_HORIZONTAL = DIRECTION_HORIZONTAL;
  Hammer.DIRECTION_VERTICAL = DIRECTION_VERTICAL;
  Hammer.DIRECTION_NONE = DIRECTION_NONE;
  Hammer.DIRECTION_DOWN = DIRECTION_DOWN;
  Hammer.INPUT_START = INPUT_START;
  Hammer.INPUT_MOVE = INPUT_MOVE;
  Hammer.INPUT_END = INPUT_END;
  Hammer.INPUT_CANCEL = INPUT_CANCEL;
  Hammer.STATE_POSSIBLE = STATE_POSSIBLE;
  Hammer.STATE_BEGAN = STATE_BEGAN;
  Hammer.STATE_CHANGED = STATE_CHANGED;
  Hammer.STATE_ENDED = STATE_ENDED;
  Hammer.STATE_RECOGNIZED = STATE_RECOGNIZED;
  Hammer.STATE_CANCELLED = STATE_CANCELLED;
  Hammer.STATE_FAILED = STATE_FAILED;
  Hammer.Manager = Manager;
  Hammer.Input = Input;
  Hammer.TouchAction = TouchAction;
  Hammer.TouchInput = TouchInput;
  Hammer.MouseInput = MouseInput;
  Hammer.PointerEventInput = PointerEventInput;
  Hammer.TouchMouseInput = TouchMouseInput;
  Hammer.SingleTouchInput = SingleTouchInput;
  Hammer.Recognizer = Recognizer;
  Hammer.AttrRecognizer = AttrRecognizer;
  Hammer.Tap = TapRecognizer;
  Hammer.Pan = PanRecognizer;
  Hammer.Swipe = SwipeRecognizer;
  Hammer.Pinch = PinchRecognizer;
  Hammer.Rotate = RotateRecognizer;
  Hammer.Press = PressRecognizer;
  Hammer.on = addEventListeners;
  Hammer.off = removeEventListeners;
  Hammer.each = each$5;
  Hammer.merge = merge$2;
  Hammer.extend = extend$1;
  Hammer.bindFn = bindFn;
  Hammer.assign = assign$1;
  Hammer.inherit = inherit;
  Hammer.bindFn = bindFn;
  Hammer.prefixed = prefixed;
  Hammer.toArray = toArray;
  Hammer.inArray = inArray;
  Hammer.uniqueArray = uniqueArray;
  Hammer.splitStr = splitStr;
  Hammer.boolOrFn = boolOrFn;
  Hammer.hasParent = hasParent;
  Hammer.addEventListeners = addEventListeners;
  Hammer.removeEventListeners = removeEventListeners;
  Hammer.defaults = assign$1({}, defaults$1, {
    preset: preset
  });
  return Hammer;
}();

//  style loader but by script tag, not by the loader.

Hammer$2.defaults;

var RealHammer = Hammer$2;

function _createForOfIteratorHelper$6(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray$6(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$6(o, minLen) { var _context21; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$6(o, minLen); var n = _sliceInstanceProperty(_context21 = Object.prototype.toString.call(o)).call(_context21, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$6(o, minLen); }
function _arrayLikeToArray$6(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

/**
 * Use this symbol to delete properies in deepObjectAssign.
 */
_Symbol("DELETE");

/**
 * Seedable, fast and reasonably good (not crypto but more than okay for our
 * needs) random number generator.
 *
 * @remarks
 * Adapted from {@link https://web.archive.org/web/20110429100736/http://baagoe.com:80/en/RandomMusings/javascript}.
 * Original algorithm created by Johannes Baagøe \<baagoe\@baagoe.com\> in 2010.
 */
/**
 * Create a seeded pseudo random generator based on Alea by Johannes Baagøe.
 *
 * @param seed - All supplied arguments will be used as a seed. In case nothing
 * is supplied the current time will be used to seed the generator.
 * @returns A ready to use seeded generator.
 */
function Alea() {
  for (var _len3 = arguments.length, seed = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
    seed[_key3] = arguments[_key3];
  }
  return AleaImplementation(seed.length ? seed : [_Date$now()]);
}
/**
 * An implementation of [[Alea]] without user input validation.
 *
 * @param seed - The data that will be used to seed the generator.
 * @returns A ready to use seeded generator.
 */
function AleaImplementation(seed) {
  var _mashSeed = mashSeed(seed),
    _mashSeed2 = _slicedToArray(_mashSeed, 3),
    s0 = _mashSeed2[0],
    s1 = _mashSeed2[1],
    s2 = _mashSeed2[2];
  var c = 1;
  var random = function random() {
    var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
    s0 = s1;
    s1 = s2;
    return s2 = t - (c = t | 0);
  };
  random.uint32 = function () {
    return random() * 0x100000000;
  }; // 2^32
  random.fract53 = function () {
    return random() + (random() * 0x200000 | 0) * 1.1102230246251565e-16;
  }; // 2^-53
  random.algorithm = "Alea";
  random.seed = seed;
  random.version = "0.9";
  return random;
}
/**
 * Turn arbitrary data into values [[AleaImplementation]] can use to generate
 * random numbers.
 *
 * @param seed - Arbitrary data that will be used as the seed.
 * @returns Three numbers to use as initial values for [[AleaImplementation]].
 */
function mashSeed() {
  var mash = Mash();
  var s0 = mash(" ");
  var s1 = mash(" ");
  var s2 = mash(" ");
  for (var i = 0; i < arguments.length; i++) {
    s0 -= mash(i < 0 || arguments.length <= i ? undefined : arguments[i]);
    if (s0 < 0) {
      s0 += 1;
    }
    s1 -= mash(i < 0 || arguments.length <= i ? undefined : arguments[i]);
    if (s1 < 0) {
      s1 += 1;
    }
    s2 -= mash(i < 0 || arguments.length <= i ? undefined : arguments[i]);
    if (s2 < 0) {
      s2 += 1;
    }
  }
  return [s0, s1, s2];
}
/**
 * Create a new mash function.
 *
 * @returns A nonpure function that takes arbitrary [[Mashable]] data and turns
 * them into numbers.
 */
function Mash() {
  var n = 0xefc8249d;
  return function (data) {
    var string = data.toString();
    for (var i = 0; i < string.length; i++) {
      n += string.charCodeAt(i);
      var h = 0.02519603282416938 * n;
      n = h >>> 0;
      h -= n;
      h *= n;
      n = h >>> 0;
      h -= n;
      n += h * 0x100000000; // 2^32
    }

    return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
  };
}

/**
 * Setup a mock hammer.js object, for unit testing.
 *
 * Inspiration: https://github.com/uber/deck.gl/pull/658
 *
 * @returns {{on: noop, off: noop, destroy: noop, emit: noop, get: get}}
 */
function hammerMock() {
  var noop = function noop() {};
  return {
    on: noop,
    off: noop,
    destroy: noop,
    emit: noop,
    get: function get() {
      return {
        set: noop
      };
    }
  };
}
var Hammer$1 = typeof window !== "undefined" ? window.Hammer || RealHammer : function () {
  // hammer.js is only available in a browser, not in node.js. Replacing it with a mock object.
  return hammerMock();
};

/**
 * Turn an element into an clickToUse element.
 * When not active, the element has a transparent overlay. When the overlay is
 * clicked, the mode is changed to active.
 * When active, the element is displayed with a blue border around it, and
 * the interactive contents of the element can be used. When clicked outside
 * the element, the elements mode is changed to inactive.
 *
 * @param {Element} container
 * @class Activator
 */
function Activator$1(container) {
  var _this = this,
    _context3;
  this._cleanupQueue = [];
  this.active = false;
  this._dom = {
    container: container,
    overlay: document.createElement("div")
  };
  this._dom.overlay.classList.add("vis-overlay");
  this._dom.container.appendChild(this._dom.overlay);
  this._cleanupQueue.push(function () {
    _this._dom.overlay.parentNode.removeChild(_this._dom.overlay);
  });
  var hammer = Hammer$1(this._dom.overlay);
  hammer.on("tap", _bindInstanceProperty$1(_context3 = this._onTapOverlay).call(_context3, this));
  this._cleanupQueue.push(function () {
    hammer.destroy();
    // FIXME: cleaning up hammer instances doesn't work (Timeline not removed
    // from memory)
  });

  // block all touch events (except tap)
  var events = ["tap", "doubletap", "press", "pinch", "pan", "panstart", "panmove", "panend"];
  _forEachInstanceProperty(events).call(events, function (event) {
    hammer.on(event, function (event) {
      event.srcEvent.stopPropagation();
    });
  });

  // attach a click event to the window, in order to deactivate when clicking outside the timeline
  if (document && document.body) {
    this._onClick = function (event) {
      if (!_hasParent(event.target, container)) {
        _this.deactivate();
      }
    };
    document.body.addEventListener("click", this._onClick);
    this._cleanupQueue.push(function () {
      document.body.removeEventListener("click", _this._onClick);
    });
  }

  // prepare escape key listener for deactivating when active
  this._escListener = function (event) {
    if ("key" in event ? event.key === "Escape" : event.keyCode === 27 /* the keyCode is for IE11 */) {
      _this.deactivate();
    }
  };
}

// turn into an event emitter
Emitter(Activator$1.prototype);

// The currently active activator
Activator$1.current = null;

/**
 * Destroy the activator. Cleans up all created DOM and event listeners
 */
Activator$1.prototype.destroy = function () {
  var _context4, _context5;
  this.deactivate();
  var _iterator2 = _createForOfIteratorHelper$6(_reverseInstanceProperty(_context4 = _spliceInstanceProperty(_context5 = this._cleanupQueue).call(_context5, 0)).call(_context4)),
    _step2;
  try {
    for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
      var callback = _step2.value;
      callback();
    }
  } catch (err) {
    _iterator2.e(err);
  } finally {
    _iterator2.f();
  }
};

/**
 * Activate the element
 * Overlay is hidden, element is decorated with a blue shadow border
 */
Activator$1.prototype.activate = function () {
  // we allow only one active activator at a time
  if (Activator$1.current) {
    Activator$1.current.deactivate();
  }
  Activator$1.current = this;
  this.active = true;
  this._dom.overlay.style.display = "none";
  this._dom.container.classList.add("vis-active");
  this.emit("change");
  this.emit("activate");

  // ugly hack: bind ESC after emitting the events, as the Network rebinds all
  // keyboard events on a 'change' event
  document.body.addEventListener("keydown", this._escListener);
};

/**
 * Deactivate the element
 * Overlay is displayed on top of the element
 */
Activator$1.prototype.deactivate = function () {
  this.active = false;
  this._dom.overlay.style.display = "block";
  this._dom.container.classList.remove("vis-active");
  document.body.removeEventListener("keydown", this._escListener);
  this.emit("change");
  this.emit("deactivate");
};

/**
 * Handle a tap event: activate the container
 *
 * @param {Event}  event   The event
 * @private
 */
Activator$1.prototype._onTapOverlay = function (event) {
  // activate the container
  this.activate();
  event.srcEvent.stopPropagation();
};

/**
 * Test whether the element has the requested parent element somewhere in
 * its chain of parent nodes.
 *
 * @param {HTMLElement} element
 * @param {HTMLElement} parent
 * @returns {boolean} Returns true when the parent is found somewhere in the
 *                    chain of parent nodes.
 * @private
 */
function _hasParent(element, parent) {
  while (element) {
    if (element === parent) {
      return true;
    }
    element = element.parentNode;
  }
  return false;
}
// Color REs
var fullHexRE = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
var shortHexRE = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
var rgbRE = /^rgb\( *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *\)$/i;
var rgbaRE = /^rgba\( *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *(1?\d{1,2}|2[0-4]\d|25[0-5]) *, *([01]|0?\.\d+) *\)$/i;
/**
 * Remove everything in the DOM object.
 *
 * @param DOMobject - Node whose child nodes will be recursively deleted.
 */
function recursiveDOMDelete(DOMobject) {
  if (DOMobject) {
    while (DOMobject.hasChildNodes() === true) {
      var child = DOMobject.firstChild;
      if (child) {
        recursiveDOMDelete(child);
        DOMobject.removeChild(child);
      }
    }
  }
}
/**
 * Test whether given object is a string.
 *
 * @param value - Input value of unknown type.
 * @returns True if string, false otherwise.
 */
function isString$1(value) {
  return value instanceof String || typeof value === "string";
}
/**
 * Test whether given object is a object (not primitive or null).
 *
 * @param value - Input value of unknown type.
 * @returns True if not null object, false otherwise.
 */
function isObject$7(value) {
  return _typeof(value) === "object" && value !== null;
}
/**
 * Copy property from b to a if property present in a.
 * If property in b explicitly set to null, delete it if `allowDeletion` set.
 *
 * Internal helper routine, should not be exported. Not added to `exports` for that reason.
 *
 * @param a - Target object.
 * @param b - Source object.
 * @param prop - Name of property to copy from b to a.
 * @param allowDeletion - If true, delete property in a if explicitly set to null in b.
 */
function copyOrDelete(a, b, prop, allowDeletion) {
  var doDeletion = false;
  if (allowDeletion === true) {
    doDeletion = b[prop] === null && a[prop] !== undefined;
  }
  if (doDeletion) {
    delete a[prop];
  } else {
    a[prop] = b[prop]; // Remember, this is a reference copy!
  }
}
/**
 * Fill an object with a possibly partially defined other object.
 *
 * Only copies values for the properties already present in a.
 * That means an object is not created on a property if only the b object has it.
 *
 * @param a - The object that will have it's properties updated.
 * @param b - The object with property updates.
 * @param allowDeletion - If true, delete properties in a that are explicitly set to null in b.
 */
function fillIfDefined(a, b) {
  var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  // NOTE: iteration of properties of a
  // NOTE: prototype properties iterated over as well
  for (var prop in a) {
    if (b[prop] !== undefined) {
      if (b[prop] === null || _typeof(b[prop]) !== "object") {
        // Note: typeof null === 'object'
        copyOrDelete(a, b, prop, allowDeletion);
      } else {
        var aProp = a[prop];
        var bProp = b[prop];
        if (isObject$7(aProp) && isObject$7(bProp)) {
          fillIfDefined(aProp, bProp, allowDeletion);
        }
      }
    }
  }
}
/**
 * Extend object a with selected properties of object b.
 * Only properties with defined values are copied.
 *
 * @remarks
 * Previous version of this routine implied that multiple source objects could
 * be used; however, the implementation was **wrong**. Since multiple (\>1)
 * sources weren't used anywhere in the `vis.js` code, this has been removed
 * @param props - Names of first-level properties to copy over.
 * @param a - Target object.
 * @param b - Source object.
 * @param allowDeletion - If true, delete property in a if explicitly set to null in b.
 * @returns Argument a.
 */
function selectiveDeepExtend(props, a, b) {
  var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
  // TODO: add support for Arrays to deepExtend
  if (_Array$isArray(b)) {
    throw new TypeError("Arrays are not supported by deepExtend");
  }
  for (var p = 0; p < props.length; p++) {
    var prop = props[p];
    if (Object.prototype.hasOwnProperty.call(b, prop)) {
      if (b[prop] && b[prop].constructor === Object) {
        if (a[prop] === undefined) {
          a[prop] = {};
        }
        if (a[prop].constructor === Object) {
          deepExtend(a[prop], b[prop], false, allowDeletion);
        } else {
          copyOrDelete(a, b, prop, allowDeletion);
        }
      } else if (_Array$isArray(b[prop])) {
        throw new TypeError("Arrays are not supported by deepExtend");
      } else {
        copyOrDelete(a, b, prop, allowDeletion);
      }
    }
  }
  return a;
}
/**
 * Extend object `a` with properties of object `b`, ignoring properties which
 * are explicitly specified to be excluded.
 *
 * @remarks
 * The properties of `b` are considered for copying. Properties which are
 * themselves objects are are also extended. Only properties with defined
 * values are copied.
 * @param propsToExclude - Names of properties which should *not* be copied.
 * @param a - Object to extend.
 * @param b - Object to take properties from for extension.
 * @param allowDeletion - If true, delete properties in a that are explicitly
 * set to null in b.
 * @returns Argument a.
 */
function selectiveNotDeepExtend(propsToExclude, a, b) {
  var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
  // TODO: add support for Arrays to deepExtend
  // NOTE: array properties have an else-below; apparently, there is a problem here.
  if (_Array$isArray(b)) {
    throw new TypeError("Arrays are not supported by deepExtend");
  }
  for (var prop in b) {
    if (!Object.prototype.hasOwnProperty.call(b, prop)) {
      continue;
    } // Handle local properties only
    if (_includesInstanceProperty(propsToExclude).call(propsToExclude, prop)) {
      continue;
    } // In exclusion list, skip
    if (b[prop] && b[prop].constructor === Object) {
      if (a[prop] === undefined) {
        a[prop] = {};
      }
      if (a[prop].constructor === Object) {
        deepExtend(a[prop], b[prop]); // NOTE: allowDeletion not propagated!
      } else {
        copyOrDelete(a, b, prop, allowDeletion);
      }
    } else if (_Array$isArray(b[prop])) {
      a[prop] = [];
      for (var i = 0; i < b[prop].length; i++) {
        a[prop].push(b[prop][i]);
      }
    } else {
      copyOrDelete(a, b, prop, allowDeletion);
    }
  }
  return a;
}
/**
 * Deep extend an object a with the properties of object b.
 *
 * @param a - Target object.
 * @param b - Source object.
 * @param protoExtend - If true, the prototype values will also be extended.
 * (That is the options objects that inherit from others will also get the
 * inherited options).
 * @param allowDeletion - If true, the values of fields that are null will be deleted.
 * @returns Argument a.
 */
function deepExtend(a, b) {
  var protoExtend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
  for (var prop in b) {
    if (Object.prototype.hasOwnProperty.call(b, prop) || protoExtend === true) {
      if (_typeof(b[prop]) === "object" && b[prop] !== null && _Object$getPrototypeOf$1(b[prop]) === Object.prototype) {
        if (a[prop] === undefined) {
          a[prop] = deepExtend({}, b[prop], protoExtend); // NOTE: allowDeletion not propagated!
        } else if (_typeof(a[prop]) === "object" && a[prop] !== null && _Object$getPrototypeOf$1(a[prop]) === Object.prototype) {
          deepExtend(a[prop], b[prop], protoExtend); // NOTE: allowDeletion not propagated!
        } else {
          copyOrDelete(a, b, prop, allowDeletion);
        }
      } else if (_Array$isArray(b[prop])) {
        var _context6;
        a[prop] = _sliceInstanceProperty(_context6 = b[prop]).call(_context6);
      } else {
        copyOrDelete(a, b, prop, allowDeletion);
      }
    }
  }
  return a;
}
/**
 * Used to extend an array and copy it. This is used to propagate paths recursively.
 *
 * @param arr - First part.
 * @param newValue - The value to be aadded into the array.
 * @returns A new array with all items from arr and newValue (which is last).
 */
function copyAndExtendArray(arr, newValue) {
  var _context7;
  return _concatInstanceProperty(_context7 = []).call(_context7, _toConsumableArray(arr), [newValue]);
}
/**
 * Used to extend an array and copy it. This is used to propagate paths recursively.
 *
 * @param arr - The array to be copied.
 * @returns Shallow copy of arr.
 */
function copyArray(arr) {
  return _sliceInstanceProperty(arr).call(arr);
}
/**
 * Retrieve the absolute left value of a DOM element.
 *
 * @param elem - A dom element, for example a div.
 * @returns The absolute left position of this element in the browser page.
 */
function getAbsoluteLeft(elem) {
  return elem.getBoundingClientRect().left;
}
/**
 * Retrieve the absolute top value of a DOM element.
 *
 * @param elem - A dom element, for example a div.
 * @returns The absolute top position of this element in the browser page.
 */
function getAbsoluteTop(elem) {
  return elem.getBoundingClientRect().top;
}
/**
 * For each method for both arrays and objects.
 * In case of an array, the built-in Array.forEach() is applied (**No, it's not!**).
 * In case of an Object, the method loops over all properties of the object.
 *
 * @param object - An Object or Array to be iterated over.
 * @param callback - Array.forEach-like callback.
 */
function forEach$1(object, callback) {
  if (_Array$isArray(object)) {
    // array
    var len = object.length;
    for (var i = 0; i < len; i++) {
      callback(object[i], i, object);
    }
  } else {
    // object
    for (var key in object) {
      if (Object.prototype.hasOwnProperty.call(object, key)) {
        callback(object[key], key, object);
      }
    }
  }
}
/**
 * Add and event listener. Works for all browsers.
 *
 * @param element - The element to bind the event listener to.
 * @param action - Same as Element.addEventListener(action, —, —).
 * @param listener - Same as Element.addEventListener(—, listener, —).
 * @param useCapture - Same as Element.addEventListener(—, —, useCapture).
 */
function addEventListener$1(element, action, listener, useCapture) {
  if (element.addEventListener) {
    var _context8;
    if (useCapture === undefined) {
      useCapture = false;
    }
    if (action === "mousewheel" && _includesInstanceProperty(_context8 = navigator.userAgent).call(_context8, "Firefox")) {
      action = "DOMMouseScroll"; // For Firefox
    }

    element.addEventListener(action, listener, useCapture);
  } else {
    // @TODO: IE types? Does anyone care?
    element.attachEvent("on" + action, listener); // IE browsers
  }
}
/**
 * Remove an event listener from an element.
 *
 * @param element - The element to bind the event listener to.
 * @param action - Same as Element.removeEventListener(action, —, —).
 * @param listener - Same as Element.removeEventListener(—, listener, —).
 * @param useCapture - Same as Element.removeEventListener(—, —, useCapture).
 */
function removeEventListener$1(element, action, listener, useCapture) {
  if (element.removeEventListener) {
    var _context9;
    // non-IE browsers
    if (useCapture === undefined) {
      useCapture = false;
    }
    if (action === "mousewheel" && _includesInstanceProperty(_context9 = navigator.userAgent).call(_context9, "Firefox")) {
      action = "DOMMouseScroll"; // For Firefox
    }

    element.removeEventListener(action, listener, useCapture);
  } else {
    // @TODO: IE types? Does anyone care?
    element.detachEvent("on" + action, listener); // IE browsers
  }
}
/**
 * Convert hex color string into RGB color object.
 *
 * @remarks
 * {@link http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb}
 * @param hex - Hex color string (3 or 6 digits, with or without #).
 * @returns RGB color object.
 */
function hexToRGB(hex) {
  var result;
  switch (hex.length) {
    case 3:
    case 4:
      result = shortHexRE.exec(hex);
      return result ? {
        r: _parseInt(result[1] + result[1], 16),
        g: _parseInt(result[2] + result[2], 16),
        b: _parseInt(result[3] + result[3], 16)
      } : null;
    case 6:
    case 7:
      result = fullHexRE.exec(hex);
      return result ? {
        r: _parseInt(result[1], 16),
        g: _parseInt(result[2], 16),
        b: _parseInt(result[3], 16)
      } : null;
    default:
      return null;
  }
}
/**
 * This function takes string color in hex or RGB format and adds the opacity, RGBA is passed through unchanged.
 *
 * @param color - The color string (hex, RGB, RGBA).
 * @param opacity - The new opacity.
 * @returns RGBA string, for example 'rgba(255, 0, 127, 0.3)'.
 */
function overrideOpacity(color, opacity) {
  if (_includesInstanceProperty(color).call(color, "rgba")) {
    return color;
  } else if (_includesInstanceProperty(color).call(color, "rgb")) {
    var rgb = color.substr(_indexOfInstanceProperty(color).call(color, "(") + 1).replace(")", "").split(",");
    return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opacity + ")";
  } else {
    var _rgb = hexToRGB(color);
    if (_rgb == null) {
      return color;
    } else {
      return "rgba(" + _rgb.r + "," + _rgb.g + "," + _rgb.b + "," + opacity + ")";
    }
  }
}
/**
 * Convert RGB \<0, 255\> into hex color string.
 *
 * @param red - Red channel.
 * @param green - Green channel.
 * @param blue - Blue channel.
 * @returns Hex color string (for example: '#0acdc0').
 */
function RGBToHex(red, green, blue) {
  var _context10;
  return "#" + _sliceInstanceProperty(_context10 = ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16)).call(_context10, 1);
}
/**
 * Parse a color property into an object with border, background, and highlight colors.
 *
 * @param inputColor - Shorthand color string or input color object.
 * @param defaultColor - Full color object to fill in missing values in inputColor.
 * @returns Color object.
 */
function parseColor(inputColor, defaultColor) {
  if (isString$1(inputColor)) {
    var colorStr = inputColor;
    if (isValidRGB(colorStr)) {
      var _context11;
      var rgb = _mapInstanceProperty(_context11 = colorStr.substr(4).substr(0, colorStr.length - 5).split(",")).call(_context11, function (value) {
        return _parseInt(value);
      });
      colorStr = RGBToHex(rgb[0], rgb[1], rgb[2]);
    }
    if (isValidHex(colorStr) === true) {
      var hsv = hexToHSV(colorStr);
      var lighterColorHSV = {
        h: hsv.h,
        s: hsv.s * 0.8,
        v: Math.min(1, hsv.v * 1.02)
      };
      var darkerColorHSV = {
        h: hsv.h,
        s: Math.min(1, hsv.s * 1.25),
        v: hsv.v * 0.8
      };
      var darkerColorHex = HSVToHex(darkerColorHSV.h, darkerColorHSV.s, darkerColorHSV.v);
      var lighterColorHex = HSVToHex(lighterColorHSV.h, lighterColorHSV.s, lighterColorHSV.v);
      return {
        background: colorStr,
        border: darkerColorHex,
        highlight: {
          background: lighterColorHex,
          border: darkerColorHex
        },
        hover: {
          background: lighterColorHex,
          border: darkerColorHex
        }
      };
    } else {
      return {
        background: colorStr,
        border: colorStr,
        highlight: {
          background: colorStr,
          border: colorStr
        },
        hover: {
          background: colorStr,
          border: colorStr
        }
      };
    }
  } else {
    if (defaultColor) {
      var color = {
        background: inputColor.background || defaultColor.background,
        border: inputColor.border || defaultColor.border,
        highlight: isString$1(inputColor.highlight) ? {
          border: inputColor.highlight,
          background: inputColor.highlight
        } : {
          background: inputColor.highlight && inputColor.highlight.background || defaultColor.highlight.background,
          border: inputColor.highlight && inputColor.highlight.border || defaultColor.highlight.border
        },
        hover: isString$1(inputColor.hover) ? {
          border: inputColor.hover,
          background: inputColor.hover
        } : {
          border: inputColor.hover && inputColor.hover.border || defaultColor.hover.border,
          background: inputColor.hover && inputColor.hover.background || defaultColor.hover.background
        }
      };
      return color;
    } else {
      var _color = {
        background: inputColor.background || undefined,
        border: inputColor.border || undefined,
        highlight: isString$1(inputColor.highlight) ? {
          border: inputColor.highlight,
          background: inputColor.highlight
        } : {
          background: inputColor.highlight && inputColor.highlight.background || undefined,
          border: inputColor.highlight && inputColor.highlight.border || undefined
        },
        hover: isString$1(inputColor.hover) ? {
          border: inputColor.hover,
          background: inputColor.hover
        } : {
          border: inputColor.hover && inputColor.hover.border || undefined,
          background: inputColor.hover && inputColor.hover.background || undefined
        }
      };
      return _color;
    }
  }
}
/**
 * Convert RGB \<0, 255\> into HSV object.
 *
 * @remarks
 * {@link http://www.javascripter.net/faq/rgb2hsv.htm}
 * @param red - Red channel.
 * @param green - Green channel.
 * @param blue - Blue channel.
 * @returns HSV color object.
 */
function RGBToHSV(red, green, blue) {
  red = red / 255;
  green = green / 255;
  blue = blue / 255;
  var minRGB = Math.min(red, Math.min(green, blue));
  var maxRGB = Math.max(red, Math.max(green, blue));
  // Black-gray-white
  if (minRGB === maxRGB) {
    return {
      h: 0,
      s: 0,
      v: minRGB
    };
  }
  // Colors other than black-gray-white:
  var d = red === minRGB ? green - blue : blue === minRGB ? red - green : blue - red;
  var h = red === minRGB ? 3 : blue === minRGB ? 1 : 5;
  var hue = 60 * (h - d / (maxRGB - minRGB)) / 360;
  var saturation = (maxRGB - minRGB) / maxRGB;
  var value = maxRGB;
  return {
    h: hue,
    s: saturation,
    v: value
  };
}
/**
 * Convert HSV \<0, 1\> into RGB color object.
 *
 * @remarks
 * {@link https://gist.github.com/mjijackson/5311256}
 * @param h - Hue.
 * @param s - Saturation.
 * @param v - Value.
 * @returns RGB color object.
 */
function HSVToRGB(h, s, v) {
  var r;
  var g;
  var b;
  var i = Math.floor(h * 6);
  var f = h * 6 - i;
  var p = v * (1 - s);
  var q = v * (1 - f * s);
  var t = v * (1 - (1 - f) * s);
  switch (i % 6) {
    case 0:
      r = v, g = t, b = p;
      break;
    case 1:
      r = q, g = v, b = p;
      break;
    case 2:
      r = p, g = v, b = t;
      break;
    case 3:
      r = p, g = q, b = v;
      break;
    case 4:
      r = t, g = p, b = v;
      break;
    case 5:
      r = v, g = p, b = q;
      break;
  }
  return {
    r: Math.floor(r * 255),
    g: Math.floor(g * 255),
    b: Math.floor(b * 255)
  };
}
/**
 * Convert HSV \<0, 1\> into hex color string.
 *
 * @param h - Hue.
 * @param s - Saturation.
 * @param v - Value.
 * @returns Hex color string.
 */
function HSVToHex(h, s, v) {
  var rgb = HSVToRGB(h, s, v);
  return RGBToHex(rgb.r, rgb.g, rgb.b);
}
/**
 * Convert hex color string into HSV \<0, 1\>.
 *
 * @param hex - Hex color string.
 * @returns HSV color object.
 */
function hexToHSV(hex) {
  var rgb = hexToRGB(hex);
  if (!rgb) {
    throw new TypeError("'".concat(hex, "' is not a valid color."));
  }
  return RGBToHSV(rgb.r, rgb.g, rgb.b);
}
/**
 * Validate hex color string.
 *
 * @param hex - Unknown string that may contain a color.
 * @returns True if the string is valid, false otherwise.
 */
function isValidHex(hex) {
  var isOk = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex);
  return isOk;
}
/**
 * Validate RGB color string.
 *
 * @param rgb - Unknown string that may contain a color.
 * @returns True if the string is valid, false otherwise.
 */
function isValidRGB(rgb) {
  return rgbRE.test(rgb);
}
/**
 * Validate RGBA color string.
 *
 * @param rgba - Unknown string that may contain a color.
 * @returns True if the string is valid, false otherwise.
 */
function isValidRGBA(rgba) {
  return rgbaRE.test(rgba);
}
/**
 * This recursively redirects the prototype of JSON objects to the referenceObject.
 * This is used for default options.
 *
 * @param referenceObject - The original object.
 * @returns The Element if the referenceObject is an Element, or a new object inheriting from the referenceObject.
 */
function bridgeObject(referenceObject) {
  if (referenceObject === null || _typeof(referenceObject) !== "object") {
    return null;
  }
  if (referenceObject instanceof Element) {
    // Avoid bridging DOM objects
    return referenceObject;
  }
  var objectTo = _Object$create$1(referenceObject);
  for (var i in referenceObject) {
    if (Object.prototype.hasOwnProperty.call(referenceObject, i)) {
      if (_typeof(referenceObject[i]) == "object") {
        objectTo[i] = bridgeObject(referenceObject[i]);
      }
    }
  }
  return objectTo;
}
/**
 * This is used to set the options of subobjects in the options object.
 *
 * A requirement of these subobjects is that they have an 'enabled' element
 * which is optional for the user but mandatory for the program.
 *
 * The added value here of the merge is that option 'enabled' is set as required.
 *
 * @param mergeTarget - Either this.options or the options used for the groups.
 * @param options - Options.
 * @param option - Option key in the options argument.
 * @param globalOptions - Global options, passed in to determine value of option 'enabled'.
 */
function mergeOptions(mergeTarget, options, option) {
  var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  // Local helpers
  var isPresent = function isPresent(obj) {
    return obj !== null && obj !== undefined;
  };
  var isObject = function isObject(obj) {
    return obj !== null && _typeof(obj) === "object";
  };
  // https://stackoverflow.com/a/34491287/1223531
  var isEmpty = function isEmpty(obj) {
    for (var x in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, x)) {
        return false;
      }
    }
    return true;
  };
  // Guards
  if (!isObject(mergeTarget)) {
    throw new Error("Parameter mergeTarget must be an object");
  }
  if (!isObject(options)) {
    throw new Error("Parameter options must be an object");
  }
  if (!isPresent(option)) {
    throw new Error("Parameter option must have a value");
  }
  if (!isObject(globalOptions)) {
    throw new Error("Parameter globalOptions must be an object");
  }
  //
  // Actual merge routine, separated from main logic
  // Only a single level of options is merged. Deeper levels are ref'd. This may actually be an issue.
  //
  var doMerge = function doMerge(target, options, option) {
    if (!isObject(target[option])) {
      target[option] = {};
    }
    var src = options[option];
    var dst = target[option];
    for (var prop in src) {
      if (Object.prototype.hasOwnProperty.call(src, prop)) {
        dst[prop] = src[prop];
      }
    }
  };
  // Local initialization
  var srcOption = options[option];
  var globalPassed = isObject(globalOptions) && !isEmpty(globalOptions);
  var globalOption = globalPassed ? globalOptions[option] : undefined;
  var globalEnabled = globalOption ? globalOption.enabled : undefined;
  /////////////////////////////////////////
  // Main routine
  /////////////////////////////////////////
  if (srcOption === undefined) {
    return; // Nothing to do
  }

  if (typeof srcOption === "boolean") {
    if (!isObject(mergeTarget[option])) {
      mergeTarget[option] = {};
    }
    mergeTarget[option].enabled = srcOption;
    return;
  }
  if (srcOption === null && !isObject(mergeTarget[option])) {
    // If possible, explicit copy from globals
    if (isPresent(globalOption)) {
      mergeTarget[option] = _Object$create$1(globalOption);
    } else {
      return; // Nothing to do
    }
  }

  if (!isObject(srcOption)) {
    return;
  }
  //
  // Ensure that 'enabled' is properly set. It is required internally
  // Note that the value from options will always overwrite the existing value
  //
  var enabled = true; // default value
  if (srcOption.enabled !== undefined) {
    enabled = srcOption.enabled;
  } else {
    // Take from globals, if present
    if (globalEnabled !== undefined) {
      enabled = globalOption.enabled;
    }
  }
  doMerge(mergeTarget, options, option);
  mergeTarget[option].enabled = enabled;
}
/*
 * Easing Functions.
 * Only considering the t value for the range [0, 1] => [0, 1].
 *
 * Inspiration: from http://gizma.com/easing/
 * https://gist.github.com/gre/1650294
 */
var easingFunctions = {
  /**
   * Provides no easing and no acceleration.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  linear: function linear(t) {
    return t;
  },
  /**
   * Accelerate from zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInQuad: function easeInQuad(t) {
    return t * t;
  },
  /**
   * Decelerate to zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeOutQuad: function easeOutQuad(t) {
    return t * (2 - t);
  },
  /**
   * Accelerate until halfway, then decelerate.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInOutQuad: function easeInOutQuad(t) {
    return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
  },
  /**
   * Accelerate from zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInCubic: function easeInCubic(t) {
    return t * t * t;
  },
  /**
   * Decelerate to zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeOutCubic: function easeOutCubic(t) {
    return --t * t * t + 1;
  },
  /**
   * Accelerate until halfway, then decelerate.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInOutCubic: function easeInOutCubic(t) {
    return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
  },
  /**
   * Accelerate from zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInQuart: function easeInQuart(t) {
    return t * t * t * t;
  },
  /**
   * Decelerate to zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeOutQuart: function easeOutQuart(t) {
    return 1 - --t * t * t * t;
  },
  /**
   * Accelerate until halfway, then decelerate.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInOutQuart: function easeInOutQuart(t) {
    return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
  },
  /**
   * Accelerate from zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInQuint: function easeInQuint(t) {
    return t * t * t * t * t;
  },
  /**
   * Decelerate to zero velocity.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeOutQuint: function easeOutQuint(t) {
    return 1 + --t * t * t * t * t;
  },
  /**
   * Accelerate until halfway, then decelerate.
   *
   * @param t - Time.
   * @returns Value at time t.
   */
  easeInOutQuint: function easeInOutQuint(t) {
    return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
  }
};
// @TODO: This doesn't work properly.
// It works only for single property objects,
// otherwise it combines all of the types in a union.
// export function topMost<K1 extends string, V1> (
//   pile: Record<K1, undefined | V1>[],
//   accessors: K1 | [K1]
// ): undefined | V1
// export function topMost<K1 extends string, K2 extends string, V1, V2> (
//   pile: Record<K1, undefined | V1 | Record<K2, undefined | V2>>[],
//   accessors: [K1, K2]
// ): undefined | V1 | V2
// export function topMost<K1 extends string, K2 extends string, K3 extends string, V1, V2, V3> (
//   pile: Record<K1, undefined | V1 | Record<K2, undefined | V2 | Record<K3, undefined | V3>>>[],
//   accessors: [K1, K2, K3]
// ): undefined | V1 | V2 | V3
/**
 * Get the top most property value from a pile of objects.
 *
 * @param pile - Array of objects, no required format.
 * @param accessors - Array of property names.
 * For example `object['foo']['bar']` → `['foo', 'bar']`.
 * @returns Value of the property with given accessors path from the first pile item where it's not undefined.
 */
function topMost(pile, accessors) {
  var candidate;
  if (!_Array$isArray(accessors)) {
    accessors = [accessors];
  }
  var _iterator3 = _createForOfIteratorHelper$6(pile),
    _step3;
  try {
    for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
      var member = _step3.value;
      if (member) {
        candidate = member[accessors[0]];
        for (var i = 1; i < accessors.length; i++) {
          if (candidate) {
            candidate = candidate[accessors[i]];
          }
        }
        if (typeof candidate !== "undefined") {
          break;
        }
      }
    }
  } catch (err) {
    _iterator3.e(err);
  } finally {
    _iterator3.f();
  }
  return candidate;
}
var htmlColors = {
  black: "#000000",
  navy: "#000080",
  darkblue: "#00008B",
  mediumblue: "#0000CD",
  blue: "#0000FF",
  darkgreen: "#006400",
  green: "#008000",
  teal: "#008080",
  darkcyan: "#008B8B",
  deepskyblue: "#00BFFF",
  darkturquoise: "#00CED1",
  mediumspringgreen: "#00FA9A",
  lime: "#00FF00",
  springgreen: "#00FF7F",
  aqua: "#00FFFF",
  cyan: "#00FFFF",
  midnightblue: "#191970",
  dodgerblue: "#1E90FF",
  lightseagreen: "#20B2AA",
  forestgreen: "#228B22",
  seagreen: "#2E8B57",
  darkslategray: "#2F4F4F",
  limegreen: "#32CD32",
  mediumseagreen: "#3CB371",
  turquoise: "#40E0D0",
  royalblue: "#4169E1",
  steelblue: "#4682B4",
  darkslateblue: "#483D8B",
  mediumturquoise: "#48D1CC",
  indigo: "#4B0082",
  darkolivegreen: "#556B2F",
  cadetblue: "#5F9EA0",
  cornflowerblue: "#6495ED",
  mediumaquamarine: "#66CDAA",
  dimgray: "#696969",
  slateblue: "#6A5ACD",
  olivedrab: "#6B8E23",
  slategray: "#708090",
  lightslategray: "#778899",
  mediumslateblue: "#7B68EE",
  lawngreen: "#7CFC00",
  chartreuse: "#7FFF00",
  aquamarine: "#7FFFD4",
  maroon: "#800000",
  purple: "#800080",
  olive: "#808000",
  gray: "#808080",
  skyblue: "#87CEEB",
  lightskyblue: "#87CEFA",
  blueviolet: "#8A2BE2",
  darkred: "#8B0000",
  darkmagenta: "#8B008B",
  saddlebrown: "#8B4513",
  darkseagreen: "#8FBC8F",
  lightgreen: "#90EE90",
  mediumpurple: "#9370D8",
  darkviolet: "#9400D3",
  palegreen: "#98FB98",
  darkorchid: "#9932CC",
  yellowgreen: "#9ACD32",
  sienna: "#A0522D",
  brown: "#A52A2A",
  darkgray: "#A9A9A9",
  lightblue: "#ADD8E6",
  greenyellow: "#ADFF2F",
  paleturquoise: "#AFEEEE",
  lightsteelblue: "#B0C4DE",
  powderblue: "#B0E0E6",
  firebrick: "#B22222",
  darkgoldenrod: "#B8860B",
  mediumorchid: "#BA55D3",
  rosybrown: "#BC8F8F",
  darkkhaki: "#BDB76B",
  silver: "#C0C0C0",
  mediumvioletred: "#C71585",
  indianred: "#CD5C5C",
  peru: "#CD853F",
  chocolate: "#D2691E",
  tan: "#D2B48C",
  lightgrey: "#D3D3D3",
  palevioletred: "#D87093",
  thistle: "#D8BFD8",
  orchid: "#DA70D6",
  goldenrod: "#DAA520",
  crimson: "#DC143C",
  gainsboro: "#DCDCDC",
  plum: "#DDA0DD",
  burlywood: "#DEB887",
  lightcyan: "#E0FFFF",
  lavender: "#E6E6FA",
  darksalmon: "#E9967A",
  violet: "#EE82EE",
  palegoldenrod: "#EEE8AA",
  lightcoral: "#F08080",
  khaki: "#F0E68C",
  aliceblue: "#F0F8FF",
  honeydew: "#F0FFF0",
  azure: "#F0FFFF",
  sandybrown: "#F4A460",
  wheat: "#F5DEB3",
  beige: "#F5F5DC",
  whitesmoke: "#F5F5F5",
  mintcream: "#F5FFFA",
  ghostwhite: "#F8F8FF",
  salmon: "#FA8072",
  antiquewhite: "#FAEBD7",
  linen: "#FAF0E6",
  lightgoldenrodyellow: "#FAFAD2",
  oldlace: "#FDF5E6",
  red: "#FF0000",
  fuchsia: "#FF00FF",
  magenta: "#FF00FF",
  deeppink: "#FF1493",
  orangered: "#FF4500",
  tomato: "#FF6347",
  hotpink: "#FF69B4",
  coral: "#FF7F50",
  darkorange: "#FF8C00",
  lightsalmon: "#FFA07A",
  orange: "#FFA500",
  lightpink: "#FFB6C1",
  pink: "#FFC0CB",
  gold: "#FFD700",
  peachpuff: "#FFDAB9",
  navajowhite: "#FFDEAD",
  moccasin: "#FFE4B5",
  bisque: "#FFE4C4",
  mistyrose: "#FFE4E1",
  blanchedalmond: "#FFEBCD",
  papayawhip: "#FFEFD5",
  lavenderblush: "#FFF0F5",
  seashell: "#FFF5EE",
  cornsilk: "#FFF8DC",
  lemonchiffon: "#FFFACD",
  floralwhite: "#FFFAF0",
  snow: "#FFFAFA",
  yellow: "#FFFF00",
  lightyellow: "#FFFFE0",
  ivory: "#FFFFF0",
  white: "#FFFFFF"
};

/**
 * @param {number} [pixelRatio=1]
 */
var ColorPicker$1 = /*#__PURE__*/function () {
  /**
   * @param {number} [pixelRatio=1]
   */
  function ColorPicker$1() {
    var pixelRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
    _classCallCheck(this, ColorPicker$1);
    this.pixelRatio = pixelRatio;
    this.generated = false;
    this.centerCoordinates = {
      x: 289 / 2,
      y: 289 / 2
    };
    this.r = 289 * 0.49;
    this.color = {
      r: 255,
      g: 255,
      b: 255,
      a: 1.0
    };
    this.hueCircle = undefined;
    this.initialColor = {
      r: 255,
      g: 255,
      b: 255,
      a: 1.0
    };
    this.previousColor = undefined;
    this.applied = false;

    // bound by
    this.updateCallback = function () {};
    this.closeCallback = function () {};

    // create all DOM elements
    this._create();
  }

  /**
   * this inserts the colorPicker into a div from the DOM
   *
   * @param {Element} container
   */
  _createClass(ColorPicker$1, [{
    key: "insertTo",
    value: function insertTo(container) {
      if (this.hammer !== undefined) {
        this.hammer.destroy();
        this.hammer = undefined;
      }
      this.container = container;
      this.container.appendChild(this.frame);
      this._bindHammer();
      this._setSize();
    }

    /**
     * the callback is executed on apply and save. Bind it to the application
     *
     * @param {Function} callback
     */
  }, {
    key: "setUpdateCallback",
    value: function setUpdateCallback(callback) {
      if (typeof callback === "function") {
        this.updateCallback = callback;
      } else {
        throw new Error("Function attempted to set as colorPicker update callback is not a function.");
      }
    }

    /**
     * the callback is executed on apply and save. Bind it to the application
     *
     * @param {Function} callback
     */
  }, {
    key: "setCloseCallback",
    value: function setCloseCallback(callback) {
      if (typeof callback === "function") {
        this.closeCallback = callback;
      } else {
        throw new Error("Function attempted to set as colorPicker closing callback is not a function.");
      }
    }

    /**
     *
     * @param {string} color
     * @returns {string}
     * @private
     */
  }, {
    key: "_isColorString",
    value: function _isColorString(color) {
      if (typeof color === "string") {
        return htmlColors[color];
      }
    }

    /**
     * Set the color of the colorPicker
     * Supported formats:
     * 'red'                   --> HTML color string
     * '#ffffff'               --> hex string
     * 'rgb(255,255,255)'      --> rgb string
     * 'rgba(255,255,255,1.0)' --> rgba string
     * {r:255,g:255,b:255}     --> rgb object
     * {r:255,g:255,b:255,a:1.0} --> rgba object
     *
     * @param {string | object} color
     * @param {boolean} [setInitial=true]
     */
  }, {
    key: "setColor",
    value: function setColor(color) {
      var setInitial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      if (color === "none") {
        return;
      }
      var rgba;

      // if a html color shorthand is used, convert to hex
      var htmlColor = this._isColorString(color);
      if (htmlColor !== undefined) {
        color = htmlColor;
      }

      // check format
      if (isString$1(color) === true) {
        if (isValidRGB(color) === true) {
          var rgbaArray = color.substr(4).substr(0, color.length - 5).split(",");
          rgba = {
            r: rgbaArray[0],
            g: rgbaArray[1],
            b: rgbaArray[2],
            a: 1.0
          };
        } else if (isValidRGBA(color) === true) {
          var _rgbaArray = color.substr(5).substr(0, color.length - 6).split(",");
          rgba = {
            r: _rgbaArray[0],
            g: _rgbaArray[1],
            b: _rgbaArray[2],
            a: _rgbaArray[3]
          };
        } else if (isValidHex(color) === true) {
          var rgbObj = hexToRGB(color);
          rgba = {
            r: rgbObj.r,
            g: rgbObj.g,
            b: rgbObj.b,
            a: 1.0
          };
        }
      } else {
        if (color instanceof Object) {
          if (color.r !== undefined && color.g !== undefined && color.b !== undefined) {
            var alpha = color.a !== undefined ? color.a : "1.0";
            rgba = {
              r: color.r,
              g: color.g,
              b: color.b,
              a: alpha
            };
          }
        }
      }

      // set color
      if (rgba === undefined) {
        throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: " + _JSON$stringify(color));
      } else {
        this._setColor(rgba, setInitial);
      }
    }

    /**
     * this shows the color picker.
     * The hue circle is constructed once and stored.
     */
  }, {
    key: "show",
    value: function show() {
      if (this.closeCallback !== undefined) {
        this.closeCallback();
        this.closeCallback = undefined;
      }
      this.applied = false;
      this.frame.style.display = "block";
      this._generateHueCircle();
    }

    // ------------------------------------------ PRIVATE ----------------------------- //

    /**
     * Hide the picker. Is called by the cancel button.
     * Optional boolean to store the previous color for easy access later on.
     *
     * @param {boolean} [storePrevious=true]
     * @private
     */
  }, {
    key: "_hide",
    value: function _hide() {
      var _this2 = this;
      var storePrevious = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
      // store the previous color for next time;
      if (storePrevious === true) {
        this.previousColor = _Object$assign({}, this.color);
      }
      if (this.applied === true) {
        this.updateCallback(this.initialColor);
      }
      this.frame.style.display = "none";

      // call the closing callback, restoring the onclick method.
      // this is in a setTimeout because it will trigger the show again before the click is done.
      _setTimeout(function () {
        if (_this2.closeCallback !== undefined) {
          _this2.closeCallback();
          _this2.closeCallback = undefined;
        }
      }, 0);
    }

    /**
     * bound to the save button. Saves and hides.
     *
     * @private
     */
  }, {
    key: "_save",
    value: function _save() {
      this.updateCallback(this.color);
      this.applied = false;
      this._hide();
    }

    /**
     * Bound to apply button. Saves but does not close. Is undone by the cancel button.
     *
     * @private
     */
  }, {
    key: "_apply",
    value: function _apply() {
      this.applied = true;
      this.updateCallback(this.color);
      this._updatePicker(this.color);
    }

    /**
     * load the color from the previous session.
     *
     * @private
     */
  }, {
    key: "_loadLast",
    value: function _loadLast() {
      if (this.previousColor !== undefined) {
        this.setColor(this.previousColor, false);
      } else {
        alert("There is no last color to load...");
      }
    }

    /**
     * set the color, place the picker
     *
     * @param {object} rgba
     * @param {boolean} [setInitial=true]
     * @private
     */
  }, {
    key: "_setColor",
    value: function _setColor(rgba) {
      var setInitial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      // store the initial color
      if (setInitial === true) {
        this.initialColor = _Object$assign({}, rgba);
      }
      this.color = rgba;
      var hsv = RGBToHSV(rgba.r, rgba.g, rgba.b);
      var angleConvert = 2 * Math.PI;
      var radius = this.r * hsv.s;
      var x = this.centerCoordinates.x + radius * Math.sin(angleConvert * hsv.h);
      var y = this.centerCoordinates.y + radius * Math.cos(angleConvert * hsv.h);
      this.colorPickerSelector.style.left = x - 0.5 * this.colorPickerSelector.clientWidth + "px";
      this.colorPickerSelector.style.top = y - 0.5 * this.colorPickerSelector.clientHeight + "px";
      this._updatePicker(rgba);
    }

    /**
     * bound to opacity control
     *
     * @param {number} value
     * @private
     */
  }, {
    key: "_setOpacity",
    value: function _setOpacity(value) {
      this.color.a = value / 100;
      this._updatePicker(this.color);
    }

    /**
     * bound to brightness control
     *
     * @param {number} value
     * @private
     */
  }, {
    key: "_setBrightness",
    value: function _setBrightness(value) {
      var hsv = RGBToHSV(this.color.r, this.color.g, this.color.b);
      hsv.v = value / 100;
      var rgba = HSVToRGB(hsv.h, hsv.s, hsv.v);
      rgba["a"] = this.color.a;
      this.color = rgba;
      this._updatePicker();
    }

    /**
     * update the color picker. A black circle overlays the hue circle to mimic the brightness decreasing.
     *
     * @param {object} rgba
     * @private
     */
  }, {
    key: "_updatePicker",
    value: function _updatePicker() {
      var rgba = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.color;
      var hsv = RGBToHSV(rgba.r, rgba.g, rgba.b);
      var ctx = this.colorPickerCanvas.getContext("2d");
      if (this.pixelRation === undefined) {
        this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1);
      }
      ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);

      // clear the canvas
      var w = this.colorPickerCanvas.clientWidth;
      var h = this.colorPickerCanvas.clientHeight;
      ctx.clearRect(0, 0, w, h);
      ctx.putImageData(this.hueCircle, 0, 0);
      ctx.fillStyle = "rgba(0,0,0," + (1 - hsv.v) + ")";
      ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r);
      _fillInstanceProperty(ctx).call(ctx);
      this.brightnessRange.value = 100 * hsv.v;
      this.opacityRange.value = 100 * rgba.a;
      this.initialColorDiv.style.backgroundColor = "rgba(" + this.initialColor.r + "," + this.initialColor.g + "," + this.initialColor.b + "," + this.initialColor.a + ")";
      this.newColorDiv.style.backgroundColor = "rgba(" + this.color.r + "," + this.color.g + "," + this.color.b + "," + this.color.a + ")";
    }

    /**
     * used by create to set the size of the canvas.
     *
     * @private
     */
  }, {
    key: "_setSize",
    value: function _setSize() {
      this.colorPickerCanvas.style.width = "100%";
      this.colorPickerCanvas.style.height = "100%";
      this.colorPickerCanvas.width = 289 * this.pixelRatio;
      this.colorPickerCanvas.height = 289 * this.pixelRatio;
    }

    /**
     * create all dom elements
     * TODO: cleanup, lots of similar dom elements
     *
     * @private
     */
  }, {
    key: "_create",
    value: function _create() {
      var _context16, _context17, _context18, _context19;
      this.frame = document.createElement("div");
      this.frame.className = "vis-color-picker";
      this.colorPickerDiv = document.createElement("div");
      this.colorPickerSelector = document.createElement("div");
      this.colorPickerSelector.className = "vis-selector";
      this.colorPickerDiv.appendChild(this.colorPickerSelector);
      this.colorPickerCanvas = document.createElement("canvas");
      this.colorPickerDiv.appendChild(this.colorPickerCanvas);
      if (!this.colorPickerCanvas.getContext) {
        var noCanvas = document.createElement("DIV");
        noCanvas.style.color = "red";
        noCanvas.style.fontWeight = "bold";
        noCanvas.style.padding = "10px";
        noCanvas.innerText = "Error: your browser does not support HTML canvas";
        this.colorPickerCanvas.appendChild(noCanvas);
      } else {
        var ctx = this.colorPickerCanvas.getContext("2d");
        this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1);
        this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);
      }
      this.colorPickerDiv.className = "vis-color";
      this.opacityDiv = document.createElement("div");
      this.opacityDiv.className = "vis-opacity";
      this.brightnessDiv = document.createElement("div");
      this.brightnessDiv.className = "vis-brightness";
      this.arrowDiv = document.createElement("div");
      this.arrowDiv.className = "vis-arrow";
      this.opacityRange = document.createElement("input");
      try {
        this.opacityRange.type = "range"; // Not supported on IE9
        this.opacityRange.min = "0";
        this.opacityRange.max = "100";
      } catch (err) {
        // TODO: Add some error handling.
      }
      this.opacityRange.value = "100";
      this.opacityRange.className = "vis-range";
      this.brightnessRange = document.createElement("input");
      try {
        this.brightnessRange.type = "range"; // Not supported on IE9
        this.brightnessRange.min = "0";
        this.brightnessRange.max = "100";
      } catch (err) {
        // TODO: Add some error handling.
      }
      this.brightnessRange.value = "100";
      this.brightnessRange.className = "vis-range";
      this.opacityDiv.appendChild(this.opacityRange);
      this.brightnessDiv.appendChild(this.brightnessRange);
      var me = this;
      this.opacityRange.onchange = function () {
        me._setOpacity(this.value);
      };
      this.opacityRange.oninput = function () {
        me._setOpacity(this.value);
      };
      this.brightnessRange.onchange = function () {
        me._setBrightness(this.value);
      };
      this.brightnessRange.oninput = function () {
        me._setBrightness(this.value);
      };
      this.brightnessLabel = document.createElement("div");
      this.brightnessLabel.className = "vis-label vis-brightness";
      this.brightnessLabel.innerText = "brightness:";
      this.opacityLabel = document.createElement("div");
      this.opacityLabel.className = "vis-label vis-opacity";
      this.opacityLabel.innerText = "opacity:";
      this.newColorDiv = document.createElement("div");
      this.newColorDiv.className = "vis-new-color";
      this.newColorDiv.innerText = "new";
      this.initialColorDiv = document.createElement("div");
      this.initialColorDiv.className = "vis-initial-color";
      this.initialColorDiv.innerText = "initial";
      this.cancelButton = document.createElement("div");
      this.cancelButton.className = "vis-button vis-cancel";
      this.cancelButton.innerText = "cancel";
      this.cancelButton.onclick = _bindInstanceProperty$1(_context16 = this._hide).call(_context16, this, false);
      this.applyButton = document.createElement("div");
      this.applyButton.className = "vis-button vis-apply";
      this.applyButton.innerText = "apply";
      this.applyButton.onclick = _bindInstanceProperty$1(_context17 = this._apply).call(_context17, this);
      this.saveButton = document.createElement("div");
      this.saveButton.className = "vis-button vis-save";
      this.saveButton.innerText = "save";
      this.saveButton.onclick = _bindInstanceProperty$1(_context18 = this._save).call(_context18, this);
      this.loadButton = document.createElement("div");
      this.loadButton.className = "vis-button vis-load";
      this.loadButton.innerText = "load last";
      this.loadButton.onclick = _bindInstanceProperty$1(_context19 = this._loadLast).call(_context19, this);
      this.frame.appendChild(this.colorPickerDiv);
      this.frame.appendChild(this.arrowDiv);
      this.frame.appendChild(this.brightnessLabel);
      this.frame.appendChild(this.brightnessDiv);
      this.frame.appendChild(this.opacityLabel);
      this.frame.appendChild(this.opacityDiv);
      this.frame.appendChild(this.newColorDiv);
      this.frame.appendChild(this.initialColorDiv);
      this.frame.appendChild(this.cancelButton);
      this.frame.appendChild(this.applyButton);
      this.frame.appendChild(this.saveButton);
      this.frame.appendChild(this.loadButton);
    }

    /**
     * bind hammer to the color picker
     *
     * @private
     */
  }, {
    key: "_bindHammer",
    value: function _bindHammer() {
      var _this3 = this;
      this.drag = {};
      this.pinch = {};
      this.hammer = new Hammer$1(this.colorPickerCanvas);
      this.hammer.get("pinch").set({
        enable: true
      });
      this.hammer.on("hammer.input", function (event) {
        if (event.isFirst) {
          _this3._moveSelector(event);
        }
      });
      this.hammer.on("tap", function (event) {
        _this3._moveSelector(event);
      });
      this.hammer.on("panstart", function (event) {
        _this3._moveSelector(event);
      });
      this.hammer.on("panmove", function (event) {
        _this3._moveSelector(event);
      });
      this.hammer.on("panend", function (event) {
        _this3._moveSelector(event);
      });
    }

    /**
     * generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown.
     *
     * @private
     */
  }, {
    key: "_generateHueCircle",
    value: function _generateHueCircle() {
      if (this.generated === false) {
        var ctx = this.colorPickerCanvas.getContext("2d");
        if (this.pixelRation === undefined) {
          this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1);
        }
        ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);

        // clear the canvas
        var w = this.colorPickerCanvas.clientWidth;
        var h = this.colorPickerCanvas.clientHeight;
        ctx.clearRect(0, 0, w, h);

        // draw hue circle
        var x, y, hue, sat;
        this.centerCoordinates = {
          x: w * 0.5,
          y: h * 0.5
        };
        this.r = 0.49 * w;
        var angleConvert = 2 * Math.PI / 360;
        var hfac = 1 / 360;
        var sfac = 1 / this.r;
        var rgb;
        for (hue = 0; hue < 360; hue++) {
          for (sat = 0; sat < this.r; sat++) {
            x = this.centerCoordinates.x + sat * Math.sin(angleConvert * hue);
            y = this.centerCoordinates.y + sat * Math.cos(angleConvert * hue);
            rgb = HSVToRGB(hue * hfac, sat * sfac, 1);
            ctx.fillStyle = "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
            ctx.fillRect(x - 0.5, y - 0.5, 2, 2);
          }
        }
        ctx.strokeStyle = "rgba(0,0,0,1)";
        ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r);
        ctx.stroke();
        this.hueCircle = ctx.getImageData(0, 0, w, h);
      }
      this.generated = true;
    }

    /**
     * move the selector. This is called by hammer functions.
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "_moveSelector",
    value: function _moveSelector(event) {
      var rect = this.colorPickerDiv.getBoundingClientRect();
      var left = event.center.x - rect.left;
      var top = event.center.y - rect.top;
      var centerY = 0.5 * this.colorPickerDiv.clientHeight;
      var centerX = 0.5 * this.colorPickerDiv.clientWidth;
      var x = left - centerX;
      var y = top - centerY;
      var angle = Math.atan2(x, y);
      var radius = 0.98 * Math.min(Math.sqrt(x * x + y * y), centerX);
      var newTop = Math.cos(angle) * radius + centerY;
      var newLeft = Math.sin(angle) * radius + centerX;
      this.colorPickerSelector.style.top = newTop - 0.5 * this.colorPickerSelector.clientHeight + "px";
      this.colorPickerSelector.style.left = newLeft - 0.5 * this.colorPickerSelector.clientWidth + "px";

      // set color
      var h = angle / (2 * Math.PI);
      h = h < 0 ? h + 1 : h;
      var s = radius / this.r;
      var hsv = RGBToHSV(this.color.r, this.color.g, this.color.b);
      hsv.h = h;
      hsv.s = s;
      var rgba = HSVToRGB(hsv.h, hsv.s, hsv.v);
      rgba["a"] = this.color.a;
      this.color = rgba;

      // update previews
      this.initialColorDiv.style.backgroundColor = "rgba(" + this.initialColor.r + "," + this.initialColor.g + "," + this.initialColor.b + "," + this.initialColor.a + ")";
      this.newColorDiv.style.backgroundColor = "rgba(" + this.color.r + "," + this.color.g + "," + this.color.b + "," + this.color.a + ")";
    }
  }]);
  return ColorPicker$1;
}();
/**
 * Wrap given text (last argument) in HTML elements (all preceding arguments).
 *
 * @param {...any} rest - List of tag names followed by inner text.
 * @returns An element or a text node.
 */
function wrapInTag() {
  for (var _len5 = arguments.length, rest = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
    rest[_key5] = arguments[_key5];
  }
  if (rest.length < 1) {
    throw new TypeError("Invalid arguments.");
  } else if (rest.length === 1) {
    return document.createTextNode(rest[0]);
  } else {
    var element = document.createElement(rest[0]);
    element.appendChild(wrapInTag.apply(void 0, _toConsumableArray(_sliceInstanceProperty(rest).call(rest, 1))));
    return element;
  }
}

/**
 * The way this works is for all properties of this.possible options, you can supply the property name in any form to list the options.
 * Boolean options are recognised as Boolean
 * Number options should be written as array: [default value, min value, max value, stepsize]
 * Colors should be written as array: ['color', '#ffffff']
 * Strings with should be written as array: [option1, option2, option3, ..]
 *
 * The options are matched with their counterparts in each of the modules and the values used in the configuration are
 */
var Configurator$1 = /*#__PURE__*/function () {
  /**
   * @param {object} parentModule        | the location where parentModule.setOptions() can be called
   * @param {object} defaultContainer    | the default container of the module
   * @param {object} configureOptions    | the fully configured and predefined options set found in allOptions.js
   * @param {number} pixelRatio          | canvas pixel ratio
   * @param {Function} hideOption        | custom logic to dynamically hide options
   */
  function Configurator$1(parentModule, defaultContainer, configureOptions) {
    var pixelRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
    var hideOption = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : function () {
      return false;
    };
    _classCallCheck(this, Configurator$1);
    this.parent = parentModule;
    this.changedOptions = [];
    this.container = defaultContainer;
    this.allowCreation = false;
    this.hideOption = hideOption;
    this.options = {};
    this.initialized = false;
    this.popupCounter = 0;
    this.defaultOptions = {
      enabled: false,
      filter: true,
      container: undefined,
      showButton: true
    };
    _Object$assign(this.options, this.defaultOptions);
    this.configureOptions = configureOptions;
    this.moduleOptions = {};
    this.domElements = [];
    this.popupDiv = {};
    this.popupLimit = 5;
    this.popupHistory = {};
    this.colorPicker = new ColorPicker$1(pixelRatio);
    this.wrapper = undefined;
  }

  /**
   * refresh all options.
   * Because all modules parse their options by themselves, we just use their options. We copy them here.
   *
   * @param {object} options
   */
  _createClass(Configurator$1, [{
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        // reset the popup history because the indices may have been changed.
        this.popupHistory = {};
        this._removePopup();
        var enabled = true;
        if (typeof options === "string") {
          this.options.filter = options;
        } else if (_Array$isArray(options)) {
          this.options.filter = options.join();
        } else if (_typeof(options) === "object") {
          if (options == null) {
            throw new TypeError("options cannot be null");
          }
          if (options.container !== undefined) {
            this.options.container = options.container;
          }
          if (_filterInstanceProperty(options) !== undefined) {
            this.options.filter = _filterInstanceProperty(options);
          }
          if (options.showButton !== undefined) {
            this.options.showButton = options.showButton;
          }
          if (options.enabled !== undefined) {
            enabled = options.enabled;
          }
        } else if (typeof options === "boolean") {
          this.options.filter = true;
          enabled = options;
        } else if (typeof options === "function") {
          this.options.filter = options;
          enabled = true;
        }
        if (_filterInstanceProperty(this.options) === false) {
          enabled = false;
        }
        this.options.enabled = enabled;
      }
      this._clean();
    }

    /**
     *
     * @param {object} moduleOptions
     */
  }, {
    key: "setModuleOptions",
    value: function setModuleOptions(moduleOptions) {
      this.moduleOptions = moduleOptions;
      if (this.options.enabled === true) {
        this._clean();
        if (this.options.container !== undefined) {
          this.container = this.options.container;
        }
        this._create();
      }
    }

    /**
     * Create all DOM elements
     *
     * @private
     */
  }, {
    key: "_create",
    value: function _create() {
      this._clean();
      this.changedOptions = [];
      var filter = _filterInstanceProperty(this.options);
      var counter = 0;
      var show = false;
      for (var _option in this.configureOptions) {
        if (Object.prototype.hasOwnProperty.call(this.configureOptions, _option)) {
          this.allowCreation = false;
          show = false;
          if (typeof filter === "function") {
            show = filter(_option, []);
            show = show || this._handleObject(this.configureOptions[_option], [_option], true);
          } else if (filter === true || _indexOfInstanceProperty(filter).call(filter, _option) !== -1) {
            show = true;
          }
          if (show !== false) {
            this.allowCreation = true;

            // linebreak between categories
            if (counter > 0) {
              this._makeItem([]);
            }
            // a header for the category
            this._makeHeader(_option);

            // get the sub options
            this._handleObject(this.configureOptions[_option], [_option]);
          }
          counter++;
        }
      }
      this._makeButton();
      this._push();
      //~ this.colorPicker.insertTo(this.container);
    }

    /**
     * draw all DOM elements on the screen
     *
     * @private
     */
  }, {
    key: "_push",
    value: function _push() {
      this.wrapper = document.createElement("div");
      this.wrapper.className = "vis-configuration-wrapper";
      this.container.appendChild(this.wrapper);
      for (var i = 0; i < this.domElements.length; i++) {
        this.wrapper.appendChild(this.domElements[i]);
      }
      this._showPopupIfNeeded();
    }

    /**
     * delete all DOM elements
     *
     * @private
     */
  }, {
    key: "_clean",
    value: function _clean() {
      for (var i = 0; i < this.domElements.length; i++) {
        this.wrapper.removeChild(this.domElements[i]);
      }
      if (this.wrapper !== undefined) {
        this.container.removeChild(this.wrapper);
        this.wrapper = undefined;
      }
      this.domElements = [];
      this._removePopup();
    }

    /**
     * get the value from the actualOptions if it exists
     *
     * @param {Array} path    | where to look for the actual option
     * @returns {*}
     * @private
     */
  }, {
    key: "_getValue",
    value: function _getValue(path) {
      var base = this.moduleOptions;
      for (var i = 0; i < path.length; i++) {
        if (base[path[i]] !== undefined) {
          base = base[path[i]];
        } else {
          base = undefined;
          break;
        }
      }
      return base;
    }

    /**
     * all option elements are wrapped in an item
     *
     * @param {Array} path    | where to look for the actual option
     * @param {Array.<Element>} domElements
     * @returns {number}
     * @private
     */
  }, {
    key: "_makeItem",
    value: function _makeItem(path) {
      if (this.allowCreation === true) {
        var item = document.createElement("div");
        item.className = "vis-configuration vis-config-item vis-config-s" + path.length;
        for (var _len6 = arguments.length, domElements = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
          domElements[_key6 - 1] = arguments[_key6];
        }
        _forEachInstanceProperty(domElements).call(domElements, function (element) {
          item.appendChild(element);
        });
        this.domElements.push(item);
        return this.domElements.length;
      }
      return 0;
    }

    /**
     * header for major subjects
     *
     * @param {string} name
     * @private
     */
  }, {
    key: "_makeHeader",
    value: function _makeHeader(name) {
      var div = document.createElement("div");
      div.className = "vis-configuration vis-config-header";
      div.innerText = name;
      this._makeItem([], div);
    }

    /**
     * make a label, if it is an object label, it gets different styling.
     *
     * @param {string} name
     * @param {Array} path    | where to look for the actual option
     * @param {string} objectLabel
     * @returns {HTMLElement}
     * @private
     */
  }, {
    key: "_makeLabel",
    value: function _makeLabel(name, path) {
      var objectLabel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var div = document.createElement("div");
      div.className = "vis-configuration vis-config-label vis-config-s" + path.length;
      if (objectLabel === true) {
        while (div.firstChild) {
          div.removeChild(div.firstChild);
        }
        div.appendChild(wrapInTag("i", "b", name));
      } else {
        div.innerText = name + ":";
      }
      return div;
    }

    /**
     * make a dropdown list for multiple possible string optoins
     *
     * @param {Array.<number>} arr
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_makeDropdown",
    value: function _makeDropdown(arr, value, path) {
      var select = document.createElement("select");
      select.className = "vis-configuration vis-config-select";
      var selectedValue = 0;
      if (value !== undefined) {
        if (_indexOfInstanceProperty(arr).call(arr, value) !== -1) {
          selectedValue = _indexOfInstanceProperty(arr).call(arr, value);
        }
      }
      for (var i = 0; i < arr.length; i++) {
        var _option2 = document.createElement("option");
        _option2.value = arr[i];
        if (i === selectedValue) {
          _option2.selected = "selected";
        }
        _option2.innerText = arr[i];
        select.appendChild(_option2);
      }
      var me = this;
      select.onchange = function () {
        me._update(this.value, path);
      };
      var label = this._makeLabel(path[path.length - 1], path);
      this._makeItem(path, label, select);
    }

    /**
     * make a range object for numeric options
     *
     * @param {Array.<number>} arr
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_makeRange",
    value: function _makeRange(arr, value, path) {
      var defaultValue = arr[0];
      var min = arr[1];
      var max = arr[2];
      var step = arr[3];
      var range = document.createElement("input");
      range.className = "vis-configuration vis-config-range";
      try {
        range.type = "range"; // not supported on IE9
        range.min = min;
        range.max = max;
      } catch (err) {
        // TODO: Add some error handling.
      }
      range.step = step;

      // set up the popup settings in case they are needed.
      var popupString = "";
      var popupValue = 0;
      if (value !== undefined) {
        var factor = 1.2;
        if (value < 0 && value * factor < min) {
          range.min = Math.ceil(value * factor);
          popupValue = range.min;
          popupString = "range increased";
        } else if (value / factor < min) {
          range.min = Math.ceil(value / factor);
          popupValue = range.min;
          popupString = "range increased";
        }
        if (value * factor > max && max !== 1) {
          range.max = Math.ceil(value * factor);
          popupValue = range.max;
          popupString = "range increased";
        }
        range.value = value;
      } else {
        range.value = defaultValue;
      }
      var input = document.createElement("input");
      input.className = "vis-configuration vis-config-rangeinput";
      input.value = range.value;
      var me = this;
      range.onchange = function () {
        input.value = this.value;
        me._update(Number(this.value), path);
      };
      range.oninput = function () {
        input.value = this.value;
      };
      var label = this._makeLabel(path[path.length - 1], path);
      var itemIndex = this._makeItem(path, label, range, input);

      // if a popup is needed AND it has not been shown for this value, show it.
      if (popupString !== "" && this.popupHistory[itemIndex] !== popupValue) {
        this.popupHistory[itemIndex] = popupValue;
        this._setupPopup(popupString, itemIndex);
      }
    }

    /**
     * make a button object
     *
     * @private
     */
  }, {
    key: "_makeButton",
    value: function _makeButton() {
      var _this4 = this;
      if (this.options.showButton === true) {
        var generateButton = document.createElement("div");
        generateButton.className = "vis-configuration vis-config-button";
        generateButton.innerText = "generate options";
        generateButton.onclick = function () {
          _this4._printOptions();
        };
        generateButton.onmouseover = function () {
          generateButton.className = "vis-configuration vis-config-button hover";
        };
        generateButton.onmouseout = function () {
          generateButton.className = "vis-configuration vis-config-button";
        };
        this.optionsContainer = document.createElement("div");
        this.optionsContainer.className = "vis-configuration vis-config-option-container";
        this.domElements.push(this.optionsContainer);
        this.domElements.push(generateButton);
      }
    }

    /**
     * prepare the popup
     *
     * @param {string} string
     * @param {number} index
     * @private
     */
  }, {
    key: "_setupPopup",
    value: function _setupPopup(string, index) {
      var _this5 = this;
      if (this.initialized === true && this.allowCreation === true && this.popupCounter < this.popupLimit) {
        var div = document.createElement("div");
        div.id = "vis-configuration-popup";
        div.className = "vis-configuration-popup";
        div.innerText = string;
        div.onclick = function () {
          _this5._removePopup();
        };
        this.popupCounter += 1;
        this.popupDiv = {
          html: div,
          index: index
        };
      }
    }

    /**
     * remove the popup from the dom
     *
     * @private
     */
  }, {
    key: "_removePopup",
    value: function _removePopup() {
      if (this.popupDiv.html !== undefined) {
        this.popupDiv.html.parentNode.removeChild(this.popupDiv.html);
        clearTimeout(this.popupDiv.hideTimeout);
        clearTimeout(this.popupDiv.deleteTimeout);
        this.popupDiv = {};
      }
    }

    /**
     * Show the popup if it is needed.
     *
     * @private
     */
  }, {
    key: "_showPopupIfNeeded",
    value: function _showPopupIfNeeded() {
      var _this6 = this;
      if (this.popupDiv.html !== undefined) {
        var correspondingElement = this.domElements[this.popupDiv.index];
        var rect = correspondingElement.getBoundingClientRect();
        this.popupDiv.html.style.left = rect.left + "px";
        this.popupDiv.html.style.top = rect.top - 30 + "px"; // 30 is the height;
        document.body.appendChild(this.popupDiv.html);
        this.popupDiv.hideTimeout = _setTimeout(function () {
          _this6.popupDiv.html.style.opacity = 0;
        }, 1500);
        this.popupDiv.deleteTimeout = _setTimeout(function () {
          _this6._removePopup();
        }, 1800);
      }
    }

    /**
     * make a checkbox for boolean options.
     *
     * @param {number} defaultValue
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_makeCheckbox",
    value: function _makeCheckbox(defaultValue, value, path) {
      var checkbox = document.createElement("input");
      checkbox.type = "checkbox";
      checkbox.className = "vis-configuration vis-config-checkbox";
      checkbox.checked = defaultValue;
      if (value !== undefined) {
        checkbox.checked = value;
        if (value !== defaultValue) {
          if (_typeof(defaultValue) === "object") {
            if (value !== defaultValue.enabled) {
              this.changedOptions.push({
                path: path,
                value: value
              });
            }
          } else {
            this.changedOptions.push({
              path: path,
              value: value
            });
          }
        }
      }
      var me = this;
      checkbox.onchange = function () {
        me._update(this.checked, path);
      };
      var label = this._makeLabel(path[path.length - 1], path);
      this._makeItem(path, label, checkbox);
    }

    /**
     * make a text input field for string options.
     *
     * @param {number} defaultValue
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_makeTextInput",
    value: function _makeTextInput(defaultValue, value, path) {
      var checkbox = document.createElement("input");
      checkbox.type = "text";
      checkbox.className = "vis-configuration vis-config-text";
      checkbox.value = value;
      if (value !== defaultValue) {
        this.changedOptions.push({
          path: path,
          value: value
        });
      }
      var me = this;
      checkbox.onchange = function () {
        me._update(this.value, path);
      };
      var label = this._makeLabel(path[path.length - 1], path);
      this._makeItem(path, label, checkbox);
    }

    /**
     * make a color field with a color picker for color fields
     *
     * @param {Array.<number>} arr
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_makeColorField",
    value: function _makeColorField(arr, value, path) {
      var _this7 = this;
      var defaultColor = arr[1];
      var div = document.createElement("div");
      value = value === undefined ? defaultColor : value;
      if (value !== "none") {
        div.className = "vis-configuration vis-config-colorBlock";
        div.style.backgroundColor = value;
      } else {
        div.className = "vis-configuration vis-config-colorBlock none";
      }
      value = value === undefined ? defaultColor : value;
      div.onclick = function () {
        _this7._showColorPicker(value, div, path);
      };
      var label = this._makeLabel(path[path.length - 1], path);
      this._makeItem(path, label, div);
    }

    /**
     * used by the color buttons to call the color picker.
     *
     * @param {number} value
     * @param {HTMLElement} div
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_showColorPicker",
    value: function _showColorPicker(value, div, path) {
      var _this8 = this;
      // clear the callback from this div
      div.onclick = function () {};
      this.colorPicker.insertTo(div);
      this.colorPicker.show();
      this.colorPicker.setColor(value);
      this.colorPicker.setUpdateCallback(function (color) {
        var colorString = "rgba(" + color.r + "," + color.g + "," + color.b + "," + color.a + ")";
        div.style.backgroundColor = colorString;
        _this8._update(colorString, path);
      });

      // on close of the colorpicker, restore the callback.
      this.colorPicker.setCloseCallback(function () {
        div.onclick = function () {
          _this8._showColorPicker(value, div, path);
        };
      });
    }

    /**
     * parse an object and draw the correct items
     *
     * @param {object} obj
     * @param {Array} [path=[]]    | where to look for the actual option
     * @param {boolean} [checkOnly=false]
     * @returns {boolean}
     * @private
     */
  }, {
    key: "_handleObject",
    value: function _handleObject(obj) {
      var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
      var checkOnly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var show = false;
      var filter = _filterInstanceProperty(this.options);
      var visibleInSet = false;
      for (var subObj in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, subObj)) {
          show = true;
          var item = obj[subObj];
          var newPath = copyAndExtendArray(path, subObj);
          if (typeof filter === "function") {
            show = filter(subObj, path);

            // if needed we must go deeper into the object.
            if (show === false) {
              if (!_Array$isArray(item) && typeof item !== "string" && typeof item !== "boolean" && item instanceof Object) {
                this.allowCreation = false;
                show = this._handleObject(item, newPath, true);
                this.allowCreation = checkOnly === false;
              }
            }
          }
          if (show !== false) {
            visibleInSet = true;
            var value = this._getValue(newPath);
            if (_Array$isArray(item)) {
              this._handleArray(item, value, newPath);
            } else if (typeof item === "string") {
              this._makeTextInput(item, value, newPath);
            } else if (typeof item === "boolean") {
              this._makeCheckbox(item, value, newPath);
            } else if (item instanceof Object) {
              // skip the options that are not enabled
              if (!this.hideOption(path, subObj, this.moduleOptions)) {
                // initially collapse options with an disabled enabled option.
                if (item.enabled !== undefined) {
                  var enabledPath = copyAndExtendArray(newPath, "enabled");
                  var enabledValue = this._getValue(enabledPath);
                  if (enabledValue === true) {
                    var label = this._makeLabel(subObj, newPath, true);
                    this._makeItem(newPath, label);
                    visibleInSet = this._handleObject(item, newPath) || visibleInSet;
                  } else {
                    this._makeCheckbox(item, enabledValue, newPath);
                  }
                } else {
                  var _label = this._makeLabel(subObj, newPath, true);
                  this._makeItem(newPath, _label);
                  visibleInSet = this._handleObject(item, newPath) || visibleInSet;
                }
              }
            } else {
              console.error("dont know how to handle", item, subObj, newPath);
            }
          }
        }
      }
      return visibleInSet;
    }

    /**
     * handle the array type of option
     *
     * @param {Array.<number>} arr
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_handleArray",
    value: function _handleArray(arr, value, path) {
      if (typeof arr[0] === "string" && arr[0] === "color") {
        this._makeColorField(arr, value, path);
        if (arr[1] !== value) {
          this.changedOptions.push({
            path: path,
            value: value
          });
        }
      } else if (typeof arr[0] === "string") {
        this._makeDropdown(arr, value, path);
        if (arr[0] !== value) {
          this.changedOptions.push({
            path: path,
            value: value
          });
        }
      } else if (typeof arr[0] === "number") {
        this._makeRange(arr, value, path);
        if (arr[0] !== value) {
          this.changedOptions.push({
            path: path,
            value: Number(value)
          });
        }
      }
    }

    /**
     * called to update the network with the new settings.
     *
     * @param {number} value
     * @param {Array} path    | where to look for the actual option
     * @private
     */
  }, {
    key: "_update",
    value: function _update(value, path) {
      var options = this._constructOptions(value, path);
      if (this.parent.body && this.parent.body.emitter && this.parent.body.emitter.emit) {
        this.parent.body.emitter.emit("configChange", options);
      }
      this.initialized = true;
      this.parent.setOptions(options);
    }

    /**
     *
     * @param {string | boolean} value
     * @param {Array.<string>} path
     * @param {{}} optionsObj
     * @returns {{}}
     * @private
     */
  }, {
    key: "_constructOptions",
    value: function _constructOptions(value, path) {
      var optionsObj = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      var pointer = optionsObj;

      // when dropdown boxes can be string or boolean, we typecast it into correct types
      value = value === "true" ? true : value;
      value = value === "false" ? false : value;
      for (var i = 0; i < path.length; i++) {
        if (path[i] !== "global") {
          if (pointer[path[i]] === undefined) {
            pointer[path[i]] = {};
          }
          if (i !== path.length - 1) {
            pointer = pointer[path[i]];
          } else {
            pointer[path[i]] = value;
          }
        }
      }
      return optionsObj;
    }

    /**
     * @private
     */
  }, {
    key: "_printOptions",
    value: function _printOptions() {
      var options = this.getOptions();
      while (this.optionsContainer.firstChild) {
        this.optionsContainer.removeChild(this.optionsContainer.firstChild);
      }
      this.optionsContainer.appendChild(wrapInTag("pre", "const options = " + _JSON$stringify(options, null, 2)));
    }

    /**
     *
     * @returns {{}} options
     */
  }, {
    key: "getOptions",
    value: function getOptions() {
      var options = {};
      for (var i = 0; i < this.changedOptions.length; i++) {
        this._constructOptions(this.changedOptions[i].value, this.changedOptions[i].path, options);
      }
      return options;
    }
  }]);
  return Configurator$1;
}();
/**
 * Popup is a class to create a popup window with some text
 */
var Popup$1 = /*#__PURE__*/function () {
  /**
   * @param {Element} container       The container object.
   * @param {string}  overflowMethod  How the popup should act to overflowing ('flip' or 'cap')
   */
  function Popup$1(container, overflowMethod) {
    _classCallCheck(this, Popup$1);
    this.container = container;
    this.overflowMethod = overflowMethod || "cap";
    this.x = 0;
    this.y = 0;
    this.padding = 5;
    this.hidden = false;

    // create the frame
    this.frame = document.createElement("div");
    this.frame.className = "vis-tooltip";
    this.container.appendChild(this.frame);
  }

  /**
   * @param {number} x   Horizontal position of the popup window
   * @param {number} y   Vertical position of the popup window
   */
  _createClass(Popup$1, [{
    key: "setPosition",
    value: function setPosition(x, y) {
      this.x = _parseInt(x);
      this.y = _parseInt(y);
    }

    /**
     * Set the content for the popup window. This can be HTML code or text.
     *
     * @param {string | Element} content
     */
  }, {
    key: "setText",
    value: function setText(content) {
      if (content instanceof Element) {
        while (this.frame.firstChild) {
          this.frame.removeChild(this.frame.firstChild);
        }
        this.frame.appendChild(content);
      } else {
        // String containing literal text, element has to be used for HTML due to
        // XSS risks associated with innerHTML (i.e. prevent XSS by accident).
        this.frame.innerText = content;
      }
    }

    /**
     * Show the popup window
     *
     * @param {boolean} [doShow]    Show or hide the window
     */
  }, {
    key: "show",
    value: function show(doShow) {
      if (doShow === undefined) {
        doShow = true;
      }
      if (doShow === true) {
        var height = this.frame.clientHeight;
        var width = this.frame.clientWidth;
        var maxHeight = this.frame.parentNode.clientHeight;
        var maxWidth = this.frame.parentNode.clientWidth;
        var left = 0,
          top = 0;
        if (this.overflowMethod == "flip") {
          var isLeft = false,
            isTop = true; // Where around the position it's located

          if (this.y - height < this.padding) {
            isTop = false;
          }
          if (this.x + width > maxWidth - this.padding) {
            isLeft = true;
          }
          if (isLeft) {
            left = this.x - width;
          } else {
            left = this.x;
          }
          if (isTop) {
            top = this.y - height;
          } else {
            top = this.y;
          }
        } else {
          top = this.y - height;
          if (top + height + this.padding > maxHeight) {
            top = maxHeight - height - this.padding;
          }
          if (top < this.padding) {
            top = this.padding;
          }
          left = this.x;
          if (left + width + this.padding > maxWidth) {
            left = maxWidth - width - this.padding;
          }
          if (left < this.padding) {
            left = this.padding;
          }
        }
        this.frame.style.left = left + "px";
        this.frame.style.top = top + "px";
        this.frame.style.visibility = "visible";
        this.hidden = false;
      } else {
        this.hide();
      }
    }

    /**
     * Hide the popup window
     */
  }, {
    key: "hide",
    value: function hide() {
      this.hidden = true;
      this.frame.style.left = "0";
      this.frame.style.top = "0";
      this.frame.style.visibility = "hidden";
    }

    /**
     * Remove the popup window
     */
  }, {
    key: "destroy",
    value: function destroy() {
      this.frame.parentNode.removeChild(this.frame); // Remove element from DOM
    }
  }]);
  return Popup$1;
}();
var errorFound = false;
var allOptions$1;
var VALIDATOR_PRINT_STYLE$1 = "background: #FFeeee; color: #dd0000";

/**
 *  Used to validate options.
 */
var Validator$1 = /*#__PURE__*/function () {
  function Validator$1() {
    _classCallCheck(this, Validator$1);
  }
  _createClass(Validator$1, null, [{
    key: "validate",
    value:
    /**
     * Main function to be called
     *
     * @param {object} options
     * @param {object} referenceOptions
     * @param {object} subObject
     * @returns {boolean}
     * @static
     */
    function validate(options, referenceOptions, subObject) {
      errorFound = false;
      allOptions$1 = referenceOptions;
      var usedOptions = referenceOptions;
      if (subObject !== undefined) {
        usedOptions = referenceOptions[subObject];
      }
      Validator$1.parse(options, usedOptions, []);
      return errorFound;
    }

    /**
     * Will traverse an object recursively and check every value
     *
     * @param {object} options
     * @param {object} referenceOptions
     * @param {Array} path    | where to look for the actual option
     * @static
     */
  }, {
    key: "parse",
    value: function parse(options, referenceOptions, path) {
      for (var _option3 in options) {
        if (Object.prototype.hasOwnProperty.call(options, _option3)) {
          Validator$1.check(_option3, options, referenceOptions, path);
        }
      }
    }

    /**
     * Check every value. If the value is an object, call the parse function on that object.
     *
     * @param {string} option
     * @param {object} options
     * @param {object} referenceOptions
     * @param {Array} path    | where to look for the actual option
     * @static
     */
  }, {
    key: "check",
    value: function check(option, options, referenceOptions, path) {
      if (referenceOptions[option] === undefined && referenceOptions.__any__ === undefined) {
        Validator$1.getSuggestion(option, referenceOptions, path);
        return;
      }
      var referenceOption = option;
      var is_object = true;
      if (referenceOptions[option] === undefined && referenceOptions.__any__ !== undefined) {
        // NOTE: This only triggers if the __any__ is in the top level of the options object.
        //       THAT'S A REALLY BAD PLACE TO ALLOW IT!!!!
        // TODO: Examine if needed, remove if possible

        // __any__ is a wildcard. Any value is accepted and will be further analysed by reference.
        referenceOption = "__any__";

        // if the any-subgroup is not a predefined object in the configurator,
        // we do not look deeper into the object.
        is_object = Validator$1.getType(options[option]) === "object";
      }
      var refOptionObj = referenceOptions[referenceOption];
      if (is_object && refOptionObj.__type__ !== undefined) {
        refOptionObj = refOptionObj.__type__;
      }
      Validator$1.checkFields(option, options, referenceOptions, referenceOption, refOptionObj, path);
    }

    /**
     *
     * @param {string}  option           | the option property
     * @param {object}  options          | The supplied options object
     * @param {object}  referenceOptions | The reference options containing all options and their allowed formats
     * @param {string}  referenceOption  | Usually this is the same as option, except when handling an __any__ tag.
     * @param {string}  refOptionObj     | This is the type object from the reference options
     * @param {Array}   path             | where in the object is the option
     * @static
     */
  }, {
    key: "checkFields",
    value: function checkFields(option, options, referenceOptions, referenceOption, refOptionObj, path) {
      var log = function log(message) {
        console.error("%c" + message + Validator$1.printLocation(path, option), VALIDATOR_PRINT_STYLE$1);
      };
      var optionType = Validator$1.getType(options[option]);
      var refOptionType = refOptionObj[optionType];
      if (refOptionType !== undefined) {
        // if the type is correct, we check if it is supposed to be one of a few select values
        if (Validator$1.getType(refOptionType) === "array" && _indexOfInstanceProperty(refOptionType).call(refOptionType, options[option]) === -1) {
          log('Invalid option detected in "' + option + '".' + " Allowed values are:" + Validator$1.print(refOptionType) + ' not "' + options[option] + '". ');
          errorFound = true;
        } else if (optionType === "object" && referenceOption !== "__any__") {
          path = copyAndExtendArray(path, option);
          Validator$1.parse(options[option], referenceOptions[referenceOption], path);
        }
      } else if (refOptionObj["any"] === undefined) {
        // type of the field is incorrect and the field cannot be any
        log('Invalid type received for "' + option + '". Expected: ' + Validator$1.print(_Object$keys(refOptionObj)) + ". Received [" + optionType + '] "' + options[option] + '"');
        errorFound = true;
      }
    }

    /**
     *
     * @param {object | boolean | number | string | Array.<number> | Date | Node | Moment | undefined | null} object
     * @returns {string}
     * @static
     */
  }, {
    key: "getType",
    value: function getType(object) {
      var type = _typeof(object);
      if (type === "object") {
        if (object === null) {
          return "null";
        }
        if (object instanceof Boolean) {
          return "boolean";
        }
        if (object instanceof Number) {
          return "number";
        }
        if (object instanceof String) {
          return "string";
        }
        if (_Array$isArray(object)) {
          return "array";
        }
        if (object instanceof Date) {
          return "date";
        }
        if (object.nodeType !== undefined) {
          return "dom";
        }
        if (object._isAMomentObject === true) {
          return "moment";
        }
        return "object";
      } else if (type === "number") {
        return "number";
      } else if (type === "boolean") {
        return "boolean";
      } else if (type === "string") {
        return "string";
      } else if (type === undefined) {
        return "undefined";
      }
      return type;
    }

    /**
     * @param {string} option
     * @param {object} options
     * @param {Array.<string>} path
     * @static
     */
  }, {
    key: "getSuggestion",
    value: function getSuggestion(option, options, path) {
      var localSearch = Validator$1.findInOptions(option, options, path, false);
      var globalSearch = Validator$1.findInOptions(option, allOptions$1, [], true);
      var localSearchThreshold = 8;
      var globalSearchThreshold = 4;
      var msg;
      if (localSearch.indexMatch !== undefined) {
        msg = " in " + Validator$1.printLocation(localSearch.path, option, "") + 'Perhaps it was incomplete? Did you mean: "' + localSearch.indexMatch + '"?\n\n';
      } else if (globalSearch.distance <= globalSearchThreshold && localSearch.distance > globalSearch.distance) {
        msg = " in " + Validator$1.printLocation(localSearch.path, option, "") + "Perhaps it was misplaced? Matching option found at: " + Validator$1.printLocation(globalSearch.path, globalSearch.closestMatch, "");
      } else if (localSearch.distance <= localSearchThreshold) {
        msg = '. Did you mean "' + localSearch.closestMatch + '"?' + Validator$1.printLocation(localSearch.path, option);
      } else {
        msg = ". Did you mean one of these: " + Validator$1.print(_Object$keys(options)) + Validator$1.printLocation(path, option);
      }
      console.error('%cUnknown option detected: "' + option + '"' + msg, VALIDATOR_PRINT_STYLE$1);
      errorFound = true;
    }

    /**
     * traverse the options in search for a match.
     *
     * @param {string} option
     * @param {object} options
     * @param {Array} path    | where to look for the actual option
     * @param {boolean} [recursive=false]
     * @returns {{closestMatch: string, path: Array, distance: number}}
     * @static
     */
  }, {
    key: "findInOptions",
    value: function findInOptions(option, options, path) {
      var recursive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
      var min = 1e9;
      var closestMatch = "";
      var closestMatchPath = [];
      var lowerCaseOption = option.toLowerCase();
      var indexMatch = undefined;
      for (var op in options) {
        var distance = void 0;
        if (options[op].__type__ !== undefined && recursive === true) {
          var result = Validator$1.findInOptions(option, options[op], copyAndExtendArray(path, op));
          if (min > result.distance) {
            closestMatch = result.closestMatch;
            closestMatchPath = result.path;
            min = result.distance;
            indexMatch = result.indexMatch;
          }
        } else {
          var _context20;
          if (_indexOfInstanceProperty(_context20 = op.toLowerCase()).call(_context20, lowerCaseOption) !== -1) {
            indexMatch = op;
          }
          distance = Validator$1.levenshteinDistance(option, op);
          if (min > distance) {
            closestMatch = op;
            closestMatchPath = copyArray(path);
            min = distance;
          }
        }
      }
      return {
        closestMatch: closestMatch,
        path: closestMatchPath,
        distance: min,
        indexMatch: indexMatch
      };
    }

    /**
     * @param {Array.<string>} path
     * @param {object} option
     * @param {string} prefix
     * @returns {string}
     * @static
     */
  }, {
    key: "printLocation",
    value: function printLocation(path, option) {
      var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "Problem value found at: \n";
      var str = "\n\n" + prefix + "options = {\n";
      for (var i = 0; i < path.length; i++) {
        for (var j = 0; j < i + 1; j++) {
          str += "  ";
        }
        str += path[i] + ": {\n";
      }
      for (var _j = 0; _j < path.length + 1; _j++) {
        str += "  ";
      }
      str += option + "\n";
      for (var _i3 = 0; _i3 < path.length + 1; _i3++) {
        for (var _j2 = 0; _j2 < path.length - _i3; _j2++) {
          str += "  ";
        }
        str += "}\n";
      }
      return str + "\n\n";
    }

    /**
     * @param {object} options
     * @returns {string}
     * @static
     */
  }, {
    key: "print",
    value: function print(options) {
      return _JSON$stringify(options).replace(/(")|(\[)|(\])|(,"__type__")/g, "").replace(/(,)/g, ", ");
    }

    /**
     *  Compute the edit distance between the two given strings
     * http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
     *
     * Copyright (c) 2011 Andrei Mackenzie
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * @param {string} a
     * @param {string} b
     * @returns {Array.<Array.<number>>}}
     * @static
     */
  }, {
    key: "levenshteinDistance",
    value: function levenshteinDistance(a, b) {
      if (a.length === 0) return b.length;
      if (b.length === 0) return a.length;
      var matrix = [];

      // increment along the first column of each row
      var i;
      for (i = 0; i <= b.length; i++) {
        matrix[i] = [i];
      }

      // increment each column in the first row
      var j;
      for (j = 0; j <= a.length; j++) {
        matrix[0][j] = j;
      }

      // Fill in the rest of the matrix
      for (i = 1; i <= b.length; i++) {
        for (j = 1; j <= a.length; j++) {
          if (b.charAt(i - 1) == a.charAt(j - 1)) {
            matrix[i][j] = matrix[i - 1][j - 1];
          } else {
            matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1,
            // substitution
            Math.min(matrix[i][j - 1] + 1,
            // insertion
            matrix[i - 1][j] + 1)); // deletion
          }
        }
      }

      return matrix[b.length][a.length];
    }
  }]);
  return Validator$1;
}();
var Activator = Activator$1;
var Configurator = Configurator$1;
var Hammer = Hammer$1;
var Popup = Popup$1;
var VALIDATOR_PRINT_STYLE = VALIDATOR_PRINT_STYLE$1;
var Validator = Validator$1;

/* eslint-disable no-prototype-builtins */
/* eslint-disable no-unused-vars */
/* eslint-disable no-var */

/**
 * Parse a text source containing data in DOT language into a JSON object.
 * The object contains two lists: one with nodes and one with edges.
 *
 * DOT language reference: http://www.graphviz.org/doc/info/lang.html
 *
 * DOT language attributes: http://graphviz.org/content/attrs
 *
 * @param {string} data     Text containing a graph in DOT-notation
 * @returns {object} graph   An object containing two parameters:
 *                          {Object[]} nodes
 *                          {Object[]} edges
 *
 * -------------------------------------------
 * TODO
 * ====
 *
 * For label handling, this is an incomplete implementation. From docs (quote #3015):
 *
 * > the escape sequences "\n", "\l" and "\r" divide the label into lines, centered,
 * > left-justified, and right-justified, respectively.
 *
 * Source: http://www.graphviz.org/content/attrs#kescString
 *
 * > As another aid for readability, dot allows double-quoted strings to span multiple physical
 * > lines using the standard C convention of a backslash immediately preceding a newline
 * > character
 * > In addition, double-quoted strings can be concatenated using a '+' operator.
 * > As HTML strings can contain newline characters, which are used solely for formatting,
 * > the language does not allow escaped newlines or concatenation operators to be used
 * > within them.
 *
 * - Currently, only '\\n' is handled
 * - Note that text explicitly says 'labels'; the dot parser currently handles escape
 *   sequences in **all** strings.
 */
function parseDOT(data) {
  dot = data;
  return parseGraph();
}

// mapping of attributes from DOT (the keys) to vis.js (the values)
var NODE_ATTR_MAPPING = {
  fontsize: "font.size",
  fontcolor: "font.color",
  labelfontcolor: "font.color",
  fontname: "font.face",
  color: ["color.border", "color.background"],
  fillcolor: "color.background",
  tooltip: "title",
  labeltooltip: "title"
};
var EDGE_ATTR_MAPPING = _Object$create$1(NODE_ATTR_MAPPING);
EDGE_ATTR_MAPPING.color = "color.color";
EDGE_ATTR_MAPPING.style = "dashes";

// token types enumeration
var TOKENTYPE = {
  NULL: 0,
  DELIMITER: 1,
  IDENTIFIER: 2,
  UNKNOWN: 3
};

// map with all delimiters
var DELIMITERS = {
  "{": true,
  "}": true,
  "[": true,
  "]": true,
  ";": true,
  "=": true,
  ",": true,
  "->": true,
  "--": true
};
var dot = ""; // current dot file
var index = 0; // current index in dot file
var c = ""; // current token character in expr
var token = ""; // current token
var tokenType = TOKENTYPE.NULL; // type of the token

/**
 * Get the first character from the dot file.
 * The character is stored into the char c. If the end of the dot file is
 * reached, the function puts an empty string in c.
 */
function first() {
  index = 0;
  c = dot.charAt(0);
}

/**
 * Get the next character from the dot file.
 * The character is stored into the char c. If the end of the dot file is
 * reached, the function puts an empty string in c.
 */
function next() {
  index++;
  c = dot.charAt(index);
}

/**
 * Preview the next character from the dot file.
 *
 * @returns {string} cNext
 */
function nextPreview() {
  return dot.charAt(index + 1);
}

/**
 * Test whether given character is alphabetic or numeric ( a-zA-Z_0-9.:# )
 *
 * @param {string} c
 * @returns {boolean} isAlphaNumeric
 */
function isAlphaNumeric(c) {
  var charCode = c.charCodeAt(0);
  if (charCode < 47) {
    // #.
    return charCode === 35 || charCode === 46;
  }
  if (charCode < 59) {
    // 0-9 and :
    return charCode > 47;
  }
  if (charCode < 91) {
    // A-Z
    return charCode > 64;
  }
  if (charCode < 96) {
    // _
    return charCode === 95;
  }
  if (charCode < 123) {
    // a-z
    return charCode > 96;
  }
  return false;
}

/**
 * Merge all options of object b into object b
 *
 * @param {object} a
 * @param {object} b
 * @returns {object} a
 */
function merge$1(a, b) {
  if (!a) {
    a = {};
  }
  if (b) {
    for (var name in b) {
      if (b.hasOwnProperty(name)) {
        a[name] = b[name];
      }
    }
  }
  return a;
}

/**
 * Set a value in an object, where the provided parameter name can be a
 * path with nested parameters. For example:
 *
 *     var obj = {a: 2};
 *     setValue(obj, 'b.c', 3);     // obj = {a: 2, b: {c: 3}}
 *
 * @param {object} obj
 * @param {string} path  A parameter name or dot-separated parameter path,
 *                      like "color.highlight.border".
 * @param {*} value
 */
function setValue(obj, path, value) {
  var keys = path.split(".");
  var o = obj;
  while (keys.length) {
    var key = keys.shift();
    if (keys.length) {
      // this isn't the end point
      if (!o[key]) {
        o[key] = {};
      }
      o = o[key];
    } else {
      // this is the end point
      o[key] = value;
    }
  }
}

/**
 * Add a node to a graph object. If there is already a node with
 * the same id, their attributes will be merged.
 *
 * @param {object} graph
 * @param {object} node
 */
function addNode(graph, node) {
  var i, len;
  var current = null;

  // find root graph (in case of subgraph)
  var graphs = [graph]; // list with all graphs from current graph to root graph
  var root = graph;
  while (root.parent) {
    graphs.push(root.parent);
    root = root.parent;
  }

  // find existing node (at root level) by its id
  if (root.nodes) {
    for (i = 0, len = root.nodes.length; i < len; i++) {
      if (node.id === root.nodes[i].id) {
        current = root.nodes[i];
        break;
      }
    }
  }
  if (!current) {
    // this is a new node
    current = {
      id: node.id
    };
    if (graph.node) {
      // clone default attributes
      current.attr = merge$1(current.attr, graph.node);
    }
  }

  // add node to this (sub)graph and all its parent graphs
  for (i = graphs.length - 1; i >= 0; i--) {
    var _context;
    var g = graphs[i];
    if (!g.nodes) {
      g.nodes = [];
    }
    if (_indexOfInstanceProperty(_context = g.nodes).call(_context, current) === -1) {
      g.nodes.push(current);
    }
  }

  // merge attributes
  if (node.attr) {
    current.attr = merge$1(current.attr, node.attr);
  }
}

/**
 * Add an edge to a graph object
 *
 * @param {object} graph
 * @param {object} edge
 */
function addEdge(graph, edge) {
  if (!graph.edges) {
    graph.edges = [];
  }
  graph.edges.push(edge);
  if (graph.edge) {
    var attr = merge$1({}, graph.edge); // clone default attributes
    edge.attr = merge$1(attr, edge.attr); // merge attributes
  }
}

/**
 * Create an edge to a graph object
 *
 * @param {object} graph
 * @param {string | number | object} from
 * @param {string | number | object} to
 * @param {string} type
 * @param {object | null} attr
 * @returns {object} edge
 */
function createEdge(graph, from, to, type, attr) {
  var edge = {
    from: from,
    to: to,
    type: type
  };
  if (graph.edge) {
    edge.attr = merge$1({}, graph.edge); // clone default attributes
  }

  edge.attr = merge$1(edge.attr || {}, attr); // merge attributes

  // Move arrows attribute from attr to edge temporally created in
  // parseAttributeList().
  if (attr != null) {
    if (attr.hasOwnProperty("arrows") && attr["arrows"] != null) {
      edge["arrows"] = {
        to: {
          enabled: true,
          type: attr.arrows.type
        }
      };
      attr["arrows"] = null;
    }
  }
  return edge;
}

/**
 * Get next token in the current dot file.
 * The token and token type are available as token and tokenType
 */
function getToken() {
  tokenType = TOKENTYPE.NULL;
  token = "";

  // skip over whitespaces
  while (c === " " || c === "\t" || c === "\n" || c === "\r") {
    // space, tab, enter
    next();
  }
  do {
    var isComment = false;

    // skip comment
    if (c === "#") {
      // find the previous non-space character
      var i = index - 1;
      while (dot.charAt(i) === " " || dot.charAt(i) === "\t") {
        i--;
      }
      if (dot.charAt(i) === "\n" || dot.charAt(i) === "") {
        // the # is at the start of a line, this is indeed a line comment
        while (c != "" && c != "\n") {
          next();
        }
        isComment = true;
      }
    }
    if (c === "/" && nextPreview() === "/") {
      // skip line comment
      while (c != "" && c != "\n") {
        next();
      }
      isComment = true;
    }
    if (c === "/" && nextPreview() === "*") {
      // skip block comment
      while (c != "") {
        if (c === "*" && nextPreview() === "/") {
          // end of block comment found. skip these last two characters
          next();
          next();
          break;
        } else {
          next();
        }
      }
      isComment = true;
    }

    // skip over whitespaces
    while (c === " " || c === "\t" || c === "\n" || c === "\r") {
      // space, tab, enter
      next();
    }
  } while (isComment);

  // check for end of dot file
  if (c === "") {
    // token is still empty
    tokenType = TOKENTYPE.DELIMITER;
    return;
  }

  // check for delimiters consisting of 2 characters
  var c2 = c + nextPreview();
  if (DELIMITERS[c2]) {
    tokenType = TOKENTYPE.DELIMITER;
    token = c2;
    next();
    next();
    return;
  }

  // check for delimiters consisting of 1 character
  if (DELIMITERS[c]) {
    tokenType = TOKENTYPE.DELIMITER;
    token = c;
    next();
    return;
  }

  // check for an identifier (number or string)
  // TODO: more precise parsing of numbers/strings (and the port separator ':')
  if (isAlphaNumeric(c) || c === "-") {
    token += c;
    next();
    while (isAlphaNumeric(c)) {
      token += c;
      next();
    }
    if (token === "false") {
      token = false; // convert to boolean
    } else if (token === "true") {
      token = true; // convert to boolean
    } else if (!isNaN(Number(token))) {
      token = Number(token); // convert to number
    }

    tokenType = TOKENTYPE.IDENTIFIER;
    return;
  }

  // check for a string enclosed by double quotes
  if (c === '"') {
    next();
    while (c != "" && (c != '"' || c === '"' && nextPreview() === '"')) {
      if (c === '"') {
        // skip the escape character
        token += c;
        next();
      } else if (c === "\\" && nextPreview() === "n") {
        // Honor a newline escape sequence
        token += "\n";
        next();
      } else {
        token += c;
      }
      next();
    }
    if (c != '"') {
      throw newSyntaxError('End of string " expected');
    }
    next();
    tokenType = TOKENTYPE.IDENTIFIER;
    return;
  }

  // something unknown is found, wrong characters, a syntax error
  tokenType = TOKENTYPE.UNKNOWN;
  while (c != "") {
    token += c;
    next();
  }
  throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"');
}

/**
 * Parse a graph.
 *
 * @returns {object} graph
 */
function parseGraph() {
  var graph = {};
  first();
  getToken();

  // optional strict keyword
  if (token === "strict") {
    graph.strict = true;
    getToken();
  }

  // graph or digraph keyword
  if (token === "graph" || token === "digraph") {
    graph.type = token;
    getToken();
  }

  // optional graph id
  if (tokenType === TOKENTYPE.IDENTIFIER) {
    graph.id = token;
    getToken();
  }

  // open angle bracket
  if (token != "{") {
    throw newSyntaxError("Angle bracket { expected");
  }
  getToken();

  // statements
  parseStatements(graph);

  // close angle bracket
  if (token != "}") {
    throw newSyntaxError("Angle bracket } expected");
  }
  getToken();

  // end of file
  if (token !== "") {
    throw newSyntaxError("End of file expected");
  }
  getToken();

  // remove temporary default options
  delete graph.node;
  delete graph.edge;
  delete graph.graph;
  return graph;
}

/**
 * Parse a list with statements.
 *
 * @param {object} graph
 */
function parseStatements(graph) {
  while (token !== "" && token != "}") {
    parseStatement(graph);
    if (token === ";") {
      getToken();
    }
  }
}

/**
 * Parse a single statement. Can be a an attribute statement, node
 * statement, a series of node statements and edge statements, or a
 * parameter.
 *
 * @param {object} graph
 */
function parseStatement(graph) {
  // parse subgraph
  var subgraph = parseSubgraph(graph);
  if (subgraph) {
    // edge statements
    parseEdge(graph, subgraph);
    return;
  }

  // parse an attribute statement
  var attr = parseAttributeStatement(graph);
  if (attr) {
    return;
  }

  // parse node
  if (tokenType != TOKENTYPE.IDENTIFIER) {
    throw newSyntaxError("Identifier expected");
  }
  var id = token; // id can be a string or a number
  getToken();
  if (token === "=") {
    // id statement
    getToken();
    if (tokenType != TOKENTYPE.IDENTIFIER) {
      throw newSyntaxError("Identifier expected");
    }
    graph[id] = token;
    getToken();
    // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] "
  } else {
    parseNodeStatement(graph, id);
  }
}

/**
 * Parse a subgraph
 *
 * @param {object} graph    parent graph object
 * @returns {object | null} subgraph
 */
function parseSubgraph(graph) {
  var subgraph = null;

  // optional subgraph keyword
  if (token === "subgraph") {
    subgraph = {};
    subgraph.type = "subgraph";
    getToken();

    // optional graph id
    if (tokenType === TOKENTYPE.IDENTIFIER) {
      subgraph.id = token;
      getToken();
    }
  }

  // open angle bracket
  if (token === "{") {
    getToken();
    if (!subgraph) {
      subgraph = {};
    }
    subgraph.parent = graph;
    subgraph.node = graph.node;
    subgraph.edge = graph.edge;
    subgraph.graph = graph.graph;

    // statements
    parseStatements(subgraph);

    // close angle bracket
    if (token != "}") {
      throw newSyntaxError("Angle bracket } expected");
    }
    getToken();

    // remove temporary default options
    delete subgraph.node;
    delete subgraph.edge;
    delete subgraph.graph;
    delete subgraph.parent;

    // register at the parent graph
    if (!graph.subgraphs) {
      graph.subgraphs = [];
    }
    graph.subgraphs.push(subgraph);
  }
  return subgraph;
}

/**
 * parse an attribute statement like "node [shape=circle fontSize=16]".
 * Available keywords are 'node', 'edge', 'graph'.
 * The previous list with default attributes will be replaced
 *
 * @param {object} graph
 * @returns {string | null} keyword Returns the name of the parsed attribute
 *                                  (node, edge, graph), or null if nothing
 *                                  is parsed.
 */
function parseAttributeStatement(graph) {
  // attribute statements
  if (token === "node") {
    getToken();

    // node attributes
    graph.node = parseAttributeList();
    return "node";
  } else if (token === "edge") {
    getToken();

    // edge attributes
    graph.edge = parseAttributeList();
    return "edge";
  } else if (token === "graph") {
    getToken();

    // graph attributes
    graph.graph = parseAttributeList();
    return "graph";
  }
  return null;
}

/**
 * parse a node statement
 *
 * @param {object} graph
 * @param {string | number} id
 */
function parseNodeStatement(graph, id) {
  // node statement
  var node = {
    id: id
  };
  var attr = parseAttributeList();
  if (attr) {
    node.attr = attr;
  }
  addNode(graph, node);

  // edge statements
  parseEdge(graph, id);
}

/**
 * Parse an edge or a series of edges
 *
 * @param {object} graph
 * @param {string | number} from        Id of the from node
 */
function parseEdge(graph, from) {
  while (token === "->" || token === "--") {
    var to;
    var type = token;
    getToken();
    var subgraph = parseSubgraph(graph);
    if (subgraph) {
      to = subgraph;
    } else {
      if (tokenType != TOKENTYPE.IDENTIFIER) {
        throw newSyntaxError("Identifier or subgraph expected");
      }
      to = token;
      addNode(graph, {
        id: to
      });
      getToken();
    }

    // parse edge attributes
    var attr = parseAttributeList();

    // create edge
    var edge = createEdge(graph, from, to, type, attr);
    addEdge(graph, edge);
    from = to;
  }
}

/**
 * Parse a set with attributes,
 * for example [label="1.000", shape=solid]
 *
 * @returns {object | null} attr
 */
function parseAttributeList() {
  var i;
  var attr = null;

  // edge styles of dot and vis
  var edgeStyles = {
    dashed: true,
    solid: false,
    dotted: [1, 5]
  };

  /**
   * Define arrow types.
   * vis currently supports types defined in 'arrowTypes'.
   * Details of arrow shapes are described in
   * http://www.graphviz.org/content/arrow-shapes
   */
  var arrowTypes = {
    dot: "circle",
    box: "box",
    crow: "crow",
    curve: "curve",
    icurve: "inv_curve",
    normal: "triangle",
    inv: "inv_triangle",
    diamond: "diamond",
    tee: "bar",
    vee: "vee"
  };

  /**
   * 'attr_list' contains attributes for checking if some of them are affected
   * later. For instance, both of 'arrowhead' and 'dir' (edge style defined
   * in DOT) make changes to 'arrows' attribute in vis.
   */
  var attr_list = new Array();
  var attr_names = new Array(); // used for checking the case.

  // parse attributes
  while (token === "[") {
    getToken();
    attr = {};
    while (token !== "" && token != "]") {
      if (tokenType != TOKENTYPE.IDENTIFIER) {
        throw newSyntaxError("Attribute name expected");
      }
      var name = token;
      getToken();
      if (token != "=") {
        throw newSyntaxError("Equal sign = expected");
      }
      getToken();
      if (tokenType != TOKENTYPE.IDENTIFIER) {
        throw newSyntaxError("Attribute value expected");
      }
      var value = token;

      // convert from dot style to vis
      if (name === "style") {
        value = edgeStyles[value];
      }
      var arrowType;
      if (name === "arrowhead") {
        arrowType = arrowTypes[value];
        name = "arrows";
        value = {
          to: {
            enabled: true,
            type: arrowType
          }
        };
      }
      if (name === "arrowtail") {
        arrowType = arrowTypes[value];
        name = "arrows";
        value = {
          from: {
            enabled: true,
            type: arrowType
          }
        };
      }
      attr_list.push({
        attr: attr,
        name: name,
        value: value
      });
      attr_names.push(name);
      getToken();
      if (token == ",") {
        getToken();
      }
    }
    if (token != "]") {
      throw newSyntaxError("Bracket ] expected");
    }
    getToken();
  }

  /**
   * As explained in [1], graphviz has limitations for combination of
   * arrow[head|tail] and dir. If attribute list includes 'dir',
   * following cases just be supported.
   *   1. both or none + arrowhead, arrowtail
   *   2. forward + arrowhead (arrowtail is not affedted)
   *   3. back + arrowtail (arrowhead is not affected)
   * [1] https://www.graphviz.org/doc/info/attrs.html#h:undir_note
   */
  if (_includesInstanceProperty(attr_names).call(attr_names, "dir")) {
    var idx = {}; // get index of 'arrows' and 'dir'
    idx.arrows = {};
    for (i = 0; i < attr_list.length; i++) {
      if (attr_list[i].name === "arrows") {
        if (attr_list[i].value.to != null) {
          idx.arrows.to = i;
        } else if (attr_list[i].value.from != null) {
          idx.arrows.from = i;
        } else {
          throw newSyntaxError("Invalid value of arrows");
        }
      } else if (attr_list[i].name === "dir") {
        idx.dir = i;
      }
    }

    // first, add default arrow shape if it is not assigned to avoid error
    var dir_type = attr_list[idx.dir].value;
    if (!_includesInstanceProperty(attr_names).call(attr_names, "arrows")) {
      if (dir_type === "both") {
        attr_list.push({
          attr: attr_list[idx.dir].attr,
          name: "arrows",
          value: {
            to: {
              enabled: true
            }
          }
        });
        idx.arrows.to = attr_list.length - 1;
        attr_list.push({
          attr: attr_list[idx.dir].attr,
          name: "arrows",
          value: {
            from: {
              enabled: true
            }
          }
        });
        idx.arrows.from = attr_list.length - 1;
      } else if (dir_type === "forward") {
        attr_list.push({
          attr: attr_list[idx.dir].attr,
          name: "arrows",
          value: {
            to: {
              enabled: true
            }
          }
        });
        idx.arrows.to = attr_list.length - 1;
      } else if (dir_type === "back") {
        attr_list.push({
          attr: attr_list[idx.dir].attr,
          name: "arrows",
          value: {
            from: {
              enabled: true
            }
          }
        });
        idx.arrows.from = attr_list.length - 1;
      } else if (dir_type === "none") {
        attr_list.push({
          attr: attr_list[idx.dir].attr,
          name: "arrows",
          value: ""
        });
        idx.arrows.to = attr_list.length - 1;
      } else {
        throw newSyntaxError('Invalid dir type "' + dir_type + '"');
      }
    }
    var from_type;
    var to_type;
    // update 'arrows' attribute from 'dir'.
    if (dir_type === "both") {
      // both of shapes of 'from' and 'to' are given
      if (idx.arrows.to && idx.arrows.from) {
        to_type = attr_list[idx.arrows.to].value.to.type;
        from_type = attr_list[idx.arrows.from].value.from.type;
        attr_list[idx.arrows.to] = {
          attr: attr_list[idx.arrows.to].attr,
          name: attr_list[idx.arrows.to].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };
        _spliceInstanceProperty(attr_list).call(attr_list, idx.arrows.from, 1);

        // shape of 'to' is assigned and use default to 'from'
      } else if (idx.arrows.to) {
        to_type = attr_list[idx.arrows.to].value.to.type;
        from_type = "arrow";
        attr_list[idx.arrows.to] = {
          attr: attr_list[idx.arrows.to].attr,
          name: attr_list[idx.arrows.to].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };

        // only shape of 'from' is assigned and use default for 'to'
      } else if (idx.arrows.from) {
        to_type = "arrow";
        from_type = attr_list[idx.arrows.from].value.from.type;
        attr_list[idx.arrows.from] = {
          attr: attr_list[idx.arrows.from].attr,
          name: attr_list[idx.arrows.from].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };
      }
    } else if (dir_type === "back") {
      // given both of shapes, but use only 'from'
      if (idx.arrows.to && idx.arrows.from) {
        to_type = "";
        from_type = attr_list[idx.arrows.from].value.from.type;
        attr_list[idx.arrows.from] = {
          attr: attr_list[idx.arrows.from].attr,
          name: attr_list[idx.arrows.from].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };

        // given shape of 'to', but does not use it
      } else if (idx.arrows.to) {
        to_type = "";
        from_type = "arrow";
        idx.arrows.from = idx.arrows.to;
        attr_list[idx.arrows.from] = {
          attr: attr_list[idx.arrows.from].attr,
          name: attr_list[idx.arrows.from].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };

        // assign given 'from' shape
      } else if (idx.arrows.from) {
        to_type = "";
        from_type = attr_list[idx.arrows.from].value.from.type;
        attr_list[idx.arrows.to] = {
          attr: attr_list[idx.arrows.from].attr,
          name: attr_list[idx.arrows.from].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };
      }
      attr_list[idx.arrows.from] = {
        attr: attr_list[idx.arrows.from].attr,
        name: attr_list[idx.arrows.from].name,
        value: {
          from: {
            enabled: true,
            type: attr_list[idx.arrows.from].value.from.type
          }
        }
      };
    } else if (dir_type === "none") {
      var idx_arrow;
      if (idx.arrows.to) {
        idx_arrow = idx.arrows.to;
      } else {
        idx_arrow = idx.arrows.from;
      }
      attr_list[idx_arrow] = {
        attr: attr_list[idx_arrow].attr,
        name: attr_list[idx_arrow].name,
        value: ""
      };
    } else if (dir_type === "forward") {
      // given both of shapes, but use only 'to'
      if (idx.arrows.to && idx.arrows.from) {
        to_type = attr_list[idx.arrows.to].value.to.type;
        from_type = "";
        attr_list[idx.arrows.to] = {
          attr: attr_list[idx.arrows.to].attr,
          name: attr_list[idx.arrows.to].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };

        // assign given 'to' shape
      } else if (idx.arrows.to) {
        to_type = attr_list[idx.arrows.to].value.to.type;
        from_type = "";
        attr_list[idx.arrows.to] = {
          attr: attr_list[idx.arrows.to].attr,
          name: attr_list[idx.arrows.to].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };

        // given shape of 'from', but does not use it
      } else if (idx.arrows.from) {
        to_type = "arrow";
        from_type = "";
        idx.arrows.to = idx.arrows.from;
        attr_list[idx.arrows.to] = {
          attr: attr_list[idx.arrows.to].attr,
          name: attr_list[idx.arrows.to].name,
          value: {
            to: {
              enabled: true,
              type: to_type
            },
            from: {
              enabled: true,
              type: from_type
            }
          }
        };
      }
      attr_list[idx.arrows.to] = {
        attr: attr_list[idx.arrows.to].attr,
        name: attr_list[idx.arrows.to].name,
        value: {
          to: {
            enabled: true,
            type: attr_list[idx.arrows.to].value.to.type
          }
        }
      };
    } else {
      throw newSyntaxError('Invalid dir type "' + dir_type + '"');
    }

    // remove 'dir' attribute no need anymore
    _spliceInstanceProperty(attr_list).call(attr_list, idx.dir, 1);
  }

  // parse 'penwidth'
  var nof_attr_list;
  if (_includesInstanceProperty(attr_names).call(attr_names, "penwidth")) {
    var tmp_attr_list = [];
    nof_attr_list = attr_list.length;
    for (i = 0; i < nof_attr_list; i++) {
      // exclude 'width' from attr_list if 'penwidth' exists
      if (attr_list[i].name !== "width") {
        if (attr_list[i].name === "penwidth") {
          attr_list[i].name = "width";
        }
        tmp_attr_list.push(attr_list[i]);
      }
    }
    attr_list = tmp_attr_list;
  }
  nof_attr_list = attr_list.length;
  for (i = 0; i < nof_attr_list; i++) {
    setValue(attr_list[i].attr, attr_list[i].name, attr_list[i].value);
  }
  return attr;
}

/**
 * Create a syntax error with extra information on current token and index.
 *
 * @param {string} message
 * @returns {SyntaxError} err
 */
function newSyntaxError(message) {
  return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ")");
}

/**
 * Chop off text after a maximum length
 *
 * @param {string} text
 * @param {number} maxLength
 * @returns {string}
 */
function chop(text, maxLength) {
  return text.length <= maxLength ? text : text.substr(0, 27) + "...";
}

/**
 * Execute a function fn for each pair of elements in two arrays
 *
 * @param {Array | *} array1
 * @param {Array | *} array2
 * @param {Function} fn
 */
function forEach2(array1, array2, fn) {
  if (_Array$isArray(array1)) {
    _forEachInstanceProperty(array1).call(array1, function (elem1) {
      if (_Array$isArray(array2)) {
        _forEachInstanceProperty(array2).call(array2, function (elem2) {
          fn(elem1, elem2);
        });
      } else {
        fn(elem1, array2);
      }
    });
  } else {
    if (_Array$isArray(array2)) {
      _forEachInstanceProperty(array2).call(array2, function (elem2) {
        fn(array1, elem2);
      });
    } else {
      fn(array1, array2);
    }
  }
}

/**
 * Set a nested property on an object
 * When nested objects are missing, they will be created.
 * For example setProp({}, 'font.color', 'red') will return {font: {color: 'red'}}
 *
 * @param {object} object
 * @param {string} path   A dot separated string like 'font.color'
 * @param {*} value       Value for the property
 * @returns {object} Returns the original object, allows for chaining.
 */
function setProp(object, path, value) {
  var names = path.split(".");
  var prop = names.pop();

  // traverse over the nested objects
  var obj = object;
  for (var i = 0; i < names.length; i++) {
    var name = names[i];
    if (!(name in obj)) {
      obj[name] = {};
    }
    obj = obj[name];
  }

  // set the property value
  obj[prop] = value;
  return object;
}

/**
 * Convert an object with DOT attributes to their vis.js equivalents.
 *
 * @param {object} attr     Object with DOT attributes
 * @param {object} mapping
 * @returns {object}         Returns an object with vis.js attributes
 */
function convertAttr(attr, mapping) {
  var converted = {};
  for (var prop in attr) {
    if (attr.hasOwnProperty(prop)) {
      var visProp = mapping[prop];
      if (_Array$isArray(visProp)) {
        _forEachInstanceProperty(visProp).call(visProp, function (visPropI) {
          setProp(converted, visPropI, attr[prop]);
        });
      } else if (typeof visProp === "string") {
        setProp(converted, visProp, attr[prop]);
      } else {
        setProp(converted, prop, attr[prop]);
      }
    }
  }
  return converted;
}

/**
 * Convert a string containing a graph in DOT language into a map containing
 * with nodes and edges in the format of graph.
 *
 * @param {string} data         Text containing a graph in DOT-notation
 * @returns {object} graphData
 */
function DOTToGraph(data) {
  // parse the DOT file
  var dotData = parseDOT(data);
  var graphData = {
    nodes: [],
    edges: [],
    options: {}
  };

  // copy the nodes
  if (dotData.nodes) {
    var _context2;
    _forEachInstanceProperty(_context2 = dotData.nodes).call(_context2, function (dotNode) {
      var graphNode = {
        id: dotNode.id,
        label: String(dotNode.label || dotNode.id)
      };
      merge$1(graphNode, convertAttr(dotNode.attr, NODE_ATTR_MAPPING));
      if (graphNode.image) {
        graphNode.shape = "image";
      }
      graphData.nodes.push(graphNode);
    });
  }

  // copy the edges
  if (dotData.edges) {
    var _context3;
    /**
     * Convert an edge in DOT format to an edge with VisGraph format
     *
     * @param {object} dotEdge
     * @returns {object} graphEdge
     */
    var convertEdge = function convertEdge(dotEdge) {
      var graphEdge = {
        from: dotEdge.from,
        to: dotEdge.to
      };
      merge$1(graphEdge, convertAttr(dotEdge.attr, EDGE_ATTR_MAPPING));

      // Add arrows attribute to default styled arrow.
      // The reason why default style is not added in parseAttributeList() is
      // because only default is cleared before here.
      if (graphEdge.arrows == null && dotEdge.type === "->") {
        graphEdge.arrows = "to";
      }
      return graphEdge;
    };
    _forEachInstanceProperty(_context3 = dotData.edges).call(_context3, function (dotEdge) {
      var from, to;
      if (dotEdge.from instanceof Object) {
        from = dotEdge.from.nodes;
      } else {
        from = {
          id: dotEdge.from
        };
      }
      if (dotEdge.to instanceof Object) {
        to = dotEdge.to.nodes;
      } else {
        to = {
          id: dotEdge.to
        };
      }
      if (dotEdge.from instanceof Object && dotEdge.from.edges) {
        var _context4;
        _forEachInstanceProperty(_context4 = dotEdge.from.edges).call(_context4, function (subEdge) {
          var graphEdge = convertEdge(subEdge);
          graphData.edges.push(graphEdge);
        });
      }
      forEach2(from, to, function (from, to) {
        var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr);
        var graphEdge = convertEdge(subEdge);
        graphData.edges.push(graphEdge);
      });
      if (dotEdge.to instanceof Object && dotEdge.to.edges) {
        var _context5;
        _forEachInstanceProperty(_context5 = dotEdge.to.edges).call(_context5, function (subEdge) {
          var graphEdge = convertEdge(subEdge);
          graphData.edges.push(graphEdge);
        });
      }
    });
  }

  // copy the options
  if (dotData.attr) {
    graphData.options = dotData.attr;
  }
  return graphData;
}

/**
 * Convert Gephi to Vis.
 *
 * @param gephiJSON - The parsed JSON data in Gephi format.
 * @param optionsObj - Additional options.
 * @returns The converted data ready to be used in Vis.
 */
function parseGephi(gephiJSON, optionsObj) {
  var _context;
  var options = {
    edges: {
      inheritColor: false
    },
    nodes: {
      fixed: false,
      parseColor: false
    }
  };
  if (optionsObj != null) {
    if (optionsObj.fixed != null) {
      options.nodes.fixed = optionsObj.fixed;
    }
    if (optionsObj.parseColor != null) {
      options.nodes.parseColor = optionsObj.parseColor;
    }
    if (optionsObj.inheritColor != null) {
      options.edges.inheritColor = optionsObj.inheritColor;
    }
  }
  var gEdges = gephiJSON.edges;
  var vEdges = _mapInstanceProperty(gEdges).call(gEdges, function (gEdge) {
    var vEdge = {
      from: gEdge.source,
      id: gEdge.id,
      to: gEdge.target
    };
    if (gEdge.attributes != null) {
      vEdge.attributes = gEdge.attributes;
    }
    if (gEdge.label != null) {
      vEdge.label = gEdge.label;
    }
    if (gEdge.attributes != null && gEdge.attributes.title != null) {
      vEdge.title = gEdge.attributes.title;
    }
    if (gEdge.type === "Directed") {
      vEdge.arrows = "to";
    }
    // edge['value'] = gEdge.attributes != null ? gEdge.attributes.Weight : undefined;
    // edge['width'] = edge['value'] != null ? undefined : edgegEdge.size;
    if (gEdge.color && options.edges.inheritColor === false) {
      vEdge.color = gEdge.color;
    }
    return vEdge;
  });
  var vNodes = _mapInstanceProperty(_context = gephiJSON.nodes).call(_context, function (gNode) {
    var vNode = {
      id: gNode.id,
      fixed: options.nodes.fixed && gNode.x != null && gNode.y != null
    };
    if (gNode.attributes != null) {
      vNode.attributes = gNode.attributes;
    }
    if (gNode.label != null) {
      vNode.label = gNode.label;
    }
    if (gNode.size != null) {
      vNode.size = gNode.size;
    }
    if (gNode.attributes != null && gNode.attributes.title != null) {
      vNode.title = gNode.attributes.title;
    }
    if (gNode.title != null) {
      vNode.title = gNode.title;
    }
    if (gNode.x != null) {
      vNode.x = gNode.x;
    }
    if (gNode.y != null) {
      vNode.y = gNode.y;
    }
    if (gNode.color != null) {
      if (options.nodes.parseColor === true) {
        vNode.color = gNode.color;
      } else {
        vNode.color = {
          background: gNode.color,
          border: gNode.color,
          highlight: {
            background: gNode.color,
            border: gNode.color
          },
          hover: {
            background: gNode.color,
            border: gNode.color
          }
        };
      }
    }
    return vNode;
  });
  return {
    nodes: vNodes,
    edges: vEdges
  };
}

// English
var en = {
  addDescription: "Click in an empty space to place a new node.",
  addEdge: "Add Edge",
  addNode: "Add Node",
  back: "Back",
  close: "Close",
  createEdgeError: "Cannot link edges to a cluster.",
  del: "Delete selected",
  deleteClusterError: "Clusters cannot be deleted.",
  edgeDescription: "Click on a node and drag the edge to another node to connect them.",
  edit: "Edit",
  editClusterError: "Clusters cannot be edited.",
  editEdge: "Edit Edge",
  editEdgeDescription: "Click on the control points and drag them to a node to connect to it.",
  editNode: "Edit Node"
};
// German
var de = {
  addDescription: "Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",
  addEdge: "Kante hinzuf\xFCgen",
  addNode: "Knoten hinzuf\xFCgen",
  back: "Zur\xFCck",
  close: "Schließen",
  createEdgeError: "Es ist nicht m\xF6glich, Kanten mit Clustern zu verbinden.",
  del: "L\xF6sche Auswahl",
  deleteClusterError: "Cluster k\xF6nnen nicht gel\xF6scht werden.",
  edgeDescription: "Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",
  edit: "Editieren",
  editClusterError: "Cluster k\xF6nnen nicht editiert werden.",
  editEdge: "Kante editieren",
  editEdgeDescription: "Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",
  editNode: "Knoten editieren"
};
// Spanish
var es = {
  addDescription: "Haga clic en un lugar vac\xEDo para colocar un nuevo nodo.",
  addEdge: "A\xF1adir arista",
  addNode: "A\xF1adir nodo",
  back: "Atr\xE1s",
  close: "Cerrar",
  createEdgeError: "No se puede conectar una arista a un grupo.",
  del: "Eliminar selecci\xF3n",
  deleteClusterError: "No es posible eliminar grupos.",
  edgeDescription: "Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",
  edit: "Editar",
  editClusterError: "No es posible editar grupos.",
  editEdge: "Editar arista",
  editEdgeDescription: "Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",
  editNode: "Editar nodo"
};
//Italiano
var it = {
  addDescription: "Clicca per aggiungere un nuovo nodo",
  addEdge: "Aggiungi un vertice",
  addNode: "Aggiungi un nodo",
  back: "Indietro",
  close: "Chiudere",
  createEdgeError: "Non si possono collegare vertici ad un cluster",
  del: "Cancella la selezione",
  deleteClusterError: "I cluster non possono essere cancellati",
  edgeDescription: "Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",
  edit: "Modifica",
  editClusterError: "I clusters non possono essere modificati.",
  editEdge: "Modifica il vertice",
  editEdgeDescription: "Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",
  editNode: "Modifica il nodo"
};
// Dutch
var nl = {
  addDescription: "Klik op een leeg gebied om een nieuwe node te maken.",
  addEdge: "Link toevoegen",
  addNode: "Node toevoegen",
  back: "Terug",
  close: "Sluiten",
  createEdgeError: "Kan geen link maken naar een cluster.",
  del: "Selectie verwijderen",
  deleteClusterError: "Clusters kunnen niet worden verwijderd.",
  edgeDescription: "Klik op een node en sleep de link naar een andere node om ze te verbinden.",
  edit: "Wijzigen",
  editClusterError: "Clusters kunnen niet worden aangepast.",
  editEdge: "Link wijzigen",
  editEdgeDescription: "Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",
  editNode: "Node wijzigen"
};
// Portuguese Brazil
var pt = {
  addDescription: "Clique em um espaço em branco para adicionar um novo nó",
  addEdge: "Adicionar aresta",
  addNode: "Adicionar nó",
  back: "Voltar",
  close: "Fechar",
  createEdgeError: "Não foi possível linkar arestas a um cluster.",
  del: "Remover selecionado",
  deleteClusterError: "Clusters não puderam ser removidos.",
  edgeDescription: "Clique em um nó e arraste a aresta até outro nó para conectá-los",
  edit: "Editar",
  editClusterError: "Clusters não puderam ser editados.",
  editEdge: "Editar aresta",
  editEdgeDescription: "Clique nos pontos de controle e os arraste para um nó para conectá-los",
  editNode: "Editar nó"
};
// Russian
var ru = {
  addDescription: "Кликните в свободное место, чтобы добавить новый узел.",
  addEdge: "Добавить ребро",
  addNode: "Добавить узел",
  back: "Назад",
  close: "Закрывать",
  createEdgeError: "Невозможно соединить ребра в кластер.",
  del: "Удалить выбранное",
  deleteClusterError: "Кластеры не могут быть удалены",
  edgeDescription: "Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",
  edit: "Редактировать",
  editClusterError: "Кластеры недоступны для редактирования.",
  editEdge: "Редактировать ребро",
  editEdgeDescription: "Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",
  editNode: "Редактировать узел"
};
// Chinese
var cn = {
  addDescription: "单击空白处放置新节点。",
  addEdge: "添加连接线",
  addNode: "添加节点",
  back: "返回",
  close: "關閉",
  createEdgeError: "无法将连接线连接到群集。",
  del: "删除选定",
  deleteClusterError: "无法删除群集。",
  edgeDescription: "单击某个节点并将该连接线拖动到另一个节点以连接它们。",
  edit: "编辑",
  editClusterError: "无法编辑群集。",
  editEdge: "编辑连接线",
  editEdgeDescription: "单击控制节点并将它们拖到节点上连接。",
  editNode: "编辑节点"
};
// Ukrainian
var uk = {
  addDescription: "Kлікніть на вільне місце, щоб додати новий вузол.",
  addEdge: "Додати край",
  addNode: "Додати вузол",
  back: "Назад",
  close: "Закрити",
  createEdgeError: "Не можливо об'єднати краї в групу.",
  del: "Видалити обране",
  deleteClusterError: "Групи не можуть бути видалені.",
  edgeDescription: "Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з'єднати.",
  edit: "Редагувати",
  editClusterError: "Групи недоступні для редагування.",
  editEdge: "Редагувати край",
  editEdgeDescription: "Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.",
  editNode: "Редагувати вузол"
};
// French
var fr = {
  addDescription: "Cliquez dans un endroit vide pour placer un nœud.",
  addEdge: "Ajouter un lien",
  addNode: "Ajouter un nœud",
  back: "Retour",
  close: "Fermer",
  createEdgeError: "Impossible de créer un lien vers un cluster.",
  del: "Effacer la sélection",
  deleteClusterError: "Les clusters ne peuvent pas être effacés.",
  edgeDescription: "Cliquez sur un nœud et glissez le lien vers un autre nœud pour les connecter.",
  edit: "Éditer",
  editClusterError: "Les clusters ne peuvent pas être édités.",
  editEdge: "Éditer le lien",
  editEdgeDescription: "Cliquez sur les points de contrôle et glissez-les pour connecter un nœud.",
  editNode: "Éditer le nœud"
};
// Czech
var cs = {
  addDescription: "Kluknutím do prázdného prostoru můžete přidat nový vrchol.",
  addEdge: "Přidat hranu",
  addNode: "Přidat vrchol",
  back: "Zpět",
  close: "Zavřít",
  createEdgeError: "Nelze připojit hranu ke shluku.",
  del: "Smazat výběr",
  deleteClusterError: "Nelze mazat shluky.",
  edgeDescription: "Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.",
  edit: "Upravit",
  editClusterError: "Nelze upravovat shluky.",
  editEdge: "Upravit hranu",
  editEdgeDescription: "Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.",
  editNode: "Upravit vrchol"
};

var locales = /*#__PURE__*/Object.freeze({
	__proto__: null,
	cn: cn,
	cs: cs,
	de: de,
	en: en,
	es: es,
	fr: fr,
	it: it,
	nl: nl,
	pt: pt,
	ru: ru,
	uk: uk
});

/**
 * Normalizes language code into the format used internally.
 *
 * @param locales - All the available locales.
 * @param rawCode - The original code as supplied by the user.
 * @returns Language code in the format language-COUNTRY or language, eventually
 * fallbacks to en.
 */
function normalizeLanguageCode(locales, rawCode) {
  try {
    var _rawCode$split = rawCode.split(/[-_ /]/, 2),
      _rawCode$split2 = _slicedToArray(_rawCode$split, 2),
      rawLanguage = _rawCode$split2[0],
      rawCountry = _rawCode$split2[1];
    var language = rawLanguage != null ? rawLanguage.toLowerCase() : null;
    var country = rawCountry != null ? rawCountry.toUpperCase() : null;
    if (language && country) {
      var code = language + "-" + country;
      if (Object.prototype.hasOwnProperty.call(locales, code)) {
        return code;
      } else {
        var _context;
        console.warn(_concatInstanceProperty(_context = "Unknown variant ".concat(country, " of language ")).call(_context, language, "."));
      }
    }
    if (language) {
      var _code = language;
      if (Object.prototype.hasOwnProperty.call(locales, _code)) {
        return _code;
      } else {
        console.warn("Unknown language ".concat(language));
      }
    }
    console.warn("Unknown locale ".concat(rawCode, ", falling back to English."));
    return "en";
  } catch (error) {
    console.error(error);
    console.warn("Unexpected error while normalizing locale ".concat(rawCode, ", falling back to English."));
    return "en";
  }
}

/**
 * Associates a canvas to a given image, containing a number of renderings
 * of the image at various sizes.
 *
 * This technique is known as 'mipmapping'.
 *
 * NOTE: Images can also be of type 'data:svg+xml`. This code also works
 *       for svg, but the mipmapping may not be necessary.
 *
 * @param {Image} image
 */
var CachedImage = /*#__PURE__*/function () {
  /**
   * @ignore
   */
  function CachedImage() {
    _classCallCheck(this, CachedImage);
    this.NUM_ITERATIONS = 4; // Number of items in the coordinates array

    this.image = new Image();
    this.canvas = document.createElement("canvas");
  }

  /**
   * Called when the image has been successfully loaded.
   */
  _createClass(CachedImage, [{
    key: "init",
    value: function init() {
      if (this.initialized()) return;
      this.src = this.image.src; // For same interface with Image
      var w = this.image.width;
      var h = this.image.height;

      // Ease external access
      this.width = w;
      this.height = h;
      var h2 = Math.floor(h / 2);
      var h4 = Math.floor(h / 4);
      var h8 = Math.floor(h / 8);
      var h16 = Math.floor(h / 16);
      var w2 = Math.floor(w / 2);
      var w4 = Math.floor(w / 4);
      var w8 = Math.floor(w / 8);
      var w16 = Math.floor(w / 16);

      // Make canvas as small as possible
      this.canvas.width = 3 * w4;
      this.canvas.height = h2;

      // Coordinates and sizes of images contained in the canvas
      // Values per row:  [top x, left y, width, height]

      this.coordinates = [[0, 0, w2, h2], [w2, 0, w4, h4], [w2, h4, w8, h8], [5 * w8, h4, w16, h16]];
      this._fillMipMap();
    }

    /**
     * @returns {boolean} true if init() has been called, false otherwise.
     */
  }, {
    key: "initialized",
    value: function initialized() {
      return this.coordinates !== undefined;
    }

    /**
     * Redraw main image in various sizes to the context.
     *
     * The rationale behind this is to reduce artefacts due to interpolation
     * at differing zoom levels.
     *
     * Source: http://stackoverflow.com/q/18761404/1223531
     *
     * This methods takes the resizing out of the drawing loop, in order to
     * reduce performance overhead.
     *
     * TODO: The code assumes that a 2D context can always be gotten. This is
     *       not necessarily true! OTOH, if not true then usage of this class
     *       is senseless.
     *
     * @private
     */
  }, {
    key: "_fillMipMap",
    value: function _fillMipMap() {
      var ctx = this.canvas.getContext("2d");

      // First zoom-level comes from the image
      var to = this.coordinates[0];
      ctx.drawImage(this.image, to[0], to[1], to[2], to[3]);

      // The rest are copy actions internal to the canvas/context
      for (var iterations = 1; iterations < this.NUM_ITERATIONS; iterations++) {
        var from = this.coordinates[iterations - 1];
        var _to = this.coordinates[iterations];
        ctx.drawImage(this.canvas, from[0], from[1], from[2], from[3], _to[0], _to[1], _to[2], _to[3]);
      }
    }

    /**
     * Draw the image, using the mipmap if necessary.
     *
     * MipMap is only used if param factor > 2; otherwise, original bitmap
     * is resized. This is also used to skip mipmap usage, e.g. by setting factor = 1
     *
     * Credits to 'Alex de Mulder' for original implementation.
     *
     * @param {CanvasRenderingContext2D} ctx  context on which to draw zoomed image
     * @param {Float} factor scale factor at which to draw
     * @param {number} left
     * @param {number} top
     * @param {number} width
     * @param {number} height
     */
  }, {
    key: "drawImageAtPosition",
    value: function drawImageAtPosition(ctx, factor, left, top, width, height) {
      if (!this.initialized()) return; //can't draw image yet not intialized

      if (factor > 2) {
        // Determine which zoomed image to use
        factor *= 0.5;
        var iterations = 0;
        while (factor > 2 && iterations < this.NUM_ITERATIONS) {
          factor *= 0.5;
          iterations += 1;
        }
        if (iterations >= this.NUM_ITERATIONS) {
          iterations = this.NUM_ITERATIONS - 1;
        }
        //console.log("iterations: " + iterations);

        var from = this.coordinates[iterations];
        ctx.drawImage(this.canvas, from[0], from[1], from[2], from[3], left, top, width, height);
      } else {
        // Draw image directly
        ctx.drawImage(this.image, left, top, width, height);
      }
    }
  }]);
  return CachedImage;
}();

/**
 * This callback is a callback that accepts an Image.
 *
 * @callback ImageCallback
 * @param {Image} image
 */

/**
 * This class loads images and keeps them stored.
 *
 * @param {ImageCallback} callback
 */
var Images = /*#__PURE__*/function () {
  /**
   * @param {ImageCallback} callback
   */
  function Images(callback) {
    _classCallCheck(this, Images);
    this.images = {};
    this.imageBroken = {};
    this.callback = callback;
  }

  /**
   * @param {string} url                      The original Url that failed to load, if the broken image is successfully loaded it will be added to the cache using this Url as the key so that subsequent requests for this Url will return the broken image
   * @param {string} brokenUrl                Url the broken image to try and load
   * @param {Image} imageToLoadBrokenUrlOn   The image object
   */
  _createClass(Images, [{
    key: "_tryloadBrokenUrl",
    value: function _tryloadBrokenUrl(url, brokenUrl, imageToLoadBrokenUrlOn) {
      //If these parameters aren't specified then exit the function because nothing constructive can be done
      if (url === undefined || imageToLoadBrokenUrlOn === undefined) return;
      if (brokenUrl === undefined) {
        console.warn("No broken url image defined");
        return;
      }

      //Clear the old subscription to the error event and put a new in place that only handle errors in loading the brokenImageUrl
      imageToLoadBrokenUrlOn.image.onerror = function () {
        console.error("Could not load brokenImage:", brokenUrl);
        // cache item will contain empty image, this should be OK for default
      };

      //Set the source of the image to the brokenUrl, this is actually what kicks off the loading of the broken image
      imageToLoadBrokenUrlOn.image.src = brokenUrl;
    }

    /**
     *
     * @param {vis.Image} imageToRedrawWith
     * @private
     */
  }, {
    key: "_redrawWithImage",
    value: function _redrawWithImage(imageToRedrawWith) {
      if (this.callback) {
        this.callback(imageToRedrawWith);
      }
    }

    /**
     * @param {string} url          Url of the image
     * @param {string} brokenUrl    Url of an image to use if the url image is not found
     * @returns {Image} img          The image object
     */
  }, {
    key: "load",
    value: function load(url, brokenUrl) {
      var _this = this;
      //Try and get the image from the cache, if successful then return the cached image
      var cachedImage = this.images[url];
      if (cachedImage) return cachedImage;

      //Create a new image
      var img = new CachedImage();

      // Need to add to cache here, otherwise final return will spawn different copies of the same image,
      // Also, there will be multiple loads of the same image.
      this.images[url] = img;

      //Subscribe to the event that is raised if the image loads successfully
      img.image.onload = function () {
        // Properly init the cached item and then request a redraw
        _this._fixImageCoordinates(img.image);
        img.init();
        _this._redrawWithImage(img);
      };

      //Subscribe to the event that is raised if the image fails to load
      img.image.onerror = function () {
        console.error("Could not load image:", url);
        //Try and load the image specified by the brokenUrl using
        _this._tryloadBrokenUrl(url, brokenUrl, img);
      };

      //Set the source of the image to the url, this is what actually kicks off the loading of the image
      img.image.src = url;

      //Return the new image
      return img;
    }

    /**
     * IE11 fix -- thanks dponch!
     *
     * Local helper function
     *
     * @param {vis.Image} imageToCache
     * @private
     */
  }, {
    key: "_fixImageCoordinates",
    value: function _fixImageCoordinates(imageToCache) {
      if (imageToCache.width === 0) {
        document.body.appendChild(imageToCache);
        imageToCache.width = imageToCache.offsetWidth;
        imageToCache.height = imageToCache.offsetHeight;
        document.body.removeChild(imageToCache);
      }
    }
  }]);
  return Images;
}();

var mapExports = {};
var map$2 = {
  get exports(){ return mapExports; },
  set exports(v){ mapExports = v; },
};

var internalMetadataExports = {};
var internalMetadata = {
  get exports(){ return internalMetadataExports; },
  set exports(v){ internalMetadataExports = v; },
};

// FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
var fails$8 = fails$w;

var arrayBufferNonExtensible = fails$8(function () {
  if (typeof ArrayBuffer == 'function') {
    var buffer = new ArrayBuffer(8);
    // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
    if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
  }
});

var fails$7 = fails$w;
var isObject$6 = isObject$j;
var classof$2 = classofRaw$2;
var ARRAY_BUFFER_NON_EXTENSIBLE = arrayBufferNonExtensible;

// eslint-disable-next-line es/no-object-isextensible -- safe
var $isExtensible = Object.isExtensible;
var FAILS_ON_PRIMITIVES$1 = fails$7(function () { $isExtensible(1); });

// `Object.isExtensible` method
// https://tc39.es/ecma262/#sec-object.isextensible
var objectIsExtensible = (FAILS_ON_PRIMITIVES$1 || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {
  if (!isObject$6(it)) return false;
  if (ARRAY_BUFFER_NON_EXTENSIBLE && classof$2(it) == 'ArrayBuffer') return false;
  return $isExtensible ? $isExtensible(it) : true;
} : $isExtensible;

var fails$6 = fails$w;

var freezing = !fails$6(function () {
  // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing
  return Object.isExtensible(Object.preventExtensions({}));
});

var $$d = _export;
var uncurryThis$4 = functionUncurryThis;
var hiddenKeys = hiddenKeys$6;
var isObject$5 = isObject$j;
var hasOwn$3 = hasOwnProperty_1;
var defineProperty$1 = objectDefineProperty.f;
var getOwnPropertyNamesModule = objectGetOwnPropertyNames;
var getOwnPropertyNamesExternalModule = objectGetOwnPropertyNamesExternal;
var isExtensible$1 = objectIsExtensible;
var uid = uid$4;
var FREEZING$1 = freezing;

var REQUIRED = false;
var METADATA = uid('meta');
var id$1 = 0;

var setMetadata = function (it) {
  defineProperty$1(it, METADATA, { value: {
    objectID: 'O' + id$1++, // object ID
    weakData: {}          // weak collections IDs
  } });
};

var fastKey$1 = function (it, create) {
  // return a primitive with prefix
  if (!isObject$5(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
  if (!hasOwn$3(it, METADATA)) {
    // can't set metadata to uncaught frozen object
    if (!isExtensible$1(it)) return 'F';
    // not necessary to add metadata
    if (!create) return 'E';
    // add missing metadata
    setMetadata(it);
  // return object ID
  } return it[METADATA].objectID;
};

var getWeakData$1 = function (it, create) {
  if (!hasOwn$3(it, METADATA)) {
    // can't set metadata to uncaught frozen object
    if (!isExtensible$1(it)) return true;
    // not necessary to add metadata
    if (!create) return false;
    // add missing metadata
    setMetadata(it);
  // return the store of weak collections IDs
  } return it[METADATA].weakData;
};

// add metadata on freeze-family methods calling
var onFreeze = function (it) {
  if (FREEZING$1 && REQUIRED && isExtensible$1(it) && !hasOwn$3(it, METADATA)) setMetadata(it);
  return it;
};

var enable = function () {
  meta$1.enable = function () { /* empty */ };
  REQUIRED = true;
  var getOwnPropertyNames = getOwnPropertyNamesModule.f;
  var splice = uncurryThis$4([].splice);
  var test = {};
  test[METADATA] = 1;

  // prevent exposing of metadata key
  if (getOwnPropertyNames(test).length) {
    getOwnPropertyNamesModule.f = function (it) {
      var result = getOwnPropertyNames(it);
      for (var i = 0, length = result.length; i < length; i++) {
        if (result[i] === METADATA) {
          splice(result, i, 1);
          break;
        }
      } return result;
    };

    $$d({ target: 'Object', stat: true, forced: true }, {
      getOwnPropertyNames: getOwnPropertyNamesExternalModule.f
    });
  }
};

var meta$1 = internalMetadata.exports = {
  enable: enable,
  fastKey: fastKey$1,
  getWeakData: getWeakData$1,
  onFreeze: onFreeze
};

hiddenKeys[METADATA] = true;

var bind$6 = functionBindContext;
var call$1 = functionCall;
var anObject$3 = anObject$d;
var tryToString$1 = tryToString$6;
var isArrayIteratorMethod = isArrayIteratorMethod$2;
var lengthOfArrayLike$2 = lengthOfArrayLike$b;
var isPrototypeOf$6 = objectIsPrototypeOf;
var getIterator = getIterator$2;
var getIteratorMethod = getIteratorMethod$9;
var iteratorClose = iteratorClose$2;

var $TypeError$3 = TypeError;

var Result = function (stopped, result) {
  this.stopped = stopped;
  this.result = result;
};

var ResultPrototype = Result.prototype;

var iterate$3 = function (iterable, unboundFunction, options) {
  var that = options && options.that;
  var AS_ENTRIES = !!(options && options.AS_ENTRIES);
  var IS_RECORD = !!(options && options.IS_RECORD);
  var IS_ITERATOR = !!(options && options.IS_ITERATOR);
  var INTERRUPTED = !!(options && options.INTERRUPTED);
  var fn = bind$6(unboundFunction, that);
  var iterator, iterFn, index, length, result, next, step;

  var stop = function (condition) {
    if (iterator) iteratorClose(iterator, 'normal', condition);
    return new Result(true, condition);
  };

  var callFn = function (value) {
    if (AS_ENTRIES) {
      anObject$3(value);
      return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
    } return INTERRUPTED ? fn(value, stop) : fn(value);
  };

  if (IS_RECORD) {
    iterator = iterable.iterator;
  } else if (IS_ITERATOR) {
    iterator = iterable;
  } else {
    iterFn = getIteratorMethod(iterable);
    if (!iterFn) throw $TypeError$3(tryToString$1(iterable) + ' is not iterable');
    // optimisation for array iterators
    if (isArrayIteratorMethod(iterFn)) {
      for (index = 0, length = lengthOfArrayLike$2(iterable); length > index; index++) {
        result = callFn(iterable[index]);
        if (result && isPrototypeOf$6(ResultPrototype, result)) return result;
      } return new Result(false);
    }
    iterator = getIterator(iterable, iterFn);
  }

  next = IS_RECORD ? iterable.next : iterator.next;
  while (!(step = call$1(next, iterator)).done) {
    try {
      result = callFn(step.value);
    } catch (error) {
      iteratorClose(iterator, 'throw', error);
    }
    if (typeof result == 'object' && result && isPrototypeOf$6(ResultPrototype, result)) return result;
  } return new Result(false);
};

var isPrototypeOf$5 = objectIsPrototypeOf;

var $TypeError$2 = TypeError;

var anInstance$3 = function (it, Prototype) {
  if (isPrototypeOf$5(Prototype, it)) return it;
  throw $TypeError$2('Incorrect invocation');
};

var $$c = _export;
var global$4 = global$l;
var InternalMetadataModule$1 = internalMetadataExports;
var fails$5 = fails$w;
var createNonEnumerableProperty = createNonEnumerableProperty$6;
var iterate$2 = iterate$3;
var anInstance$2 = anInstance$3;
var isCallable = isCallable$i;
var isObject$4 = isObject$j;
var setToStringTag = setToStringTag$6;
var defineProperty = objectDefineProperty.f;
var forEach = arrayIteration.forEach;
var DESCRIPTORS$2 = descriptors;
var InternalStateModule$2 = internalState;

var setInternalState$2 = InternalStateModule$2.set;
var internalStateGetterFor$2 = InternalStateModule$2.getterFor;

var collection$3 = function (CONSTRUCTOR_NAME, wrapper, common) {
  var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
  var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
  var ADDER = IS_MAP ? 'set' : 'add';
  var NativeConstructor = global$4[CONSTRUCTOR_NAME];
  var NativePrototype = NativeConstructor && NativeConstructor.prototype;
  var exported = {};
  var Constructor;

  if (!DESCRIPTORS$2 || !isCallable(NativeConstructor)
    || !(IS_WEAK || NativePrototype.forEach && !fails$5(function () { new NativeConstructor().entries().next(); }))
  ) {
    // create collection constructor
    Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
    InternalMetadataModule$1.enable();
  } else {
    Constructor = wrapper(function (target, iterable) {
      setInternalState$2(anInstance$2(target, Prototype), {
        type: CONSTRUCTOR_NAME,
        collection: new NativeConstructor()
      });
      if (iterable != undefined) iterate$2(iterable, target[ADDER], { that: target, AS_ENTRIES: IS_MAP });
    });

    var Prototype = Constructor.prototype;

    var getInternalState = internalStateGetterFor$2(CONSTRUCTOR_NAME);

    forEach(['add', 'clear', 'delete', 'forEach', 'get', 'has', 'set', 'keys', 'values', 'entries'], function (KEY) {
      var IS_ADDER = KEY == 'add' || KEY == 'set';
      if (KEY in NativePrototype && !(IS_WEAK && KEY == 'clear')) {
        createNonEnumerableProperty(Prototype, KEY, function (a, b) {
          var collection = getInternalState(this).collection;
          if (!IS_ADDER && IS_WEAK && !isObject$4(a)) return KEY == 'get' ? undefined : false;
          var result = collection[KEY](a === 0 ? 0 : a, b);
          return IS_ADDER ? this : result;
        });
      }
    });

    IS_WEAK || defineProperty(Prototype, 'size', {
      configurable: true,
      get: function () {
        return getInternalState(this).collection.size;
      }
    });
  }

  setToStringTag(Constructor, CONSTRUCTOR_NAME, false, true);

  exported[CONSTRUCTOR_NAME] = Constructor;
  $$c({ global: true, forced: true }, exported);

  if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);

  return Constructor;
};

var defineBuiltIn = defineBuiltIn$5;

var defineBuiltIns$3 = function (target, src, options) {
  for (var key in src) {
    if (options && options.unsafe && target[key]) target[key] = src[key];
    else defineBuiltIn(target, key, src[key], options);
  } return target;
};

var getBuiltIn$1 = getBuiltIn$c;
var defineBuiltInAccessor$1 = defineBuiltInAccessor$3;
var wellKnownSymbol = wellKnownSymbol$l;
var DESCRIPTORS$1 = descriptors;

var SPECIES = wellKnownSymbol('species');

var setSpecies$1 = function (CONSTRUCTOR_NAME) {
  var Constructor = getBuiltIn$1(CONSTRUCTOR_NAME);

  if (DESCRIPTORS$1 && Constructor && !Constructor[SPECIES]) {
    defineBuiltInAccessor$1(Constructor, SPECIES, {
      configurable: true,
      get: function () { return this; }
    });
  }
};

var create$5 = objectCreate;
var defineBuiltInAccessor = defineBuiltInAccessor$3;
var defineBuiltIns$2 = defineBuiltIns$3;
var bind$5 = functionBindContext;
var anInstance$1 = anInstance$3;
var isNullOrUndefined$1 = isNullOrUndefined$5;
var iterate$1 = iterate$3;
var defineIterator = iteratorDefine;
var createIterResultObject = createIterResultObject$3;
var setSpecies = setSpecies$1;
var DESCRIPTORS = descriptors;
var fastKey = internalMetadataExports.fastKey;
var InternalStateModule$1 = internalState;

var setInternalState$1 = InternalStateModule$1.set;
var internalStateGetterFor$1 = InternalStateModule$1.getterFor;

var collectionStrong$2 = {
  getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
    var Constructor = wrapper(function (that, iterable) {
      anInstance$1(that, Prototype);
      setInternalState$1(that, {
        type: CONSTRUCTOR_NAME,
        index: create$5(null),
        first: undefined,
        last: undefined,
        size: 0
      });
      if (!DESCRIPTORS) that.size = 0;
      if (!isNullOrUndefined$1(iterable)) iterate$1(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
    });

    var Prototype = Constructor.prototype;

    var getInternalState = internalStateGetterFor$1(CONSTRUCTOR_NAME);

    var define = function (that, key, value) {
      var state = getInternalState(that);
      var entry = getEntry(that, key);
      var previous, index;
      // change existing entry
      if (entry) {
        entry.value = value;
      // create new entry
      } else {
        state.last = entry = {
          index: index = fastKey(key, true),
          key: key,
          value: value,
          previous: previous = state.last,
          next: undefined,
          removed: false
        };
        if (!state.first) state.first = entry;
        if (previous) previous.next = entry;
        if (DESCRIPTORS) state.size++;
        else that.size++;
        // add to index
        if (index !== 'F') state.index[index] = entry;
      } return that;
    };

    var getEntry = function (that, key) {
      var state = getInternalState(that);
      // fast case
      var index = fastKey(key);
      var entry;
      if (index !== 'F') return state.index[index];
      // frozen object case
      for (entry = state.first; entry; entry = entry.next) {
        if (entry.key == key) return entry;
      }
    };

    defineBuiltIns$2(Prototype, {
      // `{ Map, Set }.prototype.clear()` methods
      // https://tc39.es/ecma262/#sec-map.prototype.clear
      // https://tc39.es/ecma262/#sec-set.prototype.clear
      clear: function clear() {
        var that = this;
        var state = getInternalState(that);
        var data = state.index;
        var entry = state.first;
        while (entry) {
          entry.removed = true;
          if (entry.previous) entry.previous = entry.previous.next = undefined;
          delete data[entry.index];
          entry = entry.next;
        }
        state.first = state.last = undefined;
        if (DESCRIPTORS) state.size = 0;
        else that.size = 0;
      },
      // `{ Map, Set }.prototype.delete(key)` methods
      // https://tc39.es/ecma262/#sec-map.prototype.delete
      // https://tc39.es/ecma262/#sec-set.prototype.delete
      'delete': function (key) {
        var that = this;
        var state = getInternalState(that);
        var entry = getEntry(that, key);
        if (entry) {
          var next = entry.next;
          var prev = entry.previous;
          delete state.index[entry.index];
          entry.removed = true;
          if (prev) prev.next = next;
          if (next) next.previous = prev;
          if (state.first == entry) state.first = next;
          if (state.last == entry) state.last = prev;
          if (DESCRIPTORS) state.size--;
          else that.size--;
        } return !!entry;
      },
      // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
      // https://tc39.es/ecma262/#sec-map.prototype.foreach
      // https://tc39.es/ecma262/#sec-set.prototype.foreach
      forEach: function forEach(callbackfn /* , that = undefined */) {
        var state = getInternalState(this);
        var boundFunction = bind$5(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
        var entry;
        while (entry = entry ? entry.next : state.first) {
          boundFunction(entry.value, entry.key, this);
          // revert to the last existing entry
          while (entry && entry.removed) entry = entry.previous;
        }
      },
      // `{ Map, Set}.prototype.has(key)` methods
      // https://tc39.es/ecma262/#sec-map.prototype.has
      // https://tc39.es/ecma262/#sec-set.prototype.has
      has: function has(key) {
        return !!getEntry(this, key);
      }
    });

    defineBuiltIns$2(Prototype, IS_MAP ? {
      // `Map.prototype.get(key)` method
      // https://tc39.es/ecma262/#sec-map.prototype.get
      get: function get(key) {
        var entry = getEntry(this, key);
        return entry && entry.value;
      },
      // `Map.prototype.set(key, value)` method
      // https://tc39.es/ecma262/#sec-map.prototype.set
      set: function set(key, value) {
        return define(this, key === 0 ? 0 : key, value);
      }
    } : {
      // `Set.prototype.add(value)` method
      // https://tc39.es/ecma262/#sec-set.prototype.add
      add: function add(value) {
        return define(this, value = value === 0 ? 0 : value, value);
      }
    });
    if (DESCRIPTORS) defineBuiltInAccessor(Prototype, 'size', {
      configurable: true,
      get: function () {
        return getInternalState(this).size;
      }
    });
    return Constructor;
  },
  setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
    var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
    var getInternalCollectionState = internalStateGetterFor$1(CONSTRUCTOR_NAME);
    var getInternalIteratorState = internalStateGetterFor$1(ITERATOR_NAME);
    // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
    // https://tc39.es/ecma262/#sec-map.prototype.entries
    // https://tc39.es/ecma262/#sec-map.prototype.keys
    // https://tc39.es/ecma262/#sec-map.prototype.values
    // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
    // https://tc39.es/ecma262/#sec-set.prototype.entries
    // https://tc39.es/ecma262/#sec-set.prototype.keys
    // https://tc39.es/ecma262/#sec-set.prototype.values
    // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
    defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
      setInternalState$1(this, {
        type: ITERATOR_NAME,
        target: iterated,
        state: getInternalCollectionState(iterated),
        kind: kind,
        last: undefined
      });
    }, function () {
      var state = getInternalIteratorState(this);
      var kind = state.kind;
      var entry = state.last;
      // revert to the last existing entry
      while (entry && entry.removed) entry = entry.previous;
      // get next entry
      if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
        // or finish the iteration
        state.target = undefined;
        return createIterResultObject(undefined, true);
      }
      // return step by kind
      if (kind == 'keys') return createIterResultObject(entry.key, false);
      if (kind == 'values') return createIterResultObject(entry.value, false);
      return createIterResultObject([entry.key, entry.value], false);
    }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);

    // `{ Map, Set }.prototype[@@species]` accessors
    // https://tc39.es/ecma262/#sec-get-map-@@species
    // https://tc39.es/ecma262/#sec-get-set-@@species
    setSpecies(CONSTRUCTOR_NAME);
  }
};

var collection$2 = collection$3;
var collectionStrong$1 = collectionStrong$2;

// `Map` constructor
// https://tc39.es/ecma262/#sec-map-objects
collection$2('Map', function (init) {
  return function Map() { return init(this, arguments.length ? arguments[0] : undefined); };
}, collectionStrong$1);

var path$b = path$y;

var map$1$1 = path$b.Map;

var parent$r = map$1$1;


var map$7 = parent$r;

(function (module) {
	module.exports = map$7;
} (map$2));

var _Map = /*@__PURE__*/getDefaultExportFromCjs$1(mapExports);

/**
 * This class can store groups and options specific for groups.
 */
var Groups = /*#__PURE__*/function () {
  /**
   * @ignore
   */
  function Groups() {
    _classCallCheck(this, Groups);
    this.clear();
    this._defaultIndex = 0;
    this._groupIndex = 0;
    this._defaultGroups = [{
      border: "#2B7CE9",
      background: "#97C2FC",
      highlight: {
        border: "#2B7CE9",
        background: "#D2E5FF"
      },
      hover: {
        border: "#2B7CE9",
        background: "#D2E5FF"
      }
    },
    // 0: blue
    {
      border: "#FFA500",
      background: "#FFFF00",
      highlight: {
        border: "#FFA500",
        background: "#FFFFA3"
      },
      hover: {
        border: "#FFA500",
        background: "#FFFFA3"
      }
    },
    // 1: yellow
    {
      border: "#FA0A10",
      background: "#FB7E81",
      highlight: {
        border: "#FA0A10",
        background: "#FFAFB1"
      },
      hover: {
        border: "#FA0A10",
        background: "#FFAFB1"
      }
    },
    // 2: red
    {
      border: "#41A906",
      background: "#7BE141",
      highlight: {
        border: "#41A906",
        background: "#A1EC76"
      },
      hover: {
        border: "#41A906",
        background: "#A1EC76"
      }
    },
    // 3: green
    {
      border: "#E129F0",
      background: "#EB7DF4",
      highlight: {
        border: "#E129F0",
        background: "#F0B3F5"
      },
      hover: {
        border: "#E129F0",
        background: "#F0B3F5"
      }
    },
    // 4: magenta
    {
      border: "#7C29F0",
      background: "#AD85E4",
      highlight: {
        border: "#7C29F0",
        background: "#D3BDF0"
      },
      hover: {
        border: "#7C29F0",
        background: "#D3BDF0"
      }
    },
    // 5: purple
    {
      border: "#C37F00",
      background: "#FFA807",
      highlight: {
        border: "#C37F00",
        background: "#FFCA66"
      },
      hover: {
        border: "#C37F00",
        background: "#FFCA66"
      }
    },
    // 6: orange
    {
      border: "#4220FB",
      background: "#6E6EFD",
      highlight: {
        border: "#4220FB",
        background: "#9B9BFD"
      },
      hover: {
        border: "#4220FB",
        background: "#9B9BFD"
      }
    },
    // 7: darkblue
    {
      border: "#FD5A77",
      background: "#FFC0CB",
      highlight: {
        border: "#FD5A77",
        background: "#FFD1D9"
      },
      hover: {
        border: "#FD5A77",
        background: "#FFD1D9"
      }
    },
    // 8: pink
    {
      border: "#4AD63A",
      background: "#C2FABC",
      highlight: {
        border: "#4AD63A",
        background: "#E6FFE3"
      },
      hover: {
        border: "#4AD63A",
        background: "#E6FFE3"
      }
    },
    // 9: mint

    {
      border: "#990000",
      background: "#EE0000",
      highlight: {
        border: "#BB0000",
        background: "#FF3333"
      },
      hover: {
        border: "#BB0000",
        background: "#FF3333"
      }
    },
    // 10:bright red

    {
      border: "#FF6000",
      background: "#FF6000",
      highlight: {
        border: "#FF6000",
        background: "#FF6000"
      },
      hover: {
        border: "#FF6000",
        background: "#FF6000"
      }
    },
    // 12: real orange
    {
      border: "#97C2FC",
      background: "#2B7CE9",
      highlight: {
        border: "#D2E5FF",
        background: "#2B7CE9"
      },
      hover: {
        border: "#D2E5FF",
        background: "#2B7CE9"
      }
    },
    // 13: blue
    {
      border: "#399605",
      background: "#255C03",
      highlight: {
        border: "#399605",
        background: "#255C03"
      },
      hover: {
        border: "#399605",
        background: "#255C03"
      }
    },
    // 14: green
    {
      border: "#B70054",
      background: "#FF007E",
      highlight: {
        border: "#B70054",
        background: "#FF007E"
      },
      hover: {
        border: "#B70054",
        background: "#FF007E"
      }
    },
    // 15: magenta
    {
      border: "#AD85E4",
      background: "#7C29F0",
      highlight: {
        border: "#D3BDF0",
        background: "#7C29F0"
      },
      hover: {
        border: "#D3BDF0",
        background: "#7C29F0"
      }
    },
    // 16: purple
    {
      border: "#4557FA",
      background: "#000EA1",
      highlight: {
        border: "#6E6EFD",
        background: "#000EA1"
      },
      hover: {
        border: "#6E6EFD",
        background: "#000EA1"
      }
    },
    // 17: darkblue
    {
      border: "#FFC0CB",
      background: "#FD5A77",
      highlight: {
        border: "#FFD1D9",
        background: "#FD5A77"
      },
      hover: {
        border: "#FFD1D9",
        background: "#FD5A77"
      }
    },
    // 18: pink
    {
      border: "#C2FABC",
      background: "#74D66A",
      highlight: {
        border: "#E6FFE3",
        background: "#74D66A"
      },
      hover: {
        border: "#E6FFE3",
        background: "#74D66A"
      }
    },
    // 19: mint

    {
      border: "#EE0000",
      background: "#990000",
      highlight: {
        border: "#FF3333",
        background: "#BB0000"
      },
      hover: {
        border: "#FF3333",
        background: "#BB0000"
      }
    } // 20:bright red
    ];

    this.options = {};
    this.defaultOptions = {
      useDefaultGroups: true
    };
    _Object$assign(this.options, this.defaultOptions);
  }

  /**
   *
   * @param {object} options
   */
  _createClass(Groups, [{
    key: "setOptions",
    value: function setOptions(options) {
      var optionFields = ["useDefaultGroups"];
      if (options !== undefined) {
        for (var groupName in options) {
          if (Object.prototype.hasOwnProperty.call(options, groupName)) {
            if (_indexOfInstanceProperty(optionFields).call(optionFields, groupName) === -1) {
              var group = options[groupName];
              this.add(groupName, group);
            }
          }
        }
      }
    }

    /**
     * Clear all groups
     */
  }, {
    key: "clear",
    value: function clear() {
      this._groups = new _Map();
      this._groupNames = [];
    }

    /**
     * Get group options of a groupname.
     * If groupname is not found, a new group may be created.
     *
     * @param {*}       groupname     Can be a number, string, Date, etc.
     * @param {boolean} [shouldCreate=true] If true, create a new group
     * @returns {object} The found or created group
     */
  }, {
    key: "get",
    value: function get(groupname) {
      var shouldCreate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var group = this._groups.get(groupname);
      if (group === undefined && shouldCreate) {
        if (this.options.useDefaultGroups === false && this._groupNames.length > 0) {
          // create new group
          var index = this._groupIndex % this._groupNames.length;
          ++this._groupIndex;
          group = {};
          group.color = this._groups.get(this._groupNames[index]);
          this._groups.set(groupname, group);
        } else {
          // create new group
          var _index = this._defaultIndex % this._defaultGroups.length;
          this._defaultIndex++;
          group = {};
          group.color = this._defaultGroups[_index];
          this._groups.set(groupname, group);
        }
      }
      return group;
    }

    /**
     * Add custom group style.
     *
     * @param {string} groupName - The name of the group, a new group will be
     * created if a group with the same name doesn't exist, otherwise the old
     * groups style will be overwritten.
     * @param {object} style - An object containing borderColor, backgroundColor,
     * etc.
     * @returns {object} The created group object.
     */
  }, {
    key: "add",
    value: function add(groupName, style) {
      // Only push group name once to prevent duplicates which would consume more
      // RAM and also skew the distribution towards more often updated groups,
      // neither of which is desirable.
      if (!this._groups.has(groupName)) {
        this._groupNames.push(groupName);
      }
      this._groups.set(groupName, style);
      return style;
    }
  }]);
  return Groups;
}();

var isNanExports = {};
var isNan$2 = {
  get exports(){ return isNanExports; },
  set exports(v){ isNanExports = v; },
};

var $$b = _export;

// `Number.isNaN` method
// https://tc39.es/ecma262/#sec-number.isnan
$$b({ target: 'Number', stat: true }, {
  isNaN: function isNaN(number) {
    // eslint-disable-next-line no-self-compare -- NaN check
    return number != number;
  }
});

var path$a = path$y;

var isNan$1 = path$a.Number.isNaN;

var parent$q = isNan$1;

var isNan = parent$q;

(function (module) {
	module.exports = isNan;
} (isNan$2));

var _Number$isNaN = /*@__PURE__*/getDefaultExportFromCjs$1(isNanExports);

var _isFiniteExports = {};
var _isFinite$2 = {
  get exports(){ return _isFiniteExports; },
  set exports(v){ _isFiniteExports = v; },
};

var global$3 = global$l;

var globalIsFinite = global$3.isFinite;

// `Number.isFinite` method
// https://tc39.es/ecma262/#sec-number.isfinite
// eslint-disable-next-line es/no-number-isfinite -- safe
var numberIsFinite$1 = Number.isFinite || function isFinite(it) {
  return typeof it == 'number' && globalIsFinite(it);
};

var $$a = _export;
var numberIsFinite = numberIsFinite$1;

// `Number.isFinite` method
// https://tc39.es/ecma262/#sec-number.isfinite
$$a({ target: 'Number', stat: true }, { isFinite: numberIsFinite });

var path$9 = path$y;

var _isFinite$1 = path$9.Number.isFinite;

var parent$p = _isFinite$1;

var _isFinite = parent$p;

(function (module) {
	module.exports = _isFinite;
} (_isFinite$2));

var _Number$isFinite = /*@__PURE__*/getDefaultExportFromCjs$1(_isFiniteExports);

var someExports = {};
var some$3 = {
  get exports(){ return someExports; },
  set exports(v){ someExports = v; },
};

var $$9 = _export;
var $some = arrayIteration.some;
var arrayMethodIsStrict$3 = arrayMethodIsStrict$6;

var STRICT_METHOD$2 = arrayMethodIsStrict$3('some');

// `Array.prototype.some` method
// https://tc39.es/ecma262/#sec-array.prototype.some
$$9({ target: 'Array', proto: true, forced: !STRICT_METHOD$2 }, {
  some: function some(callbackfn /* , thisArg */) {
    return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$4 = entryVirtual$i;

var some$2 = entryVirtual$4('Array').some;

var isPrototypeOf$4 = objectIsPrototypeOf;
var method$4 = some$2;

var ArrayPrototype$4 = Array.prototype;

var some$1 = function (it) {
  var own = it.some;
  return it === ArrayPrototype$4 || (isPrototypeOf$4(ArrayPrototype$4, it) && own === ArrayPrototype$4.some) ? method$4 : own;
};

var parent$o = some$1;

var some = parent$o;

(function (module) {
	module.exports = some;
} (some$3));

var _someInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(someExports);

var _parseFloatExports = {};
var _parseFloat$3 = {
  get exports(){ return _parseFloatExports; },
  set exports(v){ _parseFloatExports = v; },
};

var global$2 = global$l;
var fails$4 = fails$w;
var uncurryThis$3 = functionUncurryThis;
var toString$1 = toString$a;
var trim$6 = stringTrim.trim;
var whitespaces = whitespaces$4;

var charAt = uncurryThis$3(''.charAt);
var $parseFloat$1 = global$2.parseFloat;
var Symbol$1 = global$2.Symbol;
var ITERATOR = Symbol$1 && Symbol$1.iterator;
var FORCED$4 = 1 / $parseFloat$1(whitespaces + '-0') !== -Infinity
  // MS Edge 18- broken with boxed symbols
  || (ITERATOR && !fails$4(function () { $parseFloat$1(Object(ITERATOR)); }));

// `parseFloat` method
// https://tc39.es/ecma262/#sec-parsefloat-string
var numberParseFloat = FORCED$4 ? function parseFloat(string) {
  var trimmedString = trim$6(toString$1(string));
  var result = $parseFloat$1(trimmedString);
  return result === 0 && charAt(trimmedString, 0) == '-' ? -0 : result;
} : $parseFloat$1;

var $$8 = _export;
var $parseFloat = numberParseFloat;

// `parseFloat` method
// https://tc39.es/ecma262/#sec-parsefloat-string
$$8({ global: true, forced: parseFloat != $parseFloat }, {
  parseFloat: $parseFloat
});

var path$8 = path$y;

var _parseFloat$2 = path$8.parseFloat;

var parent$n = _parseFloat$2;

var _parseFloat$1 = parent$n;

(function (module) {
	module.exports = _parseFloat$1;
} (_parseFloat$3));

var _parseFloat = /*@__PURE__*/getDefaultExportFromCjs$1(_parseFloatExports);

var getOwnPropertyNamesExports = {};
var getOwnPropertyNames$3 = {
  get exports(){ return getOwnPropertyNamesExports; },
  set exports(v){ getOwnPropertyNamesExports = v; },
};

var $$7 = _export;
var fails$3 = fails$w;
var getOwnPropertyNames$2 = objectGetOwnPropertyNamesExternal.f;

// eslint-disable-next-line es/no-object-getownpropertynames -- required for testing
var FAILS_ON_PRIMITIVES = fails$3(function () { return !Object.getOwnPropertyNames(1); });

// `Object.getOwnPropertyNames` method
// https://tc39.es/ecma262/#sec-object.getownpropertynames
$$7({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES }, {
  getOwnPropertyNames: getOwnPropertyNames$2
});

var path$7 = path$y;

var Object$1 = path$7.Object;

var getOwnPropertyNames$1 = function getOwnPropertyNames(it) {
  return Object$1.getOwnPropertyNames(it);
};

var parent$m = getOwnPropertyNames$1;

var getOwnPropertyNames = parent$m;

(function (module) {
	module.exports = getOwnPropertyNames;
} (getOwnPropertyNames$3));

var _Object$getOwnPropertyNames = /*@__PURE__*/getDefaultExportFromCjs$1(getOwnPropertyNamesExports);

/**
 * Helper functions for components
 */

/**
 * Determine values to use for (sub)options of 'chosen'.
 *
 * This option is either a boolean or an object whose values should be examined further.
 * The relevant structures are:
 *
 * - chosen: <boolean value>
 * - chosen: { subOption: <boolean or function> }
 *
 * Where subOption is 'node', 'edge' or 'label'.
 *
 * The intention of this method appears to be to set a specific priority to the options;
 * Since most properties are either bridged or merged into the local options objects, there
 * is not much point in handling them separately.
 * TODO: examine if 'most' in previous sentence can be replaced with 'all'. In that case, we
 *       should be able to get rid of this method.
 *
 * @param {string}  subOption  option within object 'chosen' to consider; either 'node', 'edge' or 'label'
 * @param {object}  pile       array of options objects to consider
 * @returns {boolean | Function}  value for passed subOption of 'chosen' to use
 */
function choosify(subOption, pile) {
  // allowed values for subOption
  var allowed = ["node", "edge", "label"];
  var value = true;
  var chosen = topMost(pile, "chosen");
  if (typeof chosen === "boolean") {
    value = chosen;
  } else if (_typeof(chosen) === "object") {
    if (_indexOfInstanceProperty(allowed).call(allowed, subOption) === -1) {
      throw new Error("choosify: subOption '" + subOption + "' should be one of " + "'" + allowed.join("', '") + "'");
    }
    var chosenEdge = topMost(pile, ["chosen", subOption]);
    if (typeof chosenEdge === "boolean" || typeof chosenEdge === "function") {
      value = chosenEdge;
    }
  }
  return value;
}

/**
 * Check if the point falls within the given rectangle.
 *
 * @param {rect} rect
 * @param {point} point
 * @param {rotationPoint} [rotationPoint] if specified, the rotation that applies to the rectangle.
 * @returns {boolean}  true if point within rectangle, false otherwise
 */
function pointInRect(rect, point, rotationPoint) {
  if (rect.width <= 0 || rect.height <= 0) {
    return false; // early out
  }

  if (rotationPoint !== undefined) {
    // Rotate the point the same amount as the rectangle
    var tmp = {
      x: point.x - rotationPoint.x,
      y: point.y - rotationPoint.y
    };
    if (rotationPoint.angle !== 0) {
      // In order to get the coordinates the same, you need to
      // rotate in the reverse direction
      var angle = -rotationPoint.angle;
      var tmp2 = {
        x: Math.cos(angle) * tmp.x - Math.sin(angle) * tmp.y,
        y: Math.sin(angle) * tmp.x + Math.cos(angle) * tmp.y
      };
      point = tmp2;
    } else {
      point = tmp;
    }

    // Note that if a rotation is specified, the rectangle coordinates
    // are **not* the full canvas coordinates. They are relative to the
    // rotationPoint. Hence, the point coordinates need not be translated
    // back in this case.
  }

  var right = rect.x + rect.width;
  var bottom = rect.y + rect.width;
  return rect.left < point.x && right > point.x && rect.top < point.y && bottom > point.y;
}

/**
 * Check if given value is acceptable as a label text.
 *
 * @param {*} text value to check; can be anything at this point
 * @returns {boolean} true if valid label value, false otherwise
 */
function isValidLabel(text) {
  // Note that this is quite strict: types that *might* be converted to string are disallowed
  return typeof text === "string" && text !== "";
}

/**
 * Returns x, y of self reference circle based on provided angle
 *
 * @param {object} ctx
 * @param {number} angle
 * @param {number} radius
 * @param {VisNode} node
 * @returns {object} x and y coordinates
 */
function getSelfRefCoordinates(ctx, angle, radius, node) {
  var x = node.x;
  var y = node.y;
  if (typeof node.distanceToBorder === "function") {
    //calculating opposite and adjacent
    //distaneToBorder becomes Hypotenuse.
    //Formulas sin(a) = Opposite / Hypotenuse and cos(a) = Adjacent / Hypotenuse
    var toBorderDist = node.distanceToBorder(ctx, angle);
    var yFromNodeCenter = Math.sin(angle) * toBorderDist;
    var xFromNodeCenter = Math.cos(angle) * toBorderDist;
    //xFromNodeCenter is basically x and if xFromNodeCenter equals to the distance to border then it means
    //that y does not need calculation because it is equal node.height / 2 or node.y
    //same thing with yFromNodeCenter and if yFromNodeCenter equals to the distance to border then it means
    //that x is equal node.width / 2 or node.x
    if (xFromNodeCenter === toBorderDist) {
      x += toBorderDist;
      y = node.y;
    } else if (yFromNodeCenter === toBorderDist) {
      x = node.x;
      y -= toBorderDist;
    } else {
      x += xFromNodeCenter;
      y -= yFromNodeCenter;
    }
  } else if (node.shape.width > node.shape.height) {
    x = node.x + node.shape.width * 0.5;
    y = node.y - radius;
  } else {
    x = node.x + radius;
    y = node.y - node.shape.height * 0.5;
  }
  return {
    x: x,
    y: y
  };
}

var valuesExports = {};
var values$3 = {
  get exports(){ return valuesExports; },
  set exports(v){ valuesExports = v; },
};

var entryVirtual$3 = entryVirtual$i;

var values$2 = entryVirtual$3('Array').values;

var parent$l = values$2;

var values$1 = parent$l;

var classof$1 = classof$d;
var hasOwn$2 = hasOwnProperty_1;
var isPrototypeOf$3 = objectIsPrototypeOf;
var method$3 = values$1;

var ArrayPrototype$3 = Array.prototype;

var DOMIterables = {
  DOMTokenList: true,
  NodeList: true
};

var values = function (it) {
  var own = it.values;
  return it === ArrayPrototype$3 || (isPrototypeOf$3(ArrayPrototype$3, it) && own === ArrayPrototype$3.values)
    || hasOwn$2(DOMIterables, classof$1(it)) ? method$3 : own;
};

(function (module) {
	module.exports = values;
} (values$3));

var _valuesInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(valuesExports);

/**
 * Callback to determine text dimensions, using the parent label settings.
 *
 * @callback MeasureText
 * @param {text} text
 * @param {text} mod
 * @returns {object} { width, values} width in pixels and font attributes
 */
/**
 * Helper class for Label which collects results of splitting labels into lines and blocks.
 *
 * @private
 */
var LabelAccumulator = /*#__PURE__*/function () {
  /**
   * @param {MeasureText} measureText
   */
  function LabelAccumulator(measureText) {
    _classCallCheck(this, LabelAccumulator);
    this.measureText = measureText;
    this.current = 0;
    this.width = 0;
    this.height = 0;
    this.lines = [];
  }

  /**
   * Append given text to the given line.
   *
   * @param {number}  l    index of line to add to
   * @param {string}  text string to append to line
   * @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal']
   * @private
   */
  _createClass(LabelAccumulator, [{
    key: "_add",
    value: function _add(l, text) {
      var mod = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "normal";
      if (this.lines[l] === undefined) {
        this.lines[l] = {
          width: 0,
          height: 0,
          blocks: []
        };
      }

      // We still need to set a block for undefined and empty texts, hence return at this point
      // This is necessary because we don't know at this point if we're at the
      // start of an empty line or not.
      // To compensate, empty blocks are removed in `finalize()`.
      //
      // Empty strings should still have a height
      var tmpText = text;
      if (text === undefined || text === "") tmpText = " ";

      // Determine width and get the font properties
      var result = this.measureText(tmpText, mod);
      var block = _Object$assign({}, _valuesInstanceProperty(result));
      block.text = text;
      block.width = result.width;
      block.mod = mod;
      if (text === undefined || text === "") {
        block.width = 0;
      }
      this.lines[l].blocks.push(block);

      // Update the line width. We need this for determining if a string goes over max width
      this.lines[l].width += block.width;
    }

    /**
     * Returns the width in pixels of the current line.
     *
     * @returns {number}
     */
  }, {
    key: "curWidth",
    value: function curWidth() {
      var line = this.lines[this.current];
      if (line === undefined) return 0;
      return line.width;
    }

    /**
     * Add text in block to current line
     *
     * @param {string} text
     * @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal']
     */
  }, {
    key: "append",
    value: function append(text) {
      var mod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "normal";
      this._add(this.current, text, mod);
    }

    /**
     * Add text in block to current line and start a new line
     *
     * @param {string} text
     * @param {'bold'|'ital'|'boldital'|'mono'|'normal'} [mod='normal']
     */
  }, {
    key: "newLine",
    value: function newLine(text) {
      var mod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "normal";
      this._add(this.current, text, mod);
      this.current++;
    }

    /**
     * Determine and set the heights of all the lines currently contained in this instance
     *
     * Note that width has already been set.
     *
     * @private
     */
  }, {
    key: "determineLineHeights",
    value: function determineLineHeights() {
      for (var k = 0; k < this.lines.length; k++) {
        var line = this.lines[k];

        // Looking for max height of blocks in line
        var height = 0;
        if (line.blocks !== undefined) {
          // Can happen if text contains e.g. '\n '
          for (var l = 0; l < line.blocks.length; l++) {
            var block = line.blocks[l];
            if (height < block.height) {
              height = block.height;
            }
          }
        }
        line.height = height;
      }
    }

    /**
     * Determine the full size of the label text, as determined by current lines and blocks
     *
     * @private
     */
  }, {
    key: "determineLabelSize",
    value: function determineLabelSize() {
      var width = 0;
      var height = 0;
      for (var k = 0; k < this.lines.length; k++) {
        var line = this.lines[k];
        if (line.width > width) {
          width = line.width;
        }
        height += line.height;
      }
      this.width = width;
      this.height = height;
    }

    /**
     * Remove all empty blocks and empty lines we don't need
     *
     * This must be done after the width/height determination,
     * so that these are set properly for processing here.
     *
     * @returns {Array<Line>} Lines with empty blocks (and some empty lines) removed
     * @private
     */
  }, {
    key: "removeEmptyBlocks",
    value: function removeEmptyBlocks() {
      var tmpLines = [];
      for (var k = 0; k < this.lines.length; k++) {
        var line = this.lines[k];

        // Note: an empty line in between text has width zero but is still relevant to layout.
        // So we can't use width for testing empty line here
        if (line.blocks.length === 0) continue;

        // Discard final empty line always
        if (k === this.lines.length - 1) {
          if (line.width === 0) continue;
        }
        var tmpLine = {};
        _Object$assign(tmpLine, line);
        tmpLine.blocks = [];
        var firstEmptyBlock = void 0;
        var tmpBlocks = [];
        for (var l = 0; l < line.blocks.length; l++) {
          var block = line.blocks[l];
          if (block.width !== 0) {
            tmpBlocks.push(block);
          } else {
            if (firstEmptyBlock === undefined) {
              firstEmptyBlock = block;
            }
          }
        }

        // Ensure that there is *some* text present
        if (tmpBlocks.length === 0 && firstEmptyBlock !== undefined) {
          tmpBlocks.push(firstEmptyBlock);
        }
        tmpLine.blocks = tmpBlocks;
        tmpLines.push(tmpLine);
      }
      return tmpLines;
    }

    /**
     * Set the sizes for all lines and the whole thing.
     *
     * @returns {{width: (number|*), height: (number|*), lines: Array}}
     */
  }, {
    key: "finalize",
    value: function finalize() {
      //console.log(JSON.stringify(this.lines, null, 2));

      this.determineLineHeights();
      this.determineLabelSize();
      var tmpLines = this.removeEmptyBlocks();

      // Return a simple hash object for further processing.
      return {
        width: this.width,
        height: this.height,
        lines: tmpLines
      };
    }
  }]);
  return LabelAccumulator;
}();

// Hash of prepared regexp's for tags
var tagPattern = {
  // HTML
  "<b>": /<b>/,
  "<i>": /<i>/,
  "<code>": /<code>/,
  "</b>": /<\/b>/,
  "</i>": /<\/i>/,
  "</code>": /<\/code>/,
  // Markdown
  "*": /\*/,
  // bold
  _: /_/,
  // ital
  "`": /`/,
  // mono
  afterBold: /[^*]/,
  afterItal: /[^_]/,
  afterMono: /[^`]/
};

/**
 * Internal helper class for parsing the markup tags for HTML and Markdown.
 *
 * NOTE: Sequences of tabs and spaces are reduced to single space.
 *       Scan usage of `this.spacing` within method
 */
var MarkupAccumulator = /*#__PURE__*/function () {
  /**
   * Create an instance
   *
   * @param {string} text  text to parse for markup
   */
  function MarkupAccumulator(text) {
    _classCallCheck(this, MarkupAccumulator);
    this.text = text;
    this.bold = false;
    this.ital = false;
    this.mono = false;
    this.spacing = false;
    this.position = 0;
    this.buffer = "";
    this.modStack = [];
    this.blocks = [];
  }

  /**
   * Return the mod label currently on the top of the stack
   *
   * @returns {string}  label of topmost mod
   * @private
   */
  _createClass(MarkupAccumulator, [{
    key: "mod",
    value: function mod() {
      return this.modStack.length === 0 ? "normal" : this.modStack[0];
    }

    /**
     * Return the mod label currently active
     *
     * @returns {string}  label of active mod
     * @private
     */
  }, {
    key: "modName",
    value: function modName() {
      if (this.modStack.length === 0) return "normal";else if (this.modStack[0] === "mono") return "mono";else {
        if (this.bold && this.ital) {
          return "boldital";
        } else if (this.bold) {
          return "bold";
        } else if (this.ital) {
          return "ital";
        }
      }
    }

    /**
     * @private
     */
  }, {
    key: "emitBlock",
    value: function emitBlock() {
      if (this.spacing) {
        this.add(" ");
        this.spacing = false;
      }
      if (this.buffer.length > 0) {
        this.blocks.push({
          text: this.buffer,
          mod: this.modName()
        });
        this.buffer = "";
      }
    }

    /**
     * Output text to buffer
     *
     * @param {string} text  text to add
     * @private
     */
  }, {
    key: "add",
    value: function add(text) {
      if (text === " ") {
        this.spacing = true;
      }
      if (this.spacing) {
        this.buffer += " ";
        this.spacing = false;
      }
      if (text != " ") {
        this.buffer += text;
      }
    }

    /**
     * Handle parsing of whitespace
     *
     * @param {string} ch  the character to check
     * @returns {boolean} true if the character was processed as whitespace, false otherwise
     */
  }, {
    key: "parseWS",
    value: function parseWS(ch) {
      if (/[ \t]/.test(ch)) {
        if (!this.mono) {
          this.spacing = true;
        } else {
          this.add(ch);
        }
        return true;
      }
      return false;
    }

    /**
     * @param {string} tagName  label for block type to set
     * @private
     */
  }, {
    key: "setTag",
    value: function setTag(tagName) {
      this.emitBlock();
      this[tagName] = true;
      this.modStack.unshift(tagName);
    }

    /**
     * @param {string} tagName  label for block type to unset
     * @private
     */
  }, {
    key: "unsetTag",
    value: function unsetTag(tagName) {
      this.emitBlock();
      this[tagName] = false;
      this.modStack.shift();
    }

    /**
     * @param {string} tagName label for block type we are currently processing
     * @param {string|RegExp} tag string to match in text
     * @returns {boolean} true if the tag was processed, false otherwise
     */
  }, {
    key: "parseStartTag",
    value: function parseStartTag(tagName, tag) {
      // Note: if 'mono' passed as tagName, there is a double check here. This is OK
      if (!this.mono && !this[tagName] && this.match(tag)) {
        this.setTag(tagName);
        return true;
      }
      return false;
    }

    /**
     * @param {string|RegExp} tag
     * @param {number} [advance=true] if set, advance current position in text
     * @returns {boolean} true if match at given position, false otherwise
     * @private
     */
  }, {
    key: "match",
    value: function match(tag) {
      var advance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var _this$prepareRegExp = this.prepareRegExp(tag),
        _this$prepareRegExp2 = _slicedToArray(_this$prepareRegExp, 2),
        regExp = _this$prepareRegExp2[0],
        length = _this$prepareRegExp2[1];
      var matched = regExp.test(this.text.substr(this.position, length));
      if (matched && advance) {
        this.position += length - 1;
      }
      return matched;
    }

    /**
     * @param {string} tagName label for block type we are currently processing
     * @param {string|RegExp} tag string to match in text
     * @param {RegExp} [nextTag] regular expression to match for characters *following* the current tag
     * @returns {boolean} true if the tag was processed, false otherwise
     */
  }, {
    key: "parseEndTag",
    value: function parseEndTag(tagName, tag, nextTag) {
      var checkTag = this.mod() === tagName;
      if (tagName === "mono") {
        // special handling for 'mono'
        checkTag = checkTag && this.mono;
      } else {
        checkTag = checkTag && !this.mono;
      }
      if (checkTag && this.match(tag)) {
        if (nextTag !== undefined) {
          // Purpose of the following match is to prevent a direct unset/set of a given tag
          // E.g. '*bold **still bold*' => '*bold still bold*'
          if (this.position === this.text.length - 1 || this.match(nextTag, false)) {
            this.unsetTag(tagName);
          }
        } else {
          this.unsetTag(tagName);
        }
        return true;
      }
      return false;
    }

    /**
     * @param {string|RegExp} tag  string to match in text
     * @param {value} value  string to replace tag with, if found at current position
     * @returns {boolean} true if the tag was processed, false otherwise
     */
  }, {
    key: "replace",
    value: function replace(tag, value) {
      if (this.match(tag)) {
        this.add(value);
        this.position += length - 1;
        return true;
      }
      return false;
    }

    /**
     * Create a regular expression for the tag if it isn't already one.
     *
     * The return value is an array `[RegExp, number]`, with exactly two value, where:
     *  - RegExp is the regular expression to use
     *  - number is the lenth of the input string to match
     *
     * @param {string|RegExp} tag  string to match in text
     * @returns {Array}  regular expression to use and length of input string to match
     * @private
     */
  }, {
    key: "prepareRegExp",
    value: function prepareRegExp(tag) {
      var length;
      var regExp;
      if (tag instanceof RegExp) {
        regExp = tag;
        length = 1; // ASSUMPTION: regexp only tests one character
      } else {
        // use prepared regexp if present
        var prepared = tagPattern[tag];
        if (prepared !== undefined) {
          regExp = prepared;
        } else {
          regExp = new RegExp(tag);
        }
        length = tag.length;
      }
      return [regExp, length];
    }
  }]);
  return MarkupAccumulator;
}();
/**
 * Helper class for Label which explodes the label text into lines and blocks within lines
 *
 * @private
 */
var LabelSplitter = /*#__PURE__*/function () {
  /**
   * @param {CanvasRenderingContext2D} ctx Canvas rendering context
   * @param {Label} parent reference to the Label instance using current instance
   * @param {boolean} selected
   * @param {boolean} hover
   */
  function LabelSplitter(ctx, parent, selected, hover) {
    var _this = this;
    _classCallCheck(this, LabelSplitter);
    this.ctx = ctx;
    this.parent = parent;
    this.selected = selected;
    this.hover = hover;

    /**
     * Callback to determine text width; passed to LabelAccumulator instance
     *
     * @param  {string} text string to determine width of
     * @param  {string} mod  font type to use for this text
     * @returns {object} { width, values} width in pixels and font attributes
     */
    var textWidth = function textWidth(text, mod) {
      if (text === undefined) return 0;

      // TODO: This can be done more efficiently with caching
      // This will set the ctx.font correctly, depending on selected/hover and mod - so that ctx.measureText() will be accurate.
      var values = _this.parent.getFormattingValues(ctx, selected, hover, mod);
      var width = 0;
      if (text !== "") {
        var measure = _this.ctx.measureText(text);
        width = measure.width;
      }
      return {
        width: width,
        values: values
      };
    };
    this.lines = new LabelAccumulator(textWidth);
  }

  /**
   * Split passed text of a label into lines and blocks.
   *
   * # NOTE
   *
   * The handling of spacing is option dependent:
   *
   * - if `font.multi : false`, all spaces are retained
   * - if `font.multi : true`, every sequence of spaces is compressed to a single space
   *
   * This might not be the best way to do it, but this is as it has been working till now.
   * In order not to break existing functionality, for the time being this behaviour will
   * be retained in any code changes.
   *
   * @param {string} text  text to split
   * @returns {Array<line>}
   */
  _createClass(LabelSplitter, [{
    key: "process",
    value: function process(text) {
      if (!isValidLabel(text)) {
        return this.lines.finalize();
      }
      var font = this.parent.fontOptions;

      // Normalize the end-of-line's to a single representation - order important
      text = text.replace(/\r\n/g, "\n"); // Dos EOL's
      text = text.replace(/\r/g, "\n"); // Mac EOL's

      // Note that at this point, there can be no \r's in the text.
      // This is used later on splitStringIntoLines() to split multifont texts.

      var nlLines = String(text).split("\n");
      var lineCount = nlLines.length;
      if (font.multi) {
        // Multi-font case: styling tags active
        for (var i = 0; i < lineCount; i++) {
          var blocks = this.splitBlocks(nlLines[i], font.multi);
          // Post: Sequences of tabs and spaces are reduced to single space

          if (blocks === undefined) continue;
          if (blocks.length === 0) {
            this.lines.newLine("");
            continue;
          }
          if (font.maxWdt > 0) {
            // widthConstraint.maximum defined
            //console.log('Running widthConstraint multi, max: ' + this.fontOptions.maxWdt);
            for (var j = 0; j < blocks.length; j++) {
              var mod = blocks[j].mod;
              var _text = blocks[j].text;
              this.splitStringIntoLines(_text, mod, true);
            }
          } else {
            // widthConstraint.maximum NOT defined
            for (var _j = 0; _j < blocks.length; _j++) {
              var _mod = blocks[_j].mod;
              var _text2 = blocks[_j].text;
              this.lines.append(_text2, _mod);
            }
          }
          this.lines.newLine();
        }
      } else {
        // Single-font case
        if (font.maxWdt > 0) {
          // widthConstraint.maximum defined
          // console.log('Running widthConstraint normal, max: ' + this.fontOptions.maxWdt);
          for (var _i = 0; _i < lineCount; _i++) {
            this.splitStringIntoLines(nlLines[_i]);
          }
        } else {
          // widthConstraint.maximum NOT defined
          for (var _i2 = 0; _i2 < lineCount; _i2++) {
            this.lines.newLine(nlLines[_i2]);
          }
        }
      }
      return this.lines.finalize();
    }

    /**
     * normalize the markup system
     *
     * @param {boolean|'md'|'markdown'|'html'} markupSystem
     * @returns {string}
     */
  }, {
    key: "decodeMarkupSystem",
    value: function decodeMarkupSystem(markupSystem) {
      var system = "none";
      if (markupSystem === "markdown" || markupSystem === "md") {
        system = "markdown";
      } else if (markupSystem === true || markupSystem === "html") {
        system = "html";
      }
      return system;
    }

    /**
     *
     * @param {string} text
     * @returns {Array}
     */
  }, {
    key: "splitHtmlBlocks",
    value: function splitHtmlBlocks(text) {
      var s = new MarkupAccumulator(text);
      var parseEntities = function parseEntities(ch) {
        if (/&/.test(ch)) {
          var parsed = s.replace(s.text, "&lt;", "<") || s.replace(s.text, "&amp;", "&");
          if (!parsed) {
            s.add("&");
          }
          return true;
        }
        return false;
      };
      while (s.position < s.text.length) {
        var ch = s.text.charAt(s.position);
        var parsed = s.parseWS(ch) || /</.test(ch) && (s.parseStartTag("bold", "<b>") || s.parseStartTag("ital", "<i>") || s.parseStartTag("mono", "<code>") || s.parseEndTag("bold", "</b>") || s.parseEndTag("ital", "</i>") || s.parseEndTag("mono", "</code>")) || parseEntities(ch);
        if (!parsed) {
          s.add(ch);
        }
        s.position++;
      }
      s.emitBlock();
      return s.blocks;
    }

    /**
     *
     * @param {string} text
     * @returns {Array}
     */
  }, {
    key: "splitMarkdownBlocks",
    value: function splitMarkdownBlocks(text) {
      var _this2 = this;
      var s = new MarkupAccumulator(text);
      var beginable = true;
      var parseOverride = function parseOverride(ch) {
        if (/\\/.test(ch)) {
          if (s.position < _this2.text.length + 1) {
            s.position++;
            ch = _this2.text.charAt(s.position);
            if (/ \t/.test(ch)) {
              s.spacing = true;
            } else {
              s.add(ch);
              beginable = false;
            }
          }
          return true;
        }
        return false;
      };
      while (s.position < s.text.length) {
        var ch = s.text.charAt(s.position);
        var parsed = s.parseWS(ch) || parseOverride(ch) || (beginable || s.spacing) && (s.parseStartTag("bold", "*") || s.parseStartTag("ital", "_") || s.parseStartTag("mono", "`")) || s.parseEndTag("bold", "*", "afterBold") || s.parseEndTag("ital", "_", "afterItal") || s.parseEndTag("mono", "`", "afterMono");
        if (!parsed) {
          s.add(ch);
          beginable = false;
        }
        s.position++;
      }
      s.emitBlock();
      return s.blocks;
    }

    /**
     * Explodes a piece of text into single-font blocks using a given markup
     *
     * @param {string} text
     * @param {boolean|'md'|'markdown'|'html'} markupSystem
     * @returns {Array.<{text: string, mod: string}>}
     * @private
     */
  }, {
    key: "splitBlocks",
    value: function splitBlocks(text, markupSystem) {
      var system = this.decodeMarkupSystem(markupSystem);
      if (system === "none") {
        return [{
          text: text,
          mod: "normal"
        }];
      } else if (system === "markdown") {
        return this.splitMarkdownBlocks(text);
      } else if (system === "html") {
        return this.splitHtmlBlocks(text);
      }
    }

    /**
     * @param {string} text
     * @returns {boolean} true if text length over the current max with
     * @private
     */
  }, {
    key: "overMaxWidth",
    value: function overMaxWidth(text) {
      var width = this.ctx.measureText(text).width;
      return this.lines.curWidth() + width > this.parent.fontOptions.maxWdt;
    }

    /**
     * Determine the longest part of the sentence which still fits in the
     * current max width.
     *
     * @param {Array} words  Array of strings signifying a text lines
     * @returns {number}      index of first item in string making string go over max
     * @private
     */
  }, {
    key: "getLongestFit",
    value: function getLongestFit(words) {
      var text = "";
      var w = 0;
      while (w < words.length) {
        var pre = text === "" ? "" : " ";
        var newText = text + pre + words[w];
        if (this.overMaxWidth(newText)) break;
        text = newText;
        w++;
      }
      return w;
    }

    /**
     * Determine the longest part of the string which still fits in the
     * current max width.
     *
     * @param {Array} words Array of strings signifying a text lines
     * @returns {number} index of first item in string making string go over max
     */
  }, {
    key: "getLongestFitWord",
    value: function getLongestFitWord(words) {
      var w = 0;
      while (w < words.length) {
        if (this.overMaxWidth(_sliceInstanceProperty(words).call(words, 0, w))) break;
        w++;
      }
      return w;
    }

    /**
     * Split the passed text into lines, according to width constraint (if any).
     *
     * The method assumes that the input string is a single line, i.e. without lines break.
     *
     * This method retains spaces, if still present (case `font.multi: false`).
     * A space which falls on an internal line break, will be replaced by a newline.
     * There is no special handling of tabs; these go along with the flow.
     *
     * @param {string} str
     * @param {string} [mod='normal']
     * @param {boolean} [appendLast=false]
     * @private
     */
  }, {
    key: "splitStringIntoLines",
    value: function splitStringIntoLines(str) {
      var mod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "normal";
      var appendLast = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      // Set the canvas context font, based upon the current selected/hover state
      // and the provided mod, so the text measurement performed by getLongestFit
      // will be accurate - and not just use the font of whoever last used the canvas.
      this.parent.getFormattingValues(this.ctx, this.selected, this.hover, mod);

      // Still-present spaces are relevant, retain them
      str = str.replace(/^( +)/g, "$1\r");
      str = str.replace(/([^\r][^ ]*)( +)/g, "$1\r$2\r");
      var words = str.split("\r");
      while (words.length > 0) {
        var w = this.getLongestFit(words);
        if (w === 0) {
          // Special case: the first word is already larger than the max width.
          var word = words[0];

          // Break the word to the largest part that fits the line
          var x = this.getLongestFitWord(word);
          this.lines.newLine(_sliceInstanceProperty(word).call(word, 0, x), mod);

          // Adjust the word, so that the rest will be done next iteration
          words[0] = _sliceInstanceProperty(word).call(word, x);
        } else {
          // skip any space that is replaced by a newline
          var newW = w;
          if (words[w - 1] === " ") {
            w--;
          } else if (words[newW] === " ") {
            newW++;
          }
          var text = _sliceInstanceProperty(words).call(words, 0, w).join("");
          if (w == words.length && appendLast) {
            this.lines.append(text, mod);
          } else {
            this.lines.newLine(text, mod);
          }

          // Adjust the word, so that the rest will be done next iteration
          words = _sliceInstanceProperty(words).call(words, newW);
        }
      }
    }
  }]);
  return LabelSplitter;
}();

/**
 * List of special styles for multi-fonts
 *
 * @private
 */
var multiFontStyle = ["bold", "ital", "boldital", "mono"];

/**
 * A Label to be used for Nodes or Edges.
 */
var Label = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {object} options
   * @param {boolean} [edgelabel=false]
   */
  function Label(body, options) {
    var edgelabel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    _classCallCheck(this, Label);
    this.body = body;
    this.pointToSelf = false;
    this.baseSize = undefined;
    this.fontOptions = {}; // instance variable containing the *instance-local* font options
    this.setOptions(options);
    this.size = {
      top: 0,
      left: 0,
      width: 0,
      height: 0,
      yLine: 0
    };
    this.isEdgeLabel = edgelabel;
  }

  /**
   * @param {object} options the options of the parent Node-instance
   */
  _createClass(Label, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.elementOptions = options; // Reference to the options of the parent Node-instance

      this.initFontOptions(options.font);
      if (isValidLabel(options.label)) {
        this.labelDirty = true;
      } else {
        // Bad label! Change the option value to prevent bad stuff happening
        options.label = undefined;
      }
      if (options.font !== undefined && options.font !== null) {
        // font options can be deleted at various levels
        if (typeof options.font === "string") {
          this.baseSize = this.fontOptions.size;
        } else if (_typeof(options.font) === "object") {
          var size = options.font.size;
          if (size !== undefined) {
            this.baseSize = size;
          }
        }
      }
    }

    /**
     * Init the font Options structure.
     *
     * Member fontOptions serves as an accumulator for the current font options.
     * As such, it needs to be completely separated from the node options.
     *
     * @param {object} newFontOptions the new font options to process
     * @private
     */
  }, {
    key: "initFontOptions",
    value: function initFontOptions(newFontOptions) {
      var _this = this;
      // Prepare the multi-font option objects.
      // These will be filled in propagateFonts(), if required
      forEach$1(multiFontStyle, function (style) {
        _this.fontOptions[style] = {};
      });

      // Handle shorthand option, if present
      if (Label.parseFontString(this.fontOptions, newFontOptions)) {
        this.fontOptions.vadjust = 0;
        return;
      }

      // Copy over the non-multifont options, if specified
      forEach$1(newFontOptions, function (prop, n) {
        if (prop !== undefined && prop !== null && _typeof(prop) !== "object") {
          _this.fontOptions[n] = prop;
        }
      });
    }

    /**
     * If in-variable is a string, parse it as a font specifier.
     *
     * Note that following is not done here and have to be done after the call:
     * - Not all font options are set (vadjust, mod)
     *
     * @param {object} outOptions  out-parameter, object in which to store the parse results (if any)
     * @param {object} inOptions  font options to parse
     * @returns {boolean} true if font parsed as string, false otherwise
     * @static
     */
  }, {
    key: "constrain",
    value:
    /**
     * Set the width and height constraints based on 'nearest' value
     *
     * @param {Array} pile array of option objects to consider
     * @returns {object} the actual constraint values to use
     * @private
     */
    function constrain(pile) {
      // NOTE: constrainWidth and  constrainHeight never set!
      // NOTE: for edge labels, only 'maxWdt' set
      // Node labels can set all the fields
      var fontOptions = {
        constrainWidth: false,
        maxWdt: -1,
        minWdt: -1,
        constrainHeight: false,
        minHgt: -1,
        valign: "middle"
      };
      var widthConstraint = topMost(pile, "widthConstraint");
      if (typeof widthConstraint === "number") {
        fontOptions.maxWdt = Number(widthConstraint);
        fontOptions.minWdt = Number(widthConstraint);
      } else if (_typeof(widthConstraint) === "object") {
        var widthConstraintMaximum = topMost(pile, ["widthConstraint", "maximum"]);
        if (typeof widthConstraintMaximum === "number") {
          fontOptions.maxWdt = Number(widthConstraintMaximum);
        }
        var widthConstraintMinimum = topMost(pile, ["widthConstraint", "minimum"]);
        if (typeof widthConstraintMinimum === "number") {
          fontOptions.minWdt = Number(widthConstraintMinimum);
        }
      }
      var heightConstraint = topMost(pile, "heightConstraint");
      if (typeof heightConstraint === "number") {
        fontOptions.minHgt = Number(heightConstraint);
      } else if (_typeof(heightConstraint) === "object") {
        var heightConstraintMinimum = topMost(pile, ["heightConstraint", "minimum"]);
        if (typeof heightConstraintMinimum === "number") {
          fontOptions.minHgt = Number(heightConstraintMinimum);
        }
        var heightConstraintValign = topMost(pile, ["heightConstraint", "valign"]);
        if (typeof heightConstraintValign === "string") {
          if (heightConstraintValign === "top" || heightConstraintValign === "bottom") {
            fontOptions.valign = heightConstraintValign;
          }
        }
      }
      return fontOptions;
    }

    /**
     * Set options and update internal state
     *
     * @param {object} options  options to set
     * @param {Array}  pile     array of option objects to consider for option 'chosen'
     */
  }, {
    key: "update",
    value: function update(options, pile) {
      this.setOptions(options, true);
      this.propagateFonts(pile);
      deepExtend(this.fontOptions, this.constrain(pile));
      this.fontOptions.chooser = choosify("label", pile);
    }

    /**
     * When margins are set in an element, adjust sizes is called to remove them
     * from the width/height constraints. This must be done prior to label sizing.
     *
     * @param {{top: number, right: number, bottom: number, left: number}} margins
     */
  }, {
    key: "adjustSizes",
    value: function adjustSizes(margins) {
      var widthBias = margins ? margins.right + margins.left : 0;
      if (this.fontOptions.constrainWidth) {
        this.fontOptions.maxWdt -= widthBias;
        this.fontOptions.minWdt -= widthBias;
      }
      var heightBias = margins ? margins.top + margins.bottom : 0;
      if (this.fontOptions.constrainHeight) {
        this.fontOptions.minHgt -= heightBias;
      }
    }

    /////////////////////////////////////////////////////////
    // Methods for handling options piles
    // Eventually, these will be moved to a separate class
    /////////////////////////////////////////////////////////

    /**
     * Add the font members of the passed list of option objects to the pile.
     *
     * @param {Pile} dstPile  pile of option objects add to
     * @param {Pile} srcPile  pile of option objects to take font options from
     * @private
     */
  }, {
    key: "addFontOptionsToPile",
    value: function addFontOptionsToPile(dstPile, srcPile) {
      for (var i = 0; i < srcPile.length; ++i) {
        this.addFontToPile(dstPile, srcPile[i]);
      }
    }

    /**
     * Add given font option object to the list of objects (the 'pile') to consider for determining
     * multi-font option values.
     *
     * @param {Pile} pile  pile of option objects to use
     * @param {object} options  instance to add to pile
     * @private
     */
  }, {
    key: "addFontToPile",
    value: function addFontToPile(pile, options) {
      if (options === undefined) return;
      if (options.font === undefined || options.font === null) return;
      var item = options.font;
      pile.push(item);
    }

    /**
     * Collect all own-property values from the font pile that aren't multi-font option objectss.
     *
     * @param {Pile} pile  pile of option objects to use
     * @returns {object} object with all current own basic font properties
     * @private
     */
  }, {
    key: "getBasicOptions",
    value: function getBasicOptions(pile) {
      var ret = {};

      // Scans the whole pile to get all options present
      for (var n = 0; n < pile.length; ++n) {
        var fontOptions = pile[n];

        // Convert shorthand if necessary
        var tmpShorthand = {};
        if (Label.parseFontString(tmpShorthand, fontOptions)) {
          fontOptions = tmpShorthand;
        }
        forEach$1(fontOptions, function (opt, name) {
          if (opt === undefined) return; // multi-font option need not be present
          if (Object.prototype.hasOwnProperty.call(ret, name)) return; // Keep first value we encounter

          if (_indexOfInstanceProperty(multiFontStyle).call(multiFontStyle, name) !== -1) {
            // Skip multi-font properties but we do need the structure
            ret[name] = {};
          } else {
            ret[name] = opt;
          }
        });
      }
      return ret;
    }

    /**
     * Return the value for given option for the given multi-font.
     *
     * All available option objects are trawled in the set order to construct the option values.
     *
     * ---------------------------------------------------------------------
     * ## Traversal of pile for multi-fonts
     *
     * The determination of multi-font option values is a special case, because any values not
     * present in the multi-font options should by definition be taken from the main font options,
     * i.e. from the current 'parent' object of the multi-font option.
     *
     * ### Search order for multi-fonts
     *
     * 'bold' used as example:
     *
     *   - search in option group 'bold' in local properties
     *   - search in main font option group in local properties
     *
     * ---------------------------------------------------------------------
     *
     * @param {Pile} pile  pile of option objects to use
     * @param {MultiFontStyle} multiName sub path for the multi-font
     * @param {string} option  the option to search for, for the given multi-font
     * @returns {string|number} the value for the given option
     * @private
     */
  }, {
    key: "getFontOption",
    value: function getFontOption(pile, multiName, option) {
      var multiFont;

      // Search multi font in local properties
      for (var n = 0; n < pile.length; ++n) {
        var fontOptions = pile[n];
        if (Object.prototype.hasOwnProperty.call(fontOptions, multiName)) {
          multiFont = fontOptions[multiName];
          if (multiFont === undefined || multiFont === null) continue;

          // Convert shorthand if necessary
          // TODO: inefficient to do this conversion every time; find a better way.
          var tmpShorthand = {};
          if (Label.parseFontString(tmpShorthand, multiFont)) {
            multiFont = tmpShorthand;
          }
          if (Object.prototype.hasOwnProperty.call(multiFont, option)) {
            return multiFont[option];
          }
        }
      }

      // Option is not mentioned in the multi font options; take it from the parent font options.
      // These have already been converted with getBasicOptions(), so use the converted values.
      if (Object.prototype.hasOwnProperty.call(this.fontOptions, option)) {
        return this.fontOptions[option];
      }

      // A value **must** be found; you should never get here.
      throw new Error("Did not find value for multi-font for property: '" + option + "'");
    }

    /**
     * Return all options values for the given multi-font.
     *
     * All available option objects are trawled in the set order to construct the option values.
     *
     * @param {Pile} pile  pile of option objects to use
     * @param {MultiFontStyle} multiName sub path for the mod-font
     * @returns {MultiFontOptions}
     * @private
     */
  }, {
    key: "getFontOptions",
    value: function getFontOptions(pile, multiName) {
      var result = {};
      var optionNames = ["color", "size", "face", "mod", "vadjust"]; // List of allowed options per multi-font

      for (var i = 0; i < optionNames.length; ++i) {
        var mod = optionNames[i];
        result[mod] = this.getFontOption(pile, multiName, mod);
      }
      return result;
    }

    /////////////////////////////////////////////////////////
    // End methods for handling options piles
    /////////////////////////////////////////////////////////

    /**
     * Collapse the font options for the multi-font to single objects, from
     * the chain of option objects passed (the 'pile').
     *
     * @param {Pile} pile  sequence of option objects to consider.
     *                     First item in list assumed to be the newly set options.
     */
  }, {
    key: "propagateFonts",
    value: function propagateFonts(pile) {
      var _this2 = this;
      var fontPile = []; // sequence of font objects to consider, order important

      // Note that this.elementOptions is not used here.
      this.addFontOptionsToPile(fontPile, pile);
      this.fontOptions = this.getBasicOptions(fontPile);

      // We set multifont values even if multi === false, for consistency (things break otherwise)
      var _loop = function _loop() {
        var mod = multiFontStyle[i];
        var modOptions = _this2.fontOptions[mod];
        var tmpMultiFontOptions = _this2.getFontOptions(fontPile, mod);

        // Copy over found values
        forEach$1(tmpMultiFontOptions, function (option, n) {
          modOptions[n] = option;
        });
        modOptions.size = Number(modOptions.size);
        modOptions.vadjust = Number(modOptions.vadjust);
      };
      for (var i = 0; i < multiFontStyle.length; ++i) {
        _loop();
      }
    }

    /**
     * Main function. This is called from anything that wants to draw a label.
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x
     * @param {number} y
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {string} [baseline='middle']
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover) {
      var baseline = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : "middle";
      // if no label, return
      if (this.elementOptions.label === undefined) return;

      // check if we have to render the label
      var viewFontSize = this.fontOptions.size * this.body.view.scale;
      if (this.elementOptions.label && viewFontSize < this.elementOptions.scaling.label.drawThreshold - 1) return;

      // This ensures that there will not be HUGE letters on screen
      // by setting an upper limit on the visible text size (regardless of zoomLevel)
      if (viewFontSize >= this.elementOptions.scaling.label.maxVisible) {
        viewFontSize = Number(this.elementOptions.scaling.label.maxVisible) / this.body.view.scale;
      }

      // update the size cache if required
      this.calculateLabelSize(ctx, selected, hover, x, y, baseline);
      this._drawBackground(ctx);
      this._drawText(ctx, x, this.size.yLine, baseline, viewFontSize);
    }

    /**
     * Draws the label background
     *
     * @param {CanvasRenderingContext2D} ctx
     * @private
     */
  }, {
    key: "_drawBackground",
    value: function _drawBackground(ctx) {
      if (this.fontOptions.background !== undefined && this.fontOptions.background !== "none") {
        ctx.fillStyle = this.fontOptions.background;
        var size = this.getSize();
        ctx.fillRect(size.left, size.top, size.width, size.height);
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x
     * @param {number} y
     * @param {string} [baseline='middle']
     * @param {number} viewFontSize
     * @private
     */
  }, {
    key: "_drawText",
    value: function _drawText(ctx, x, y) {
      var baseline = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "middle";
      var viewFontSize = arguments.length > 4 ? arguments[4] : undefined;
      var _this$_setAlignment = this._setAlignment(ctx, x, y, baseline);
      var _this$_setAlignment2 = _slicedToArray(_this$_setAlignment, 2);
      x = _this$_setAlignment2[0];
      y = _this$_setAlignment2[1];
      ctx.textAlign = "left";
      x = x - this.size.width / 2; // Shift label 1/2-distance to the left
      if (this.fontOptions.valign && this.size.height > this.size.labelHeight) {
        if (this.fontOptions.valign === "top") {
          y -= (this.size.height - this.size.labelHeight) / 2;
        }
        if (this.fontOptions.valign === "bottom") {
          y += (this.size.height - this.size.labelHeight) / 2;
        }
      }

      // draw the text
      for (var i = 0; i < this.lineCount; i++) {
        var line = this.lines[i];
        if (line && line.blocks) {
          var width = 0;
          if (this.isEdgeLabel || this.fontOptions.align === "center") {
            width += (this.size.width - line.width) / 2;
          } else if (this.fontOptions.align === "right") {
            width += this.size.width - line.width;
          }
          for (var j = 0; j < line.blocks.length; j++) {
            var block = line.blocks[j];
            ctx.font = block.font;
            var _this$_getColor = this._getColor(block.color, viewFontSize, block.strokeColor),
              _this$_getColor2 = _slicedToArray(_this$_getColor, 2),
              fontColor = _this$_getColor2[0],
              strokeColor = _this$_getColor2[1];
            if (block.strokeWidth > 0) {
              ctx.lineWidth = block.strokeWidth;
              ctx.strokeStyle = strokeColor;
              ctx.lineJoin = "round";
            }
            ctx.fillStyle = fontColor;
            if (block.strokeWidth > 0) {
              ctx.strokeText(block.text, x + width, y + block.vadjust);
            }
            ctx.fillText(block.text, x + width, y + block.vadjust);
            width += block.width;
          }
          y += line.height;
        }
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x
     * @param {number} y
     * @param {string} baseline
     * @returns {Array.<number>}
     * @private
     */
  }, {
    key: "_setAlignment",
    value: function _setAlignment(ctx, x, y, baseline) {
      // check for label alignment (for edges)
      // TODO: make alignment for nodes
      if (this.isEdgeLabel && this.fontOptions.align !== "horizontal" && this.pointToSelf === false) {
        x = 0;
        y = 0;
        var lineMargin = 2;
        if (this.fontOptions.align === "top") {
          ctx.textBaseline = "alphabetic";
          y -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers
        } else if (this.fontOptions.align === "bottom") {
          ctx.textBaseline = "hanging";
          y += 2 * lineMargin; // distance from edge, required because we use hanging. Hanging has less difference between browsers
        } else {
          ctx.textBaseline = "middle";
        }
      } else {
        ctx.textBaseline = baseline;
      }
      return [x, y];
    }

    /**
     * fade in when relative scale is between threshold and threshold - 1.
     * If the relative scale would be smaller than threshold -1 the draw function would have returned before coming here.
     *
     * @param {string} color  The font color to use
     * @param {number} viewFontSize
     * @param {string} initialStrokeColor
     * @returns {Array.<string>} An array containing the font color and stroke color
     * @private
     */
  }, {
    key: "_getColor",
    value: function _getColor(color, viewFontSize, initialStrokeColor) {
      var fontColor = color || "#000000";
      var strokeColor = initialStrokeColor || "#ffffff";
      if (viewFontSize <= this.elementOptions.scaling.label.drawThreshold) {
        var opacity = Math.max(0, Math.min(1, 1 - (this.elementOptions.scaling.label.drawThreshold - viewFontSize)));
        fontColor = overrideOpacity(fontColor, opacity);
        strokeColor = overrideOpacity(strokeColor, opacity);
      }
      return [fontColor, strokeColor];
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     * @returns {{width: number, height: number}}
     */
  }, {
    key: "getTextSize",
    value: function getTextSize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      this._processLabel(ctx, selected, hover);
      return {
        width: this.size.width,
        height: this.size.height,
        lineCount: this.lineCount
      };
    }

    /**
     * Get the current dimensions of the label
     *
     * @returns {rect}
     */
  }, {
    key: "getSize",
    value: function getSize() {
      var lineMargin = 2;
      var x = this.size.left; // default values which might be overridden below
      var y = this.size.top - 0.5 * lineMargin; // idem

      if (this.isEdgeLabel) {
        var x2 = -this.size.width * 0.5;
        switch (this.fontOptions.align) {
          case "middle":
            x = x2;
            y = -this.size.height * 0.5;
            break;
          case "top":
            x = x2;
            y = -(this.size.height + lineMargin);
            break;
          case "bottom":
            x = x2;
            y = lineMargin;
            break;
        }
      }
      var ret = {
        left: x,
        top: y,
        width: this.size.width,
        height: this.size.height
      };
      return ret;
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {number} [x=0]
     * @param {number} [y=0]
     * @param {'middle'|'hanging'} [baseline='middle']
     */
  }, {
    key: "calculateLabelSize",
    value: function calculateLabelSize(ctx, selected, hover) {
      var x = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
      var y = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
      var baseline = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : "middle";
      this._processLabel(ctx, selected, hover);
      this.size.left = x - this.size.width * 0.5;
      this.size.top = y - this.size.height * 0.5;
      this.size.yLine = y + (1 - this.lineCount) * 0.5 * this.fontOptions.size;
      if (baseline === "hanging") {
        this.size.top += 0.5 * this.fontOptions.size;
        this.size.top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers
        this.size.yLine += 4; // distance from node
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {string} mod
     * @returns {{color, size, face, mod, vadjust, strokeWidth: *, strokeColor: (*|string|allOptions.edges.font.strokeColor|{string}|allOptions.nodes.font.strokeColor|Array)}}
     */
  }, {
    key: "getFormattingValues",
    value: function getFormattingValues(ctx, selected, hover, mod) {
      var getValue = function getValue(fontOptions, mod, option) {
        if (mod === "normal") {
          if (option === "mod") return "";
          return fontOptions[option];
        }
        if (fontOptions[mod][option] !== undefined) {
          // Grumbl leaving out test on undefined equals false for ""
          return fontOptions[mod][option];
        } else {
          // Take from parent font option
          return fontOptions[option];
        }
      };
      var values = {
        color: getValue(this.fontOptions, mod, "color"),
        size: getValue(this.fontOptions, mod, "size"),
        face: getValue(this.fontOptions, mod, "face"),
        mod: getValue(this.fontOptions, mod, "mod"),
        vadjust: getValue(this.fontOptions, mod, "vadjust"),
        strokeWidth: this.fontOptions.strokeWidth,
        strokeColor: this.fontOptions.strokeColor
      };
      if (selected || hover) {
        if (mod === "normal" && this.fontOptions.chooser === true && this.elementOptions.labelHighlightBold) {
          values.mod = "bold";
        } else {
          if (typeof this.fontOptions.chooser === "function") {
            this.fontOptions.chooser(values, this.elementOptions.id, selected, hover);
          }
        }
      }
      var fontString = "";
      if (values.mod !== undefined && values.mod !== "") {
        // safeguard for undefined - this happened
        fontString += values.mod + " ";
      }
      fontString += values.size + "px " + values.face;
      ctx.font = fontString.replace(/"/g, "");
      values.font = ctx.font;
      values.height = values.size;
      return values;
    }

    /**
     *
     * @param {boolean} selected
     * @param {boolean} hover
     * @returns {boolean}
     */
  }, {
    key: "differentState",
    value: function differentState(selected, hover) {
      return selected !== this.selectedState || hover !== this.hoverState;
    }

    /**
     * This explodes the passed text into lines and determines the width, height and number of lines.
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {string} inText  the text to explode
     * @returns {{width, height, lines}|*}
     * @private
     */
  }, {
    key: "_processLabelText",
    value: function _processLabelText(ctx, selected, hover, inText) {
      var splitter = new LabelSplitter(ctx, this, selected, hover);
      return splitter.process(inText);
    }

    /**
     * This explodes the label string into lines and sets the width, height and number of lines.
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     * @private
     */
  }, {
    key: "_processLabel",
    value: function _processLabel(ctx, selected, hover) {
      if (this.labelDirty === false && !this.differentState(selected, hover)) return;
      var state = this._processLabelText(ctx, selected, hover, this.elementOptions.label);
      if (this.fontOptions.minWdt > 0 && state.width < this.fontOptions.minWdt) {
        state.width = this.fontOptions.minWdt;
      }
      this.size.labelHeight = state.height;
      if (this.fontOptions.minHgt > 0 && state.height < this.fontOptions.minHgt) {
        state.height = this.fontOptions.minHgt;
      }
      this.lines = state.lines;
      this.lineCount = state.lines.length;
      this.size.width = state.width;
      this.size.height = state.height;
      this.selectedState = selected;
      this.hoverState = hover;
      this.labelDirty = false;
    }

    /**
     * Check if this label is visible
     *
     * @returns {boolean} true if this label will be show, false otherwise
     */
  }, {
    key: "visible",
    value: function visible() {
      if (this.size.width === 0 || this.size.height === 0 || this.elementOptions.label === undefined) {
        return false; // nothing to display
      }

      var viewFontSize = this.fontOptions.size * this.body.view.scale;
      if (viewFontSize < this.elementOptions.scaling.label.drawThreshold - 1) {
        return false; // Too small or too far away to show
      }

      return true;
    }
  }], [{
    key: "parseFontString",
    value: function parseFontString(outOptions, inOptions) {
      if (!inOptions || typeof inOptions !== "string") return false;
      var newOptionsArray = inOptions.split(" ");
      outOptions.size = +newOptionsArray[0].replace("px", "");
      outOptions.face = newOptionsArray[1];
      outOptions.color = newOptionsArray[2];
      return true;
    }
  }]);
  return Label;
}();

var constructExports = {};
var construct$2 = {
  get exports(){ return constructExports; },
  set exports(v){ constructExports = v; },
};

var isConstructor = isConstructor$4;
var tryToString = tryToString$6;

var $TypeError$1 = TypeError;

// `Assert: IsConstructor(argument) is true`
var aConstructor$1 = function (argument) {
  if (isConstructor(argument)) return argument;
  throw $TypeError$1(tryToString(argument) + ' is not a constructor');
};

var $$6 = _export;
var getBuiltIn = getBuiltIn$c;
var apply = functionApply;
var bind$4 = functionBind;
var aConstructor = aConstructor$1;
var anObject$2 = anObject$d;
var isObject$3$1 = isObject$j;
var create$4 = objectCreate;
var fails$2 = fails$w;

var nativeConstruct = getBuiltIn('Reflect', 'construct');
var ObjectPrototype = Object.prototype;
var push$1 = [].push;

// `Reflect.construct` method
// https://tc39.es/ecma262/#sec-reflect.construct
// MS Edge supports only 2 arguments and argumentsList argument is optional
// FF Nightly sets third argument as `new.target`, but does not create `this` from it
var NEW_TARGET_BUG = fails$2(function () {
  function F() { /* empty */ }
  return !(nativeConstruct(function () { /* empty */ }, [], F) instanceof F);
});

var ARGS_BUG = !fails$2(function () {
  nativeConstruct(function () { /* empty */ });
});

var FORCED$3 = NEW_TARGET_BUG || ARGS_BUG;

$$6({ target: 'Reflect', stat: true, forced: FORCED$3, sham: FORCED$3 }, {
  construct: function construct(Target, args /* , newTarget */) {
    aConstructor(Target);
    anObject$2(args);
    var newTarget = arguments.length < 3 ? Target : aConstructor(arguments[2]);
    if (ARGS_BUG && !NEW_TARGET_BUG) return nativeConstruct(Target, args, newTarget);
    if (Target == newTarget) {
      // w/o altered newTarget, optimization for 0-4 arguments
      switch (args.length) {
        case 0: return new Target();
        case 1: return new Target(args[0]);
        case 2: return new Target(args[0], args[1]);
        case 3: return new Target(args[0], args[1], args[2]);
        case 4: return new Target(args[0], args[1], args[2], args[3]);
      }
      // w/o altered newTarget, lot of arguments case
      var $args = [null];
      apply(push$1, $args, args);
      return new (apply(bind$4, Target, $args))();
    }
    // with altered newTarget, not support built-in constructors
    var proto = newTarget.prototype;
    var instance = create$4(isObject$3$1(proto) ? proto : ObjectPrototype);
    var result = apply(Target, instance, args);
    return isObject$3$1(result) ? result : instance;
  }
});

var path$6 = path$y;

var construct$1 = path$6.Reflect.construct;

var parent$k = construct$1;

var construct = parent$k;

(function (module) {
	module.exports = construct;
} (construct$2));

var _Reflect$construct = /*@__PURE__*/getDefaultExportFromCjs$1(constructExports);

var createExports$1 = {};
var create$3 = {
  get exports(){ return createExports$1; },
  set exports(v){ createExports$1 = v; },
};

var createExports = {};
var create$2 = {
  get exports(){ return createExports; },
  set exports(v){ createExports = v; },
};

var parent$j = create$6;

var create$1$1 = parent$j;

var parent$i = create$1$1;

var create$c = parent$i;

(function (module) {
	module.exports = create$c;
} (create$2));

(function (module) {
	module.exports = createExports;
} (create$3));

var _Object$create = /*@__PURE__*/getDefaultExportFromCjs$1(createExports$1);

var setPrototypeOfExports$1 = {};
var setPrototypeOf$6 = {
  get exports(){ return setPrototypeOfExports$1; },
  set exports(v){ setPrototypeOfExports$1 = v; },
};

var setPrototypeOfExports = {};
var setPrototypeOf$5 = {
  get exports(){ return setPrototypeOfExports; },
  set exports(v){ setPrototypeOfExports = v; },
};

var $$5 = _export;
var setPrototypeOf$4 = objectSetPrototypeOf;

// `Object.setPrototypeOf` method
// https://tc39.es/ecma262/#sec-object.setprototypeof
$$5({ target: 'Object', stat: true }, {
  setPrototypeOf: setPrototypeOf$4
});

var path$5 = path$y;

var setPrototypeOf$3 = path$5.Object.setPrototypeOf;

var parent$h = setPrototypeOf$3;

var setPrototypeOf$2 = parent$h;

var parent$g = setPrototypeOf$2;

var setPrototypeOf$1 = parent$g;

var parent$f = setPrototypeOf$1;

var setPrototypeOf = parent$f;

(function (module) {
	module.exports = setPrototypeOf;
} (setPrototypeOf$5));

(function (module) {
	module.exports = setPrototypeOfExports;
} (setPrototypeOf$6));

var _Object$setPrototypeOf = /*@__PURE__*/getDefaultExportFromCjs$1(setPrototypeOfExports$1);

var bindExports$1 = {};
var bind$3 = {
  get exports(){ return bindExports$1; },
  set exports(v){ bindExports$1 = v; },
};

var bindExports = {};
var bind$2 = {
  get exports(){ return bindExports; },
  set exports(v){ bindExports = v; },
};

var parent$e = bind$9;

var bind$1$1 = parent$e;

var parent$d = bind$1$1;

var bind$g = parent$d;

(function (module) {
	module.exports = bind$g;
} (bind$2));

(function (module) {
	module.exports = bindExports;
} (bind$3));

var _bindInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(bindExports$1);

function _setPrototypeOf(o, p) {
  var _context;
  _setPrototypeOf = _Object$setPrototypeOf ? _bindInstanceProperty(_context = _Object$setPrototypeOf).call(_context) : function _setPrototypeOf(o, p) {
    o.__proto__ = p;
    return o;
  };
  return _setPrototypeOf(o, p);
}

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 _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);
}

var getPrototypeOfExports$1 = {};
var getPrototypeOf$4 = {
  get exports(){ return getPrototypeOfExports$1; },
  set exports(v){ getPrototypeOfExports$1 = v; },
};

var getPrototypeOfExports = {};
var getPrototypeOf$3 = {
  get exports(){ return getPrototypeOfExports; },
  set exports(v){ getPrototypeOfExports = v; },
};

var parent$c = getPrototypeOf$5;

var getPrototypeOf$2 = parent$c;

var parent$b = getPrototypeOf$2;

var getPrototypeOf$1 = parent$b;

(function (module) {
	module.exports = getPrototypeOf$1;
} (getPrototypeOf$3));

(function (module) {
	module.exports = getPrototypeOfExports;
} (getPrototypeOf$4));

var _Object$getPrototypeOf = /*@__PURE__*/getDefaultExportFromCjs$1(getPrototypeOfExports$1);

function _getPrototypeOf(o) {
  var _context;
  _getPrototypeOf = _Object$setPrototypeOf ? _bindInstanceProperty(_context = _Object$getPrototypeOf).call(_context) : function _getPrototypeOf(o) {
    return o.__proto__ || _Object$getPrototypeOf(o);
  };
  return _getPrototypeOf(o);
}

/**
 * The Base class for all Nodes.
 */
var NodeBase = /*#__PURE__*/function () {
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function NodeBase(options, body, labelModule) {
    _classCallCheck(this, NodeBase);
    this.body = body;
    this.labelModule = labelModule;
    this.setOptions(options);
    this.top = undefined;
    this.left = undefined;
    this.height = undefined;
    this.width = undefined;
    this.radius = undefined;
    this.margin = undefined;
    this.refreshNeeded = true;
    this.boundingBox = {
      top: 0,
      left: 0,
      right: 0,
      bottom: 0
    };
  }

  /**
   *
   * @param {object} options
   */
  _createClass(NodeBase, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
    }

    /**
     *
     * @param {Label} labelModule
     * @private
     */
  }, {
    key: "_setMargins",
    value: function _setMargins(labelModule) {
      this.margin = {};
      if (this.options.margin) {
        if (_typeof(this.options.margin) == "object") {
          this.margin.top = this.options.margin.top;
          this.margin.right = this.options.margin.right;
          this.margin.bottom = this.options.margin.bottom;
          this.margin.left = this.options.margin.left;
        } else {
          this.margin.top = this.options.margin;
          this.margin.right = this.options.margin;
          this.margin.bottom = this.options.margin;
          this.margin.left = this.options.margin;
        }
      }
      labelModule.adjustSizes(this.margin);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     * @private
     */
  }, {
    key: "_distanceToBorder",
    value: function _distanceToBorder(ctx, angle) {
      var borderWidth = this.options.borderWidth;
      if (ctx) {
        this.resize(ctx);
      }
      return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "enableShadow",
    value: function enableShadow(ctx, values) {
      if (values.shadow) {
        ctx.shadowColor = values.shadowColor;
        ctx.shadowBlur = values.shadowSize;
        ctx.shadowOffsetX = values.shadowX;
        ctx.shadowOffsetY = values.shadowY;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "disableShadow",
    value: function disableShadow(ctx, values) {
      if (values.shadow) {
        ctx.shadowColor = "rgba(0,0,0,0)";
        ctx.shadowBlur = 0;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "enableBorderDashes",
    value: function enableBorderDashes(ctx, values) {
      if (values.borderDashes !== false) {
        if (ctx.setLineDash !== undefined) {
          var dashes = values.borderDashes;
          if (dashes === true) {
            dashes = [5, 15];
          }
          ctx.setLineDash(dashes);
        } else {
          console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used.");
          this.options.shapeProperties.borderDashes = false;
          values.borderDashes = false;
        }
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "disableBorderDashes",
    value: function disableBorderDashes(ctx, values) {
      if (values.borderDashes !== false) {
        if (ctx.setLineDash !== undefined) {
          ctx.setLineDash([0]);
        } else {
          console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used.");
          this.options.shapeProperties.borderDashes = false;
          values.borderDashes = false;
        }
      }
    }

    /**
     * Determine if the shape of a node needs to be recalculated.
     *
     * @param {boolean} selected
     * @param {boolean} hover
     * @returns {boolean}
     * @protected
     */
  }, {
    key: "needsRefresh",
    value: function needsRefresh(selected, hover) {
      if (this.refreshNeeded === true) {
        // This is probably not the best location to reset this member.
        // However, in the current logic, it is the most convenient one.
        this.refreshNeeded = false;
        return true;
      }
      return this.width === undefined || this.labelModule.differentState(selected, hover);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "initContextForDraw",
    value: function initContextForDraw(ctx, values) {
      var borderWidth = values.borderWidth / this.body.view.scale;
      ctx.lineWidth = Math.min(this.width, borderWidth);
      ctx.strokeStyle = values.borderColor;
      ctx.fillStyle = values.color;
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "performStroke",
    value: function performStroke(ctx, values) {
      var borderWidth = values.borderWidth / this.body.view.scale;

      //draw dashed border if enabled, save and restore is required for firefox not to crash on unix.
      ctx.save();
      // if borders are zero width, they will be drawn with width 1 by default. This prevents that
      if (borderWidth > 0) {
        this.enableBorderDashes(ctx, values);
        //draw the border
        ctx.stroke();
        //disable dashed border for other elements
        this.disableBorderDashes(ctx, values);
      }
      ctx.restore();
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     */
  }, {
    key: "performFill",
    value: function performFill(ctx, values) {
      ctx.save();
      ctx.fillStyle = values.color;
      // draw shadow if enabled
      this.enableShadow(ctx, values);
      // draw the background
      _fillInstanceProperty(ctx).call(ctx);
      // disable shadows for other elements.
      this.disableShadow(ctx, values);
      ctx.restore();
      this.performStroke(ctx, values);
    }

    /**
     *
     * @param {number} margin
     * @private
     */
  }, {
    key: "_addBoundingBoxMargin",
    value: function _addBoundingBoxMargin(margin) {
      this.boundingBox.left -= margin;
      this.boundingBox.top -= margin;
      this.boundingBox.bottom += margin;
      this.boundingBox.right += margin;
    }

    /**
     * Actual implementation of this method call.
     *
     * Doing it like this makes it easier to override
     * in the child classes.
     *
     * @param {number} x width
     * @param {number} y height
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     * @private
     */
  }, {
    key: "_updateBoundingBox",
    value: function _updateBoundingBox(x, y, ctx, selected, hover) {
      if (ctx !== undefined) {
        this.resize(ctx, selected, hover);
      }
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;
      this.boundingBox.left = this.left;
      this.boundingBox.top = this.top;
      this.boundingBox.bottom = this.top + this.height;
      this.boundingBox.right = this.left + this.width;
    }

    /**
     * Default implementation of this method call.
     * This acts as a stub which can be overridden.
     *
     * @param {number} x width
     * @param {number} y height
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y, ctx, selected, hover) {
      this._updateBoundingBox(x, y, ctx, selected, hover);
    }

    /**
     * Determine the dimensions to use for nodes with an internal label
     *
     * Currently, these are: Circle, Ellipse, Database, Box
     * The other nodes have external labels, and will not call this method
     *
     * If there is no label, decent default values are supplied.
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} [selected]
     * @param {boolean} [hover]
     * @returns {{width:number, height:number}}
     */
  }, {
    key: "getDimensionsFromLabel",
    value: function getDimensionsFromLabel(ctx, selected, hover) {
      // NOTE: previously 'textSize' was not put in 'this' for Ellipse
      // TODO: examine the consequences.
      this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
      var width = this.textSize.width;
      var height = this.textSize.height;
      var DEFAULT_SIZE = 14;
      if (width === 0) {
        // This happens when there is no label text set
        width = DEFAULT_SIZE; // use a decent default
        height = DEFAULT_SIZE; // if width zero, then height also always zero
      }

      return {
        width: width,
        height: height
      };
    }
  }]);
  return NodeBase;
}();

function _createSuper$s(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$s(); 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 _isNativeReflectConstruct$s() { 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; } }

/**
 * A Box Node/Cluster shape.
 *
 * @augments NodeBase
 */
var Box$1 = /*#__PURE__*/function (_NodeBase) {
  _inherits(Box, _NodeBase);
  var _super = _createSuper$s(Box);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Box(options, body, labelModule) {
    var _this;
    _classCallCheck(this, Box);
    _this = _super.call(this, options, body, labelModule);
    _this._setMargins(labelModule);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   */
  _createClass(Box, [{
    key: "resize",
    value: function resize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
      if (this.needsRefresh(selected, hover)) {
        var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
        this.width = dimensions.width + this.margin.right + this.margin.left;
        this.height = dimensions.height + this.margin.top + this.margin.bottom;
        this.radius = this.width / 2;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.resize(ctx, selected, hover);
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;
      this.initContextForDraw(ctx, values);
      drawRoundRect(ctx, this.left, this.top, this.width, this.height, values.borderRadius);
      this.performFill(ctx, values);
      this.updateBoundingBox(x, y, ctx, selected, hover);
      this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, this.top + this.textSize.height / 2 + this.margin.top, selected, hover);
    }

    /**
     *
     * @param {number} x width
     * @param {number} y height
     * @param {CanvasRenderingContext2D} ctx
     * @param {boolean} selected
     * @param {boolean} hover
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y, ctx, selected, hover) {
      this._updateBoundingBox(x, y, ctx, selected, hover);
      var borderRadius = this.options.shapeProperties.borderRadius; // only effective for box
      this._addBoundingBoxMargin(borderRadius);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      if (ctx) {
        this.resize(ctx);
      }
      var borderWidth = this.options.borderWidth;
      return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
    }
  }]);
  return Box;
}(NodeBase);

function _createSuper$r(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$r(); 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 _isNativeReflectConstruct$r() { 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; } }

/**
 * NOTE: This is a bad base class
 *
 * Child classes are:
 *
 *   Image       - uses *only* image methods
 *   Circle      - uses *only* _drawRawCircle
 *   CircleImage - uses all
 *
 * TODO: Refactor, move _drawRawCircle to different module, derive Circle from NodeBase
 *       Rename this to ImageBase
 *       Consolidate common code in Image and CircleImage to base class
 *
 * @augments NodeBase
 */
var CircleImageBase = /*#__PURE__*/function (_NodeBase) {
  _inherits(CircleImageBase, _NodeBase);
  var _super = _createSuper$r(CircleImageBase);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function CircleImageBase(options, body, labelModule) {
    var _this;
    _classCallCheck(this, CircleImageBase);
    _this = _super.call(this, options, body, labelModule);
    _this.labelOffset = 0;
    _this.selected = false;
    return _this;
  }

  /**
   *
   * @param {object} options
   * @param {object} [imageObj]
   * @param {object} [imageObjAlt]
   */
  _createClass(CircleImageBase, [{
    key: "setOptions",
    value: function setOptions(options, imageObj, imageObjAlt) {
      this.options = options;
      if (!(imageObj === undefined && imageObjAlt === undefined)) {
        this.setImages(imageObj, imageObjAlt);
      }
    }

    /**
     * Set the images for this node.
     *
     * The images can be updated after the initial setting of options;
     * therefore, this method needs to be reentrant.
     *
     * For correct working in error cases, it is necessary to properly set
     * field 'nodes.brokenImage' in the options.
     *
     * @param {Image} imageObj  required; main image to show for this node
     * @param {Image|undefined} imageObjAlt optional; image to show when node is selected
     */
  }, {
    key: "setImages",
    value: function setImages(imageObj, imageObjAlt) {
      if (imageObjAlt && this.selected) {
        this.imageObj = imageObjAlt;
        this.imageObjAlt = imageObj;
      } else {
        this.imageObj = imageObj;
        this.imageObjAlt = imageObjAlt;
      }
    }

    /**
     * Set selection and switch between the base and the selected image.
     *
     * Do the switch only if imageObjAlt exists.
     *
     * @param {boolean} selected value of new selected state for current node
     */
  }, {
    key: "switchImages",
    value: function switchImages(selected) {
      var selection_changed = selected && !this.selected || !selected && this.selected;
      this.selected = selected; // Remember new selection

      if (this.imageObjAlt !== undefined && selection_changed) {
        var imageTmp = this.imageObj;
        this.imageObj = this.imageObjAlt;
        this.imageObjAlt = imageTmp;
      }
    }

    /**
     * Returns Image Padding from node options
     *
     * @returns {{top: number,left: number,bottom: number,right: number}} image padding inside this shape
     * @private
     */
  }, {
    key: "_getImagePadding",
    value: function _getImagePadding() {
      var imgPadding = {
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
      };
      if (this.options.imagePadding) {
        var optImgPadding = this.options.imagePadding;
        if (_typeof(optImgPadding) == "object") {
          imgPadding.top = optImgPadding.top;
          imgPadding.right = optImgPadding.right;
          imgPadding.bottom = optImgPadding.bottom;
          imgPadding.left = optImgPadding.left;
        } else {
          imgPadding.top = optImgPadding;
          imgPadding.right = optImgPadding;
          imgPadding.bottom = optImgPadding;
          imgPadding.left = optImgPadding;
        }
      }
      return imgPadding;
    }

    /**
     * Adjust the node dimensions for a loaded image.
     *
     * Pre: this.imageObj is valid
     */
  }, {
    key: "_resizeImage",
    value: function _resizeImage() {
      var width, height;
      if (this.options.shapeProperties.useImageSize === false) {
        // Use the size property
        var ratio_width = 1;
        var ratio_height = 1;

        // Only calculate the proper ratio if both width and height not zero
        if (this.imageObj.width && this.imageObj.height) {
          if (this.imageObj.width > this.imageObj.height) {
            ratio_width = this.imageObj.width / this.imageObj.height;
          } else {
            ratio_height = this.imageObj.height / this.imageObj.width;
          }
        }
        width = this.options.size * 2 * ratio_width;
        height = this.options.size * 2 * ratio_height;
      } else {
        // Use the image size with image padding
        var imgPadding = this._getImagePadding();
        width = this.imageObj.width + imgPadding.left + imgPadding.right;
        height = this.imageObj.height + imgPadding.top + imgPadding.bottom;
      }
      this.width = width;
      this.height = height;
      this.radius = 0.5 * this.width;
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {ArrowOptions} values
     * @private
     */
  }, {
    key: "_drawRawCircle",
    value: function _drawRawCircle(ctx, x, y, values) {
      this.initContextForDraw(ctx, values);
      drawCircle(ctx, x, y, values.size);
      this.performFill(ctx, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {ArrowOptions} values
     * @private
     */
  }, {
    key: "_drawImageAtPosition",
    value: function _drawImageAtPosition(ctx, values) {
      if (this.imageObj.width != 0) {
        // draw the image
        ctx.globalAlpha = values.opacity !== undefined ? values.opacity : 1;

        // draw shadow if enabled
        this.enableShadow(ctx, values);
        var factor = 1;
        if (this.options.shapeProperties.interpolation === true) {
          factor = this.imageObj.width / this.width / this.body.view.scale;
        }
        var imgPadding = this._getImagePadding();
        var imgPosLeft = this.left + imgPadding.left;
        var imgPosTop = this.top + imgPadding.top;
        var imgWidth = this.width - imgPadding.left - imgPadding.right;
        var imgHeight = this.height - imgPadding.top - imgPadding.bottom;
        this.imageObj.drawImageAtPosition(ctx, factor, imgPosLeft, imgPosTop, imgWidth, imgHeight);

        // disable shadows for other elements.
        this.disableShadow(ctx, values);
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @private
     */
  }, {
    key: "_drawImageLabel",
    value: function _drawImageLabel(ctx, x, y, selected, hover) {
      var offset = 0;
      if (this.height !== undefined) {
        offset = this.height * 0.5;
        var labelDimensions = this.labelModule.getTextSize(ctx, selected, hover);
        if (labelDimensions.lineCount >= 1) {
          offset += labelDimensions.height / 2;
        }
      }
      var yLabel = y + offset;
      if (this.options.label) {
        this.labelOffset = offset;
      }
      this.labelModule.draw(ctx, x, yLabel, selected, hover, "hanging");
    }
  }]);
  return CircleImageBase;
}(NodeBase);

function _createSuper$q(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$q(); 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 _isNativeReflectConstruct$q() { 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; } }

/**
 * A Circle Node/Cluster shape.
 *
 * @augments CircleImageBase
 */
var Circle$1$1 = /*#__PURE__*/function (_CircleImageBase) {
  _inherits(Circle, _CircleImageBase);
  var _super = _createSuper$q(Circle);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Circle(options, body, labelModule) {
    var _this;
    _classCallCheck(this, Circle);
    _this = _super.call(this, options, body, labelModule);
    _this._setMargins(labelModule);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   */
  _createClass(Circle, [{
    key: "resize",
    value: function resize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
      if (this.needsRefresh(selected, hover)) {
        var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
        var diameter = Math.max(dimensions.width + this.margin.right + this.margin.left, dimensions.height + this.margin.top + this.margin.bottom);
        this.options.size = diameter / 2; // NOTE: this size field only set here, not in Ellipse, Database, Box
        this.width = diameter;
        this.height = diameter;
        this.radius = this.width / 2;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.resize(ctx, selected, hover);
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;
      this._drawRawCircle(ctx, x, y, values);
      this.updateBoundingBox(x, y);
      this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, y, selected, hover);
    }

    /**
     *
     * @param {number} x width
     * @param {number} y height
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y) {
      this.boundingBox.top = y - this.options.size;
      this.boundingBox.left = x - this.options.size;
      this.boundingBox.right = x + this.options.size;
      this.boundingBox.bottom = y + this.options.size;
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx) {
      if (ctx) {
        this.resize(ctx);
      }
      return this.width * 0.5;
    }
  }]);
  return Circle;
}(CircleImageBase);

function _createSuper$p(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$p(); 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 _isNativeReflectConstruct$p() { 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; } }

/**
 * A CircularImage Node/Cluster shape.
 *
 * @augments CircleImageBase
 */
var CircularImage = /*#__PURE__*/function (_CircleImageBase) {
  _inherits(CircularImage, _CircleImageBase);
  var _super = _createSuper$p(CircularImage);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   * @param {Image} imageObj
   * @param {Image} imageObjAlt
   */
  function CircularImage(options, body, labelModule, imageObj, imageObjAlt) {
    var _this;
    _classCallCheck(this, CircularImage);
    _this = _super.call(this, options, body, labelModule);
    _this.setImages(imageObj, imageObjAlt);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   */
  _createClass(CircularImage, [{
    key: "resize",
    value: function resize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
      var imageAbsent = this.imageObj.src === undefined || this.imageObj.width === undefined || this.imageObj.height === undefined;
      if (imageAbsent) {
        var diameter = this.options.size * 2;
        this.width = diameter;
        this.height = diameter;
        this.radius = 0.5 * this.width;
        return;
      }

      // At this point, an image is present, i.e. this.imageObj is valid.
      if (this.needsRefresh(selected, hover)) {
        this._resizeImage();
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.switchImages(selected);
      this.resize();
      var labelX = x,
        labelY = y;
      if (this.options.shapeProperties.coordinateOrigin === "top-left") {
        this.left = x;
        this.top = y;
        labelX += this.width / 2;
        labelY += this.height / 2;
      } else {
        this.left = x - this.width / 2;
        this.top = y - this.height / 2;
      }

      // draw the background circle. IMPORTANT: the stroke in this method is used by the clip method below.
      this._drawRawCircle(ctx, labelX, labelY, values);

      // now we draw in the circle, we save so we can revert the clip operation after drawing.
      ctx.save();
      // clip is used to use the stroke in drawRawCircle as an area that we can draw in.
      ctx.clip();
      // draw the image
      this._drawImageAtPosition(ctx, values);
      // restore so we can again draw on the full canvas
      ctx.restore();
      this._drawImageLabel(ctx, labelX, labelY, selected, hover);
      this.updateBoundingBox(x, y);
    }

    // TODO: compare with Circle.updateBoundingBox(), consolidate? More stuff is happening here
    /**
     *
     * @param {number} x width
     * @param {number} y height
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y) {
      if (this.options.shapeProperties.coordinateOrigin === "top-left") {
        this.boundingBox.top = y;
        this.boundingBox.left = x;
        this.boundingBox.right = x + this.options.size * 2;
        this.boundingBox.bottom = y + this.options.size * 2;
      } else {
        this.boundingBox.top = y - this.options.size;
        this.boundingBox.left = x - this.options.size;
        this.boundingBox.right = x + this.options.size;
        this.boundingBox.bottom = y + this.options.size;
      }

      // TODO: compare with Image.updateBoundingBox(), consolidate?
      this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
      this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
      this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelOffset);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx) {
      if (ctx) {
        this.resize(ctx);
      }
      return this.width * 0.5;
    }
  }]);
  return CircularImage;
}(CircleImageBase);

function _createSuper$o(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$o(); 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 _isNativeReflectConstruct$o() { 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; } }

/**
 * Base class for constructing Node/Cluster Shapes.
 *
 * @augments NodeBase
 */
var ShapeBase = /*#__PURE__*/function (_NodeBase) {
  _inherits(ShapeBase, _NodeBase);
  var _super = _createSuper$o(ShapeBase);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function ShapeBase(options, body, labelModule) {
    _classCallCheck(this, ShapeBase);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   * @param {object} [values={size: this.options.size}]
   */
  _createClass(ShapeBase, [{
    key: "resize",
    value: function resize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
      var values = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
        size: this.options.size
      };
      if (this.needsRefresh(selected, hover)) {
        var _this$customSizeWidth, _this$customSizeHeigh;
        this.labelModule.getTextSize(ctx, selected, hover);
        var size = 2 * values.size;
        this.width = (_this$customSizeWidth = this.customSizeWidth) !== null && _this$customSizeWidth !== void 0 ? _this$customSizeWidth : size;
        this.height = (_this$customSizeHeigh = this.customSizeHeight) !== null && _this$customSizeHeigh !== void 0 ? _this$customSizeHeigh : size;
        this.radius = 0.5 * this.width;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {string} shape
     * @param {number} sizeMultiplier - Unused! TODO: Remove next major release
     * @param {number} x
     * @param {number} y
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     * @private
     * @returns {object} Callbacks to draw later on higher layers.
     */
  }, {
    key: "_drawShape",
    value: function _drawShape(ctx, shape, sizeMultiplier, x, y, selected, hover, values) {
      var _this = this;
      this.resize(ctx, selected, hover, values);
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;
      this.initContextForDraw(ctx, values);
      getShape(shape)(ctx, x, y, values.size);
      this.performFill(ctx, values);
      if (this.options.icon !== undefined) {
        if (this.options.icon.code !== undefined) {
          ctx.font = (selected ? "bold " : "") + this.height / 2 + "px " + (this.options.icon.face || "FontAwesome");
          ctx.fillStyle = this.options.icon.color || "black";
          ctx.textAlign = "center";
          ctx.textBaseline = "middle";
          ctx.fillText(this.options.icon.code, x, y);
        }
      }
      return {
        drawExternalLabel: function drawExternalLabel() {
          if (_this.options.label !== undefined) {
            // Need to call following here in order to ensure value for
            // `this.labelModule.size.height`.
            _this.labelModule.calculateLabelSize(ctx, selected, hover, x, y, "hanging");
            var yLabel = y + 0.5 * _this.height + 0.5 * _this.labelModule.size.height;
            _this.labelModule.draw(ctx, x, yLabel, selected, hover, "hanging");
          }
          _this.updateBoundingBox(x, y);
        }
      };
    }

    /**
     *
     * @param {number} x
     * @param {number} y
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y) {
      this.boundingBox.top = y - this.options.size;
      this.boundingBox.left = x - this.options.size;
      this.boundingBox.right = x + this.options.size;
      this.boundingBox.bottom = y + this.options.size;
      if (this.options.label !== undefined && this.labelModule.size.width > 0) {
        this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
        this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
        this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height);
      }
    }
  }]);
  return ShapeBase;
}(NodeBase);

function ownKeys$3(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor$1(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread$3(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys$3(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys$3(Object(source))).call(_context2, function (key) { _Object$defineProperty$1(target, key, _Object$getOwnPropertyDescriptor$1(source, key)); }); } return target; }
function _createSuper$n(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$n(); 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 _isNativeReflectConstruct$n() { 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; } }

/**
 * A CustomShape Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var CustomShape = /*#__PURE__*/function (_ShapeBase) {
  _inherits(CustomShape, _ShapeBase);
  var _super = _createSuper$n(CustomShape);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   * @param {Function} ctxRenderer
   */
  function CustomShape(options, body, labelModule, ctxRenderer) {
    var _this;
    _classCallCheck(this, CustomShape);
    _this = _super.call(this, options, body, labelModule, ctxRenderer);
    _this.ctxRenderer = ctxRenderer;
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x width
   * @param {number} y height
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on different layers.
   */
  _createClass(CustomShape, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.resize(ctx, selected, hover, values);
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;

      // Guard right away because someone may just draw in the function itself.
      ctx.save();
      var drawLater = this.ctxRenderer({
        ctx: ctx,
        id: this.options.id,
        x: x,
        y: y,
        state: {
          selected: selected,
          hover: hover
        },
        style: _objectSpread$3({}, values),
        label: this.options.label
      });
      // Render the node shape bellow arrows.
      if (drawLater.drawNode != null) {
        drawLater.drawNode();
      }
      ctx.restore();
      if (drawLater.drawExternalLabel) {
        // Guard the external label (above arrows) drawing function.
        var drawExternalLabel = drawLater.drawExternalLabel;
        drawLater.drawExternalLabel = function () {
          ctx.save();
          drawExternalLabel();
          ctx.restore();
        };
      }
      if (drawLater.nodeDimensions) {
        this.customSizeWidth = drawLater.nodeDimensions.width;
        this.customSizeHeight = drawLater.nodeDimensions.height;
      }
      return drawLater;
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return CustomShape;
}(ShapeBase);

function _createSuper$m(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$m(); 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 _isNativeReflectConstruct$m() { 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; } }

/**
 * A Database Node/Cluster shape.
 *
 * @augments NodeBase
 */
var Database = /*#__PURE__*/function (_NodeBase) {
  _inherits(Database, _NodeBase);
  var _super = _createSuper$m(Database);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Database(options, body, labelModule) {
    var _this;
    _classCallCheck(this, Database);
    _this = _super.call(this, options, body, labelModule);
    _this._setMargins(labelModule);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} selected
   * @param {boolean} hover
   */
  _createClass(Database, [{
    key: "resize",
    value: function resize(ctx, selected, hover) {
      if (this.needsRefresh(selected, hover)) {
        var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
        var size = dimensions.width + this.margin.right + this.margin.left;
        this.width = size;
        this.height = size;
        this.radius = this.width / 2;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.resize(ctx, selected, hover);
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;
      this.initContextForDraw(ctx, values);
      drawDatabase(ctx, x - this.width / 2, y - this.height / 2, this.width, this.height);
      this.performFill(ctx, values);
      this.updateBoundingBox(x, y, ctx, selected, hover);
      this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, this.top + this.textSize.height / 2 + this.margin.top, selected, hover);
    }
    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Database;
}(NodeBase);

function _createSuper$l(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$l(); 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 _isNativeReflectConstruct$l() { 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; } }

/**
 * A Diamond Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var Diamond$1 = /*#__PURE__*/function (_ShapeBase) {
  _inherits(Diamond, _ShapeBase);
  var _super = _createSuper$l(Diamond);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Diamond(options, body, labelModule) {
    _classCallCheck(this, Diamond);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x width
   * @param {number} y height
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(Diamond, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "diamond", 4, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Diamond;
}(ShapeBase);

function _createSuper$k(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$k(); 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 _isNativeReflectConstruct$k() { 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; } }

/**
 * A Dot Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var Dot = /*#__PURE__*/function (_ShapeBase) {
  _inherits(Dot, _ShapeBase);
  var _super = _createSuper$k(Dot);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Dot(options, body, labelModule) {
    _classCallCheck(this, Dot);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x width
   * @param {number} y height
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(Dot, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "circle", 2, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx) {
      if (ctx) {
        this.resize(ctx);
      }
      return this.options.size;
    }
  }]);
  return Dot;
}(ShapeBase);

function _createSuper$j(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$j(); 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 _isNativeReflectConstruct$j() { 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; } }

/**
 * Am Ellipse Node/Cluster shape.
 *
 * @augments NodeBase
 */
var Ellipse$2 = /*#__PURE__*/function (_NodeBase) {
  _inherits(Ellipse, _NodeBase);
  var _super = _createSuper$j(Ellipse);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Ellipse(options, body, labelModule) {
    _classCallCheck(this, Ellipse);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   */
  _createClass(Ellipse, [{
    key: "resize",
    value: function resize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
      if (this.needsRefresh(selected, hover)) {
        var dimensions = this.getDimensionsFromLabel(ctx, selected, hover);
        this.height = dimensions.height * 2;
        this.width = dimensions.width + dimensions.height;
        this.radius = 0.5 * this.width;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.resize(ctx, selected, hover);
      this.left = x - this.width * 0.5;
      this.top = y - this.height * 0.5;
      this.initContextForDraw(ctx, values);
      drawEllipse(ctx, this.left, this.top, this.width, this.height);
      this.performFill(ctx, values);
      this.updateBoundingBox(x, y, ctx, selected, hover);
      this.labelModule.draw(ctx, x, y, selected, hover);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      if (ctx) {
        this.resize(ctx);
      }
      var a = this.width * 0.5;
      var b = this.height * 0.5;
      var w = Math.sin(angle) * a;
      var h = Math.cos(angle) * b;
      return a * b / Math.sqrt(w * w + h * h);
    }
  }]);
  return Ellipse;
}(NodeBase);

function _createSuper$i(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$i(); 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 _isNativeReflectConstruct$i() { 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; } }

/**
 * An icon replacement for the default Node shape.
 *
 * @augments NodeBase
 */
var Icon = /*#__PURE__*/function (_NodeBase) {
  _inherits(Icon, _NodeBase);
  var _super = _createSuper$i(Icon);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Icon(options, body, labelModule) {
    var _this;
    _classCallCheck(this, Icon);
    _this = _super.call(this, options, body, labelModule);
    _this._setMargins(labelModule);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx - Unused.
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   */
  _createClass(Icon, [{
    key: "resize",
    value: function resize(ctx, selected, hover) {
      if (this.needsRefresh(selected, hover)) {
        this.iconSize = {
          width: Number(this.options.icon.size),
          height: Number(this.options.icon.size)
        };
        this.width = this.iconSize.width + this.margin.right + this.margin.left;
        this.height = this.iconSize.height + this.margin.top + this.margin.bottom;
        this.radius = 0.5 * this.width;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     * @returns {object} Callbacks to draw later on higher layers.
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      var _this2 = this;
      this.resize(ctx, selected, hover);
      this.options.icon.size = this.options.icon.size || 50;
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;
      this._icon(ctx, x, y, selected, hover, values);
      return {
        drawExternalLabel: function drawExternalLabel() {
          if (_this2.options.label !== undefined) {
            var iconTextSpacing = 5;
            _this2.labelModule.draw(ctx, _this2.left + _this2.iconSize.width / 2 + _this2.margin.left, y + _this2.height / 2 + iconTextSpacing, selected);
          }
          _this2.updateBoundingBox(x, y);
        }
      };
    }

    /**
     *
     * @param {number} x
     * @param {number} y
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y) {
      this.boundingBox.top = y - this.options.icon.size * 0.5;
      this.boundingBox.left = x - this.options.icon.size * 0.5;
      this.boundingBox.right = x + this.options.icon.size * 0.5;
      this.boundingBox.bottom = y + this.options.icon.size * 0.5;
      if (this.options.label !== undefined && this.labelModule.size.width > 0) {
        var iconTextSpacing = 5;
        this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
        this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
        this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height + iconTextSpacing);
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover - Unused
     * @param {ArrowOptions} values
     */
  }, {
    key: "_icon",
    value: function _icon(ctx, x, y, selected, hover, values) {
      var iconSize = Number(this.options.icon.size);
      if (this.options.icon.code !== undefined) {
        ctx.font = [this.options.icon.weight != null ? this.options.icon.weight : selected ? "bold" : "",
        // If the weight is forced (for example to make Font Awesome 5 work
        // properly) substitute slightly bigger size for bold font face.
        (this.options.icon.weight != null && selected ? 5 : 0) + iconSize + "px", this.options.icon.face].join(" ");

        // draw icon
        ctx.fillStyle = this.options.icon.color || "black";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";

        // draw shadow if enabled
        this.enableShadow(ctx, values);
        ctx.fillText(this.options.icon.code, x, y);

        // disable shadows for other elements.
        this.disableShadow(ctx, values);
      } else {
        console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.");
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Icon;
}(NodeBase);

function _createSuper$h(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$h(); 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 _isNativeReflectConstruct$h() { 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; } }

/**
 * An image-based replacement for the default Node shape.
 *
 * @augments CircleImageBase
 */
var Image$2 = /*#__PURE__*/function (_CircleImageBase) {
  _inherits(Image, _CircleImageBase);
  var _super = _createSuper$h(Image);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   * @param {Image} imageObj
   * @param {Image} imageObjAlt
   */
  function Image(options, body, labelModule, imageObj, imageObjAlt) {
    var _this;
    _classCallCheck(this, Image);
    _this = _super.call(this, options, body, labelModule);
    _this.setImages(imageObj, imageObjAlt);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx - Unused.
   * @param {boolean} [selected]
   * @param {boolean} [hover]
   */
  _createClass(Image, [{
    key: "resize",
    value: function resize(ctx) {
      var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.selected;
      var hover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hover;
      var imageAbsent = this.imageObj.src === undefined || this.imageObj.width === undefined || this.imageObj.height === undefined;
      if (imageAbsent) {
        var side = this.options.size * 2;
        this.width = side;
        this.height = side;
        return;
      }
      if (this.needsRefresh(selected, hover)) {
        this._resizeImage();
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      ctx.save();
      this.switchImages(selected);
      this.resize();
      var labelX = x,
        labelY = y;
      if (this.options.shapeProperties.coordinateOrigin === "top-left") {
        this.left = x;
        this.top = y;
        labelX += this.width / 2;
        labelY += this.height / 2;
      } else {
        this.left = x - this.width / 2;
        this.top = y - this.height / 2;
      }
      if (this.options.shapeProperties.useBorderWithImage === true) {
        var neutralborderWidth = this.options.borderWidth;
        var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth;
        var borderWidth = (selected ? selectionLineWidth : neutralborderWidth) / this.body.view.scale;
        ctx.lineWidth = Math.min(this.width, borderWidth);
        ctx.beginPath();
        var strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border;
        var fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background;
        if (values.opacity !== undefined) {
          strokeStyle = overrideOpacity(strokeStyle, values.opacity);
          fillStyle = overrideOpacity(fillStyle, values.opacity);
        }
        // setup the line properties.
        ctx.strokeStyle = strokeStyle;

        // set a fillstyle
        ctx.fillStyle = fillStyle;

        // draw a rectangle to form the border around. This rectangle is filled so the opacity of a picture (in future vis releases?) can be used to tint the image
        ctx.rect(this.left - 0.5 * ctx.lineWidth, this.top - 0.5 * ctx.lineWidth, this.width + ctx.lineWidth, this.height + ctx.lineWidth);
        _fillInstanceProperty(ctx).call(ctx);
        this.performStroke(ctx, values);
        ctx.closePath();
      }
      this._drawImageAtPosition(ctx, values);
      this._drawImageLabel(ctx, labelX, labelY, selected, hover);
      this.updateBoundingBox(x, y);
      ctx.restore();
    }

    /**
     *
     * @param {number} x
     * @param {number} y
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(x, y) {
      this.resize();
      if (this.options.shapeProperties.coordinateOrigin === "top-left") {
        this.left = x;
        this.top = y;
      } else {
        this.left = x - this.width / 2;
        this.top = y - this.height / 2;
      }
      this.boundingBox.left = this.left;
      this.boundingBox.top = this.top;
      this.boundingBox.bottom = this.top + this.height;
      this.boundingBox.right = this.left + this.width;
      if (this.options.label !== undefined && this.labelModule.size.width > 0) {
        this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left);
        this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width);
        this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelOffset);
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Image;
}(CircleImageBase);

function _createSuper$g(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$g(); 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 _isNativeReflectConstruct$g() { 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; } }

/**
 * A Square Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var Square = /*#__PURE__*/function (_ShapeBase) {
  _inherits(Square, _ShapeBase);
  var _super = _createSuper$g(Square);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Square(options, body, labelModule) {
    _classCallCheck(this, Square);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x width
   * @param {number} y height
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(Square, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "square", 2, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Square;
}(ShapeBase);

function _createSuper$f(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$f(); 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 _isNativeReflectConstruct$f() { 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; } }

/**
 * A Hexagon Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var Hexagon = /*#__PURE__*/function (_ShapeBase) {
  _inherits(Hexagon, _ShapeBase);
  var _super = _createSuper$f(Hexagon);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Hexagon(options, body, labelModule) {
    _classCallCheck(this, Hexagon);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x width
   * @param {number} y height
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(Hexagon, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "hexagon", 4, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Hexagon;
}(ShapeBase);

function _createSuper$e(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$e(); 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 _isNativeReflectConstruct$e() { 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; } }

/**
 * A Star Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var Star = /*#__PURE__*/function (_ShapeBase) {
  _inherits(Star, _ShapeBase);
  var _super = _createSuper$e(Star);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Star(options, body, labelModule) {
    _classCallCheck(this, Star);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x width
   * @param {number} y height
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(Star, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "star", 4, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Star;
}(ShapeBase);

function _createSuper$d(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$d(); 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 _isNativeReflectConstruct$d() { 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; } }

/**
 * A text-based replacement for the default Node shape.
 *
 * @augments NodeBase
 */
var Text = /*#__PURE__*/function (_NodeBase) {
  _inherits(Text, _NodeBase);
  var _super = _createSuper$d(Text);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Text(options, body, labelModule) {
    var _this;
    _classCallCheck(this, Text);
    _this = _super.call(this, options, body, labelModule);
    _this._setMargins(labelModule);
    return _this;
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {boolean} selected
   * @param {boolean} hover
   */
  _createClass(Text, [{
    key: "resize",
    value: function resize(ctx, selected, hover) {
      if (this.needsRefresh(selected, hover)) {
        this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
        this.width = this.textSize.width + this.margin.right + this.margin.left;
        this.height = this.textSize.height + this.margin.top + this.margin.bottom;
        this.radius = 0.5 * this.width;
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} x width
     * @param {number} y height
     * @param {boolean} selected
     * @param {boolean} hover
     * @param {ArrowOptions} values
     */
  }, {
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      this.resize(ctx, selected, hover);
      this.left = x - this.width / 2;
      this.top = y - this.height / 2;

      // draw shadow if enabled
      this.enableShadow(ctx, values);
      this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, this.top + this.textSize.height / 2 + this.margin.top, selected, hover);

      // disable shadows for other elements.
      this.disableShadow(ctx, values);
      this.updateBoundingBox(x, y, ctx, selected, hover);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Text;
}(NodeBase);

function _createSuper$c(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$c(); 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 _isNativeReflectConstruct$c() { 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; } }

/**
 * A Triangle Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var Triangle$1 = /*#__PURE__*/function (_ShapeBase) {
  _inherits(Triangle, _ShapeBase);
  var _super = _createSuper$c(Triangle);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function Triangle(options, body, labelModule) {
    _classCallCheck(this, Triangle);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x
   * @param {number} y
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(Triangle, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "triangle", 3, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return Triangle;
}(ShapeBase);

function _createSuper$b(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$b(); 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 _isNativeReflectConstruct$b() { 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; } }

/**
 * A downward facing Triangle Node/Cluster shape.
 *
 * @augments ShapeBase
 */
var TriangleDown = /*#__PURE__*/function (_ShapeBase) {
  _inherits(TriangleDown, _ShapeBase);
  var _super = _createSuper$b(TriangleDown);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Label} labelModule
   */
  function TriangleDown(options, body, labelModule) {
    _classCallCheck(this, TriangleDown);
    return _super.call(this, options, body, labelModule);
  }

  /**
   *
   * @param {CanvasRenderingContext2D} ctx
   * @param {number} x
   * @param {number} y
   * @param {boolean} selected
   * @param {boolean} hover
   * @param {ArrowOptions} values
   * @returns {object} Callbacks to draw later on higher layers.
   */
  _createClass(TriangleDown, [{
    key: "draw",
    value: function draw(ctx, x, y, selected, hover, values) {
      return this._drawShape(ctx, "triangleDown", 3, x, y, selected, hover, values);
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {number} angle
     * @returns {number}
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this._distanceToBorder(ctx, angle);
    }
  }]);
  return TriangleDown;
}(ShapeBase);

function ownKeys$2(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor$1(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread$2(target) { for (var i = 1; i < arguments.length; i++) { var _context5, _context6; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context5 = ownKeys$2(Object(source), !0)).call(_context5, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context6 = ownKeys$2(Object(source))).call(_context6, function (key) { _Object$defineProperty$1(target, key, _Object$getOwnPropertyDescriptor$1(source, key)); }); } return target; }

/**
 * A node. A node can be connected to other nodes via one or multiple edges.
 */
var Node = /*#__PURE__*/function () {
  /**
   *
   * @param {object} options An object containing options for the node. All
   *                            options are optional, except for the id.
   *                              {number} id     Id of the node. Required
   *                              {string} label  Text label for the node
   *                              {number} x      Horizontal position of the node
   *                              {number} y      Vertical position of the node
   *                              {string} shape  Node shape
   *                              {string} image  An image url
   *                              {string} title  A title text, can be HTML
   *                              {anytype} group A group name or number
   * @param {object} body               Shared state of current network instance
   * @param {Network.Images} imagelist  A list with images. Only needed when the node has an image
   * @param {Groups} grouplist          A list with groups. Needed for retrieving group options
   * @param {object} globalOptions      Current global node options; these serve as defaults for the node instance
   * @param {object} defaultOptions     Global default options for nodes; note that this is also the prototype
   *                                    for parameter `globalOptions`.
   */
  function Node(options, body, imagelist, grouplist, globalOptions, defaultOptions) {
    _classCallCheck(this, Node);
    this.options = bridgeObject(globalOptions);
    this.globalOptions = globalOptions;
    this.defaultOptions = defaultOptions;
    this.body = body;
    this.edges = []; // all edges connected to this node

    // set defaults for the options
    this.id = undefined;
    this.imagelist = imagelist;
    this.grouplist = grouplist;

    // state options
    this.x = undefined;
    this.y = undefined;
    this.baseSize = this.options.size;
    this.baseFontSize = this.options.font.size;
    this.predefinedPosition = false; // used to check if initial fit should just take the range or approximate
    this.selected = false;
    this.hover = false;
    this.labelModule = new Label(this.body, this.options, false /* Not edge label */);

    this.setOptions(options);
  }

  /**
   * Attach a edge to the node
   *
   * @param {Edge} edge
   */
  _createClass(Node, [{
    key: "attachEdge",
    value: function attachEdge(edge) {
      var _context;
      if (_indexOfInstanceProperty(_context = this.edges).call(_context, edge) === -1) {
        this.edges.push(edge);
      }
    }

    /**
     * Detach a edge from the node
     *
     * @param {Edge} edge
     */
  }, {
    key: "detachEdge",
    value: function detachEdge(edge) {
      var _context2;
      var index = _indexOfInstanceProperty(_context2 = this.edges).call(_context2, edge);
      if (index != -1) {
        var _context3;
        _spliceInstanceProperty(_context3 = this.edges).call(_context3, index, 1);
      }
    }

    /**
     * Set or overwrite options for the node
     *
     * @param {object} options an object with options
     * @returns {null|boolean}
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      var currentShape = this.options.shape;
      if (!options) {
        return; // Note that the return value will be 'undefined'! This is OK.
      }

      // Save the color for later.
      // This is necessary in order to prevent local color from being overwritten by group color.
      // TODO: To prevent such workarounds the way options are handled should be rewritten from scratch.
      // This is not the only problem with current options handling.
      if (typeof options.color !== "undefined") {
        this._localColor = options.color;
      }

      // basic options
      if (options.id !== undefined) {
        this.id = options.id;
      }
      if (this.id === undefined) {
        throw new Error("Node must have an id");
      }
      Node.checkMass(options, this.id);

      // set these options locally
      // clear x and y positions
      if (options.x !== undefined) {
        if (options.x === null) {
          this.x = undefined;
          this.predefinedPosition = false;
        } else {
          this.x = _parseInt(options.x);
          this.predefinedPosition = true;
        }
      }
      if (options.y !== undefined) {
        if (options.y === null) {
          this.y = undefined;
          this.predefinedPosition = false;
        } else {
          this.y = _parseInt(options.y);
          this.predefinedPosition = true;
        }
      }
      if (options.size !== undefined) {
        this.baseSize = options.size;
      }
      if (options.value !== undefined) {
        options.value = _parseFloat(options.value);
      }

      // this transforms all shorthands into fully defined options
      Node.parseOptions(this.options, options, true, this.globalOptions, this.grouplist);
      var pile = [options, this.options, this.defaultOptions];
      this.chooser = choosify("node", pile);
      this._load_images();
      this.updateLabelModule(options);

      // Need to set local opacity after `this.updateLabelModule(options);` because `this.updateLabelModule(options);` overrites local opacity with group opacity
      if (options.opacity !== undefined && Node.checkOpacity(options.opacity)) {
        this.options.opacity = options.opacity;
      }
      this.updateShape(currentShape);
      return options.hidden !== undefined || options.physics !== undefined;
    }

    /**
     * Load the images from the options, for the nodes that need them.
     *
     * Images are always loaded, even if they are not used in the current shape.
     * The user may switch to an image shape later on.
     *
     * @private
     */
  }, {
    key: "_load_images",
    value: function _load_images() {
      if (this.options.shape === "circularImage" || this.options.shape === "image") {
        if (this.options.image === undefined) {
          throw new Error("Option image must be defined for node type '" + this.options.shape + "'");
        }
      }
      if (this.options.image === undefined) {
        return;
      }
      if (this.imagelist === undefined) {
        throw new Error("Internal Error: No images provided");
      }
      if (typeof this.options.image === "string") {
        this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage, this.id);
      } else {
        if (this.options.image.unselected === undefined) {
          throw new Error("No unselected image provided");
        }
        this.imageObj = this.imagelist.load(this.options.image.unselected, this.options.brokenImage, this.id);
        if (this.options.image.selected !== undefined) {
          this.imageObjAlt = this.imagelist.load(this.options.image.selected, this.options.brokenImage, this.id);
        } else {
          this.imageObjAlt = undefined;
        }
      }
    }

    /**
     * Check that opacity is only between 0 and 1
     *
     * @param {number} opacity
     * @returns {boolean}
     */
  }, {
    key: "getFormattingValues",
    value:
    /**
     *
     * @returns {{color: *, borderWidth: *, borderColor: *, size: *, borderDashes: (boolean|Array|allOptions.nodes.shapeProperties.borderDashes|{boolean, array}), borderRadius: (number|allOptions.nodes.shapeProperties.borderRadius|{number}|Array), shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *}}
     */
    function getFormattingValues() {
      var values = {
        color: this.options.color.background,
        opacity: this.options.opacity,
        borderWidth: this.options.borderWidth,
        borderColor: this.options.color.border,
        size: this.options.size,
        borderDashes: this.options.shapeProperties.borderDashes,
        borderRadius: this.options.shapeProperties.borderRadius,
        shadow: this.options.shadow.enabled,
        shadowColor: this.options.shadow.color,
        shadowSize: this.options.shadow.size,
        shadowX: this.options.shadow.x,
        shadowY: this.options.shadow.y
      };
      if (this.selected || this.hover) {
        if (this.chooser === true) {
          if (this.selected) {
            if (this.options.borderWidthSelected != null) {
              values.borderWidth = this.options.borderWidthSelected;
            } else {
              values.borderWidth *= 2;
            }
            values.color = this.options.color.highlight.background;
            values.borderColor = this.options.color.highlight.border;
            values.shadow = this.options.shadow.enabled;
          } else if (this.hover) {
            values.color = this.options.color.hover.background;
            values.borderColor = this.options.color.hover.border;
            values.shadow = this.options.shadow.enabled;
          }
        } else if (typeof this.chooser === "function") {
          this.chooser(values, this.options.id, this.selected, this.hover);
          if (values.shadow === false) {
            if (values.shadowColor !== this.options.shadow.color || values.shadowSize !== this.options.shadow.size || values.shadowX !== this.options.shadow.x || values.shadowY !== this.options.shadow.y) {
              values.shadow = true;
            }
          }
        }
      } else {
        values.shadow = this.options.shadow.enabled;
      }
      if (this.options.opacity !== undefined) {
        var opacity = this.options.opacity;
        values.borderColor = overrideOpacity(values.borderColor, opacity);
        values.color = overrideOpacity(values.color, opacity);
        values.shadowColor = overrideOpacity(values.shadowColor, opacity);
      }
      return values;
    }

    /**
     *
     * @param {object} options
     */
  }, {
    key: "updateLabelModule",
    value: function updateLabelModule(options) {
      if (this.options.label === undefined || this.options.label === null) {
        this.options.label = "";
      }
      Node.updateGroupOptions(this.options, _objectSpread$2(_objectSpread$2({}, options), {}, {
        color: options && options.color || this._localColor || undefined
      }), this.grouplist);

      //
      // Note:The prototype chain for this.options is:
      //
      // this.options ->    NodesHandler.options    -> NodesHandler.defaultOptions
      //                 (also: this.globalOptions)
      //
      // Note that the prototypes are mentioned explicitly in the pile list below;
      // WE DON'T WANT THE ORDER OF THE PROTOTYPES!!!! At least, not for font handling of labels.
      // This is a good indication that the prototype usage of options is deficient.
      //
      var currentGroup = this.grouplist.get(this.options.group, false);
      var pile = [options,
      // new options
      this.options,
      // current node options, see comment above for prototype
      currentGroup,
      // group options, if any
      this.globalOptions,
      // Currently set global node options
      this.defaultOptions // Default global node options
      ];

      this.labelModule.update(this.options, pile);
      if (this.labelModule.baseSize !== undefined) {
        this.baseFontSize = this.labelModule.baseSize;
      }
    }

    /**
     *
     * @param {string} currentShape
     */
  }, {
    key: "updateShape",
    value: function updateShape(currentShape) {
      if (currentShape === this.options.shape && this.shape) {
        this.shape.setOptions(this.options, this.imageObj, this.imageObjAlt);
      } else {
        // choose draw method depending on the shape
        switch (this.options.shape) {
          case "box":
            this.shape = new Box$1(this.options, this.body, this.labelModule);
            break;
          case "circle":
            this.shape = new Circle$1$1(this.options, this.body, this.labelModule);
            break;
          case "circularImage":
            this.shape = new CircularImage(this.options, this.body, this.labelModule, this.imageObj, this.imageObjAlt);
            break;
          case "custom":
            this.shape = new CustomShape(this.options, this.body, this.labelModule, this.options.ctxRenderer);
            break;
          case "database":
            this.shape = new Database(this.options, this.body, this.labelModule);
            break;
          case "diamond":
            this.shape = new Diamond$1(this.options, this.body, this.labelModule);
            break;
          case "dot":
            this.shape = new Dot(this.options, this.body, this.labelModule);
            break;
          case "ellipse":
            this.shape = new Ellipse$2(this.options, this.body, this.labelModule);
            break;
          case "icon":
            this.shape = new Icon(this.options, this.body, this.labelModule);
            break;
          case "image":
            this.shape = new Image$2(this.options, this.body, this.labelModule, this.imageObj, this.imageObjAlt);
            break;
          case "square":
            this.shape = new Square(this.options, this.body, this.labelModule);
            break;
          case "hexagon":
            this.shape = new Hexagon(this.options, this.body, this.labelModule);
            break;
          case "star":
            this.shape = new Star(this.options, this.body, this.labelModule);
            break;
          case "text":
            this.shape = new Text(this.options, this.body, this.labelModule);
            break;
          case "triangle":
            this.shape = new Triangle$1(this.options, this.body, this.labelModule);
            break;
          case "triangleDown":
            this.shape = new TriangleDown(this.options, this.body, this.labelModule);
            break;
          default:
            this.shape = new Ellipse$2(this.options, this.body, this.labelModule);
            break;
        }
      }
      this.needsRefresh();
    }

    /**
     * select this node
     */
  }, {
    key: "select",
    value: function select() {
      this.selected = true;
      this.needsRefresh();
    }

    /**
     * unselect this node
     */
  }, {
    key: "unselect",
    value: function unselect() {
      this.selected = false;
      this.needsRefresh();
    }

    /**
     * Reset the calculated size of the node, forces it to recalculate its size
     */
  }, {
    key: "needsRefresh",
    value: function needsRefresh() {
      this.shape.refreshNeeded = true;
    }

    /**
     * get the title of this node.
     *
     * @returns {string} title    The title of the node, or undefined when no title
     *                           has been set.
     */
  }, {
    key: "getTitle",
    value: function getTitle() {
      return this.options.title;
    }

    /**
     * Calculate the distance to the border of the Node
     *
     * @param {CanvasRenderingContext2D}   ctx
     * @param {number} angle        Angle in radians
     * @returns {number} distance   Distance to the border in pixels
     */
  }, {
    key: "distanceToBorder",
    value: function distanceToBorder(ctx, angle) {
      return this.shape.distanceToBorder(ctx, angle);
    }

    /**
     * Check if this node has a fixed x and y position
     *
     * @returns {boolean}      true if fixed, false if not
     */
  }, {
    key: "isFixed",
    value: function isFixed() {
      return this.options.fixed.x && this.options.fixed.y;
    }

    /**
     * check if this node is selecte
     *
     * @returns {boolean} selected   True if node is selected, else false
     */
  }, {
    key: "isSelected",
    value: function isSelected() {
      return this.selected;
    }

    /**
     * Retrieve the value of the node. Can be undefined
     *
     * @returns {number} value
     */
  }, {
    key: "getValue",
    value: function getValue() {
      return this.options.value;
    }

    /**
     * Get the current dimensions of the label
     *
     * @returns {rect}
     */
  }, {
    key: "getLabelSize",
    value: function getLabelSize() {
      return this.labelModule.size();
    }

    /**
     * Adjust the value range of the node. The node will adjust it's size
     * based on its value.
     *
     * @param {number} min
     * @param {number} max
     * @param {number} total
     */
  }, {
    key: "setValueRange",
    value: function setValueRange(min, max, total) {
      if (this.options.value !== undefined) {
        var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value);
        var sizeDiff = this.options.scaling.max - this.options.scaling.min;
        if (this.options.scaling.label.enabled === true) {
          var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min;
          this.options.font.size = this.options.scaling.label.min + scale * fontDiff;
        }
        this.options.size = this.options.scaling.min + scale * sizeDiff;
      } else {
        this.options.size = this.baseSize;
        this.options.font.size = this.baseFontSize;
      }
      this.updateLabelModule();
    }

    /**
     * Draw this node in the given canvas
     * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
     *
     * @param {CanvasRenderingContext2D}   ctx
     * @returns {object} Callbacks to draw later on higher layers.
     */
  }, {
    key: "draw",
    value: function draw(ctx) {
      var values = this.getFormattingValues();
      return this.shape.draw(ctx, this.x, this.y, this.selected, this.hover, values) || {};
    }

    /**
     * Update the bounding box of the shape
     *
     * @param {CanvasRenderingContext2D}   ctx
     */
  }, {
    key: "updateBoundingBox",
    value: function updateBoundingBox(ctx) {
      this.shape.updateBoundingBox(this.x, this.y, ctx);
    }

    /**
     * Recalculate the size of this node in the given canvas
     * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
     *
     * @param {CanvasRenderingContext2D}   ctx
     */
  }, {
    key: "resize",
    value: function resize(ctx) {
      var values = this.getFormattingValues();
      this.shape.resize(ctx, this.selected, this.hover, values);
    }

    /**
     * Determine all visual elements of this node instance, in which the given
     * point falls within the bounding shape.
     *
     * @param {point} point
     * @returns {Array.<nodeClickItem|nodeLabelClickItem>} list with the items which are on the point
     */
  }, {
    key: "getItemsOnPoint",
    value: function getItemsOnPoint(point) {
      var ret = [];
      if (this.labelModule.visible()) {
        if (pointInRect(this.labelModule.getSize(), point)) {
          ret.push({
            nodeId: this.id,
            labelId: 0
          });
        }
      }
      if (pointInRect(this.shape.boundingBox, point)) {
        ret.push({
          nodeId: this.id
        });
      }
      return ret;
    }

    /**
     * Check if this object is overlapping with the provided object
     *
     * @param {object} obj   an object with parameters left, top, right, bottom
     * @returns {boolean}     True if location is located on node
     */
  }, {
    key: "isOverlappingWith",
    value: function isOverlappingWith(obj) {
      return this.shape.left < obj.right && this.shape.left + this.shape.width > obj.left && this.shape.top < obj.bottom && this.shape.top + this.shape.height > obj.top;
    }

    /**
     * Check if this object is overlapping with the provided object
     *
     * @param {object} obj   an object with parameters left, top, right, bottom
     * @returns {boolean}     True if location is located on node
     */
  }, {
    key: "isBoundingBoxOverlappingWith",
    value: function isBoundingBoxOverlappingWith(obj) {
      return this.shape.boundingBox.left < obj.right && this.shape.boundingBox.right > obj.left && this.shape.boundingBox.top < obj.bottom && this.shape.boundingBox.bottom > obj.top;
    }

    /**
     * Check valid values for mass
     *
     * The mass may not be negative or zero. If it is, reset to 1
     *
     * @param {object} options
     * @param {Node.id} id
     * @static
     */
  }], [{
    key: "checkOpacity",
    value: function checkOpacity(opacity) {
      return 0 <= opacity && opacity <= 1;
    }

    /**
     * Check that origin is 'center' or 'top-left'
     *
     * @param {string} origin
     * @returns {boolean}
     */
  }, {
    key: "checkCoordinateOrigin",
    value: function checkCoordinateOrigin(origin) {
      return origin === undefined || origin === "center" || origin === "top-left";
    }

    /**
     * Copy group option values into the node options.
     *
     * The group options override the global node options, so the copy of group options
     *  must happen *after* the global node options have been set.
     *
     * This method must also be called also if the global node options have changed and the group options did not.
     *
     * @param {object} parentOptions
     * @param {object} newOptions  new values for the options, currently only passed in for check
     * @param {object} groupList
     */
  }, {
    key: "updateGroupOptions",
    value: function updateGroupOptions(parentOptions, newOptions, groupList) {
      var _context4;
      if (groupList === undefined) return; // No groups, nothing to do

      var group = parentOptions.group;

      // paranoia: the selected group is already merged into node options, check.
      if (newOptions !== undefined && newOptions.group !== undefined && group !== newOptions.group) {
        throw new Error("updateGroupOptions: group values in options don't match.");
      }
      var hasGroup = typeof group === "number" || typeof group === "string" && group != "";
      if (!hasGroup) return; // current node has no group, no need to merge

      var groupObj = groupList.get(group);
      if (groupObj.opacity !== undefined && newOptions.opacity === undefined) {
        if (!Node.checkOpacity(groupObj.opacity)) {
          console.error("Invalid option for node opacity. Value must be between 0 and 1, found: " + groupObj.opacity);
          groupObj.opacity = undefined;
        }
      }

      // Skip any new option to avoid them being overridden by the group options.
      var skipProperties = _filterInstanceProperty(_context4 = _Object$getOwnPropertyNames(newOptions)).call(_context4, function (p) {
        return newOptions[p] != null;
      });
      // Always skip merging group font options into parent; these are required to be distinct for labels
      skipProperties.push("font");
      selectiveNotDeepExtend(skipProperties, parentOptions, groupObj);

      // the color object needs to be completely defined.
      // Since groups can partially overwrite the colors, we parse it again, just in case.
      parentOptions.color = parseColor(parentOptions.color);
    }

    /**
     * This process all possible shorthands in the new options and makes sure that the parentOptions are fully defined.
     * Static so it can also be used by the handler.
     *
     * @param {object} parentOptions
     * @param {object} newOptions
     * @param {boolean} [allowDeletion=false]
     * @param {object} [globalOptions={}]
     * @param {object} [groupList]
     * @static
     */
  }, {
    key: "parseOptions",
    value: function parseOptions(parentOptions, newOptions) {
      var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
      var groupList = arguments.length > 4 ? arguments[4] : undefined;
      var fields = ["color", "fixed", "shadow"];
      selectiveNotDeepExtend(fields, parentOptions, newOptions, allowDeletion);
      Node.checkMass(newOptions);
      if (parentOptions.opacity !== undefined) {
        if (!Node.checkOpacity(parentOptions.opacity)) {
          console.error("Invalid option for node opacity. Value must be between 0 and 1, found: " + parentOptions.opacity);
          parentOptions.opacity = undefined;
        }
      }
      if (newOptions.opacity !== undefined) {
        if (!Node.checkOpacity(newOptions.opacity)) {
          console.error("Invalid option for node opacity. Value must be between 0 and 1, found: " + newOptions.opacity);
          newOptions.opacity = undefined;
        }
      }
      if (newOptions.shapeProperties && !Node.checkCoordinateOrigin(newOptions.shapeProperties.coordinateOrigin)) {
        console.error("Invalid option for node coordinateOrigin, found: " + newOptions.shapeProperties.coordinateOrigin);
      }

      // merge the shadow options into the parent.
      mergeOptions(parentOptions, newOptions, "shadow", globalOptions);

      // individual shape newOptions
      if (newOptions.color !== undefined && newOptions.color !== null) {
        var parsedColor = parseColor(newOptions.color);
        fillIfDefined(parentOptions.color, parsedColor);
      } else if (allowDeletion === true && newOptions.color === null) {
        parentOptions.color = bridgeObject(globalOptions.color); // set the object back to the global options
      }

      // handle the fixed options
      if (newOptions.fixed !== undefined && newOptions.fixed !== null) {
        if (typeof newOptions.fixed === "boolean") {
          parentOptions.fixed.x = newOptions.fixed;
          parentOptions.fixed.y = newOptions.fixed;
        } else {
          if (newOptions.fixed.x !== undefined && typeof newOptions.fixed.x === "boolean") {
            parentOptions.fixed.x = newOptions.fixed.x;
          }
          if (newOptions.fixed.y !== undefined && typeof newOptions.fixed.y === "boolean") {
            parentOptions.fixed.y = newOptions.fixed.y;
          }
        }
      }
      if (allowDeletion === true && newOptions.font === null) {
        parentOptions.font = bridgeObject(globalOptions.font); // set the object back to the global options
      }

      Node.updateGroupOptions(parentOptions, newOptions, groupList);

      // handle the scaling options, specifically the label part
      if (newOptions.scaling !== undefined) {
        mergeOptions(parentOptions.scaling, newOptions.scaling, "label", globalOptions.scaling);
      }
    }
  }, {
    key: "checkMass",
    value: function checkMass(options, id) {
      if (options.mass !== undefined && options.mass <= 0) {
        var strId = "";
        if (id !== undefined) {
          strId = " in node id: " + id;
        }
        console.error("%cNegative or zero mass disallowed" + strId + ", setting mass to 1.", VALIDATOR_PRINT_STYLE);
        options.mass = 1;
      }
    }
  }]);
  return Node;
}();

function _createForOfIteratorHelper$5(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray$5(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$5(o, minLen) { var _context4; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$5(o, minLen); var n = _sliceInstanceProperty(_context4 = Object.prototype.toString.call(o)).call(_context4, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$5(o, minLen); }
function _arrayLikeToArray$5(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

/**
 * Handler for Nodes
 */
var NodesHandler = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Images} images
   * @param {Array.<Group>} groups
   * @param {LayoutEngine} layoutEngine
   */
  function NodesHandler(body, images, groups, layoutEngine) {
    var _context,
      _this = this;
    _classCallCheck(this, NodesHandler);
    this.body = body;
    this.images = images;
    this.groups = groups;
    this.layoutEngine = layoutEngine;

    // create the node API in the body container
    this.body.functions.createNode = _bindInstanceProperty$1(_context = this.create).call(_context, this);
    this.nodesListeners = {
      add: function add(event, params) {
        _this.add(params.items);
      },
      update: function update(event, params) {
        _this.update(params.items, params.data, params.oldData);
      },
      remove: function remove(event, params) {
        _this.remove(params.items);
      }
    };
    this.defaultOptions = {
      borderWidth: 1,
      borderWidthSelected: undefined,
      brokenImage: undefined,
      color: {
        border: "#2B7CE9",
        background: "#97C2FC",
        highlight: {
          border: "#2B7CE9",
          background: "#D2E5FF"
        },
        hover: {
          border: "#2B7CE9",
          background: "#D2E5FF"
        }
      },
      opacity: undefined,
      // number between 0 and 1
      fixed: {
        x: false,
        y: false
      },
      font: {
        color: "#343434",
        size: 14,
        // px
        face: "arial",
        background: "none",
        strokeWidth: 0,
        // px
        strokeColor: "#ffffff",
        align: "center",
        vadjust: 0,
        multi: false,
        bold: {
          mod: "bold"
        },
        boldital: {
          mod: "bold italic"
        },
        ital: {
          mod: "italic"
        },
        mono: {
          mod: "",
          size: 15,
          // px
          face: "monospace",
          vadjust: 2
        }
      },
      group: undefined,
      hidden: false,
      icon: {
        face: "FontAwesome",
        //'FontAwesome',
        code: undefined,
        //'\uf007',
        size: 50,
        //50,
        color: "#2B7CE9" //'#aa00ff'
      },

      image: undefined,
      // --> URL
      imagePadding: {
        // only for image shape
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
      },
      label: undefined,
      labelHighlightBold: true,
      level: undefined,
      margin: {
        top: 5,
        right: 5,
        bottom: 5,
        left: 5
      },
      mass: 1,
      physics: true,
      scaling: {
        min: 10,
        max: 30,
        label: {
          enabled: false,
          min: 14,
          max: 30,
          maxVisible: 30,
          drawThreshold: 5
        },
        customScalingFunction: function customScalingFunction(min, max, total, value) {
          if (max === min) {
            return 0.5;
          } else {
            var scale = 1 / (max - min);
            return Math.max(0, (value - min) * scale);
          }
        }
      },
      shadow: {
        enabled: false,
        color: "rgba(0,0,0,0.5)",
        size: 10,
        x: 5,
        y: 5
      },
      shape: "ellipse",
      shapeProperties: {
        borderDashes: false,
        // only for borders
        borderRadius: 6,
        // only for box shape
        interpolation: true,
        // only for image and circularImage shapes
        useImageSize: false,
        // only for image and circularImage shapes
        useBorderWithImage: false,
        // only for image shape
        coordinateOrigin: "center" // only for image and circularImage shapes
      },

      size: 25,
      title: undefined,
      value: undefined,
      x: undefined,
      y: undefined
    };

    // Protect from idiocy
    if (this.defaultOptions.mass <= 0) {
      throw "Internal error: mass in defaultOptions of NodesHandler may not be zero or negative";
    }
    this.options = bridgeObject(this.defaultOptions);
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(NodesHandler, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _context2,
        _context3,
        _this2 = this;
      // refresh the nodes. Used when reverting from hierarchical layout
      this.body.emitter.on("refreshNodes", _bindInstanceProperty$1(_context2 = this.refresh).call(_context2, this));
      this.body.emitter.on("refresh", _bindInstanceProperty$1(_context3 = this.refresh).call(_context3, this));
      this.body.emitter.on("destroy", function () {
        forEach$1(_this2.nodesListeners, function (callback, event) {
          if (_this2.body.data.nodes) _this2.body.data.nodes.off(event, callback);
        });
        delete _this2.body.functions.createNode;
        delete _this2.nodesListeners.add;
        delete _this2.nodesListeners.update;
        delete _this2.nodesListeners.remove;
        delete _this2.nodesListeners;
      });
    }

    /**
     *
     * @param {object} options
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        Node.parseOptions(this.options, options);

        // Need to set opacity here because Node.parseOptions is also used for groups,
        // if you set opacity in Node.parseOptions it overwrites group opacity.
        if (options.opacity !== undefined) {
          if (_Number$isNaN(options.opacity) || !_Number$isFinite(options.opacity) || options.opacity < 0 || options.opacity > 1) {
            console.error("Invalid option for node opacity. Value must be between 0 and 1, found: " + options.opacity);
          } else {
            this.options.opacity = options.opacity;
          }
        }

        // update the shape in all nodes
        if (options.shape !== undefined) {
          for (var nodeId in this.body.nodes) {
            if (Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) {
              this.body.nodes[nodeId].updateShape();
            }
          }
        }

        // Update the labels of nodes if any relevant options changed.
        if (typeof options.font !== "undefined" || typeof options.widthConstraint !== "undefined" || typeof options.heightConstraint !== "undefined") {
          for (var _i = 0, _Object$keys$1 = _Object$keys(this.body.nodes); _i < _Object$keys$1.length; _i++) {
            var _nodeId = _Object$keys$1[_i];
            this.body.nodes[_nodeId].updateLabelModule();
            this.body.nodes[_nodeId].needsRefresh();
          }
        }

        // update the shape size in all nodes
        if (options.size !== undefined) {
          for (var _nodeId2 in this.body.nodes) {
            if (Object.prototype.hasOwnProperty.call(this.body.nodes, _nodeId2)) {
              this.body.nodes[_nodeId2].needsRefresh();
            }
          }
        }

        // update the state of the variables if needed
        if (options.hidden !== undefined || options.physics !== undefined) {
          this.body.emitter.emit("_dataChanged");
        }
      }
    }

    /**
     * Set a data set with nodes for the network
     *
     * @param {Array | DataSet | DataView} nodes         The data containing the nodes.
     * @param {boolean} [doNotEmit=false] - Suppress data changed event.
     * @private
     */
  }, {
    key: "setData",
    value: function setData(nodes) {
      var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var oldNodesData = this.body.data.nodes;
      if (isDataViewLike("id", nodes)) {
        this.body.data.nodes = nodes;
      } else if (_Array$isArray(nodes)) {
        this.body.data.nodes = new DataSet();
        this.body.data.nodes.add(nodes);
      } else if (!nodes) {
        this.body.data.nodes = new DataSet();
      } else {
        throw new TypeError("Array or DataSet expected");
      }
      if (oldNodesData) {
        // unsubscribe from old dataset
        forEach$1(this.nodesListeners, function (callback, event) {
          oldNodesData.off(event, callback);
        });
      }

      // remove drawn nodes
      this.body.nodes = {};
      if (this.body.data.nodes) {
        // subscribe to new dataset
        var me = this;
        forEach$1(this.nodesListeners, function (callback, event) {
          me.body.data.nodes.on(event, callback);
        });

        // draw all new nodes
        var ids = this.body.data.nodes.getIds();
        this.add(ids, true);
      }
      if (doNotEmit === false) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     * Add nodes
     *
     * @param {number[] | string[]} ids
     * @param {boolean} [doNotEmit=false]
     * @private
     */
  }, {
    key: "add",
    value: function add(ids) {
      var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var id;
      var newNodes = [];
      for (var i = 0; i < ids.length; i++) {
        id = ids[i];
        var properties = this.body.data.nodes.get(id);
        var node = this.create(properties);
        newNodes.push(node);
        this.body.nodes[id] = node; // note: this may replace an existing node
      }

      this.layoutEngine.positionInitially(newNodes);
      if (doNotEmit === false) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     * Update existing nodes, or create them when not yet existing
     *
     * @param {number[] | string[]} ids id's of changed nodes
     * @param {Array} changedData array with changed data
     * @param {Array|undefined} oldData optional; array with previous data
     * @private
     */
  }, {
    key: "update",
    value: function update(ids, changedData, oldData) {
      var nodes = this.body.nodes;
      var dataChanged = false;
      for (var i = 0; i < ids.length; i++) {
        var id = ids[i];
        var node = nodes[id];
        var data = changedData[i];
        if (node !== undefined) {
          // update node
          if (node.setOptions(data)) {
            dataChanged = true;
          }
        } else {
          dataChanged = true;
          // create node
          node = this.create(data);
          nodes[id] = node;
        }
      }
      if (!dataChanged && oldData !== undefined) {
        // Check for any changes which should trigger a layout recalculation
        // For now, this is just 'level' for hierarchical layout
        // Assumption: old and new data arranged in same order; at time of writing, this holds.
        dataChanged = _someInstanceProperty(changedData).call(changedData, function (newValue, index) {
          var oldValue = oldData[index];
          return oldValue && oldValue.level !== newValue.level;
        });
      }
      if (dataChanged === true) {
        this.body.emitter.emit("_dataChanged");
      } else {
        this.body.emitter.emit("_dataUpdated");
      }
    }

    /**
     * Remove existing nodes. If nodes do not exist, the method will just ignore it.
     *
     * @param {number[] | string[]} ids
     * @private
     */
  }, {
    key: "remove",
    value: function remove(ids) {
      var nodes = this.body.nodes;
      for (var i = 0; i < ids.length; i++) {
        var id = ids[i];
        delete nodes[id];
      }
      this.body.emitter.emit("_dataChanged");
    }

    /**
     * create a node
     *
     * @param {object} properties
     * @param {class} [constructorClass=Node.default]
     * @returns {*}
     */
  }, {
    key: "create",
    value: function create(properties) {
      var constructorClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Node;
      return new constructorClass(properties, this.body, this.images, this.groups, this.options, this.defaultOptions);
    }

    /**
     *
     * @param {boolean} [clearPositions=false]
     */
  }, {
    key: "refresh",
    value: function refresh() {
      var _this3 = this;
      var clearPositions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      forEach$1(this.body.nodes, function (node, nodeId) {
        var data = _this3.body.data.nodes.get(nodeId);
        if (data !== undefined) {
          if (clearPositions === true) {
            node.setOptions({
              x: null,
              y: null
            });
          }
          node.setOptions({
            fixed: false
          });
          node.setOptions(data);
        }
      });
    }

    /**
     * Returns the positions of the nodes.
     *
     * @param {Array.<Node.id> | string} [ids]  --> optional, can be array of nodeIds, can be string
     * @returns {{}}
     */
  }, {
    key: "getPositions",
    value: function getPositions(ids) {
      var dataArray = {};
      if (ids !== undefined) {
        if (_Array$isArray(ids) === true) {
          for (var i = 0; i < ids.length; i++) {
            if (this.body.nodes[ids[i]] !== undefined) {
              var node = this.body.nodes[ids[i]];
              dataArray[ids[i]] = {
                x: Math.round(node.x),
                y: Math.round(node.y)
              };
            }
          }
        } else {
          if (this.body.nodes[ids] !== undefined) {
            var _node = this.body.nodes[ids];
            dataArray[ids] = {
              x: Math.round(_node.x),
              y: Math.round(_node.y)
            };
          }
        }
      } else {
        for (var _i2 = 0; _i2 < this.body.nodeIndices.length; _i2++) {
          var _node2 = this.body.nodes[this.body.nodeIndices[_i2]];
          dataArray[this.body.nodeIndices[_i2]] = {
            x: Math.round(_node2.x),
            y: Math.round(_node2.y)
          };
        }
      }
      return dataArray;
    }

    /**
     * Retrieves the x y position of a specific id.
     *
     * @param {string} id The id to retrieve.
     * @throws {TypeError} If no id is included.
     * @throws {ReferenceError} If an invalid id is provided.
     * @returns {{ x: number, y: number }} Returns X, Y canvas position of the node with given id.
     */
  }, {
    key: "getPosition",
    value: function getPosition(id) {
      if (id == undefined) {
        throw new TypeError("No id was specified for getPosition method.");
      } else if (this.body.nodes[id] == undefined) {
        throw new ReferenceError("NodeId provided for getPosition does not exist. Provided: ".concat(id));
      } else {
        return {
          x: Math.round(this.body.nodes[id].x),
          y: Math.round(this.body.nodes[id].y)
        };
      }
    }

    /**
     * Load the XY positions of the nodes into the dataset.
     */
  }, {
    key: "storePositions",
    value: function storePositions() {
      // todo: add support for clusters and hierarchical.
      var dataArray = [];
      var dataset = this.body.data.nodes.getDataSet();
      var _iterator = _createForOfIteratorHelper$5(dataset.get()),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var dsNode = _step.value;
          var id = dsNode.id;
          var bodyNode = this.body.nodes[id];
          var x = Math.round(bodyNode.x);
          var y = Math.round(bodyNode.y);
          if (dsNode.x !== x || dsNode.y !== y) {
            dataArray.push({
              id: id,
              x: x,
              y: y
            });
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
      dataset.update(dataArray);
    }

    /**
     * get the bounding box of a node.
     *
     * @param {Node.id} nodeId
     * @returns {j|*}
     */
  }, {
    key: "getBoundingBox",
    value: function getBoundingBox(nodeId) {
      if (this.body.nodes[nodeId] !== undefined) {
        return this.body.nodes[nodeId].shape.boundingBox;
      }
    }

    /**
     * Get the Ids of nodes connected to this node.
     *
     * @param {Node.id} nodeId
     * @param {'to'|'from'|undefined} direction values 'from' and 'to' select respectively parent and child nodes only.
     *                                          Any other value returns both parent and child nodes.
     * @returns {Array}
     */
  }, {
    key: "getConnectedNodes",
    value: function getConnectedNodes(nodeId, direction) {
      var nodeList = [];
      if (this.body.nodes[nodeId] !== undefined) {
        var node = this.body.nodes[nodeId];
        var nodeObj = {}; // used to quickly check if node already exists
        for (var i = 0; i < node.edges.length; i++) {
          var edge = node.edges[i];
          if (direction !== "to" && edge.toId == node.id) {
            // these are double equals since ids can be numeric or string
            if (nodeObj[edge.fromId] === undefined) {
              nodeList.push(edge.fromId);
              nodeObj[edge.fromId] = true;
            }
          } else if (direction !== "from" && edge.fromId == node.id) {
            // these are double equals since ids can be numeric or string
            if (nodeObj[edge.toId] === undefined) {
              nodeList.push(edge.toId);
              nodeObj[edge.toId] = true;
            }
          }
        }
      }
      return nodeList;
    }

    /**
     * Get the ids of the edges connected to this node.
     *
     * @param {Node.id} nodeId
     * @returns {*}
     */
  }, {
    key: "getConnectedEdges",
    value: function getConnectedEdges(nodeId) {
      var edgeList = [];
      if (this.body.nodes[nodeId] !== undefined) {
        var node = this.body.nodes[nodeId];
        for (var i = 0; i < node.edges.length; i++) {
          edgeList.push(node.edges[i].id);
        }
      } else {
        console.error("NodeId provided for getConnectedEdges does not exist. Provided: ", nodeId);
      }
      return edgeList;
    }

    /**
     * Move a node.
     *
     * @param {Node.id} nodeId
     * @param {number} x
     * @param {number} y
     */
  }, {
    key: "moveNode",
    value: function moveNode(nodeId, x, y) {
      var _this4 = this;
      if (this.body.nodes[nodeId] !== undefined) {
        this.body.nodes[nodeId].x = Number(x);
        this.body.nodes[nodeId].y = Number(y);
        _setTimeout(function () {
          _this4.body.emitter.emit("startSimulation");
        }, 0);
      } else {
        console.error("Node id supplied to moveNode does not exist. Provided: ", nodeId);
      }
    }
  }]);
  return NodesHandler;
}();

var getExports$1 = {};
var get$6 = {
  get exports(){ return getExports$1; },
  set exports(v){ getExports$1 = v; },
};

var getExports = {};
var get$5 = {
  get exports(){ return getExports; },
  set exports(v){ getExports = v; },
};

var hasOwn$1 = hasOwnProperty_1;

var isDataDescriptor$1 = function (descriptor) {
  return descriptor !== undefined && (hasOwn$1(descriptor, 'value') || hasOwn$1(descriptor, 'writable'));
};

var $$4 = _export;
var call = functionCall;
var isObject$2$1 = isObject$j;
var anObject$1 = anObject$d;
var isDataDescriptor = isDataDescriptor$1;
var getOwnPropertyDescriptorModule = objectGetOwnPropertyDescriptor;
var getPrototypeOf = objectGetPrototypeOf;

// `Reflect.get` method
// https://tc39.es/ecma262/#sec-reflect.get
function get$4(target, propertyKey /* , receiver */) {
  var receiver = arguments.length < 3 ? target : arguments[2];
  var descriptor, prototype;
  if (anObject$1(target) === receiver) return target[propertyKey];
  descriptor = getOwnPropertyDescriptorModule.f(target, propertyKey);
  if (descriptor) return isDataDescriptor(descriptor)
    ? descriptor.value
    : descriptor.get === undefined ? undefined : call(descriptor.get, receiver);
  if (isObject$2$1(prototype = getPrototypeOf(target))) return get$4(prototype, propertyKey, receiver);
}

$$4({ target: 'Reflect', stat: true }, {
  get: get$4
});

var path$4 = path$y;

var get$3 = path$4.Reflect.get;

var parent$a = get$3;

var get$2 = parent$a;

var parent$9 = get$2;

var get$1 = parent$9;

var parent$8 = get$1;

var get$8 = parent$8;

(function (module) {
	module.exports = get$8;
} (get$5));

(function (module) {
	module.exports = getExports;
} (get$6));

var _Reflect$get = /*@__PURE__*/getDefaultExportFromCjs$1(getExports$1);

var getOwnPropertyDescriptorExports$1 = {};
var getOwnPropertyDescriptor$3 = {
  get exports(){ return getOwnPropertyDescriptorExports$1; },
  set exports(v){ getOwnPropertyDescriptorExports$1 = v; },
};

var getOwnPropertyDescriptorExports = {};
var getOwnPropertyDescriptor$2 = {
  get exports(){ return getOwnPropertyDescriptorExports; },
  set exports(v){ getOwnPropertyDescriptorExports = v; },
};

var parent$7 = getOwnPropertyDescriptor$5;

var getOwnPropertyDescriptor$1 = parent$7;

var parent$6 = getOwnPropertyDescriptor$1;

var getOwnPropertyDescriptor = parent$6;

(function (module) {
	module.exports = getOwnPropertyDescriptor;
} (getOwnPropertyDescriptor$2));

(function (module) {
	module.exports = getOwnPropertyDescriptorExports;
} (getOwnPropertyDescriptor$3));

var _Object$getOwnPropertyDescriptor = /*@__PURE__*/getDefaultExportFromCjs$1(getOwnPropertyDescriptorExports$1);

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) {
    var _context;
    _get = _bindInstanceProperty(_context = _Reflect$get).call(_context);
  } 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);
}

var hypotExports = {};
var hypot$2 = {
  get exports(){ return hypotExports; },
  set exports(v){ hypotExports = v; },
};

var $$3 = _export;

// eslint-disable-next-line es/no-math-hypot -- required for testing
var $hypot = Math.hypot;
var abs$2 = Math.abs;
var sqrt = Math.sqrt;

// Chrome 77 bug
// https://bugs.chromium.org/p/v8/issues/detail?id=9546
var FORCED$2 = !!$hypot && $hypot(Infinity, NaN) !== Infinity;

// `Math.hypot` method
// https://tc39.es/ecma262/#sec-math.hypot
$$3({ target: 'Math', stat: true, arity: 2, forced: FORCED$2 }, {
  // eslint-disable-next-line no-unused-vars -- required for `.length`
  hypot: function hypot(value1, value2) {
    var sum = 0;
    var i = 0;
    var aLen = arguments.length;
    var larg = 0;
    var arg, div;
    while (i < aLen) {
      arg = abs$2(arguments[i++]);
      if (larg < arg) {
        div = larg / arg;
        sum = sum * div * div + 1;
        larg = arg;
      } else if (arg > 0) {
        div = arg / larg;
        sum += div * div;
      } else sum += arg;
    }
    return larg === Infinity ? Infinity : larg * sqrt(sum);
  }
});

var path$3 = path$y;

var hypot$1 = path$3.Math.hypot;

var parent$5 = hypot$1;

var hypot = parent$5;

(function (module) {
	module.exports = hypot;
} (hypot$2));

var _Math$hypot = /*@__PURE__*/getDefaultExportFromCjs$1(hypotExports);

function _createSuper$a(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$a(); 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 _isNativeReflectConstruct$a() { 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; } }
/**
 * Common methods for endpoints
 *
 * @class
 */
var EndPoint = /*#__PURE__*/function () {
  function EndPoint() {
    _classCallCheck(this, EndPoint);
  }
  _createClass(EndPoint, null, [{
    key: "transform",
    value:
    /**
     * Apply transformation on points for display.
     *
     * The following is done:
     * - rotate by the specified angle
     * - multiply the (normalized) coordinates by the passed length
     * - offset by the target coordinates
     *
     * @param points - The point(s) to be transformed.
     * @param arrowData - The data determining the result of the transformation.
     */
    function transform(points, arrowData) {
      if (!_Array$isArray(points)) {
        points = [points];
      }
      var x = arrowData.point.x;
      var y = arrowData.point.y;
      var angle = arrowData.angle;
      var length = arrowData.length;
      for (var i = 0; i < points.length; ++i) {
        var p = points[i];
        var xt = p.x * Math.cos(angle) - p.y * Math.sin(angle);
        var yt = p.x * Math.sin(angle) + p.y * Math.cos(angle);
        p.x = x + length * xt;
        p.y = y + length * yt;
      }
    }
    /**
     * Draw a closed path using the given real coordinates.
     *
     * @param ctx - The path will be rendered into this context.
     * @param points - The points of the path.
     */
  }, {
    key: "drawPath",
    value: function drawPath(ctx, points) {
      ctx.beginPath();
      ctx.moveTo(points[0].x, points[0].y);
      for (var i = 1; i < points.length; ++i) {
        ctx.lineTo(points[i].x, points[i].y);
      }
      ctx.closePath();
    }
  }]);
  return EndPoint;
}();
/**
 * Drawing methods for the arrow endpoint.
 */
var Image$1 = /*#__PURE__*/function (_EndPoint) {
  _inherits(Image, _EndPoint);
  var _super = _createSuper$a(Image);
  function Image() {
    _classCallCheck(this, Image);
    return _super.apply(this, arguments);
  }
  _createClass(Image, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns False as there is no way to fill an image.
     */
    function draw(ctx, arrowData) {
      if (arrowData.image) {
        ctx.save();
        ctx.translate(arrowData.point.x, arrowData.point.y);
        ctx.rotate(Math.PI / 2 + arrowData.angle);
        var width = arrowData.imageWidth != null ? arrowData.imageWidth : arrowData.image.width;
        var height = arrowData.imageHeight != null ? arrowData.imageHeight : arrowData.image.height;
        arrowData.image.drawImageAtPosition(ctx, 1,
        // scale
        -width / 2,
        // x
        0,
        // y
        width, height);
        ctx.restore();
      }
      return false;
    }
  }]);
  return Image;
}(EndPoint);
/**
 * Drawing methods for the arrow endpoint.
 */
var Arrow$1 = /*#__PURE__*/function (_EndPoint2) {
  _inherits(Arrow, _EndPoint2);
  var _super2 = _createSuper$a(Arrow);
  function Arrow() {
    _classCallCheck(this, Arrow);
    return _super2.apply(this, arguments);
  }
  _createClass(Arrow, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var points = [{
        x: 0,
        y: 0
      }, {
        x: -1,
        y: 0.3
      }, {
        x: -0.9,
        y: 0
      }, {
        x: -1,
        y: -0.3
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Arrow;
}(EndPoint);
/**
 * Drawing methods for the crow endpoint.
 */
var Crow = /*#__PURE__*/function () {
  function Crow() {
    _classCallCheck(this, Crow);
  }
  _createClass(Crow, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var points = [{
        x: -1,
        y: 0
      }, {
        x: 0,
        y: 0.3
      }, {
        x: -0.4,
        y: 0
      }, {
        x: 0,
        y: -0.3
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Crow;
}();
/**
 * Drawing methods for the curve endpoint.
 */
var Curve = /*#__PURE__*/function () {
  function Curve() {
    _classCallCheck(this, Curve);
  }
  _createClass(Curve, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var point = {
        x: -0.4,
        y: 0
      };
      EndPoint.transform(point, arrowData);
      // Update endpoint style for drawing transparent arc.
      ctx.strokeStyle = ctx.fillStyle;
      ctx.fillStyle = "rgba(0, 0, 0, 0)";
      // Define curve endpoint as semicircle.
      var pi = Math.PI;
      var startAngle = arrowData.angle - pi / 2;
      var endAngle = arrowData.angle + pi / 2;
      ctx.beginPath();
      ctx.arc(point.x, point.y, arrowData.length * 0.4, startAngle, endAngle, false);
      ctx.stroke();
      return true;
    }
  }]);
  return Curve;
}();
/**
 * Drawing methods for the inverted curve endpoint.
 */
var InvertedCurve = /*#__PURE__*/function () {
  function InvertedCurve() {
    _classCallCheck(this, InvertedCurve);
  }
  _createClass(InvertedCurve, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var point = {
        x: -0.3,
        y: 0
      };
      EndPoint.transform(point, arrowData);
      // Update endpoint style for drawing transparent arc.
      ctx.strokeStyle = ctx.fillStyle;
      ctx.fillStyle = "rgba(0, 0, 0, 0)";
      // Define inverted curve endpoint as semicircle.
      var pi = Math.PI;
      var startAngle = arrowData.angle + pi / 2;
      var endAngle = arrowData.angle + 3 * pi / 2;
      ctx.beginPath();
      ctx.arc(point.x, point.y, arrowData.length * 0.4, startAngle, endAngle, false);
      ctx.stroke();
      return true;
    }
  }]);
  return InvertedCurve;
}();
/**
 * Drawing methods for the trinagle endpoint.
 */
var Triangle$2 = /*#__PURE__*/function () {
  function Triangle() {
    _classCallCheck(this, Triangle);
  }
  _createClass(Triangle, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var points = [{
        x: 0.02,
        y: 0
      }, {
        x: -1,
        y: 0.3
      }, {
        x: -1,
        y: -0.3
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Triangle;
}();
/**
 * Drawing methods for the inverted trinagle endpoint.
 */
var InvertedTriangle = /*#__PURE__*/function () {
  function InvertedTriangle() {
    _classCallCheck(this, InvertedTriangle);
  }
  _createClass(InvertedTriangle, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var points = [{
        x: 0,
        y: 0.3
      }, {
        x: 0,
        y: -0.3
      }, {
        x: -1,
        y: 0
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return InvertedTriangle;
}();
/**
 * Drawing methods for the circle endpoint.
 */
var Circle$2 = /*#__PURE__*/function () {
  function Circle() {
    _classCallCheck(this, Circle);
  }
  _createClass(Circle, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      var point = {
        x: -0.4,
        y: 0
      };
      EndPoint.transform(point, arrowData);
      drawCircle(ctx, point.x, point.y, arrowData.length * 0.4);
      return true;
    }
  }]);
  return Circle;
}();
/**
 * Drawing methods for the bar endpoint.
 */
var Bar = /*#__PURE__*/function () {
  function Bar() {
    _classCallCheck(this, Bar);
  }
  _createClass(Bar, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      /*
      var points = [
        {x:0, y:0.5},
        {x:0, y:-0.5}
      ];
           EndPoint.transform(points, arrowData);
      ctx.beginPath();
      ctx.moveTo(points[0].x, points[0].y);
      ctx.lineTo(points[1].x, points[1].y);
      ctx.stroke();
      */
      var points = [{
        x: 0,
        y: 0.5
      }, {
        x: 0,
        y: -0.5
      }, {
        x: -0.15,
        y: -0.5
      }, {
        x: -0.15,
        y: 0.5
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Bar;
}();
/**
 * Drawing methods for the box endpoint.
 */
var Box = /*#__PURE__*/function () {
  function Box() {
    _classCallCheck(this, Box);
  }
  _createClass(Box, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      var points = [{
        x: 0,
        y: 0.3
      }, {
        x: 0,
        y: -0.3
      }, {
        x: -0.6,
        y: -0.3
      }, {
        x: -0.6,
        y: 0.3
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Box;
}();
/**
 * Drawing methods for the diamond endpoint.
 */
var Diamond$2 = /*#__PURE__*/function () {
  function Diamond() {
    _classCallCheck(this, Diamond);
  }
  _createClass(Diamond, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      var points = [{
        x: 0,
        y: 0
      }, {
        x: -0.5,
        y: -0.3
      }, {
        x: -1,
        y: 0
      }, {
        x: -0.5,
        y: 0.3
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Diamond;
}();
/**
 * Drawing methods for the vee endpoint.
 */
var Vee = /*#__PURE__*/function () {
  function Vee() {
    _classCallCheck(this, Vee);
  }
  _createClass(Vee, null, [{
    key: "draw",
    value:
    /**
     * Draw this shape at the end of a line.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True because ctx.fill() can be used to fill the arrow.
     */
    function draw(ctx, arrowData) {
      // Normalized points of closed path, in the order that they should be drawn.
      // (0, 0) is the attachment point, and the point around which should be rotated
      var points = [{
        x: -1,
        y: 0.3
      }, {
        x: -0.5,
        y: 0
      }, {
        x: -1,
        y: -0.3
      }, {
        x: 0,
        y: 0
      }];
      EndPoint.transform(points, arrowData);
      EndPoint.drawPath(ctx, points);
      return true;
    }
  }]);
  return Vee;
}();
/**
 * Drawing methods for the endpoints.
 */
var EndPoints = /*#__PURE__*/function () {
  function EndPoints() {
    _classCallCheck(this, EndPoints);
  }
  _createClass(EndPoints, null, [{
    key: "draw",
    value:
    /**
     * Draw an endpoint.
     *
     * @param ctx - The shape will be rendered into this context.
     * @param arrowData - The data determining the shape.
     * @returns True if ctx.fill() can be used to fill the arrow, false otherwise.
     */
    function draw(ctx, arrowData) {
      var type;
      if (arrowData.type) {
        type = arrowData.type.toLowerCase();
      }
      switch (type) {
        case "image":
          return Image$1.draw(ctx, arrowData);
        case "circle":
          return Circle$2.draw(ctx, arrowData);
        case "box":
          return Box.draw(ctx, arrowData);
        case "crow":
          return Crow.draw(ctx, arrowData);
        case "curve":
          return Curve.draw(ctx, arrowData);
        case "diamond":
          return Diamond$2.draw(ctx, arrowData);
        case "inv_curve":
          return InvertedCurve.draw(ctx, arrowData);
        case "triangle":
          return Triangle$2.draw(ctx, arrowData);
        case "inv_triangle":
          return InvertedTriangle.draw(ctx, arrowData);
        case "bar":
          return Bar.draw(ctx, arrowData);
        case "vee":
          return Vee.draw(ctx, arrowData);
        case "arrow": // fall-through
        default:
          return Arrow$1.draw(ctx, arrowData);
      }
    }
  }]);
  return EndPoints;
}();

function ownKeys$1(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor$1(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var _context2, _context3; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context2 = ownKeys$1(Object(source), !0)).call(_context2, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context3 = ownKeys$1(Object(source))).call(_context3, function (key) { _Object$defineProperty$1(target, key, _Object$getOwnPropertyDescriptor$1(source, key)); }); } return target; }
/**
 * The Base Class for all edges.
 */
var EdgeBase = /*#__PURE__*/function () {
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param _body - The body of the network.
   * @param _labelModule - Label module.
   */
  function EdgeBase(options, _body, _labelModule) {
    _classCallCheck(this, EdgeBase);
    this._body = _body;
    this._labelModule = _labelModule;
    this.color = {};
    this.colorDirty = true;
    this.hoverWidth = 1.5;
    this.selectionWidth = 2;
    this.setOptions(options);
    this.fromPoint = this.from;
    this.toPoint = this.to;
  }
  /** @inheritDoc */
  _createClass(EdgeBase, [{
    key: "connect",
    value: function connect() {
      this.from = this._body.nodes[this.options.from];
      this.to = this._body.nodes[this.options.to];
    }
    /** @inheritDoc */
  }, {
    key: "cleanup",
    value: function cleanup() {
      return false;
    }
    /**
     * Set new edge options.
     *
     * @param options - The new edge options object.
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
      this.from = this._body.nodes[this.options.from];
      this.to = this._body.nodes[this.options.to];
      this.id = this.options.id;
    }
    /** @inheritDoc */
  }, {
    key: "drawLine",
    value: function drawLine(ctx, values, _selected, _hover) {
      var viaNode = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : this.getViaNode();
      // set style
      ctx.strokeStyle = this.getColor(ctx, values);
      ctx.lineWidth = values.width;
      if (values.dashes !== false) {
        this._drawDashedLine(ctx, values, viaNode);
      } else {
        this._drawLine(ctx, values, viaNode);
      }
    }
    /**
     * Draw a line with given style between two nodes through supplied node(s).
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values like color, opacity or shadow.
     * @param viaNode - Additional control point(s) for the edge.
     * @param fromPoint - TODO: Seems ignored, remove?
     * @param toPoint - TODO: Seems ignored, remove?
     */
  }, {
    key: "_drawLine",
    value: function _drawLine(ctx, values, viaNode, fromPoint, toPoint) {
      if (this.from != this.to) {
        // draw line
        this._line(ctx, values, viaNode, fromPoint, toPoint);
      } else {
        var _this$_getCircleData = this._getCircleData(ctx),
          _this$_getCircleData2 = _slicedToArray(_this$_getCircleData, 3),
          x = _this$_getCircleData2[0],
          y = _this$_getCircleData2[1],
          radius = _this$_getCircleData2[2];
        this._circle(ctx, values, x, y, radius);
      }
    }
    /**
     * Draw a dashed line with given style between two nodes through supplied node(s).
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values like color, opacity or shadow.
     * @param viaNode - Additional control point(s) for the edge.
     * @param _fromPoint - Ignored (TODO: remove in the future).
     * @param _toPoint - Ignored (TODO: remove in the future).
     */
  }, {
    key: "_drawDashedLine",
    value: function _drawDashedLine(ctx, values, viaNode, _fromPoint, _toPoint) {
      ctx.lineCap = "round";
      var pattern = _Array$isArray(values.dashes) ? values.dashes : [5, 5];
      // only firefox and chrome support this method, else we use the legacy one.
      if (ctx.setLineDash !== undefined) {
        ctx.save();
        // set dash settings for chrome or firefox
        ctx.setLineDash(pattern);
        ctx.lineDashOffset = 0;
        // draw the line
        if (this.from != this.to) {
          // draw line
          this._line(ctx, values, viaNode);
        } else {
          var _this$_getCircleData3 = this._getCircleData(ctx),
            _this$_getCircleData4 = _slicedToArray(_this$_getCircleData3, 3),
            x = _this$_getCircleData4[0],
            y = _this$_getCircleData4[1],
            radius = _this$_getCircleData4[2];
          this._circle(ctx, values, x, y, radius);
        }
        // restore the dash settings.
        ctx.setLineDash([0]);
        ctx.lineDashOffset = 0;
        ctx.restore();
      } else {
        // unsupporting smooth lines
        if (this.from != this.to) {
          // draw line
          drawDashedLine(ctx, this.from.x, this.from.y, this.to.x, this.to.y, pattern);
        } else {
          var _this$_getCircleData5 = this._getCircleData(ctx),
            _this$_getCircleData6 = _slicedToArray(_this$_getCircleData5, 3),
            _x = _this$_getCircleData6[0],
            _y = _this$_getCircleData6[1],
            _radius = _this$_getCircleData6[2];
          this._circle(ctx, values, _x, _y, _radius);
        }
        // draw shadow if enabled
        this.enableShadow(ctx, values);
        ctx.stroke();
        // disable shadows for other elements.
        this.disableShadow(ctx, values);
      }
    }
    /**
     * Find the intersection between the border of the node and the edge.
     *
     * @param node - The node (either from or to node of the edge).
     * @param ctx - The context that will be used for rendering.
     * @param options - Additional options.
     * @returns Cartesian coordinates of the intersection between the border of the node and the edge.
     */
  }, {
    key: "findBorderPosition",
    value: function findBorderPosition(node, ctx, options) {
      if (this.from != this.to) {
        return this._findBorderPosition(node, ctx, options);
      } else {
        return this._findBorderPositionCircle(node, ctx, options);
      }
    }
    /** @inheritDoc */
  }, {
    key: "findBorderPositions",
    value: function findBorderPositions(ctx) {
      if (this.from != this.to) {
        return {
          from: this._findBorderPosition(this.from, ctx),
          to: this._findBorderPosition(this.to, ctx)
        };
      } else {
        var _context;
        var _this$_getCircleData$ = _sliceInstanceProperty(_context = this._getCircleData(ctx)).call(_context, 0, 2),
          _this$_getCircleData$2 = _slicedToArray(_this$_getCircleData$, 2),
          x = _this$_getCircleData$2[0],
          y = _this$_getCircleData$2[1];
        return {
          from: this._findBorderPositionCircle(this.from, ctx, {
            x: x,
            y: y,
            low: 0.25,
            high: 0.6,
            direction: -1
          }),
          to: this._findBorderPositionCircle(this.from, ctx, {
            x: x,
            y: y,
            low: 0.6,
            high: 0.8,
            direction: 1
          })
        };
      }
    }
    /**
     * Compute the center point and radius of an edge connected to the same node at both ends.
     *
     * @param ctx - The context that will be used for rendering.
     * @returns `[x, y, radius]`
     */
  }, {
    key: "_getCircleData",
    value: function _getCircleData(ctx) {
      var radius = this.options.selfReference.size;
      if (ctx !== undefined) {
        if (this.from.shape.width === undefined) {
          this.from.shape.resize(ctx);
        }
      }
      // get circle coordinates
      var coordinates = getSelfRefCoordinates(ctx, this.options.selfReference.angle, radius, this.from);
      return [coordinates.x, coordinates.y, radius];
    }
    /**
     * Get a point on a circle.
     *
     * @param x - Center of the circle on the x axis.
     * @param y - Center of the circle on the y axis.
     * @param radius - Radius of the circle.
     * @param position - Value between 0 (line start) and 1 (line end).
     * @returns Cartesian coordinates of requested point on the circle.
     */
  }, {
    key: "_pointOnCircle",
    value: function _pointOnCircle(x, y, radius, position) {
      var angle = position * 2 * Math.PI;
      return {
        x: x + radius * Math.cos(angle),
        y: y - radius * Math.sin(angle)
      };
    }
    /**
     * Find the intersection between the border of the node and the edge.
     *
     * @remarks
     * This function uses binary search to look for the point where the circle crosses the border of the node.
     * @param nearNode - The node (either from or to node of the edge).
     * @param ctx - The context that will be used for rendering.
     * @param options - Additional options.
     * @returns Cartesian coordinates of the intersection between the border of the node and the edge.
     */
  }, {
    key: "_findBorderPositionCircle",
    value: function _findBorderPositionCircle(nearNode, ctx, options) {
      var x = options.x;
      var y = options.y;
      var low = options.low;
      var high = options.high;
      var direction = options.direction;
      var maxIterations = 10;
      var radius = this.options.selfReference.size;
      var threshold = 0.05;
      var pos;
      var middle = (low + high) * 0.5;
      var endPointOffset = 0;
      if (this.options.arrowStrikethrough === true) {
        if (direction === -1) {
          endPointOffset = this.options.endPointOffset.from;
        } else if (direction === 1) {
          endPointOffset = this.options.endPointOffset.to;
        }
      }
      var iteration = 0;
      do {
        middle = (low + high) * 0.5;
        pos = this._pointOnCircle(x, y, radius, middle);
        var angle = Math.atan2(nearNode.y - pos.y, nearNode.x - pos.x);
        var distanceToBorder = nearNode.distanceToBorder(ctx, angle) + endPointOffset;
        var distanceToPoint = Math.sqrt(Math.pow(pos.x - nearNode.x, 2) + Math.pow(pos.y - nearNode.y, 2));
        var difference = distanceToBorder - distanceToPoint;
        if (Math.abs(difference) < threshold) {
          break; // found
        } else if (difference > 0) {
          // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node.
          if (direction > 0) {
            low = middle;
          } else {
            high = middle;
          }
        } else {
          if (direction > 0) {
            high = middle;
          } else {
            low = middle;
          }
        }
        ++iteration;
      } while (low <= high && iteration < maxIterations);
      return _objectSpread$1(_objectSpread$1({}, pos), {}, {
        t: middle
      });
    }
    /**
     * Get the line width of the edge. Depends on width and whether one of the connected nodes is selected.
     *
     * @param selected - Determines wheter the line is selected.
     * @param hover - Determines wheter the line is being hovered, only applies if selected is false.
     * @returns The width of the line.
     */
  }, {
    key: "getLineWidth",
    value: function getLineWidth(selected, hover) {
      if (selected === true) {
        return Math.max(this.selectionWidth, 0.3 / this._body.view.scale);
      } else if (hover === true) {
        return Math.max(this.hoverWidth, 0.3 / this._body.view.scale);
      } else {
        return Math.max(this.options.width, 0.3 / this._body.view.scale);
      }
    }
    /**
     * Compute the color or gradient for given edge.
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values like color, opacity or shadow.
     * @param _selected - Ignored (TODO: remove in the future).
     * @param _hover - Ignored (TODO: remove in the future).
     * @returns Color string if single color is inherited or gradient if two.
     */
  }, {
    key: "getColor",
    value: function getColor(ctx, values) {
      if (values.inheritsColor !== false) {
        // when this is a loop edge, just use the 'from' method
        if (values.inheritsColor === "both" && this.from.id !== this.to.id) {
          var grd = ctx.createLinearGradient(this.from.x, this.from.y, this.to.x, this.to.y);
          var fromColor = this.from.options.color.highlight.border;
          var toColor = this.to.options.color.highlight.border;
          if (this.from.selected === false && this.to.selected === false) {
            fromColor = overrideOpacity(this.from.options.color.border, values.opacity);
            toColor = overrideOpacity(this.to.options.color.border, values.opacity);
          } else if (this.from.selected === true && this.to.selected === false) {
            toColor = this.to.options.color.border;
          } else if (this.from.selected === false && this.to.selected === true) {
            fromColor = this.from.options.color.border;
          }
          grd.addColorStop(0, fromColor);
          grd.addColorStop(1, toColor);
          // -------------------- this returns -------------------- //
          return grd;
        }
        if (values.inheritsColor === "to") {
          return overrideOpacity(this.to.options.color.border, values.opacity);
        } else {
          // "from"
          return overrideOpacity(this.from.options.color.border, values.opacity);
        }
      } else {
        return overrideOpacity(values.color, values.opacity);
      }
    }
    /**
     * Draw a line from a node to itself, a circle.
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values like color, opacity or shadow.
     * @param x - Center of the circle on the x axis.
     * @param y - Center of the circle on the y axis.
     * @param radius - Radius of the circle.
     */
  }, {
    key: "_circle",
    value: function _circle(ctx, values, x, y, radius) {
      // draw shadow if enabled
      this.enableShadow(ctx, values);
      //full circle
      var angleFrom = 0;
      var angleTo = Math.PI * 2;
      if (!this.options.selfReference.renderBehindTheNode) {
        //render only parts which are not overlaping with parent node
        //need to find x,y of from point and x,y to point
        //calculating radians
        var low = this.options.selfReference.angle;
        var high = this.options.selfReference.angle + Math.PI;
        var pointTFrom = this._findBorderPositionCircle(this.from, ctx, {
          x: x,
          y: y,
          low: low,
          high: high,
          direction: -1
        });
        var pointTTo = this._findBorderPositionCircle(this.from, ctx, {
          x: x,
          y: y,
          low: low,
          high: high,
          direction: 1
        });
        angleFrom = Math.atan2(pointTFrom.y - y, pointTFrom.x - x);
        angleTo = Math.atan2(pointTTo.y - y, pointTTo.x - x);
      }
      // draw a circle
      ctx.beginPath();
      ctx.arc(x, y, radius, angleFrom, angleTo, false);
      ctx.stroke();
      // disable shadows for other elements.
      this.disableShadow(ctx, values);
    }
    /**
     * @inheritDoc
     * @remarks
     * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
     */
  }, {
    key: "getDistanceToEdge",
    value: function getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
      if (this.from != this.to) {
        return this._getDistanceToEdge(x1, y1, x2, y2, x3, y3);
      } else {
        var _this$_getCircleData7 = this._getCircleData(undefined),
          _this$_getCircleData8 = _slicedToArray(_this$_getCircleData7, 3),
          x = _this$_getCircleData8[0],
          y = _this$_getCircleData8[1],
          radius = _this$_getCircleData8[2];
        var dx = x - x3;
        var dy = y - y3;
        return Math.abs(Math.sqrt(dx * dx + dy * dy) - radius);
      }
    }
    /**
     * Calculate the distance between a point (x3, y3) and a line segment from (x1, y1) to (x2, y2).
     *
     * @param x1 - First end of the line segment on the x axis.
     * @param y1 - First end of the line segment on the y axis.
     * @param x2 - Second end of the line segment on the x axis.
     * @param y2 - Second end of the line segment on the y axis.
     * @param x3 - Position of the point on the x axis.
     * @param y3 - Position of the point on the y axis.
     * @returns The distance between the line segment and the point.
     */
  }, {
    key: "_getDistanceToLine",
    value: function _getDistanceToLine(x1, y1, x2, y2, x3, y3) {
      var px = x2 - x1;
      var py = y2 - y1;
      var something = px * px + py * py;
      var u = ((x3 - x1) * px + (y3 - y1) * py) / something;
      if (u > 1) {
        u = 1;
      } else if (u < 0) {
        u = 0;
      }
      var x = x1 + u * px;
      var y = y1 + u * py;
      var dx = x - x3;
      var dy = y - y3;
      //# Note: If the actual distance does not matter,
      //# if you only want to compare what this function
      //# returns to other results of this function, you
      //# can just return the squared distance instead
      //# (i.e. remove the sqrt) to gain a little performance
      return Math.sqrt(dx * dx + dy * dy);
    }
    /** @inheritDoc */
  }, {
    key: "getArrowData",
    value: function getArrowData(ctx, position, viaNode, _selected, _hover, values) {
      // set lets
      var angle;
      var arrowPoint;
      var node1;
      var node2;
      var reversed;
      var scaleFactor;
      var type;
      var lineWidth = values.width;
      if (position === "from") {
        node1 = this.from;
        node2 = this.to;
        reversed = values.fromArrowScale < 0;
        scaleFactor = Math.abs(values.fromArrowScale);
        type = values.fromArrowType;
      } else if (position === "to") {
        node1 = this.to;
        node2 = this.from;
        reversed = values.toArrowScale < 0;
        scaleFactor = Math.abs(values.toArrowScale);
        type = values.toArrowType;
      } else {
        node1 = this.to;
        node2 = this.from;
        reversed = values.middleArrowScale < 0;
        scaleFactor = Math.abs(values.middleArrowScale);
        type = values.middleArrowType;
      }
      var length = 15 * scaleFactor + 3 * lineWidth; // 3* lineWidth is the width of the edge.
      // if not connected to itself
      if (node1 != node2) {
        var approximateEdgeLength = _Math$hypot(node1.x - node2.x, node1.y - node2.y);
        var relativeLength = length / approximateEdgeLength;
        if (position !== "middle") {
          // draw arrow head
          if (this.options.smooth.enabled === true) {
            var pointT = this._findBorderPosition(node1, ctx, {
              via: viaNode
            });
            var guidePos = this.getPoint(pointT.t + relativeLength * (position === "from" ? 1 : -1), viaNode);
            angle = Math.atan2(pointT.y - guidePos.y, pointT.x - guidePos.x);
            arrowPoint = pointT;
          } else {
            angle = Math.atan2(node1.y - node2.y, node1.x - node2.x);
            arrowPoint = this._findBorderPosition(node1, ctx);
          }
        } else {
          // Negative half length reverses arrow direction.
          var halfLength = (reversed ? -relativeLength : relativeLength) / 2;
          var guidePos1 = this.getPoint(0.5 + halfLength, viaNode);
          var guidePos2 = this.getPoint(0.5 - halfLength, viaNode);
          angle = Math.atan2(guidePos1.y - guidePos2.y, guidePos1.x - guidePos2.x);
          arrowPoint = this.getPoint(0.5, viaNode);
        }
      } else {
        // draw circle
        var _this$_getCircleData9 = this._getCircleData(ctx),
          _this$_getCircleData10 = _slicedToArray(_this$_getCircleData9, 3),
          x = _this$_getCircleData10[0],
          y = _this$_getCircleData10[1],
          radius = _this$_getCircleData10[2];
        if (position === "from") {
          var low = this.options.selfReference.angle;
          var high = this.options.selfReference.angle + Math.PI;
          var _pointT = this._findBorderPositionCircle(this.from, ctx, {
            x: x,
            y: y,
            low: low,
            high: high,
            direction: -1
          });
          angle = _pointT.t * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
          arrowPoint = _pointT;
        } else if (position === "to") {
          var _low = this.options.selfReference.angle;
          var _high = this.options.selfReference.angle + Math.PI;
          var _pointT2 = this._findBorderPositionCircle(this.from, ctx, {
            x: x,
            y: y,
            low: _low,
            high: _high,
            direction: 1
          });
          angle = _pointT2.t * -2 * Math.PI + 1.5 * Math.PI - 1.1 * Math.PI;
          arrowPoint = _pointT2;
        } else {
          var pos = this.options.selfReference.angle / (2 * Math.PI);
          arrowPoint = this._pointOnCircle(x, y, radius, pos);
          angle = pos * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
        }
      }
      var xi = arrowPoint.x - length * 0.9 * Math.cos(angle);
      var yi = arrowPoint.y - length * 0.9 * Math.sin(angle);
      var arrowCore = {
        x: xi,
        y: yi
      };
      return {
        point: arrowPoint,
        core: arrowCore,
        angle: angle,
        length: length,
        type: type
      };
    }
    /** @inheritDoc */
  }, {
    key: "drawArrowHead",
    value: function drawArrowHead(ctx, values, _selected, _hover, arrowData) {
      // set style
      ctx.strokeStyle = this.getColor(ctx, values);
      ctx.fillStyle = ctx.strokeStyle;
      ctx.lineWidth = values.width;
      var canFill = EndPoints.draw(ctx, arrowData);
      if (canFill) {
        // draw shadow if enabled
        this.enableShadow(ctx, values);
        _fillInstanceProperty(ctx).call(ctx);
        // disable shadows for other elements.
        this.disableShadow(ctx, values);
      }
    }
    /**
     * Set the shadow formatting values in the context if enabled, do nothing otherwise.
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values for the shadow.
     */
  }, {
    key: "enableShadow",
    value: function enableShadow(ctx, values) {
      if (values.shadow === true) {
        ctx.shadowColor = values.shadowColor;
        ctx.shadowBlur = values.shadowSize;
        ctx.shadowOffsetX = values.shadowX;
        ctx.shadowOffsetY = values.shadowY;
      }
    }
    /**
     * Reset the shadow formatting values in the context if enabled, do nothing otherwise.
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values for the shadow.
     */
  }, {
    key: "disableShadow",
    value: function disableShadow(ctx, values) {
      if (values.shadow === true) {
        ctx.shadowColor = "rgba(0,0,0,0)";
        ctx.shadowBlur = 0;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
      }
    }
    /**
     * Render the background according to the formatting values.
     *
     * @param ctx - The context that will be used for rendering.
     * @param values - Formatting values for the background.
     */
  }, {
    key: "drawBackground",
    value: function drawBackground(ctx, values) {
      if (values.background !== false) {
        // save original line attrs
        var origCtxAttr = {
          strokeStyle: ctx.strokeStyle,
          lineWidth: ctx.lineWidth,
          dashes: ctx.dashes
        };
        ctx.strokeStyle = values.backgroundColor;
        ctx.lineWidth = values.backgroundSize;
        this.setStrokeDashed(ctx, values.backgroundDashes);
        ctx.stroke();
        // restore original line attrs
        ctx.strokeStyle = origCtxAttr.strokeStyle;
        ctx.lineWidth = origCtxAttr.lineWidth;
        ctx.dashes = origCtxAttr.dashes;
        this.setStrokeDashed(ctx, values.dashes);
      }
    }
    /**
     * Set the line dash pattern if supported. Logs a warning to the console if it isn't supported.
     *
     * @param ctx - The context that will be used for rendering.
     * @param dashes - The pattern [line, space, line…], true for default dashed line or false for normal line.
     */
  }, {
    key: "setStrokeDashed",
    value: function setStrokeDashed(ctx, dashes) {
      if (dashes !== false) {
        if (ctx.setLineDash !== undefined) {
          var pattern = _Array$isArray(dashes) ? dashes : [5, 5];
          ctx.setLineDash(pattern);
        } else {
          console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");
        }
      } else {
        if (ctx.setLineDash !== undefined) {
          ctx.setLineDash([]);
        } else {
          console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");
        }
      }
    }
  }]);
  return EdgeBase;
}();

function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor$1(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty$1(target, key, _Object$getOwnPropertyDescriptor$1(source, key)); }); } return target; }
function _createSuper$9(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$9(); 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 _isNativeReflectConstruct$9() { 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; } }
/**
 * The Base Class for all Bezier edges.
 * Bezier curves are used to model smooth gradual curves in paths between nodes.
 */
var BezierEdgeBase = /*#__PURE__*/function (_EdgeBase) {
  _inherits(BezierEdgeBase, _EdgeBase);
  var _super = _createSuper$9(BezierEdgeBase);
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param body - The body of the network.
   * @param labelModule - Label module.
   */
  function BezierEdgeBase(options, body, labelModule) {
    _classCallCheck(this, BezierEdgeBase);
    return _super.call(this, options, body, labelModule);
  }
  /**
   * Find the intersection between the border of the node and the edge.
   *
   * @remarks
   * This function uses binary search to look for the point where the bezier curve crosses the border of the node.
   * @param nearNode - The node (either from or to node of the edge).
   * @param ctx - The context that will be used for rendering.
   * @param viaNode - Additional node(s) the edge passes through.
   * @returns Cartesian coordinates of the intersection between the border of the node and the edge.
   */
  _createClass(BezierEdgeBase, [{
    key: "_findBorderPositionBezier",
    value: function _findBorderPositionBezier(nearNode, ctx) {
      var viaNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this._getViaCoordinates();
      var maxIterations = 10;
      var threshold = 0.2;
      var from = false;
      var high = 1;
      var low = 0;
      var node = this.to;
      var pos;
      var middle;
      var endPointOffset = this.options.endPointOffset ? this.options.endPointOffset.to : 0;
      if (nearNode.id === this.from.id) {
        node = this.from;
        from = true;
        endPointOffset = this.options.endPointOffset ? this.options.endPointOffset.from : 0;
      }
      if (this.options.arrowStrikethrough === false) {
        endPointOffset = 0;
      }
      var iteration = 0;
      do {
        middle = (low + high) * 0.5;
        pos = this.getPoint(middle, viaNode);
        var angle = Math.atan2(node.y - pos.y, node.x - pos.x);
        var distanceToBorder = node.distanceToBorder(ctx, angle) + endPointOffset;
        var distanceToPoint = Math.sqrt(Math.pow(pos.x - node.x, 2) + Math.pow(pos.y - node.y, 2));
        var difference = distanceToBorder - distanceToPoint;
        if (Math.abs(difference) < threshold) {
          break; // found
        } else if (difference < 0) {
          // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node.
          if (from === false) {
            low = middle;
          } else {
            high = middle;
          }
        } else {
          if (from === false) {
            high = middle;
          } else {
            low = middle;
          }
        }
        ++iteration;
      } while (low <= high && iteration < maxIterations);
      return _objectSpread(_objectSpread({}, pos), {}, {
        t: middle
      });
    }
    /**
     * Calculate the distance between a point (x3,y3) and a line segment from (x1,y1) to (x2,y2).
     *
     * @remarks
     * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
     * @param x1 - First end of the line segment on the x axis.
     * @param y1 - First end of the line segment on the y axis.
     * @param x2 - Second end of the line segment on the x axis.
     * @param y2 - Second end of the line segment on the y axis.
     * @param x3 - Position of the point on the x axis.
     * @param y3 - Position of the point on the y axis.
     * @param via - The control point for the edge.
     * @returns The distance between the line segment and the point.
     */
  }, {
    key: "_getDistanceToBezierEdge",
    value: function _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via) {
      // x3,y3 is the point
      var minDistance = 1e9;
      var distance;
      var i, t, x, y;
      var lastX = x1;
      var lastY = y1;
      for (i = 1; i < 10; i++) {
        t = 0.1 * i;
        x = Math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * x2;
        y = Math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * y2;
        if (i > 0) {
          distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3);
          minDistance = distance < minDistance ? distance : minDistance;
        }
        lastX = x;
        lastY = y;
      }
      return minDistance;
    }
    /**
     * Render a bezier curve between two nodes.
     *
     * @remarks
     * The method accepts zero, one or two control points.
     * Passing zero control points just draws a straight line.
     * @param ctx - The context that will be used for rendering.
     * @param values - Style options for edge drawing.
     * @param viaNode1 - First control point for curve drawing.
     * @param viaNode2 - Second control point for curve drawing.
     */
  }, {
    key: "_bezierCurve",
    value: function _bezierCurve(ctx, values, viaNode1, viaNode2) {
      ctx.beginPath();
      ctx.moveTo(this.fromPoint.x, this.fromPoint.y);
      if (viaNode1 != null && viaNode1.x != null) {
        if (viaNode2 != null && viaNode2.x != null) {
          ctx.bezierCurveTo(viaNode1.x, viaNode1.y, viaNode2.x, viaNode2.y, this.toPoint.x, this.toPoint.y);
        } else {
          ctx.quadraticCurveTo(viaNode1.x, viaNode1.y, this.toPoint.x, this.toPoint.y);
        }
      } else {
        // fallback to normal straight edge
        ctx.lineTo(this.toPoint.x, this.toPoint.y);
      }
      // draw a background
      this.drawBackground(ctx, values);
      // draw shadow if enabled
      this.enableShadow(ctx, values);
      ctx.stroke();
      this.disableShadow(ctx, values);
    }
    /** @inheritDoc */
  }, {
    key: "getViaNode",
    value: function getViaNode() {
      return this._getViaCoordinates();
    }
  }]);
  return BezierEdgeBase;
}(EdgeBase);

function _createSuper$8(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$8(); 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 _isNativeReflectConstruct$8() { 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; } }
/**
 * A Dynamic Bezier Edge. Bezier curves are used to model smooth gradual
 * curves in paths between nodes. The Dynamic piece refers to how the curve
 * reacts to physics changes.
 *
 * @augments BezierEdgeBase
 */
var BezierEdgeDynamic = /*#__PURE__*/function (_BezierEdgeBase) {
  _inherits(BezierEdgeDynamic, _BezierEdgeBase);
  var _super = _createSuper$8(BezierEdgeDynamic);
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param body - The body of the network.
   * @param labelModule - Label module.
   */
  function BezierEdgeDynamic(options, body, labelModule) {
    var _this;
    _classCallCheck(this, BezierEdgeDynamic);
    //this.via = undefined; // Here for completeness but not allowed to defined before super() is invoked.
    _this = _super.call(this, options, body, labelModule); // --> this calls the setOptions below
    _this.via = _this.via; // constructor → super → super → setOptions → setupSupportNode
    _this._boundFunction = function () {
      _this.positionBezierNode();
    };
    _this._body.emitter.on("_repositionBezierNodes", _this._boundFunction);
    return _this;
  }
  /** @inheritDoc */
  _createClass(BezierEdgeDynamic, [{
    key: "setOptions",
    value: function setOptions(options) {
      _get(_getPrototypeOf(BezierEdgeDynamic.prototype), "setOptions", this).call(this, options);
      // check if the physics has changed.
      var physicsChange = false;
      if (this.options.physics !== options.physics) {
        physicsChange = true;
      }
      // set the options and the to and from nodes
      this.options = options;
      this.id = this.options.id;
      this.from = this._body.nodes[this.options.from];
      this.to = this._body.nodes[this.options.to];
      // setup the support node and connect
      this.setupSupportNode();
      this.connect();
      // when we change the physics state of the edge, we reposition the support node.
      if (physicsChange === true) {
        this.via.setOptions({
          physics: this.options.physics
        });
        this.positionBezierNode();
      }
    }
    /** @inheritDoc */
  }, {
    key: "connect",
    value: function connect() {
      this.from = this._body.nodes[this.options.from];
      this.to = this._body.nodes[this.options.to];
      if (this.from === undefined || this.to === undefined || this.options.physics === false) {
        this.via.setOptions({
          physics: false
        });
      } else {
        // fix weird behaviour where a self referencing node has physics enabled
        if (this.from.id === this.to.id) {
          this.via.setOptions({
            physics: false
          });
        } else {
          this.via.setOptions({
            physics: true
          });
        }
      }
    }
    /** @inheritDoc */
  }, {
    key: "cleanup",
    value: function cleanup() {
      this._body.emitter.off("_repositionBezierNodes", this._boundFunction);
      if (this.via !== undefined) {
        delete this._body.nodes[this.via.id];
        this.via = undefined;
        return true;
      }
      return false;
    }
    /**
     * Create and add a support node if not already present.
     *
     * @remarks
     * Bezier curves require an anchor point to calculate the smooth flow.
     * These points are nodes.
     * These nodes are invisible but are used for the force calculation.
     *
     * The changed data is not called, if needed, it is returned by the main edge constructor.
     */
  }, {
    key: "setupSupportNode",
    value: function setupSupportNode() {
      if (this.via === undefined) {
        var nodeId = "edgeId:" + this.id;
        var node = this._body.functions.createNode({
          id: nodeId,
          shape: "circle",
          physics: true,
          hidden: true
        });
        this._body.nodes[nodeId] = node;
        this.via = node;
        this.via.parentEdgeId = this.id;
        this.positionBezierNode();
      }
    }
    /**
     * Position bezier node.
     */
  }, {
    key: "positionBezierNode",
    value: function positionBezierNode() {
      if (this.via !== undefined && this.from !== undefined && this.to !== undefined) {
        this.via.x = 0.5 * (this.from.x + this.to.x);
        this.via.y = 0.5 * (this.from.y + this.to.y);
      } else if (this.via !== undefined) {
        this.via.x = 0;
        this.via.y = 0;
      }
    }
    /** @inheritDoc */
  }, {
    key: "_line",
    value: function _line(ctx, values, viaNode) {
      this._bezierCurve(ctx, values, viaNode);
    }
    /** @inheritDoc */
  }, {
    key: "_getViaCoordinates",
    value: function _getViaCoordinates() {
      return this.via;
    }
    /** @inheritDoc */
  }, {
    key: "getViaNode",
    value: function getViaNode() {
      return this.via;
    }
    /** @inheritDoc */
  }, {
    key: "getPoint",
    value: function getPoint(position) {
      var viaNode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.via;
      if (this.from === this.to) {
        var _this$_getCircleData = this._getCircleData(),
          _this$_getCircleData2 = _slicedToArray(_this$_getCircleData, 3),
          cx = _this$_getCircleData2[0],
          cy = _this$_getCircleData2[1],
          cr = _this$_getCircleData2[2];
        var a = 2 * Math.PI * (1 - position);
        return {
          x: cx + cr * Math.sin(a),
          y: cy + cr - cr * (1 - Math.cos(a))
        };
      } else {
        return {
          x: Math.pow(1 - position, 2) * this.fromPoint.x + 2 * position * (1 - position) * viaNode.x + Math.pow(position, 2) * this.toPoint.x,
          y: Math.pow(1 - position, 2) * this.fromPoint.y + 2 * position * (1 - position) * viaNode.y + Math.pow(position, 2) * this.toPoint.y
        };
      }
    }
    /** @inheritDoc */
  }, {
    key: "_findBorderPosition",
    value: function _findBorderPosition(nearNode, ctx) {
      return this._findBorderPositionBezier(nearNode, ctx, this.via);
    }
    /** @inheritDoc */
  }, {
    key: "_getDistanceToEdge",
    value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
      // x3,y3 is the point
      return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, this.via);
    }
  }]);
  return BezierEdgeDynamic;
}(BezierEdgeBase);

function _createSuper$7(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$7(); 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 _isNativeReflectConstruct$7() { 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; } }
/**
 * A Static Bezier Edge. Bezier curves are used to model smooth gradual curves in paths between nodes.
 */
var BezierEdgeStatic = /*#__PURE__*/function (_BezierEdgeBase) {
  _inherits(BezierEdgeStatic, _BezierEdgeBase);
  var _super = _createSuper$7(BezierEdgeStatic);
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param body - The body of the network.
   * @param labelModule - Label module.
   */
  function BezierEdgeStatic(options, body, labelModule) {
    _classCallCheck(this, BezierEdgeStatic);
    return _super.call(this, options, body, labelModule);
  }
  /** @inheritDoc */
  _createClass(BezierEdgeStatic, [{
    key: "_line",
    value: function _line(ctx, values, viaNode) {
      this._bezierCurve(ctx, values, viaNode);
    }
    /** @inheritDoc */
  }, {
    key: "getViaNode",
    value: function getViaNode() {
      return this._getViaCoordinates();
    }
    /**
     * Compute the coordinates of the via node.
     *
     * @remarks
     * We do not use the to and fromPoints here to make the via nodes the same as edges without arrows.
     * @returns Cartesian coordinates of the via node.
     */
  }, {
    key: "_getViaCoordinates",
    value: function _getViaCoordinates() {
      // Assumption: x/y coordinates in from/to always defined
      var factor = this.options.smooth.roundness;
      var type = this.options.smooth.type;
      var dx = Math.abs(this.from.x - this.to.x);
      var dy = Math.abs(this.from.y - this.to.y);
      if (type === "discrete" || type === "diagonalCross") {
        var stepX;
        var stepY;
        if (dx <= dy) {
          stepX = stepY = factor * dy;
        } else {
          stepX = stepY = factor * dx;
        }
        if (this.from.x > this.to.x) {
          stepX = -stepX;
        }
        if (this.from.y >= this.to.y) {
          stepY = -stepY;
        }
        var xVia = this.from.x + stepX;
        var yVia = this.from.y + stepY;
        if (type === "discrete") {
          if (dx <= dy) {
            xVia = dx < factor * dy ? this.from.x : xVia;
          } else {
            yVia = dy < factor * dx ? this.from.y : yVia;
          }
        }
        return {
          x: xVia,
          y: yVia
        };
      } else if (type === "straightCross") {
        var _stepX = (1 - factor) * dx;
        var _stepY = (1 - factor) * dy;
        if (dx <= dy) {
          // up - down
          _stepX = 0;
          if (this.from.y < this.to.y) {
            _stepY = -_stepY;
          }
        } else {
          // left - right
          if (this.from.x < this.to.x) {
            _stepX = -_stepX;
          }
          _stepY = 0;
        }
        return {
          x: this.to.x + _stepX,
          y: this.to.y + _stepY
        };
      } else if (type === "horizontal") {
        var _stepX2 = (1 - factor) * dx;
        if (this.from.x < this.to.x) {
          _stepX2 = -_stepX2;
        }
        return {
          x: this.to.x + _stepX2,
          y: this.from.y
        };
      } else if (type === "vertical") {
        var _stepY2 = (1 - factor) * dy;
        if (this.from.y < this.to.y) {
          _stepY2 = -_stepY2;
        }
        return {
          x: this.from.x,
          y: this.to.y + _stepY2
        };
      } else if (type === "curvedCW") {
        dx = this.to.x - this.from.x;
        dy = this.from.y - this.to.y;
        var radius = Math.sqrt(dx * dx + dy * dy);
        var pi = Math.PI;
        var originalAngle = Math.atan2(dy, dx);
        var myAngle = (originalAngle + (factor * 0.5 + 0.5) * pi) % (2 * pi);
        return {
          x: this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle),
          y: this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle)
        };
      } else if (type === "curvedCCW") {
        dx = this.to.x - this.from.x;
        dy = this.from.y - this.to.y;
        var _radius = Math.sqrt(dx * dx + dy * dy);
        var _pi = Math.PI;
        var _originalAngle = Math.atan2(dy, dx);
        var _myAngle = (_originalAngle + (-factor * 0.5 + 0.5) * _pi) % (2 * _pi);
        return {
          x: this.from.x + (factor * 0.5 + 0.5) * _radius * Math.sin(_myAngle),
          y: this.from.y + (factor * 0.5 + 0.5) * _radius * Math.cos(_myAngle)
        };
      } else {
        // continuous
        var _stepX3;
        var _stepY3;
        if (dx <= dy) {
          _stepX3 = _stepY3 = factor * dy;
        } else {
          _stepX3 = _stepY3 = factor * dx;
        }
        if (this.from.x > this.to.x) {
          _stepX3 = -_stepX3;
        }
        if (this.from.y >= this.to.y) {
          _stepY3 = -_stepY3;
        }
        var _xVia = this.from.x + _stepX3;
        var _yVia = this.from.y + _stepY3;
        if (dx <= dy) {
          if (this.from.x <= this.to.x) {
            _xVia = this.to.x < _xVia ? this.to.x : _xVia;
          } else {
            _xVia = this.to.x > _xVia ? this.to.x : _xVia;
          }
        } else {
          if (this.from.y >= this.to.y) {
            _yVia = this.to.y > _yVia ? this.to.y : _yVia;
          } else {
            _yVia = this.to.y < _yVia ? this.to.y : _yVia;
          }
        }
        return {
          x: _xVia,
          y: _yVia
        };
      }
    }
    /** @inheritDoc */
  }, {
    key: "_findBorderPosition",
    value: function _findBorderPosition(nearNode, ctx) {
      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      return this._findBorderPositionBezier(nearNode, ctx, options.via);
    }
    /** @inheritDoc */
  }, {
    key: "_getDistanceToEdge",
    value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
      var viaNode = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : this._getViaCoordinates();
      // x3,y3 is the point
      return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, viaNode);
    }
    /** @inheritDoc */
  }, {
    key: "getPoint",
    value: function getPoint(position) {
      var viaNode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._getViaCoordinates();
      var t = position;
      var x = Math.pow(1 - t, 2) * this.fromPoint.x + 2 * t * (1 - t) * viaNode.x + Math.pow(t, 2) * this.toPoint.x;
      var y = Math.pow(1 - t, 2) * this.fromPoint.y + 2 * t * (1 - t) * viaNode.y + Math.pow(t, 2) * this.toPoint.y;
      return {
        x: x,
        y: y
      };
    }
  }]);
  return BezierEdgeStatic;
}(BezierEdgeBase);

function _createSuper$6(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$6(); 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 _isNativeReflectConstruct$6() { 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; } }
/**
 * A Base Class for all Cubic Bezier Edges. Bezier curves are used to model
 * smooth gradual curves in paths between nodes.
 *
 * @augments BezierEdgeBase
 */
var CubicBezierEdgeBase = /*#__PURE__*/function (_BezierEdgeBase) {
  _inherits(CubicBezierEdgeBase, _BezierEdgeBase);
  var _super = _createSuper$6(CubicBezierEdgeBase);
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param body - The body of the network.
   * @param labelModule - Label module.
   */
  function CubicBezierEdgeBase(options, body, labelModule) {
    _classCallCheck(this, CubicBezierEdgeBase);
    return _super.call(this, options, body, labelModule);
  }
  /**
   * Calculate the distance between a point (x3,y3) and a line segment from (x1,y1) to (x2,y2).
   *
   * @remarks
   * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
   * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
   * @param x1 - First end of the line segment on the x axis.
   * @param y1 - First end of the line segment on the y axis.
   * @param x2 - Second end of the line segment on the x axis.
   * @param y2 - Second end of the line segment on the y axis.
   * @param x3 - Position of the point on the x axis.
   * @param y3 - Position of the point on the y axis.
   * @param via1 - The first point this edge passes through.
   * @param via2 - The second point this edge passes through.
   * @returns The distance between the line segment and the point.
   */
  _createClass(CubicBezierEdgeBase, [{
    key: "_getDistanceToBezierEdge2",
    value: function _getDistanceToBezierEdge2(x1, y1, x2, y2, x3, y3, via1, via2) {
      // x3,y3 is the point
      var minDistance = 1e9;
      var lastX = x1;
      var lastY = y1;
      var vec = [0, 0, 0, 0];
      for (var i = 1; i < 10; i++) {
        var t = 0.1 * i;
        vec[0] = Math.pow(1 - t, 3);
        vec[1] = 3 * t * Math.pow(1 - t, 2);
        vec[2] = 3 * Math.pow(t, 2) * (1 - t);
        vec[3] = Math.pow(t, 3);
        var x = vec[0] * x1 + vec[1] * via1.x + vec[2] * via2.x + vec[3] * x2;
        var y = vec[0] * y1 + vec[1] * via1.y + vec[2] * via2.y + vec[3] * y2;
        if (i > 0) {
          var distance = this._getDistanceToLine(lastX, lastY, x, y, x3, y3);
          minDistance = distance < minDistance ? distance : minDistance;
        }
        lastX = x;
        lastY = y;
      }
      return minDistance;
    }
  }]);
  return CubicBezierEdgeBase;
}(BezierEdgeBase);

function _createSuper$5(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$5(); 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 _isNativeReflectConstruct$5() { 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; } }
/**
 * A Cubic Bezier Edge. Bezier curves are used to model smooth gradual curves in paths between nodes.
 */
var CubicBezierEdge = /*#__PURE__*/function (_CubicBezierEdgeBase) {
  _inherits(CubicBezierEdge, _CubicBezierEdgeBase);
  var _super = _createSuper$5(CubicBezierEdge);
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param body - The body of the network.
   * @param labelModule - Label module.
   */
  function CubicBezierEdge(options, body, labelModule) {
    _classCallCheck(this, CubicBezierEdge);
    return _super.call(this, options, body, labelModule);
  }
  /** @inheritDoc */
  _createClass(CubicBezierEdge, [{
    key: "_line",
    value: function _line(ctx, values, viaNodes) {
      // get the coordinates of the support points.
      var via1 = viaNodes[0];
      var via2 = viaNodes[1];
      this._bezierCurve(ctx, values, via1, via2);
    }
    /**
     * Compute the additional points the edge passes through.
     *
     * @returns Cartesian coordinates of the points the edge passes through.
     */
  }, {
    key: "_getViaCoordinates",
    value: function _getViaCoordinates() {
      var dx = this.from.x - this.to.x;
      var dy = this.from.y - this.to.y;
      var x1;
      var y1;
      var x2;
      var y2;
      var roundness = this.options.smooth.roundness;
      // horizontal if x > y or if direction is forced or if direction is horizontal
      if ((Math.abs(dx) > Math.abs(dy) || this.options.smooth.forceDirection === true || this.options.smooth.forceDirection === "horizontal") && this.options.smooth.forceDirection !== "vertical") {
        y1 = this.from.y;
        y2 = this.to.y;
        x1 = this.from.x - roundness * dx;
        x2 = this.to.x + roundness * dx;
      } else {
        y1 = this.from.y - roundness * dy;
        y2 = this.to.y + roundness * dy;
        x1 = this.from.x;
        x2 = this.to.x;
      }
      return [{
        x: x1,
        y: y1
      }, {
        x: x2,
        y: y2
      }];
    }
    /** @inheritDoc */
  }, {
    key: "getViaNode",
    value: function getViaNode() {
      return this._getViaCoordinates();
    }
    /** @inheritDoc */
  }, {
    key: "_findBorderPosition",
    value: function _findBorderPosition(nearNode, ctx) {
      return this._findBorderPositionBezier(nearNode, ctx);
    }
    /** @inheritDoc */
  }, {
    key: "_getDistanceToEdge",
    value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
      var _ref = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : this._getViaCoordinates(),
        _ref2 = _slicedToArray(_ref, 2),
        via1 = _ref2[0],
        via2 = _ref2[1];
      // x3,y3 is the point
      return this._getDistanceToBezierEdge2(x1, y1, x2, y2, x3, y3, via1, via2);
    }
    /** @inheritDoc */
  }, {
    key: "getPoint",
    value: function getPoint(position) {
      var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._getViaCoordinates(),
        _ref4 = _slicedToArray(_ref3, 2),
        via1 = _ref4[0],
        via2 = _ref4[1];
      var t = position;
      var vec = [Math.pow(1 - t, 3), 3 * t * Math.pow(1 - t, 2), 3 * Math.pow(t, 2) * (1 - t), Math.pow(t, 3)];
      var x = vec[0] * this.fromPoint.x + vec[1] * via1.x + vec[2] * via2.x + vec[3] * this.toPoint.x;
      var y = vec[0] * this.fromPoint.y + vec[1] * via1.y + vec[2] * via2.y + vec[3] * this.toPoint.y;
      return {
        x: x,
        y: y
      };
    }
  }]);
  return CubicBezierEdge;
}(CubicBezierEdgeBase);

function _createSuper$4(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$4(); 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 _isNativeReflectConstruct$4() { 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; } }
/**
 * A Straight Edge.
 */
var StraightEdge = /*#__PURE__*/function (_EdgeBase) {
  _inherits(StraightEdge, _EdgeBase);
  var _super = _createSuper$4(StraightEdge);
  /**
   * Create a new instance.
   *
   * @param options - The options object of given edge.
   * @param body - The body of the network.
   * @param labelModule - Label module.
   */
  function StraightEdge(options, body, labelModule) {
    _classCallCheck(this, StraightEdge);
    return _super.call(this, options, body, labelModule);
  }
  /** @inheritDoc */
  _createClass(StraightEdge, [{
    key: "_line",
    value: function _line(ctx, values) {
      // draw a straight line
      ctx.beginPath();
      ctx.moveTo(this.fromPoint.x, this.fromPoint.y);
      ctx.lineTo(this.toPoint.x, this.toPoint.y);
      // draw shadow if enabled
      this.enableShadow(ctx, values);
      ctx.stroke();
      this.disableShadow(ctx, values);
    }
    /** @inheritDoc */
  }, {
    key: "getViaNode",
    value: function getViaNode() {
      return undefined;
    }
    /** @inheritDoc */
  }, {
    key: "getPoint",
    value: function getPoint(position) {
      return {
        x: (1 - position) * this.fromPoint.x + position * this.toPoint.x,
        y: (1 - position) * this.fromPoint.y + position * this.toPoint.y
      };
    }
    /** @inheritDoc */
  }, {
    key: "_findBorderPosition",
    value: function _findBorderPosition(nearNode, ctx) {
      var node1 = this.to;
      var node2 = this.from;
      if (nearNode.id === this.from.id) {
        node1 = this.from;
        node2 = this.to;
      }
      var angle = Math.atan2(node1.y - node2.y, node1.x - node2.x);
      var dx = node1.x - node2.x;
      var dy = node1.y - node2.y;
      var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy);
      var toBorderDist = nearNode.distanceToBorder(ctx, angle);
      var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength;
      return {
        x: (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x,
        y: (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y,
        t: 0
      };
    }
    /** @inheritDoc */
  }, {
    key: "_getDistanceToEdge",
    value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) {
      // x3,y3 is the point
      return this._getDistanceToLine(x1, y1, x2, y2, x3, y3);
    }
  }]);
  return StraightEdge;
}(EdgeBase);

/**
 * An edge connects two nodes and has a specific direction.
 */
var Edge = /*#__PURE__*/function () {
  /**
   * @param {object} options        values specific to this edge, must contain at least 'from' and 'to'
   * @param {object} body           shared state from Network instance
   * @param {Network.Images} imagelist  A list with images. Only needed when the edge has image arrows.
   * @param {object} globalOptions  options from the EdgesHandler instance
   * @param {object} defaultOptions default options from the EdgeHandler instance. Value and reference are constant
   */
  function Edge(options, body, imagelist, globalOptions, defaultOptions) {
    _classCallCheck(this, Edge);
    if (body === undefined) {
      throw new Error("No body provided");
    }

    // Since globalOptions is constant in values as well as reference,
    // Following needs to be done only once.

    this.options = bridgeObject(globalOptions);
    this.globalOptions = globalOptions;
    this.defaultOptions = defaultOptions;
    this.body = body;
    this.imagelist = imagelist;

    // initialize variables
    this.id = undefined;
    this.fromId = undefined;
    this.toId = undefined;
    this.selected = false;
    this.hover = false;
    this.labelDirty = true;
    this.baseWidth = this.options.width;
    this.baseFontSize = this.options.font.size;
    this.from = undefined; // a node
    this.to = undefined; // a node

    this.edgeType = undefined;
    this.connected = false;
    this.labelModule = new Label(this.body, this.options, true /* It's an edge label */);

    this.setOptions(options);
  }

  /**
   * Set or overwrite options for the edge
   *
   * @param {object} options  an object with options
   * @returns {undefined|boolean} undefined if no options, true if layout affecting data changed, false otherwise.
   */
  _createClass(Edge, [{
    key: "setOptions",
    value: function setOptions(options) {
      if (!options) {
        return;
      }

      // Following options if changed affect the layout.
      var affectsLayout = typeof options.physics !== "undefined" && this.options.physics !== options.physics || typeof options.hidden !== "undefined" && (this.options.hidden || false) !== (options.hidden || false) || typeof options.from !== "undefined" && this.options.from !== options.from || typeof options.to !== "undefined" && this.options.to !== options.to;
      Edge.parseOptions(this.options, options, true, this.globalOptions);
      if (options.id !== undefined) {
        this.id = options.id;
      }
      if (options.from !== undefined) {
        this.fromId = options.from;
      }
      if (options.to !== undefined) {
        this.toId = options.to;
      }
      if (options.title !== undefined) {
        this.title = options.title;
      }
      if (options.value !== undefined) {
        options.value = _parseFloat(options.value);
      }
      var pile = [options, this.options, this.defaultOptions];
      this.chooser = choosify("edge", pile);

      // update label Module
      this.updateLabelModule(options);

      // Update edge type, this if changed affects the layout.
      affectsLayout = this.updateEdgeType() || affectsLayout;

      // if anything has been updates, reset the selection width and the hover width
      this._setInteractionWidths();

      // A node is connected when it has a from and to node that both exist in the network.body.nodes.
      this.connect();
      return affectsLayout;
    }

    /**
     *
     * @param {object} parentOptions
     * @param {object} newOptions
     * @param {boolean} [allowDeletion=false]
     * @param {object} [globalOptions={}]
     * @param {boolean} [copyFromGlobals=false]
     */
  }, {
    key: "getFormattingValues",
    value:
    /**
     *
     * @returns {ArrowOptions}
     */
    function getFormattingValues() {
      var toArrow = this.options.arrows.to === true || this.options.arrows.to.enabled === true;
      var fromArrow = this.options.arrows.from === true || this.options.arrows.from.enabled === true;
      var middleArrow = this.options.arrows.middle === true || this.options.arrows.middle.enabled === true;
      var inheritsColor = this.options.color.inherit;
      var values = {
        toArrow: toArrow,
        toArrowScale: this.options.arrows.to.scaleFactor,
        toArrowType: this.options.arrows.to.type,
        toArrowSrc: this.options.arrows.to.src,
        toArrowImageWidth: this.options.arrows.to.imageWidth,
        toArrowImageHeight: this.options.arrows.to.imageHeight,
        middleArrow: middleArrow,
        middleArrowScale: this.options.arrows.middle.scaleFactor,
        middleArrowType: this.options.arrows.middle.type,
        middleArrowSrc: this.options.arrows.middle.src,
        middleArrowImageWidth: this.options.arrows.middle.imageWidth,
        middleArrowImageHeight: this.options.arrows.middle.imageHeight,
        fromArrow: fromArrow,
        fromArrowScale: this.options.arrows.from.scaleFactor,
        fromArrowType: this.options.arrows.from.type,
        fromArrowSrc: this.options.arrows.from.src,
        fromArrowImageWidth: this.options.arrows.from.imageWidth,
        fromArrowImageHeight: this.options.arrows.from.imageHeight,
        arrowStrikethrough: this.options.arrowStrikethrough,
        color: inheritsColor ? undefined : this.options.color.color,
        inheritsColor: inheritsColor,
        opacity: this.options.color.opacity,
        hidden: this.options.hidden,
        length: this.options.length,
        shadow: this.options.shadow.enabled,
        shadowColor: this.options.shadow.color,
        shadowSize: this.options.shadow.size,
        shadowX: this.options.shadow.x,
        shadowY: this.options.shadow.y,
        dashes: this.options.dashes,
        width: this.options.width,
        background: this.options.background.enabled,
        backgroundColor: this.options.background.color,
        backgroundSize: this.options.background.size,
        backgroundDashes: this.options.background.dashes
      };
      if (this.selected || this.hover) {
        if (this.chooser === true) {
          if (this.selected) {
            var selectedWidth = this.options.selectionWidth;
            if (typeof selectedWidth === "function") {
              values.width = selectedWidth(values.width);
            } else if (typeof selectedWidth === "number") {
              values.width += selectedWidth;
            }
            values.width = Math.max(values.width, 0.3 / this.body.view.scale);
            values.color = this.options.color.highlight;
            values.shadow = this.options.shadow.enabled;
          } else if (this.hover) {
            var hoverWidth = this.options.hoverWidth;
            if (typeof hoverWidth === "function") {
              values.width = hoverWidth(values.width);
            } else if (typeof hoverWidth === "number") {
              values.width += hoverWidth;
            }
            values.width = Math.max(values.width, 0.3 / this.body.view.scale);
            values.color = this.options.color.hover;
            values.shadow = this.options.shadow.enabled;
          }
        } else if (typeof this.chooser === "function") {
          this.chooser(values, this.options.id, this.selected, this.hover);
          if (values.color !== undefined) {
            values.inheritsColor = false;
          }
          if (values.shadow === false) {
            if (values.shadowColor !== this.options.shadow.color || values.shadowSize !== this.options.shadow.size || values.shadowX !== this.options.shadow.x || values.shadowY !== this.options.shadow.y) {
              values.shadow = true;
            }
          }
        }
      } else {
        values.shadow = this.options.shadow.enabled;
        values.width = Math.max(values.width, 0.3 / this.body.view.scale);
      }
      return values;
    }

    /**
     * update the options in the label module
     *
     * @param {object} options
     */
  }, {
    key: "updateLabelModule",
    value: function updateLabelModule(options) {
      var pile = [options, this.options, this.globalOptions,
      // Currently set global edge options
      this.defaultOptions];
      this.labelModule.update(this.options, pile);
      if (this.labelModule.baseSize !== undefined) {
        this.baseFontSize = this.labelModule.baseSize;
      }
    }

    /**
     * update the edge type, set the options
     *
     * @returns {boolean}
     */
  }, {
    key: "updateEdgeType",
    value: function updateEdgeType() {
      var smooth = this.options.smooth;
      var dataChanged = false;
      var changeInType = true;
      if (this.edgeType !== undefined) {
        if (this.edgeType instanceof BezierEdgeDynamic && smooth.enabled === true && smooth.type === "dynamic" || this.edgeType instanceof CubicBezierEdge && smooth.enabled === true && smooth.type === "cubicBezier" || this.edgeType instanceof BezierEdgeStatic && smooth.enabled === true && smooth.type !== "dynamic" && smooth.type !== "cubicBezier" || this.edgeType instanceof StraightEdge && smooth.type.enabled === false) {
          changeInType = false;
        }
        if (changeInType === true) {
          dataChanged = this.cleanup();
        }
      }
      if (changeInType === true) {
        if (smooth.enabled === true) {
          if (smooth.type === "dynamic") {
            dataChanged = true;
            this.edgeType = new BezierEdgeDynamic(this.options, this.body, this.labelModule);
          } else if (smooth.type === "cubicBezier") {
            this.edgeType = new CubicBezierEdge(this.options, this.body, this.labelModule);
          } else {
            this.edgeType = new BezierEdgeStatic(this.options, this.body, this.labelModule);
          }
        } else {
          this.edgeType = new StraightEdge(this.options, this.body, this.labelModule);
        }
      } else {
        // if nothing changes, we just set the options.
        this.edgeType.setOptions(this.options);
      }
      return dataChanged;
    }

    /**
     * Connect an edge to its nodes
     */
  }, {
    key: "connect",
    value: function connect() {
      this.disconnect();
      this.from = this.body.nodes[this.fromId] || undefined;
      this.to = this.body.nodes[this.toId] || undefined;
      this.connected = this.from !== undefined && this.to !== undefined;
      if (this.connected === true) {
        this.from.attachEdge(this);
        this.to.attachEdge(this);
      } else {
        if (this.from) {
          this.from.detachEdge(this);
        }
        if (this.to) {
          this.to.detachEdge(this);
        }
      }
      this.edgeType.connect();
    }

    /**
     * Disconnect an edge from its nodes
     */
  }, {
    key: "disconnect",
    value: function disconnect() {
      if (this.from) {
        this.from.detachEdge(this);
        this.from = undefined;
      }
      if (this.to) {
        this.to.detachEdge(this);
        this.to = undefined;
      }
      this.connected = false;
    }

    /**
     * get the title of this edge.
     *
     * @returns {string} title    The title of the edge, or undefined when no title
     *                           has been set.
     */
  }, {
    key: "getTitle",
    value: function getTitle() {
      return this.title;
    }

    /**
     * check if this node is selecte
     *
     * @returns {boolean} selected   True if node is selected, else false
     */
  }, {
    key: "isSelected",
    value: function isSelected() {
      return this.selected;
    }

    /**
     * Retrieve the value of the edge. Can be undefined
     *
     * @returns {number} value
     */
  }, {
    key: "getValue",
    value: function getValue() {
      return this.options.value;
    }

    /**
     * Adjust the value range of the edge. The edge will adjust it's width
     * based on its value.
     *
     * @param {number} min
     * @param {number} max
     * @param {number} total
     */
  }, {
    key: "setValueRange",
    value: function setValueRange(min, max, total) {
      if (this.options.value !== undefined) {
        var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value);
        var widthDiff = this.options.scaling.max - this.options.scaling.min;
        if (this.options.scaling.label.enabled === true) {
          var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min;
          this.options.font.size = this.options.scaling.label.min + scale * fontDiff;
        }
        this.options.width = this.options.scaling.min + scale * widthDiff;
      } else {
        this.options.width = this.baseWidth;
        this.options.font.size = this.baseFontSize;
      }
      this._setInteractionWidths();
      this.updateLabelModule();
    }

    /**
     *
     * @private
     */
  }, {
    key: "_setInteractionWidths",
    value: function _setInteractionWidths() {
      if (typeof this.options.hoverWidth === "function") {
        this.edgeType.hoverWidth = this.options.hoverWidth(this.options.width);
      } else {
        this.edgeType.hoverWidth = this.options.hoverWidth + this.options.width;
      }
      if (typeof this.options.selectionWidth === "function") {
        this.edgeType.selectionWidth = this.options.selectionWidth(this.options.width);
      } else {
        this.edgeType.selectionWidth = this.options.selectionWidth + this.options.width;
      }
    }

    /**
     * Redraw a edge
     * Draw this edge in the given canvas
     * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
     *
     * @param {CanvasRenderingContext2D}   ctx
     */
  }, {
    key: "draw",
    value: function draw(ctx) {
      var values = this.getFormattingValues();
      if (values.hidden) {
        return;
      }

      // get the via node from the edge type
      var viaNode = this.edgeType.getViaNode();

      // draw line and label
      this.edgeType.drawLine(ctx, values, this.selected, this.hover, viaNode);
      this.drawLabel(ctx, viaNode);
    }

    /**
     * Redraw arrows
     * Draw this arrows in the given canvas
     * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
     *
     * @param {CanvasRenderingContext2D}   ctx
     */
  }, {
    key: "drawArrows",
    value: function drawArrows(ctx) {
      var values = this.getFormattingValues();
      if (values.hidden) {
        return;
      }

      // get the via node from the edge type
      var viaNode = this.edgeType.getViaNode();
      var arrowData = {};

      // restore edge targets to defaults
      this.edgeType.fromPoint = this.edgeType.from;
      this.edgeType.toPoint = this.edgeType.to;

      // from and to arrows give a different end point for edges. we set them here
      if (values.fromArrow) {
        arrowData.from = this.edgeType.getArrowData(ctx, "from", viaNode, this.selected, this.hover, values);
        if (values.arrowStrikethrough === false) this.edgeType.fromPoint = arrowData.from.core;
        if (values.fromArrowSrc) {
          arrowData.from.image = this.imagelist.load(values.fromArrowSrc);
        }
        if (values.fromArrowImageWidth) {
          arrowData.from.imageWidth = values.fromArrowImageWidth;
        }
        if (values.fromArrowImageHeight) {
          arrowData.from.imageHeight = values.fromArrowImageHeight;
        }
      }
      if (values.toArrow) {
        arrowData.to = this.edgeType.getArrowData(ctx, "to", viaNode, this.selected, this.hover, values);
        if (values.arrowStrikethrough === false) this.edgeType.toPoint = arrowData.to.core;
        if (values.toArrowSrc) {
          arrowData.to.image = this.imagelist.load(values.toArrowSrc);
        }
        if (values.toArrowImageWidth) {
          arrowData.to.imageWidth = values.toArrowImageWidth;
        }
        if (values.toArrowImageHeight) {
          arrowData.to.imageHeight = values.toArrowImageHeight;
        }
      }

      // the middle arrow depends on the line, which can depend on the to and from arrows so we do this one lastly.
      if (values.middleArrow) {
        arrowData.middle = this.edgeType.getArrowData(ctx, "middle", viaNode, this.selected, this.hover, values);
        if (values.middleArrowSrc) {
          arrowData.middle.image = this.imagelist.load(values.middleArrowSrc);
        }
        if (values.middleArrowImageWidth) {
          arrowData.middle.imageWidth = values.middleArrowImageWidth;
        }
        if (values.middleArrowImageHeight) {
          arrowData.middle.imageHeight = values.middleArrowImageHeight;
        }
      }
      if (values.fromArrow) {
        this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.from);
      }
      if (values.middleArrow) {
        this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.middle);
      }
      if (values.toArrow) {
        this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.to);
      }
    }

    /**
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {Node} viaNode
     */
  }, {
    key: "drawLabel",
    value: function drawLabel(ctx, viaNode) {
      if (this.options.label !== undefined) {
        // set style
        var node1 = this.from;
        var node2 = this.to;
        if (this.labelModule.differentState(this.selected, this.hover)) {
          this.labelModule.getTextSize(ctx, this.selected, this.hover);
        }
        var point;
        if (node1.id != node2.id) {
          this.labelModule.pointToSelf = false;
          point = this.edgeType.getPoint(0.5, viaNode);
          ctx.save();
          var rotationPoint = this._getRotation(ctx);
          if (rotationPoint.angle != 0) {
            ctx.translate(rotationPoint.x, rotationPoint.y);
            ctx.rotate(rotationPoint.angle);
          }

          // draw the label
          this.labelModule.draw(ctx, point.x, point.y, this.selected, this.hover);

          /*
          // Useful debug code: draw a border around the label
          // This should **not** be enabled in production!
          var size = this.labelModule.getSize();; // ;; intentional so lint catches it
          ctx.strokeStyle = "#ff0000";
          ctx.strokeRect(size.left, size.top, size.width, size.height);
          // End  debug code
          */

          ctx.restore();
        } else {
          // Ignore the orientations.
          this.labelModule.pointToSelf = true;

          // get circle coordinates
          var coordinates = getSelfRefCoordinates(ctx, this.options.selfReference.angle, this.options.selfReference.size, node1);
          point = this._pointOnCircle(coordinates.x, coordinates.y, this.options.selfReference.size, this.options.selfReference.angle);
          this.labelModule.draw(ctx, point.x, point.y, this.selected, this.hover);
        }
      }
    }

    /**
     * Determine all visual elements of this edge instance, in which the given
     * point falls within the bounding shape.
     *
     * @param {point} point
     * @returns {Array.<edgeClickItem|edgeLabelClickItem>} list with the items which are on the point
     */
  }, {
    key: "getItemsOnPoint",
    value: function getItemsOnPoint(point) {
      var ret = [];
      if (this.labelModule.visible()) {
        var rotationPoint = this._getRotation();
        if (pointInRect(this.labelModule.getSize(), point, rotationPoint)) {
          ret.push({
            edgeId: this.id,
            labelId: 0
          });
        }
      }
      var obj = {
        left: point.x,
        top: point.y
      };
      if (this.isOverlappingWith(obj)) {
        ret.push({
          edgeId: this.id
        });
      }
      return ret;
    }

    /**
     * Check if this object is overlapping with the provided object
     *
     * @param {object} obj   an object with parameters left, top
     * @returns {boolean}     True if location is located on the edge
     */
  }, {
    key: "isOverlappingWith",
    value: function isOverlappingWith(obj) {
      if (this.connected) {
        var distMax = 10;
        var xFrom = this.from.x;
        var yFrom = this.from.y;
        var xTo = this.to.x;
        var yTo = this.to.y;
        var xObj = obj.left;
        var yObj = obj.top;
        var dist = this.edgeType.getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj);
        return dist < distMax;
      } else {
        return false;
      }
    }

    /**
     * Determine the rotation point, if any.
     *
     * @param {CanvasRenderingContext2D} [ctx] if passed, do a recalculation of the label size
     * @returns {rotationPoint} the point to rotate around and the angle in radians to rotate
     * @private
     */
  }, {
    key: "_getRotation",
    value: function _getRotation(ctx) {
      var viaNode = this.edgeType.getViaNode();
      var point = this.edgeType.getPoint(0.5, viaNode);
      if (ctx !== undefined) {
        this.labelModule.calculateLabelSize(ctx, this.selected, this.hover, point.x, point.y);
      }
      var ret = {
        x: point.x,
        y: this.labelModule.size.yLine,
        angle: 0
      };
      if (!this.labelModule.visible()) {
        return ret; // Don't even bother doing the atan2, there's nothing to draw
      }

      if (this.options.font.align === "horizontal") {
        return ret; // No need to calculate angle
      }

      var dy = this.from.y - this.to.y;
      var dx = this.from.x - this.to.x;
      var angle = Math.atan2(dy, dx); // radians

      // rotate so that label is readable
      if (angle < -1 && dx < 0 || angle > 0 && dx < 0) {
        angle += Math.PI;
      }
      ret.angle = angle;
      return ret;
    }

    /**
     * Get a point on a circle
     *
     * @param {number} x
     * @param {number} y
     * @param {number} radius
     * @param {number} angle
     * @returns {object} point
     * @private
     */
  }, {
    key: "_pointOnCircle",
    value: function _pointOnCircle(x, y, radius, angle) {
      return {
        x: x + radius * Math.cos(angle),
        y: y - radius * Math.sin(angle)
      };
    }

    /**
     * Sets selected state to true
     */
  }, {
    key: "select",
    value: function select() {
      this.selected = true;
    }

    /**
     * Sets selected state to false
     */
  }, {
    key: "unselect",
    value: function unselect() {
      this.selected = false;
    }

    /**
     * cleans all required things on delete
     *
     * @returns {*}
     */
  }, {
    key: "cleanup",
    value: function cleanup() {
      return this.edgeType.cleanup();
    }

    /**
     * Remove edge from the list and perform necessary cleanup.
     */
  }, {
    key: "remove",
    value: function remove() {
      this.cleanup();
      this.disconnect();
      delete this.body.edges[this.id];
    }

    /**
     * Check if both connecting nodes exist
     *
     * @returns {boolean}
     */
  }, {
    key: "endPointsValid",
    value: function endPointsValid() {
      return this.body.nodes[this.fromId] !== undefined && this.body.nodes[this.toId] !== undefined;
    }
  }], [{
    key: "parseOptions",
    value: function parseOptions(parentOptions, newOptions) {
      var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
      var copyFromGlobals = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
      var fields = ["endPointOffset", "arrowStrikethrough", "id", "from", "hidden", "hoverWidth", "labelHighlightBold", "length", "line", "opacity", "physics", "scaling", "selectionWidth", "selfReferenceSize", "selfReference", "to", "title", "value", "width", "font", "chosen", "widthConstraint"];

      // only deep extend the items in the field array. These do not have shorthand.
      selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion);

      // Only use endPointOffset values (from and to) if it's valid values
      if (newOptions.endPointOffset !== undefined && newOptions.endPointOffset.from !== undefined) {
        if (_Number$isFinite(newOptions.endPointOffset.from)) {
          parentOptions.endPointOffset.from = newOptions.endPointOffset.from;
        } else {
          parentOptions.endPointOffset.from = globalOptions.endPointOffset.from !== undefined ? globalOptions.endPointOffset.from : 0;
          console.error("endPointOffset.from is not a valid number");
        }
      }
      if (newOptions.endPointOffset !== undefined && newOptions.endPointOffset.to !== undefined) {
        if (_Number$isFinite(newOptions.endPointOffset.to)) {
          parentOptions.endPointOffset.to = newOptions.endPointOffset.to;
        } else {
          parentOptions.endPointOffset.to = globalOptions.endPointOffset.to !== undefined ? globalOptions.endPointOffset.to : 0;
          console.error("endPointOffset.to is not a valid number");
        }
      }

      // Only copy label if it's a legal value.
      if (isValidLabel(newOptions.label)) {
        parentOptions.label = newOptions.label;
      } else if (!isValidLabel(parentOptions.label)) {
        parentOptions.label = undefined;
      }
      mergeOptions(parentOptions, newOptions, "smooth", globalOptions);
      mergeOptions(parentOptions, newOptions, "shadow", globalOptions);
      mergeOptions(parentOptions, newOptions, "background", globalOptions);
      if (newOptions.dashes !== undefined && newOptions.dashes !== null) {
        parentOptions.dashes = newOptions.dashes;
      } else if (allowDeletion === true && newOptions.dashes === null) {
        parentOptions.dashes = _Object$create$1(globalOptions.dashes); // this sets the pointer of the option back to the global option.
      }

      // set the scaling newOptions
      if (newOptions.scaling !== undefined && newOptions.scaling !== null) {
        if (newOptions.scaling.min !== undefined) {
          parentOptions.scaling.min = newOptions.scaling.min;
        }
        if (newOptions.scaling.max !== undefined) {
          parentOptions.scaling.max = newOptions.scaling.max;
        }
        mergeOptions(parentOptions.scaling, newOptions.scaling, "label", globalOptions.scaling);
      } else if (allowDeletion === true && newOptions.scaling === null) {
        parentOptions.scaling = _Object$create$1(globalOptions.scaling); // this sets the pointer of the option back to the global option.
      }

      // handle multiple input cases for arrows
      if (newOptions.arrows !== undefined && newOptions.arrows !== null) {
        if (typeof newOptions.arrows === "string") {
          var arrows = newOptions.arrows.toLowerCase();
          parentOptions.arrows.to.enabled = _indexOfInstanceProperty(arrows).call(arrows, "to") != -1;
          parentOptions.arrows.middle.enabled = _indexOfInstanceProperty(arrows).call(arrows, "middle") != -1;
          parentOptions.arrows.from.enabled = _indexOfInstanceProperty(arrows).call(arrows, "from") != -1;
        } else if (_typeof(newOptions.arrows) === "object") {
          mergeOptions(parentOptions.arrows, newOptions.arrows, "to", globalOptions.arrows);
          mergeOptions(parentOptions.arrows, newOptions.arrows, "middle", globalOptions.arrows);
          mergeOptions(parentOptions.arrows, newOptions.arrows, "from", globalOptions.arrows);
        } else {
          throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" + _JSON$stringify(newOptions.arrows));
        }
      } else if (allowDeletion === true && newOptions.arrows === null) {
        parentOptions.arrows = _Object$create$1(globalOptions.arrows); // this sets the pointer of the option back to the global option.
      }

      // handle multiple input cases for color
      if (newOptions.color !== undefined && newOptions.color !== null) {
        var fromColor = isString$1(newOptions.color) ? {
          color: newOptions.color,
          highlight: newOptions.color,
          hover: newOptions.color,
          inherit: false,
          opacity: 1
        } : newOptions.color;
        var toColor = parentOptions.color;

        // If passed, fill in values from default options - required in the case of no prototype bridging
        if (copyFromGlobals) {
          deepExtend(toColor, globalOptions.color, false, allowDeletion);
        } else {
          // Clear local properties - need to do it like this in order to retain prototype bridges
          for (var i in toColor) {
            if (Object.prototype.hasOwnProperty.call(toColor, i)) {
              delete toColor[i];
            }
          }
        }
        if (isString$1(toColor)) {
          toColor.color = toColor;
          toColor.highlight = toColor;
          toColor.hover = toColor;
          toColor.inherit = false;
          if (fromColor.opacity === undefined) {
            toColor.opacity = 1.0; // set default
          }
        } else {
          var colorsDefined = false;
          if (fromColor.color !== undefined) {
            toColor.color = fromColor.color;
            colorsDefined = true;
          }
          if (fromColor.highlight !== undefined) {
            toColor.highlight = fromColor.highlight;
            colorsDefined = true;
          }
          if (fromColor.hover !== undefined) {
            toColor.hover = fromColor.hover;
            colorsDefined = true;
          }
          if (fromColor.inherit !== undefined) {
            toColor.inherit = fromColor.inherit;
          }
          if (fromColor.opacity !== undefined) {
            toColor.opacity = Math.min(1, Math.max(0, fromColor.opacity));
          }
          if (colorsDefined === true) {
            toColor.inherit = false;
          } else {
            if (toColor.inherit === undefined) {
              toColor.inherit = "from"; // Set default
            }
          }
        }
      } else if (allowDeletion === true && newOptions.color === null) {
        parentOptions.color = bridgeObject(globalOptions.color); // set the object back to the global options
      }

      if (allowDeletion === true && newOptions.font === null) {
        parentOptions.font = bridgeObject(globalOptions.font); // set the object back to the global options
      }

      if (Object.prototype.hasOwnProperty.call(newOptions, "selfReferenceSize")) {
        console.warn("The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}");
        parentOptions.selfReference.size = newOptions.selfReferenceSize;
      }
    }
  }]);
  return Edge;
}();

/**
 * Handler for Edges
 */
var EdgesHandler = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Array.<Image>} images
   * @param {Array.<Group>} groups
   */
  function EdgesHandler(body, images, groups) {
    var _context,
      _this = this;
    _classCallCheck(this, EdgesHandler);
    this.body = body;
    this.images = images;
    this.groups = groups;

    // create the edge API in the body container
    this.body.functions.createEdge = _bindInstanceProperty$1(_context = this.create).call(_context, this);
    this.edgesListeners = {
      add: function add(event, params) {
        _this.add(params.items);
      },
      update: function update(event, params) {
        _this.update(params.items);
      },
      remove: function remove(event, params) {
        _this.remove(params.items);
      }
    };
    this.options = {};
    this.defaultOptions = {
      arrows: {
        to: {
          enabled: false,
          scaleFactor: 1,
          type: "arrow"
        },
        // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1}
        middle: {
          enabled: false,
          scaleFactor: 1,
          type: "arrow"
        },
        from: {
          enabled: false,
          scaleFactor: 1,
          type: "arrow"
        }
      },
      endPointOffset: {
        from: 0,
        to: 0
      },
      arrowStrikethrough: true,
      color: {
        color: "#848484",
        highlight: "#848484",
        hover: "#848484",
        inherit: "from",
        opacity: 1.0
      },
      dashes: false,
      font: {
        color: "#343434",
        size: 14,
        // px
        face: "arial",
        background: "none",
        strokeWidth: 2,
        // px
        strokeColor: "#ffffff",
        align: "horizontal",
        multi: false,
        vadjust: 0,
        bold: {
          mod: "bold"
        },
        boldital: {
          mod: "bold italic"
        },
        ital: {
          mod: "italic"
        },
        mono: {
          mod: "",
          size: 15,
          // px
          face: "courier new",
          vadjust: 2
        }
      },
      hidden: false,
      hoverWidth: 1.5,
      label: undefined,
      labelHighlightBold: true,
      length: undefined,
      physics: true,
      scaling: {
        min: 1,
        max: 15,
        label: {
          enabled: true,
          min: 14,
          max: 30,
          maxVisible: 30,
          drawThreshold: 5
        },
        customScalingFunction: function customScalingFunction(min, max, total, value) {
          if (max === min) {
            return 0.5;
          } else {
            var scale = 1 / (max - min);
            return Math.max(0, (value - min) * scale);
          }
        }
      },
      selectionWidth: 1.5,
      selfReference: {
        size: 20,
        angle: Math.PI / 4,
        renderBehindTheNode: true
      },
      shadow: {
        enabled: false,
        color: "rgba(0,0,0,0.5)",
        size: 10,
        x: 5,
        y: 5
      },
      background: {
        enabled: false,
        color: "rgba(111,111,111,1)",
        size: 10,
        dashes: false
      },
      smooth: {
        enabled: true,
        type: "dynamic",
        forceDirection: "none",
        roundness: 0.5
      },
      title: undefined,
      width: 1,
      value: undefined
    };
    deepExtend(this.options, this.defaultOptions);
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(EdgesHandler, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _this2 = this,
        _context2,
        _context3;
      // this allows external modules to force all dynamic curves to turn static.
      this.body.emitter.on("_forceDisableDynamicCurves", function (type) {
        var emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
        if (type === "dynamic") {
          type = "continuous";
        }
        var dataChanged = false;
        for (var edgeId in _this2.body.edges) {
          if (Object.prototype.hasOwnProperty.call(_this2.body.edges, edgeId)) {
            var edge = _this2.body.edges[edgeId];
            var edgeData = _this2.body.data.edges.get(edgeId);

            // only forcibly remove the smooth curve if the data has been set of the edge has the smooth curves defined.
            // this is because a change in the global would not affect these curves.
            if (edgeData != null) {
              var smoothOptions = edgeData.smooth;
              if (smoothOptions !== undefined) {
                if (smoothOptions.enabled === true && smoothOptions.type === "dynamic") {
                  if (type === undefined) {
                    edge.setOptions({
                      smooth: false
                    });
                  } else {
                    edge.setOptions({
                      smooth: {
                        type: type
                      }
                    });
                  }
                  dataChanged = true;
                }
              }
            }
          }
        }
        if (emit === true && dataChanged === true) {
          _this2.body.emitter.emit("_dataChanged");
        }
      });

      // this is called when options of EXISTING nodes or edges have changed.
      //
      // NOTE: Not true, called when options have NOT changed, for both existing as well as new nodes.
      //       See update() for logic.
      // TODO: Verify and examine the consequences of this. It might still trigger when
      //       non-option fields have changed, but then reconnecting edges is still useless.
      //       Alternatively, it might also be called when edges are removed.
      //
      this.body.emitter.on("_dataUpdated", function () {
        _this2.reconnectEdges();
      });

      // refresh the edges. Used when reverting from hierarchical layout
      this.body.emitter.on("refreshEdges", _bindInstanceProperty$1(_context2 = this.refresh).call(_context2, this));
      this.body.emitter.on("refresh", _bindInstanceProperty$1(_context3 = this.refresh).call(_context3, this));
      this.body.emitter.on("destroy", function () {
        forEach$1(_this2.edgesListeners, function (callback, event) {
          if (_this2.body.data.edges) _this2.body.data.edges.off(event, callback);
        });
        delete _this2.body.functions.createEdge;
        delete _this2.edgesListeners.add;
        delete _this2.edgesListeners.update;
        delete _this2.edgesListeners.remove;
        delete _this2.edgesListeners;
      });
    }

    /**
     *
     * @param {object} options
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        // use the parser from the Edge class to fill in all shorthand notations
        Edge.parseOptions(this.options, options, true, this.defaultOptions, true);

        // update smooth settings in all edges
        var dataChanged = false;
        if (options.smooth !== undefined) {
          for (var edgeId in this.body.edges) {
            if (Object.prototype.hasOwnProperty.call(this.body.edges, edgeId)) {
              dataChanged = this.body.edges[edgeId].updateEdgeType() || dataChanged;
            }
          }
        }

        // update fonts in all edges
        if (options.font !== undefined) {
          for (var _edgeId in this.body.edges) {
            if (Object.prototype.hasOwnProperty.call(this.body.edges, _edgeId)) {
              this.body.edges[_edgeId].updateLabelModule();
            }
          }
        }

        // update the state of the variables if needed
        if (options.hidden !== undefined || options.physics !== undefined || dataChanged === true) {
          this.body.emitter.emit("_dataChanged");
        }
      }
    }

    /**
     * Load edges by reading the data table
     *
     * @param {Array | DataSet | DataView} edges    The data containing the edges.
     * @param {boolean} [doNotEmit=false] - Suppress data changed event.
     * @private
     */
  }, {
    key: "setData",
    value: function setData(edges) {
      var _this3 = this;
      var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var oldEdgesData = this.body.data.edges;
      if (isDataViewLike("id", edges)) {
        this.body.data.edges = edges;
      } else if (_Array$isArray(edges)) {
        this.body.data.edges = new DataSet();
        this.body.data.edges.add(edges);
      } else if (!edges) {
        this.body.data.edges = new DataSet();
      } else {
        throw new TypeError("Array or DataSet expected");
      }

      // TODO: is this null or undefined or false?
      if (oldEdgesData) {
        // unsubscribe from old dataset
        forEach$1(this.edgesListeners, function (callback, event) {
          oldEdgesData.off(event, callback);
        });
      }

      // remove drawn edges
      this.body.edges = {};

      // TODO: is this null or undefined or false?
      if (this.body.data.edges) {
        // subscribe to new dataset
        forEach$1(this.edgesListeners, function (callback, event) {
          _this3.body.data.edges.on(event, callback);
        });

        // draw all new nodes
        var ids = this.body.data.edges.getIds();
        this.add(ids, true);
      }
      this.body.emitter.emit("_adjustEdgesForHierarchicalLayout");
      if (doNotEmit === false) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     * Add edges
     *
     * @param {number[] | string[]} ids
     * @param {boolean} [doNotEmit=false]
     * @private
     */
  }, {
    key: "add",
    value: function add(ids) {
      var doNotEmit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var edges = this.body.edges;
      var edgesData = this.body.data.edges;
      for (var i = 0; i < ids.length; i++) {
        var id = ids[i];
        var oldEdge = edges[id];
        if (oldEdge) {
          oldEdge.disconnect();
        }
        var data = edgesData.get(id, {
          showInternalIds: true
        });
        edges[id] = this.create(data);
      }
      this.body.emitter.emit("_adjustEdgesForHierarchicalLayout");
      if (doNotEmit === false) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     * Update existing edges, or create them when not yet existing
     *
     * @param {number[] | string[]} ids
     * @private
     */
  }, {
    key: "update",
    value: function update(ids) {
      var edges = this.body.edges;
      var edgesData = this.body.data.edges;
      var dataChanged = false;
      for (var i = 0; i < ids.length; i++) {
        var id = ids[i];
        var data = edgesData.get(id);
        var edge = edges[id];
        if (edge !== undefined) {
          // update edge
          edge.disconnect();
          dataChanged = edge.setOptions(data) || dataChanged; // if a support node is added, data can be changed.
          edge.connect();
        } else {
          // create edge
          this.body.edges[id] = this.create(data);
          dataChanged = true;
        }
      }
      if (dataChanged === true) {
        this.body.emitter.emit("_adjustEdgesForHierarchicalLayout");
        this.body.emitter.emit("_dataChanged");
      } else {
        this.body.emitter.emit("_dataUpdated");
      }
    }

    /**
     * Remove existing edges. Non existing ids will be ignored
     *
     * @param {number[] | string[]} ids
     * @param {boolean} [emit=true]
     * @private
     */
  }, {
    key: "remove",
    value: function remove(ids) {
      var emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      if (ids.length === 0) return; // early out

      var edges = this.body.edges;
      forEach$1(ids, function (id) {
        var edge = edges[id];
        if (edge !== undefined) {
          edge.remove();
        }
      });
      if (emit) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     * Refreshes Edge Handler
     */
  }, {
    key: "refresh",
    value: function refresh() {
      var _this4 = this;
      forEach$1(this.body.edges, function (edge, edgeId) {
        var data = _this4.body.data.edges.get(edgeId);
        if (data !== undefined) {
          edge.setOptions(data);
        }
      });
    }

    /**
     *
     * @param {object} properties
     * @returns {Edge}
     */
  }, {
    key: "create",
    value: function create(properties) {
      return new Edge(properties, this.body, this.images, this.options, this.defaultOptions);
    }

    /**
     * Reconnect all edges
     *
     * @private
     */
  }, {
    key: "reconnectEdges",
    value: function reconnectEdges() {
      var id;
      var nodes = this.body.nodes;
      var edges = this.body.edges;
      for (id in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, id)) {
          nodes[id].edges = [];
        }
      }
      for (id in edges) {
        if (Object.prototype.hasOwnProperty.call(edges, id)) {
          var edge = edges[id];
          edge.from = null;
          edge.to = null;
          edge.connect();
        }
      }
    }

    /**
     *
     * @param {Edge.id} edgeId
     * @returns {Array}
     */
  }, {
    key: "getConnectedNodes",
    value: function getConnectedNodes(edgeId) {
      var nodeList = [];
      if (this.body.edges[edgeId] !== undefined) {
        var edge = this.body.edges[edgeId];
        if (edge.fromId !== undefined) {
          nodeList.push(edge.fromId);
        }
        if (edge.toId !== undefined) {
          nodeList.push(edge.toId);
        }
      }
      return nodeList;
    }

    /**
     * There is no direct relation between the nodes and the edges DataSet,
     * so the right place to do call this is in the handler for event `_dataUpdated`.
     */
  }, {
    key: "_updateState",
    value: function _updateState() {
      this._addMissingEdges();
      this._removeInvalidEdges();
    }

    /**
     * Scan for missing nodes and remove corresponding edges, if any.
     *
     * @private
     */
  }, {
    key: "_removeInvalidEdges",
    value: function _removeInvalidEdges() {
      var _this5 = this;
      var edgesToDelete = [];
      forEach$1(this.body.edges, function (edge, id) {
        var toNode = _this5.body.nodes[edge.toId];
        var fromNode = _this5.body.nodes[edge.fromId];

        // Skip clustering edges here, let the Clustering module handle those
        if (toNode !== undefined && toNode.isCluster === true || fromNode !== undefined && fromNode.isCluster === true) {
          return;
        }
        if (toNode === undefined || fromNode === undefined) {
          edgesToDelete.push(id);
        }
      });
      this.remove(edgesToDelete, false);
    }

    /**
     * add all edges from dataset that are not in the cached state
     *
     * @private
     */
  }, {
    key: "_addMissingEdges",
    value: function _addMissingEdges() {
      var edgesData = this.body.data.edges;
      if (edgesData === undefined || edgesData === null) {
        return; // No edges DataSet yet; can happen on startup
      }

      var edges = this.body.edges;
      var addIds = [];
      _forEachInstanceProperty(edgesData).call(edgesData, function (edgeData, edgeId) {
        var edge = edges[edgeId];
        if (edge === undefined) {
          addIds.push(edgeId);
        }
      });
      this.add(addIds, true);
    }
  }]);
  return EdgesHandler;
}();

/**
 * Barnes Hut Solver
 */
var BarnesHutSolver = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function BarnesHutSolver(body, physicsBody, options) {
    _classCallCheck(this, BarnesHutSolver);
    this.body = body;
    this.physicsBody = physicsBody;
    this.barnesHutTree;
    this.setOptions(options);
    this._rng = Alea("BARNES HUT SOLVER");

    // debug: show grid
    // this.body.emitter.on("afterDrawing", (ctx) => {this._debug(ctx,'#ff0000')})
  }

  /**
   *
   * @param {object} options
   */
  _createClass(BarnesHutSolver, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
      this.thetaInversed = 1 / this.options.theta;

      // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius
      this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1, this.options.avoidOverlap));
    }

    /**
     * This function calculates the forces the nodes apply on each other based on a gravitational model.
     * The Barnes Hut method is used to speed up this N-body simulation.
     *
     * @private
     */
  }, {
    key: "solve",
    value: function solve() {
      if (this.options.gravitationalConstant !== 0 && this.physicsBody.physicsNodeIndices.length > 0) {
        var node;
        var nodes = this.body.nodes;
        var nodeIndices = this.physicsBody.physicsNodeIndices;
        var nodeCount = nodeIndices.length;

        // create the tree
        var barnesHutTree = this._formBarnesHutTree(nodes, nodeIndices);

        // for debugging
        this.barnesHutTree = barnesHutTree;

        // place the nodes one by one recursively
        for (var i = 0; i < nodeCount; i++) {
          node = nodes[nodeIndices[i]];
          if (node.options.mass > 0) {
            // starting with root is irrelevant, it never passes the BarnesHutSolver condition
            this._getForceContributions(barnesHutTree.root, node);
          }
        }
      }
    }

    /**
     * @param {object} parentBranch
     * @param {Node} node
     * @private
     */
  }, {
    key: "_getForceContributions",
    value: function _getForceContributions(parentBranch, node) {
      this._getForceContribution(parentBranch.children.NW, node);
      this._getForceContribution(parentBranch.children.NE, node);
      this._getForceContribution(parentBranch.children.SW, node);
      this._getForceContribution(parentBranch.children.SE, node);
    }

    /**
     * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass.
     * If a region contains a single node, we check if it is not itself, then we apply the force.
     *
     * @param {object} parentBranch
     * @param {Node} node
     * @private
     */
  }, {
    key: "_getForceContribution",
    value: function _getForceContribution(parentBranch, node) {
      // we get no force contribution from an empty region
      if (parentBranch.childrenCount > 0) {
        // get the distance from the center of mass to the node.
        var dx = parentBranch.centerOfMass.x - node.x;
        var dy = parentBranch.centerOfMass.y - node.y;
        var distance = Math.sqrt(dx * dx + dy * dy);

        // BarnesHutSolver condition
        // original condition : s/d < theta = passed  ===  d/s > 1/theta = passed
        // calcSize = 1/s --> d * 1/s > 1/theta = passed
        if (distance * parentBranch.calcSize > this.thetaInversed) {
          this._calculateForces(distance, dx, dy, node, parentBranch);
        } else {
          // Did not pass the condition, go into children if available
          if (parentBranch.childrenCount === 4) {
            this._getForceContributions(parentBranch, node);
          } else {
            // parentBranch must have only one node, if it was empty we wouldnt be here
            if (parentBranch.children.data.id != node.id) {
              // if it is not self
              this._calculateForces(distance, dx, dy, node, parentBranch);
            }
          }
        }
      }
    }

    /**
     * Calculate the forces based on the distance.
     *
     * @param {number} distance
     * @param {number} dx
     * @param {number} dy
     * @param {Node} node
     * @param {object} parentBranch
     * @private
     */
  }, {
    key: "_calculateForces",
    value: function _calculateForces(distance, dx, dy, node, parentBranch) {
      if (distance === 0) {
        distance = 0.1;
        dx = distance;
      }
      if (this.overlapAvoidanceFactor < 1 && node.shape.radius) {
        distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius);
      }

      // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines
      // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce
      var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / Math.pow(distance, 3);
      var fx = dx * gravityForce;
      var fy = dy * gravityForce;
      this.physicsBody.forces[node.id].x += fx;
      this.physicsBody.forces[node.id].y += fy;
    }

    /**
     * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes.
     *
     * @param {Array.<Node>} nodes
     * @param {Array.<number>} nodeIndices
     * @returns {{root: {centerOfMass: {x: number, y: number}, mass: number, range: {minX: number, maxX: number, minY: number, maxY: number}, size: number, calcSize: number, children: {data: null}, maxWidth: number, level: number, childrenCount: number}}} BarnesHutTree
     * @private
     */
  }, {
    key: "_formBarnesHutTree",
    value: function _formBarnesHutTree(nodes, nodeIndices) {
      var node;
      var nodeCount = nodeIndices.length;
      var minX = nodes[nodeIndices[0]].x;
      var minY = nodes[nodeIndices[0]].y;
      var maxX = nodes[nodeIndices[0]].x;
      var maxY = nodes[nodeIndices[0]].y;

      // get the range of the nodes
      for (var i = 1; i < nodeCount; i++) {
        var _node = nodes[nodeIndices[i]];
        var x = _node.x;
        var y = _node.y;
        if (_node.options.mass > 0) {
          if (x < minX) {
            minX = x;
          }
          if (x > maxX) {
            maxX = x;
          }
          if (y < minY) {
            minY = y;
          }
          if (y > maxY) {
            maxY = y;
          }
        }
      }
      // make the range a square
      var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y
      if (sizeDiff > 0) {
        minY -= 0.5 * sizeDiff;
        maxY += 0.5 * sizeDiff;
      } // xSize > ySize
      else {
        minX += 0.5 * sizeDiff;
        maxX -= 0.5 * sizeDiff;
      } // xSize < ySize

      var minimumTreeSize = 1e-5;
      var rootSize = Math.max(minimumTreeSize, Math.abs(maxX - minX));
      var halfRootSize = 0.5 * rootSize;
      var centerX = 0.5 * (minX + maxX),
        centerY = 0.5 * (minY + maxY);

      // construct the barnesHutTree
      var barnesHutTree = {
        root: {
          centerOfMass: {
            x: 0,
            y: 0
          },
          mass: 0,
          range: {
            minX: centerX - halfRootSize,
            maxX: centerX + halfRootSize,
            minY: centerY - halfRootSize,
            maxY: centerY + halfRootSize
          },
          size: rootSize,
          calcSize: 1 / rootSize,
          children: {
            data: null
          },
          maxWidth: 0,
          level: 0,
          childrenCount: 4
        }
      };
      this._splitBranch(barnesHutTree.root);

      // place the nodes one by one recursively
      for (var _i = 0; _i < nodeCount; _i++) {
        node = nodes[nodeIndices[_i]];
        if (node.options.mass > 0) {
          this._placeInTree(barnesHutTree.root, node);
        }
      }

      // make global
      return barnesHutTree;
    }

    /**
     * this updates the mass of a branch. this is increased by adding a node.
     *
     * @param {object} parentBranch
     * @param {Node} node
     * @private
     */
  }, {
    key: "_updateBranchMass",
    value: function _updateBranchMass(parentBranch, node) {
      var centerOfMass = parentBranch.centerOfMass;
      var totalMass = parentBranch.mass + node.options.mass;
      var totalMassInv = 1 / totalMass;
      centerOfMass.x = centerOfMass.x * parentBranch.mass + node.x * node.options.mass;
      centerOfMass.x *= totalMassInv;
      centerOfMass.y = centerOfMass.y * parentBranch.mass + node.y * node.options.mass;
      centerOfMass.y *= totalMassInv;
      parentBranch.mass = totalMass;
      var biggestSize = Math.max(Math.max(node.height, node.radius), node.width);
      parentBranch.maxWidth = parentBranch.maxWidth < biggestSize ? biggestSize : parentBranch.maxWidth;
    }

    /**
     * determine in which branch the node will be placed.
     *
     * @param {object} parentBranch
     * @param {Node} node
     * @param {boolean} skipMassUpdate
     * @private
     */
  }, {
    key: "_placeInTree",
    value: function _placeInTree(parentBranch, node, skipMassUpdate) {
      if (skipMassUpdate != true || skipMassUpdate === undefined) {
        // update the mass of the branch.
        this._updateBranchMass(parentBranch, node);
      }
      var range = parentBranch.children.NW.range;
      var region;
      if (range.maxX > node.x) {
        // in NW or SW
        if (range.maxY > node.y) {
          region = "NW";
        } else {
          region = "SW";
        }
      } else {
        // in NE or SE
        if (range.maxY > node.y) {
          region = "NE";
        } else {
          region = "SE";
        }
      }
      this._placeInRegion(parentBranch, node, region);
    }

    /**
     * actually place the node in a region (or branch)
     *
     * @param {object} parentBranch
     * @param {Node} node
     * @param {'NW'| 'NE' | 'SW' | 'SE'} region
     * @private
     */
  }, {
    key: "_placeInRegion",
    value: function _placeInRegion(parentBranch, node, region) {
      var children = parentBranch.children[region];
      switch (children.childrenCount) {
        case 0:
          // place node here
          children.children.data = node;
          children.childrenCount = 1;
          this._updateBranchMass(children, node);
          break;
        case 1:
          // convert into children
          // if there are two nodes exactly overlapping (on init, on opening of cluster etc.)
          // we move one node a little bit and we do not put it in the tree.
          if (children.children.data.x === node.x && children.children.data.y === node.y) {
            node.x += this._rng();
            node.y += this._rng();
          } else {
            this._splitBranch(children);
            this._placeInTree(children, node);
          }
          break;
        case 4:
          // place in branch
          this._placeInTree(children, node);
          break;
      }
    }

    /**
     * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch
     * after the split is complete.
     *
     * @param {object} parentBranch
     * @private
     */
  }, {
    key: "_splitBranch",
    value: function _splitBranch(parentBranch) {
      // if the branch is shaded with a node, replace the node in the new subset.
      var containedNode = null;
      if (parentBranch.childrenCount === 1) {
        containedNode = parentBranch.children.data;
        parentBranch.mass = 0;
        parentBranch.centerOfMass.x = 0;
        parentBranch.centerOfMass.y = 0;
      }
      parentBranch.childrenCount = 4;
      parentBranch.children.data = null;
      this._insertRegion(parentBranch, "NW");
      this._insertRegion(parentBranch, "NE");
      this._insertRegion(parentBranch, "SW");
      this._insertRegion(parentBranch, "SE");
      if (containedNode != null) {
        this._placeInTree(parentBranch, containedNode);
      }
    }

    /**
     * This function subdivides the region into four new segments.
     * Specifically, this inserts a single new segment.
     * It fills the children section of the parentBranch
     *
     * @param {object} parentBranch
     * @param {'NW'| 'NE' | 'SW' | 'SE'} region
     * @private
     */
  }, {
    key: "_insertRegion",
    value: function _insertRegion(parentBranch, region) {
      var minX, maxX, minY, maxY;
      var childSize = 0.5 * parentBranch.size;
      switch (region) {
        case "NW":
          minX = parentBranch.range.minX;
          maxX = parentBranch.range.minX + childSize;
          minY = parentBranch.range.minY;
          maxY = parentBranch.range.minY + childSize;
          break;
        case "NE":
          minX = parentBranch.range.minX + childSize;
          maxX = parentBranch.range.maxX;
          minY = parentBranch.range.minY;
          maxY = parentBranch.range.minY + childSize;
          break;
        case "SW":
          minX = parentBranch.range.minX;
          maxX = parentBranch.range.minX + childSize;
          minY = parentBranch.range.minY + childSize;
          maxY = parentBranch.range.maxY;
          break;
        case "SE":
          minX = parentBranch.range.minX + childSize;
          maxX = parentBranch.range.maxX;
          minY = parentBranch.range.minY + childSize;
          maxY = parentBranch.range.maxY;
          break;
      }
      parentBranch.children[region] = {
        centerOfMass: {
          x: 0,
          y: 0
        },
        mass: 0,
        range: {
          minX: minX,
          maxX: maxX,
          minY: minY,
          maxY: maxY
        },
        size: 0.5 * parentBranch.size,
        calcSize: 2 * parentBranch.calcSize,
        children: {
          data: null
        },
        maxWidth: 0,
        level: parentBranch.level + 1,
        childrenCount: 0
      };
    }

    //---------------------------  DEBUGGING BELOW  ---------------------------//

    /**
     * This function is for debugging purposed, it draws the tree.
     *
     * @param {CanvasRenderingContext2D} ctx
     * @param {string} color
     * @private
     */
  }, {
    key: "_debug",
    value: function _debug(ctx, color) {
      if (this.barnesHutTree !== undefined) {
        ctx.lineWidth = 1;
        this._drawBranch(this.barnesHutTree.root, ctx, color);
      }
    }

    /**
     * This function is for debugging purposes. It draws the branches recursively.
     *
     * @param {object} branch
     * @param {CanvasRenderingContext2D} ctx
     * @param {string} color
     * @private
     */
  }, {
    key: "_drawBranch",
    value: function _drawBranch(branch, ctx, color) {
      if (color === undefined) {
        color = "#FF0000";
      }
      if (branch.childrenCount === 4) {
        this._drawBranch(branch.children.NW, ctx);
        this._drawBranch(branch.children.NE, ctx);
        this._drawBranch(branch.children.SE, ctx);
        this._drawBranch(branch.children.SW, ctx);
      }
      ctx.strokeStyle = color;
      ctx.beginPath();
      ctx.moveTo(branch.range.minX, branch.range.minY);
      ctx.lineTo(branch.range.maxX, branch.range.minY);
      ctx.stroke();
      ctx.beginPath();
      ctx.moveTo(branch.range.maxX, branch.range.minY);
      ctx.lineTo(branch.range.maxX, branch.range.maxY);
      ctx.stroke();
      ctx.beginPath();
      ctx.moveTo(branch.range.maxX, branch.range.maxY);
      ctx.lineTo(branch.range.minX, branch.range.maxY);
      ctx.stroke();
      ctx.beginPath();
      ctx.moveTo(branch.range.minX, branch.range.maxY);
      ctx.lineTo(branch.range.minX, branch.range.minY);
      ctx.stroke();

      /*
       if (branch.mass > 0) {
       ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass);
       ctx.stroke();
       }
       */
    }
  }]);
  return BarnesHutSolver;
}();

/**
 * Repulsion Solver
 */
var RepulsionSolver = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function RepulsionSolver(body, physicsBody, options) {
    _classCallCheck(this, RepulsionSolver);
    this._rng = Alea("REPULSION SOLVER");
    this.body = body;
    this.physicsBody = physicsBody;
    this.setOptions(options);
  }

  /**
   *
   * @param {object} options
   */
  _createClass(RepulsionSolver, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
    }

    /**
     * Calculate the forces the nodes apply on each other based on a repulsion field.
     * This field is linearly approximated.
     *
     * @private
     */
  }, {
    key: "solve",
    value: function solve() {
      var dx, dy, distance, fx, fy, repulsingForce, node1, node2;
      var nodes = this.body.nodes;
      var nodeIndices = this.physicsBody.physicsNodeIndices;
      var forces = this.physicsBody.forces;

      // repulsing forces between nodes
      var nodeDistance = this.options.nodeDistance;

      // approximation constants
      var a = -2 / 3 / nodeDistance;
      var b = 4 / 3;

      // we loop from i over all but the last entree in the array
      // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
      for (var i = 0; i < nodeIndices.length - 1; i++) {
        node1 = nodes[nodeIndices[i]];
        for (var j = i + 1; j < nodeIndices.length; j++) {
          node2 = nodes[nodeIndices[j]];
          dx = node2.x - node1.x;
          dy = node2.y - node1.y;
          distance = Math.sqrt(dx * dx + dy * dy);

          // same condition as BarnesHutSolver, making sure nodes are never 100% overlapping.
          if (distance === 0) {
            distance = 0.1 * this._rng();
            dx = distance;
          }
          if (distance < 2 * nodeDistance) {
            if (distance < 0.5 * nodeDistance) {
              repulsingForce = 1.0;
            } else {
              repulsingForce = a * distance + b; // linear approx of  1 / (1 + Math.exp((distance / nodeDistance - 1) * steepness))
            }

            repulsingForce = repulsingForce / distance;
            fx = dx * repulsingForce;
            fy = dy * repulsingForce;
            forces[node1.id].x -= fx;
            forces[node1.id].y -= fy;
            forces[node2.id].x += fx;
            forces[node2.id].y += fy;
          }
        }
      }
    }
  }]);
  return RepulsionSolver;
}();

/**
 * Hierarchical Repulsion Solver
 */
var HierarchicalRepulsionSolver = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function HierarchicalRepulsionSolver(body, physicsBody, options) {
    _classCallCheck(this, HierarchicalRepulsionSolver);
    this.body = body;
    this.physicsBody = physicsBody;
    this.setOptions(options);
  }

  /**
   *
   * @param {object} options
   */
  _createClass(HierarchicalRepulsionSolver, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
      this.overlapAvoidanceFactor = Math.max(0, Math.min(1, this.options.avoidOverlap || 0));
    }

    /**
     * Calculate the forces the nodes apply on each other based on a repulsion field.
     * This field is linearly approximated.
     *
     * @private
     */
  }, {
    key: "solve",
    value: function solve() {
      var nodes = this.body.nodes;
      var nodeIndices = this.physicsBody.physicsNodeIndices;
      var forces = this.physicsBody.forces;

      // repulsing forces between nodes
      var nodeDistance = this.options.nodeDistance;

      // we loop from i over all but the last entree in the array
      // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
      for (var i = 0; i < nodeIndices.length - 1; i++) {
        var node1 = nodes[nodeIndices[i]];
        for (var j = i + 1; j < nodeIndices.length; j++) {
          var node2 = nodes[nodeIndices[j]];

          // nodes only affect nodes on their level
          if (node1.level === node2.level) {
            var theseNodesDistance = nodeDistance + this.overlapAvoidanceFactor * ((node1.shape.radius || 0) / 2 + (node2.shape.radius || 0) / 2);
            var dx = node2.x - node1.x;
            var dy = node2.y - node1.y;
            var distance = Math.sqrt(dx * dx + dy * dy);
            var steepness = 0.05;
            var repulsingForce = void 0;
            if (distance < theseNodesDistance) {
              repulsingForce = -Math.pow(steepness * distance, 2) + Math.pow(steepness * theseNodesDistance, 2);
            } else {
              repulsingForce = 0;
            }
            // normalize force with
            if (distance !== 0) {
              repulsingForce = repulsingForce / distance;
            }
            var fx = dx * repulsingForce;
            var fy = dy * repulsingForce;
            forces[node1.id].x -= fx;
            forces[node1.id].y -= fy;
            forces[node2.id].x += fx;
            forces[node2.id].y += fy;
          }
        }
      }
    }
  }]);
  return HierarchicalRepulsionSolver;
}();

/**
 * Spring Solver
 */
var SpringSolver = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function SpringSolver(body, physicsBody, options) {
    _classCallCheck(this, SpringSolver);
    this.body = body;
    this.physicsBody = physicsBody;
    this.setOptions(options);
  }

  /**
   *
   * @param {object} options
   */
  _createClass(SpringSolver, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
    }

    /**
     * This function calculates the springforces on the nodes, accounting for the support nodes.
     *
     * @private
     */
  }, {
    key: "solve",
    value: function solve() {
      var edgeLength, edge;
      var edgeIndices = this.physicsBody.physicsEdgeIndices;
      var edges = this.body.edges;
      var node1, node2, node3;

      // forces caused by the edges, modelled as springs
      for (var i = 0; i < edgeIndices.length; i++) {
        edge = edges[edgeIndices[i]];
        if (edge.connected === true && edge.toId !== edge.fromId) {
          // only calculate forces if nodes are in the same sector
          if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) {
            if (edge.edgeType.via !== undefined) {
              edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
              node1 = edge.to;
              node2 = edge.edgeType.via;
              node3 = edge.from;
              this._calculateSpringForce(node1, node2, 0.5 * edgeLength);
              this._calculateSpringForce(node2, node3, 0.5 * edgeLength);
            } else {
              // the * 1.5 is here so the edge looks as large as a smooth edge. It does not initially because the smooth edges use
              // the support nodes which exert a repulsive force on the to and from nodes, making the edge appear larger.
              edgeLength = edge.options.length === undefined ? this.options.springLength * 1.5 : edge.options.length;
              this._calculateSpringForce(edge.from, edge.to, edgeLength);
            }
          }
        }
      }
    }

    /**
     * This is the code actually performing the calculation for the function above.
     *
     * @param {Node} node1
     * @param {Node} node2
     * @param {number} edgeLength
     * @private
     */
  }, {
    key: "_calculateSpringForce",
    value: function _calculateSpringForce(node1, node2, edgeLength) {
      var dx = node1.x - node2.x;
      var dy = node1.y - node2.y;
      var distance = Math.max(Math.sqrt(dx * dx + dy * dy), 0.01);

      // the 1/distance is so the fx and fy can be calculated without sine or cosine.
      var springForce = this.options.springConstant * (edgeLength - distance) / distance;
      var fx = dx * springForce;
      var fy = dy * springForce;

      // handle the case where one node is not part of the physcis
      if (this.physicsBody.forces[node1.id] !== undefined) {
        this.physicsBody.forces[node1.id].x += fx;
        this.physicsBody.forces[node1.id].y += fy;
      }
      if (this.physicsBody.forces[node2.id] !== undefined) {
        this.physicsBody.forces[node2.id].x -= fx;
        this.physicsBody.forces[node2.id].y -= fy;
      }
    }
  }]);
  return SpringSolver;
}();

/**
 * Hierarchical Spring Solver
 */
var HierarchicalSpringSolver = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function HierarchicalSpringSolver(body, physicsBody, options) {
    _classCallCheck(this, HierarchicalSpringSolver);
    this.body = body;
    this.physicsBody = physicsBody;
    this.setOptions(options);
  }

  /**
   *
   * @param {object} options
   */
  _createClass(HierarchicalSpringSolver, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
    }

    /**
     * This function calculates the springforces on the nodes, accounting for the support nodes.
     *
     * @private
     */
  }, {
    key: "solve",
    value: function solve() {
      var edgeLength, edge;
      var dx, dy, fx, fy, springForce, distance;
      var edges = this.body.edges;
      var factor = 0.5;
      var edgeIndices = this.physicsBody.physicsEdgeIndices;
      var nodeIndices = this.physicsBody.physicsNodeIndices;
      var forces = this.physicsBody.forces;

      // initialize the spring force counters
      for (var i = 0; i < nodeIndices.length; i++) {
        var nodeId = nodeIndices[i];
        forces[nodeId].springFx = 0;
        forces[nodeId].springFy = 0;
      }

      // forces caused by the edges, modelled as springs
      for (var _i = 0; _i < edgeIndices.length; _i++) {
        edge = edges[edgeIndices[_i]];
        if (edge.connected === true) {
          edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
          dx = edge.from.x - edge.to.x;
          dy = edge.from.y - edge.to.y;
          distance = Math.sqrt(dx * dx + dy * dy);
          distance = distance === 0 ? 0.01 : distance;

          // the 1/distance is so the fx and fy can be calculated without sine or cosine.
          springForce = this.options.springConstant * (edgeLength - distance) / distance;
          fx = dx * springForce;
          fy = dy * springForce;
          if (edge.to.level != edge.from.level) {
            if (forces[edge.toId] !== undefined) {
              forces[edge.toId].springFx -= fx;
              forces[edge.toId].springFy -= fy;
            }
            if (forces[edge.fromId] !== undefined) {
              forces[edge.fromId].springFx += fx;
              forces[edge.fromId].springFy += fy;
            }
          } else {
            if (forces[edge.toId] !== undefined) {
              forces[edge.toId].x -= factor * fx;
              forces[edge.toId].y -= factor * fy;
            }
            if (forces[edge.fromId] !== undefined) {
              forces[edge.fromId].x += factor * fx;
              forces[edge.fromId].y += factor * fy;
            }
          }
        }
      }

      // normalize spring forces
      springForce = 1;
      var springFx, springFy;
      for (var _i2 = 0; _i2 < nodeIndices.length; _i2++) {
        var _nodeId = nodeIndices[_i2];
        springFx = Math.min(springForce, Math.max(-springForce, forces[_nodeId].springFx));
        springFy = Math.min(springForce, Math.max(-springForce, forces[_nodeId].springFy));
        forces[_nodeId].x += springFx;
        forces[_nodeId].y += springFy;
      }

      // retain energy balance
      var totalFx = 0;
      var totalFy = 0;
      for (var _i3 = 0; _i3 < nodeIndices.length; _i3++) {
        var _nodeId2 = nodeIndices[_i3];
        totalFx += forces[_nodeId2].x;
        totalFy += forces[_nodeId2].y;
      }
      var correctionFx = totalFx / nodeIndices.length;
      var correctionFy = totalFy / nodeIndices.length;
      for (var _i4 = 0; _i4 < nodeIndices.length; _i4++) {
        var _nodeId3 = nodeIndices[_i4];
        forces[_nodeId3].x -= correctionFx;
        forces[_nodeId3].y -= correctionFy;
      }
    }
  }]);
  return HierarchicalSpringSolver;
}();

/**
 * Central Gravity Solver
 */
var CentralGravitySolver = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function CentralGravitySolver(body, physicsBody, options) {
    _classCallCheck(this, CentralGravitySolver);
    this.body = body;
    this.physicsBody = physicsBody;
    this.setOptions(options);
  }

  /**
   *
   * @param {object} options
   */
  _createClass(CentralGravitySolver, [{
    key: "setOptions",
    value: function setOptions(options) {
      this.options = options;
    }

    /**
     * Calculates forces for each node
     */
  }, {
    key: "solve",
    value: function solve() {
      var dx, dy, distance, node;
      var nodes = this.body.nodes;
      var nodeIndices = this.physicsBody.physicsNodeIndices;
      var forces = this.physicsBody.forces;
      for (var i = 0; i < nodeIndices.length; i++) {
        var nodeId = nodeIndices[i];
        node = nodes[nodeId];
        dx = -node.x;
        dy = -node.y;
        distance = Math.sqrt(dx * dx + dy * dy);
        this._calculateForces(distance, dx, dy, forces, node);
      }
    }

    /**
     * Calculate the forces based on the distance.
     *
     * @param {number} distance
     * @param {number} dx
     * @param {number} dy
     * @param {Object<Node.id, vis.Node>} forces
     * @param {Node} node
     * @private
     */
  }, {
    key: "_calculateForces",
    value: function _calculateForces(distance, dx, dy, forces, node) {
      var gravityForce = distance === 0 ? 0 : this.options.centralGravity / distance;
      forces[node.id].x = dx * gravityForce;
      forces[node.id].y = dy * gravityForce;
    }
  }]);
  return CentralGravitySolver;
}();

function _createSuper$3(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$3(); 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 _isNativeReflectConstruct$3() { 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; } }

/**
 * @augments BarnesHutSolver
 */
var ForceAtlas2BasedRepulsionSolver = /*#__PURE__*/function (_BarnesHutSolver) {
  _inherits(ForceAtlas2BasedRepulsionSolver, _BarnesHutSolver);
  var _super = _createSuper$3(ForceAtlas2BasedRepulsionSolver);
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function ForceAtlas2BasedRepulsionSolver(body, physicsBody, options) {
    var _this;
    _classCallCheck(this, ForceAtlas2BasedRepulsionSolver);
    _this = _super.call(this, body, physicsBody, options);
    _this._rng = Alea("FORCE ATLAS 2 BASED REPULSION SOLVER");
    return _this;
  }

  /**
   * Calculate the forces based on the distance.
   *
   * @param {number} distance
   * @param {number} dx
   * @param {number} dy
   * @param {Node} node
   * @param {object} parentBranch
   * @private
   */
  _createClass(ForceAtlas2BasedRepulsionSolver, [{
    key: "_calculateForces",
    value: function _calculateForces(distance, dx, dy, node, parentBranch) {
      if (distance === 0) {
        distance = 0.1 * this._rng();
        dx = distance;
      }
      if (this.overlapAvoidanceFactor < 1 && node.shape.radius) {
        distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius);
      }
      var degree = node.edges.length + 1;
      // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines
      // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce
      var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass * degree / Math.pow(distance, 2);
      var fx = dx * gravityForce;
      var fy = dy * gravityForce;
      this.physicsBody.forces[node.id].x += fx;
      this.physicsBody.forces[node.id].y += fy;
    }
  }]);
  return ForceAtlas2BasedRepulsionSolver;
}(BarnesHutSolver);

function _createSuper$2(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$2(); 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 _isNativeReflectConstruct$2() { 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; } }

/**
 * @augments CentralGravitySolver
 */
var ForceAtlas2BasedCentralGravitySolver = /*#__PURE__*/function (_CentralGravitySolver) {
  _inherits(ForceAtlas2BasedCentralGravitySolver, _CentralGravitySolver);
  var _super = _createSuper$2(ForceAtlas2BasedCentralGravitySolver);
  /**
   * @param {object} body
   * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
   * @param {object} options
   */
  function ForceAtlas2BasedCentralGravitySolver(body, physicsBody, options) {
    _classCallCheck(this, ForceAtlas2BasedCentralGravitySolver);
    return _super.call(this, body, physicsBody, options);
  }

  /**
   * Calculate the forces based on the distance.
   *
   * @param {number} distance
   * @param {number} dx
   * @param {number} dy
   * @param {Object<Node.id, Node>} forces
   * @param {Node} node
   * @private
   */
  _createClass(ForceAtlas2BasedCentralGravitySolver, [{
    key: "_calculateForces",
    value: function _calculateForces(distance, dx, dy, forces, node) {
      if (distance > 0) {
        var degree = node.edges.length + 1;
        var gravityForce = this.options.centralGravity * degree * node.options.mass;
        forces[node.id].x = dx * gravityForce;
        forces[node.id].y = dy * gravityForce;
      }
    }
  }]);
  return ForceAtlas2BasedCentralGravitySolver;
}(CentralGravitySolver);

/**
 * The physics engine
 */
var PhysicsEngine = /*#__PURE__*/function () {
  /**
   * @param {object} body
   */
  function PhysicsEngine(body) {
    _classCallCheck(this, PhysicsEngine);
    this.body = body;
    this.physicsBody = {
      physicsNodeIndices: [],
      physicsEdgeIndices: [],
      forces: {},
      velocities: {}
    };
    this.physicsEnabled = true;
    this.simulationInterval = 1000 / 60;
    this.requiresTimeout = true;
    this.previousStates = {};
    this.referenceState = {};
    this.freezeCache = {};
    this.renderTimer = undefined;

    // parameters for the adaptive timestep
    this.adaptiveTimestep = false;
    this.adaptiveTimestepEnabled = false;
    this.adaptiveCounter = 0;
    this.adaptiveInterval = 3;
    this.stabilized = false;
    this.startedStabilization = false;
    this.stabilizationIterations = 0;
    this.ready = false; // will be set to true if the stabilize

    // default options
    this.options = {};
    this.defaultOptions = {
      enabled: true,
      barnesHut: {
        theta: 0.5,
        gravitationalConstant: -2000,
        centralGravity: 0.3,
        springLength: 95,
        springConstant: 0.04,
        damping: 0.09,
        avoidOverlap: 0
      },
      forceAtlas2Based: {
        theta: 0.5,
        gravitationalConstant: -50,
        centralGravity: 0.01,
        springConstant: 0.08,
        springLength: 100,
        damping: 0.4,
        avoidOverlap: 0
      },
      repulsion: {
        centralGravity: 0.2,
        springLength: 200,
        springConstant: 0.05,
        nodeDistance: 100,
        damping: 0.09,
        avoidOverlap: 0
      },
      hierarchicalRepulsion: {
        centralGravity: 0.0,
        springLength: 100,
        springConstant: 0.01,
        nodeDistance: 120,
        damping: 0.09
      },
      maxVelocity: 50,
      minVelocity: 0.75,
      // px/s
      solver: "barnesHut",
      stabilization: {
        enabled: true,
        iterations: 1000,
        // maximum number of iteration to stabilize
        updateInterval: 50,
        onlyDynamicEdges: false,
        fit: true
      },
      timestep: 0.5,
      adaptiveTimestep: true,
      wind: {
        x: 0,
        y: 0
      }
    };
    _Object$assign(this.options, this.defaultOptions);
    this.timestep = 0.5;
    this.layoutFailed = false;
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(PhysicsEngine, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _this = this;
      this.body.emitter.on("initPhysics", function () {
        _this.initPhysics();
      });
      this.body.emitter.on("_layoutFailed", function () {
        _this.layoutFailed = true;
      });
      this.body.emitter.on("resetPhysics", function () {
        _this.stopSimulation();
        _this.ready = false;
      });
      this.body.emitter.on("disablePhysics", function () {
        _this.physicsEnabled = false;
        _this.stopSimulation();
      });
      this.body.emitter.on("restorePhysics", function () {
        _this.setOptions(_this.options);
        if (_this.ready === true) {
          _this.startSimulation();
        }
      });
      this.body.emitter.on("startSimulation", function () {
        if (_this.ready === true) {
          _this.startSimulation();
        }
      });
      this.body.emitter.on("stopSimulation", function () {
        _this.stopSimulation();
      });
      this.body.emitter.on("destroy", function () {
        _this.stopSimulation(false);
        _this.body.emitter.off();
      });
      this.body.emitter.on("_dataChanged", function () {
        // Nodes and/or edges have been added or removed, update shortcut lists.
        _this.updatePhysicsData();
      });

      // debug: show forces
      // this.body.emitter.on("afterDrawing", (ctx) => {this._drawForces(ctx);});
    }

    /**
     * set the physics options
     *
     * @param {object} options
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        if (options === false) {
          this.options.enabled = false;
          this.physicsEnabled = false;
          this.stopSimulation();
        } else if (options === true) {
          this.options.enabled = true;
          this.physicsEnabled = true;
          this.startSimulation();
        } else {
          this.physicsEnabled = true;
          selectiveNotDeepExtend(["stabilization"], this.options, options);
          mergeOptions(this.options, options, "stabilization");
          if (options.enabled === undefined) {
            this.options.enabled = true;
          }
          if (this.options.enabled === false) {
            this.physicsEnabled = false;
            this.stopSimulation();
          }
          var wind = this.options.wind;
          if (wind) {
            if (typeof wind.x !== "number" || _Number$isNaN(wind.x)) {
              wind.x = 0;
            }
            if (typeof wind.y !== "number" || _Number$isNaN(wind.y)) {
              wind.y = 0;
            }
          }

          // set the timestep
          this.timestep = this.options.timestep;
        }
      }
      this.init();
    }

    /**
     * configure the engine.
     */
  }, {
    key: "init",
    value: function init() {
      var options;
      if (this.options.solver === "forceAtlas2Based") {
        options = this.options.forceAtlas2Based;
        this.nodesSolver = new ForceAtlas2BasedRepulsionSolver(this.body, this.physicsBody, options);
        this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options);
        this.gravitySolver = new ForceAtlas2BasedCentralGravitySolver(this.body, this.physicsBody, options);
      } else if (this.options.solver === "repulsion") {
        options = this.options.repulsion;
        this.nodesSolver = new RepulsionSolver(this.body, this.physicsBody, options);
        this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options);
        this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options);
      } else if (this.options.solver === "hierarchicalRepulsion") {
        options = this.options.hierarchicalRepulsion;
        this.nodesSolver = new HierarchicalRepulsionSolver(this.body, this.physicsBody, options);
        this.edgesSolver = new HierarchicalSpringSolver(this.body, this.physicsBody, options);
        this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options);
      } else {
        // barnesHut
        options = this.options.barnesHut;
        this.nodesSolver = new BarnesHutSolver(this.body, this.physicsBody, options);
        this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options);
        this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options);
      }
      this.modelOptions = options;
    }

    /**
     * initialize the engine
     */
  }, {
    key: "initPhysics",
    value: function initPhysics() {
      if (this.physicsEnabled === true && this.options.enabled === true) {
        if (this.options.stabilization.enabled === true) {
          this.stabilize();
        } else {
          this.stabilized = false;
          this.ready = true;
          this.body.emitter.emit("fit", {}, this.layoutFailed); // if the layout failed, we use the approximation for the zoom
          this.startSimulation();
        }
      } else {
        this.ready = true;
        this.body.emitter.emit("fit");
      }
    }

    /**
     * Start the simulation
     */
  }, {
    key: "startSimulation",
    value: function startSimulation() {
      if (this.physicsEnabled === true && this.options.enabled === true) {
        this.stabilized = false;

        // when visible, adaptivity is disabled.
        this.adaptiveTimestep = false;

        // this sets the width of all nodes initially which could be required for the avoidOverlap
        this.body.emitter.emit("_resizeNodes");
        if (this.viewFunction === undefined) {
          var _context;
          this.viewFunction = _bindInstanceProperty$1(_context = this.simulationStep).call(_context, this);
          this.body.emitter.on("initRedraw", this.viewFunction);
          this.body.emitter.emit("_startRendering");
        }
      } else {
        this.body.emitter.emit("_redraw");
      }
    }

    /**
     * Stop the simulation, force stabilization.
     *
     * @param {boolean} [emit=true]
     */
  }, {
    key: "stopSimulation",
    value: function stopSimulation() {
      var emit = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
      this.stabilized = true;
      if (emit === true) {
        this._emitStabilized();
      }
      if (this.viewFunction !== undefined) {
        this.body.emitter.off("initRedraw", this.viewFunction);
        this.viewFunction = undefined;
        if (emit === true) {
          this.body.emitter.emit("_stopRendering");
        }
      }
    }

    /**
     * The viewFunction inserts this step into each render loop. It calls the physics tick and handles the cleanup at stabilized.
     *
     */
  }, {
    key: "simulationStep",
    value: function simulationStep() {
      // check if the physics have settled
      var startTime = _Date$now();
      this.physicsTick();
      var physicsTime = _Date$now() - startTime;

      // run double speed if it is a little graph
      if ((physicsTime < 0.4 * this.simulationInterval || this.runDoubleSpeed === true) && this.stabilized === false) {
        this.physicsTick();

        // this makes sure there is no jitter. The decision is taken once to run it at double speed.
        this.runDoubleSpeed = true;
      }
      if (this.stabilized === true) {
        this.stopSimulation();
      }
    }

    /**
     * trigger the stabilized event.
     *
     * @param {number} [amountOfIterations=this.stabilizationIterations]
     * @private
     */
  }, {
    key: "_emitStabilized",
    value: function _emitStabilized() {
      var _this2 = this;
      var amountOfIterations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.stabilizationIterations;
      if (this.stabilizationIterations > 1 || this.startedStabilization === true) {
        _setTimeout(function () {
          _this2.body.emitter.emit("stabilized", {
            iterations: amountOfIterations
          });
          _this2.startedStabilization = false;
          _this2.stabilizationIterations = 0;
        }, 0);
      }
    }

    /**
     * Calculate the forces for one physics iteration and move the nodes.
     *
     * @private
     */
  }, {
    key: "physicsStep",
    value: function physicsStep() {
      this.gravitySolver.solve();
      this.nodesSolver.solve();
      this.edgesSolver.solve();
      this.moveNodes();
    }

    /**
     * Make dynamic adjustments to the timestep, based on current state.
     *
     * Helper function for physicsTick().
     *
     * @private
     */
  }, {
    key: "adjustTimeStep",
    value: function adjustTimeStep() {
      var factor = 1.2; // Factor for increasing the timestep on success.

      // we compare the two steps. if it is acceptable we double the step.
      if (this._evaluateStepQuality() === true) {
        this.timestep = factor * this.timestep;
      } else {
        // if not, we decrease the step to a minimum of the options timestep.
        // if the decreased timestep is smaller than the options step, we do not reset the counter
        // we assume that the options timestep is stable enough.
        if (this.timestep / factor < this.options.timestep) {
          this.timestep = this.options.timestep;
        } else {
          // if the timestep was larger than 2 times the option one we check the adaptivity again to ensure
          // that large instabilities do not form.
          this.adaptiveCounter = -1; // check again next iteration
          this.timestep = Math.max(this.options.timestep, this.timestep / factor);
        }
      }
    }

    /**
     * A single simulation step (or 'tick') in the physics simulation
     *
     * @private
     */
  }, {
    key: "physicsTick",
    value: function physicsTick() {
      this._startStabilizing(); // this ensures that there is no start event when the network is already stable.
      if (this.stabilized === true) return;

      // adaptivity means the timestep adapts to the situation, only applicable for stabilization
      if (this.adaptiveTimestep === true && this.adaptiveTimestepEnabled === true) {
        // timestep remains stable for "interval" iterations.
        var doAdaptive = this.adaptiveCounter % this.adaptiveInterval === 0;
        if (doAdaptive) {
          // first the big step and revert.
          this.timestep = 2 * this.timestep;
          this.physicsStep();
          this.revert(); // saves the reference state

          // now the normal step. Since this is the last step, it is the more stable one and we will take this.
          this.timestep = 0.5 * this.timestep;

          // since it's half the step, we do it twice.
          this.physicsStep();
          this.physicsStep();
          this.adjustTimeStep();
        } else {
          this.physicsStep(); // normal step, keeping timestep constant
        }

        this.adaptiveCounter += 1;
      } else {
        // case for the static timestep, we reset it to the one in options and take a normal step.
        this.timestep = this.options.timestep;
        this.physicsStep();
      }
      if (this.stabilized === true) this.revert();
      this.stabilizationIterations++;
    }

    /**
     * Nodes and edges can have the physics toggles on or off. A collection of indices is created here so we can skip the check all the time.
     *
     * @private
     */
  }, {
    key: "updatePhysicsData",
    value: function updatePhysicsData() {
      this.physicsBody.forces = {};
      this.physicsBody.physicsNodeIndices = [];
      this.physicsBody.physicsEdgeIndices = [];
      var nodes = this.body.nodes;
      var edges = this.body.edges;

      // get node indices for physics
      for (var nodeId in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
          if (nodes[nodeId].options.physics === true) {
            this.physicsBody.physicsNodeIndices.push(nodes[nodeId].id);
          }
        }
      }

      // get edge indices for physics
      for (var edgeId in edges) {
        if (Object.prototype.hasOwnProperty.call(edges, edgeId)) {
          if (edges[edgeId].options.physics === true) {
            this.physicsBody.physicsEdgeIndices.push(edges[edgeId].id);
          }
        }
      }

      // get the velocity and the forces vector
      for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) {
        var _nodeId = this.physicsBody.physicsNodeIndices[i];
        this.physicsBody.forces[_nodeId] = {
          x: 0,
          y: 0
        };

        // forces can be reset because they are recalculated. Velocities have to persist.
        if (this.physicsBody.velocities[_nodeId] === undefined) {
          this.physicsBody.velocities[_nodeId] = {
            x: 0,
            y: 0
          };
        }
      }

      // clean deleted nodes from the velocity vector
      for (var _nodeId2 in this.physicsBody.velocities) {
        if (nodes[_nodeId2] === undefined) {
          delete this.physicsBody.velocities[_nodeId2];
        }
      }
    }

    /**
     * Revert the simulation one step. This is done so after stabilization, every new start of the simulation will also say stabilized.
     */
  }, {
    key: "revert",
    value: function revert() {
      var nodeIds = _Object$keys(this.previousStates);
      var nodes = this.body.nodes;
      var velocities = this.physicsBody.velocities;
      this.referenceState = {};
      for (var i = 0; i < nodeIds.length; i++) {
        var nodeId = nodeIds[i];
        if (nodes[nodeId] !== undefined) {
          if (nodes[nodeId].options.physics === true) {
            this.referenceState[nodeId] = {
              positions: {
                x: nodes[nodeId].x,
                y: nodes[nodeId].y
              }
            };
            velocities[nodeId].x = this.previousStates[nodeId].vx;
            velocities[nodeId].y = this.previousStates[nodeId].vy;
            nodes[nodeId].x = this.previousStates[nodeId].x;
            nodes[nodeId].y = this.previousStates[nodeId].y;
          }
        } else {
          delete this.previousStates[nodeId];
        }
      }
    }

    /**
     * This compares the reference state to the current state
     *
     * @returns {boolean}
     * @private
     */
  }, {
    key: "_evaluateStepQuality",
    value: function _evaluateStepQuality() {
      var dx, dy, dpos;
      var nodes = this.body.nodes;
      var reference = this.referenceState;
      var posThreshold = 0.3;
      for (var nodeId in this.referenceState) {
        if (Object.prototype.hasOwnProperty.call(this.referenceState, nodeId) && nodes[nodeId] !== undefined) {
          dx = nodes[nodeId].x - reference[nodeId].positions.x;
          dy = nodes[nodeId].y - reference[nodeId].positions.y;
          dpos = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
          if (dpos > posThreshold) {
            return false;
          }
        }
      }
      return true;
    }

    /**
     * move the nodes one timestep and check if they are stabilized
     */
  }, {
    key: "moveNodes",
    value: function moveNodes() {
      var nodeIndices = this.physicsBody.physicsNodeIndices;
      var maxNodeVelocity = 0;
      var averageNodeVelocity = 0;

      // the velocity threshold (energy in the system) for the adaptivity toggle
      var velocityAdaptiveThreshold = 5;
      for (var i = 0; i < nodeIndices.length; i++) {
        var nodeId = nodeIndices[i];
        var nodeVelocity = this._performStep(nodeId);
        // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized
        maxNodeVelocity = Math.max(maxNodeVelocity, nodeVelocity);
        averageNodeVelocity += nodeVelocity;
      }

      // evaluating the stabilized and adaptiveTimestepEnabled conditions
      this.adaptiveTimestepEnabled = averageNodeVelocity / nodeIndices.length < velocityAdaptiveThreshold;
      this.stabilized = maxNodeVelocity < this.options.minVelocity;
    }

    /**
     * Calculate new velocity for a coordinate direction
     *
     * @param {number} v  velocity for current coordinate
     * @param {number} f  regular force for current coordinate
     * @param {number} m  mass of current node
     * @returns {number} new velocity for current coordinate
     * @private
     */
  }, {
    key: "calculateComponentVelocity",
    value: function calculateComponentVelocity(v, f, m) {
      var df = this.modelOptions.damping * v; // damping force
      var a = (f - df) / m; // acceleration

      v += a * this.timestep;

      // Put a limit on the velocities if it is really high
      var maxV = this.options.maxVelocity || 1e9;
      if (Math.abs(v) > maxV) {
        v = v > 0 ? maxV : -maxV;
      }
      return v;
    }

    /**
     * Perform the actual step
     *
     * @param {Node.id} nodeId
     * @returns {number} the new velocity of given node
     * @private
     */
  }, {
    key: "_performStep",
    value: function _performStep(nodeId) {
      var node = this.body.nodes[nodeId];
      var force = this.physicsBody.forces[nodeId];
      if (this.options.wind) {
        force.x += this.options.wind.x;
        force.y += this.options.wind.y;
      }
      var velocity = this.physicsBody.velocities[nodeId];

      // store the state so we can revert
      this.previousStates[nodeId] = {
        x: node.x,
        y: node.y,
        vx: velocity.x,
        vy: velocity.y
      };
      if (node.options.fixed.x === false) {
        velocity.x = this.calculateComponentVelocity(velocity.x, force.x, node.options.mass);
        node.x += velocity.x * this.timestep;
      } else {
        force.x = 0;
        velocity.x = 0;
      }
      if (node.options.fixed.y === false) {
        velocity.y = this.calculateComponentVelocity(velocity.y, force.y, node.options.mass);
        node.y += velocity.y * this.timestep;
      } else {
        force.y = 0;
        velocity.y = 0;
      }
      var totalVelocity = Math.sqrt(Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2));
      return totalVelocity;
    }

    /**
     * When initializing and stabilizing, we can freeze nodes with a predefined position.
     * This greatly speeds up stabilization because only the supportnodes for the smoothCurves have to settle.
     *
     * @private
     */
  }, {
    key: "_freezeNodes",
    value: function _freezeNodes() {
      var nodes = this.body.nodes;
      for (var id in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, id)) {
          if (nodes[id].x && nodes[id].y) {
            var fixed = nodes[id].options.fixed;
            this.freezeCache[id] = {
              x: fixed.x,
              y: fixed.y
            };
            fixed.x = true;
            fixed.y = true;
          }
        }
      }
    }

    /**
     * Unfreezes the nodes that have been frozen by _freezeDefinedNodes.
     *
     * @private
     */
  }, {
    key: "_restoreFrozenNodes",
    value: function _restoreFrozenNodes() {
      var nodes = this.body.nodes;
      for (var id in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, id)) {
          if (this.freezeCache[id] !== undefined) {
            nodes[id].options.fixed.x = this.freezeCache[id].x;
            nodes[id].options.fixed.y = this.freezeCache[id].y;
          }
        }
      }
      this.freezeCache = {};
    }

    /**
     * Find a stable position for all nodes
     *
     * @param {number} [iterations=this.options.stabilization.iterations]
     */
  }, {
    key: "stabilize",
    value: function stabilize() {
      var _this3 = this;
      var iterations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.stabilization.iterations;
      if (typeof iterations !== "number") {
        iterations = this.options.stabilization.iterations;
        console.error("The stabilize method needs a numeric amount of iterations. Switching to default: ", iterations);
      }
      if (this.physicsBody.physicsNodeIndices.length === 0) {
        this.ready = true;
        return;
      }

      // enable adaptive timesteps
      this.adaptiveTimestep = this.options.adaptiveTimestep;

      // this sets the width of all nodes initially which could be required for the avoidOverlap
      this.body.emitter.emit("_resizeNodes");
      this.stopSimulation(); // stop the render loop
      this.stabilized = false;

      // block redraw requests
      this.body.emitter.emit("_blockRedraw");
      this.targetIterations = iterations;

      // start the stabilization
      if (this.options.stabilization.onlyDynamicEdges === true) {
        this._freezeNodes();
      }
      this.stabilizationIterations = 0;
      _setTimeout(function () {
        return _this3._stabilizationBatch();
      }, 0);
    }

    /**
     * If not already stabilizing, start it and emit a start event.
     *
     * @returns {boolean} true if stabilization started with this call
     * @private
     */
  }, {
    key: "_startStabilizing",
    value: function _startStabilizing() {
      if (this.startedStabilization === true) return false;
      this.body.emitter.emit("startStabilizing");
      this.startedStabilization = true;
      return true;
    }

    /**
     * One batch of stabilization
     *
     * @private
     */
  }, {
    key: "_stabilizationBatch",
    value: function _stabilizationBatch() {
      var _this4 = this;
      var running = function running() {
        return _this4.stabilized === false && _this4.stabilizationIterations < _this4.targetIterations;
      };
      var sendProgress = function sendProgress() {
        _this4.body.emitter.emit("stabilizationProgress", {
          iterations: _this4.stabilizationIterations,
          total: _this4.targetIterations
        });
      };
      if (this._startStabilizing()) {
        sendProgress(); // Ensure that there is at least one start event.
      }

      var count = 0;
      while (running() && count < this.options.stabilization.updateInterval) {
        this.physicsTick();
        count++;
      }
      sendProgress();
      if (running()) {
        var _context2;
        _setTimeout(_bindInstanceProperty$1(_context2 = this._stabilizationBatch).call(_context2, this), 0);
      } else {
        this._finalizeStabilization();
      }
    }

    /**
     * Wrap up the stabilization, fit and emit the events.
     *
     * @private
     */
  }, {
    key: "_finalizeStabilization",
    value: function _finalizeStabilization() {
      this.body.emitter.emit("_allowRedraw");
      if (this.options.stabilization.fit === true) {
        this.body.emitter.emit("fit");
      }
      if (this.options.stabilization.onlyDynamicEdges === true) {
        this._restoreFrozenNodes();
      }
      this.body.emitter.emit("stabilizationIterationsDone");
      this.body.emitter.emit("_requestRedraw");
      if (this.stabilized === true) {
        this._emitStabilized();
      } else {
        this.startSimulation();
      }
      this.ready = true;
    }

    //---------------------------  DEBUGGING BELOW  ---------------------------//

    /**
     * Debug function that display arrows for the forces currently active in the network.
     *
     * Use this when debugging only.
     *
     * @param {CanvasRenderingContext2D} ctx
     * @private
     */
  }, {
    key: "_drawForces",
    value: function _drawForces(ctx) {
      for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) {
        var index = this.physicsBody.physicsNodeIndices[i];
        var node = this.body.nodes[index];
        var force = this.physicsBody.forces[index];
        var factor = 20;
        var colorFactor = 0.03;
        var forceSize = Math.sqrt(Math.pow(force.x, 2) + Math.pow(force.x, 2));
        var size = Math.min(Math.max(5, forceSize), 15);
        var arrowSize = 3 * size;
        var color = HSVToHex((180 - Math.min(1, Math.max(0, colorFactor * forceSize)) * 180) / 360, 1, 1);
        var point = {
          x: node.x + factor * force.x,
          y: node.y + factor * force.y
        };
        ctx.lineWidth = size;
        ctx.strokeStyle = color;
        ctx.beginPath();
        ctx.moveTo(node.x, node.y);
        ctx.lineTo(point.x, point.y);
        ctx.stroke();
        var angle = Math.atan2(force.y, force.x);
        ctx.fillStyle = color;
        EndPoints.draw(ctx, {
          type: "arrow",
          point: point,
          angle: angle,
          length: arrowSize
        });
        _fillInstanceProperty(ctx).call(ctx);
      }
    }
  }]);
  return PhysicsEngine;
}();

// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
let getRandomValues;
const rnds8 = new Uint8Array(16);
function rng() {
  // lazy load so that environments that need to polyfill have a chance to do so
  if (!getRandomValues) {
    // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
    getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);

    if (!getRandomValues) {
      throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
    }
  }

  return getRandomValues(rnds8);
}

/**
 * Convert array of 16 byte values to UUID string format of the form:
 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 */

const byteToHex = [];

for (let i = 0; i < 256; ++i) {
  byteToHex.push((i + 0x100).toString(16).slice(1));
}

function unsafeStringify(arr, offset = 0) {
  // Note: Be careful editing this code!  It's been tuned for performance
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
  return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
}

const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
var native = {
  randomUUID
};

function v4(options, buf, offset) {
  if (native.randomUUID && !buf && !options) {
    return native.randomUUID();
  }

  options = options || {};
  const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`

  rnds[6] = rnds[6] & 0x0f | 0x40;
  rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided

  if (buf) {
    offset = offset || 0;

    for (let i = 0; i < 16; ++i) {
      buf[offset + i] = rnds[i];
    }

    return buf;
  }

  return unsafeStringify(rnds);
}

/**
 * Utility Class
 */
var NetworkUtil = /*#__PURE__*/function () {
  /**
   * @ignore
   */
  function NetworkUtil() {
    _classCallCheck(this, NetworkUtil);
  }

  /**
   * Find the center position of the network considering the bounding boxes
   *
   * @param {Array.<Node>} allNodes
   * @param {Array.<Node>} [specificNodes=[]]
   * @returns {{minX: number, maxX: number, minY: number, maxY: number}}
   * @static
   */
  _createClass(NetworkUtil, null, [{
    key: "getRange",
    value: function getRange(allNodes) {
      var specificNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
      var minY = 1e9,
        maxY = -1e9,
        minX = 1e9,
        maxX = -1e9,
        node;
      if (specificNodes.length > 0) {
        for (var i = 0; i < specificNodes.length; i++) {
          node = allNodes[specificNodes[i]];
          if (minX > node.shape.boundingBox.left) {
            minX = node.shape.boundingBox.left;
          }
          if (maxX < node.shape.boundingBox.right) {
            maxX = node.shape.boundingBox.right;
          }
          if (minY > node.shape.boundingBox.top) {
            minY = node.shape.boundingBox.top;
          } // top is negative, bottom is positive
          if (maxY < node.shape.boundingBox.bottom) {
            maxY = node.shape.boundingBox.bottom;
          } // top is negative, bottom is positive
        }
      }

      if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) {
        minY = 0, maxY = 0, minX = 0, maxX = 0;
      }
      return {
        minX: minX,
        maxX: maxX,
        minY: minY,
        maxY: maxY
      };
    }

    /**
     * Find the center position of the network
     *
     * @param {Array.<Node>} allNodes
     * @param {Array.<Node>} [specificNodes=[]]
     * @returns {{minX: number, maxX: number, minY: number, maxY: number}}
     * @static
     */
  }, {
    key: "getRangeCore",
    value: function getRangeCore(allNodes) {
      var specificNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
      var minY = 1e9,
        maxY = -1e9,
        minX = 1e9,
        maxX = -1e9,
        node;
      if (specificNodes.length > 0) {
        for (var i = 0; i < specificNodes.length; i++) {
          node = allNodes[specificNodes[i]];
          if (minX > node.x) {
            minX = node.x;
          }
          if (maxX < node.x) {
            maxX = node.x;
          }
          if (minY > node.y) {
            minY = node.y;
          } // top is negative, bottom is positive
          if (maxY < node.y) {
            maxY = node.y;
          } // top is negative, bottom is positive
        }
      }

      if (minX === 1e9 && maxX === -1e9 && minY === 1e9 && maxY === -1e9) {
        minY = 0, maxY = 0, minX = 0, maxX = 0;
      }
      return {
        minX: minX,
        maxX: maxX,
        minY: minY,
        maxY: maxY
      };
    }

    /**
     * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY};
     * @returns {{x: number, y: number}}
     * @static
     */
  }, {
    key: "findCenter",
    value: function findCenter(range) {
      return {
        x: 0.5 * (range.maxX + range.minX),
        y: 0.5 * (range.maxY + range.minY)
      };
    }

    /**
     * This returns a clone of the options or options of the edge or node to be used for construction of new edges or check functions for new nodes.
     *
     * @param {vis.Item} item
     * @param {'node'|undefined} type
     * @returns {{}}
     * @static
     */
  }, {
    key: "cloneOptions",
    value: function cloneOptions(item, type) {
      var clonedOptions = {};
      if (type === undefined || type === "node") {
        deepExtend(clonedOptions, item.options, true);
        clonedOptions.x = item.x;
        clonedOptions.y = item.y;
        clonedOptions.amountOfConnections = item.edges.length;
      } else {
        deepExtend(clonedOptions, item.options, true);
      }
      return clonedOptions;
    }
  }]);
  return NetworkUtil;
}();

function _createSuper$1(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$1(); 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 _isNativeReflectConstruct$1() { 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; } }

/**
 * A Cluster is a special Node that allows a group of Nodes positioned closely together
 * to be represented by a single Cluster Node.
 *
 * @augments Node
 */
var Cluster = /*#__PURE__*/function (_Node) {
  _inherits(Cluster, _Node);
  var _super = _createSuper$1(Cluster);
  /**
   * @param {object} options
   * @param {object} body
   * @param {Array.<HTMLImageElement>}imagelist
   * @param {Array} grouplist
   * @param {object} globalOptions
   * @param {object} defaultOptions     Global default options for nodes
   */
  function Cluster(options, body, imagelist, grouplist, globalOptions, defaultOptions) {
    var _this;
    _classCallCheck(this, Cluster);
    _this = _super.call(this, options, body, imagelist, grouplist, globalOptions, defaultOptions);
    _this.isCluster = true;
    _this.containedNodes = {};
    _this.containedEdges = {};
    return _this;
  }

  /**
   * Transfer child cluster data to current and disconnect the child cluster.
   *
   * Please consult the header comment in 'Clustering.js' for the fields set here.
   *
   * @param {string|number} childClusterId  id of child cluster to open
   */
  _createClass(Cluster, [{
    key: "_openChildCluster",
    value: function _openChildCluster(childClusterId) {
      var _this2 = this;
      var childCluster = this.body.nodes[childClusterId];
      if (this.containedNodes[childClusterId] === undefined) {
        throw new Error("node with id: " + childClusterId + " not in current cluster");
      }
      if (!childCluster.isCluster) {
        throw new Error("node with id: " + childClusterId + " is not a cluster");
      }

      // Disconnect child cluster from current cluster
      delete this.containedNodes[childClusterId];
      forEach$1(childCluster.edges, function (edge) {
        delete _this2.containedEdges[edge.id];
      });

      // Transfer nodes and edges
      forEach$1(childCluster.containedNodes, function (node, nodeId) {
        _this2.containedNodes[nodeId] = node;
      });
      childCluster.containedNodes = {};
      forEach$1(childCluster.containedEdges, function (edge, edgeId) {
        _this2.containedEdges[edgeId] = edge;
      });
      childCluster.containedEdges = {};

      // Transfer edges within cluster edges which are clustered
      forEach$1(childCluster.edges, function (clusterEdge) {
        forEach$1(_this2.edges, function (parentClusterEdge) {
          var _context, _context2;
          // Assumption: a clustered edge can only be present in a single clustering edge
          // Not tested here
          var index = _indexOfInstanceProperty(_context = parentClusterEdge.clusteringEdgeReplacingIds).call(_context, clusterEdge.id);
          if (index === -1) return;
          forEach$1(clusterEdge.clusteringEdgeReplacingIds, function (srcId) {
            parentClusterEdge.clusteringEdgeReplacingIds.push(srcId);

            // Maintain correct bookkeeping for transferred edge
            _this2.body.edges[srcId].edgeReplacedById = parentClusterEdge.id;
          });

          // Remove cluster edge from parent cluster edge
          _spliceInstanceProperty(_context2 = parentClusterEdge.clusteringEdgeReplacingIds).call(_context2, index, 1);
        });
      });
      childCluster.edges = [];
    }
  }]);
  return Cluster;
}(Node);

/**
 * The clustering engine
 */
var ClusterEngine = /*#__PURE__*/function () {
  /**
   * @param {object} body
   */
  function ClusterEngine(body) {
    var _this = this;
    _classCallCheck(this, ClusterEngine);
    this.body = body;
    this.clusteredNodes = {}; // key: node id, value: { clusterId: <id of cluster>, node: <node instance>}
    this.clusteredEdges = {}; // key: edge id, value: restore information for given edge

    this.options = {};
    this.defaultOptions = {};
    _Object$assign(this.options, this.defaultOptions);
    this.body.emitter.on("_resetData", function () {
      _this.clusteredNodes = {};
      _this.clusteredEdges = {};
    });
  }

  /**
   *
   * @param {number} hubsize
   * @param {object} options
   */
  _createClass(ClusterEngine, [{
    key: "clusterByHubsize",
    value: function clusterByHubsize(hubsize, options) {
      if (hubsize === undefined) {
        hubsize = this._getHubSize();
      } else if (_typeof(hubsize) === "object") {
        options = this._checkOptions(hubsize);
        hubsize = this._getHubSize();
      }
      var nodesToCluster = [];
      for (var i = 0; i < this.body.nodeIndices.length; i++) {
        var node = this.body.nodes[this.body.nodeIndices[i]];
        if (node.edges.length >= hubsize) {
          nodesToCluster.push(node.id);
        }
      }
      for (var _i = 0; _i < nodesToCluster.length; _i++) {
        this.clusterByConnection(nodesToCluster[_i], options, true);
      }
      this.body.emitter.emit("_dataChanged");
    }

    /**
     * loop over all nodes, check if they adhere to the condition and cluster if needed.
     *
     * @param {object} options
     * @param {boolean} [refreshData=true]
     */
  }, {
    key: "cluster",
    value: function cluster() {
      var _this2 = this;
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var refreshData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      if (options.joinCondition === undefined) {
        throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");
      }

      // check if the options object is fine, append if needed
      options = this._checkOptions(options);
      var childNodesObj = {};
      var childEdgesObj = {};

      // collect the nodes that will be in the cluster
      forEach$1(this.body.nodes, function (node, nodeId) {
        if (node.options && options.joinCondition(node.options) === true) {
          childNodesObj[nodeId] = node;

          // collect the edges that will be in the cluster
          forEach$1(node.edges, function (edge) {
            if (_this2.clusteredEdges[edge.id] === undefined) {
              childEdgesObj[edge.id] = edge;
            }
          });
        }
      });
      this._cluster(childNodesObj, childEdgesObj, options, refreshData);
    }

    /**
     * Cluster all nodes in the network that have only X edges
     *
     * @param {number} edgeCount
     * @param {object} options
     * @param {boolean} [refreshData=true]
     */
  }, {
    key: "clusterByEdgeCount",
    value: function clusterByEdgeCount(edgeCount, options) {
      var _this3 = this;
      var refreshData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
      options = this._checkOptions(options);
      var clusters = [];
      var usedNodes = {};
      var edge, edges, relevantEdgeCount;
      // collect the nodes that will be in the cluster
      var _loop = function _loop() {
        var childNodesObj = {};
        var childEdgesObj = {};
        var nodeId = _this3.body.nodeIndices[i];
        var node = _this3.body.nodes[nodeId];

        // if this node is already used in another cluster this session, we do not have to re-evaluate it.
        if (usedNodes[nodeId] === undefined) {
          relevantEdgeCount = 0;
          edges = [];
          for (var j = 0; j < node.edges.length; j++) {
            edge = node.edges[j];
            if (_this3.clusteredEdges[edge.id] === undefined) {
              if (edge.toId !== edge.fromId) {
                relevantEdgeCount++;
              }
              edges.push(edge);
            }
          }

          // this node qualifies, we collect its neighbours to start the clustering process.
          if (relevantEdgeCount === edgeCount) {
            var checkJoinCondition = function checkJoinCondition(node) {
              if (options.joinCondition === undefined || options.joinCondition === null) {
                return true;
              }
              var clonedOptions = NetworkUtil.cloneOptions(node);
              return options.joinCondition(clonedOptions);
            };
            var gatheringSuccessful = true;
            for (var _j = 0; _j < edges.length; _j++) {
              edge = edges[_j];
              var childNodeId = _this3._getConnectedId(edge, nodeId);
              // add the nodes to the list by the join condition.
              if (checkJoinCondition(node)) {
                childEdgesObj[edge.id] = edge;
                childNodesObj[nodeId] = node;
                childNodesObj[childNodeId] = _this3.body.nodes[childNodeId];
                usedNodes[nodeId] = true;
              } else {
                // this node does not qualify after all.
                gatheringSuccessful = false;
                break;
              }
            }

            // add to the cluster queue
            if (_Object$keys(childNodesObj).length > 0 && _Object$keys(childEdgesObj).length > 0 && gatheringSuccessful === true) {
              /**
               * Search for cluster data that contains any of the node id's
               *
               * @returns {boolean} true if no joinCondition, otherwise return value of joinCondition
               */
              var findClusterData = function findClusterData() {
                for (var n = 0; n < clusters.length; ++n) {
                  // Search for a cluster containing any of the node id's
                  for (var m in childNodesObj) {
                    if (clusters[n].nodes[m] !== undefined) {
                      return clusters[n];
                    }
                  }
                }
                return undefined;
              };

              // If any of the found nodes is part of a cluster found in this method,
              // add the current values to that cluster
              var foundCluster = findClusterData();
              if (foundCluster !== undefined) {
                // Add nodes to found cluster if not present
                for (var m in childNodesObj) {
                  if (foundCluster.nodes[m] === undefined) {
                    foundCluster.nodes[m] = childNodesObj[m];
                  }
                }

                // Add edges to found cluster, if not present
                for (var _m in childEdgesObj) {
                  if (foundCluster.edges[_m] === undefined) {
                    foundCluster.edges[_m] = childEdgesObj[_m];
                  }
                }
              } else {
                // Create a new cluster group
                clusters.push({
                  nodes: childNodesObj,
                  edges: childEdgesObj
                });
              }
            }
          }
        }
      };
      for (var i = 0; i < this.body.nodeIndices.length; i++) {
        _loop();
      }
      for (var _i2 = 0; _i2 < clusters.length; _i2++) {
        this._cluster(clusters[_i2].nodes, clusters[_i2].edges, options, false);
      }
      if (refreshData === true) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     * Cluster all nodes in the network that have only 1 edge
     *
     * @param {object} options
     * @param {boolean} [refreshData=true]
     */
  }, {
    key: "clusterOutliers",
    value: function clusterOutliers(options) {
      var refreshData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      this.clusterByEdgeCount(1, options, refreshData);
    }

    /**
     * Cluster all nodes in the network that have only 2 edge
     *
     * @param {object} options
     * @param {boolean} [refreshData=true]
     */
  }, {
    key: "clusterBridges",
    value: function clusterBridges(options) {
      var refreshData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      this.clusterByEdgeCount(2, options, refreshData);
    }

    /**
     * suck all connected nodes of a node into the node.
     *
     * @param {Node.id} nodeId
     * @param {object} options
     * @param {boolean} [refreshData=true]
     */
  }, {
    key: "clusterByConnection",
    value: function clusterByConnection(nodeId, options) {
      var _context;
      var refreshData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
      // kill conditions
      if (nodeId === undefined) {
        throw new Error("No nodeId supplied to clusterByConnection!");
      }
      if (this.body.nodes[nodeId] === undefined) {
        throw new Error("The nodeId given to clusterByConnection does not exist!");
      }
      var node = this.body.nodes[nodeId];
      options = this._checkOptions(options, node);
      if (options.clusterNodeProperties.x === undefined) {
        options.clusterNodeProperties.x = node.x;
      }
      if (options.clusterNodeProperties.y === undefined) {
        options.clusterNodeProperties.y = node.y;
      }
      if (options.clusterNodeProperties.fixed === undefined) {
        options.clusterNodeProperties.fixed = {};
        options.clusterNodeProperties.fixed.x = node.options.fixed.x;
        options.clusterNodeProperties.fixed.y = node.options.fixed.y;
      }
      var childNodesObj = {};
      var childEdgesObj = {};
      var parentNodeId = node.id;
      var parentClonedOptions = NetworkUtil.cloneOptions(node);
      childNodesObj[parentNodeId] = node;

      // collect the nodes that will be in the cluster
      for (var i = 0; i < node.edges.length; i++) {
        var edge = node.edges[i];
        if (this.clusteredEdges[edge.id] === undefined) {
          var childNodeId = this._getConnectedId(edge, parentNodeId);

          // if the child node is not in a cluster
          if (this.clusteredNodes[childNodeId] === undefined) {
            if (childNodeId !== parentNodeId) {
              if (options.joinCondition === undefined) {
                childEdgesObj[edge.id] = edge;
                childNodesObj[childNodeId] = this.body.nodes[childNodeId];
              } else {
                // clone the options and insert some additional parameters that could be interesting.
                var childClonedOptions = NetworkUtil.cloneOptions(this.body.nodes[childNodeId]);
                if (options.joinCondition(parentClonedOptions, childClonedOptions) === true) {
                  childEdgesObj[edge.id] = edge;
                  childNodesObj[childNodeId] = this.body.nodes[childNodeId];
                }
              }
            } else {
              // swallow the edge if it is self-referencing.
              childEdgesObj[edge.id] = edge;
            }
          }
        }
      }
      var childNodeIDs = _mapInstanceProperty(_context = _Object$keys(childNodesObj)).call(_context, function (childNode) {
        return childNodesObj[childNode].id;
      });
      for (var childNodeKey in childNodesObj) {
        if (!Object.prototype.hasOwnProperty.call(childNodesObj, childNodeKey)) continue;
        var childNode = childNodesObj[childNodeKey];
        for (var y = 0; y < childNode.edges.length; y++) {
          var childEdge = childNode.edges[y];
          if (_indexOfInstanceProperty(childNodeIDs).call(childNodeIDs, this._getConnectedId(childEdge, childNode.id)) > -1) {
            childEdgesObj[childEdge.id] = childEdge;
          }
        }
      }
      this._cluster(childNodesObj, childEdgesObj, options, refreshData);
    }

    /**
     * This function creates the edges that will be attached to the cluster
     * It looks for edges that are connected to the nodes from the "outside' of the cluster.
     *
     * @param {{Node.id: vis.Node}} childNodesObj
     * @param {{vis.Edge.id: vis.Edge}} childEdgesObj
     * @param {object} clusterNodeProperties
     * @param {object} clusterEdgeProperties
     * @private
     */
  }, {
    key: "_createClusterEdges",
    value: function _createClusterEdges(childNodesObj, childEdgesObj, clusterNodeProperties, clusterEdgeProperties) {
      var edge, childNodeId, childNode, toId, fromId, otherNodeId;

      // loop over all child nodes and their edges to find edges going out of the cluster
      // these edges will be replaced by clusterEdges.
      var childKeys = _Object$keys(childNodesObj);
      var createEdges = [];
      for (var i = 0; i < childKeys.length; i++) {
        childNodeId = childKeys[i];
        childNode = childNodesObj[childNodeId];

        // construct new edges from the cluster to others
        for (var j = 0; j < childNode.edges.length; j++) {
          edge = childNode.edges[j];
          // we only handle edges that are visible to the system, not the disabled ones from the clustering process.
          if (this.clusteredEdges[edge.id] === undefined) {
            // self-referencing edges will be added to the "hidden" list
            if (edge.toId == edge.fromId) {
              childEdgesObj[edge.id] = edge;
            } else {
              // set up the from and to.
              if (edge.toId == childNodeId) {
                // this is a double equals because ints and strings can be interchanged here.
                toId = clusterNodeProperties.id;
                fromId = edge.fromId;
                otherNodeId = fromId;
              } else {
                toId = edge.toId;
                fromId = clusterNodeProperties.id;
                otherNodeId = toId;
              }
            }

            // Only edges from the cluster outwards are being replaced.
            if (childNodesObj[otherNodeId] === undefined) {
              createEdges.push({
                edge: edge,
                fromId: fromId,
                toId: toId
              });
            }
          }
        }
      }

      //
      // Here we actually create the replacement edges.
      //
      // We could not do this in the loop above as the creation process
      // would add an edge to the edges array we are iterating over.
      //
      // NOTE: a clustered edge can have multiple base edges!
      //
      var newEdges = [];

      /**
       * Find a cluster edge which matches the given created edge.
       *
       * @param {vis.Edge} createdEdge
       * @returns {vis.Edge}
       */
      var getNewEdge = function getNewEdge(createdEdge) {
        for (var _j2 = 0; _j2 < newEdges.length; _j2++) {
          var newEdge = newEdges[_j2];

          // We replace both to and from edges with a single cluster edge
          var matchToDirection = createdEdge.fromId === newEdge.fromId && createdEdge.toId === newEdge.toId;
          var matchFromDirection = createdEdge.fromId === newEdge.toId && createdEdge.toId === newEdge.fromId;
          if (matchToDirection || matchFromDirection) {
            return newEdge;
          }
        }
        return null;
      };
      for (var _j3 = 0; _j3 < createEdges.length; _j3++) {
        var createdEdge = createEdges[_j3];
        var _edge = createdEdge.edge;
        var newEdge = getNewEdge(createdEdge);
        if (newEdge === null) {
          // Create a clustered edge for this connection
          newEdge = this._createClusteredEdge(createdEdge.fromId, createdEdge.toId, _edge, clusterEdgeProperties);
          newEdges.push(newEdge);
        } else {
          newEdge.clusteringEdgeReplacingIds.push(_edge.id);
        }

        // also reference the new edge in the old edge
        this.body.edges[_edge.id].edgeReplacedById = newEdge.id;

        // hide the replaced edge
        this._backupEdgeOptions(_edge);
        _edge.setOptions({
          physics: false
        });
      }
    }

    /**
     * This function checks the options that can be supplied to the different cluster functions
     * for certain fields and inserts defaults if needed
     *
     * @param {object} options
     * @returns {*}
     * @private
     */
  }, {
    key: "_checkOptions",
    value: function _checkOptions() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      if (options.clusterEdgeProperties === undefined) {
        options.clusterEdgeProperties = {};
      }
      if (options.clusterNodeProperties === undefined) {
        options.clusterNodeProperties = {};
      }
      return options;
    }

    /**
     *
     * @param {object}    childNodesObj         | object with node objects, id as keys, same as childNodes except it also contains a source node
     * @param {object}    childEdgesObj         | object with edge objects, id as keys
     * @param {Array}     options               | object with {clusterNodeProperties, clusterEdgeProperties, processProperties}
     * @param {boolean}   refreshData | when true, do not wrap up
     * @private
     */
  }, {
    key: "_cluster",
    value: function _cluster(childNodesObj, childEdgesObj, options) {
      var refreshData = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
      // Remove nodes which are already clustered
      var tmpNodesToRemove = [];
      for (var nodeId in childNodesObj) {
        if (Object.prototype.hasOwnProperty.call(childNodesObj, nodeId)) {
          if (this.clusteredNodes[nodeId] !== undefined) {
            tmpNodesToRemove.push(nodeId);
          }
        }
      }
      for (var n = 0; n < tmpNodesToRemove.length; ++n) {
        delete childNodesObj[tmpNodesToRemove[n]];
      }

      // kill condition: no nodes don't bother
      if (_Object$keys(childNodesObj).length == 0) {
        return;
      }

      // allow clusters of 1 if options allow
      if (_Object$keys(childNodesObj).length == 1 && options.clusterNodeProperties.allowSingleNodeCluster != true) {
        return;
      }
      var clusterNodeProperties = deepExtend({}, options.clusterNodeProperties);

      // construct the clusterNodeProperties
      if (options.processProperties !== undefined) {
        // get the childNode options
        var childNodesOptions = [];
        for (var _nodeId in childNodesObj) {
          if (Object.prototype.hasOwnProperty.call(childNodesObj, _nodeId)) {
            var clonedOptions = NetworkUtil.cloneOptions(childNodesObj[_nodeId]);
            childNodesOptions.push(clonedOptions);
          }
        }

        // get cluster properties based on childNodes
        var childEdgesOptions = [];
        for (var edgeId in childEdgesObj) {
          if (Object.prototype.hasOwnProperty.call(childEdgesObj, edgeId)) {
            // these cluster edges will be removed on creation of the cluster.
            if (edgeId.substr(0, 12) !== "clusterEdge:") {
              var _clonedOptions = NetworkUtil.cloneOptions(childEdgesObj[edgeId], "edge");
              childEdgesOptions.push(_clonedOptions);
            }
          }
        }
        clusterNodeProperties = options.processProperties(clusterNodeProperties, childNodesOptions, childEdgesOptions);
        if (!clusterNodeProperties) {
          throw new Error("The processProperties function does not return properties!");
        }
      }

      // check if we have an unique id;
      if (clusterNodeProperties.id === undefined) {
        clusterNodeProperties.id = "cluster:" + v4();
      }
      var clusterId = clusterNodeProperties.id;
      if (clusterNodeProperties.label === undefined) {
        clusterNodeProperties.label = "cluster";
      }

      // give the clusterNode a position if it does not have one.
      var pos = undefined;
      if (clusterNodeProperties.x === undefined) {
        pos = this._getClusterPosition(childNodesObj);
        clusterNodeProperties.x = pos.x;
      }
      if (clusterNodeProperties.y === undefined) {
        if (pos === undefined) {
          pos = this._getClusterPosition(childNodesObj);
        }
        clusterNodeProperties.y = pos.y;
      }

      // force the ID to remain the same
      clusterNodeProperties.id = clusterId;

      // create the cluster Node
      // Note that allowSingleNodeCluster, if present, is stored in the options as well
      var clusterNode = this.body.functions.createNode(clusterNodeProperties, Cluster);
      clusterNode.containedNodes = childNodesObj;
      clusterNode.containedEdges = childEdgesObj;
      // cache a copy from the cluster edge properties if we have to reconnect others later on
      clusterNode.clusterEdgeProperties = options.clusterEdgeProperties;

      // finally put the cluster node into global
      this.body.nodes[clusterNodeProperties.id] = clusterNode;
      this._clusterEdges(childNodesObj, childEdgesObj, clusterNodeProperties, options.clusterEdgeProperties);

      // set ID to undefined so no duplicates arise
      clusterNodeProperties.id = undefined;

      // wrap up
      if (refreshData === true) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     *
     * @param {Edge} edge
     * @private
     */
  }, {
    key: "_backupEdgeOptions",
    value: function _backupEdgeOptions(edge) {
      if (this.clusteredEdges[edge.id] === undefined) {
        this.clusteredEdges[edge.id] = {
          physics: edge.options.physics
        };
      }
    }

    /**
     *
     * @param {Edge} edge
     * @private
     */
  }, {
    key: "_restoreEdge",
    value: function _restoreEdge(edge) {
      var originalOptions = this.clusteredEdges[edge.id];
      if (originalOptions !== undefined) {
        edge.setOptions({
          physics: originalOptions.physics
        });
        delete this.clusteredEdges[edge.id];
      }
    }

    /**
     * Check if a node is a cluster.
     *
     * @param {Node.id} nodeId
     * @returns {*}
     */
  }, {
    key: "isCluster",
    value: function isCluster(nodeId) {
      if (this.body.nodes[nodeId] !== undefined) {
        return this.body.nodes[nodeId].isCluster === true;
      } else {
        console.error("Node does not exist.");
        return false;
      }
    }

    /**
     * get the position of the cluster node based on what's inside
     *
     * @param {object} childNodesObj    | object with node objects, id as keys
     * @returns {{x: number, y: number}}
     * @private
     */
  }, {
    key: "_getClusterPosition",
    value: function _getClusterPosition(childNodesObj) {
      var childKeys = _Object$keys(childNodesObj);
      var minX = childNodesObj[childKeys[0]].x;
      var maxX = childNodesObj[childKeys[0]].x;
      var minY = childNodesObj[childKeys[0]].y;
      var maxY = childNodesObj[childKeys[0]].y;
      var node;
      for (var i = 1; i < childKeys.length; i++) {
        node = childNodesObj[childKeys[i]];
        minX = node.x < minX ? node.x : minX;
        maxX = node.x > maxX ? node.x : maxX;
        minY = node.y < minY ? node.y : minY;
        maxY = node.y > maxY ? node.y : maxY;
      }
      return {
        x: 0.5 * (minX + maxX),
        y: 0.5 * (minY + maxY)
      };
    }

    /**
     * Open a cluster by calling this function.
     *
     * @param {vis.Edge.id}  clusterNodeId | the ID of the cluster node
     * @param {object} options
     * @param {boolean} refreshData | wrap up afterwards if not true
     */
  }, {
    key: "openCluster",
    value: function openCluster(clusterNodeId, options) {
      var refreshData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
      // kill conditions
      if (clusterNodeId === undefined) {
        throw new Error("No clusterNodeId supplied to openCluster.");
      }
      var clusterNode = this.body.nodes[clusterNodeId];
      if (clusterNode === undefined) {
        throw new Error("The clusterNodeId supplied to openCluster does not exist.");
      }
      if (clusterNode.isCluster !== true || clusterNode.containedNodes === undefined || clusterNode.containedEdges === undefined) {
        throw new Error("The node:" + clusterNodeId + " is not a valid cluster.");
      }

      // Check if current cluster is clustered itself
      var stack = this.findNode(clusterNodeId);
      var parentIndex = _indexOfInstanceProperty(stack).call(stack, clusterNodeId) - 1;
      if (parentIndex >= 0) {
        // Current cluster is clustered; transfer contained nodes and edges to parent
        var parentClusterNodeId = stack[parentIndex];
        var parentClusterNode = this.body.nodes[parentClusterNodeId];

        // clustering.clusteredNodes and clustering.clusteredEdges remain unchanged
        parentClusterNode._openChildCluster(clusterNodeId);

        // All components of child cluster node have been transferred. It can die now.
        delete this.body.nodes[clusterNodeId];
        if (refreshData === true) {
          this.body.emitter.emit("_dataChanged");
        }
        return;
      }

      // main body
      var containedNodes = clusterNode.containedNodes;
      var containedEdges = clusterNode.containedEdges;

      // allow the user to position the nodes after release.
      if (options !== undefined && options.releaseFunction !== undefined && typeof options.releaseFunction === "function") {
        var positions = {};
        var clusterPosition = {
          x: clusterNode.x,
          y: clusterNode.y
        };
        for (var nodeId in containedNodes) {
          if (Object.prototype.hasOwnProperty.call(containedNodes, nodeId)) {
            var containedNode = this.body.nodes[nodeId];
            positions[nodeId] = {
              x: containedNode.x,
              y: containedNode.y
            };
          }
        }
        var newPositions = options.releaseFunction(clusterPosition, positions);
        for (var _nodeId2 in containedNodes) {
          if (Object.prototype.hasOwnProperty.call(containedNodes, _nodeId2)) {
            var _containedNode = this.body.nodes[_nodeId2];
            if (newPositions[_nodeId2] !== undefined) {
              _containedNode.x = newPositions[_nodeId2].x === undefined ? clusterNode.x : newPositions[_nodeId2].x;
              _containedNode.y = newPositions[_nodeId2].y === undefined ? clusterNode.y : newPositions[_nodeId2].y;
            }
          }
        }
      } else {
        // copy the position from the cluster
        forEach$1(containedNodes, function (containedNode) {
          // inherit position
          if (containedNode.options.fixed.x === false) {
            containedNode.x = clusterNode.x;
          }
          if (containedNode.options.fixed.y === false) {
            containedNode.y = clusterNode.y;
          }
        });
      }

      // release nodes
      for (var _nodeId3 in containedNodes) {
        if (Object.prototype.hasOwnProperty.call(containedNodes, _nodeId3)) {
          var _containedNode2 = this.body.nodes[_nodeId3];

          // inherit speed
          _containedNode2.vx = clusterNode.vx;
          _containedNode2.vy = clusterNode.vy;
          _containedNode2.setOptions({
            physics: true
          });
          delete this.clusteredNodes[_nodeId3];
        }
      }

      // copy the clusterNode edges because we cannot iterate over an object that we add or remove from.
      var edgesToBeDeleted = [];
      for (var i = 0; i < clusterNode.edges.length; i++) {
        edgesToBeDeleted.push(clusterNode.edges[i]);
      }

      // actually handling the deleting.
      for (var _i3 = 0; _i3 < edgesToBeDeleted.length; _i3++) {
        var edge = edgesToBeDeleted[_i3];
        var otherNodeId = this._getConnectedId(edge, clusterNodeId);
        var otherNode = this.clusteredNodes[otherNodeId];
        for (var j = 0; j < edge.clusteringEdgeReplacingIds.length; j++) {
          var transferId = edge.clusteringEdgeReplacingIds[j];
          var transferEdge = this.body.edges[transferId];
          if (transferEdge === undefined) continue;

          // if the other node is in another cluster, we transfer ownership of this edge to the other cluster
          if (otherNode !== undefined) {
            // transfer ownership:
            var otherCluster = this.body.nodes[otherNode.clusterId];
            otherCluster.containedEdges[transferEdge.id] = transferEdge;

            // delete local reference
            delete containedEdges[transferEdge.id];

            // get to and from
            var fromId = transferEdge.fromId;
            var toId = transferEdge.toId;
            if (transferEdge.toId == otherNodeId) {
              toId = otherNode.clusterId;
            } else {
              fromId = otherNode.clusterId;
            }

            // create new cluster edge from the otherCluster
            this._createClusteredEdge(fromId, toId, transferEdge, otherCluster.clusterEdgeProperties, {
              hidden: false,
              physics: true
            });
          } else {
            this._restoreEdge(transferEdge);
          }
        }
        edge.remove();
      }

      // handle the releasing of the edges
      for (var edgeId in containedEdges) {
        if (Object.prototype.hasOwnProperty.call(containedEdges, edgeId)) {
          this._restoreEdge(containedEdges[edgeId]);
        }
      }

      // remove clusterNode
      delete this.body.nodes[clusterNodeId];
      if (refreshData === true) {
        this.body.emitter.emit("_dataChanged");
      }
    }

    /**
     *
     * @param {Cluster.id} clusterId
     * @returns {Array.<Node.id>}
     */
  }, {
    key: "getNodesInCluster",
    value: function getNodesInCluster(clusterId) {
      var nodesArray = [];
      if (this.isCluster(clusterId) === true) {
        var containedNodes = this.body.nodes[clusterId].containedNodes;
        for (var nodeId in containedNodes) {
          if (Object.prototype.hasOwnProperty.call(containedNodes, nodeId)) {
            nodesArray.push(this.body.nodes[nodeId].id);
          }
        }
      }
      return nodesArray;
    }

    /**
     * Get the stack clusterId's that a certain node resides in. cluster A -> cluster B -> cluster C -> node
     *
     * If a node can't be found in the chain, return an empty array.
     *
     * @param {string|number} nodeId
     * @returns {Array}
     */
  }, {
    key: "findNode",
    value: function findNode(nodeId) {
      var stack = [];
      var max = 100;
      var counter = 0;
      var node;
      while (this.clusteredNodes[nodeId] !== undefined && counter < max) {
        node = this.body.nodes[nodeId];
        if (node === undefined) return [];
        stack.push(node.id);
        nodeId = this.clusteredNodes[nodeId].clusterId;
        counter++;
      }
      node = this.body.nodes[nodeId];
      if (node === undefined) return [];
      stack.push(node.id);
      _reverseInstanceProperty(stack).call(stack);
      return stack;
    }

    /**
     * Using a clustered nodeId, update with the new options
     *
     * @param {Node.id} clusteredNodeId
     * @param {object} newOptions
     */
  }, {
    key: "updateClusteredNode",
    value: function updateClusteredNode(clusteredNodeId, newOptions) {
      if (clusteredNodeId === undefined) {
        throw new Error("No clusteredNodeId supplied to updateClusteredNode.");
      }
      if (newOptions === undefined) {
        throw new Error("No newOptions supplied to updateClusteredNode.");
      }
      if (this.body.nodes[clusteredNodeId] === undefined) {
        throw new Error("The clusteredNodeId supplied to updateClusteredNode does not exist.");
      }
      this.body.nodes[clusteredNodeId].setOptions(newOptions);
      this.body.emitter.emit("_dataChanged");
    }

    /**
     * Using a base edgeId, update all related clustered edges with the new options
     *
     * @param {vis.Edge.id} startEdgeId
     * @param {object} newOptions
     */
  }, {
    key: "updateEdge",
    value: function updateEdge(startEdgeId, newOptions) {
      if (startEdgeId === undefined) {
        throw new Error("No startEdgeId supplied to updateEdge.");
      }
      if (newOptions === undefined) {
        throw new Error("No newOptions supplied to updateEdge.");
      }
      if (this.body.edges[startEdgeId] === undefined) {
        throw new Error("The startEdgeId supplied to updateEdge does not exist.");
      }
      var allEdgeIds = this.getClusteredEdges(startEdgeId);
      for (var i = 0; i < allEdgeIds.length; i++) {
        var edge = this.body.edges[allEdgeIds[i]];
        edge.setOptions(newOptions);
      }
      this.body.emitter.emit("_dataChanged");
    }

    /**
     * Get a stack of clusterEdgeId's (+base edgeid) that a base edge is the same as. cluster edge C -> cluster edge B -> cluster edge A -> base edge(edgeId)
     *
     * @param {vis.Edge.id} edgeId
     * @returns {Array.<vis.Edge.id>}
     */
  }, {
    key: "getClusteredEdges",
    value: function getClusteredEdges(edgeId) {
      var stack = [];
      var max = 100;
      var counter = 0;
      while (edgeId !== undefined && this.body.edges[edgeId] !== undefined && counter < max) {
        stack.push(this.body.edges[edgeId].id);
        edgeId = this.body.edges[edgeId].edgeReplacedById;
        counter++;
      }
      _reverseInstanceProperty(stack).call(stack);
      return stack;
    }

    /**
     * Get the base edge id of clusterEdgeId. cluster edge (clusteredEdgeId) -> cluster edge B -> cluster edge C -> base edge
     *
     * @param {vis.Edge.id} clusteredEdgeId
     * @returns {vis.Edge.id} baseEdgeId
     *
     * TODO: deprecate in 5.0.0. Method getBaseEdges() is the correct one to use.
     */
  }, {
    key: "getBaseEdge",
    value: function getBaseEdge(clusteredEdgeId) {
      // Just kludge this by returning the first base edge id found
      return this.getBaseEdges(clusteredEdgeId)[0];
    }

    /**
     * Get all regular edges for this clustered edge id.
     *
     * @param {vis.Edge.id} clusteredEdgeId
     * @returns {Array.<vis.Edge.id>} all baseEdgeId's under this clustered edge
     */
  }, {
    key: "getBaseEdges",
    value: function getBaseEdges(clusteredEdgeId) {
      var IdsToHandle = [clusteredEdgeId];
      var doneIds = [];
      var foundIds = [];
      var max = 100;
      var counter = 0;
      while (IdsToHandle.length > 0 && counter < max) {
        var nextId = IdsToHandle.pop();
        if (nextId === undefined) continue; // Paranoia here and onwards
        var nextEdge = this.body.edges[nextId];
        if (nextEdge === undefined) continue;
        counter++;
        var replacingIds = nextEdge.clusteringEdgeReplacingIds;
        if (replacingIds === undefined) {
          // nextId is a base id
          foundIds.push(nextId);
        } else {
          // Another cluster edge, unravel this one as well
          for (var i = 0; i < replacingIds.length; ++i) {
            var replacingId = replacingIds[i];

            // Don't add if already handled
            // TODO: never triggers; find a test-case which does
            if (_indexOfInstanceProperty(IdsToHandle).call(IdsToHandle, replacingIds) !== -1 || _indexOfInstanceProperty(doneIds).call(doneIds, replacingIds) !== -1) {
              continue;
            }
            IdsToHandle.push(replacingId);
          }
        }
        doneIds.push(nextId);
      }
      return foundIds;
    }

    /**
     * Get the Id the node is connected to
     *
     * @param {vis.Edge} edge
     * @param {Node.id} nodeId
     * @returns {*}
     * @private
     */
  }, {
    key: "_getConnectedId",
    value: function _getConnectedId(edge, nodeId) {
      if (edge.toId != nodeId) {
        return edge.toId;
      } else if (edge.fromId != nodeId) {
        return edge.fromId;
      } else {
        return edge.fromId;
      }
    }

    /**
     * We determine how many connections denote an important hub.
     * We take the mean + 2*std as the important hub size. (Assuming a normal distribution of data, ~2.2%)
     *
     * @returns {number}
     * @private
     */
  }, {
    key: "_getHubSize",
    value: function _getHubSize() {
      var average = 0;
      var averageSquared = 0;
      var hubCounter = 0;
      var largestHub = 0;
      for (var i = 0; i < this.body.nodeIndices.length; i++) {
        var node = this.body.nodes[this.body.nodeIndices[i]];
        if (node.edges.length > largestHub) {
          largestHub = node.edges.length;
        }
        average += node.edges.length;
        averageSquared += Math.pow(node.edges.length, 2);
        hubCounter += 1;
      }
      average = average / hubCounter;
      averageSquared = averageSquared / hubCounter;
      var variance = averageSquared - Math.pow(average, 2);
      var standardDeviation = Math.sqrt(variance);
      var hubThreshold = Math.floor(average + 2 * standardDeviation);

      // always have at least one to cluster
      if (hubThreshold > largestHub) {
        hubThreshold = largestHub;
      }
      return hubThreshold;
    }

    /**
     * Create an edge for the cluster representation.
     *
     * @param {Node.id} fromId
     * @param {Node.id} toId
     * @param {vis.Edge} baseEdge
     * @param {object} clusterEdgeProperties
     * @param {object} extraOptions
     * @returns {Edge} newly created clustered edge
     * @private
     */
  }, {
    key: "_createClusteredEdge",
    value: function _createClusteredEdge(fromId, toId, baseEdge, clusterEdgeProperties, extraOptions) {
      // copy the options of the edge we will replace
      var clonedOptions = NetworkUtil.cloneOptions(baseEdge, "edge");
      // make sure the properties of clusterEdges are superimposed on it
      deepExtend(clonedOptions, clusterEdgeProperties);

      // set up the edge
      clonedOptions.from = fromId;
      clonedOptions.to = toId;
      clonedOptions.id = "clusterEdge:" + v4();

      // apply the edge specific options to it if specified
      if (extraOptions !== undefined) {
        deepExtend(clonedOptions, extraOptions);
      }
      var newEdge = this.body.functions.createEdge(clonedOptions);
      newEdge.clusteringEdgeReplacingIds = [baseEdge.id];
      newEdge.connect();

      // Register the new edge
      this.body.edges[newEdge.id] = newEdge;
      return newEdge;
    }

    /**
     * Add the passed child nodes and edges to the given cluster node.
     *
     * @param {object | Node} childNodes  hash of nodes or single node to add in cluster
     * @param {object | Edge} childEdges  hash of edges or single edge to take into account when clustering
     * @param {Node} clusterNode  cluster node to add nodes and edges to
     * @param {object} [clusterEdgeProperties]
     * @private
     */
  }, {
    key: "_clusterEdges",
    value: function _clusterEdges(childNodes, childEdges, clusterNode, clusterEdgeProperties) {
      if (childEdges instanceof Edge) {
        var edge = childEdges;
        var obj = {};
        obj[edge.id] = edge;
        childEdges = obj;
      }
      if (childNodes instanceof Node) {
        var node = childNodes;
        var _obj = {};
        _obj[node.id] = node;
        childNodes = _obj;
      }
      if (clusterNode === undefined || clusterNode === null) {
        throw new Error("_clusterEdges: parameter clusterNode required");
      }
      if (clusterEdgeProperties === undefined) {
        // Take the required properties from the cluster node
        clusterEdgeProperties = clusterNode.clusterEdgeProperties;
      }

      // create the new edges that will connect to the cluster.
      // All self-referencing edges will be added to childEdges here.
      this._createClusterEdges(childNodes, childEdges, clusterNode, clusterEdgeProperties);

      // disable the childEdges
      for (var edgeId in childEdges) {
        if (Object.prototype.hasOwnProperty.call(childEdges, edgeId)) {
          if (this.body.edges[edgeId] !== undefined) {
            var _edge2 = this.body.edges[edgeId];
            // cache the options before changing
            this._backupEdgeOptions(_edge2);
            // disable physics and hide the edge
            _edge2.setOptions({
              physics: false
            });
          }
        }
      }

      // disable the childNodes
      for (var nodeId in childNodes) {
        if (Object.prototype.hasOwnProperty.call(childNodes, nodeId)) {
          this.clusteredNodes[nodeId] = {
            clusterId: clusterNode.id,
            node: this.body.nodes[nodeId]
          };
          this.body.nodes[nodeId].setOptions({
            physics: false
          });
        }
      }
    }

    /**
     * Determine in which cluster given nodeId resides.
     *
     * If not in cluster, return undefined.
     *
     * NOTE: If you know a cleaner way to do this, please enlighten me (wimrijnders).
     *
     * @param {Node.id} nodeId
     * @returns {Node|undefined} Node instance for cluster, if present
     * @private
     */
  }, {
    key: "_getClusterNodeForNode",
    value: function _getClusterNodeForNode(nodeId) {
      if (nodeId === undefined) return undefined;
      var clusteredNode = this.clusteredNodes[nodeId];

      // NOTE: If no cluster info found, it should actually be an error
      if (clusteredNode === undefined) return undefined;
      var clusterId = clusteredNode.clusterId;
      if (clusterId === undefined) return undefined;
      return this.body.nodes[clusterId];
    }

    /**
     * Internal helper function for conditionally removing items in array
     *
     * Done like this because Array.filter() is not fully supported by all IE's.
     *
     * @param {Array} arr
     * @param {Function} callback
     * @returns {Array}
     * @private
     */
  }, {
    key: "_filter",
    value: function _filter(arr, callback) {
      var ret = [];
      forEach$1(arr, function (item) {
        if (callback(item)) {
          ret.push(item);
        }
      });
      return ret;
    }

    /**
     * Scan all edges for changes in clustering and adjust this if necessary.
     *
     * Call this (internally) after there has been a change in node or edge data.
     *
     * Pre: States of this.body.nodes and this.body.edges consistent
     * Pre: this.clusteredNodes and this.clusteredEdge consistent with containedNodes and containedEdges
     *      of cluster nodes.
     */
  }, {
    key: "_updateState",
    value: function _updateState() {
      var _this4 = this;
      var nodeId;
      var deletedNodeIds = [];
      var deletedEdgeIds = {};

      /**
       * Utility function to iterate over clustering nodes only
       *
       * @param {Function} callback  function to call for each cluster node
       */
      var eachClusterNode = function eachClusterNode(callback) {
        forEach$1(_this4.body.nodes, function (node) {
          if (node.isCluster === true) {
            callback(node);
          }
        });
      };

      //
      // Remove deleted regular nodes from clustering
      //

      // Determine the deleted nodes
      for (nodeId in this.clusteredNodes) {
        if (!Object.prototype.hasOwnProperty.call(this.clusteredNodes, nodeId)) continue;
        var node = this.body.nodes[nodeId];
        if (node === undefined) {
          deletedNodeIds.push(nodeId);
        }
      }

      // Remove nodes from cluster nodes
      eachClusterNode(function (clusterNode) {
        for (var n = 0; n < deletedNodeIds.length; n++) {
          delete clusterNode.containedNodes[deletedNodeIds[n]];
        }
      });

      // Remove nodes from cluster list
      for (var n = 0; n < deletedNodeIds.length; n++) {
        delete this.clusteredNodes[deletedNodeIds[n]];
      }

      //
      // Remove deleted edges from clustering
      //

      // Add the deleted clustered edges to the list
      forEach$1(this.clusteredEdges, function (edgeId) {
        var edge = _this4.body.edges[edgeId];
        if (edge === undefined || !edge.endPointsValid()) {
          deletedEdgeIds[edgeId] = edgeId;
        }
      });

      // Cluster nodes can also contain edges which are not clustered,
      // i.e. nodes 1-2 within cluster with an edge in between.
      // So the cluster nodes also need to be scanned for invalid edges
      eachClusterNode(function (clusterNode) {
        forEach$1(clusterNode.containedEdges, function (edge, edgeId) {
          if (!edge.endPointsValid() && !deletedEdgeIds[edgeId]) {
            deletedEdgeIds[edgeId] = edgeId;
          }
        });
      });

      // Also scan for cluster edges which need to be removed in the active list.
      // Regular edges have been removed beforehand, so this only picks up the cluster edges.
      forEach$1(this.body.edges, function (edge, edgeId) {
        // Explicitly scan the contained edges for validity
        var isValid = true;
        var replacedIds = edge.clusteringEdgeReplacingIds;
        if (replacedIds !== undefined) {
          var numValid = 0;
          forEach$1(replacedIds, function (containedEdgeId) {
            var containedEdge = _this4.body.edges[containedEdgeId];
            if (containedEdge !== undefined && containedEdge.endPointsValid()) {
              numValid += 1;
            }
          });
          isValid = numValid > 0;
        }
        if (!edge.endPointsValid() || !isValid) {
          deletedEdgeIds[edgeId] = edgeId;
        }
      });

      // Remove edges from cluster nodes
      eachClusterNode(function (clusterNode) {
        forEach$1(deletedEdgeIds, function (deletedEdgeId) {
          delete clusterNode.containedEdges[deletedEdgeId];
          forEach$1(clusterNode.edges, function (edge, m) {
            if (edge.id === deletedEdgeId) {
              clusterNode.edges[m] = null; // Don't want to directly delete here, because in the loop
              return;
            }
            edge.clusteringEdgeReplacingIds = _this4._filter(edge.clusteringEdgeReplacingIds, function (id) {
              return !deletedEdgeIds[id];
            });
          });

          // Clean up the nulls
          clusterNode.edges = _this4._filter(clusterNode.edges, function (item) {
            return item !== null;
          });
        });
      });

      // Remove from cluster list
      forEach$1(deletedEdgeIds, function (edgeId) {
        delete _this4.clusteredEdges[edgeId];
      });

      // Remove cluster edges from active list (this.body.edges).
      // deletedEdgeIds still contains id of regular edges, but these should all
      // be gone when you reach here.
      forEach$1(deletedEdgeIds, function (edgeId) {
        delete _this4.body.edges[edgeId];
      });

      //
      // Check changed cluster state of edges
      //

      // Iterating over keys here, because edges may be removed in the loop
      var ids = _Object$keys(this.body.edges);
      forEach$1(ids, function (edgeId) {
        var edge = _this4.body.edges[edgeId];
        var shouldBeClustered = _this4._isClusteredNode(edge.fromId) || _this4._isClusteredNode(edge.toId);
        if (shouldBeClustered === _this4._isClusteredEdge(edge.id)) {
          return; // all is well
        }

        if (shouldBeClustered) {
          // add edge to clustering
          var clusterFrom = _this4._getClusterNodeForNode(edge.fromId);
          if (clusterFrom !== undefined) {
            _this4._clusterEdges(_this4.body.nodes[edge.fromId], edge, clusterFrom);
          }
          var clusterTo = _this4._getClusterNodeForNode(edge.toId);
          if (clusterTo !== undefined) {
            _this4._clusterEdges(_this4.body.nodes[edge.toId], edge, clusterTo);
          }

          // TODO: check that it works for both edges clustered
          //       (This might be paranoia)
        } else {
          delete _this4._clusterEdges[edgeId];
          _this4._restoreEdge(edge);
          // This should not be happening, the state should
          // be properly updated at this point.
          //
          // If it *is* reached during normal operation, then we have to implement
          // undo clustering for this edge here.
          // throw new Error('remove edge from clustering not implemented!')
        }
      });

      // Clusters may be nested to any level. Keep on opening until nothing to open
      var changed = false;
      var continueLoop = true;
      var _loop2 = function _loop2() {
        var clustersToOpen = [];

        // Determine the id's of clusters that need opening
        eachClusterNode(function (clusterNode) {
          var numNodes = _Object$keys(clusterNode.containedNodes).length;
          var allowSingle = clusterNode.options.allowSingleNodeCluster === true;
          if (allowSingle && numNodes < 1 || !allowSingle && numNodes < 2) {
            clustersToOpen.push(clusterNode.id);
          }
        });

        // Open them
        for (var _n = 0; _n < clustersToOpen.length; ++_n) {
          _this4.openCluster(clustersToOpen[_n], {}, false /* Don't refresh, we're in an refresh/update already */);
        }

        continueLoop = clustersToOpen.length > 0;
        changed = changed || continueLoop;
      };
      while (continueLoop) {
        _loop2();
      }
      if (changed) {
        this._updateState(); // Redo this method (recursion possible! should be safe)
      }
    }

    /**
     * Determine if node with given id is part of a cluster.
     *
     * @param {Node.id} nodeId
     * @returns {boolean} true if part of a cluster.
     */
  }, {
    key: "_isClusteredNode",
    value: function _isClusteredNode(nodeId) {
      return this.clusteredNodes[nodeId] !== undefined;
    }

    /**
     * Determine if edge with given id is not visible due to clustering.
     *
     * An edge is considered clustered if:
     * - it is directly replaced by a clustering edge
     * - any of its connecting nodes is in a cluster
     *
     * @param {vis.Edge.id} edgeId
     * @returns {boolean} true if part of a cluster.
     */
  }, {
    key: "_isClusteredEdge",
    value: function _isClusteredEdge(edgeId) {
      return this.clusteredEdges[edgeId] !== undefined;
    }
  }]);
  return ClusterEngine;
}();

/**
 * Initializes window.requestAnimationFrame() to a usable form.
 *
 * Specifically, set up this method for the case of running on node.js with jsdom enabled.
 *
 * NOTES:
 *
 * On node.js, when calling this directly outside of this class, `window` is not defined.
 *   This happens even if jsdom is used.
 * For node.js + jsdom, `window` is available at the moment the constructor is called.
 *   For this reason, the called is placed within the constructor.
 * Even then, `window.requestAnimationFrame()` is not defined, so it still needs to be added.
 * During unit testing, it happens that the window object is reset during execution, causing
 *   a runtime error due to missing `requestAnimationFrame()`. This needs to be compensated for,
 *   see `_requestNextFrame()`.
 * Since this is a global object, it may affect other modules besides `Network`. With normal
 *   usage, this does not cause any problems. During unit testing, errors may occur. These have
 *   been compensated for, see comment block in _requestNextFrame().
 *
 * @private
 */
function _initRequestAnimationFrame() {
  var func;
  if (window !== undefined) {
    func = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  }
  if (func === undefined) {
    // window or method not present, setting mock requestAnimationFrame
    window.requestAnimationFrame = function (callback) {
      //console.log("Called mock requestAnimationFrame");
      callback();
    };
  } else {
    window.requestAnimationFrame = func;
  }
}

/**
 * The canvas renderer
 */
var CanvasRenderer = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Canvas} canvas
   */
  function CanvasRenderer(body, canvas) {
    _classCallCheck(this, CanvasRenderer);
    _initRequestAnimationFrame();
    this.body = body;
    this.canvas = canvas;
    this.redrawRequested = false;
    this.renderTimer = undefined;
    this.requiresTimeout = true;
    this.renderingActive = false;
    this.renderRequests = 0;
    this.allowRedraw = true;
    this.dragging = false;
    this.zooming = false;
    this.options = {};
    this.defaultOptions = {
      hideEdgesOnDrag: false,
      hideEdgesOnZoom: false,
      hideNodesOnDrag: false
    };
    _Object$assign(this.options, this.defaultOptions);
    this._determineBrowserMethod();
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(CanvasRenderer, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _this = this,
        _context2;
      this.body.emitter.on("dragStart", function () {
        _this.dragging = true;
      });
      this.body.emitter.on("dragEnd", function () {
        _this.dragging = false;
      });
      this.body.emitter.on("zoom", function () {
        _this.zooming = true;
        window.clearTimeout(_this.zoomTimeoutId);
        _this.zoomTimeoutId = _setTimeout(function () {
          var _context;
          _this.zooming = false;
          _bindInstanceProperty$1(_context = _this._requestRedraw).call(_context, _this)();
        }, 250);
      });
      this.body.emitter.on("_resizeNodes", function () {
        _this._resizeNodes();
      });
      this.body.emitter.on("_redraw", function () {
        if (_this.renderingActive === false) {
          _this._redraw();
        }
      });
      this.body.emitter.on("_blockRedraw", function () {
        _this.allowRedraw = false;
      });
      this.body.emitter.on("_allowRedraw", function () {
        _this.allowRedraw = true;
        _this.redrawRequested = false;
      });
      this.body.emitter.on("_requestRedraw", _bindInstanceProperty$1(_context2 = this._requestRedraw).call(_context2, this));
      this.body.emitter.on("_startRendering", function () {
        _this.renderRequests += 1;
        _this.renderingActive = true;
        _this._startRendering();
      });
      this.body.emitter.on("_stopRendering", function () {
        _this.renderRequests -= 1;
        _this.renderingActive = _this.renderRequests > 0;
        _this.renderTimer = undefined;
      });
      this.body.emitter.on("destroy", function () {
        _this.renderRequests = 0;
        _this.allowRedraw = false;
        _this.renderingActive = false;
        if (_this.requiresTimeout === true) {
          clearTimeout(_this.renderTimer);
        } else {
          window.cancelAnimationFrame(_this.renderTimer);
        }
        _this.body.emitter.off();
      });
    }

    /**
     *
     * @param {object} options
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        var fields = ["hideEdgesOnDrag", "hideEdgesOnZoom", "hideNodesOnDrag"];
        selectiveDeepExtend(fields, this.options, options);
      }
    }

    /**
     * Prepare the drawing of the next frame.
     *
     * Calls the callback when the next frame can or will be drawn.
     *
     * @param {Function} callback
     * @param {number} delay - timeout case only, wait this number of milliseconds
     * @returns {Function | undefined}
     * @private
     */
  }, {
    key: "_requestNextFrame",
    value: function _requestNextFrame(callback, delay) {
      // During unit testing, it happens that the mock window object is reset while
      // the next frame is still pending. Then, either 'window' is not present, or
      // 'requestAnimationFrame()' is not present because it is not defined on the
      // mock window object.
      //
      // As a consequence, unrelated unit tests may appear to fail, even if the problem
      // described happens in the current unit test.
      //
      // This is not something that will happen in normal operation, but we still need
      // to take it into account.
      //
      if (typeof window === "undefined") return; // Doing `if (window === undefined)` does not work here!

      var timer;
      var myWindow = window; // Grab a reference to reduce the possibility that 'window' is reset
      // while running this method.

      if (this.requiresTimeout === true) {
        // wait given number of milliseconds and perform the animation step function
        timer = _setTimeout(callback, delay);
      } else {
        if (myWindow.requestAnimationFrame) {
          timer = myWindow.requestAnimationFrame(callback);
        }
      }
      return timer;
    }

    /**
     *
     * @private
     */
  }, {
    key: "_startRendering",
    value: function _startRendering() {
      if (this.renderingActive === true) {
        if (this.renderTimer === undefined) {
          var _context3;
          this.renderTimer = this._requestNextFrame(_bindInstanceProperty$1(_context3 = this._renderStep).call(_context3, this), this.simulationInterval);
        }
      }
    }

    /**
     *
     * @private
     */
  }, {
    key: "_renderStep",
    value: function _renderStep() {
      if (this.renderingActive === true) {
        // reset the renderTimer so a new scheduled animation step can be set
        this.renderTimer = undefined;
        if (this.requiresTimeout === true) {
          // this schedules a new simulation step
          this._startRendering();
        }
        this._redraw();
        if (this.requiresTimeout === false) {
          // this schedules a new simulation step
          this._startRendering();
        }
      }
    }

    /**
     * Redraw the network with the current data
     * chart will be resized too.
     */
  }, {
    key: "redraw",
    value: function redraw() {
      this.body.emitter.emit("setSize");
      this._redraw();
    }

    /**
     * Redraw the network with the current data
     *
     * @private
     */
  }, {
    key: "_requestRedraw",
    value: function _requestRedraw() {
      var _this2 = this;
      if (this.redrawRequested !== true && this.renderingActive === false && this.allowRedraw === true) {
        this.redrawRequested = true;
        this._requestNextFrame(function () {
          _this2._redraw(false);
        }, 0);
      }
    }

    /**
     * Redraw the network with the current data
     *
     * @param {boolean} [hidden=false] | Used to get the first estimate of the node sizes.
     *                                   Only the nodes are drawn after which they are quickly drawn over.
     * @private
     */
  }, {
    key: "_redraw",
    value: function _redraw() {
      var hidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      if (this.allowRedraw === true) {
        this.body.emitter.emit("initRedraw");
        this.redrawRequested = false;
        var drawLater = {
          drawExternalLabels: null
        };

        // when the container div was hidden, this fixes it back up!
        if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) {
          this.canvas.setSize();
        }
        this.canvas.setTransform();
        var ctx = this.canvas.getContext();

        // clear the canvas
        var w = this.canvas.frame.canvas.clientWidth;
        var h = this.canvas.frame.canvas.clientHeight;
        ctx.clearRect(0, 0, w, h);

        // if the div is hidden, we stop the redraw here for performance.
        if (this.canvas.frame.clientWidth === 0) {
          return;
        }

        // set scaling and translation
        ctx.save();
        ctx.translate(this.body.view.translation.x, this.body.view.translation.y);
        ctx.scale(this.body.view.scale, this.body.view.scale);
        ctx.beginPath();
        this.body.emitter.emit("beforeDrawing", ctx);
        ctx.closePath();
        if (hidden === false) {
          if ((this.dragging === false || this.dragging === true && this.options.hideEdgesOnDrag === false) && (this.zooming === false || this.zooming === true && this.options.hideEdgesOnZoom === false)) {
            this._drawEdges(ctx);
          }
        }
        if (this.dragging === false || this.dragging === true && this.options.hideNodesOnDrag === false) {
          var _this$_drawNodes = this._drawNodes(ctx, hidden),
            drawExternalLabels = _this$_drawNodes.drawExternalLabels;
          drawLater.drawExternalLabels = drawExternalLabels;
        }

        // draw the arrows last so they will be at the top
        if (hidden === false) {
          if ((this.dragging === false || this.dragging === true && this.options.hideEdgesOnDrag === false) && (this.zooming === false || this.zooming === true && this.options.hideEdgesOnZoom === false)) {
            this._drawArrows(ctx);
          }
        }
        if (drawLater.drawExternalLabels != null) {
          drawLater.drawExternalLabels();
        }
        if (hidden === false) {
          this._drawSelectionBox(ctx);
        }
        ctx.beginPath();
        this.body.emitter.emit("afterDrawing", ctx);
        ctx.closePath();

        // restore original scaling and translation
        ctx.restore();
        if (hidden === true) {
          ctx.clearRect(0, 0, w, h);
        }
      }
    }

    /**
     * Redraw all nodes
     *
     * @param {CanvasRenderingContext2D}   ctx
     * @param {boolean} [alwaysShow]
     * @private
     */
  }, {
    key: "_resizeNodes",
    value: function _resizeNodes() {
      this.canvas.setTransform();
      var ctx = this.canvas.getContext();
      ctx.save();
      ctx.translate(this.body.view.translation.x, this.body.view.translation.y);
      ctx.scale(this.body.view.scale, this.body.view.scale);
      var nodes = this.body.nodes;
      var node;

      // resize all nodes
      for (var nodeId in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
          node = nodes[nodeId];
          node.resize(ctx);
          node.updateBoundingBox(ctx, node.selected);
        }
      }

      // restore original scaling and translation
      ctx.restore();
    }

    /**
     * Redraw all nodes
     *
     * @param {CanvasRenderingContext2D} ctx  2D context of a HTML canvas
     * @param {boolean} [alwaysShow]
     * @private
     * @returns {object} Callbacks to draw later on higher layers.
     */
  }, {
    key: "_drawNodes",
    value: function _drawNodes(ctx) {
      var alwaysShow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var nodes = this.body.nodes;
      var nodeIndices = this.body.nodeIndices;
      var node;
      var selected = [];
      var hovered = [];
      var margin = 20;
      var topLeft = this.canvas.DOMtoCanvas({
        x: -margin,
        y: -margin
      });
      var bottomRight = this.canvas.DOMtoCanvas({
        x: this.canvas.frame.canvas.clientWidth + margin,
        y: this.canvas.frame.canvas.clientHeight + margin
      });
      var viewableArea = {
        top: topLeft.y,
        left: topLeft.x,
        bottom: bottomRight.y,
        right: bottomRight.x
      };
      var _drawExternalLabels = [];

      // draw unselected nodes;
      for (var _i = 0; _i < nodeIndices.length; _i++) {
        node = nodes[nodeIndices[_i]];
        // set selected and hovered nodes aside
        if (node.hover) {
          hovered.push(nodeIndices[_i]);
        } else if (node.isSelected()) {
          selected.push(nodeIndices[_i]);
        } else {
          if (alwaysShow === true) {
            var drawLater = node.draw(ctx);
            if (drawLater.drawExternalLabel != null) {
              _drawExternalLabels.push(drawLater.drawExternalLabel);
            }
          } else if (node.isBoundingBoxOverlappingWith(viewableArea) === true) {
            var _drawLater = node.draw(ctx);
            if (_drawLater.drawExternalLabel != null) {
              _drawExternalLabels.push(_drawLater.drawExternalLabel);
            }
          } else {
            node.updateBoundingBox(ctx, node.selected);
          }
        }
      }
      var i;
      var selectedLength = selected.length;
      var hoveredLength = hovered.length;

      // draw the selected nodes on top
      for (i = 0; i < selectedLength; i++) {
        node = nodes[selected[i]];
        var _drawLater2 = node.draw(ctx);
        if (_drawLater2.drawExternalLabel != null) {
          _drawExternalLabels.push(_drawLater2.drawExternalLabel);
        }
      }

      // draw hovered nodes above everything else: fixes https://github.com/visjs/vis-network/issues/226
      for (i = 0; i < hoveredLength; i++) {
        node = nodes[hovered[i]];
        var _drawLater3 = node.draw(ctx);
        if (_drawLater3.drawExternalLabel != null) {
          _drawExternalLabels.push(_drawLater3.drawExternalLabel);
        }
      }
      return {
        drawExternalLabels: function drawExternalLabels() {
          for (var _i2 = 0, _drawExternalLabels2 = _drawExternalLabels; _i2 < _drawExternalLabels2.length; _i2++) {
            var draw = _drawExternalLabels2[_i2];
            draw();
          }
        }
      };
    }

    /**
     * Redraw all edges
     *
     * @param {CanvasRenderingContext2D} ctx  2D context of a HTML canvas
     * @private
     */
  }, {
    key: "_drawEdges",
    value: function _drawEdges(ctx) {
      var edges = this.body.edges;
      var edgeIndices = this.body.edgeIndices;
      for (var i = 0; i < edgeIndices.length; i++) {
        var edge = edges[edgeIndices[i]];
        if (edge.connected === true) {
          edge.draw(ctx);
        }
      }
    }

    /**
     * Redraw all arrows
     *
     * @param {CanvasRenderingContext2D} ctx  2D context of a HTML canvas
     * @private
     */
  }, {
    key: "_drawArrows",
    value: function _drawArrows(ctx) {
      var edges = this.body.edges;
      var edgeIndices = this.body.edgeIndices;
      for (var i = 0; i < edgeIndices.length; i++) {
        var edge = edges[edgeIndices[i]];
        if (edge.connected === true) {
          edge.drawArrows(ctx);
        }
      }
    }

    /**
     * Determine if the browser requires a setTimeout or a requestAnimationFrame. This was required because
     * some implementations (safari and IE9) did not support requestAnimationFrame
     *
     * @private
     */
  }, {
    key: "_determineBrowserMethod",
    value: function _determineBrowserMethod() {
      if (typeof window !== "undefined") {
        var browserType = navigator.userAgent.toLowerCase();
        this.requiresTimeout = false;
        if (_indexOfInstanceProperty(browserType).call(browserType, "msie 9.0") != -1) {
          // IE 9
          this.requiresTimeout = true;
        } else if (_indexOfInstanceProperty(browserType).call(browserType, "safari") != -1) {
          // safari
          if (_indexOfInstanceProperty(browserType).call(browserType, "chrome") <= -1) {
            this.requiresTimeout = true;
          }
        }
      } else {
        this.requiresTimeout = true;
      }
    }

    /**
     * Redraw selection box
     *
     * @param {CanvasRenderingContext2D} ctx  2D context of a HTML canvas
     * @private
     */
  }, {
    key: "_drawSelectionBox",
    value: function _drawSelectionBox(ctx) {
      if (this.body.selectionBox.show) {
        ctx.beginPath();
        var width = this.body.selectionBox.position.end.x - this.body.selectionBox.position.start.x;
        var height = this.body.selectionBox.position.end.y - this.body.selectionBox.position.start.y;
        ctx.rect(this.body.selectionBox.position.start.x, this.body.selectionBox.position.start.y, width, height);
        ctx.fillStyle = "rgba(151, 194, 252, 0.2)";
        ctx.fillRect(this.body.selectionBox.position.start.x, this.body.selectionBox.position.start.y, width, height);
        ctx.strokeStyle = "rgba(151, 194, 252, 1)";
        ctx.stroke();
      } else {
        ctx.closePath();
      }
    }
  }]);
  return CanvasRenderer;
}();

var setIntervalExports = {};
var setInterval$1 = {
  get exports(){ return setIntervalExports; },
  set exports(v){ setIntervalExports = v; },
};

var path$2 = path$y;

var setInterval$3 = path$2.setInterval;

(function (module) {
	module.exports = setInterval$3;
} (setInterval$1));

var _setInterval = /*@__PURE__*/getDefaultExportFromCjs$1(setIntervalExports);

/**
 * Register a touch event, taking place before a gesture
 *
 * @param {Hammer} hammer       A hammer instance
 * @param {Function} callback   Callback, called as callback(event)
 */
function onTouch(hammer, callback) {
  callback.inputHandler = function (event) {
    if (event.isFirst) {
      callback(event);
    }
  };
  hammer.on("hammer.input", callback.inputHandler);
}

/**
 * Register a release event, taking place after a gesture
 *
 * @param {Hammer} hammer       A hammer instance
 * @param {Function} callback   Callback, called as callback(event)
 * @returns {*}
 */
function onRelease(hammer, callback) {
  callback.inputHandler = function (event) {
    if (event.isFinal) {
      callback(event);
    }
  };
  return hammer.on("hammer.input", callback.inputHandler);
}

/**
 * Create the main frame for the Network.
 * This function is executed once when a Network object is created. The frame
 * contains a canvas, and this canvas contains all objects like the axis and
 * nodes.
 */
var Canvas = /*#__PURE__*/function () {
  /**
   * @param {object} body
   */
  function Canvas(body) {
    _classCallCheck(this, Canvas);
    this.body = body;
    this.pixelRatio = 1;
    this.cameraState = {};
    this.initialized = false;
    this.canvasViewCenter = {};
    this._cleanupCallbacks = [];
    this.options = {};
    this.defaultOptions = {
      autoResize: true,
      height: "100%",
      width: "100%"
    };
    _Object$assign(this.options, this.defaultOptions);
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(Canvas, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _this = this,
        _context;
      // bind the events
      this.body.emitter.once("resize", function (obj) {
        if (obj.width !== 0) {
          _this.body.view.translation.x = obj.width * 0.5;
        }
        if (obj.height !== 0) {
          _this.body.view.translation.y = obj.height * 0.5;
        }
      });
      this.body.emitter.on("setSize", _bindInstanceProperty$1(_context = this.setSize).call(_context, this));
      this.body.emitter.on("destroy", function () {
        _this.hammerFrame.destroy();
        _this.hammer.destroy();
        _this._cleanUp();
      });
    }

    /**
     * @param {object} options
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      var _this2 = this;
      if (options !== undefined) {
        var fields = ["width", "height", "autoResize"];
        selectiveDeepExtend(fields, this.options, options);
      }

      // Automatically adapt to changing size of the container element.
      this._cleanUp();
      if (this.options.autoResize === true) {
        var _context2;
        if (window.ResizeObserver) {
          // decent browsers, immediate reactions
          var observer = new ResizeObserver(function () {
            var changed = _this2.setSize();
            if (changed === true) {
              _this2.body.emitter.emit("_requestRedraw");
            }
          });
          var frame = this.frame;
          observer.observe(frame);
          this._cleanupCallbacks.push(function () {
            observer.unobserve(frame);
          });
        } else {
          // IE11, continous polling
          var resizeTimer = _setInterval(function () {
            var changed = _this2.setSize();
            if (changed === true) {
              _this2.body.emitter.emit("_requestRedraw");
            }
          }, 1000);
          this._cleanupCallbacks.push(function () {
            clearInterval(resizeTimer);
          });
        }

        // Automatically adapt to changing size of the browser.
        var resizeFunction = _bindInstanceProperty$1(_context2 = this._onResize).call(_context2, this);
        addEventListener$1(window, "resize", resizeFunction);
        this._cleanupCallbacks.push(function () {
          removeEventListener$1(window, "resize", resizeFunction);
        });
      }
    }

    /**
     * @private
     */
  }, {
    key: "_cleanUp",
    value: function _cleanUp() {
      var _context3, _context4, _context5;
      _forEachInstanceProperty(_context3 = _reverseInstanceProperty(_context4 = _spliceInstanceProperty(_context5 = this._cleanupCallbacks).call(_context5, 0)).call(_context4)).call(_context3, function (callback) {
        try {
          callback();
        } catch (error) {
          console.error(error);
        }
      });
    }

    /**
     * @private
     */
  }, {
    key: "_onResize",
    value: function _onResize() {
      this.setSize();
      this.body.emitter.emit("_redraw");
    }

    /**
     * Get and store the cameraState
     *
     * @param {number} [pixelRatio=this.pixelRatio]
     * @private
     */
  }, {
    key: "_getCameraState",
    value: function _getCameraState() {
      var pixelRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.pixelRatio;
      if (this.initialized === true) {
        this.cameraState.previousWidth = this.frame.canvas.width / pixelRatio;
        this.cameraState.previousHeight = this.frame.canvas.height / pixelRatio;
        this.cameraState.scale = this.body.view.scale;
        this.cameraState.position = this.DOMtoCanvas({
          x: 0.5 * this.frame.canvas.width / pixelRatio,
          y: 0.5 * this.frame.canvas.height / pixelRatio
        });
      }
    }

    /**
     * Set the cameraState
     *
     * @private
     */
  }, {
    key: "_setCameraState",
    value: function _setCameraState() {
      if (this.cameraState.scale !== undefined && this.frame.canvas.clientWidth !== 0 && this.frame.canvas.clientHeight !== 0 && this.pixelRatio !== 0 && this.cameraState.previousWidth > 0 && this.cameraState.previousHeight > 0) {
        var widthRatio = this.frame.canvas.width / this.pixelRatio / this.cameraState.previousWidth;
        var heightRatio = this.frame.canvas.height / this.pixelRatio / this.cameraState.previousHeight;
        var newScale = this.cameraState.scale;
        if (widthRatio != 1 && heightRatio != 1) {
          newScale = this.cameraState.scale * 0.5 * (widthRatio + heightRatio);
        } else if (widthRatio != 1) {
          newScale = this.cameraState.scale * widthRatio;
        } else if (heightRatio != 1) {
          newScale = this.cameraState.scale * heightRatio;
        }
        this.body.view.scale = newScale;
        // this comes from the view module.
        var currentViewCenter = this.DOMtoCanvas({
          x: 0.5 * this.frame.canvas.clientWidth,
          y: 0.5 * this.frame.canvas.clientHeight
        });
        var distanceFromCenter = {
          // offset from view, distance view has to change by these x and y to center the node
          x: currentViewCenter.x - this.cameraState.position.x,
          y: currentViewCenter.y - this.cameraState.position.y
        };
        this.body.view.translation.x += distanceFromCenter.x * this.body.view.scale;
        this.body.view.translation.y += distanceFromCenter.y * this.body.view.scale;
      }
    }

    /**
     *
     * @param {number|string} value
     * @returns {string}
     * @private
     */
  }, {
    key: "_prepareValue",
    value: function _prepareValue(value) {
      if (typeof value === "number") {
        return value + "px";
      } else if (typeof value === "string") {
        if (_indexOfInstanceProperty(value).call(value, "%") !== -1 || _indexOfInstanceProperty(value).call(value, "px") !== -1) {
          return value;
        } else if (_indexOfInstanceProperty(value).call(value, "%") === -1) {
          return value + "px";
        }
      }
      throw new Error("Could not use the value supplied for width or height:" + value);
    }

    /**
     * Create the HTML
     */
  }, {
    key: "_create",
    value: function _create() {
      // remove all elements from the container element.
      while (this.body.container.hasChildNodes()) {
        this.body.container.removeChild(this.body.container.firstChild);
      }
      this.frame = document.createElement("div");
      this.frame.className = "vis-network";
      this.frame.style.position = "relative";
      this.frame.style.overflow = "hidden";
      this.frame.tabIndex = 0; // tab index is required for keycharm to bind keystrokes to the div instead of the window

      //////////////////////////////////////////////////////////////////

      this.frame.canvas = document.createElement("canvas");
      this.frame.canvas.style.position = "relative";
      this.frame.appendChild(this.frame.canvas);
      if (!this.frame.canvas.getContext) {
        var noCanvas = document.createElement("DIV");
        noCanvas.style.color = "red";
        noCanvas.style.fontWeight = "bold";
        noCanvas.style.padding = "10px";
        noCanvas.innerText = "Error: your browser does not support HTML canvas";
        this.frame.canvas.appendChild(noCanvas);
      } else {
        this._setPixelRatio();
        this.setTransform();
      }

      // add the frame to the container element
      this.body.container.appendChild(this.frame);
      this.body.view.scale = 1;
      this.body.view.translation = {
        x: 0.5 * this.frame.canvas.clientWidth,
        y: 0.5 * this.frame.canvas.clientHeight
      };
      this._bindHammer();
    }

    /**
     * This function binds hammer, it can be repeated over and over due to the uniqueness check.
     *
     * @private
     */
  }, {
    key: "_bindHammer",
    value: function _bindHammer() {
      var _this3 = this;
      if (this.hammer !== undefined) {
        this.hammer.destroy();
      }
      this.drag = {};
      this.pinch = {};

      // init hammer
      this.hammer = new Hammer(this.frame.canvas);
      this.hammer.get("pinch").set({
        enable: true
      });
      // enable to get better response, todo: test on mobile.
      this.hammer.get("pan").set({
        threshold: 5,
        direction: Hammer.DIRECTION_ALL
      });
      onTouch(this.hammer, function (event) {
        _this3.body.eventListeners.onTouch(event);
      });
      this.hammer.on("tap", function (event) {
        _this3.body.eventListeners.onTap(event);
      });
      this.hammer.on("doubletap", function (event) {
        _this3.body.eventListeners.onDoubleTap(event);
      });
      this.hammer.on("press", function (event) {
        _this3.body.eventListeners.onHold(event);
      });
      this.hammer.on("panstart", function (event) {
        _this3.body.eventListeners.onDragStart(event);
      });
      this.hammer.on("panmove", function (event) {
        _this3.body.eventListeners.onDrag(event);
      });
      this.hammer.on("panend", function (event) {
        _this3.body.eventListeners.onDragEnd(event);
      });
      this.hammer.on("pinch", function (event) {
        _this3.body.eventListeners.onPinch(event);
      });

      // TODO: neatly cleanup these handlers when re-creating the Canvas, IF these are done with hammer, event.stopPropagation will not work?
      this.frame.canvas.addEventListener("wheel", function (event) {
        _this3.body.eventListeners.onMouseWheel(event);
      });
      this.frame.canvas.addEventListener("mousemove", function (event) {
        _this3.body.eventListeners.onMouseMove(event);
      });
      this.frame.canvas.addEventListener("contextmenu", function (event) {
        _this3.body.eventListeners.onContext(event);
      });
      this.hammerFrame = new Hammer(this.frame);
      onRelease(this.hammerFrame, function (event) {
        _this3.body.eventListeners.onRelease(event);
      });
    }

    /**
     * Set a new size for the network
     *
     * @param {string} width   Width in pixels or percentage (for example '800px'
     *                         or '50%')
     * @param {string} height  Height in pixels or percentage  (for example '400px'
     *                         or '30%')
     * @returns {boolean}
     */
  }, {
    key: "setSize",
    value: function setSize() {
      var width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.width;
      var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.options.height;
      width = this._prepareValue(width);
      height = this._prepareValue(height);
      var emitEvent = false;
      var oldWidth = this.frame.canvas.width;
      var oldHeight = this.frame.canvas.height;

      // update the pixel ratio
      //
      // NOTE: Comment in following is rather inconsistent; this is the ONLY place in the code
      //       where it is assumed that the pixel ratio could change at runtime.
      //       The only way I can think of this happening is a rotating screen or tablet; but then
      //       there should be a mechanism for reloading the data (TODO: check if this is present).
      //
      //       If the assumption is true (i.e. pixel ratio can change at runtime), then *all* usage
      //       of pixel ratio must be overhauled for this.
      //
      //       For the time being, I will humor the assumption here, and in the rest of the code assume it is
      //       constant.
      var previousRatio = this.pixelRatio; // we cache this because the camera state storage needs the old value
      this._setPixelRatio();
      if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) {
        this._getCameraState(previousRatio);
        this.frame.style.width = width;
        this.frame.style.height = height;
        this.frame.canvas.style.width = "100%";
        this.frame.canvas.style.height = "100%";
        this.frame.canvas.width = Math.round(this.frame.canvas.clientWidth * this.pixelRatio);
        this.frame.canvas.height = Math.round(this.frame.canvas.clientHeight * this.pixelRatio);
        this.options.width = width;
        this.options.height = height;
        this.canvasViewCenter = {
          x: 0.5 * this.frame.clientWidth,
          y: 0.5 * this.frame.clientHeight
        };
        emitEvent = true;
      } else {
        // this would adapt the width of the canvas to the width from 100% if and only if
        // there is a change.

        var newWidth = Math.round(this.frame.canvas.clientWidth * this.pixelRatio);
        var newHeight = Math.round(this.frame.canvas.clientHeight * this.pixelRatio);

        // store the camera if there is a change in size.
        if (this.frame.canvas.width !== newWidth || this.frame.canvas.height !== newHeight) {
          this._getCameraState(previousRatio);
        }
        if (this.frame.canvas.width !== newWidth) {
          this.frame.canvas.width = newWidth;
          emitEvent = true;
        }
        if (this.frame.canvas.height !== newHeight) {
          this.frame.canvas.height = newHeight;
          emitEvent = true;
        }
      }
      if (emitEvent === true) {
        this.body.emitter.emit("resize", {
          width: Math.round(this.frame.canvas.width / this.pixelRatio),
          height: Math.round(this.frame.canvas.height / this.pixelRatio),
          oldWidth: Math.round(oldWidth / this.pixelRatio),
          oldHeight: Math.round(oldHeight / this.pixelRatio)
        });

        // restore the camera on change.
        this._setCameraState();
      }

      // set initialized so the get and set camera will work from now on.
      this.initialized = true;
      return emitEvent;
    }

    /**
     *
     * @returns {CanvasRenderingContext2D}
     */
  }, {
    key: "getContext",
    value: function getContext() {
      return this.frame.canvas.getContext("2d");
    }

    /**
     * Determine the pixel ratio for various browsers.
     *
     * @returns {number}
     * @private
     */
  }, {
    key: "_determinePixelRatio",
    value: function _determinePixelRatio() {
      var ctx = this.getContext();
      if (ctx === undefined) {
        throw new Error("Could not get canvax context");
      }
      var numerator = 1;
      if (typeof window !== "undefined") {
        // (window !== undefined) doesn't work here!
        // Protection during unit tests, where 'window' can be missing
        numerator = window.devicePixelRatio || 1;
      }
      var denominator = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
      return numerator / denominator;
    }

    /**
     * Lazy determination of pixel ratio.
     *
     * @private
     */
  }, {
    key: "_setPixelRatio",
    value: function _setPixelRatio() {
      this.pixelRatio = this._determinePixelRatio();
    }

    /**
     * Set the transform in the contained context, based on its pixelRatio
     */
  }, {
    key: "setTransform",
    value: function setTransform() {
      var ctx = this.getContext();
      if (ctx === undefined) {
        throw new Error("Could not get canvax context");
      }
      ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0);
    }

    /**
     * Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to
     * the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon)
     *
     * @param {number} x
     * @returns {number}
     * @private
     */
  }, {
    key: "_XconvertDOMtoCanvas",
    value: function _XconvertDOMtoCanvas(x) {
      return (x - this.body.view.translation.x) / this.body.view.scale;
    }

    /**
     * Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to
     * the X coordinate in DOM-space (coordinate point in browser relative to the container div)
     *
     * @param {number} x
     * @returns {number}
     * @private
     */
  }, {
    key: "_XconvertCanvasToDOM",
    value: function _XconvertCanvasToDOM(x) {
      return x * this.body.view.scale + this.body.view.translation.x;
    }

    /**
     * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to
     * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon)
     *
     * @param {number} y
     * @returns {number}
     * @private
     */
  }, {
    key: "_YconvertDOMtoCanvas",
    value: function _YconvertDOMtoCanvas(y) {
      return (y - this.body.view.translation.y) / this.body.view.scale;
    }

    /**
     * Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to
     * the Y coordinate in DOM-space (coordinate point in browser relative to the container div)
     *
     * @param {number} y
     * @returns {number}
     * @private
     */
  }, {
    key: "_YconvertCanvasToDOM",
    value: function _YconvertCanvasToDOM(y) {
      return y * this.body.view.scale + this.body.view.translation.y;
    }

    /**
     * @param {point} pos
     * @returns {point}
     */
  }, {
    key: "canvasToDOM",
    value: function canvasToDOM(pos) {
      return {
        x: this._XconvertCanvasToDOM(pos.x),
        y: this._YconvertCanvasToDOM(pos.y)
      };
    }

    /**
     *
     * @param {point} pos
     * @returns {point}
     */
  }, {
    key: "DOMtoCanvas",
    value: function DOMtoCanvas(pos) {
      return {
        x: this._XconvertDOMtoCanvas(pos.x),
        y: this._YconvertDOMtoCanvas(pos.y)
      };
    }
  }]);
  return Canvas;
}();

/**
 * Validate the fit options, replace missing optional values by defaults etc.
 *
 * @param rawOptions - The raw options.
 * @param allNodeIds - All node ids that will be used if nodes are omitted in
 * the raw options.
 * @returns Options with everything filled in and validated.
 */
function normalizeFitOptions(rawOptions, allNodeIds) {
  var options = _Object$assign({
    nodes: allNodeIds,
    minZoomLevel: Number.MIN_VALUE,
    maxZoomLevel: 1
  }, rawOptions !== null && rawOptions !== void 0 ? rawOptions : {});
  if (!_Array$isArray(options.nodes)) {
    throw new TypeError("Nodes has to be an array of ids.");
  }
  if (options.nodes.length === 0) {
    options.nodes = allNodeIds;
  }
  if (!(typeof options.minZoomLevel === "number" && options.minZoomLevel > 0)) {
    throw new TypeError("Min zoom level has to be a number higher than zero.");
  }
  if (!(typeof options.maxZoomLevel === "number" && options.minZoomLevel <= options.maxZoomLevel)) {
    throw new TypeError("Max zoom level has to be a number higher than min zoom level.");
  }
  return options;
}

/**
 * The view
 */
var View = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Canvas} canvas
   */
  function View(body, canvas) {
    var _context,
      _this = this,
      _context2;
    _classCallCheck(this, View);
    this.body = body;
    this.canvas = canvas;
    this.animationSpeed = 1 / this.renderRefreshRate;
    this.animationEasingFunction = "easeInOutQuint";
    this.easingTime = 0;
    this.sourceScale = 0;
    this.targetScale = 0;
    this.sourceTranslation = 0;
    this.targetTranslation = 0;
    this.lockedOnNodeId = undefined;
    this.lockedOnNodeOffset = undefined;
    this.touchTime = 0;
    this.viewFunction = undefined;
    this.body.emitter.on("fit", _bindInstanceProperty$1(_context = this.fit).call(_context, this));
    this.body.emitter.on("animationFinished", function () {
      _this.body.emitter.emit("_stopRendering");
    });
    this.body.emitter.on("unlockNode", _bindInstanceProperty$1(_context2 = this.releaseNode).call(_context2, this));
  }

  /**
   *
   * @param {object} [options={}]
   */
  _createClass(View, [{
    key: "setOptions",
    value: function setOptions() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      this.options = options;
    }

    /**
     * This function zooms out to fit all data on screen based on amount of nodes
     *
     * @param {object} [options={{nodes=Array}}]
     * @param options
     * @param {boolean} [initialZoom=false]  | zoom based on fitted formula or range, true = fitted, default = false;
     */
  }, {
    key: "fit",
    value: function fit(options) {
      var initialZoom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      options = normalizeFitOptions(options, this.body.nodeIndices);
      var canvasWidth = this.canvas.frame.canvas.clientWidth;
      var canvasHeight = this.canvas.frame.canvas.clientHeight;
      var range;
      var zoomLevel;
      if (canvasWidth === 0 || canvasHeight === 0) {
        // There's no point in trying to fit into zero sized canvas. This could
        // potentially even result in invalid values being computed. For example
        // for network without nodes and zero sized canvas the zoom level would
        // end up being computed as 0/0 which results in NaN. In any other case
        // this would be 0/something which is again pointless to compute.
        zoomLevel = 1;
        range = NetworkUtil.getRange(this.body.nodes, options.nodes);
      } else if (initialZoom === true) {
        // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation.
        var positionDefined = 0;
        for (var nodeId in this.body.nodes) {
          if (Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) {
            var node = this.body.nodes[nodeId];
            if (node.predefinedPosition === true) {
              positionDefined += 1;
            }
          }
        }
        if (positionDefined > 0.5 * this.body.nodeIndices.length) {
          this.fit(options, false);
          return;
        }
        range = NetworkUtil.getRange(this.body.nodes, options.nodes);
        var numberOfNodes = this.body.nodeIndices.length;
        zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good.

        // correct for larger canvasses.
        var factor = Math.min(canvasWidth / 600, canvasHeight / 600);
        zoomLevel *= factor;
      } else {
        this.body.emitter.emit("_resizeNodes");
        range = NetworkUtil.getRange(this.body.nodes, options.nodes);
        var xDistance = Math.abs(range.maxX - range.minX) * 1.1;
        var yDistance = Math.abs(range.maxY - range.minY) * 1.1;
        var xZoomLevel = canvasWidth / xDistance;
        var yZoomLevel = canvasHeight / yDistance;
        zoomLevel = xZoomLevel <= yZoomLevel ? xZoomLevel : yZoomLevel;
      }
      if (zoomLevel > options.maxZoomLevel) {
        zoomLevel = options.maxZoomLevel;
      } else if (zoomLevel < options.minZoomLevel) {
        zoomLevel = options.minZoomLevel;
      }
      var center = NetworkUtil.findCenter(range);
      var animationOptions = {
        position: center,
        scale: zoomLevel,
        animation: options.animation
      };
      this.moveTo(animationOptions);
    }

    // animation

    /**
     * Center a node in view.
     *
     * @param {number} nodeId
     * @param {number} [options]
     */
  }, {
    key: "focus",
    value: function focus(nodeId) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      if (this.body.nodes[nodeId] !== undefined) {
        var nodePosition = {
          x: this.body.nodes[nodeId].x,
          y: this.body.nodes[nodeId].y
        };
        options.position = nodePosition;
        options.lockedOnNode = nodeId;
        this.moveTo(options);
      } else {
        console.error("Node: " + nodeId + " cannot be found.");
      }
    }

    /**
     *
     * @param {object} options  |  options.offset   = {x:number, y:number}   // offset from the center in DOM pixels
     *                          |  options.scale    = number                 // scale to move to
     *                          |  options.position = {x:number, y:number}   // position to move to
     *                          |  options.animation = {duration:number, easingFunction:String} || Boolean   // position to move to
     */
  }, {
    key: "moveTo",
    value: function moveTo(options) {
      if (options === undefined) {
        options = {};
        return;
      }
      if (options.offset != null) {
        if (options.offset.x != null) {
          // Coerce and verify that x is valid.
          options.offset.x = +options.offset.x;
          if (!_Number$isFinite(options.offset.x)) {
            throw new TypeError('The option "offset.x" has to be a finite number.');
          }
        } else {
          options.offset.x = 0;
        }
        if (options.offset.y != null) {
          // Coerce and verify that y is valid.
          options.offset.y = +options.offset.y;
          if (!_Number$isFinite(options.offset.y)) {
            throw new TypeError('The option "offset.y" has to be a finite number.');
          }
        } else {
          options.offset.x = 0;
        }
      } else {
        options.offset = {
          x: 0,
          y: 0
        };
      }
      if (options.position != null) {
        if (options.position.x != null) {
          // Coerce and verify that x is valid.
          options.position.x = +options.position.x;
          if (!_Number$isFinite(options.position.x)) {
            throw new TypeError('The option "position.x" has to be a finite number.');
          }
        } else {
          options.position.x = 0;
        }
        if (options.position.y != null) {
          // Coerce and verify that y is valid.
          options.position.y = +options.position.y;
          if (!_Number$isFinite(options.position.y)) {
            throw new TypeError('The option "position.y" has to be a finite number.');
          }
        } else {
          options.position.x = 0;
        }
      } else {
        options.position = this.getViewPosition();
      }
      if (options.scale != null) {
        // Coerce and verify that the scale is valid.
        options.scale = +options.scale;
        if (!(options.scale > 0)) {
          throw new TypeError('The option "scale" has to be a number greater than zero.');
        }
      } else {
        options.scale = this.body.view.scale;
      }
      if (options.animation === undefined) {
        options.animation = {
          duration: 0
        };
      }
      if (options.animation === false) {
        options.animation = {
          duration: 0
        };
      }
      if (options.animation === true) {
        options.animation = {};
      }
      if (options.animation.duration === undefined) {
        options.animation.duration = 1000;
      } // default duration
      if (options.animation.easingFunction === undefined) {
        options.animation.easingFunction = "easeInOutQuad";
      } // default easing function

      this.animateView(options);
    }

    /**
     *
     * @param {object} options  |  options.offset   = {x:number, y:number}   // offset from the center in DOM pixels
     *                          |  options.time     = number                 // animation time in milliseconds
     *                          |  options.scale    = number                 // scale to animate to
     *                          |  options.position = {x:number, y:number}   // position to animate to
     *                          |  options.easingFunction = String           // linear, easeInQuad, easeOutQuad, easeInOutQuad,
     *                                                                       // easeInCubic, easeOutCubic, easeInOutCubic,
     *                                                                       // easeInQuart, easeOutQuart, easeInOutQuart,
     *                                                                       // easeInQuint, easeOutQuint, easeInOutQuint
     */
  }, {
    key: "animateView",
    value: function animateView(options) {
      if (options === undefined) {
        return;
      }
      this.animationEasingFunction = options.animation.easingFunction;
      // release if something focussed on the node
      this.releaseNode();
      if (options.locked === true) {
        this.lockedOnNodeId = options.lockedOnNode;
        this.lockedOnNodeOffset = options.offset;
      }

      // forcefully complete the old animation if it was still running
      if (this.easingTime != 0) {
        this._transitionRedraw(true); // by setting easingtime to 1, we finish the animation.
      }

      this.sourceScale = this.body.view.scale;
      this.sourceTranslation = this.body.view.translation;
      this.targetScale = options.scale;

      // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw
      // but at least then we'll have the target transition
      this.body.view.scale = this.targetScale;
      var viewCenter = this.canvas.DOMtoCanvas({
        x: 0.5 * this.canvas.frame.canvas.clientWidth,
        y: 0.5 * this.canvas.frame.canvas.clientHeight
      });
      var distanceFromCenter = {
        // offset from view, distance view has to change by these x and y to center the node
        x: viewCenter.x - options.position.x,
        y: viewCenter.y - options.position.y
      };
      this.targetTranslation = {
        x: this.sourceTranslation.x + distanceFromCenter.x * this.targetScale + options.offset.x,
        y: this.sourceTranslation.y + distanceFromCenter.y * this.targetScale + options.offset.y
      };

      // if the time is set to 0, don't do an animation
      if (options.animation.duration === 0) {
        if (this.lockedOnNodeId != undefined) {
          var _context3;
          this.viewFunction = _bindInstanceProperty$1(_context3 = this._lockedRedraw).call(_context3, this);
          this.body.emitter.on("initRedraw", this.viewFunction);
        } else {
          this.body.view.scale = this.targetScale;
          this.body.view.translation = this.targetTranslation;
          this.body.emitter.emit("_requestRedraw");
        }
      } else {
        var _context4;
        this.animationSpeed = 1 / (60 * options.animation.duration * 0.001) || 1 / 60; // 60 for 60 seconds, 0.001 for milli's
        this.animationEasingFunction = options.animation.easingFunction;
        this.viewFunction = _bindInstanceProperty$1(_context4 = this._transitionRedraw).call(_context4, this);
        this.body.emitter.on("initRedraw", this.viewFunction);
        this.body.emitter.emit("_startRendering");
      }
    }

    /**
     * used to animate smoothly by hijacking the redraw function.
     *
     * @private
     */
  }, {
    key: "_lockedRedraw",
    value: function _lockedRedraw() {
      var nodePosition = {
        x: this.body.nodes[this.lockedOnNodeId].x,
        y: this.body.nodes[this.lockedOnNodeId].y
      };
      var viewCenter = this.canvas.DOMtoCanvas({
        x: 0.5 * this.canvas.frame.canvas.clientWidth,
        y: 0.5 * this.canvas.frame.canvas.clientHeight
      });
      var distanceFromCenter = {
        // offset from view, distance view has to change by these x and y to center the node
        x: viewCenter.x - nodePosition.x,
        y: viewCenter.y - nodePosition.y
      };
      var sourceTranslation = this.body.view.translation;
      var targetTranslation = {
        x: sourceTranslation.x + distanceFromCenter.x * this.body.view.scale + this.lockedOnNodeOffset.x,
        y: sourceTranslation.y + distanceFromCenter.y * this.body.view.scale + this.lockedOnNodeOffset.y
      };
      this.body.view.translation = targetTranslation;
    }

    /**
     * Resets state of a locked on Node
     */
  }, {
    key: "releaseNode",
    value: function releaseNode() {
      if (this.lockedOnNodeId !== undefined && this.viewFunction !== undefined) {
        this.body.emitter.off("initRedraw", this.viewFunction);
        this.lockedOnNodeId = undefined;
        this.lockedOnNodeOffset = undefined;
      }
    }

    /**
     * @param {boolean} [finished=false]
     * @private
     */
  }, {
    key: "_transitionRedraw",
    value: function _transitionRedraw() {
      var finished = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      this.easingTime += this.animationSpeed;
      this.easingTime = finished === true ? 1.0 : this.easingTime;
      var progress = easingFunctions[this.animationEasingFunction](this.easingTime);
      this.body.view.scale = this.sourceScale + (this.targetScale - this.sourceScale) * progress;
      this.body.view.translation = {
        x: this.sourceTranslation.x + (this.targetTranslation.x - this.sourceTranslation.x) * progress,
        y: this.sourceTranslation.y + (this.targetTranslation.y - this.sourceTranslation.y) * progress
      };

      // cleanup
      if (this.easingTime >= 1.0) {
        this.body.emitter.off("initRedraw", this.viewFunction);
        this.easingTime = 0;
        if (this.lockedOnNodeId != undefined) {
          var _context5;
          this.viewFunction = _bindInstanceProperty$1(_context5 = this._lockedRedraw).call(_context5, this);
          this.body.emitter.on("initRedraw", this.viewFunction);
        }
        this.body.emitter.emit("animationFinished");
      }
    }

    /**
     *
     * @returns {number}
     */
  }, {
    key: "getScale",
    value: function getScale() {
      return this.body.view.scale;
    }

    /**
     *
     * @returns {{x: number, y: number}}
     */
  }, {
    key: "getViewPosition",
    value: function getViewPosition() {
      return this.canvas.DOMtoCanvas({
        x: 0.5 * this.canvas.frame.canvas.clientWidth,
        y: 0.5 * this.canvas.frame.canvas.clientHeight
      });
    }
  }]);
  return View;
}();

/**
 * Created by Alex on 11/6/2014.
 */
function keycharm(options) {
  var preventDefault = options && options.preventDefault || false;

  var container = options && options.container || window;

  var _exportFunctions = {};
  var _bound = {keydown:{}, keyup:{}};
  var _keys = {};
  var i;

  // a - z
  for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};}
  // A - Z
  for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};}
  // 0 - 9
  for (i = 0;  i <= 9;   i++) {_keys['' + i] = {code:48 + i, shift: false};}
  // F1 - F12
  for (i = 1;  i <= 12;   i++) {_keys['F' + i] = {code:111 + i, shift: false};}
  // num0 - num9
  for (i = 0;  i <= 9;   i++) {_keys['num' + i] = {code:96 + i, shift: false};}

  // numpad misc
  _keys['num*'] = {code:106, shift: false};
  _keys['num+'] = {code:107, shift: false};
  _keys['num-'] = {code:109, shift: false};
  _keys['num/'] = {code:111, shift: false};
  _keys['num.'] = {code:110, shift: false};
  // arrows
  _keys['left']  = {code:37, shift: false};
  _keys['up']    = {code:38, shift: false};
  _keys['right'] = {code:39, shift: false};
  _keys['down']  = {code:40, shift: false};
  // extra keys
  _keys['space'] = {code:32, shift: false};
  _keys['enter'] = {code:13, shift: false};
  _keys['shift'] = {code:16, shift: undefined};
  _keys['esc']   = {code:27, shift: false};
  _keys['backspace'] = {code:8, shift: false};
  _keys['tab']       = {code:9, shift: false};
  _keys['ctrl']      = {code:17, shift: false};
  _keys['alt']       = {code:18, shift: false};
  _keys['delete']    = {code:46, shift: false};
  _keys['pageup']    = {code:33, shift: false};
  _keys['pagedown']  = {code:34, shift: false};
  // symbols
  _keys['=']     = {code:187, shift: false};
  _keys['-']     = {code:189, shift: false};
  _keys[']']     = {code:221, shift: false};
  _keys['[']     = {code:219, shift: false};



  var down = function(event) {handleEvent(event,'keydown');};
  var up = function(event) {handleEvent(event,'keyup');};

  // handle the actualy bound key with the event
  var handleEvent = function(event,type) {
    if (_bound[type][event.keyCode] !== undefined) {
      var bound = _bound[type][event.keyCode];
      for (var i = 0; i < bound.length; i++) {
        if (bound[i].shift === undefined) {
          bound[i].fn(event);
        }
        else if (bound[i].shift == true && event.shiftKey == true) {
          bound[i].fn(event);
        }
        else if (bound[i].shift == false && event.shiftKey == false) {
          bound[i].fn(event);
        }
      }

      if (preventDefault == true) {
        event.preventDefault();
      }
    }
  };

  // bind a key to a callback
  _exportFunctions.bind = function(key, callback, type) {
    if (type === undefined) {
      type = 'keydown';
    }
    if (_keys[key] === undefined) {
      throw new Error("unsupported key: " + key);
    }
    if (_bound[type][_keys[key].code] === undefined) {
      _bound[type][_keys[key].code] = [];
    }
    _bound[type][_keys[key].code].push({fn:callback, shift:_keys[key].shift});
  };


  // bind all keys to a call back (demo purposes)
  _exportFunctions.bindAll = function(callback, type) {
    if (type === undefined) {
      type = 'keydown';
    }
    for (var key in _keys) {
      if (_keys.hasOwnProperty(key)) {
        _exportFunctions.bind(key,callback,type);
      }
    }
  };

  // get the key label from an event
  _exportFunctions.getKey = function(event) {
    for (var key in _keys) {
      if (_keys.hasOwnProperty(key)) {
        if (event.shiftKey == true && _keys[key].shift == true && event.keyCode == _keys[key].code) {
          return key;
        }
        else if (event.shiftKey == false && _keys[key].shift == false && event.keyCode == _keys[key].code) {
          return key;
        }
        else if (event.keyCode == _keys[key].code && key == 'shift') {
          return key;
        }
      }
    }
    return "unknown key, currently not supported";
  };

  // unbind either a specific callback from a key or all of them (by leaving callback undefined)
  _exportFunctions.unbind = function(key, callback, type) {
    if (type === undefined) {
      type = 'keydown';
    }
    if (_keys[key] === undefined) {
      throw new Error("unsupported key: " + key);
    }
    if (callback !== undefined) {
      var newBindings = [];
      var bound = _bound[type][_keys[key].code];
      if (bound !== undefined) {
        for (var i = 0; i < bound.length; i++) {
          if (!(bound[i].fn == callback && bound[i].shift == _keys[key].shift)) {
            newBindings.push(_bound[type][_keys[key].code][i]);
          }
        }
      }
      _bound[type][_keys[key].code] = newBindings;
    }
    else {
      _bound[type][_keys[key].code] = [];
    }
  };

  // reset all bound variables.
  _exportFunctions.reset = function() {
    _bound = {keydown:{}, keyup:{}};
  };

  // unbind all listeners and reset all variables.
  _exportFunctions.destroy = function() {
    _bound = {keydown:{}, keyup:{}};
    container.removeEventListener('keydown', down, true);
    container.removeEventListener('keyup', up, true);
  };

  // create listeners.
  container.addEventListener('keydown',down,true);
  container.addEventListener('keyup',up,true);

  // return the public functions.
  return _exportFunctions;
}

/**
 * Navigation Handler
 */
var NavigationHandler = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Canvas} canvas
   */
  function NavigationHandler(body, canvas) {
    var _this = this;
    _classCallCheck(this, NavigationHandler);
    this.body = body;
    this.canvas = canvas;
    this.iconsCreated = false;
    this.navigationHammers = [];
    this.boundFunctions = {};
    this.touchTime = 0;
    this.activated = false;
    this.body.emitter.on("activate", function () {
      _this.activated = true;
      _this.configureKeyboardBindings();
    });
    this.body.emitter.on("deactivate", function () {
      _this.activated = false;
      _this.configureKeyboardBindings();
    });
    this.body.emitter.on("destroy", function () {
      if (_this.keycharm !== undefined) {
        _this.keycharm.destroy();
      }
    });
    this.options = {};
  }

  /**
   *
   * @param {object} options
   */
  _createClass(NavigationHandler, [{
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        this.options = options;
        this.create();
      }
    }

    /**
     * Creates or refreshes navigation and sets key bindings
     */
  }, {
    key: "create",
    value: function create() {
      if (this.options.navigationButtons === true) {
        if (this.iconsCreated === false) {
          this.loadNavigationElements();
        }
      } else if (this.iconsCreated === true) {
        this.cleanNavigation();
      }
      this.configureKeyboardBindings();
    }

    /**
     * Cleans up previous navigation items
     */
  }, {
    key: "cleanNavigation",
    value: function cleanNavigation() {
      // clean hammer bindings
      if (this.navigationHammers.length != 0) {
        for (var i = 0; i < this.navigationHammers.length; i++) {
          this.navigationHammers[i].destroy();
        }
        this.navigationHammers = [];
      }

      // clean up previous navigation items
      if (this.navigationDOM && this.navigationDOM["wrapper"] && this.navigationDOM["wrapper"].parentNode) {
        this.navigationDOM["wrapper"].parentNode.removeChild(this.navigationDOM["wrapper"]);
      }
      this.iconsCreated = false;
    }

    /**
     * Creation of the navigation controls nodes. They are drawn over the rest of the nodes and are not affected by scale and translation
     * they have a triggerFunction which is called on click. If the position of the navigation controls is dependent
     * on this.frame.canvas.clientWidth or this.frame.canvas.clientHeight, we flag horizontalAlignLeft and verticalAlignTop false.
     * This means that the location will be corrected by the _relocateNavigation function on a size change of the canvas.
     *
     * @private
     */
  }, {
    key: "loadNavigationElements",
    value: function loadNavigationElements() {
      var _this2 = this;
      this.cleanNavigation();
      this.navigationDOM = {};
      var navigationDivs = ["up", "down", "left", "right", "zoomIn", "zoomOut", "zoomExtends"];
      var navigationDivActions = ["_moveUp", "_moveDown", "_moveLeft", "_moveRight", "_zoomIn", "_zoomOut", "_fit"];
      this.navigationDOM["wrapper"] = document.createElement("div");
      this.navigationDOM["wrapper"].className = "vis-navigation";
      this.canvas.frame.appendChild(this.navigationDOM["wrapper"]);
      for (var i = 0; i < navigationDivs.length; i++) {
        this.navigationDOM[navigationDivs[i]] = document.createElement("div");
        this.navigationDOM[navigationDivs[i]].className = "vis-button vis-" + navigationDivs[i];
        this.navigationDOM["wrapper"].appendChild(this.navigationDOM[navigationDivs[i]]);
        var hammer = new Hammer(this.navigationDOM[navigationDivs[i]]);
        if (navigationDivActions[i] === "_fit") {
          var _context;
          onTouch(hammer, _bindInstanceProperty$1(_context = this._fit).call(_context, this));
        } else {
          var _context2;
          onTouch(hammer, _bindInstanceProperty$1(_context2 = this.bindToRedraw).call(_context2, this, navigationDivActions[i]));
        }
        this.navigationHammers.push(hammer);
      }

      // use a hammer for the release so we do not require the one used in the rest of the network
      // the one the rest uses can be overloaded by the manipulation system.
      var hammerFrame = new Hammer(this.canvas.frame);
      onRelease(hammerFrame, function () {
        _this2._stopMovement();
      });
      this.navigationHammers.push(hammerFrame);
      this.iconsCreated = true;
    }

    /**
     *
     * @param {string} action
     */
  }, {
    key: "bindToRedraw",
    value: function bindToRedraw(action) {
      if (this.boundFunctions[action] === undefined) {
        var _context3;
        this.boundFunctions[action] = _bindInstanceProperty$1(_context3 = this[action]).call(_context3, this);
        this.body.emitter.on("initRedraw", this.boundFunctions[action]);
        this.body.emitter.emit("_startRendering");
      }
    }

    /**
     *
     * @param {string} action
     */
  }, {
    key: "unbindFromRedraw",
    value: function unbindFromRedraw(action) {
      if (this.boundFunctions[action] !== undefined) {
        this.body.emitter.off("initRedraw", this.boundFunctions[action]);
        this.body.emitter.emit("_stopRendering");
        delete this.boundFunctions[action];
      }
    }

    /**
     * this stops all movement induced by the navigation buttons
     *
     * @private
     */
  }, {
    key: "_fit",
    value: function _fit() {
      if (new Date().valueOf() - this.touchTime > 700) {
        // TODO: fix ugly hack to avoid hammer's double fireing of event (because we use release?)
        this.body.emitter.emit("fit", {
          duration: 700
        });
        this.touchTime = new Date().valueOf();
      }
    }

    /**
     * this stops all movement induced by the navigation buttons
     *
     * @private
     */
  }, {
    key: "_stopMovement",
    value: function _stopMovement() {
      for (var boundAction in this.boundFunctions) {
        if (Object.prototype.hasOwnProperty.call(this.boundFunctions, boundAction)) {
          this.body.emitter.off("initRedraw", this.boundFunctions[boundAction]);
          this.body.emitter.emit("_stopRendering");
        }
      }
      this.boundFunctions = {};
    }
    /**
     *
     * @private
     */
  }, {
    key: "_moveUp",
    value: function _moveUp() {
      this.body.view.translation.y += this.options.keyboard.speed.y;
    }
    /**
     *
     * @private
     */
  }, {
    key: "_moveDown",
    value: function _moveDown() {
      this.body.view.translation.y -= this.options.keyboard.speed.y;
    }
    /**
     *
     * @private
     */
  }, {
    key: "_moveLeft",
    value: function _moveLeft() {
      this.body.view.translation.x += this.options.keyboard.speed.x;
    }
    /**
     *
     * @private
     */
  }, {
    key: "_moveRight",
    value: function _moveRight() {
      this.body.view.translation.x -= this.options.keyboard.speed.x;
    }
    /**
     *
     * @private
     */
  }, {
    key: "_zoomIn",
    value: function _zoomIn() {
      var scaleOld = this.body.view.scale;
      var scale = this.body.view.scale * (1 + this.options.keyboard.speed.zoom);
      var translation = this.body.view.translation;
      var scaleFrac = scale / scaleOld;
      var tx = (1 - scaleFrac) * this.canvas.canvasViewCenter.x + translation.x * scaleFrac;
      var ty = (1 - scaleFrac) * this.canvas.canvasViewCenter.y + translation.y * scaleFrac;
      this.body.view.scale = scale;
      this.body.view.translation = {
        x: tx,
        y: ty
      };
      this.body.emitter.emit("zoom", {
        direction: "+",
        scale: this.body.view.scale,
        pointer: null
      });
    }

    /**
     *
     * @private
     */
  }, {
    key: "_zoomOut",
    value: function _zoomOut() {
      var scaleOld = this.body.view.scale;
      var scale = this.body.view.scale / (1 + this.options.keyboard.speed.zoom);
      var translation = this.body.view.translation;
      var scaleFrac = scale / scaleOld;
      var tx = (1 - scaleFrac) * this.canvas.canvasViewCenter.x + translation.x * scaleFrac;
      var ty = (1 - scaleFrac) * this.canvas.canvasViewCenter.y + translation.y * scaleFrac;
      this.body.view.scale = scale;
      this.body.view.translation = {
        x: tx,
        y: ty
      };
      this.body.emitter.emit("zoom", {
        direction: "-",
        scale: this.body.view.scale,
        pointer: null
      });
    }

    /**
     * bind all keys using keycharm.
     */
  }, {
    key: "configureKeyboardBindings",
    value: function configureKeyboardBindings() {
      var _this3 = this;
      if (this.keycharm !== undefined) {
        this.keycharm.destroy();
      }
      if (this.options.keyboard.enabled === true) {
        if (this.options.keyboard.bindToWindow === true) {
          this.keycharm = keycharm({
            container: window,
            preventDefault: true
          });
        } else {
          this.keycharm = keycharm({
            container: this.canvas.frame,
            preventDefault: true
          });
        }
        this.keycharm.reset();
        if (this.activated === true) {
          var _context4, _context5, _context6, _context7, _context8, _context9, _context10, _context11, _context12, _context13, _context14, _context15, _context16, _context17, _context18, _context19, _context20, _context21, _context22, _context23, _context24, _context25, _context26, _context27;
          _bindInstanceProperty$1(_context4 = this.keycharm).call(_context4, "up", function () {
            _this3.bindToRedraw("_moveUp");
          }, "keydown");
          _bindInstanceProperty$1(_context5 = this.keycharm).call(_context5, "down", function () {
            _this3.bindToRedraw("_moveDown");
          }, "keydown");
          _bindInstanceProperty$1(_context6 = this.keycharm).call(_context6, "left", function () {
            _this3.bindToRedraw("_moveLeft");
          }, "keydown");
          _bindInstanceProperty$1(_context7 = this.keycharm).call(_context7, "right", function () {
            _this3.bindToRedraw("_moveRight");
          }, "keydown");
          _bindInstanceProperty$1(_context8 = this.keycharm).call(_context8, "=", function () {
            _this3.bindToRedraw("_zoomIn");
          }, "keydown");
          _bindInstanceProperty$1(_context9 = this.keycharm).call(_context9, "num+", function () {
            _this3.bindToRedraw("_zoomIn");
          }, "keydown");
          _bindInstanceProperty$1(_context10 = this.keycharm).call(_context10, "num-", function () {
            _this3.bindToRedraw("_zoomOut");
          }, "keydown");
          _bindInstanceProperty$1(_context11 = this.keycharm).call(_context11, "-", function () {
            _this3.bindToRedraw("_zoomOut");
          }, "keydown");
          _bindInstanceProperty$1(_context12 = this.keycharm).call(_context12, "[", function () {
            _this3.bindToRedraw("_zoomOut");
          }, "keydown");
          _bindInstanceProperty$1(_context13 = this.keycharm).call(_context13, "]", function () {
            _this3.bindToRedraw("_zoomIn");
          }, "keydown");
          _bindInstanceProperty$1(_context14 = this.keycharm).call(_context14, "pageup", function () {
            _this3.bindToRedraw("_zoomIn");
          }, "keydown");
          _bindInstanceProperty$1(_context15 = this.keycharm).call(_context15, "pagedown", function () {
            _this3.bindToRedraw("_zoomOut");
          }, "keydown");
          _bindInstanceProperty$1(_context16 = this.keycharm).call(_context16, "up", function () {
            _this3.unbindFromRedraw("_moveUp");
          }, "keyup");
          _bindInstanceProperty$1(_context17 = this.keycharm).call(_context17, "down", function () {
            _this3.unbindFromRedraw("_moveDown");
          }, "keyup");
          _bindInstanceProperty$1(_context18 = this.keycharm).call(_context18, "left", function () {
            _this3.unbindFromRedraw("_moveLeft");
          }, "keyup");
          _bindInstanceProperty$1(_context19 = this.keycharm).call(_context19, "right", function () {
            _this3.unbindFromRedraw("_moveRight");
          }, "keyup");
          _bindInstanceProperty$1(_context20 = this.keycharm).call(_context20, "=", function () {
            _this3.unbindFromRedraw("_zoomIn");
          }, "keyup");
          _bindInstanceProperty$1(_context21 = this.keycharm).call(_context21, "num+", function () {
            _this3.unbindFromRedraw("_zoomIn");
          }, "keyup");
          _bindInstanceProperty$1(_context22 = this.keycharm).call(_context22, "num-", function () {
            _this3.unbindFromRedraw("_zoomOut");
          }, "keyup");
          _bindInstanceProperty$1(_context23 = this.keycharm).call(_context23, "-", function () {
            _this3.unbindFromRedraw("_zoomOut");
          }, "keyup");
          _bindInstanceProperty$1(_context24 = this.keycharm).call(_context24, "[", function () {
            _this3.unbindFromRedraw("_zoomOut");
          }, "keyup");
          _bindInstanceProperty$1(_context25 = this.keycharm).call(_context25, "]", function () {
            _this3.unbindFromRedraw("_zoomIn");
          }, "keyup");
          _bindInstanceProperty$1(_context26 = this.keycharm).call(_context26, "pageup", function () {
            _this3.unbindFromRedraw("_zoomIn");
          }, "keyup");
          _bindInstanceProperty$1(_context27 = this.keycharm).call(_context27, "pagedown", function () {
            _this3.unbindFromRedraw("_zoomOut");
          }, "keyup");
        }
      }
    }
  }]);
  return NavigationHandler;
}();

function _createForOfIteratorHelper$4(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray$4(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$4(o, minLen) { var _context15; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$4(o, minLen); var n = _sliceInstanceProperty(_context15 = Object.prototype.toString.call(o)).call(_context15, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$4(o, minLen); }
function _arrayLikeToArray$4(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

/**
 * Handler for interactions
 */
var InteractionHandler = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Canvas} canvas
   * @param {SelectionHandler} selectionHandler
   */
  function InteractionHandler(body, canvas, selectionHandler) {
    var _context, _context2, _context3, _context4, _context5, _context6, _context7, _context8, _context9, _context10, _context11, _context12, _context13;
    _classCallCheck(this, InteractionHandler);
    this.body = body;
    this.canvas = canvas;
    this.selectionHandler = selectionHandler;
    this.navigationHandler = new NavigationHandler(body, canvas);

    // bind the events from hammer to functions in this object
    this.body.eventListeners.onTap = _bindInstanceProperty$1(_context = this.onTap).call(_context, this);
    this.body.eventListeners.onTouch = _bindInstanceProperty$1(_context2 = this.onTouch).call(_context2, this);
    this.body.eventListeners.onDoubleTap = _bindInstanceProperty$1(_context3 = this.onDoubleTap).call(_context3, this);
    this.body.eventListeners.onHold = _bindInstanceProperty$1(_context4 = this.onHold).call(_context4, this);
    this.body.eventListeners.onDragStart = _bindInstanceProperty$1(_context5 = this.onDragStart).call(_context5, this);
    this.body.eventListeners.onDrag = _bindInstanceProperty$1(_context6 = this.onDrag).call(_context6, this);
    this.body.eventListeners.onDragEnd = _bindInstanceProperty$1(_context7 = this.onDragEnd).call(_context7, this);
    this.body.eventListeners.onMouseWheel = _bindInstanceProperty$1(_context8 = this.onMouseWheel).call(_context8, this);
    this.body.eventListeners.onPinch = _bindInstanceProperty$1(_context9 = this.onPinch).call(_context9, this);
    this.body.eventListeners.onMouseMove = _bindInstanceProperty$1(_context10 = this.onMouseMove).call(_context10, this);
    this.body.eventListeners.onRelease = _bindInstanceProperty$1(_context11 = this.onRelease).call(_context11, this);
    this.body.eventListeners.onContext = _bindInstanceProperty$1(_context12 = this.onContext).call(_context12, this);
    this.touchTime = 0;
    this.drag = {};
    this.pinch = {};
    this.popup = undefined;
    this.popupObj = undefined;
    this.popupTimer = undefined;
    this.body.functions.getPointer = _bindInstanceProperty$1(_context13 = this.getPointer).call(_context13, this);
    this.options = {};
    this.defaultOptions = {
      dragNodes: true,
      dragView: true,
      hover: false,
      keyboard: {
        enabled: false,
        speed: {
          x: 10,
          y: 10,
          zoom: 0.02
        },
        bindToWindow: true,
        autoFocus: true
      },
      navigationButtons: false,
      tooltipDelay: 300,
      zoomView: true,
      zoomSpeed: 1
    };
    _Object$assign(this.options, this.defaultOptions);
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(InteractionHandler, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _this = this;
      this.body.emitter.on("destroy", function () {
        clearTimeout(_this.popupTimer);
        delete _this.body.functions.getPointer;
      });
    }

    /**
     *
     * @param {object} options
     */
  }, {
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        // extend all but the values in fields
        var fields = ["hideEdgesOnDrag", "hideEdgesOnZoom", "hideNodesOnDrag", "keyboard", "multiselect", "selectable", "selectConnectedEdges"];
        selectiveNotDeepExtend(fields, this.options, options);

        // merge the keyboard options in.
        mergeOptions(this.options, options, "keyboard");
        if (options.tooltip) {
          _Object$assign(this.options.tooltip, options.tooltip);
          if (options.tooltip.color) {
            this.options.tooltip.color = parseColor(options.tooltip.color);
          }
        }
      }
      this.navigationHandler.setOptions(this.options);
    }

    /**
     * Get the pointer location from a touch location
     *
     * @param {{x: number, y: number}} touch
     * @returns {{x: number, y: number}} pointer
     * @private
     */
  }, {
    key: "getPointer",
    value: function getPointer(touch) {
      return {
        x: touch.x - getAbsoluteLeft(this.canvas.frame.canvas),
        y: touch.y - getAbsoluteTop(this.canvas.frame.canvas)
      };
    }

    /**
     * On start of a touch gesture, store the pointer
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "onTouch",
    value: function onTouch(event) {
      if (new Date().valueOf() - this.touchTime > 50) {
        this.drag.pointer = this.getPointer(event.center);
        this.drag.pinched = false;
        this.pinch.scale = this.body.view.scale;
        // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame)
        this.touchTime = new Date().valueOf();
      }
    }

    /**
     * handle tap/click event: select/unselect a node
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onTap",
    value: function onTap(event) {
      var pointer = this.getPointer(event.center);
      var multiselect = this.selectionHandler.options.multiselect && (event.changedPointers[0].ctrlKey || event.changedPointers[0].metaKey);
      this.checkSelectionChanges(pointer, multiselect);
      this.selectionHandler.commitAndEmit(pointer, event);
      this.selectionHandler.generateClickEvent("click", event, pointer);
    }

    /**
     * handle doubletap event
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onDoubleTap",
    value: function onDoubleTap(event) {
      var pointer = this.getPointer(event.center);
      this.selectionHandler.generateClickEvent("doubleClick", event, pointer);
    }

    /**
     * handle long tap event: multi select nodes
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onHold",
    value: function onHold(event) {
      var pointer = this.getPointer(event.center);
      var multiselect = this.selectionHandler.options.multiselect;
      this.checkSelectionChanges(pointer, multiselect);
      this.selectionHandler.commitAndEmit(pointer, event);
      this.selectionHandler.generateClickEvent("click", event, pointer);
      this.selectionHandler.generateClickEvent("hold", event, pointer);
    }

    /**
     * handle the release of the screen
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onRelease",
    value: function onRelease(event) {
      if (new Date().valueOf() - this.touchTime > 10) {
        var pointer = this.getPointer(event.center);
        this.selectionHandler.generateClickEvent("release", event, pointer);
        // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame)
        this.touchTime = new Date().valueOf();
      }
    }

    /**
     *
     * @param {Event} event
     */
  }, {
    key: "onContext",
    value: function onContext(event) {
      var pointer = this.getPointer({
        x: event.clientX,
        y: event.clientY
      });
      this.selectionHandler.generateClickEvent("oncontext", event, pointer);
    }

    /**
     * Select and deselect nodes depending current selection change.
     *
     * @param {{x: number, y: number}} pointer
     * @param {boolean} [add=false]
     */
  }, {
    key: "checkSelectionChanges",
    value: function checkSelectionChanges(pointer) {
      var add = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      if (add === true) {
        this.selectionHandler.selectAdditionalOnPoint(pointer);
      } else {
        this.selectionHandler.selectOnPoint(pointer);
      }
    }

    /**
     * Remove all node and edge id's from the first set that are present in the second one.
     *
     * @param {{nodes: Array.<Node>, edges: Array.<vis.Edge>}} firstSet
     * @param {{nodes: Array.<Node>, edges: Array.<vis.Edge>}} secondSet
     * @returns {{nodes: Array.<Node>, edges: Array.<vis.Edge>}}
     * @private
     */
  }, {
    key: "_determineDifference",
    value: function _determineDifference(firstSet, secondSet) {
      var arrayDiff = function arrayDiff(firstArr, secondArr) {
        var result = [];
        for (var i = 0; i < firstArr.length; i++) {
          var value = firstArr[i];
          if (_indexOfInstanceProperty(secondArr).call(secondArr, value) === -1) {
            result.push(value);
          }
        }
        return result;
      };
      return {
        nodes: arrayDiff(firstSet.nodes, secondSet.nodes),
        edges: arrayDiff(firstSet.edges, secondSet.edges)
      };
    }

    /**
     * This function is called by onDragStart.
     * It is separated out because we can then overload it for the datamanipulation system.
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onDragStart",
    value: function onDragStart(event) {
      // if already dragging, do not start
      // this can happen on touch screens with multiple fingers
      if (this.drag.dragging) {
        return;
      }

      //in case the touch event was triggered on an external div, do the initial touch now.
      if (this.drag.pointer === undefined) {
        this.onTouch(event);
      }

      // note: drag.pointer is set in onTouch to get the initial touch location
      var node = this.selectionHandler.getNodeAt(this.drag.pointer);
      this.drag.dragging = true;
      this.drag.selection = [];
      this.drag.translation = _Object$assign({}, this.body.view.translation); // copy the object
      this.drag.nodeId = undefined;
      if (event.srcEvent.shiftKey) {
        this.body.selectionBox.show = true;
        var pointer = this.getPointer(event.center);
        this.body.selectionBox.position.start = {
          x: this.canvas._XconvertDOMtoCanvas(pointer.x),
          y: this.canvas._YconvertDOMtoCanvas(pointer.y)
        };
        this.body.selectionBox.position.end = {
          x: this.canvas._XconvertDOMtoCanvas(pointer.x),
          y: this.canvas._YconvertDOMtoCanvas(pointer.y)
        };
      } else if (node !== undefined && this.options.dragNodes === true) {
        this.drag.nodeId = node.id;
        // select the clicked node if not yet selected
        if (node.isSelected() === false) {
          this.selectionHandler.setSelection({
            nodes: [node.id]
          });
        }

        // after select to contain the node
        this.selectionHandler.generateClickEvent("dragStart", event, this.drag.pointer);

        // create an array with the selected nodes and their original location and status
        var _iterator = _createForOfIteratorHelper$4(this.selectionHandler.getSelectedNodes()),
          _step;
        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var _node = _step.value;
            var s = {
              id: _node.id,
              node: _node,
              // store original x, y, xFixed and yFixed, make the node temporarily Fixed
              x: _node.x,
              y: _node.y,
              xFixed: _node.options.fixed.x,
              yFixed: _node.options.fixed.y
            };
            _node.options.fixed.x = true;
            _node.options.fixed.y = true;
            this.drag.selection.push(s);
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      } else {
        // fallback if no node is selected and thus the view is dragged.
        this.selectionHandler.generateClickEvent("dragStart", event, this.drag.pointer, undefined, true);
      }
    }

    /**
     * handle drag event
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onDrag",
    value: function onDrag(event) {
      var _this2 = this;
      if (this.drag.pinched === true) {
        return;
      }

      // remove the focus on node if it is focussed on by the focusOnNode
      this.body.emitter.emit("unlockNode");
      var pointer = this.getPointer(event.center);
      var selection = this.drag.selection;
      if (selection && selection.length && this.options.dragNodes === true) {
        this.selectionHandler.generateClickEvent("dragging", event, pointer);

        // calculate delta's and new location
        var deltaX = pointer.x - this.drag.pointer.x;
        var deltaY = pointer.y - this.drag.pointer.y;

        // update position of all selected nodes
        _forEachInstanceProperty(selection).call(selection, function (selection) {
          var node = selection.node;
          // only move the node if it was not fixed initially
          if (selection.xFixed === false) {
            node.x = _this2.canvas._XconvertDOMtoCanvas(_this2.canvas._XconvertCanvasToDOM(selection.x) + deltaX);
          }
          // only move the node if it was not fixed initially
          if (selection.yFixed === false) {
            node.y = _this2.canvas._YconvertDOMtoCanvas(_this2.canvas._YconvertCanvasToDOM(selection.y) + deltaY);
          }
        });

        // start the simulation of the physics
        this.body.emitter.emit("startSimulation");
      } else {
        // create selection box
        if (event.srcEvent.shiftKey) {
          this.selectionHandler.generateClickEvent("dragging", event, pointer, undefined, true);

          // if the drag was not started properly because the click started outside the network div, start it now.
          if (this.drag.pointer === undefined) {
            this.onDragStart(event);
            return;
          }
          this.body.selectionBox.position.end = {
            x: this.canvas._XconvertDOMtoCanvas(pointer.x),
            y: this.canvas._YconvertDOMtoCanvas(pointer.y)
          };
          this.body.emitter.emit("_requestRedraw");
        }

        // move the network
        if (this.options.dragView === true && !event.srcEvent.shiftKey) {
          this.selectionHandler.generateClickEvent("dragging", event, pointer, undefined, true);

          // if the drag was not started properly because the click started outside the network div, start it now.
          if (this.drag.pointer === undefined) {
            this.onDragStart(event);
            return;
          }
          var diffX = pointer.x - this.drag.pointer.x;
          var diffY = pointer.y - this.drag.pointer.y;
          this.body.view.translation = {
            x: this.drag.translation.x + diffX,
            y: this.drag.translation.y + diffY
          };
          this.body.emitter.emit("_requestRedraw");
        }
      }
    }

    /**
     * handle drag start event
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "onDragEnd",
    value: function onDragEnd(event) {
      var _this3 = this;
      this.drag.dragging = false;
      if (this.body.selectionBox.show) {
        var _context14;
        this.body.selectionBox.show = false;
        var selectionBoxPosition = this.body.selectionBox.position;
        var selectionBoxPositionMinMax = {
          minX: Math.min(selectionBoxPosition.start.x, selectionBoxPosition.end.x),
          minY: Math.min(selectionBoxPosition.start.y, selectionBoxPosition.end.y),
          maxX: Math.max(selectionBoxPosition.start.x, selectionBoxPosition.end.x),
          maxY: Math.max(selectionBoxPosition.start.y, selectionBoxPosition.end.y)
        };
        var toBeSelectedNodes = _filterInstanceProperty(_context14 = this.body.nodeIndices).call(_context14, function (nodeId) {
          var node = _this3.body.nodes[nodeId];
          return node.x >= selectionBoxPositionMinMax.minX && node.x <= selectionBoxPositionMinMax.maxX && node.y >= selectionBoxPositionMinMax.minY && node.y <= selectionBoxPositionMinMax.maxY;
        });
        _forEachInstanceProperty(toBeSelectedNodes).call(toBeSelectedNodes, function (nodeId) {
          return _this3.selectionHandler.selectObject(_this3.body.nodes[nodeId]);
        });
        var pointer = this.getPointer(event.center);
        this.selectionHandler.commitAndEmit(pointer, event);
        this.selectionHandler.generateClickEvent("dragEnd", event, this.getPointer(event.center), undefined, true);
        this.body.emitter.emit("_requestRedraw");
      } else {
        var selection = this.drag.selection;
        if (selection && selection.length) {
          _forEachInstanceProperty(selection).call(selection, function (s) {
            // restore original xFixed and yFixed
            s.node.options.fixed.x = s.xFixed;
            s.node.options.fixed.y = s.yFixed;
          });
          this.selectionHandler.generateClickEvent("dragEnd", event, this.getPointer(event.center));
          this.body.emitter.emit("startSimulation");
        } else {
          this.selectionHandler.generateClickEvent("dragEnd", event, this.getPointer(event.center), undefined, true);
          this.body.emitter.emit("_requestRedraw");
        }
      }
    }

    /**
     * Handle pinch event
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "onPinch",
    value: function onPinch(event) {
      var pointer = this.getPointer(event.center);
      this.drag.pinched = true;
      if (this.pinch["scale"] === undefined) {
        this.pinch.scale = 1;
      }

      // TODO: enabled moving while pinching?
      var scale = this.pinch.scale * event.scale;
      this.zoom(scale, pointer);
    }

    /**
     * Zoom the network in or out
     *
     * @param {number} scale a number around 1, and between 0.01 and 10
     * @param {{x: number, y: number}} pointer    Position on screen
     * @private
     */
  }, {
    key: "zoom",
    value: function zoom(scale, pointer) {
      if (this.options.zoomView === true) {
        var scaleOld = this.body.view.scale;
        if (scale < 0.00001) {
          scale = 0.00001;
        }
        if (scale > 10) {
          scale = 10;
        }
        var preScaleDragPointer = undefined;
        if (this.drag !== undefined) {
          if (this.drag.dragging === true) {
            preScaleDragPointer = this.canvas.DOMtoCanvas(this.drag.pointer);
          }
        }
        // + this.canvas.frame.canvas.clientHeight / 2
        var translation = this.body.view.translation;
        var scaleFrac = scale / scaleOld;
        var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac;
        var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac;
        this.body.view.scale = scale;
        this.body.view.translation = {
          x: tx,
          y: ty
        };
        if (preScaleDragPointer != undefined) {
          var postScaleDragPointer = this.canvas.canvasToDOM(preScaleDragPointer);
          this.drag.pointer.x = postScaleDragPointer.x;
          this.drag.pointer.y = postScaleDragPointer.y;
        }
        this.body.emitter.emit("_requestRedraw");
        if (scaleOld < scale) {
          this.body.emitter.emit("zoom", {
            direction: "+",
            scale: this.body.view.scale,
            pointer: pointer
          });
        } else {
          this.body.emitter.emit("zoom", {
            direction: "-",
            scale: this.body.view.scale,
            pointer: pointer
          });
        }
      }
    }

    /**
     * Event handler for mouse wheel event, used to zoom the timeline
     * See http://adomas.org/javascript-mouse-wheel/
     *     https://github.com/EightMedia/hammer.js/issues/256
     *
     * @param {MouseEvent}  event
     * @private
     */
  }, {
    key: "onMouseWheel",
    value: function onMouseWheel(event) {
      if (this.options.zoomView === true) {
        // If delta is nonzero, handle it.
        // Basically, delta is now positive if wheel was scrolled up,
        // and negative, if wheel was scrolled down.
        if (event.deltaY !== 0) {
          // calculate the new scale
          var scale = this.body.view.scale;
          scale *= 1 + (event.deltaY < 0 ? 1 : -1) * (this.options.zoomSpeed * 0.1);

          // calculate the pointer location
          var pointer = this.getPointer({
            x: event.clientX,
            y: event.clientY
          });

          // apply the new scale
          this.zoom(scale, pointer);
        }

        // Prevent default actions caused by mouse wheel.
        event.preventDefault();
      }
    }

    /**
     * Mouse move handler for checking whether the title moves over a node with a title.
     *
     * @param  {Event} event
     * @private
     */
  }, {
    key: "onMouseMove",
    value: function onMouseMove(event) {
      var _this4 = this;
      var pointer = this.getPointer({
        x: event.clientX,
        y: event.clientY
      });
      var popupVisible = false;

      // check if the previously selected node is still selected
      if (this.popup !== undefined) {
        if (this.popup.hidden === false) {
          this._checkHidePopup(pointer);
        }

        // if the popup was not hidden above
        if (this.popup.hidden === false) {
          popupVisible = true;
          this.popup.setPosition(pointer.x + 3, pointer.y - 5);
          this.popup.show();
        }
      }

      // if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over.
      if (this.options.keyboard.autoFocus && this.options.keyboard.bindToWindow === false && this.options.keyboard.enabled === true) {
        this.canvas.frame.focus();
      }

      // start a timeout that will check if the mouse is positioned above an element
      if (popupVisible === false) {
        if (this.popupTimer !== undefined) {
          clearInterval(this.popupTimer); // stop any running calculationTimer
          this.popupTimer = undefined;
        }
        if (!this.drag.dragging) {
          this.popupTimer = _setTimeout(function () {
            return _this4._checkShowPopup(pointer);
          }, this.options.tooltipDelay);
        }
      }

      // adding hover highlights
      if (this.options.hover === true) {
        this.selectionHandler.hoverObject(event, pointer);
      }
    }

    /**
     * Check if there is an element on the given position in the network
     * (a node or edge). If so, and if this element has a title,
     * show a popup window with its title.
     *
     * @param {{x:number, y:number}} pointer
     * @private
     */
  }, {
    key: "_checkShowPopup",
    value: function _checkShowPopup(pointer) {
      var x = this.canvas._XconvertDOMtoCanvas(pointer.x);
      var y = this.canvas._YconvertDOMtoCanvas(pointer.y);
      var pointerObj = {
        left: x,
        top: y,
        right: x,
        bottom: y
      };
      var previousPopupObjId = this.popupObj === undefined ? undefined : this.popupObj.id;
      var nodeUnderCursor = false;
      var popupType = "node";

      // check if a node is under the cursor.
      if (this.popupObj === undefined) {
        // search the nodes for overlap, select the top one in case of multiple nodes
        var nodeIndices = this.body.nodeIndices;
        var nodes = this.body.nodes;
        var node;
        var overlappingNodes = [];
        for (var i = 0; i < nodeIndices.length; i++) {
          node = nodes[nodeIndices[i]];
          if (node.isOverlappingWith(pointerObj) === true) {
            nodeUnderCursor = true;
            if (node.getTitle() !== undefined) {
              overlappingNodes.push(nodeIndices[i]);
            }
          }
        }
        if (overlappingNodes.length > 0) {
          // if there are overlapping nodes, select the last one, this is the one which is drawn on top of the others
          this.popupObj = nodes[overlappingNodes[overlappingNodes.length - 1]];
          // if you hover over a node, the title of the edge is not supposed to be shown.
          nodeUnderCursor = true;
        }
      }
      if (this.popupObj === undefined && nodeUnderCursor === false) {
        // search the edges for overlap
        var edgeIndices = this.body.edgeIndices;
        var edges = this.body.edges;
        var edge;
        var overlappingEdges = [];
        for (var _i = 0; _i < edgeIndices.length; _i++) {
          edge = edges[edgeIndices[_i]];
          if (edge.isOverlappingWith(pointerObj) === true) {
            if (edge.connected === true && edge.getTitle() !== undefined) {
              overlappingEdges.push(edgeIndices[_i]);
            }
          }
        }
        if (overlappingEdges.length > 0) {
          this.popupObj = edges[overlappingEdges[overlappingEdges.length - 1]];
          popupType = "edge";
        }
      }
      if (this.popupObj !== undefined) {
        // show popup message window
        if (this.popupObj.id !== previousPopupObjId) {
          if (this.popup === undefined) {
            this.popup = new Popup(this.canvas.frame);
          }
          this.popup.popupTargetType = popupType;
          this.popup.popupTargetId = this.popupObj.id;

          // adjust a small offset such that the mouse cursor is located in the
          // bottom left location of the popup, and you can easily move over the
          // popup area
          this.popup.setPosition(pointer.x + 3, pointer.y - 5);
          this.popup.setText(this.popupObj.getTitle());
          this.popup.show();
          this.body.emitter.emit("showPopup", this.popupObj.id);
        }
      } else {
        if (this.popup !== undefined) {
          this.popup.hide();
          this.body.emitter.emit("hidePopup");
        }
      }
    }

    /**
     * Check if the popup must be hidden, which is the case when the mouse is no
     * longer hovering on the object
     *
     * @param {{x:number, y:number}} pointer
     * @private
     */
  }, {
    key: "_checkHidePopup",
    value: function _checkHidePopup(pointer) {
      var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
      var stillOnObj = false;
      if (this.popup.popupTargetType === "node") {
        if (this.body.nodes[this.popup.popupTargetId] !== undefined) {
          stillOnObj = this.body.nodes[this.popup.popupTargetId].isOverlappingWith(pointerObj);

          // if the mouse is still one the node, we have to check if it is not also on one that is drawn on top of it.
          // we initially only check stillOnObj because this is much faster.
          if (stillOnObj === true) {
            var overNode = this.selectionHandler.getNodeAt(pointer);
            stillOnObj = overNode === undefined ? false : overNode.id === this.popup.popupTargetId;
          }
        }
      } else {
        if (this.selectionHandler.getNodeAt(pointer) === undefined) {
          if (this.body.edges[this.popup.popupTargetId] !== undefined) {
            stillOnObj = this.body.edges[this.popup.popupTargetId].isOverlappingWith(pointerObj);
          }
        }
      }
      if (stillOnObj === false) {
        this.popupObj = undefined;
        this.popup.hide();
        this.body.emitter.emit("hidePopup");
      }
    }
  }]);
  return InteractionHandler;
}();

var setExports = {};
var set$2 = {
  get exports(){ return setExports; },
  set exports(v){ setExports = v; },
};

var collection$1 = collection$3;
var collectionStrong = collectionStrong$2;

// `Set` constructor
// https://tc39.es/ecma262/#sec-set-objects
collection$1('Set', function (init) {
  return function Set() { return init(this, arguments.length ? arguments[0] : undefined); };
}, collectionStrong);

var path$1 = path$y;

var set$1 = path$1.Set;

var parent$4 = set$1;


var set$4 = parent$4;

(function (module) {
	module.exports = set$4;
} (set$2));

var _Set = /*@__PURE__*/getDefaultExportFromCjs$1(setExports);

var weakMapExports = {};
var weakMap$2 = {
  get exports(){ return weakMapExports; },
  set exports(v){ weakMapExports = v; },
};

var uncurryThis$2 = functionUncurryThis;
var defineBuiltIns$1 = defineBuiltIns$3;
var getWeakData = internalMetadataExports.getWeakData;
var anInstance = anInstance$3;
var anObject = anObject$d;
var isNullOrUndefined = isNullOrUndefined$5;
var isObject$1$1 = isObject$j;
var iterate = iterate$3;
var ArrayIterationModule = arrayIteration;
var hasOwn$i = hasOwnProperty_1;
var InternalStateModule = internalState;

var setInternalState = InternalStateModule.set;
var internalStateGetterFor = InternalStateModule.getterFor;
var find = ArrayIterationModule.find;
var findIndex = ArrayIterationModule.findIndex;
var splice = uncurryThis$2([].splice);
var id = 0;

// fallback for uncaught frozen keys
var uncaughtFrozenStore = function (state) {
  return state.frozen || (state.frozen = new UncaughtFrozenStore());
};

var UncaughtFrozenStore = function () {
  this.entries = [];
};

var findUncaughtFrozen = function (store, key) {
  return find(store.entries, function (it) {
    return it[0] === key;
  });
};

UncaughtFrozenStore.prototype = {
  get: function (key) {
    var entry = findUncaughtFrozen(this, key);
    if (entry) return entry[1];
  },
  has: function (key) {
    return !!findUncaughtFrozen(this, key);
  },
  set: function (key, value) {
    var entry = findUncaughtFrozen(this, key);
    if (entry) entry[1] = value;
    else this.entries.push([key, value]);
  },
  'delete': function (key) {
    var index = findIndex(this.entries, function (it) {
      return it[0] === key;
    });
    if (~index) splice(this.entries, index, 1);
    return !!~index;
  }
};

var collectionWeak$1 = {
  getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
    var Constructor = wrapper(function (that, iterable) {
      anInstance(that, Prototype);
      setInternalState(that, {
        type: CONSTRUCTOR_NAME,
        id: id++,
        frozen: undefined
      });
      if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
    });

    var Prototype = Constructor.prototype;

    var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);

    var define = function (that, key, value) {
      var state = getInternalState(that);
      var data = getWeakData(anObject(key), true);
      if (data === true) uncaughtFrozenStore(state).set(key, value);
      else data[state.id] = value;
      return that;
    };

    defineBuiltIns$1(Prototype, {
      // `{ WeakMap, WeakSet }.prototype.delete(key)` methods
      // https://tc39.es/ecma262/#sec-weakmap.prototype.delete
      // https://tc39.es/ecma262/#sec-weakset.prototype.delete
      'delete': function (key) {
        var state = getInternalState(this);
        if (!isObject$1$1(key)) return false;
        var data = getWeakData(key);
        if (data === true) return uncaughtFrozenStore(state)['delete'](key);
        return data && hasOwn$i(data, state.id) && delete data[state.id];
      },
      // `{ WeakMap, WeakSet }.prototype.has(key)` methods
      // https://tc39.es/ecma262/#sec-weakmap.prototype.has
      // https://tc39.es/ecma262/#sec-weakset.prototype.has
      has: function has(key) {
        var state = getInternalState(this);
        if (!isObject$1$1(key)) return false;
        var data = getWeakData(key);
        if (data === true) return uncaughtFrozenStore(state).has(key);
        return data && hasOwn$i(data, state.id);
      }
    });

    defineBuiltIns$1(Prototype, IS_MAP ? {
      // `WeakMap.prototype.get(key)` method
      // https://tc39.es/ecma262/#sec-weakmap.prototype.get
      get: function get(key) {
        var state = getInternalState(this);
        if (isObject$1$1(key)) {
          var data = getWeakData(key);
          if (data === true) return uncaughtFrozenStore(state).get(key);
          return data ? data[state.id] : undefined;
        }
      },
      // `WeakMap.prototype.set(key, value)` method
      // https://tc39.es/ecma262/#sec-weakmap.prototype.set
      set: function set(key, value) {
        return define(this, key, value);
      }
    } : {
      // `WeakSet.prototype.add(value)` method
      // https://tc39.es/ecma262/#sec-weakset.prototype.add
      add: function add(value) {
        return define(this, value, true);
      }
    });

    return Constructor;
  }
};

var FREEZING = freezing;
var global$1 = global$l;
var uncurryThis$1 = functionUncurryThis;
var defineBuiltIns = defineBuiltIns$3;
var InternalMetadataModule = internalMetadataExports;
var collection = collection$3;
var collectionWeak = collectionWeak$1;
var isObject$k = isObject$j;
var enforceInternalState = internalState.enforce;
var fails$1 = fails$w;
var NATIVE_WEAK_MAP = weakMapBasicDetection;

var $Object = Object;
// eslint-disable-next-line es/no-array-isarray -- safe
var isArray$g = Array.isArray;
// eslint-disable-next-line es/no-object-isextensible -- safe
var isExtensible = $Object.isExtensible;
// eslint-disable-next-line es/no-object-isfrozen -- safe
var isFrozen = $Object.isFrozen;
// eslint-disable-next-line es/no-object-issealed -- safe
var isSealed = $Object.isSealed;
// eslint-disable-next-line es/no-object-freeze -- safe
var freeze = $Object.freeze;
// eslint-disable-next-line es/no-object-seal -- safe
var seal = $Object.seal;

var FROZEN = {};
var SEALED = {};
var IS_IE11 = !global$1.ActiveXObject && 'ActiveXObject' in global$1;
var InternalWeakMap;

var wrapper = function (init) {
  return function WeakMap() {
    return init(this, arguments.length ? arguments[0] : undefined);
  };
};

// `WeakMap` constructor
// https://tc39.es/ecma262/#sec-weakmap-constructor
var $WeakMap = collection('WeakMap', wrapper, collectionWeak);
var WeakMapPrototype = $WeakMap.prototype;
var nativeSet = uncurryThis$1(WeakMapPrototype.set);

// Chakra Edge bug: adding frozen arrays to WeakMap unfreeze them
var hasMSEdgeFreezingBug = function () {
  return FREEZING && fails$1(function () {
    var frozenArray = freeze([]);
    nativeSet(new $WeakMap(), frozenArray, 1);
    return !isFrozen(frozenArray);
  });
};

// IE11 WeakMap frozen keys fix
// We can't use feature detection because it crash some old IE builds
// https://github.com/zloirock/core-js/issues/485
if (NATIVE_WEAK_MAP) if (IS_IE11) {
  InternalWeakMap = collectionWeak.getConstructor(wrapper, 'WeakMap', true);
  InternalMetadataModule.enable();
  var nativeDelete = uncurryThis$1(WeakMapPrototype['delete']);
  var nativeHas = uncurryThis$1(WeakMapPrototype.has);
  var nativeGet = uncurryThis$1(WeakMapPrototype.get);
  defineBuiltIns(WeakMapPrototype, {
    'delete': function (key) {
      if (isObject$k(key) && !isExtensible(key)) {
        var state = enforceInternalState(this);
        if (!state.frozen) state.frozen = new InternalWeakMap();
        return nativeDelete(this, key) || state.frozen['delete'](key);
      } return nativeDelete(this, key);
    },
    has: function has(key) {
      if (isObject$k(key) && !isExtensible(key)) {
        var state = enforceInternalState(this);
        if (!state.frozen) state.frozen = new InternalWeakMap();
        return nativeHas(this, key) || state.frozen.has(key);
      } return nativeHas(this, key);
    },
    get: function get(key) {
      if (isObject$k(key) && !isExtensible(key)) {
        var state = enforceInternalState(this);
        if (!state.frozen) state.frozen = new InternalWeakMap();
        return nativeHas(this, key) ? nativeGet(this, key) : state.frozen.get(key);
      } return nativeGet(this, key);
    },
    set: function set(key, value) {
      if (isObject$k(key) && !isExtensible(key)) {
        var state = enforceInternalState(this);
        if (!state.frozen) state.frozen = new InternalWeakMap();
        nativeHas(this, key) ? nativeSet(this, key, value) : state.frozen.set(key, value);
      } else nativeSet(this, key, value);
      return this;
    }
  });
// Chakra Edge frozen keys fix
} else if (hasMSEdgeFreezingBug()) {
  defineBuiltIns(WeakMapPrototype, {
    set: function set(key, value) {
      var arrayIntegrityLevel;
      if (isArray$g(key)) {
        if (isFrozen(key)) arrayIntegrityLevel = FROZEN;
        else if (isSealed(key)) arrayIntegrityLevel = SEALED;
      }
      nativeSet(this, key, value);
      if (arrayIntegrityLevel == FROZEN) freeze(key);
      if (arrayIntegrityLevel == SEALED) seal(key);
      return this;
    }
  });
}

var path = path$y;

var weakMap$1 = path.WeakMap;

var parent$3 = weakMap$1;


var weakMap = parent$3;

(function (module) {
	module.exports = weakMap;
} (weakMap$2));

var _WeakMap = /*@__PURE__*/getDefaultExportFromCjs$1(weakMapExports);

/******************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

function __classPrivateFieldGet(receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
}

function __classPrivateFieldSet(receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
}

function _createForOfIteratorHelper$3(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray$3(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$3(o, minLen) { var _context2; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$3(o, minLen); var n = _sliceInstanceProperty(_context2 = Object.prototype.toString.call(o)).call(_context2, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3(o, minLen); }
function _arrayLikeToArray$3(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
var _SingleTypeSelectionAccumulator_previousSelection, _SingleTypeSelectionAccumulator_selection, _SelectionAccumulator_nodes, _SelectionAccumulator_edges, _SelectionAccumulator_commitHandler;
/**
 * @param prev
 * @param next
 */
function diffSets(prev, next) {
  var diff = new _Set();
  var _iterator = _createForOfIteratorHelper$3(next),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var item = _step.value;
      if (!prev.has(item)) {
        diff.add(item);
      }
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return diff;
}
var SingleTypeSelectionAccumulator = /*#__PURE__*/function () {
  function SingleTypeSelectionAccumulator() {
    _classCallCheck(this, SingleTypeSelectionAccumulator);
    _SingleTypeSelectionAccumulator_previousSelection.set(this, new _Set());
    _SingleTypeSelectionAccumulator_selection.set(this, new _Set());
  }
  _createClass(SingleTypeSelectionAccumulator, [{
    key: "size",
    get: function get() {
      return __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f").size;
    }
  }, {
    key: "add",
    value: function add() {
      for (var _len = arguments.length, items = new Array(_len), _key = 0; _key < _len; _key++) {
        items[_key] = arguments[_key];
      }
      for (var _i = 0, _items = items; _i < _items.length; _i++) {
        var item = _items[_i];
        __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f").add(item);
      }
    }
  }, {
    key: "delete",
    value: function _delete() {
      for (var _len2 = arguments.length, items = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        items[_key2] = arguments[_key2];
      }
      for (var _i2 = 0, _items2 = items; _i2 < _items2.length; _i2++) {
        var item = _items2[_i2];
        __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f").delete(item);
      }
    }
  }, {
    key: "clear",
    value: function clear() {
      __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f").clear();
    }
  }, {
    key: "getSelection",
    value: function getSelection() {
      return _toConsumableArray(__classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f"));
    }
  }, {
    key: "getChanges",
    value: function getChanges() {
      return {
        added: _toConsumableArray(diffSets(__classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_previousSelection, "f"), __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f"))),
        deleted: _toConsumableArray(diffSets(__classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f"), __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_previousSelection, "f"))),
        previous: _toConsumableArray(new _Set(__classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_previousSelection, "f"))),
        current: _toConsumableArray(new _Set(__classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f")))
      };
    }
  }, {
    key: "commit",
    value: function commit() {
      var changes = this.getChanges();
      __classPrivateFieldSet(this, _SingleTypeSelectionAccumulator_previousSelection, __classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_selection, "f"), "f");
      __classPrivateFieldSet(this, _SingleTypeSelectionAccumulator_selection, new _Set(__classPrivateFieldGet(this, _SingleTypeSelectionAccumulator_previousSelection, "f")), "f");
      var _iterator2 = _createForOfIteratorHelper$3(changes.added),
        _step2;
      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var item = _step2.value;
          item.select();
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }
      var _iterator3 = _createForOfIteratorHelper$3(changes.deleted),
        _step3;
      try {
        for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
          var _item = _step3.value;
          _item.unselect();
        }
      } catch (err) {
        _iterator3.e(err);
      } finally {
        _iterator3.f();
      }
      return changes;
    }
  }]);
  return SingleTypeSelectionAccumulator;
}();
_SingleTypeSelectionAccumulator_previousSelection = new _WeakMap(), _SingleTypeSelectionAccumulator_selection = new _WeakMap();
var SelectionAccumulator = /*#__PURE__*/function () {
  function SelectionAccumulator() {
    var commitHandler = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
    _classCallCheck(this, SelectionAccumulator);
    _SelectionAccumulator_nodes.set(this, new SingleTypeSelectionAccumulator());
    _SelectionAccumulator_edges.set(this, new SingleTypeSelectionAccumulator());
    _SelectionAccumulator_commitHandler.set(this, void 0);
    __classPrivateFieldSet(this, _SelectionAccumulator_commitHandler, commitHandler, "f");
  }
  _createClass(SelectionAccumulator, [{
    key: "sizeNodes",
    get: function get() {
      return __classPrivateFieldGet(this, _SelectionAccumulator_nodes, "f").size;
    }
  }, {
    key: "sizeEdges",
    get: function get() {
      return __classPrivateFieldGet(this, _SelectionAccumulator_edges, "f").size;
    }
  }, {
    key: "getNodes",
    value: function getNodes() {
      return __classPrivateFieldGet(this, _SelectionAccumulator_nodes, "f").getSelection();
    }
  }, {
    key: "getEdges",
    value: function getEdges() {
      return __classPrivateFieldGet(this, _SelectionAccumulator_edges, "f").getSelection();
    }
  }, {
    key: "addNodes",
    value: function addNodes() {
      var _classPrivateFieldGe;
      (_classPrivateFieldGe = __classPrivateFieldGet(this, _SelectionAccumulator_nodes, "f")).add.apply(_classPrivateFieldGe, arguments);
    }
  }, {
    key: "addEdges",
    value: function addEdges() {
      var _classPrivateFieldGe2;
      (_classPrivateFieldGe2 = __classPrivateFieldGet(this, _SelectionAccumulator_edges, "f")).add.apply(_classPrivateFieldGe2, arguments);
    }
  }, {
    key: "deleteNodes",
    value: function deleteNodes(node) {
      __classPrivateFieldGet(this, _SelectionAccumulator_nodes, "f").delete(node);
    }
  }, {
    key: "deleteEdges",
    value: function deleteEdges(edge) {
      __classPrivateFieldGet(this, _SelectionAccumulator_edges, "f").delete(edge);
    }
  }, {
    key: "clear",
    value: function clear() {
      __classPrivateFieldGet(this, _SelectionAccumulator_nodes, "f").clear();
      __classPrivateFieldGet(this, _SelectionAccumulator_edges, "f").clear();
    }
  }, {
    key: "commit",
    value: function commit() {
      var _classPrivateFieldGe3, _context;
      var summary = {
        nodes: __classPrivateFieldGet(this, _SelectionAccumulator_nodes, "f").commit(),
        edges: __classPrivateFieldGet(this, _SelectionAccumulator_edges, "f").commit()
      };
      for (var _len3 = arguments.length, rest = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
        rest[_key3] = arguments[_key3];
      }
      (_classPrivateFieldGe3 = __classPrivateFieldGet(this, _SelectionAccumulator_commitHandler, "f")).call.apply(_classPrivateFieldGe3, _concatInstanceProperty(_context = [this, summary]).call(_context, rest));
      return summary;
    }
  }]);
  return SelectionAccumulator;
}();
_SelectionAccumulator_nodes = new _WeakMap(), _SelectionAccumulator_edges = new _WeakMap(), _SelectionAccumulator_commitHandler = new _WeakMap();

function _createForOfIteratorHelper$2(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray$2(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$2(o, minLen) { var _context3; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$2(o, minLen); var n = _sliceInstanceProperty(_context3 = Object.prototype.toString.call(o)).call(_context3, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2(o, minLen); }
function _arrayLikeToArray$2(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

/**
 * The handler for selections
 */
var SelectionHandler = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Canvas} canvas
   */
  function SelectionHandler(body, canvas) {
    var _this = this;
    _classCallCheck(this, SelectionHandler);
    this.body = body;
    this.canvas = canvas;
    // TODO: Consider firing an event on any change to the selection, not
    // only those caused by clicks and taps. It would be easy to implement
    // now and (at least to me) it seems like something that could be
    // quite useful.
    this._selectionAccumulator = new SelectionAccumulator();
    this.hoverObj = {
      nodes: {},
      edges: {}
    };
    this.options = {};
    this.defaultOptions = {
      multiselect: false,
      selectable: true,
      selectConnectedEdges: true,
      hoverConnectedEdges: true
    };
    _Object$assign(this.options, this.defaultOptions);
    this.body.emitter.on("_dataChanged", function () {
      _this.updateSelection();
    });
  }

  /**
   *
   * @param {object} [options]
   */
  _createClass(SelectionHandler, [{
    key: "setOptions",
    value: function setOptions(options) {
      if (options !== undefined) {
        var fields = ["multiselect", "hoverConnectedEdges", "selectable", "selectConnectedEdges"];
        selectiveDeepExtend(fields, this.options, options);
      }
    }

    /**
     * handles the selection part of the tap;
     *
     * @param {{x: number, y: number}} pointer
     * @returns {boolean}
     */
  }, {
    key: "selectOnPoint",
    value: function selectOnPoint(pointer) {
      var selected = false;
      if (this.options.selectable === true) {
        var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);

        // unselect after getting the objects in order to restore width and height.
        this.unselectAll();
        if (obj !== undefined) {
          selected = this.selectObject(obj);
        }
        this.body.emitter.emit("_requestRedraw");
      }
      return selected;
    }

    /**
     *
     * @param {{x: number, y: number}} pointer
     * @returns {boolean}
     */
  }, {
    key: "selectAdditionalOnPoint",
    value: function selectAdditionalOnPoint(pointer) {
      var selectionChanged = false;
      if (this.options.selectable === true) {
        var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);
        if (obj !== undefined) {
          selectionChanged = true;
          if (obj.isSelected() === true) {
            this.deselectObject(obj);
          } else {
            this.selectObject(obj);
          }
          this.body.emitter.emit("_requestRedraw");
        }
      }
      return selectionChanged;
    }

    /**
     * Create an object containing the standard fields for an event.
     *
     * @param {Event} event
     * @param {{x: number, y: number}} pointer Object with the x and y screen coordinates of the mouse
     * @returns {{}}
     * @private
     */
  }, {
    key: "_initBaseEvent",
    value: function _initBaseEvent(event, pointer) {
      var properties = {};
      properties["pointer"] = {
        DOM: {
          x: pointer.x,
          y: pointer.y
        },
        canvas: this.canvas.DOMtoCanvas(pointer)
      };
      properties["event"] = event;
      return properties;
    }

    /**
     * Generate an event which the user can catch.
     *
     * This adds some extra data to the event with respect to cursor position and
     * selected nodes and edges.
     *
     * @param {string} eventType                          Name of event to send
     * @param {Event}  event
     * @param {{x: number, y: number}} pointer            Object with the x and y screen coordinates of the mouse
     * @param {object | undefined} oldSelection             If present, selection state before event occured
     * @param {boolean|undefined} [emptySelection=false]  Indicate if selection data should be passed
     */
  }, {
    key: "generateClickEvent",
    value: function generateClickEvent(eventType, event, pointer, oldSelection) {
      var emptySelection = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
      var properties = this._initBaseEvent(event, pointer);
      if (emptySelection === true) {
        properties.nodes = [];
        properties.edges = [];
      } else {
        var tmp = this.getSelection();
        properties.nodes = tmp.nodes;
        properties.edges = tmp.edges;
      }
      if (oldSelection !== undefined) {
        properties["previousSelection"] = oldSelection;
      }
      if (eventType == "click") {
        // For the time being, restrict this functionality to
        // just the click event.
        properties.items = this.getClickedItems(pointer);
      }
      if (event.controlEdge !== undefined) {
        properties.controlEdge = event.controlEdge;
      }
      this.body.emitter.emit(eventType, properties);
    }

    /**
     *
     * @param {object} obj
     * @param {boolean} [highlightEdges=this.options.selectConnectedEdges]
     * @returns {boolean}
     */
  }, {
    key: "selectObject",
    value: function selectObject(obj) {
      var highlightEdges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.options.selectConnectedEdges;
      if (obj !== undefined) {
        if (obj instanceof Node) {
          if (highlightEdges === true) {
            var _this$_selectionAccum;
            (_this$_selectionAccum = this._selectionAccumulator).addEdges.apply(_this$_selectionAccum, _toConsumableArray(obj.edges));
          }
          this._selectionAccumulator.addNodes(obj);
        } else {
          this._selectionAccumulator.addEdges(obj);
        }
        return true;
      }
      return false;
    }

    /**
     *
     * @param {object} obj
     */
  }, {
    key: "deselectObject",
    value: function deselectObject(obj) {
      if (obj.isSelected() === true) {
        obj.selected = false;
        this._removeFromSelection(obj);
      }
    }

    /**
     * retrieve all nodes overlapping with given object
     *
     * @param {object} object  An object with parameters left, top, right, bottom
     * @returns {number[]}   An array with id's of the overlapping nodes
     * @private
     */
  }, {
    key: "_getAllNodesOverlappingWith",
    value: function _getAllNodesOverlappingWith(object) {
      var overlappingNodes = [];
      var nodes = this.body.nodes;
      for (var i = 0; i < this.body.nodeIndices.length; i++) {
        var nodeId = this.body.nodeIndices[i];
        if (nodes[nodeId].isOverlappingWith(object)) {
          overlappingNodes.push(nodeId);
        }
      }
      return overlappingNodes;
    }

    /**
     * Return a position object in canvasspace from a single point in screenspace
     *
     * @param {{x: number, y: number}} pointer
     * @returns {{left: number, top: number, right: number, bottom: number}}
     * @private
     */
  }, {
    key: "_pointerToPositionObject",
    value: function _pointerToPositionObject(pointer) {
      var canvasPos = this.canvas.DOMtoCanvas(pointer);
      return {
        left: canvasPos.x - 1,
        top: canvasPos.y + 1,
        right: canvasPos.x + 1,
        bottom: canvasPos.y - 1
      };
    }

    /**
     * Get the top node at the passed point (like a click)
     *
     * @param {{x: number, y: number}} pointer
     * @param {boolean} [returnNode=true]
     * @returns {Node | undefined} node
     */
  }, {
    key: "getNodeAt",
    value: function getNodeAt(pointer) {
      var returnNode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      // we first check if this is an navigation controls element
      var positionObject = this._pointerToPositionObject(pointer);
      var overlappingNodes = this._getAllNodesOverlappingWith(positionObject);
      // if there are overlapping nodes, select the last one, this is the
      // one which is drawn on top of the others
      if (overlappingNodes.length > 0) {
        if (returnNode === true) {
          return this.body.nodes[overlappingNodes[overlappingNodes.length - 1]];
        } else {
          return overlappingNodes[overlappingNodes.length - 1];
        }
      } else {
        return undefined;
      }
    }

    /**
     * retrieve all edges overlapping with given object, selector is around center
     *
     * @param {object} object  An object with parameters left, top, right, bottom
     * @param {number[]} overlappingEdges An array with id's of the overlapping nodes
     * @private
     */
  }, {
    key: "_getEdgesOverlappingWith",
    value: function _getEdgesOverlappingWith(object, overlappingEdges) {
      var edges = this.body.edges;
      for (var i = 0; i < this.body.edgeIndices.length; i++) {
        var edgeId = this.body.edgeIndices[i];
        if (edges[edgeId].isOverlappingWith(object)) {
          overlappingEdges.push(edgeId);
        }
      }
    }

    /**
     * retrieve all nodes overlapping with given object
     *
     * @param {object} object  An object with parameters left, top, right, bottom
     * @returns {number[]}   An array with id's of the overlapping nodes
     * @private
     */
  }, {
    key: "_getAllEdgesOverlappingWith",
    value: function _getAllEdgesOverlappingWith(object) {
      var overlappingEdges = [];
      this._getEdgesOverlappingWith(object, overlappingEdges);
      return overlappingEdges;
    }

    /**
     * Get the edges nearest to the passed point (like a click)
     *
     * @param {{x: number, y: number}} pointer
     * @param {boolean} [returnEdge=true]
     * @returns {Edge | undefined} node
     */
  }, {
    key: "getEdgeAt",
    value: function getEdgeAt(pointer) {
      var returnEdge = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      // Iterate over edges, pick closest within 10
      var canvasPos = this.canvas.DOMtoCanvas(pointer);
      var mindist = 10;
      var overlappingEdge = null;
      var edges = this.body.edges;
      for (var i = 0; i < this.body.edgeIndices.length; i++) {
        var edgeId = this.body.edgeIndices[i];
        var edge = edges[edgeId];
        if (edge.connected) {
          var xFrom = edge.from.x;
          var yFrom = edge.from.y;
          var xTo = edge.to.x;
          var yTo = edge.to.y;
          var dist = edge.edgeType.getDistanceToEdge(xFrom, yFrom, xTo, yTo, canvasPos.x, canvasPos.y);
          if (dist < mindist) {
            overlappingEdge = edgeId;
            mindist = dist;
          }
        }
      }
      if (overlappingEdge !== null) {
        if (returnEdge === true) {
          return this.body.edges[overlappingEdge];
        } else {
          return overlappingEdge;
        }
      } else {
        return undefined;
      }
    }

    /**
     * Add object to the selection array.
     *
     * @param {object} obj
     * @private
     */
  }, {
    key: "_addToHover",
    value: function _addToHover(obj) {
      if (obj instanceof Node) {
        this.hoverObj.nodes[obj.id] = obj;
      } else {
        this.hoverObj.edges[obj.id] = obj;
      }
    }

    /**
     * Remove a single option from selection.
     *
     * @param {object} obj
     * @private
     */
  }, {
    key: "_removeFromSelection",
    value: function _removeFromSelection(obj) {
      if (obj instanceof Node) {
        var _this$_selectionAccum2;
        this._selectionAccumulator.deleteNodes(obj);
        (_this$_selectionAccum2 = this._selectionAccumulator).deleteEdges.apply(_this$_selectionAccum2, _toConsumableArray(obj.edges));
      } else {
        this._selectionAccumulator.deleteEdges(obj);
      }
    }

    /**
     * Unselect all nodes and edges.
     */
  }, {
    key: "unselectAll",
    value: function unselectAll() {
      this._selectionAccumulator.clear();
    }

    /**
     * return the number of selected nodes
     *
     * @returns {number}
     */
  }, {
    key: "getSelectedNodeCount",
    value: function getSelectedNodeCount() {
      return this._selectionAccumulator.sizeNodes;
    }

    /**
     * return the number of selected edges
     *
     * @returns {number}
     */
  }, {
    key: "getSelectedEdgeCount",
    value: function getSelectedEdgeCount() {
      return this._selectionAccumulator.sizeEdges;
    }

    /**
     * select the edges connected to the node that is being selected
     *
     * @param {Node} node
     * @private
     */
  }, {
    key: "_hoverConnectedEdges",
    value: function _hoverConnectedEdges(node) {
      for (var i = 0; i < node.edges.length; i++) {
        var edge = node.edges[i];
        edge.hover = true;
        this._addToHover(edge);
      }
    }

    /**
     * Remove the highlight from a node or edge, in response to mouse movement
     *
     * @param {Event}  event
     * @param {{x: number, y: number}} pointer object with the x and y screen coordinates of the mouse
     * @param {Node|vis.Edge} object
     * @private
     */
  }, {
    key: "emitBlurEvent",
    value: function emitBlurEvent(event, pointer, object) {
      var properties = this._initBaseEvent(event, pointer);
      if (object.hover === true) {
        object.hover = false;
        if (object instanceof Node) {
          properties.node = object.id;
          this.body.emitter.emit("blurNode", properties);
        } else {
          properties.edge = object.id;
          this.body.emitter.emit("blurEdge", properties);
        }
      }
    }

    /**
     * Create the highlight for a node or edge, in response to mouse movement
     *
     * @param {Event}  event
     * @param {{x: number, y: number}} pointer object with the x and y screen coordinates of the mouse
     * @param {Node|vis.Edge} object
     * @returns {boolean} hoverChanged
     * @private
     */
  }, {
    key: "emitHoverEvent",
    value: function emitHoverEvent(event, pointer, object) {
      var properties = this._initBaseEvent(event, pointer);
      var hoverChanged = false;
      if (object.hover === false) {
        object.hover = true;
        this._addToHover(object);
        hoverChanged = true;
        if (object instanceof Node) {
          properties.node = object.id;
          this.body.emitter.emit("hoverNode", properties);
        } else {
          properties.edge = object.id;
          this.body.emitter.emit("hoverEdge", properties);
        }
      }
      return hoverChanged;
    }

    /**
     * Perform actions in response to a mouse movement.
     *
     * @param {Event}  event
     * @param {{x: number, y: number}} pointer | object with the x and y screen coordinates of the mouse
     */
  }, {
    key: "hoverObject",
    value: function hoverObject(event, pointer) {
      var object = this.getNodeAt(pointer);
      if (object === undefined) {
        object = this.getEdgeAt(pointer);
      }
      var hoverChanged = false;
      // remove all node hover highlights
      for (var nodeId in this.hoverObj.nodes) {
        if (Object.prototype.hasOwnProperty.call(this.hoverObj.nodes, nodeId)) {
          if (object === undefined || object instanceof Node && object.id != nodeId || object instanceof Edge) {
            this.emitBlurEvent(event, pointer, this.hoverObj.nodes[nodeId]);
            delete this.hoverObj.nodes[nodeId];
            hoverChanged = true;
          }
        }
      }

      // removing all edge hover highlights
      for (var edgeId in this.hoverObj.edges) {
        if (Object.prototype.hasOwnProperty.call(this.hoverObj.edges, edgeId)) {
          // if the hover has been changed here it means that the node has been hovered over or off
          // we then do not use the emitBlurEvent method here.
          if (hoverChanged === true) {
            this.hoverObj.edges[edgeId].hover = false;
            delete this.hoverObj.edges[edgeId];
          }
          // if the blur remains the same and the object is undefined (mouse off) or another
          // edge has been hovered, or another node has been hovered we blur the edge.
          else if (object === undefined || object instanceof Edge && object.id != edgeId || object instanceof Node && !object.hover) {
            this.emitBlurEvent(event, pointer, this.hoverObj.edges[edgeId]);
            delete this.hoverObj.edges[edgeId];
            hoverChanged = true;
          }
        }
      }
      if (object !== undefined) {
        var hoveredEdgesCount = _Object$keys(this.hoverObj.edges).length;
        var hoveredNodesCount = _Object$keys(this.hoverObj.nodes).length;
        var newOnlyHoveredEdge = object instanceof Edge && hoveredEdgesCount === 0 && hoveredNodesCount === 0;
        var newOnlyHoveredNode = object instanceof Node && hoveredEdgesCount === 0 && hoveredNodesCount === 0;
        if (hoverChanged || newOnlyHoveredEdge || newOnlyHoveredNode) {
          hoverChanged = this.emitHoverEvent(event, pointer, object);
        }
        if (object instanceof Node && this.options.hoverConnectedEdges === true) {
          this._hoverConnectedEdges(object);
        }
      }
      if (hoverChanged === true) {
        this.body.emitter.emit("_requestRedraw");
      }
    }

    /**
     * Commit the selection changes but don't emit any events.
     */
  }, {
    key: "commitWithoutEmitting",
    value: function commitWithoutEmitting() {
      this._selectionAccumulator.commit();
    }

    /**
     * Select and deselect nodes depending current selection change.
     *
     * For changing nodes, select/deselect events are fired.
     *
     * NOTE: For a given edge, if one connecting node is deselected and with the
     * same click the other node is selected, no events for the edge will fire. It
     * was selected and it will remain selected.
     *
     * @param {{x: number, y: number}} pointer - The x and y coordinates of the
     * click, tap, dragend… that triggered this.
     * @param {UIEvent} event - The event that triggered this.
     */
  }, {
    key: "commitAndEmit",
    value: function commitAndEmit(pointer, event) {
      var selected = false;
      var selectionChanges = this._selectionAccumulator.commit();
      var previousSelection = {
        nodes: selectionChanges.nodes.previous,
        edges: selectionChanges.edges.previous
      };
      if (selectionChanges.edges.deleted.length > 0) {
        this.generateClickEvent("deselectEdge", event, pointer, previousSelection);
        selected = true;
      }
      if (selectionChanges.nodes.deleted.length > 0) {
        this.generateClickEvent("deselectNode", event, pointer, previousSelection);
        selected = true;
      }
      if (selectionChanges.nodes.added.length > 0) {
        this.generateClickEvent("selectNode", event, pointer);
        selected = true;
      }
      if (selectionChanges.edges.added.length > 0) {
        this.generateClickEvent("selectEdge", event, pointer);
        selected = true;
      }

      // fire the select event if anything has been selected or deselected
      if (selected === true) {
        // select or unselect
        this.generateClickEvent("select", event, pointer);
      }
    }

    /**
     * Retrieve the currently selected node and edge ids.
     *
     * @returns {{nodes: Array.<string>, edges: Array.<string>}} Arrays with the
     * ids of the selected nodes and edges.
     */
  }, {
    key: "getSelection",
    value: function getSelection() {
      return {
        nodes: this.getSelectedNodeIds(),
        edges: this.getSelectedEdgeIds()
      };
    }

    /**
     * Retrieve the currently selected nodes.
     *
     * @returns {Array} An array with selected nodes.
     */
  }, {
    key: "getSelectedNodes",
    value: function getSelectedNodes() {
      return this._selectionAccumulator.getNodes();
    }

    /**
     * Retrieve the currently selected edges.
     *
     * @returns {Array} An array with selected edges.
     */
  }, {
    key: "getSelectedEdges",
    value: function getSelectedEdges() {
      return this._selectionAccumulator.getEdges();
    }

    /**
     * Retrieve the currently selected node ids.
     *
     * @returns {Array} An array with the ids of the selected nodes.
     */
  }, {
    key: "getSelectedNodeIds",
    value: function getSelectedNodeIds() {
      var _context;
      return _mapInstanceProperty(_context = this._selectionAccumulator.getNodes()).call(_context, function (node) {
        return node.id;
      });
    }

    /**
     * Retrieve the currently selected edge ids.
     *
     * @returns {Array} An array with the ids of the selected edges.
     */
  }, {
    key: "getSelectedEdgeIds",
    value: function getSelectedEdgeIds() {
      var _context2;
      return _mapInstanceProperty(_context2 = this._selectionAccumulator.getEdges()).call(_context2, function (edge) {
        return edge.id;
      });
    }

    /**
     * Updates the current selection
     *
     * @param {{nodes: Array.<string>, edges: Array.<string>}} selection
     * @param {object} options                                 Options
     */
  }, {
    key: "setSelection",
    value: function setSelection(selection) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      if (!selection || !selection.nodes && !selection.edges) {
        throw new TypeError("Selection must be an object with nodes and/or edges properties");
      }

      // first unselect any selected node, if option is true or undefined
      if (options.unselectAll || options.unselectAll === undefined) {
        this.unselectAll();
      }
      if (selection.nodes) {
        var _iterator = _createForOfIteratorHelper$2(selection.nodes),
          _step;
        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var id = _step.value;
            var node = this.body.nodes[id];
            if (!node) {
              throw new RangeError('Node with id "' + id + '" not found');
            }
            // don't select edges with it
            this.selectObject(node, options.highlightEdges);
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      }
      if (selection.edges) {
        var _iterator2 = _createForOfIteratorHelper$2(selection.edges),
          _step2;
        try {
          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
            var _id = _step2.value;
            var edge = this.body.edges[_id];
            if (!edge) {
              throw new RangeError('Edge with id "' + _id + '" not found');
            }
            this.selectObject(edge);
          }
        } catch (err) {
          _iterator2.e(err);
        } finally {
          _iterator2.f();
        }
      }
      this.body.emitter.emit("_requestRedraw");
      this._selectionAccumulator.commit();
    }

    /**
     * select zero or more nodes with the option to highlight edges
     *
     * @param {number[] | string[]} selection     An array with the ids of the
     *                                            selected nodes.
     * @param {boolean} [highlightEdges]
     */
  }, {
    key: "selectNodes",
    value: function selectNodes(selection) {
      var highlightEdges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      if (!selection || selection.length === undefined) throw "Selection must be an array with ids";
      this.setSelection({
        nodes: selection
      }, {
        highlightEdges: highlightEdges
      });
    }

    /**
     * select zero or more edges
     *
     * @param {number[] | string[]} selection     An array with the ids of the
     *                                            selected nodes.
     */
  }, {
    key: "selectEdges",
    value: function selectEdges(selection) {
      if (!selection || selection.length === undefined) throw "Selection must be an array with ids";
      this.setSelection({
        edges: selection
      });
    }

    /**
     * Validate the selection: remove ids of nodes which no longer exist
     *
     * @private
     */
  }, {
    key: "updateSelection",
    value: function updateSelection() {
      for (var node in this._selectionAccumulator.getNodes()) {
        if (!Object.prototype.hasOwnProperty.call(this.body.nodes, node.id)) {
          this._selectionAccumulator.deleteNodes(node);
        }
      }
      for (var edge in this._selectionAccumulator.getEdges()) {
        if (!Object.prototype.hasOwnProperty.call(this.body.edges, edge.id)) {
          this._selectionAccumulator.deleteEdges(edge);
        }
      }
    }

    /**
     * Determine all the visual elements clicked which are on the given point.
     *
     * All elements are returned; this includes nodes, edges and their labels.
     * The order returned is from highest to lowest, i.e. element 0 of the return
     * value is the topmost item clicked on.
     *
     * The return value consists of an array of the following possible elements:
     *
     * - `{nodeId:number}`             - node with given id clicked on
     * - `{nodeId:number, labelId:0}`  - label of node with given id clicked on
     * - `{edgeId:number}`             - edge with given id clicked on
     * - `{edge:number, labelId:0}`    - label of edge with given id clicked on
     *
     * ## NOTES
     *
     * - Currently, there is only one label associated with a node or an edge,
     *   but this is expected to change somewhere in the future.
     * - Since there is no z-indexing yet, it is not really possible to set the nodes and
     *   edges in the correct order. For the time being, nodes come first.
     *
     * @param {point} pointer  mouse position in screen coordinates
     * @returns {Array.<nodeClickItem|nodeLabelClickItem|edgeClickItem|edgeLabelClickItem>}
     * @private
     */
  }, {
    key: "getClickedItems",
    value: function getClickedItems(pointer) {
      var point = this.canvas.DOMtoCanvas(pointer);
      var items = [];

      // Note reverse order; we want the topmost clicked items to be first in the array
      // Also note that selected nodes are disregarded here; these normally display on top
      var nodeIndices = this.body.nodeIndices;
      var nodes = this.body.nodes;
      for (var i = nodeIndices.length - 1; i >= 0; i--) {
        var node = nodes[nodeIndices[i]];
        var ret = node.getItemsOnPoint(point);
        items.push.apply(items, ret); // Append the return value to the running list.
      }

      var edgeIndices = this.body.edgeIndices;
      var edges = this.body.edges;
      for (var _i = edgeIndices.length - 1; _i >= 0; _i--) {
        var edge = edges[edgeIndices[_i]];
        var _ret = edge.getItemsOnPoint(point);
        items.push.apply(items, _ret); // Append the return value to the running list.
      }

      return items;
    }
  }]);
  return SelectionHandler;
}();

var sortExports = {};
var sort$3 = {
  get exports(){ return sortExports; },
  set exports(v){ sortExports = v; },
};

var arraySlice$6 = arraySliceSimple;

var floor = Math.floor;

var mergeSort = function (array, comparefn) {
  var length = array.length;
  var middle = floor(length / 2);
  return length < 8 ? insertionSort(array, comparefn) : merge$3(
    array,
    mergeSort(arraySlice$6(array, 0, middle), comparefn),
    mergeSort(arraySlice$6(array, middle), comparefn),
    comparefn
  );
};

var insertionSort = function (array, comparefn) {
  var length = array.length;
  var i = 1;
  var element, j;

  while (i < length) {
    j = i;
    element = array[i];
    while (j && comparefn(array[j - 1], element) > 0) {
      array[j] = array[--j];
    }
    if (j !== i++) array[j] = element;
  } return array;
};

var merge$3 = function (array, left, right, comparefn) {
  var llength = left.length;
  var rlength = right.length;
  var lindex = 0;
  var rindex = 0;

  while (lindex < llength || rindex < rlength) {
    array[lindex + rindex] = (lindex < llength && rindex < rlength)
      ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
      : lindex < llength ? left[lindex++] : right[rindex++];
  } return array;
};

var arraySort = mergeSort;

var userAgent$1 = engineUserAgent;

var firefox = userAgent$1.match(/firefox\/(\d+)/i);

var engineFfVersion = !!firefox && +firefox[1];

var UA = engineUserAgent;

var engineIsIeOrEdge = /MSIE|Trident/.test(UA);

var userAgent = engineUserAgent;

var webkit = userAgent.match(/AppleWebKit\/(\d+)\./);

var engineWebkitVersion = !!webkit && +webkit[1];

var $$2 = _export;
var uncurryThis = functionUncurryThis;
var aCallable$1 = aCallable$7;
var toObject$1 = toObject$d;
var lengthOfArrayLike$1 = lengthOfArrayLike$b;
var deletePropertyOrThrow = deletePropertyOrThrow$2;
var toString = toString$a;
var fails = fails$w;
var internalSort = arraySort;
var arrayMethodIsStrict$2 = arrayMethodIsStrict$6;
var FF = engineFfVersion;
var IE_OR_EDGE = engineIsIeOrEdge;
var V8 = engineV8Version;
var WEBKIT = engineWebkitVersion;

var test = [];
var nativeSort = uncurryThis(test.sort);
var push = uncurryThis(test.push);

// IE8-
var FAILS_ON_UNDEFINED = fails(function () {
  test.sort(undefined);
});
// V8 bug
var FAILS_ON_NULL = fails(function () {
  test.sort(null);
});
// Old WebKit
var STRICT_METHOD$1 = arrayMethodIsStrict$2('sort');

var STABLE_SORT = !fails(function () {
  // feature detection can be too slow, so check engines versions
  if (V8) return V8 < 70;
  if (FF && FF > 3) return;
  if (IE_OR_EDGE) return true;
  if (WEBKIT) return WEBKIT < 603;

  var result = '';
  var code, chr, value, index;

  // generate an array with more 512 elements (Chakra and old V8 fails only in this case)
  for (code = 65; code < 76; code++) {
    chr = String.fromCharCode(code);

    switch (code) {
      case 66: case 69: case 70: case 72: value = 3; break;
      case 68: case 71: value = 4; break;
      default: value = 2;
    }

    for (index = 0; index < 47; index++) {
      test.push({ k: chr + index, v: value });
    }
  }

  test.sort(function (a, b) { return b.v - a.v; });

  for (index = 0; index < test.length; index++) {
    chr = test[index].k.charAt(0);
    if (result.charAt(result.length - 1) !== chr) result += chr;
  }

  return result !== 'DGBEFHACIJK';
});

var FORCED$1 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD$1 || !STABLE_SORT;

var getSortCompare = function (comparefn) {
  return function (x, y) {
    if (y === undefined) return -1;
    if (x === undefined) return 1;
    if (comparefn !== undefined) return +comparefn(x, y) || 0;
    return toString(x) > toString(y) ? 1 : -1;
  };
};

// `Array.prototype.sort` method
// https://tc39.es/ecma262/#sec-array.prototype.sort
$$2({ target: 'Array', proto: true, forced: FORCED$1 }, {
  sort: function sort(comparefn) {
    if (comparefn !== undefined) aCallable$1(comparefn);

    var array = toObject$1(this);

    if (STABLE_SORT) return comparefn === undefined ? nativeSort(array) : nativeSort(array, comparefn);

    var items = [];
    var arrayLength = lengthOfArrayLike$1(array);
    var itemsLength, index;

    for (index = 0; index < arrayLength; index++) {
      if (index in array) push(items, array[index]);
    }

    internalSort(items, getSortCompare(comparefn));

    itemsLength = lengthOfArrayLike$1(items);
    index = 0;

    while (index < itemsLength) array[index] = items[index++];
    while (index < arrayLength) deletePropertyOrThrow(array, index++);

    return array;
  }
});

var entryVirtual$2 = entryVirtual$i;

var sort$2 = entryVirtual$2('Array').sort;

var isPrototypeOf$2 = objectIsPrototypeOf;
var method$2 = sort$2;

var ArrayPrototype$2 = Array.prototype;

var sort$1 = function (it) {
  var own = it.sort;
  return it === ArrayPrototype$2 || (isPrototypeOf$2(ArrayPrototype$2, it) && own === ArrayPrototype$2.sort) ? method$2 : own;
};

var parent$2 = sort$1;

var sort$4 = parent$2;

(function (module) {
	module.exports = sort$4;
} (sort$3));

var _sortInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(sortExports);

var reduceExports = {};
var reduce$3 = {
  get exports(){ return reduceExports; },
  set exports(v){ reduceExports = v; },
};

var aCallable = aCallable$7;
var toObject = toObject$d;
var IndexedObject = indexedObject;
var lengthOfArrayLike = lengthOfArrayLike$b;

var $TypeError = TypeError;

// `Array.prototype.{ reduce, reduceRight }` methods implementation
var createMethod = function (IS_RIGHT) {
  return function (that, callbackfn, argumentsLength, memo) {
    aCallable(callbackfn);
    var O = toObject(that);
    var self = IndexedObject(O);
    var length = lengthOfArrayLike(O);
    var index = IS_RIGHT ? length - 1 : 0;
    var i = IS_RIGHT ? -1 : 1;
    if (argumentsLength < 2) while (true) {
      if (index in self) {
        memo = self[index];
        index += i;
        break;
      }
      index += i;
      if (IS_RIGHT ? index < 0 : length <= index) {
        throw $TypeError('Reduce of empty array with no initial value');
      }
    }
    for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
      memo = callbackfn(memo, self[index], index, O);
    }
    return memo;
  };
};

var arrayReduce = {
  // `Array.prototype.reduce` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduce
  left: createMethod(false),
  // `Array.prototype.reduceRight` method
  // https://tc39.es/ecma262/#sec-array.prototype.reduceright
  right: createMethod(true)
};

var classof = classofRaw$2;

var engineIsNode = typeof process != 'undefined' && classof(process) == 'process';

var $$1 = _export;
var $reduce = arrayReduce.left;
var arrayMethodIsStrict$1 = arrayMethodIsStrict$6;
var CHROME_VERSION = engineV8Version;
var IS_NODE = engineIsNode;

// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;
var FORCED = CHROME_BUG || !arrayMethodIsStrict$1('reduce');

// `Array.prototype.reduce` method
// https://tc39.es/ecma262/#sec-array.prototype.reduce
$$1({ target: 'Array', proto: true, forced: FORCED }, {
  reduce: function reduce(callbackfn /* , initialValue */) {
    var length = arguments.length;
    return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual$1 = entryVirtual$i;

var reduce$2 = entryVirtual$1('Array').reduce;

var isPrototypeOf$1 = objectIsPrototypeOf;
var method$1 = reduce$2;

var ArrayPrototype$1 = Array.prototype;

var reduce$1 = function (it) {
  var own = it.reduce;
  return it === ArrayPrototype$1 || (isPrototypeOf$1(ArrayPrototype$1, it) && own === ArrayPrototype$1.reduce) ? method$1 : own;
};

var parent$1 = reduce$1;

var reduce$4 = parent$1;

(function (module) {
	module.exports = reduce$4;
} (reduce$3));

var _reduceInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(reduceExports);

var timsortExports = {};
var timsort$1 = {
  get exports(){ return timsortExports; },
  set exports(v){ timsortExports = v; },
};

var timsort = {};

/****
 * The MIT License
 *
 * Copyright (c) 2015 Marco Ziccardi
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 ****/

(function (exports) {
	(function (global, factory) {
	  {
	    factory(exports);
	  }
	})(commonjsGlobal$1, function (exports) {

	  exports.__esModule = true;
	  exports.sort = sort;

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

	  var DEFAULT_MIN_MERGE = 32;

	  var DEFAULT_MIN_GALLOPING = 7;

	  var DEFAULT_TMP_STORAGE_LENGTH = 256;

	  var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9];

	  function log10(x) {
	    if (x < 1e5) {
	      if (x < 1e2) {
	        return x < 1e1 ? 0 : 1;
	      }

	      if (x < 1e4) {
	        return x < 1e3 ? 2 : 3;
	      }

	      return 4;
	    }

	    if (x < 1e7) {
	      return x < 1e6 ? 5 : 6;
	    }

	    if (x < 1e9) {
	      return x < 1e8 ? 7 : 8;
	    }

	    return 9;
	  }

	  function alphabeticalCompare(a, b) {
	    if (a === b) {
	      return 0;
	    }

	    if (~ ~a === a && ~ ~b === b) {
	      if (a === 0 || b === 0) {
	        return a < b ? -1 : 1;
	      }

	      if (a < 0 || b < 0) {
	        if (b >= 0) {
	          return -1;
	        }

	        if (a >= 0) {
	          return 1;
	        }

	        a = -a;
	        b = -b;
	      }

	      var al = log10(a);
	      var bl = log10(b);

	      var t = 0;

	      if (al < bl) {
	        a *= POWERS_OF_TEN[bl - al - 1];
	        b /= 10;
	        t = -1;
	      } else if (al > bl) {
	        b *= POWERS_OF_TEN[al - bl - 1];
	        a /= 10;
	        t = 1;
	      }

	      if (a === b) {
	        return t;
	      }

	      return a < b ? -1 : 1;
	    }

	    var aStr = String(a);
	    var bStr = String(b);

	    if (aStr === bStr) {
	      return 0;
	    }

	    return aStr < bStr ? -1 : 1;
	  }

	  function minRunLength(n) {
	    var r = 0;

	    while (n >= DEFAULT_MIN_MERGE) {
	      r |= n & 1;
	      n >>= 1;
	    }

	    return n + r;
	  }

	  function makeAscendingRun(array, lo, hi, compare) {
	    var runHi = lo + 1;

	    if (runHi === hi) {
	      return 1;
	    }

	    if (compare(array[runHi++], array[lo]) < 0) {
	      while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
	        runHi++;
	      }

	      reverseRun(array, lo, runHi);
	    } else {
	      while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
	        runHi++;
	      }
	    }

	    return runHi - lo;
	  }

	  function reverseRun(array, lo, hi) {
	    hi--;

	    while (lo < hi) {
	      var t = array[lo];
	      array[lo++] = array[hi];
	      array[hi--] = t;
	    }
	  }

	  function binaryInsertionSort(array, lo, hi, start, compare) {
	    if (start === lo) {
	      start++;
	    }

	    for (; start < hi; start++) {
	      var pivot = array[start];

	      var left = lo;
	      var right = start;

	      while (left < right) {
	        var mid = left + right >>> 1;

	        if (compare(pivot, array[mid]) < 0) {
	          right = mid;
	        } else {
	          left = mid + 1;
	        }
	      }

	      var n = start - left;

	      switch (n) {
	        case 3:
	          array[left + 3] = array[left + 2];

	        case 2:
	          array[left + 2] = array[left + 1];

	        case 1:
	          array[left + 1] = array[left];
	          break;
	        default:
	          while (n > 0) {
	            array[left + n] = array[left + n - 1];
	            n--;
	          }
	      }

	      array[left] = pivot;
	    }
	  }

	  function gallopLeft(value, array, start, length, hint, compare) {
	    var lastOffset = 0;
	    var maxOffset = 0;
	    var offset = 1;

	    if (compare(value, array[start + hint]) > 0) {
	      maxOffset = length - hint;

	      while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
	        lastOffset = offset;
	        offset = (offset << 1) + 1;

	        if (offset <= 0) {
	          offset = maxOffset;
	        }
	      }

	      if (offset > maxOffset) {
	        offset = maxOffset;
	      }

	      lastOffset += hint;
	      offset += hint;
	    } else {
	      maxOffset = hint + 1;
	      while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
	        lastOffset = offset;
	        offset = (offset << 1) + 1;

	        if (offset <= 0) {
	          offset = maxOffset;
	        }
	      }
	      if (offset > maxOffset) {
	        offset = maxOffset;
	      }

	      var tmp = lastOffset;
	      lastOffset = hint - offset;
	      offset = hint - tmp;
	    }

	    lastOffset++;
	    while (lastOffset < offset) {
	      var m = lastOffset + (offset - lastOffset >>> 1);

	      if (compare(value, array[start + m]) > 0) {
	        lastOffset = m + 1;
	      } else {
	        offset = m;
	      }
	    }
	    return offset;
	  }

	  function gallopRight(value, array, start, length, hint, compare) {
	    var lastOffset = 0;
	    var maxOffset = 0;
	    var offset = 1;

	    if (compare(value, array[start + hint]) < 0) {
	      maxOffset = hint + 1;

	      while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
	        lastOffset = offset;
	        offset = (offset << 1) + 1;

	        if (offset <= 0) {
	          offset = maxOffset;
	        }
	      }

	      if (offset > maxOffset) {
	        offset = maxOffset;
	      }

	      var tmp = lastOffset;
	      lastOffset = hint - offset;
	      offset = hint - tmp;
	    } else {
	      maxOffset = length - hint;

	      while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
	        lastOffset = offset;
	        offset = (offset << 1) + 1;

	        if (offset <= 0) {
	          offset = maxOffset;
	        }
	      }

	      if (offset > maxOffset) {
	        offset = maxOffset;
	      }

	      lastOffset += hint;
	      offset += hint;
	    }

	    lastOffset++;

	    while (lastOffset < offset) {
	      var m = lastOffset + (offset - lastOffset >>> 1);

	      if (compare(value, array[start + m]) < 0) {
	        offset = m;
	      } else {
	        lastOffset = m + 1;
	      }
	    }

	    return offset;
	  }

	  var TimSort = (function () {
	    function TimSort(array, compare) {
	      _classCallCheck(this, TimSort);

	      this.array = null;
	      this.compare = null;
	      this.minGallop = DEFAULT_MIN_GALLOPING;
	      this.length = 0;
	      this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
	      this.stackLength = 0;
	      this.runStart = null;
	      this.runLength = null;
	      this.stackSize = 0;

	      this.array = array;
	      this.compare = compare;

	      this.length = array.length;

	      if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
	        this.tmpStorageLength = this.length >>> 1;
	      }

	      this.tmp = new Array(this.tmpStorageLength);

	      this.stackLength = this.length < 120 ? 5 : this.length < 1542 ? 10 : this.length < 119151 ? 19 : 40;

	      this.runStart = new Array(this.stackLength);
	      this.runLength = new Array(this.stackLength);
	    }

	    TimSort.prototype.pushRun = function pushRun(runStart, runLength) {
	      this.runStart[this.stackSize] = runStart;
	      this.runLength[this.stackSize] = runLength;
	      this.stackSize += 1;
	    };

	    TimSort.prototype.mergeRuns = function mergeRuns() {
	      while (this.stackSize > 1) {
	        var n = this.stackSize - 2;

	        if (n >= 1 && this.runLength[n - 1] <= this.runLength[n] + this.runLength[n + 1] || n >= 2 && this.runLength[n - 2] <= this.runLength[n] + this.runLength[n - 1]) {

	          if (this.runLength[n - 1] < this.runLength[n + 1]) {
	            n--;
	          }
	        } else if (this.runLength[n] > this.runLength[n + 1]) {
	          break;
	        }
	        this.mergeAt(n);
	      }
	    };

	    TimSort.prototype.forceMergeRuns = function forceMergeRuns() {
	      while (this.stackSize > 1) {
	        var n = this.stackSize - 2;

	        if (n > 0 && this.runLength[n - 1] < this.runLength[n + 1]) {
	          n--;
	        }

	        this.mergeAt(n);
	      }
	    };

	    TimSort.prototype.mergeAt = function mergeAt(i) {
	      var compare = this.compare;
	      var array = this.array;

	      var start1 = this.runStart[i];
	      var length1 = this.runLength[i];
	      var start2 = this.runStart[i + 1];
	      var length2 = this.runLength[i + 1];

	      this.runLength[i] = length1 + length2;

	      if (i === this.stackSize - 3) {
	        this.runStart[i + 1] = this.runStart[i + 2];
	        this.runLength[i + 1] = this.runLength[i + 2];
	      }

	      this.stackSize--;

	      var k = gallopRight(array[start2], array, start1, length1, 0, compare);
	      start1 += k;
	      length1 -= k;

	      if (length1 === 0) {
	        return;
	      }

	      length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);

	      if (length2 === 0) {
	        return;
	      }

	      if (length1 <= length2) {
	        this.mergeLow(start1, length1, start2, length2);
	      } else {
	        this.mergeHigh(start1, length1, start2, length2);
	      }
	    };

	    TimSort.prototype.mergeLow = function mergeLow(start1, length1, start2, length2) {

	      var compare = this.compare;
	      var array = this.array;
	      var tmp = this.tmp;
	      var i = 0;

	      for (i = 0; i < length1; i++) {
	        tmp[i] = array[start1 + i];
	      }

	      var cursor1 = 0;
	      var cursor2 = start2;
	      var dest = start1;

	      array[dest++] = array[cursor2++];

	      if (--length2 === 0) {
	        for (i = 0; i < length1; i++) {
	          array[dest + i] = tmp[cursor1 + i];
	        }
	        return;
	      }

	      if (length1 === 1) {
	        for (i = 0; i < length2; i++) {
	          array[dest + i] = array[cursor2 + i];
	        }
	        array[dest + length2] = tmp[cursor1];
	        return;
	      }

	      var minGallop = this.minGallop;

	      while (true) {
	        var count1 = 0;
	        var count2 = 0;
	        var exit = false;

	        do {
	          if (compare(array[cursor2], tmp[cursor1]) < 0) {
	            array[dest++] = array[cursor2++];
	            count2++;
	            count1 = 0;

	            if (--length2 === 0) {
	              exit = true;
	              break;
	            }
	          } else {
	            array[dest++] = tmp[cursor1++];
	            count1++;
	            count2 = 0;
	            if (--length1 === 1) {
	              exit = true;
	              break;
	            }
	          }
	        } while ((count1 | count2) < minGallop);

	        if (exit) {
	          break;
	        }

	        do {
	          count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);

	          if (count1 !== 0) {
	            for (i = 0; i < count1; i++) {
	              array[dest + i] = tmp[cursor1 + i];
	            }

	            dest += count1;
	            cursor1 += count1;
	            length1 -= count1;
	            if (length1 <= 1) {
	              exit = true;
	              break;
	            }
	          }

	          array[dest++] = array[cursor2++];

	          if (--length2 === 0) {
	            exit = true;
	            break;
	          }

	          count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);

	          if (count2 !== 0) {
	            for (i = 0; i < count2; i++) {
	              array[dest + i] = array[cursor2 + i];
	            }

	            dest += count2;
	            cursor2 += count2;
	            length2 -= count2;

	            if (length2 === 0) {
	              exit = true;
	              break;
	            }
	          }
	          array[dest++] = tmp[cursor1++];

	          if (--length1 === 1) {
	            exit = true;
	            break;
	          }

	          minGallop--;
	        } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);

	        if (exit) {
	          break;
	        }

	        if (minGallop < 0) {
	          minGallop = 0;
	        }

	        minGallop += 2;
	      }

	      this.minGallop = minGallop;

	      if (minGallop < 1) {
	        this.minGallop = 1;
	      }

	      if (length1 === 1) {
	        for (i = 0; i < length2; i++) {
	          array[dest + i] = array[cursor2 + i];
	        }
	        array[dest + length2] = tmp[cursor1];
	      } else if (length1 === 0) {
	        throw new Error('mergeLow preconditions were not respected');
	      } else {
	        for (i = 0; i < length1; i++) {
	          array[dest + i] = tmp[cursor1 + i];
	        }
	      }
	    };

	    TimSort.prototype.mergeHigh = function mergeHigh(start1, length1, start2, length2) {
	      var compare = this.compare;
	      var array = this.array;
	      var tmp = this.tmp;
	      var i = 0;

	      for (i = 0; i < length2; i++) {
	        tmp[i] = array[start2 + i];
	      }

	      var cursor1 = start1 + length1 - 1;
	      var cursor2 = length2 - 1;
	      var dest = start2 + length2 - 1;
	      var customCursor = 0;
	      var customDest = 0;

	      array[dest--] = array[cursor1--];

	      if (--length1 === 0) {
	        customCursor = dest - (length2 - 1);

	        for (i = 0; i < length2; i++) {
	          array[customCursor + i] = tmp[i];
	        }

	        return;
	      }

	      if (length2 === 1) {
	        dest -= length1;
	        cursor1 -= length1;
	        customDest = dest + 1;
	        customCursor = cursor1 + 1;

	        for (i = length1 - 1; i >= 0; i--) {
	          array[customDest + i] = array[customCursor + i];
	        }

	        array[dest] = tmp[cursor2];
	        return;
	      }

	      var minGallop = this.minGallop;

	      while (true) {
	        var count1 = 0;
	        var count2 = 0;
	        var exit = false;

	        do {
	          if (compare(tmp[cursor2], array[cursor1]) < 0) {
	            array[dest--] = array[cursor1--];
	            count1++;
	            count2 = 0;
	            if (--length1 === 0) {
	              exit = true;
	              break;
	            }
	          } else {
	            array[dest--] = tmp[cursor2--];
	            count2++;
	            count1 = 0;
	            if (--length2 === 1) {
	              exit = true;
	              break;
	            }
	          }
	        } while ((count1 | count2) < minGallop);

	        if (exit) {
	          break;
	        }

	        do {
	          count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);

	          if (count1 !== 0) {
	            dest -= count1;
	            cursor1 -= count1;
	            length1 -= count1;
	            customDest = dest + 1;
	            customCursor = cursor1 + 1;

	            for (i = count1 - 1; i >= 0; i--) {
	              array[customDest + i] = array[customCursor + i];
	            }

	            if (length1 === 0) {
	              exit = true;
	              break;
	            }
	          }

	          array[dest--] = tmp[cursor2--];

	          if (--length2 === 1) {
	            exit = true;
	            break;
	          }

	          count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);

	          if (count2 !== 0) {
	            dest -= count2;
	            cursor2 -= count2;
	            length2 -= count2;
	            customDest = dest + 1;
	            customCursor = cursor2 + 1;

	            for (i = 0; i < count2; i++) {
	              array[customDest + i] = tmp[customCursor + i];
	            }

	            if (length2 <= 1) {
	              exit = true;
	              break;
	            }
	          }

	          array[dest--] = array[cursor1--];

	          if (--length1 === 0) {
	            exit = true;
	            break;
	          }

	          minGallop--;
	        } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);

	        if (exit) {
	          break;
	        }

	        if (minGallop < 0) {
	          minGallop = 0;
	        }

	        minGallop += 2;
	      }

	      this.minGallop = minGallop;

	      if (minGallop < 1) {
	        this.minGallop = 1;
	      }

	      if (length2 === 1) {
	        dest -= length1;
	        cursor1 -= length1;
	        customDest = dest + 1;
	        customCursor = cursor1 + 1;

	        for (i = length1 - 1; i >= 0; i--) {
	          array[customDest + i] = array[customCursor + i];
	        }

	        array[dest] = tmp[cursor2];
	      } else if (length2 === 0) {
	        throw new Error('mergeHigh preconditions were not respected');
	      } else {
	        customCursor = dest - (length2 - 1);
	        for (i = 0; i < length2; i++) {
	          array[customCursor + i] = tmp[i];
	        }
	      }
	    };

	    return TimSort;
	  })();

	  function sort(array, compare, lo, hi) {
	    if (!Array.isArray(array)) {
	      throw new TypeError('Can only sort arrays');
	    }

	    if (!compare) {
	      compare = alphabeticalCompare;
	    } else if (typeof compare !== 'function') {
	      hi = lo;
	      lo = compare;
	      compare = alphabeticalCompare;
	    }

	    if (!lo) {
	      lo = 0;
	    }
	    if (!hi) {
	      hi = array.length;
	    }

	    var remaining = hi - lo;

	    if (remaining < 2) {
	      return;
	    }

	    var runLength = 0;

	    if (remaining < DEFAULT_MIN_MERGE) {
	      runLength = makeAscendingRun(array, lo, hi, compare);
	      binaryInsertionSort(array, lo, hi, lo + runLength, compare);
	      return;
	    }

	    var ts = new TimSort(array, compare);

	    var minRun = minRunLength(remaining);

	    do {
	      runLength = makeAscendingRun(array, lo, hi, compare);
	      if (runLength < minRun) {
	        var force = remaining;
	        if (force > minRun) {
	          force = minRun;
	        }

	        binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
	        runLength = force;
	      }

	      ts.pushRun(lo, runLength);
	      ts.mergeRuns();

	      remaining -= runLength;
	      lo += runLength;
	    } while (remaining !== 0);

	    ts.forceMergeRuns();
	  }
	});
} (timsort));

(function (module) {
	module.exports = timsort;
} (timsort$1));

var TimSort$1 = /*@__PURE__*/getDefaultExportFromCjs$1(timsortExports);

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 _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; } }

/**
 * Interface definition for direction strategy classes.
 *
 * This class describes the interface for the Strategy
 * pattern classes used to differentiate horizontal and vertical
 * direction of hierarchical results.
 *
 * For a given direction, one coordinate will be 'fixed', meaning that it is
 * determined by level.
 * The other coordinate is 'unfixed', meaning that the nodes on a given level
 * can still move along that coordinate. So:
 *
 * - `vertical` layout: `x` unfixed, `y` fixed per level
 * - `horizontal` layout: `x` fixed per level, `y` unfixed
 *
 * The local methods are stubs and should be regarded as abstract.
 * Derived classes **must** implement all the methods themselves.
 *
 * @private
 */
var DirectionInterface = /*#__PURE__*/function () {
  function DirectionInterface() {
    _classCallCheck(this, DirectionInterface);
  }
  _createClass(DirectionInterface, [{
    key: "abstract",
    value:
    /**
     * @ignore
     */
    function abstract() {
      throw new Error("Can't instantiate abstract class!");
    }

    /**
     * This is a dummy call which is used to suppress the jsdoc errors of type:
     *
     *   "'param' is assigned a value but never used"
     *
     * @ignore
     */
  }, {
    key: "fake_use",
    value: function fake_use() {
      // Do nothing special
    }

    /**
     * Type to use to translate dynamic curves to, in the case of hierarchical layout.
     * Dynamic curves do not work for these.
     *
     * The value should be perpendicular to the actual direction of the layout.
     *
     * @returns {string} Direction, either 'vertical' or 'horizontal'
     */
  }, {
    key: "curveType",
    value: function curveType() {
      return this.abstract();
    }

    /**
     * Return the value of the coordinate that is not fixed for this direction.
     *
     * @param {Node} node The node to read
     * @returns {number} Value of the unfixed coordinate
     */
  }, {
    key: "getPosition",
    value: function getPosition(node) {
      this.fake_use(node);
      return this.abstract();
    }

    /**
     * Set the value of the coordinate that is not fixed for this direction.
     *
     * @param {Node} node The node to adjust
     * @param {number} position
     * @param {number} [level] if specified, the hierarchy level that this node should be fixed to
     */
  }, {
    key: "setPosition",
    value: function setPosition(node, position) {
      var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
      this.fake_use(node, position, level);
      this.abstract();
    }

    /**
     * Get the width of a tree.
     *
     * A `tree` here is a subset of nodes within the network which are not connected to other nodes,
     * only among themselves. In essence, it is a sub-network.
     *
     * @param {number} index The index number of a tree
     * @returns {number} the width of a tree in the view coordinates
     */
  }, {
    key: "getTreeSize",
    value: function getTreeSize(index) {
      this.fake_use(index);
      return this.abstract();
    }

    /**
     * Sort array of nodes on the unfixed coordinates.
     *
     * Note:** chrome has non-stable sorting implementation, which
     * has a tendency to change the order of the array items,
     * even if the custom sort function returns 0.
     *
     * For this reason, an external sort implementation is used,
     * which has the added benefit of being faster than the standard
     * platforms implementation. This has been verified on `node.js`,
     * `firefox` and `chrome` (all linux).
     *
     * @param {Array.<Node>} nodeArray array of nodes to sort
     */
  }, {
    key: "sort",
    value: function sort(nodeArray) {
      this.fake_use(nodeArray);
      this.abstract();
    }

    /**
     * Assign the fixed coordinate of the node to the given level
     *
     * @param {Node} node The node to adjust
     * @param {number} level The level to fix to
     */
  }, {
    key: "fix",
    value: function fix(node, level) {
      this.fake_use(node, level);
      this.abstract();
    }

    /**
     * Add an offset to the unfixed coordinate of the given node.
     *
     * @param {NodeId} nodeId Id of the node to adjust
     * @param {number} diff Offset to add to the unfixed coordinate
     */
  }, {
    key: "shift",
    value: function shift(nodeId, diff) {
      this.fake_use(nodeId, diff);
      this.abstract();
    }
  }]);
  return DirectionInterface;
}();
/**
 * Vertical Strategy
 *
 * Coordinate `y` is fixed on levels, coordinate `x` is unfixed.
 *
 * @augments DirectionInterface
 * @private
 */
var VerticalStrategy = /*#__PURE__*/function (_DirectionInterface) {
  _inherits(VerticalStrategy, _DirectionInterface);
  var _super = _createSuper(VerticalStrategy);
  /**
   * Constructor
   *
   * @param {object} layout reference to the parent LayoutEngine instance.
   */
  function VerticalStrategy(layout) {
    var _this;
    _classCallCheck(this, VerticalStrategy);
    _this = _super.call(this);
    _this.layout = layout;
    return _this;
  }

  /** @inheritDoc */
  _createClass(VerticalStrategy, [{
    key: "curveType",
    value: function curveType() {
      return "horizontal";
    }

    /** @inheritDoc */
  }, {
    key: "getPosition",
    value: function getPosition(node) {
      return node.x;
    }

    /** @inheritDoc */
  }, {
    key: "setPosition",
    value: function setPosition(node, position) {
      var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
      if (level !== undefined) {
        this.layout.hierarchical.addToOrdering(node, level);
      }
      node.x = position;
    }

    /** @inheritDoc */
  }, {
    key: "getTreeSize",
    value: function getTreeSize(index) {
      var res = this.layout.hierarchical.getTreeSize(this.layout.body.nodes, index);
      return {
        min: res.min_x,
        max: res.max_x
      };
    }

    /** @inheritDoc */
  }, {
    key: "sort",
    value: function sort(nodeArray) {
      timsortExports.sort(nodeArray, function (a, b) {
        return a.x - b.x;
      });
    }

    /** @inheritDoc */
  }, {
    key: "fix",
    value: function fix(node, level) {
      node.y = this.layout.options.hierarchical.levelSeparation * level;
      node.options.fixed.y = true;
    }

    /** @inheritDoc */
  }, {
    key: "shift",
    value: function shift(nodeId, diff) {
      this.layout.body.nodes[nodeId].x += diff;
    }
  }]);
  return VerticalStrategy;
}(DirectionInterface);
/**
 * Horizontal Strategy
 *
 * Coordinate `x` is fixed on levels, coordinate `y` is unfixed.
 *
 * @augments DirectionInterface
 * @private
 */
var HorizontalStrategy = /*#__PURE__*/function (_DirectionInterface2) {
  _inherits(HorizontalStrategy, _DirectionInterface2);
  var _super2 = _createSuper(HorizontalStrategy);
  /**
   * Constructor
   *
   * @param {object} layout reference to the parent LayoutEngine instance.
   */
  function HorizontalStrategy(layout) {
    var _this2;
    _classCallCheck(this, HorizontalStrategy);
    _this2 = _super2.call(this);
    _this2.layout = layout;
    return _this2;
  }

  /** @inheritDoc */
  _createClass(HorizontalStrategy, [{
    key: "curveType",
    value: function curveType() {
      return "vertical";
    }

    /** @inheritDoc */
  }, {
    key: "getPosition",
    value: function getPosition(node) {
      return node.y;
    }

    /** @inheritDoc */
  }, {
    key: "setPosition",
    value: function setPosition(node, position) {
      var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
      if (level !== undefined) {
        this.layout.hierarchical.addToOrdering(node, level);
      }
      node.y = position;
    }

    /** @inheritDoc */
  }, {
    key: "getTreeSize",
    value: function getTreeSize(index) {
      var res = this.layout.hierarchical.getTreeSize(this.layout.body.nodes, index);
      return {
        min: res.min_y,
        max: res.max_y
      };
    }

    /** @inheritDoc */
  }, {
    key: "sort",
    value: function sort(nodeArray) {
      timsortExports.sort(nodeArray, function (a, b) {
        return a.y - b.y;
      });
    }

    /** @inheritDoc */
  }, {
    key: "fix",
    value: function fix(node, level) {
      node.x = this.layout.options.hierarchical.levelSeparation * level;
      node.options.fixed.x = true;
    }

    /** @inheritDoc */
  }, {
    key: "shift",
    value: function shift(nodeId, diff) {
      this.layout.body.nodes[nodeId].y += diff;
    }
  }]);
  return HorizontalStrategy;
}(DirectionInterface);

var everyExports = {};
var every$3 = {
  get exports(){ return everyExports; },
  set exports(v){ everyExports = v; },
};

var $ = _export;
var $every = arrayIteration.every;
var arrayMethodIsStrict = arrayMethodIsStrict$6;

var STRICT_METHOD = arrayMethodIsStrict('every');

// `Array.prototype.every` method
// https://tc39.es/ecma262/#sec-array.prototype.every
$({ target: 'Array', proto: true, forced: !STRICT_METHOD }, {
  every: function every(callbackfn /* , thisArg */) {
    return $every(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});

var entryVirtual = entryVirtual$i;

var every$2 = entryVirtual('Array').every;

var isPrototypeOf = objectIsPrototypeOf;
var method = every$2;

var ArrayPrototype = Array.prototype;

var every$1 = function (it) {
  var own = it.every;
  return it === ArrayPrototype || (isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.every) ? method : own;
};

var parent = every$1;

var every = parent;

(function (module) {
	module.exports = every;
} (every$3));

var _everyInstanceProperty = /*@__PURE__*/getDefaultExportFromCjs$1(everyExports);

function _createForOfIteratorHelper$1(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray$1(o, minLen) { var _context9; if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = _sliceInstanceProperty(_context9 = Object.prototype.toString.call(o)).call(_context9, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); }
function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
/**
 * Try to assign levels to nodes according to their positions in the cyclic “hierarchy”.
 *
 * @param nodes - Visible nodes of the graph.
 * @param levels - If present levels will be added to it, if not a new object will be created.
 * @returns Populated node levels.
 */
function fillLevelsByDirectionCyclic(nodes, levels) {
  var edges = new _Set();
  _forEachInstanceProperty(nodes).call(nodes, function (node) {
    var _context;
    _forEachInstanceProperty(_context = node.edges).call(_context, function (edge) {
      if (edge.connected) {
        edges.add(edge);
      }
    });
  });
  _forEachInstanceProperty(edges).call(edges, function (edge) {
    var fromId = edge.from.id;
    var toId = edge.to.id;
    if (levels[fromId] == null) {
      levels[fromId] = 0;
    }
    if (levels[toId] == null || levels[fromId] >= levels[toId]) {
      levels[toId] = levels[fromId] + 1;
    }
  });
  return levels;
}
/**
 * Assign levels to nodes according to their positions in the hierarchy. Leaves will be lined up at the bottom and all other nodes as close to their children as possible.
 *
 * @param nodes - Visible nodes of the graph.
 * @returns Populated node levels.
 */
function fillLevelsByDirectionLeaves(nodes) {
  return fillLevelsByDirection(
  // Pick only leaves (nodes without children).
  function (node) {
    var _context2, _context3;
    return _everyInstanceProperty(_context2 = _filterInstanceProperty(_context3 = node.edges
    // Take only visible nodes into account.
    ).call(_context3, function (edge) {
      return nodes.has(edge.toId);
    })
    // Check that all edges lead to this node (leaf).
    ).call(_context2, function (edge) {
      return edge.to === node;
    });
  },
  // Use the lowest level.
  function (newLevel, oldLevel) {
    return oldLevel > newLevel;
  },
  // Go against the direction of the edges.
  "from", nodes);
}
/**
 * Assign levels to nodes according to their positions in the hierarchy. Roots will be lined up at the top and all nodes as close to their parents as possible.
 *
 * @param nodes - Visible nodes of the graph.
 * @returns Populated node levels.
 */
function fillLevelsByDirectionRoots(nodes) {
  return fillLevelsByDirection(
  // Pick only roots (nodes without parents).
  function (node) {
    var _context4, _context5;
    return _everyInstanceProperty(_context4 = _filterInstanceProperty(_context5 = node.edges
    // Take only visible nodes into account.
    ).call(_context5, function (edge) {
      return nodes.has(edge.toId);
    })
    // Check that all edges lead from this node (root).
    ).call(_context4, function (edge) {
      return edge.from === node;
    });
  },
  // Use the highest level.
  function (newLevel, oldLevel) {
    return oldLevel < newLevel;
  },
  // Go in the direction of the edges.
  "to", nodes);
}
/**
 * Assign levels to nodes according to their positions in the hierarchy.
 *
 * @param isEntryNode - Checks and return true if the graph should be traversed from this node.
 * @param shouldLevelBeReplaced - Checks and returns true if the level of given node should be updated to the new value.
 * @param direction - Wheter the graph should be traversed in the direction of the edges `"to"` or in the other way `"from"`.
 * @param nodes - Visible nodes of the graph.
 * @returns Populated node levels.
 */
function fillLevelsByDirection(isEntryNode, shouldLevelBeReplaced, direction, nodes) {
  var _context6;
  var levels = _Object$create$1(null);
  // If acyclic, the graph can be walked through with (most likely way) fewer
  // steps than the number bellow. The exact value isn't too important as long
  // as it's quick to compute (doesn't impact acyclic graphs too much), is
  // higher than the number of steps actually needed (doesn't cut off before
  // acyclic graph is walked through) and prevents infinite loops (cuts off for
  // cyclic graphs).
  var limit = _reduceInstanceProperty(_context6 = _toConsumableArray(_valuesInstanceProperty(nodes).call(nodes))).call(_context6, function (acc, node) {
    return acc + 1 + node.edges.length;
  }, 0);
  var edgeIdProp = direction + "Id";
  var newLevelDiff = direction === "to" ? 1 : -1;
  var _iterator = _createForOfIteratorHelper$1(nodes),
    _step;
  try {
    var _loop = function _loop() {
      var _step$value = _slicedToArray(_step.value, 2),
        entryNodeId = _step$value[0],
        entryNode = _step$value[1];
      if (
      // Skip if the node is not visible.
      !nodes.has(entryNodeId) ||
      // Skip if the node is not an entry node.
      !isEntryNode(entryNode)) {
        return "continue";
      }
      // Line up all the entry nodes on level 0.
      levels[entryNodeId] = 0;
      var stack = [entryNode];
      var done = 0;
      var node;
      var _loop2 = function _loop2() {
        var _context7, _context8;
        if (!nodes.has(entryNodeId)) {
          // Skip if the node is not visible.
          return "continue";
        }
        var newLevel = levels[node.id] + newLevelDiff;
        _forEachInstanceProperty(_context7 = _filterInstanceProperty(_context8 = node.edges).call(_context8, function (edge) {
          return (
            // Ignore disconnected edges.
            edge.connected &&
            // Ignore circular edges.
            edge.to !== edge.from &&
            // Ignore edges leading to the node that's currently being processed.
            edge[direction] !== node &&
            // Ignore edges connecting to an invisible node.
            nodes.has(edge.toId) &&
            // Ignore edges connecting from an invisible node.
            nodes.has(edge.fromId)
          );
        })).call(_context7, function (edge) {
          var targetNodeId = edge[edgeIdProp];
          var oldLevel = levels[targetNodeId];
          if (oldLevel == null || shouldLevelBeReplaced(newLevel, oldLevel)) {
            levels[targetNodeId] = newLevel;
            stack.push(edge[direction]);
          }
        });
        if (done > limit) {
          // This would run forever on a cyclic graph.
          return {
            v: {
              v: fillLevelsByDirectionCyclic(nodes, levels)
            }
          };
        } else {
          ++done;
        }
      };
      while (node = stack.pop()) {
        var _ret2 = _loop2();
        if (_ret2 === "continue") continue;
        if (_typeof(_ret2) === "object") return _ret2.v;
      }
    };
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var _ret = _loop();
      if (_ret === "continue") continue;
      if (_typeof(_ret) === "object") return _ret.v;
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return levels;
}

/**
 * There's a mix-up with terms in the code. Following are the formal definitions:
 *
 *   tree   - a strict hierarchical network, i.e. every node has at most one parent
 *   forest - a collection of trees. These distinct trees are thus not connected.
 *
 * So:
 * - in a network that is not a tree, there exist nodes with multiple parents.
 * - a network consisting of unconnected sub-networks, of which at least one
 *   is not a tree, is not a forest.
 *
 * In the code, the definitions are:
 *
 *   tree   - any disconnected sub-network, strict hierarchical or not.
 *   forest - a bunch of these sub-networks
 *
 * The difference between tree and not-tree is important in the code, notably within
 * to the block-shifting algorithm. The algorithm assumes formal trees and fails
 * for not-trees, often in a spectacular manner (search for 'exploding network' in the issues).
 *
 * In order to distinguish the definitions in the following code, the adjective 'formal' is
 * used. If 'formal' is absent, you must assume the non-formal definition.
 *
 * ----------------------------------------------------------------------------------
 * NOTES
 * =====
 *
 * A hierarchical layout is a different thing from a hierarchical network.
 * The layout is a way to arrange the nodes in the view; this can be done
 * on non-hierarchical networks as well. The converse is also possible.
 */

/**
 * Container for derived data on current network, relating to hierarchy.
 *
 * @private
 */
var HierarchicalStatus = /*#__PURE__*/function () {
  /**
   * @ignore
   */
  function HierarchicalStatus() {
    _classCallCheck(this, HierarchicalStatus);
    this.childrenReference = {}; // child id's per node id
    this.parentReference = {}; // parent id's per node id
    this.trees = {}; // tree id per node id; i.e. to which tree does given node id belong

    this.distributionOrdering = {}; // The nodes per level, in the display order
    this.levels = {}; // hierarchy level per node id
    this.distributionIndex = {}; // The position of the node in the level sorting order, per node id.

    this.isTree = false; // True if current network is a formal tree
    this.treeIndex = -1; // Highest tree id in current network.
  }

  /**
   * Add the relation between given nodes to the current state.
   *
   * @param {Node.id} parentNodeId
   * @param {Node.id} childNodeId
   */
  _createClass(HierarchicalStatus, [{
    key: "addRelation",
    value: function addRelation(parentNodeId, childNodeId) {
      if (this.childrenReference[parentNodeId] === undefined) {
        this.childrenReference[parentNodeId] = [];
      }
      this.childrenReference[parentNodeId].push(childNodeId);
      if (this.parentReference[childNodeId] === undefined) {
        this.parentReference[childNodeId] = [];
      }
      this.parentReference[childNodeId].push(parentNodeId);
    }

    /**
     * Check if the current state is for a formal tree or formal forest.
     *
     * This is the case if every node has at most one parent.
     *
     * Pre: parentReference init'ed properly for current network
     */
  }, {
    key: "checkIfTree",
    value: function checkIfTree() {
      for (var i in this.parentReference) {
        if (this.parentReference[i].length > 1) {
          this.isTree = false;
          return;
        }
      }
      this.isTree = true;
    }

    /**
     * Return the number of separate trees in the current network.
     *
     * @returns {number}
     */
  }, {
    key: "numTrees",
    value: function numTrees() {
      return this.treeIndex + 1; // This assumes the indexes are assigned consecitively
    }

    /**
     * Assign a tree id to a node
     *
     * @param {Node} node
     * @param {string|number} treeId
     */
  }, {
    key: "setTreeIndex",
    value: function setTreeIndex(node, treeId) {
      if (treeId === undefined) return; // Don't bother

      if (this.trees[node.id] === undefined) {
        this.trees[node.id] = treeId;
        this.treeIndex = Math.max(treeId, this.treeIndex);
      }
    }

    /**
     * Ensure level for given id is defined.
     *
     * Sets level to zero for given node id if not already present
     *
     * @param {Node.id} nodeId
     */
  }, {
    key: "ensureLevel",
    value: function ensureLevel(nodeId) {
      if (this.levels[nodeId] === undefined) {
        this.levels[nodeId] = 0;
      }
    }

    /**
     * get the maximum level of a branch.
     *
     * TODO: Never entered; find a test case to test this!
     *
     * @param {Node.id} nodeId
     * @returns {number}
     */
  }, {
    key: "getMaxLevel",
    value: function getMaxLevel(nodeId) {
      var _this = this;
      var accumulator = {};
      var _getMaxLevel = function _getMaxLevel(nodeId) {
        if (accumulator[nodeId] !== undefined) {
          return accumulator[nodeId];
        }
        var level = _this.levels[nodeId];
        if (_this.childrenReference[nodeId]) {
          var children = _this.childrenReference[nodeId];
          if (children.length > 0) {
            for (var i = 0; i < children.length; i++) {
              level = Math.max(level, _getMaxLevel(children[i]));
            }
          }
        }
        accumulator[nodeId] = level;
        return level;
      };
      return _getMaxLevel(nodeId);
    }

    /**
     *
     * @param {Node} nodeA
     * @param {Node} nodeB
     */
  }, {
    key: "levelDownstream",
    value: function levelDownstream(nodeA, nodeB) {
      if (this.levels[nodeB.id] === undefined) {
        // set initial level
        if (this.levels[nodeA.id] === undefined) {
          this.levels[nodeA.id] = 0;
        }
        // set level
        this.levels[nodeB.id] = this.levels[nodeA.id] + 1;
      }
    }

    /**
     * Small util method to set the minimum levels of the nodes to zero.
     *
     * @param {Array.<Node>} nodes
     */
  }, {
    key: "setMinLevelToZero",
    value: function setMinLevelToZero(nodes) {
      var minLevel = 1e9;
      // get the minimum level
      for (var nodeId in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
          if (this.levels[nodeId] !== undefined) {
            minLevel = Math.min(this.levels[nodeId], minLevel);
          }
        }
      }

      // subtract the minimum from the set so we have a range starting from 0
      for (var _nodeId in nodes) {
        if (Object.prototype.hasOwnProperty.call(nodes, _nodeId)) {
          if (this.levels[_nodeId] !== undefined) {
            this.levels[_nodeId] -= minLevel;
          }
        }
      }
    }

    /**
     * Get the min and max xy-coordinates of a given tree
     *
     * @param {Array.<Node>} nodes
     * @param {number} index
     * @returns {{min_x: number, max_x: number, min_y: number, max_y: number}}
     */
  }, {
    key: "getTreeSize",
    value: function getTreeSize(nodes, index) {
      var min_x = 1e9;
      var max_x = -1e9;
      var min_y = 1e9;
      var max_y = -1e9;
      for (var nodeId in this.trees) {
        if (Object.prototype.hasOwnProperty.call(this.trees, nodeId)) {
          if (this.trees[nodeId] === index) {
            var node = nodes[nodeId];
            min_x = Math.min(node.x, min_x);
            max_x = Math.max(node.x, max_x);
            min_y = Math.min(node.y, min_y);
            max_y = Math.max(node.y, max_y);
          }
        }
      }
      return {
        min_x: min_x,
        max_x: max_x,
        min_y: min_y,
        max_y: max_y
      };
    }

    /**
     * Check if two nodes have the same parent(s)
     *
     * @param {Node} node1
     * @param {Node} node2
     * @returns {boolean} true if the two nodes have a same ancestor node, false otherwise
     */
  }, {
    key: "hasSameParent",
    value: function hasSameParent(node1, node2) {
      var parents1 = this.parentReference[node1.id];
      var parents2 = this.parentReference[node2.id];
      if (parents1 === undefined || parents2 === undefined) {
        return false;
      }
      for (var i = 0; i < parents1.length; i++) {
        for (var j = 0; j < parents2.length; j++) {
          if (parents1[i] == parents2[j]) {
            return true;
          }
        }
      }
      return false;
    }

    /**
     * Check if two nodes are in the same tree.
     *
     * @param {Node} node1
     * @param {Node} node2
     * @returns {boolean} true if this is so, false otherwise
     */
  }, {
    key: "inSameSubNetwork",
    value: function inSameSubNetwork(node1, node2) {
      return this.trees[node1.id] === this.trees[node2.id];
    }

    /**
     * Get a list of the distinct levels in the current network
     *
     * @returns {Array}
     */
  }, {
    key: "getLevels",
    value: function getLevels() {
      return _Object$keys(this.distributionOrdering);
    }

    /**
     * Add a node to the ordering per level
     *
     * @param {Node} node
     * @param {number} level
     */
  }, {
    key: "addToOrdering",
    value: function addToOrdering(node, level) {
      if (this.distributionOrdering[level] === undefined) {
        this.distributionOrdering[level] = [];
      }
      var isPresent = false;
      var curLevel = this.distributionOrdering[level];
      for (var n in curLevel) {
        //if (curLevel[n].id === node.id) {
        if (curLevel[n] === node) {
          isPresent = true;
          break;
        }
      }
      if (!isPresent) {
        this.distributionOrdering[level].push(node);
        this.distributionIndex[node.id] = this.distributionOrdering[level].length - 1;
      }
    }
  }]);
  return HierarchicalStatus;
}();
/**
 * The Layout Engine
 */
var LayoutEngine = /*#__PURE__*/function () {
  /**
   * @param {object} body
   */
  function LayoutEngine(body) {
    _classCallCheck(this, LayoutEngine);
    this.body = body;

    // Make sure there always is some RNG because the setOptions method won't
    // set it unless there's a seed for it.
    this._resetRNG(Math.random() + ":" + _Date$now());
    this.setPhysics = false;
    this.options = {};
    this.optionsBackup = {
      physics: {}
    };
    this.defaultOptions = {
      randomSeed: undefined,
      improvedLayout: true,
      clusterThreshold: 150,
      hierarchical: {
        enabled: false,
        levelSeparation: 150,
        nodeSpacing: 100,
        treeSpacing: 200,
        blockShifting: true,
        edgeMinimization: true,
        parentCentralization: true,
        direction: "UD",
        // UD, DU, LR, RL
        sortMethod: "hubsize" // hubsize, directed
      }
    };

    _Object$assign(this.options, this.defaultOptions);
    this.bindEventListeners();
  }

  /**
   * Binds event listeners
   */
  _createClass(LayoutEngine, [{
    key: "bindEventListeners",
    value: function bindEventListeners() {
      var _this2 = this;
      this.body.emitter.on("_dataChanged", function () {
        _this2.setupHierarchicalLayout();
      });
      this.body.emitter.on("_dataLoaded", function () {
        _this2.layoutNetwork();
      });
      this.body.emitter.on("_resetHierarchicalLayout", function () {
        _this2.setupHierarchicalLayout();
      });
      this.body.emitter.on("_adjustEdgesForHierarchicalLayout", function () {
        if (_this2.options.hierarchical.enabled !== true) {
          return;
        }
        // get the type of static smooth curve in case it is required
        var type = _this2.direction.curveType();

        // force all edges into static smooth curves.
        _this2.body.emitter.emit("_forceDisableDynamicCurves", type, false);
      });
    }

    /**
     *
     * @param {object} options
     * @param {object} allOptions
     * @returns {object}
     */
  }, {
    key: "setOptions",
    value: function setOptions(options, allOptions) {
      if (options !== undefined) {
        var hierarchical = this.options.hierarchical;
        var prevHierarchicalState = hierarchical.enabled;
        selectiveDeepExtend(["randomSeed", "improvedLayout", "clusterThreshold"], this.options, options);
        mergeOptions(this.options, options, "hierarchical");
        if (options.randomSeed !== undefined) {
          this._resetRNG(options.randomSeed);
        }
        if (hierarchical.enabled === true) {
          if (prevHierarchicalState === true) {
            // refresh the overridden options for nodes and edges.
            this.body.emitter.emit("refresh", true);
          }

          // make sure the level separation is the right way up
          if (hierarchical.direction === "RL" || hierarchical.direction === "DU") {
            if (hierarchical.levelSeparation > 0) {
              hierarchical.levelSeparation *= -1;
            }
          } else {
            if (hierarchical.levelSeparation < 0) {
              hierarchical.levelSeparation *= -1;
            }
          }
          this.setDirectionStrategy();
          this.body.emitter.emit("_resetHierarchicalLayout");
          // because the hierarchical system needs it's own physics and smooth curve settings,
          // we adapt the other options if needed.
          return this.adaptAllOptionsForHierarchicalLayout(allOptions);
        } else {
          if (prevHierarchicalState === true) {
            // refresh the overridden options for nodes and edges.
            this.body.emitter.emit("refresh");
            return deepExtend(allOptions, this.optionsBackup);
          }
        }
      }
      return allOptions;
    }

    /**
     * Reset the random number generator with given seed.
     *
     * @param {any} seed - The seed that will be forwarded the the RNG.
     */
  }, {
    key: "_resetRNG",
    value: function _resetRNG(seed) {
      this.initialRandomSeed = seed;
      this._rng = Alea(this.initialRandomSeed);
    }

    /**
     *
     * @param {object} allOptions
     * @returns {object}
     */
  }, {
    key: "adaptAllOptionsForHierarchicalLayout",
    value: function adaptAllOptionsForHierarchicalLayout(allOptions) {
      if (this.options.hierarchical.enabled === true) {
        var backupPhysics = this.optionsBackup.physics;

        // set the physics
        if (allOptions.physics === undefined || allOptions.physics === true) {
          allOptions.physics = {
            enabled: backupPhysics.enabled === undefined ? true : backupPhysics.enabled,
            solver: "hierarchicalRepulsion"
          };
          backupPhysics.enabled = backupPhysics.enabled === undefined ? true : backupPhysics.enabled;
          backupPhysics.solver = backupPhysics.solver || "barnesHut";
        } else if (_typeof(allOptions.physics) === "object") {
          backupPhysics.enabled = allOptions.physics.enabled === undefined ? true : allOptions.physics.enabled;
          backupPhysics.solver = allOptions.physics.solver || "barnesHut";
          allOptions.physics.solver = "hierarchicalRepulsion";
        } else if (allOptions.physics !== false) {
          backupPhysics.solver = "barnesHut";
          allOptions.physics = {
            solver: "hierarchicalRepulsion"
          };
        }

        // get the type of static smooth curve in case it is required
        var type = this.direction.curveType();

        // disable smooth curves if nothing is defined. If smooth curves have been turned on,
        // turn them into static smooth curves.
        if (allOptions.edges === undefined) {
          this.optionsBackup.edges = {
            smooth: {
              enabled: true,
              type: "dynamic"
            }
          };
          allOptions.edges = {
            smooth: false
          };
        } else if (allOptions.edges.smooth === undefined) {
          this.optionsBackup.edges = {
            smooth: {
              enabled: true,
              type: "dynamic"
            }
          };
          allOptions.edges.smooth = false;
        } else {
          if (typeof allOptions.edges.smooth === "boolean") {
            this.optionsBackup.edges = {
              smooth: allOptions.edges.smooth
            };
            allOptions.edges.smooth = {
              enabled: allOptions.edges.smooth,
              type: type
            };
          } else {
            var smooth = allOptions.edges.smooth;

            // allow custom types except for dynamic
            if (smooth.type !== undefined && smooth.type !== "dynamic") {
              type = smooth.type;
            }

            // TODO: this is options merging; see if the standard routines can be used here.
            this.optionsBackup.edges = {
              smooth: {
                enabled: smooth.enabled === undefined ? true : smooth.enabled,
                type: smooth.type === undefined ? "dynamic" : smooth.type,
                roundness: smooth.roundness === undefined ? 0.5 : smooth.roundness,
                forceDirection: smooth.forceDirection === undefined ? false : smooth.forceDirection
              }
            };

            // NOTE: Copying an object to self; this is basically setting defaults for undefined variables
            allOptions.edges.smooth = {
              enabled: smooth.enabled === undefined ? true : smooth.enabled,
              type: type,
              roundness: smooth.roundness === undefined ? 0.5 : smooth.roundness,
              forceDirection: smooth.forceDirection === undefined ? false : smooth.forceDirection
            };
          }
        }

        // Force all edges into static smooth curves.
        // Only applies to edges that do not use the global options for smooth.
        this.body.emitter.emit("_forceDisableDynamicCurves", type);
      }
      return allOptions;
    }

    /**
     *
     * @param {Array.<Node>} nodesArray
     */
  }, {
    key: "positionInitially",
    value: function positionInitially(nodesArray) {
      if (this.options.hierarchical.enabled !== true) {
        this._resetRNG(this.initialRandomSeed);
        var radius = nodesArray.length + 50;
        for (var i = 0; i < nodesArray.length; i++) {
          var node = nodesArray[i];
          var angle = 2 * Math.PI * this._rng();
          if (node.x === undefined) {
            node.x = radius * Math.cos(angle);
          }
          if (node.y === undefined) {
            node.y = radius * Math.sin(angle);
          }
        }
      }
    }

    /**
     * Use Kamada Kawai to position nodes. This is quite a heavy algorithm so if there are a lot of nodes we
     * cluster them first to reduce the amount.
     */
  }, {
    key: "layoutNetwork",
    value: function layoutNetwork() {
      if (this.options.hierarchical.enabled !== true && this.options.improvedLayout === true) {
        var indices = this.body.nodeIndices;

        // first check if we should Kamada Kawai to layout. The threshold is if less than half of the visible
        // nodes have predefined positions we use this.
        var positionDefined = 0;
        for (var i = 0; i < indices.length; i++) {
          var node = this.body.nodes[indices[i]];
          if (node.predefinedPosition === true) {
            positionDefined += 1;
          }
        }

        // if less than half of the nodes have a predefined position we continue
        if (positionDefined < 0.5 * indices.length) {
          var MAX_LEVELS = 10;
          var level = 0;
          var clusterThreshold = this.options.clusterThreshold;

          //
          // Define the options for the hidden cluster nodes
          // These options don't propagate outside the clustering phase.
          //
          // Some options are explicitly disabled, because they may be set in group or default node options.
          // The clusters are never displayed, so most explicit settings here serve as performance optimizations.
          //
          // The explicit setting of 'shape' is to avoid `shape: 'image'`; images are not passed to the hidden
          // cluster nodes, leading to an exception on creation.
          //
          // All settings here are performance related, except when noted otherwise.
          //
          var clusterOptions = {
            clusterNodeProperties: {
              shape: "ellipse",
              // Bugfix: avoid type 'image', no images supplied
              label: "",
              // avoid label handling
              group: "",
              // avoid group handling
              font: {
                multi: false
              } // avoid font propagation
            },

            clusterEdgeProperties: {
              label: "",
              // avoid label handling
              font: {
                multi: false
              },
              // avoid font propagation
              smooth: {
                enabled: false // avoid drawing penalty for complex edges
              }
            }
          };

          // if there are a lot of nodes, we cluster before we run the algorithm.
          // NOTE: this part fails to find clusters for large scale-free networks, which should
          //       be easily clusterable.
          // TODO: examine why this is so
          if (indices.length > clusterThreshold) {
            var startLength = indices.length;
            while (indices.length > clusterThreshold && level <= MAX_LEVELS) {
              //console.time("clustering")
              level += 1;
              var before = indices.length;
              // if there are many nodes we do a hubsize cluster
              if (level % 3 === 0) {
                this.body.modules.clustering.clusterBridges(clusterOptions);
              } else {
                this.body.modules.clustering.clusterOutliers(clusterOptions);
              }
              var after = indices.length;
              if (before == after && level % 3 !== 0) {
                this._declusterAll();
                this.body.emitter.emit("_layoutFailed");
                console.info("This network could not be positioned by this version of the improved layout algorithm." + " Please disable improvedLayout for better performance.");
                return;
              }
              //console.timeEnd("clustering")
              //console.log(before,level,after);
            }
            // increase the size of the edges
            this.body.modules.kamadaKawai.setOptions({
              springLength: Math.max(150, 2 * startLength)
            });
          }
          if (level > MAX_LEVELS) {
            console.info("The clustering didn't succeed within the amount of interations allowed," + " progressing with partial result.");
          }

          // position the system for these nodes and edges
          this.body.modules.kamadaKawai.solve(indices, this.body.edgeIndices, true);

          // shift to center point
          this._shiftToCenter();

          // perturb the nodes a little bit to force the physics to kick in
          var offset = 70;
          for (var _i = 0; _i < indices.length; _i++) {
            // Only perturb the nodes that aren't fixed
            var _node = this.body.nodes[indices[_i]];
            if (_node.predefinedPosition === false) {
              _node.x += (0.5 - this._rng()) * offset;
              _node.y += (0.5 - this._rng()) * offset;
            }
          }

          // uncluster all clusters
          this._declusterAll();

          // reposition all bezier nodes.
          this.body.emitter.emit("_repositionBezierNodes");
        }
      }
    }

    /**
     * Move all the nodes towards to the center so gravitational pull wil not move the nodes away from view
     *
     * @private
     */
  }, {
    key: "_shiftToCenter",
    value: function _shiftToCenter() {
      var range = NetworkUtil.getRangeCore(this.body.nodes, this.body.nodeIndices);
      var center = NetworkUtil.findCenter(range);
      for (var i = 0; i < this.body.nodeIndices.length; i++) {
        var node = this.body.nodes[this.body.nodeIndices[i]];
        node.x -= center.x;
        node.y -= center.y;
      }
    }

    /**
     * Expands all clusters
     *
     * @private
     */
  }, {
    key: "_declusterAll",
    value: function _declusterAll() {
      var clustersPresent = true;
      while (clustersPresent === true) {
        clustersPresent = false;
        for (var i = 0; i < this.body.nodeIndices.length; i++) {
          if (this.body.nodes[this.body.nodeIndices[i]].isCluster === true) {
            clustersPresent = true;
            this.body.modules.clustering.openCluster(this.body.nodeIndices[i], {}, false);
          }
        }
        if (clustersPresent === true) {
          this.body.emitter.emit("_dataChanged");
        }
      }
    }

    /**
     *
     * @returns {number|*}
     */
  }, {
    key: "getSeed",
    value: function getSeed() {
      return this.initialRandomSeed;
    }

    /**
     * This is the main function to layout the nodes in a hierarchical way.
     * It checks if the node details are supplied correctly
     *
     * @private
     */
  }, {
    key: "setupHierarchicalLayout",
    value: function setupHierarchicalLayout() {
      if (this.options.hierarchical.enabled === true && this.body.nodeIndices.length > 0) {
        // get the size of the largest hubs and check if the user has defined a level for a node.
        var node, nodeId;
        var definedLevel = false;
        var undefinedLevel = false;
        this.lastNodeOnLevel = {};
        this.hierarchical = new HierarchicalStatus();
        for (nodeId in this.body.nodes) {
          if (Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) {
            node = this.body.nodes[nodeId];
            if (node.options.level !== undefined) {
              definedLevel = true;
              this.hierarchical.levels[nodeId] = node.options.level;
            } else {
              undefinedLevel = true;
            }
          }
        }

        // if the user defined some levels but not all, alert and run without hierarchical layout
        if (undefinedLevel === true && definedLevel === true) {
          throw new Error("To use the hierarchical layout, nodes require either no predefined levels" + " or levels have to be defined for all nodes.");
        } else {
          // define levels if undefined by the users. Based on hubsize.
          if (undefinedLevel === true) {
            var sortMethod = this.options.hierarchical.sortMethod;
            if (sortMethod === "hubsize") {
              this._determineLevelsByHubsize();
            } else if (sortMethod === "directed") {
              this._determineLevelsDirected();
            } else if (sortMethod === "custom") {
              this._determineLevelsCustomCallback();
            }
          }

          // fallback for cases where there are nodes but no edges
          for (var _nodeId2 in this.body.nodes) {
            if (Object.prototype.hasOwnProperty.call(this.body.nodes, _nodeId2)) {
              this.hierarchical.ensureLevel(_nodeId2);
            }
          }
          // check the distribution of the nodes per level.
          var distribution = this._getDistribution();

          // get the parent children relations.
          this._generateMap();

          // place the nodes on the canvas.
          this._placeNodesByHierarchy(distribution);

          // condense the whitespace.
          this._condenseHierarchy();

          // shift to center so gravity does not have to do much
          this._shiftToCenter();
        }
      }
    }

    /**
     * @private
     */
  }, {
    key: "_condenseHierarchy",
    value: function _condenseHierarchy() {
      var _this3 = this;
      // Global var in this scope to define when the movement has stopped.
      var stillShifting = false;
      var branches = {};
      // first we have some methods to help shifting trees around.
      // the main method to shift the trees
      var shiftTrees = function shiftTrees() {
        var treeSizes = getTreeSizes();
        var shiftBy = 0;
        for (var i = 0; i < treeSizes.length - 1; i++) {
          var diff = treeSizes[i].max - treeSizes[i + 1].min;
          shiftBy += diff + _this3.options.hierarchical.treeSpacing;
          shiftTree(i + 1, shiftBy);
        }
      };

      // shift a single tree by an offset
      var shiftTree = function shiftTree(index, offset) {
        var trees = _this3.hierarchical.trees;
        for (var nodeId in trees) {
          if (Object.prototype.hasOwnProperty.call(trees, nodeId)) {
            if (trees[nodeId] === index) {
              _this3.direction.shift(nodeId, offset);
            }
          }
        }
      };

      // get the width of all trees
      var getTreeSizes = function getTreeSizes() {
        var treeWidths = [];
        for (var i = 0; i < _this3.hierarchical.numTrees(); i++) {
          treeWidths.push(_this3.direction.getTreeSize(i));
        }
        return treeWidths;
      };

      // get a map of all nodes in this branch
      var getBranchNodes = function getBranchNodes(source, map) {
        if (map[source.id]) {
          return;
        }
        map[source.id] = true;
        if (_this3.hierarchical.childrenReference[source.id]) {
          var children = _this3.hierarchical.childrenReference[source.id];
          if (children.length > 0) {
            for (var i = 0; i < children.length; i++) {
              getBranchNodes(_this3.body.nodes[children[i]], map);
            }
          }
        }
      };

      // get a min max width as well as the maximum movement space it has on either sides
      // we use min max terminology because width and height can interchange depending on the direction of the layout
      var getBranchBoundary = function getBranchBoundary(branchMap) {
        var maxLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e9;
        var minSpace = 1e9;
        var maxSpace = 1e9;
        var min = 1e9;
        var max = -1e9;
        for (var branchNode in branchMap) {
          if (Object.prototype.hasOwnProperty.call(branchMap, branchNode)) {
            var node = _this3.body.nodes[branchNode];
            var level = _this3.hierarchical.levels[node.id];
            var position = _this3.direction.getPosition(node);

            // get the space around the node.
            var _this3$_getSpaceAroun = _this3._getSpaceAroundNode(node, branchMap),
              _this3$_getSpaceAroun2 = _slicedToArray(_this3$_getSpaceAroun, 2),
              minSpaceNode = _this3$_getSpaceAroun2[0],
              maxSpaceNode = _this3$_getSpaceAroun2[1];
            minSpace = Math.min(minSpaceNode, minSpace);
            maxSpace = Math.min(maxSpaceNode, maxSpace);

            // the width is only relevant for the levels two nodes have in common. This is why we filter on this.
            if (level <= maxLevel) {
              min = Math.min(position, min);
              max = Math.max(position, max);
            }
          }
        }
        return [min, max, minSpace, maxSpace];
      };

      // check what the maximum level is these nodes have in common.
      var getCollisionLevel = function getCollisionLevel(node1, node2) {
        var maxLevel1 = _this3.hierarchical.getMaxLevel(node1.id);
        var maxLevel2 = _this3.hierarchical.getMaxLevel(node2.id);
        return Math.min(maxLevel1, maxLevel2);
      };

      /**
       * Condense elements. These can be nodes or branches depending on the callback.
       *
       * @param {Function} callback
       * @param {Array.<number>} levels
       * @param {*} centerParents
       */
      var shiftElementsCloser = function shiftElementsCloser(callback, levels, centerParents) {
        var hier = _this3.hierarchical;
        for (var i = 0; i < levels.length; i++) {
          var level = levels[i];
          var levelNodes = hier.distributionOrdering[level];
          if (levelNodes.length > 1) {
            for (var j = 0; j < levelNodes.length - 1; j++) {
              var node1 = levelNodes[j];
              var node2 = levelNodes[j + 1];

              // NOTE: logic maintained as it was; if nodes have same ancestor,
              //       then of course they are in the same sub-network.
              if (hier.hasSameParent(node1, node2) && hier.inSameSubNetwork(node1, node2)) {
                callback(node1, node2, centerParents);
              }
            }
          }
        }
      };

      // callback for shifting branches
      var branchShiftCallback = function branchShiftCallback(node1, node2) {
        var centerParent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
        //window.CALLBACKS.push(() => {
        var pos1 = _this3.direction.getPosition(node1);
        var pos2 = _this3.direction.getPosition(node2);
        var diffAbs = Math.abs(pos2 - pos1);
        var nodeSpacing = _this3.options.hierarchical.nodeSpacing;
        //console.log("NOW CHECKING:", node1.id, node2.id, diffAbs);
        if (diffAbs > nodeSpacing) {
          var branchNodes1 = {};
          var branchNodes2 = {};
          getBranchNodes(node1, branchNodes1);
          getBranchNodes(node2, branchNodes2);

          // check the largest distance between the branches
          var maxLevel = getCollisionLevel(node1, node2);
          var branchNodeBoundary1 = getBranchBoundary(branchNodes1, maxLevel);
          var branchNodeBoundary2 = getBranchBoundary(branchNodes2, maxLevel);
          var max1 = branchNodeBoundary1[1];
          var min2 = branchNodeBoundary2[0];
          var minSpace2 = branchNodeBoundary2[2];

          //console.log(node1.id, getBranchBoundary(branchNodes1, maxLevel), node2.id,
          //            getBranchBoundary(branchNodes2, maxLevel), maxLevel);
          var diffBranch = Math.abs(max1 - min2);
          if (diffBranch > nodeSpacing) {
            var offset = max1 - min2 + nodeSpacing;
            if (offset < -minSpace2 + nodeSpacing) {
              offset = -minSpace2 + nodeSpacing;
              //console.log("RESETTING OFFSET", max1 - min2 + this.options.hierarchical.nodeSpacing, -minSpace2, offset);
            }

            if (offset < 0) {
              //console.log("SHIFTING", node2.id, offset);
              _this3._shiftBlock(node2.id, offset);
              stillShifting = true;
              if (centerParent === true) _this3._centerParent(node2);
            }
          }
        }
        //this.body.emitter.emit("_redraw");})
      };

      var minimizeEdgeLength = function minimizeEdgeLength(iterations, node) {
        //window.CALLBACKS.push(() => {
        //  console.log("ts",node.id);
        var nodeId = node.id;
        var allEdges = node.edges;
        var nodeLevel = _this3.hierarchical.levels[node.id];

        // gather constants
        var C2 = _this3.options.hierarchical.levelSeparation * _this3.options.hierarchical.levelSeparation;
        var referenceNodes = {};
        var aboveEdges = [];
        for (var i = 0; i < allEdges.length; i++) {
          var edge = allEdges[i];
          if (edge.toId != edge.fromId) {
            var otherNode = edge.toId == nodeId ? edge.from : edge.to;
            referenceNodes[allEdges[i].id] = otherNode;
            if (_this3.hierarchical.levels[otherNode.id] < nodeLevel) {
              aboveEdges.push(edge);
            }
          }
        }

        // differentiated sum of lengths based on only moving one node over one axis
        var getFx = function getFx(point, edges) {
          var sum = 0;
          for (var _i2 = 0; _i2 < edges.length; _i2++) {
            if (referenceNodes[edges[_i2].id] !== undefined) {
              var a = _this3.direction.getPosition(referenceNodes[edges[_i2].id]) - point;
              sum += a / Math.sqrt(a * a + C2);
            }
          }
          return sum;
        };

        // doubly differentiated sum of lengths based on only moving one node over one axis
        var getDFx = function getDFx(point, edges) {
          var sum = 0;
          for (var _i3 = 0; _i3 < edges.length; _i3++) {
            if (referenceNodes[edges[_i3].id] !== undefined) {
              var a = _this3.direction.getPosition(referenceNodes[edges[_i3].id]) - point;
              sum -= C2 * Math.pow(a * a + C2, -1.5);
            }
          }
          return sum;
        };
        var getGuess = function getGuess(iterations, edges) {
          var guess = _this3.direction.getPosition(node);
          // Newton's method for optimization
          var guessMap = {};
          for (var _i4 = 0; _i4 < iterations; _i4++) {
            var fx = getFx(guess, edges);
            var dfx = getDFx(guess, edges);

            // we limit the movement to avoid instability.
            var limit = 40;
            var ratio = Math.max(-limit, Math.min(limit, Math.round(fx / dfx)));
            guess = guess - ratio;
            // reduce duplicates
            if (guessMap[guess] !== undefined) {
              break;
            }
            guessMap[guess] = _i4;
          }
          return guess;
        };
        var moveBranch = function moveBranch(guess) {
          // position node if there is space
          var nodePosition = _this3.direction.getPosition(node);

          // check movable area of the branch
          if (branches[node.id] === undefined) {
            var branchNodes = {};
            getBranchNodes(node, branchNodes);
            branches[node.id] = branchNodes;
          }
          var branchBoundary = getBranchBoundary(branches[node.id]);
          var minSpaceBranch = branchBoundary[2];
          var maxSpaceBranch = branchBoundary[3];
          var diff = guess - nodePosition;

          // check if we are allowed to move the node:
          var branchOffset = 0;
          if (diff > 0) {
            branchOffset = Math.min(diff, maxSpaceBranch - _this3.options.hierarchical.nodeSpacing);
          } else if (diff < 0) {
            branchOffset = -Math.min(-diff, minSpaceBranch - _this3.options.hierarchical.nodeSpacing);
          }
          if (branchOffset != 0) {
            //console.log("moving branch:",branchOffset, maxSpaceBranch, minSpaceBranch)
            _this3._shiftBlock(node.id, branchOffset);
            //this.body.emitter.emit("_redraw");
            stillShifting = true;
          }
        };
        var moveNode = function moveNode(guess) {
          var nodePosition = _this3.direction.getPosition(node);

          // position node if there is space
          var _this3$_getSpaceAroun3 = _this3._getSpaceAroundNode(node),
            _this3$_getSpaceAroun4 = _slicedToArray(_this3$_getSpaceAroun3, 2),
            minSpace = _this3$_getSpaceAroun4[0],
            maxSpace = _this3$_getSpaceAroun4[1];
          var diff = guess - nodePosition;
          // check if we are allowed to move the node:
          var newPosition = nodePosition;
          if (diff > 0) {
            newPosition = Math.min(nodePosition + (maxSpace - _this3.options.hierarchical.nodeSpacing), guess);
          } else if (diff < 0) {
            newPosition = Math.max(nodePosition - (minSpace - _this3.options.hierarchical.nodeSpacing), guess);
          }
          if (newPosition !== nodePosition) {
            //console.log("moving Node:",diff, minSpace, maxSpace);
            _this3.direction.setPosition(node, newPosition);
            //this.body.emitter.emit("_redraw");
            stillShifting = true;
          }
        };
        var guess = getGuess(iterations, aboveEdges);
        moveBranch(guess);
        guess = getGuess(iterations, allEdges);
        moveNode(guess);
        //})
      };

      // method to remove whitespace between branches. Because we do bottom up, we can center the parents.
      var minimizeEdgeLengthBottomUp = function minimizeEdgeLengthBottomUp(iterations) {
        var levels = _this3.hierarchical.getLevels();
        levels = _reverseInstanceProperty(levels).call(levels);
        for (var i = 0; i < iterations; i++) {
          stillShifting = false;
          for (var j = 0; j < levels.length; j++) {
            var level = levels[j];
            var levelNodes = _this3.hierarchical.distributionOrdering[level];
            for (var k = 0; k < levelNodes.length; k++) {
              minimizeEdgeLength(1000, levelNodes[k]);
            }
          }
          if (stillShifting !== true) {
            //console.log("FINISHED minimizeEdgeLengthBottomUp IN " + i);
            break;
          }
        }
      };

      // method to remove whitespace between branches. Because we do bottom up, we can center the parents.
      var shiftBranchesCloserBottomUp = function shiftBranchesCloserBottomUp(iterations) {
        var levels = _this3.hierarchical.getLevels();
        levels = _reverseInstanceProperty(levels).call(levels);
        for (var i = 0; i < iterations; i++) {
          stillShifting = false;
          shiftElementsCloser(branchShiftCallback, levels, true);
          if (stillShifting !== true) {
            //console.log("FINISHED shiftBranchesCloserBottomUp IN " + (i+1));
            break;
          }
        }
      };

      // center all parents
      var centerAllParents = function centerAllParents() {
        for (var nodeId in _this3.body.nodes) {
          if (Object.prototype.hasOwnProperty.call(_this3.body.nodes, nodeId)) _this3._centerParent(_this3.body.nodes[nodeId]);
        }
      };

      // center all parents
      var centerAllParentsBottomUp = function centerAllParentsBottomUp() {
        var levels = _this3.hierarchical.getLevels();
        levels = _reverseInstanceProperty(levels).call(levels);
        for (var i = 0; i < levels.length; i++) {
          var level = levels[i];
          var levelNodes = _this3.hierarchical.distributionOrdering[level];
          for (var j = 0; j < levelNodes.length; j++) {
            _this3._centerParent(levelNodes[j]);
          }
        }
      };

      // the actual work is done here.
      if (this.options.hierarchical.blockShifting === true) {
        shiftBranchesCloserBottomUp(5);
        centerAllParents();
      }

      // minimize edge length
      if (this.options.hierarchical.edgeMinimization === true) {
        minimizeEdgeLengthBottomUp(20);
      }
      if (this.options.hierarchical.parentCentralization === true) {
        centerAllParentsBottomUp();
      }
      shiftTrees();
    }

    /**
     * This gives the space around the node. IF a map is supplied, it will only check against nodes NOT in the map.
     * This is used to only get the distances to nodes outside of a branch.
     *
     * @param {Node} node
     * @param {{Node.id: vis.Node}} map
     * @returns {number[]}
     * @private
     */
  }, {
    key: "_getSpaceAroundNode",
    value: function _getSpaceAroundNode(node, map) {
      var useMap = true;
      if (map === undefined) {
        useMap = false;
      }
      var level = this.hierarchical.levels[node.id];
      if (level !== undefined) {
        var index = this.hierarchical.distributionIndex[node.id];
        var position = this.direction.getPosition(node);
        var ordering = this.hierarchical.distributionOrdering[level];
        var minSpace = 1e9;
        var maxSpace = 1e9;
        if (index !== 0) {
          var prevNode = ordering[index - 1];
          if (useMap === true && map[prevNode.id] === undefined || useMap === false) {
            var prevPos = this.direction.getPosition(prevNode);
            minSpace = position - prevPos;
          }
        }
        if (index != ordering.length - 1) {
          var nextNode = ordering[index + 1];
          if (useMap === true && map[nextNode.id] === undefined || useMap === false) {
            var nextPos = this.direction.getPosition(nextNode);
            maxSpace = Math.min(maxSpace, nextPos - position);
          }
        }
        return [minSpace, maxSpace];
      } else {
        return [0, 0];
      }
    }

    /**
     * We use this method to center a parent node and check if it does not cross other nodes when it does.
     *
     * @param {Node} node
     * @private
     */
  }, {
    key: "_centerParent",
    value: function _centerParent(node) {
      if (this.hierarchical.parentReference[node.id]) {
        var parents = this.hierarchical.parentReference[node.id];
        for (var i = 0; i < parents.length; i++) {
          var parentId = parents[i];
          var parentNode = this.body.nodes[parentId];
          var children = this.hierarchical.childrenReference[parentId];
          if (children !== undefined) {
            // get the range of the children
            var newPosition = this._getCenterPosition(children);
            var position = this.direction.getPosition(parentNode);
            var _this$_getSpaceAround = this._getSpaceAroundNode(parentNode),
              _this$_getSpaceAround2 = _slicedToArray(_this$_getSpaceAround, 2),
              minSpace = _this$_getSpaceAround2[0],
              maxSpace = _this$_getSpaceAround2[1];
            var diff = position - newPosition;
            if (diff < 0 && Math.abs(diff) < maxSpace - this.options.hierarchical.nodeSpacing || diff > 0 && Math.abs(diff) < minSpace - this.options.hierarchical.nodeSpacing) {
              this.direction.setPosition(parentNode, newPosition);
            }
          }
        }
      }
    }

    /**
     * This function places the nodes on the canvas based on the hierarchial distribution.
     *
     * @param {object} distribution | obtained by the function this._getDistribution()
     * @private
     */
  }, {
    key: "_placeNodesByHierarchy",
    value: function _placeNodesByHierarchy(distribution) {
      this.positionedNodes = {};
      // start placing all the level 0 nodes first. Then recursively position their branches.
      for (var level in distribution) {
        if (Object.prototype.hasOwnProperty.call(distribution, level)) {
          var _context;
          // sort nodes in level by position:
          var nodeArray = _Object$keys(distribution[level]);
          nodeArray = this._indexArrayToNodes(nodeArray);
          _sortInstanceProperty(_context = this.direction).call(_context, nodeArray);
          var handledNodeCount = 0;
          for (var i = 0; i < nodeArray.length; i++) {
            var node = nodeArray[i];
            if (this.positionedNodes[node.id] === undefined) {
              var spacing = this.options.hierarchical.nodeSpacing;
              var pos = spacing * handledNodeCount;
              // We get the X or Y values we need and store them in pos and previousPos.
              // The get and set make sure we get X or Y
              if (handledNodeCount > 0) {
                pos = this.direction.getPosition(nodeArray[i - 1]) + spacing;
              }
              this.direction.setPosition(node, pos, level);
              this._validatePositionAndContinue(node, level, pos);
              handledNodeCount++;
            }
          }
        }
      }
    }

    /**
     * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes
     * on a X position that ensures there will be no overlap.
     *
     * @param {Node.id} parentId
     * @param {number} parentLevel
     * @private
     */
  }, {
    key: "_placeBranchNodes",
    value: function _placeBranchNodes(parentId, parentLevel) {
      var _context2;
      var childRef = this.hierarchical.childrenReference[parentId];

      // if this is not a parent, cancel the placing. This can happen with multiple parents to one child.
      if (childRef === undefined) {
        return;
      }

      // get a list of childNodes
      var childNodes = [];
      for (var i = 0; i < childRef.length; i++) {
        childNodes.push(this.body.nodes[childRef[i]]);
      }

      // use the positions to order the nodes.
      _sortInstanceProperty(_context2 = this.direction).call(_context2, childNodes);

      // position the childNodes
      for (var _i5 = 0; _i5 < childNodes.length; _i5++) {
        var childNode = childNodes[_i5];
        var childNodeLevel = this.hierarchical.levels[childNode.id];
        // check if the child node is below the parent node and if it has already been positioned.
        if (childNodeLevel > parentLevel && this.positionedNodes[childNode.id] === undefined) {
          // get the amount of space required for this node. If parent the width is based on the amount of children.
          var spacing = this.options.hierarchical.nodeSpacing;
          var pos = void 0;

          // we get the X or Y values we need and store them in pos and previousPos.
          // The get and set make sure we get X or Y
          if (_i5 === 0) {
            pos = this.direction.getPosition(this.body.nodes[parentId]);
          } else {
            pos = this.direction.getPosition(childNodes[_i5 - 1]) + spacing;
          }
          this.direction.setPosition(childNode, pos, childNodeLevel);
          this._validatePositionAndContinue(childNode, childNodeLevel, pos);
        } else {
          return;
        }
      }

      // center the parent nodes.
      var center = this._getCenterPosition(childNodes);
      this.direction.setPosition(this.body.nodes[parentId], center, parentLevel);
    }

    /**
     * This method checks for overlap and if required shifts the branch. It also keeps records of positioned nodes.
     * Finally it will call _placeBranchNodes to place the branch nodes.
     *
     * @param {Node} node
     * @param {number} level
     * @param {number} pos
     * @private
     */
  }, {
    key: "_validatePositionAndContinue",
    value: function _validatePositionAndContinue(node, level, pos) {
      // This method only works for formal trees and formal forests
      // Early exit if this is not the case
      if (!this.hierarchical.isTree) return;

      // if overlap has been detected, we shift the branch
      if (this.lastNodeOnLevel[level] !== undefined) {
        var previousPos = this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[level]]);
        if (pos - previousPos < this.options.hierarchical.nodeSpacing) {
          var diff = previousPos + this.options.hierarchical.nodeSpacing - pos;
          var sharedParent = this._findCommonParent(this.lastNodeOnLevel[level], node.id);
          this._shiftBlock(sharedParent.withChild, diff);
        }
      }
      this.lastNodeOnLevel[level] = node.id; // store change in position.
      this.positionedNodes[node.id] = true;
      this._placeBranchNodes(node.id, level);
    }

    /**
     * Receives an array with node indices and returns an array with the actual node references.
     * Used for sorting based on node properties.
     *
     * @param {Array.<Node.id>} idArray
     * @returns {Array.<Node>}
     */
  }, {
    key: "_indexArrayToNodes",
    value: function _indexArrayToNodes(idArray) {
      var array = [];
      for (var i = 0; i < idArray.length; i++) {
        array.push(this.body.nodes[idArray[i]]);
      }
      return array;
    }

    /**
     * This function get the distribution of levels based on hubsize
     *
     * @returns {object}
     * @private
     */
  }, {
    key: "_getDistribution",
    value: function _getDistribution() {
      var distribution = {};
      var nodeId, node;

      // we fix Y because the hierarchy is vertical,
      // we fix X so we do not give a node an x position for a second time.
      // the fix of X is removed after the x value has been set.
      for (nodeId in this.body.nodes) {
        if (Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) {
          node = this.body.nodes[nodeId];
          var level = this.hierarchical.levels[nodeId] === undefined ? 0 : this.hierarchical.levels[nodeId];
          this.direction.fix(node, level);
          if (distribution[level] === undefined) {
            distribution[level] = {};
          }
          distribution[level][nodeId] = node;
        }
      }
      return distribution;
    }

    /**
     * Return the active (i.e. visible) edges for this node
     *
     * @param {Node} node
     * @returns {Array.<vis.Edge>} Array of edge instances
     * @private
     */
  }, {
    key: "_getActiveEdges",
    value: function _getActiveEdges(node) {
      var _this4 = this;
      var result = [];
      forEach$1(node.edges, function (edge) {
        var _context3;
        if (_indexOfInstanceProperty(_context3 = _this4.body.edgeIndices).call(_context3, edge.id) !== -1) {
          result.push(edge);
        }
      });
      return result;
    }

    /**
     * Get the hubsizes for all active nodes.
     *
     * @returns {number}
     * @private
     */
  }, {
    key: "_getHubSizes",
    value: function _getHubSizes() {
      var _this5 = this;
      var hubSizes = {};
      var nodeIds = this.body.nodeIndices;
      forEach$1(nodeIds, function (nodeId) {
        var node = _this5.body.nodes[nodeId];
        var hubSize = _this5._getActiveEdges(node).length;
        hubSizes[hubSize] = true;
      });

      // Make an array of the size sorted descending
      var result = [];
      forEach$1(hubSizes, function (size) {
        result.push(Number(size));
      });
      _sortInstanceProperty(TimSort$1).call(TimSort$1, result, function (a, b) {
        return b - a;
      });
      return result;
    }

    /**
     * this function allocates nodes in levels based on the recursive branching from the largest hubs.
     *
     * @private
     */
  }, {
    key: "_determineLevelsByHubsize",
    value: function _determineLevelsByHubsize() {
      var _this6 = this;
      var levelDownstream = function levelDownstream(nodeA, nodeB) {
        _this6.hierarchical.levelDownstream(nodeA, nodeB);
      };
      var hubSizes = this._getHubSizes();
      var _loop = function _loop() {
        var hubSize = hubSizes[i];
        if (hubSize === 0) return "break";
        forEach$1(_this6.body.nodeIndices, function (nodeId) {
          var node = _this6.body.nodes[nodeId];
          if (hubSize === _this6._getActiveEdges(node).length) {
            _this6._crawlNetwork(levelDownstream, nodeId);
          }
        });
      };
      for (var i = 0; i < hubSizes.length; ++i) {
        var _ret = _loop();
        if (_ret === "break") break;
      }
    }

    /**
     * TODO: release feature
     * TODO: Determine if this feature is needed at all
     *
     * @private
     */
  }, {
    key: "_determineLevelsCustomCallback",
    value: function _determineLevelsCustomCallback() {
      var _this7 = this;
      var minLevel = 100000;

      // TODO: this should come from options.
      // eslint-disable-next-line no-unused-vars -- This should eventually be implemented with these parameters used.
      var customCallback = function customCallback(nodeA, nodeB, edge) {};

      // TODO: perhaps move to HierarchicalStatus.
      //       But I currently don't see the point, this method is not used.
      var levelByDirection = function levelByDirection(nodeA, nodeB, edge) {
        var levelA = _this7.hierarchical.levels[nodeA.id];
        // set initial level
        if (levelA === undefined) {
          levelA = _this7.hierarchical.levels[nodeA.id] = minLevel;
        }
        var diff = customCallback(NetworkUtil.cloneOptions(nodeA, "node"), NetworkUtil.cloneOptions(nodeB, "node"), NetworkUtil.cloneOptions(edge, "edge"));
        _this7.hierarchical.levels[nodeB.id] = levelA + diff;
      };
      this._crawlNetwork(levelByDirection);
      this.hierarchical.setMinLevelToZero(this.body.nodes);
    }

    /**
     * Allocate nodes in levels based on the direction of the edges.
     *
     * @private
     */
  }, {
    key: "_determineLevelsDirected",
    value: function _determineLevelsDirected() {
      var _context4,
        _this8 = this;
      var nodes = _reduceInstanceProperty(_context4 = this.body.nodeIndices).call(_context4, function (acc, id) {
        acc.set(id, _this8.body.nodes[id]);
        return acc;
      }, new _Map());
      if (this.options.hierarchical.shakeTowards === "roots") {
        this.hierarchical.levels = fillLevelsByDirectionRoots(nodes);
      } else {
        this.hierarchical.levels = fillLevelsByDirectionLeaves(nodes);
      }
      this.hierarchical.setMinLevelToZero(this.body.nodes);
    }

    /**
     * Update the bookkeeping of parent and child.
     *
     * @private
     */
  }, {
    key: "_generateMap",
    value: function _generateMap() {
      var _this9 = this;
      var fillInRelations = function fillInRelations(parentNode, childNode) {
        if (_this9.hierarchical.levels[childNode.id] > _this9.hierarchical.levels[parentNode.id]) {
          _this9.hierarchical.addRelation(parentNode.id, childNode.id);
        }
      };
      this._crawlNetwork(fillInRelations);
      this.hierarchical.checkIfTree();
    }

    /**
     * Crawl over the entire network and use a callback on each node couple that is connected to each other.
     *
     * @param {Function} [callback=function(){}]          | will receive nodeA, nodeB and the connecting edge. A and B are distinct.
     * @param {Node.id} startingNodeId
     * @private
     */
  }, {
    key: "_crawlNetwork",
    value: function _crawlNetwork() {
      var _this10 = this;
      var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
      var startingNodeId = arguments.length > 1 ? arguments[1] : undefined;
      var progress = {};
      var crawler = function crawler(node, tree) {
        if (progress[node.id] === undefined) {
          _this10.hierarchical.setTreeIndex(node, tree);
          progress[node.id] = true;
          var childNode;
          var edges = _this10._getActiveEdges(node);
          for (var i = 0; i < edges.length; i++) {
            var edge = edges[i];
            if (edge.connected === true) {
              if (edge.toId == node.id) {
                // Not '===' because id's can be string and numeric
                childNode = edge.from;
              } else {
                childNode = edge.to;
              }
              if (node.id != childNode.id) {
                // Not '!==' because id's can be string and numeric
                callback(node, childNode, edge);
                crawler(childNode, tree);
              }
            }
          }
        }
      };
      if (startingNodeId === undefined) {
        // Crawl over all nodes
        var treeIndex = 0; // Serves to pass a unique id for the current distinct tree

        for (var i = 0; i < this.body.nodeIndices.length; i++) {
          var nodeId = this.body.nodeIndices[i];
          if (progress[nodeId] === undefined) {
            var node = this.body.nodes[nodeId];
            crawler(node, treeIndex);
            treeIndex += 1;
          }
        }
      } else {
        // Crawl from the given starting node
        var _node2 = this.body.nodes[startingNodeId];
        if (_node2 === undefined) {
          console.error("Node not found:", startingNodeId);
          return;
        }
        crawler(_node2);
      }
    }

    /**
     * Shift a branch a certain distance
     *
     * @param {Node.id} parentId
     * @param {number} diff
     * @private
     */
  }, {
    key: "_shiftBlock",
    value: function _shiftBlock(parentId, diff) {
      var _this11 = this;
      var progress = {};
      var shifter = function shifter(parentId) {
        if (progress[parentId]) {
          return;
        }
        progress[parentId] = true;
        _this11.direction.shift(parentId, diff);
        var childRef = _this11.hierarchical.childrenReference[parentId];
        if (childRef !== undefined) {
          for (var i = 0; i < childRef.length; i++) {
            shifter(childRef[i]);
          }
        }
      };
      shifter(parentId);
    }

    /**
     * Find a common parent between branches.
     *
     * @param {Node.id} childA
     * @param {Node.id} childB
     * @returns {{foundParent, withChild}}
     * @private
     */
  }, {
    key: "_findCommonParent",
    value: function _findCommonParent(childA, childB) {
      var _this12 = this;
      var parents = {};
      var iterateParents = function iterateParents(parents, child) {
        var parentRef = _this12.hierarchical.parentReference[child];
        if (parentRef !== undefined) {
          for (var i = 0; i < parentRef.length; i++) {
            var parent = parentRef[i];
            parents[parent] = true;
            iterateParents(parents, parent);
          }
        }
      };
      var findParent = function findParent(parents, child) {
        var parentRef = _this12.hierarchical.parentReference[child];
        if (parentRef !== undefined) {
          for (var i = 0; i < parentRef.length; i++) {
            var parent = parentRef[i];
            if (parents[parent] !== undefined) {
              return {
                foundParent: parent,
                withChild: child
              };
            }
            var branch = findParent(parents, parent);
            if (branch.foundParent !== null) {
              return branch;
            }
          }
        }
        return {
          foundParent: null,
          withChild: child
        };
      };
      iterateParents(parents, childA);
      return findParent(parents, childB);
    }

    /**
     * Set the strategy pattern for handling the coordinates given the current direction.
     *
     * The individual instances contain all the operations and data specific to a layout direction.
     *
     * @param {Node} node
     * @param {{x: number, y: number}} position
     * @param {number} level
     * @param {boolean} [doNotUpdate=false]
     * @private
     */
  }, {
    key: "setDirectionStrategy",
    value: function setDirectionStrategy() {
      var isVertical = this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU";
      if (isVertical) {
        this.direction = new VerticalStrategy(this);
      } else {
        this.direction = new HorizontalStrategy(this);
      }
    }

    /**
     * Determine the center position of a branch from the passed list of child nodes
     *
     * This takes into account the positions of all the child nodes.
     *
     * @param {Array.<Node|vis.Node.id>} childNodes  Array of either child nodes or node id's
     * @returns {number}
     * @private
     */
  }, {
    key: "_getCenterPosition",
    value: function _getCenterPosition(childNodes) {
      var minPos = 1e9;
      var maxPos = -1e9;
      for (var i = 0; i < childNodes.length; i++) {
        var childNode = void 0;
        if (childNodes[i].id !== undefined) {
          childNode = childNodes[i];
        } else {
          var childNodeId = childNodes[i];
          childNode = this.body.nodes[childNodeId];
        }
        var position = this.direction.getPosition(childNode);
        minPos = Math.min(minPos, position);
        maxPos = Math.max(maxPos, position);
      }
      return 0.5 * (minPos + maxPos);
    }
  }]);
  return LayoutEngine;
}();

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { var _context32; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = _sliceInstanceProperty(_context32 = Object.prototype.toString.call(o)).call(_context32, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from$1(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

/**
 * Clears the toolbar div element of children
 *
 * @private
 */
var ManipulationSystem = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {Canvas} canvas
   * @param {SelectionHandler} selectionHandler
   * @param {InteractionHandler} interactionHandler
   */
  function ManipulationSystem(body, canvas, selectionHandler, interactionHandler) {
    var _this = this,
      _context,
      _context2;
    _classCallCheck(this, ManipulationSystem);
    this.body = body;
    this.canvas = canvas;
    this.selectionHandler = selectionHandler;
    this.interactionHandler = interactionHandler;
    this.editMode = false;
    this.manipulationDiv = undefined;
    this.editModeDiv = undefined;
    this.closeDiv = undefined;
    this._domEventListenerCleanupQueue = [];
    this.temporaryUIFunctions = {};
    this.temporaryEventFunctions = [];
    this.touchTime = 0;
    this.temporaryIds = {
      nodes: [],
      edges: []
    };
    this.guiEnabled = false;
    this.inMode = false;
    this.selectedControlNode = undefined;
    this.options = {};
    this.defaultOptions = {
      enabled: false,
      initiallyActive: false,
      addNode: true,
      addEdge: true,
      editNode: undefined,
      editEdge: true,
      deleteNode: true,
      deleteEdge: true,
      controlNodeStyle: {
        shape: "dot",
        size: 6,
        color: {
          background: "#ff0000",
          border: "#3c3c3c",
          highlight: {
            background: "#07f968",
            border: "#3c3c3c"
          }
        },
        borderWidth: 2,
        borderWidthSelected: 2
      }
    };
    _Object$assign(this.options, this.defaultOptions);
    this.body.emitter.on("destroy", function () {
      _this._clean();
    });
    this.body.emitter.on("_dataChanged", _bindInstanceProperty$1(_context = this._restore).call(_context, this));
    this.body.emitter.on("_resetData", _bindInstanceProperty$1(_context2 = this._restore).call(_context2, this));
  }

  /**
   * If something changes in the data during editing, switch back to the initial datamanipulation state and close all edit modes.
   *
   * @private
   */
  _createClass(ManipulationSystem, [{
    key: "_restore",
    value: function _restore() {
      if (this.inMode !== false) {
        if (this.options.initiallyActive === true) {
          this.enableEditMode();
        } else {
          this.disableEditMode();
        }
      }
    }

    /**
     * Set the Options
     *
     * @param {object} options
     * @param {object} allOptions
     * @param {object} globalOptions
     */
  }, {
    key: "setOptions",
    value: function setOptions(options, allOptions, globalOptions) {
      if (allOptions !== undefined) {
        if (allOptions.locale !== undefined) {
          this.options.locale = allOptions.locale;
        } else {
          this.options.locale = globalOptions.locale;
        }
        if (allOptions.locales !== undefined) {
          this.options.locales = allOptions.locales;
        } else {
          this.options.locales = globalOptions.locales;
        }
      }
      if (options !== undefined) {
        if (typeof options === "boolean") {
          this.options.enabled = options;
        } else {
          this.options.enabled = true;
          deepExtend(this.options, options);
        }
        if (this.options.initiallyActive === true) {
          this.editMode = true;
        }
        this._setup();
      }
    }

    /**
     * Enable or disable edit-mode. Draws the DOM required and cleans up after itself.
     *
     * @private
     */
  }, {
    key: "toggleEditMode",
    value: function toggleEditMode() {
      if (this.editMode === true) {
        this.disableEditMode();
      } else {
        this.enableEditMode();
      }
    }

    /**
     * Enables Edit Mode
     */
  }, {
    key: "enableEditMode",
    value: function enableEditMode() {
      this.editMode = true;
      this._clean();
      if (this.guiEnabled === true) {
        this.manipulationDiv.style.display = "block";
        this.closeDiv.style.display = "block";
        this.editModeDiv.style.display = "none";
        this.showManipulatorToolbar();
      }
    }

    /**
     * Disables Edit Mode
     */
  }, {
    key: "disableEditMode",
    value: function disableEditMode() {
      this.editMode = false;
      this._clean();
      if (this.guiEnabled === true) {
        this.manipulationDiv.style.display = "none";
        this.closeDiv.style.display = "none";
        this.editModeDiv.style.display = "block";
        this._createEditButton();
      }
    }

    /**
     * Creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar.
     *
     * @private
     */
  }, {
    key: "showManipulatorToolbar",
    value: function showManipulatorToolbar() {
      // restore the state of any bound functions or events, remove control nodes, restore physics
      this._clean();

      // reset global variables
      this.manipulationDOM = {};

      // if the gui is enabled, draw all elements.
      if (this.guiEnabled === true) {
        var _context3, _context4;
        // a _restore will hide these menus
        this.editMode = true;
        this.manipulationDiv.style.display = "block";
        this.closeDiv.style.display = "block";
        var selectedNodeCount = this.selectionHandler.getSelectedNodeCount();
        var selectedEdgeCount = this.selectionHandler.getSelectedEdgeCount();
        var selectedTotalCount = selectedNodeCount + selectedEdgeCount;
        var locale = this.options.locales[this.options.locale];
        var needSeperator = false;
        if (this.options.addNode !== false) {
          this._createAddNodeButton(locale);
          needSeperator = true;
        }
        if (this.options.addEdge !== false) {
          if (needSeperator === true) {
            this._createSeperator(1);
          } else {
            needSeperator = true;
          }
          this._createAddEdgeButton(locale);
        }
        if (selectedNodeCount === 1 && typeof this.options.editNode === "function") {
          if (needSeperator === true) {
            this._createSeperator(2);
          } else {
            needSeperator = true;
          }
          this._createEditNodeButton(locale);
        } else if (selectedEdgeCount === 1 && selectedNodeCount === 0 && this.options.editEdge !== false) {
          if (needSeperator === true) {
            this._createSeperator(3);
          } else {
            needSeperator = true;
          }
          this._createEditEdgeButton(locale);
        }

        // remove buttons
        if (selectedTotalCount !== 0) {
          if (selectedNodeCount > 0 && this.options.deleteNode !== false) {
            if (needSeperator === true) {
              this._createSeperator(4);
            }
            this._createDeleteButton(locale);
          } else if (selectedNodeCount === 0 && this.options.deleteEdge !== false) {
            if (needSeperator === true) {
              this._createSeperator(4);
            }
            this._createDeleteButton(locale);
          }
        }

        // bind the close button
        this._bindElementEvents(this.closeDiv, _bindInstanceProperty$1(_context3 = this.toggleEditMode).call(_context3, this));

        // refresh this bar based on what has been selected
        this._temporaryBindEvent("select", _bindInstanceProperty$1(_context4 = this.showManipulatorToolbar).call(_context4, this));
      }

      // redraw to show any possible changes
      this.body.emitter.emit("_redraw");
    }

    /**
     * Create the toolbar for adding Nodes
     */
  }, {
    key: "addNodeMode",
    value: function addNodeMode() {
      var _context6;
      // when using the gui, enable edit mode if it wasnt already.
      if (this.editMode !== true) {
        this.enableEditMode();
      }

      // restore the state of any bound functions or events, remove control nodes, restore physics
      this._clean();
      this.inMode = "addNode";
      if (this.guiEnabled === true) {
        var _context5;
        var locale = this.options.locales[this.options.locale];
        this.manipulationDOM = {};
        this._createBackButton(locale);
        this._createSeperator();
        this._createDescription(locale["addDescription"] || this.options.locales["en"]["addDescription"]);

        // bind the close button
        this._bindElementEvents(this.closeDiv, _bindInstanceProperty$1(_context5 = this.toggleEditMode).call(_context5, this));
      }
      this._temporaryBindEvent("click", _bindInstanceProperty$1(_context6 = this._performAddNode).call(_context6, this));
    }

    /**
     * call the bound function to handle the editing of the node. The node has to be selected.
     */
  }, {
    key: "editNode",
    value: function editNode() {
      var _this2 = this;
      // when using the gui, enable edit mode if it wasnt already.
      if (this.editMode !== true) {
        this.enableEditMode();
      }

      // restore the state of any bound functions or events, remove control nodes, restore physics
      this._clean();
      var node = this.selectionHandler.getSelectedNodes()[0];
      if (node !== undefined) {
        this.inMode = "editNode";
        if (typeof this.options.editNode === "function") {
          if (node.isCluster !== true) {
            var data = deepExtend({}, node.options, false);
            data.x = node.x;
            data.y = node.y;
            if (this.options.editNode.length === 2) {
              this.options.editNode(data, function (finalizedData) {
                if (finalizedData !== null && finalizedData !== undefined && _this2.inMode === "editNode") {
                  // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
                  _this2.body.data.nodes.getDataSet().update(finalizedData);
                }
                _this2.showManipulatorToolbar();
              });
            } else {
              throw new Error("The function for edit does not support two arguments (data, callback)");
            }
          } else {
            alert(this.options.locales[this.options.locale]["editClusterError"] || this.options.locales["en"]["editClusterError"]);
          }
        } else {
          throw new Error("No function has been configured to handle the editing of nodes.");
        }
      } else {
        this.showManipulatorToolbar();
      }
    }

    /**
     * create the toolbar to connect nodes
     */
  }, {
    key: "addEdgeMode",
    value: function addEdgeMode() {
      var _context8, _context9, _context10, _context11, _context12;
      // when using the gui, enable edit mode if it wasnt already.
      if (this.editMode !== true) {
        this.enableEditMode();
      }

      // restore the state of any bound functions or events, remove control nodes, restore physics
      this._clean();
      this.inMode = "addEdge";
      if (this.guiEnabled === true) {
        var _context7;
        var locale = this.options.locales[this.options.locale];
        this.manipulationDOM = {};
        this._createBackButton(locale);
        this._createSeperator();
        this._createDescription(locale["edgeDescription"] || this.options.locales["en"]["edgeDescription"]);

        // bind the close button
        this._bindElementEvents(this.closeDiv, _bindInstanceProperty$1(_context7 = this.toggleEditMode).call(_context7, this));
      }

      // temporarily overload functions
      this._temporaryBindUI("onTouch", _bindInstanceProperty$1(_context8 = this._handleConnect).call(_context8, this));
      this._temporaryBindUI("onDragEnd", _bindInstanceProperty$1(_context9 = this._finishConnect).call(_context9, this));
      this._temporaryBindUI("onDrag", _bindInstanceProperty$1(_context10 = this._dragControlNode).call(_context10, this));
      this._temporaryBindUI("onRelease", _bindInstanceProperty$1(_context11 = this._finishConnect).call(_context11, this));
      this._temporaryBindUI("onDragStart", _bindInstanceProperty$1(_context12 = this._dragStartEdge).call(_context12, this));
      this._temporaryBindUI("onHold", function () {});
    }

    /**
     * create the toolbar to edit edges
     */
  }, {
    key: "editEdgeMode",
    value: function editEdgeMode() {
      // when using the gui, enable edit mode if it wasn't already.
      if (this.editMode !== true) {
        this.enableEditMode();
      }

      // restore the state of any bound functions or events, remove control nodes, restore physics
      this._clean();
      this.inMode = "editEdge";
      if (_typeof(this.options.editEdge) === "object" && typeof this.options.editEdge.editWithoutDrag === "function") {
        this.edgeBeingEditedId = this.selectionHandler.getSelectedEdgeIds()[0];
        if (this.edgeBeingEditedId !== undefined) {
          var edge = this.body.edges[this.edgeBeingEditedId];
          this._performEditEdge(edge.from.id, edge.to.id);
          return;
        }
      }
      if (this.guiEnabled === true) {
        var _context13;
        var locale = this.options.locales[this.options.locale];
        this.manipulationDOM = {};
        this._createBackButton(locale);
        this._createSeperator();
        this._createDescription(locale["editEdgeDescription"] || this.options.locales["en"]["editEdgeDescription"]);

        // bind the close button
        this._bindElementEvents(this.closeDiv, _bindInstanceProperty$1(_context13 = this.toggleEditMode).call(_context13, this));
      }
      this.edgeBeingEditedId = this.selectionHandler.getSelectedEdgeIds()[0];
      if (this.edgeBeingEditedId !== undefined) {
        var _context14, _context15, _context16, _context17;
        var _edge = this.body.edges[this.edgeBeingEditedId];

        // create control nodes
        var controlNodeFrom = this._getNewTargetNode(_edge.from.x, _edge.from.y);
        var controlNodeTo = this._getNewTargetNode(_edge.to.x, _edge.to.y);
        this.temporaryIds.nodes.push(controlNodeFrom.id);
        this.temporaryIds.nodes.push(controlNodeTo.id);
        this.body.nodes[controlNodeFrom.id] = controlNodeFrom;
        this.body.nodeIndices.push(controlNodeFrom.id);
        this.body.nodes[controlNodeTo.id] = controlNodeTo;
        this.body.nodeIndices.push(controlNodeTo.id);

        // temporarily overload UI functions, cleaned up automatically because of _temporaryBindUI
        this._temporaryBindUI("onTouch", _bindInstanceProperty$1(_context14 = this._controlNodeTouch).call(_context14, this)); // used to get the position
        this._temporaryBindUI("onTap", function () {}); // disabled
        this._temporaryBindUI("onHold", function () {}); // disabled
        this._temporaryBindUI("onDragStart", _bindInstanceProperty$1(_context15 = this._controlNodeDragStart).call(_context15, this)); // used to select control node
        this._temporaryBindUI("onDrag", _bindInstanceProperty$1(_context16 = this._controlNodeDrag).call(_context16, this)); // used to drag control node
        this._temporaryBindUI("onDragEnd", _bindInstanceProperty$1(_context17 = this._controlNodeDragEnd).call(_context17, this)); // used to connect or revert control nodes
        this._temporaryBindUI("onMouseMove", function () {}); // disabled

        // create function to position control nodes correctly on movement
        // automatically cleaned up because we use the temporary bind
        this._temporaryBindEvent("beforeDrawing", function (ctx) {
          var positions = _edge.edgeType.findBorderPositions(ctx);
          if (controlNodeFrom.selected === false) {
            controlNodeFrom.x = positions.from.x;
            controlNodeFrom.y = positions.from.y;
          }
          if (controlNodeTo.selected === false) {
            controlNodeTo.x = positions.to.x;
            controlNodeTo.y = positions.to.y;
          }
        });
        this.body.emitter.emit("_redraw");
      } else {
        this.showManipulatorToolbar();
      }
    }

    /**
     * delete everything in the selection
     */
  }, {
    key: "deleteSelected",
    value: function deleteSelected() {
      var _this3 = this;
      // when using the gui, enable edit mode if it wasnt already.
      if (this.editMode !== true) {
        this.enableEditMode();
      }

      // restore the state of any bound functions or events, remove control nodes, restore physics
      this._clean();
      this.inMode = "delete";
      var selectedNodes = this.selectionHandler.getSelectedNodeIds();
      var selectedEdges = this.selectionHandler.getSelectedEdgeIds();
      var deleteFunction = undefined;
      if (selectedNodes.length > 0) {
        for (var i = 0; i < selectedNodes.length; i++) {
          if (this.body.nodes[selectedNodes[i]].isCluster === true) {
            alert(this.options.locales[this.options.locale]["deleteClusterError"] || this.options.locales["en"]["deleteClusterError"]);
            return;
          }
        }
        if (typeof this.options.deleteNode === "function") {
          deleteFunction = this.options.deleteNode;
        }
      } else if (selectedEdges.length > 0) {
        if (typeof this.options.deleteEdge === "function") {
          deleteFunction = this.options.deleteEdge;
        }
      }
      if (typeof deleteFunction === "function") {
        var data = {
          nodes: selectedNodes,
          edges: selectedEdges
        };
        if (deleteFunction.length === 2) {
          deleteFunction(data, function (finalizedData) {
            if (finalizedData !== null && finalizedData !== undefined && _this3.inMode === "delete") {
              // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
              _this3.body.data.edges.getDataSet().remove(finalizedData.edges);
              _this3.body.data.nodes.getDataSet().remove(finalizedData.nodes);
              _this3.body.emitter.emit("startSimulation");
              _this3.showManipulatorToolbar();
            } else {
              _this3.body.emitter.emit("startSimulation");
              _this3.showManipulatorToolbar();
            }
          });
        } else {
          throw new Error("The function for delete does not support two arguments (data, callback)");
        }
      } else {
        this.body.data.edges.getDataSet().remove(selectedEdges);
        this.body.data.nodes.getDataSet().remove(selectedNodes);
        this.body.emitter.emit("startSimulation");
        this.showManipulatorToolbar();
      }
    }

    //********************************************** PRIVATE ***************************************//

    /**
     * draw or remove the DOM
     *
     * @private
     */
  }, {
    key: "_setup",
    value: function _setup() {
      if (this.options.enabled === true) {
        // Enable the GUI
        this.guiEnabled = true;
        this._createWrappers();
        if (this.editMode === false) {
          this._createEditButton();
        } else {
          this.showManipulatorToolbar();
        }
      } else {
        this._removeManipulationDOM();

        // disable the gui
        this.guiEnabled = false;
      }
    }

    /**
     * create the div overlays that contain the DOM
     *
     * @private
     */
  }, {
    key: "_createWrappers",
    value: function _createWrappers() {
      // load the manipulator HTML elements. All styling done in css.
      if (this.manipulationDiv === undefined) {
        this.manipulationDiv = document.createElement("div");
        this.manipulationDiv.className = "vis-manipulation";
        if (this.editMode === true) {
          this.manipulationDiv.style.display = "block";
        } else {
          this.manipulationDiv.style.display = "none";
        }
        this.canvas.frame.appendChild(this.manipulationDiv);
      }

      // container for the edit button.
      if (this.editModeDiv === undefined) {
        this.editModeDiv = document.createElement("div");
        this.editModeDiv.className = "vis-edit-mode";
        if (this.editMode === true) {
          this.editModeDiv.style.display = "none";
        } else {
          this.editModeDiv.style.display = "block";
        }
        this.canvas.frame.appendChild(this.editModeDiv);
      }

      // container for the close div button
      if (this.closeDiv === undefined) {
        var _this$options$locales, _this$options$locales2;
        this.closeDiv = document.createElement("button");
        this.closeDiv.className = "vis-close";
        this.closeDiv.setAttribute("aria-label", (_this$options$locales = (_this$options$locales2 = this.options.locales[this.options.locale]) === null || _this$options$locales2 === void 0 ? void 0 : _this$options$locales2["close"]) !== null && _this$options$locales !== void 0 ? _this$options$locales : this.options.locales["en"]["close"]);
        this.closeDiv.style.display = this.manipulationDiv.style.display;
        this.canvas.frame.appendChild(this.closeDiv);
      }
    }

    /**
     * generate a new target node. Used for creating new edges and editing edges
     *
     * @param {number} x
     * @param {number} y
     * @returns {Node}
     * @private
     */
  }, {
    key: "_getNewTargetNode",
    value: function _getNewTargetNode(x, y) {
      var controlNodeStyle = deepExtend({}, this.options.controlNodeStyle);
      controlNodeStyle.id = "targetNode" + v4();
      controlNodeStyle.hidden = false;
      controlNodeStyle.physics = false;
      controlNodeStyle.x = x;
      controlNodeStyle.y = y;

      // we have to define the bounding box in order for the nodes to be drawn immediately
      var node = this.body.functions.createNode(controlNodeStyle);
      node.shape.boundingBox = {
        left: x,
        right: x,
        top: y,
        bottom: y
      };
      return node;
    }

    /**
     * Create the edit button
     */
  }, {
    key: "_createEditButton",
    value: function _createEditButton() {
      var _context18;
      // restore everything to it's original state (if applicable)
      this._clean();

      // reset the manipulationDOM
      this.manipulationDOM = {};

      // empty the editModeDiv
      recursiveDOMDelete(this.editModeDiv);

      // create the contents for the editMode button
      var locale = this.options.locales[this.options.locale];
      var button = this._createButton("editMode", "vis-edit vis-edit-mode", locale["edit"] || this.options.locales["en"]["edit"]);
      this.editModeDiv.appendChild(button);

      // bind a hammer listener to the button, calling the function toggleEditMode.
      this._bindElementEvents(button, _bindInstanceProperty$1(_context18 = this.toggleEditMode).call(_context18, this));
    }

    /**
     * this function cleans up after everything this module does. Temporary elements, functions and events are removed, physics restored, hammers removed.
     *
     * @private
     */
  }, {
    key: "_clean",
    value: function _clean() {
      // not in mode
      this.inMode = false;

      // _clean the divs
      if (this.guiEnabled === true) {
        recursiveDOMDelete(this.editModeDiv);
        recursiveDOMDelete(this.manipulationDiv);

        // removes all the bindings and overloads
        this._cleanupDOMEventListeners();
      }

      // remove temporary nodes and edges
      this._cleanupTemporaryNodesAndEdges();

      // restore overloaded UI functions
      this._unbindTemporaryUIs();

      // remove the temporaryEventFunctions
      this._unbindTemporaryEvents();

      // restore the physics if required
      this.body.emitter.emit("restorePhysics");
    }

    /**
     * Each dom element has it's own hammer. They are stored in this.manipulationHammers. This cleans them up.
     *
     * @private
     */
  }, {
    key: "_cleanupDOMEventListeners",
    value: function _cleanupDOMEventListeners() {
      var _context19;
      // _clean DOM event listener bindings
      var _iterator = _createForOfIteratorHelper(_spliceInstanceProperty(_context19 = this._domEventListenerCleanupQueue).call(_context19, 0)),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var callback = _step.value;
          callback();
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
    }

    /**
     * Remove all DOM elements created by this module.
     *
     * @private
     */
  }, {
    key: "_removeManipulationDOM",
    value: function _removeManipulationDOM() {
      // removes all the bindings and overloads
      this._clean();

      // empty the manipulation divs
      recursiveDOMDelete(this.manipulationDiv);
      recursiveDOMDelete(this.editModeDiv);
      recursiveDOMDelete(this.closeDiv);

      // remove the manipulation divs
      if (this.manipulationDiv) {
        this.canvas.frame.removeChild(this.manipulationDiv);
      }
      if (this.editModeDiv) {
        this.canvas.frame.removeChild(this.editModeDiv);
      }
      if (this.closeDiv) {
        this.canvas.frame.removeChild(this.closeDiv);
      }

      // set the references to undefined
      this.manipulationDiv = undefined;
      this.editModeDiv = undefined;
      this.closeDiv = undefined;
    }

    /**
     * create a seperator line. the index is to differentiate in the manipulation dom
     *
     * @param {number} [index=1]
     * @private
     */
  }, {
    key: "_createSeperator",
    value: function _createSeperator() {
      var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
      this.manipulationDOM["seperatorLineDiv" + index] = document.createElement("div");
      this.manipulationDOM["seperatorLineDiv" + index].className = "vis-separator-line";
      this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv" + index]);
    }

    // ----------------------    DOM functions for buttons    --------------------------//

    /**
     *
     * @param {Locale} locale
     * @private
     */
  }, {
    key: "_createAddNodeButton",
    value: function _createAddNodeButton(locale) {
      var _context20;
      var button = this._createButton("addNode", "vis-add", locale["addNode"] || this.options.locales["en"]["addNode"]);
      this.manipulationDiv.appendChild(button);
      this._bindElementEvents(button, _bindInstanceProperty$1(_context20 = this.addNodeMode).call(_context20, this));
    }

    /**
     *
     * @param {Locale} locale
     * @private
     */
  }, {
    key: "_createAddEdgeButton",
    value: function _createAddEdgeButton(locale) {
      var _context21;
      var button = this._createButton("addEdge", "vis-connect", locale["addEdge"] || this.options.locales["en"]["addEdge"]);
      this.manipulationDiv.appendChild(button);
      this._bindElementEvents(button, _bindInstanceProperty$1(_context21 = this.addEdgeMode).call(_context21, this));
    }

    /**
     *
     * @param {Locale} locale
     * @private
     */
  }, {
    key: "_createEditNodeButton",
    value: function _createEditNodeButton(locale) {
      var _context22;
      var button = this._createButton("editNode", "vis-edit", locale["editNode"] || this.options.locales["en"]["editNode"]);
      this.manipulationDiv.appendChild(button);
      this._bindElementEvents(button, _bindInstanceProperty$1(_context22 = this.editNode).call(_context22, this));
    }

    /**
     *
     * @param {Locale} locale
     * @private
     */
  }, {
    key: "_createEditEdgeButton",
    value: function _createEditEdgeButton(locale) {
      var _context23;
      var button = this._createButton("editEdge", "vis-edit", locale["editEdge"] || this.options.locales["en"]["editEdge"]);
      this.manipulationDiv.appendChild(button);
      this._bindElementEvents(button, _bindInstanceProperty$1(_context23 = this.editEdgeMode).call(_context23, this));
    }

    /**
     *
     * @param {Locale} locale
     * @private
     */
  }, {
    key: "_createDeleteButton",
    value: function _createDeleteButton(locale) {
      var _context24;
      var deleteBtnClass;
      if (this.options.rtl) {
        deleteBtnClass = "vis-delete-rtl";
      } else {
        deleteBtnClass = "vis-delete";
      }
      var button = this._createButton("delete", deleteBtnClass, locale["del"] || this.options.locales["en"]["del"]);
      this.manipulationDiv.appendChild(button);
      this._bindElementEvents(button, _bindInstanceProperty$1(_context24 = this.deleteSelected).call(_context24, this));
    }

    /**
     *
     * @param {Locale} locale
     * @private
     */
  }, {
    key: "_createBackButton",
    value: function _createBackButton(locale) {
      var _context25;
      var button = this._createButton("back", "vis-back", locale["back"] || this.options.locales["en"]["back"]);
      this.manipulationDiv.appendChild(button);
      this._bindElementEvents(button, _bindInstanceProperty$1(_context25 = this.showManipulatorToolbar).call(_context25, this));
    }

    /**
     *
     * @param {number|string} id
     * @param {string} className
     * @param {label} label
     * @param {string} labelClassName
     * @returns {HTMLElement}
     * @private
     */
  }, {
    key: "_createButton",
    value: function _createButton(id, className, label) {
      var labelClassName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "vis-label";
      this.manipulationDOM[id + "Div"] = document.createElement("button");
      this.manipulationDOM[id + "Div"].className = "vis-button " + className;
      this.manipulationDOM[id + "Label"] = document.createElement("div");
      this.manipulationDOM[id + "Label"].className = labelClassName;
      this.manipulationDOM[id + "Label"].innerText = label;
      this.manipulationDOM[id + "Div"].appendChild(this.manipulationDOM[id + "Label"]);
      return this.manipulationDOM[id + "Div"];
    }

    /**
     *
     * @param {Label} label
     * @private
     */
  }, {
    key: "_createDescription",
    value: function _createDescription(label) {
      this.manipulationDOM["descriptionLabel"] = document.createElement("div");
      this.manipulationDOM["descriptionLabel"].className = "vis-none";
      this.manipulationDOM["descriptionLabel"].innerText = label;
      this.manipulationDiv.appendChild(this.manipulationDOM["descriptionLabel"]);
    }

    // -------------------------- End of DOM functions for buttons ------------------------------//

    /**
     * this binds an event until cleanup by the clean functions.
     *
     * @param {Event}  event   The event
     * @param {Function} newFunction
     * @private
     */
  }, {
    key: "_temporaryBindEvent",
    value: function _temporaryBindEvent(event, newFunction) {
      this.temporaryEventFunctions.push({
        event: event,
        boundFunction: newFunction
      });
      this.body.emitter.on(event, newFunction);
    }

    /**
     * this overrides an UI function until cleanup by the clean function
     *
     * @param {string} UIfunctionName
     * @param {Function} newFunction
     * @private
     */
  }, {
    key: "_temporaryBindUI",
    value: function _temporaryBindUI(UIfunctionName, newFunction) {
      if (this.body.eventListeners[UIfunctionName] !== undefined) {
        this.temporaryUIFunctions[UIfunctionName] = this.body.eventListeners[UIfunctionName];
        this.body.eventListeners[UIfunctionName] = newFunction;
      } else {
        throw new Error("This UI function does not exist. Typo? You tried: " + UIfunctionName + " possible are: " + _JSON$stringify(_Object$keys(this.body.eventListeners)));
      }
    }

    /**
     * Restore the overridden UI functions to their original state.
     *
     * @private
     */
  }, {
    key: "_unbindTemporaryUIs",
    value: function _unbindTemporaryUIs() {
      for (var functionName in this.temporaryUIFunctions) {
        if (Object.prototype.hasOwnProperty.call(this.temporaryUIFunctions, functionName)) {
          this.body.eventListeners[functionName] = this.temporaryUIFunctions[functionName];
          delete this.temporaryUIFunctions[functionName];
        }
      }
      this.temporaryUIFunctions = {};
    }

    /**
     * Unbind the events created by _temporaryBindEvent
     *
     * @private
     */
  }, {
    key: "_unbindTemporaryEvents",
    value: function _unbindTemporaryEvents() {
      for (var i = 0; i < this.temporaryEventFunctions.length; i++) {
        var eventName = this.temporaryEventFunctions[i].event;
        var boundFunction = this.temporaryEventFunctions[i].boundFunction;
        this.body.emitter.off(eventName, boundFunction);
      }
      this.temporaryEventFunctions = [];
    }

    /**
     * Bind an hammer instance to a DOM element.
     *
     * @param {Element} domElement
     * @param {Function} boundFunction
     */
  }, {
    key: "_bindElementEvents",
    value: function _bindElementEvents(domElement, boundFunction) {
      // Bind touch events.
      var hammer = new Hammer(domElement, {});
      onTouch(hammer, boundFunction);
      this._domEventListenerCleanupQueue.push(function () {
        hammer.destroy();
      });

      // Bind keyboard events.
      var keyupListener = function keyupListener(_ref) {
        var keyCode = _ref.keyCode,
          key = _ref.key;
        if (key === "Enter" || key === " " || keyCode === 13 || keyCode === 32) {
          boundFunction();
        }
      };
      domElement.addEventListener("keyup", keyupListener, false);
      this._domEventListenerCleanupQueue.push(function () {
        domElement.removeEventListener("keyup", keyupListener, false);
      });
    }

    /**
     * Neatly clean up temporary edges and nodes
     *
     * @private
     */
  }, {
    key: "_cleanupTemporaryNodesAndEdges",
    value: function _cleanupTemporaryNodesAndEdges() {
      // _clean temporary edges
      for (var i = 0; i < this.temporaryIds.edges.length; i++) {
        var _context26;
        this.body.edges[this.temporaryIds.edges[i]].disconnect();
        delete this.body.edges[this.temporaryIds.edges[i]];
        var indexTempEdge = _indexOfInstanceProperty(_context26 = this.body.edgeIndices).call(_context26, this.temporaryIds.edges[i]);
        if (indexTempEdge !== -1) {
          var _context27;
          _spliceInstanceProperty(_context27 = this.body.edgeIndices).call(_context27, indexTempEdge, 1);
        }
      }

      // _clean temporary nodes
      for (var _i = 0; _i < this.temporaryIds.nodes.length; _i++) {
        var _context28;
        delete this.body.nodes[this.temporaryIds.nodes[_i]];
        var indexTempNode = _indexOfInstanceProperty(_context28 = this.body.nodeIndices).call(_context28, this.temporaryIds.nodes[_i]);
        if (indexTempNode !== -1) {
          var _context29;
          _spliceInstanceProperty(_context29 = this.body.nodeIndices).call(_context29, indexTempNode, 1);
        }
      }
      this.temporaryIds = {
        nodes: [],
        edges: []
      };
    }

    // ------------------------------------------ EDIT EDGE FUNCTIONS -----------------------------------------//

    /**
     * the touch is used to get the position of the initial click
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "_controlNodeTouch",
    value: function _controlNodeTouch(event) {
      this.selectionHandler.unselectAll();
      this.lastTouch = this.body.functions.getPointer(event.center);
      this.lastTouch.translation = _Object$assign({}, this.body.view.translation); // copy the object
    }

    /**
     * the drag start is used to mark one of the control nodes as selected.
     *
     * @private
     */
  }, {
    key: "_controlNodeDragStart",
    value: function _controlNodeDragStart() {
      var pointer = this.lastTouch;
      var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
      var from = this.body.nodes[this.temporaryIds.nodes[0]];
      var to = this.body.nodes[this.temporaryIds.nodes[1]];
      var edge = this.body.edges[this.edgeBeingEditedId];
      this.selectedControlNode = undefined;
      var fromSelect = from.isOverlappingWith(pointerObj);
      var toSelect = to.isOverlappingWith(pointerObj);
      if (fromSelect === true) {
        this.selectedControlNode = from;
        edge.edgeType.from = from;
      } else if (toSelect === true) {
        this.selectedControlNode = to;
        edge.edgeType.to = to;
      }

      // we use the selection to find the node that is being dragged. We explicitly select it here.
      if (this.selectedControlNode !== undefined) {
        this.selectionHandler.selectObject(this.selectedControlNode);
      }
      this.body.emitter.emit("_redraw");
    }

    /**
     * dragging the control nodes or the canvas
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "_controlNodeDrag",
    value: function _controlNodeDrag(event) {
      this.body.emitter.emit("disablePhysics");
      var pointer = this.body.functions.getPointer(event.center);
      var pos = this.canvas.DOMtoCanvas(pointer);
      if (this.selectedControlNode !== undefined) {
        this.selectedControlNode.x = pos.x;
        this.selectedControlNode.y = pos.y;
      } else {
        this.interactionHandler.onDrag(event);
      }
      this.body.emitter.emit("_redraw");
    }

    /**
     * connecting or restoring the control nodes.
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "_controlNodeDragEnd",
    value: function _controlNodeDragEnd(event) {
      var pointer = this.body.functions.getPointer(event.center);
      var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
      var edge = this.body.edges[this.edgeBeingEditedId];
      // if the node that was dragged is not a control node, return
      if (this.selectedControlNode === undefined) {
        return;
      }

      // we use the selection to find the node that is being dragged. We explicitly DEselect the control node here.
      this.selectionHandler.unselectAll();
      var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
      var node = undefined;
      for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
        if (overlappingNodeIds[i] !== this.selectedControlNode.id) {
          node = this.body.nodes[overlappingNodeIds[i]];
          break;
        }
      }
      // perform the connection
      if (node !== undefined && this.selectedControlNode !== undefined) {
        if (node.isCluster === true) {
          alert(this.options.locales[this.options.locale]["createEdgeError"] || this.options.locales["en"]["createEdgeError"]);
        } else {
          var from = this.body.nodes[this.temporaryIds.nodes[0]];
          if (this.selectedControlNode.id === from.id) {
            this._performEditEdge(node.id, edge.to.id);
          } else {
            this._performEditEdge(edge.from.id, node.id);
          }
        }
      } else {
        edge.updateEdgeType();
        this.body.emitter.emit("restorePhysics");
      }
      this.body.emitter.emit("_redraw");
    }

    // ------------------------------------ END OF EDIT EDGE FUNCTIONS -----------------------------------------//

    // ------------------------------------------- ADD EDGE FUNCTIONS -----------------------------------------//
    /**
     * the function bound to the selection event. It checks if you want to connect a cluster and changes the description
     * to walk the user through the process.
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "_handleConnect",
    value: function _handleConnect(event) {
      // check to avoid double fireing of this function.
      if (new Date().valueOf() - this.touchTime > 100) {
        this.lastTouch = this.body.functions.getPointer(event.center);
        this.lastTouch.translation = _Object$assign({}, this.body.view.translation); // copy the object

        this.interactionHandler.drag.pointer = this.lastTouch; // Drag pointer is not updated when adding edges
        this.interactionHandler.drag.translation = this.lastTouch.translation;
        var pointer = this.lastTouch;
        var node = this.selectionHandler.getNodeAt(pointer);
        if (node !== undefined) {
          if (node.isCluster === true) {
            alert(this.options.locales[this.options.locale]["createEdgeError"] || this.options.locales["en"]["createEdgeError"]);
          } else {
            // create a node the temporary line can look at
            var targetNode = this._getNewTargetNode(node.x, node.y);
            this.body.nodes[targetNode.id] = targetNode;
            this.body.nodeIndices.push(targetNode.id);

            // create a temporary edge
            var connectionEdge = this.body.functions.createEdge({
              id: "connectionEdge" + v4(),
              from: node.id,
              to: targetNode.id,
              physics: false,
              smooth: {
                enabled: true,
                type: "continuous",
                roundness: 0.5
              }
            });
            this.body.edges[connectionEdge.id] = connectionEdge;
            this.body.edgeIndices.push(connectionEdge.id);
            this.temporaryIds.nodes.push(targetNode.id);
            this.temporaryIds.edges.push(connectionEdge.id);
          }
        }
        this.touchTime = new Date().valueOf();
      }
    }

    /**
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "_dragControlNode",
    value: function _dragControlNode(event) {
      var pointer = this.body.functions.getPointer(event.center);
      var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);
      // remember the edge id
      var connectFromId = undefined;
      if (this.temporaryIds.edges[0] !== undefined) {
        connectFromId = this.body.edges[this.temporaryIds.edges[0]].fromId;
      }

      // get the overlapping node but NOT the temporary node;
      var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
      var node = undefined;
      for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
        var _context30;
        // if the node id is NOT a temporary node, accept the node.
        if (_indexOfInstanceProperty(_context30 = this.temporaryIds.nodes).call(_context30, overlappingNodeIds[i]) === -1) {
          node = this.body.nodes[overlappingNodeIds[i]];
          break;
        }
      }
      event.controlEdge = {
        from: connectFromId,
        to: node ? node.id : undefined
      };
      this.selectionHandler.generateClickEvent("controlNodeDragging", event, pointer);
      if (this.temporaryIds.nodes[0] !== undefined) {
        var targetNode = this.body.nodes[this.temporaryIds.nodes[0]]; // there is only one temp node in the add edge mode.
        targetNode.x = this.canvas._XconvertDOMtoCanvas(pointer.x);
        targetNode.y = this.canvas._YconvertDOMtoCanvas(pointer.y);
        this.body.emitter.emit("_redraw");
      } else {
        this.interactionHandler.onDrag(event);
      }
    }

    /**
     * Connect the new edge to the target if one exists, otherwise remove temp line
     *
     * @param {Event}  event   The event
     * @private
     */
  }, {
    key: "_finishConnect",
    value: function _finishConnect(event) {
      var pointer = this.body.functions.getPointer(event.center);
      var pointerObj = this.selectionHandler._pointerToPositionObject(pointer);

      // remember the edge id
      var connectFromId = undefined;
      if (this.temporaryIds.edges[0] !== undefined) {
        connectFromId = this.body.edges[this.temporaryIds.edges[0]].fromId;
      }

      // get the overlapping node but NOT the temporary node;
      var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj);
      var node = undefined;
      for (var i = overlappingNodeIds.length - 1; i >= 0; i--) {
        var _context31;
        // if the node id is NOT a temporary node, accept the node.
        if (_indexOfInstanceProperty(_context31 = this.temporaryIds.nodes).call(_context31, overlappingNodeIds[i]) === -1) {
          node = this.body.nodes[overlappingNodeIds[i]];
          break;
        }
      }

      // clean temporary nodes and edges.
      this._cleanupTemporaryNodesAndEdges();

      // perform the connection
      if (node !== undefined) {
        if (node.isCluster === true) {
          alert(this.options.locales[this.options.locale]["createEdgeError"] || this.options.locales["en"]["createEdgeError"]);
        } else {
          if (this.body.nodes[connectFromId] !== undefined && this.body.nodes[node.id] !== undefined) {
            this._performAddEdge(connectFromId, node.id);
          }
        }
      }
      event.controlEdge = {
        from: connectFromId,
        to: node ? node.id : undefined
      };
      this.selectionHandler.generateClickEvent("controlNodeDragEnd", event, pointer);

      // No need to do _generateclickevent('dragEnd') here, the regular dragEnd event fires.
      this.body.emitter.emit("_redraw");
    }

    /**
     *
     * @param {Event} event
     * @private
     */
  }, {
    key: "_dragStartEdge",
    value: function _dragStartEdge(event) {
      var pointer = this.lastTouch;
      this.selectionHandler.generateClickEvent("dragStart", event, pointer, undefined, true);
    }

    // --------------------------------------- END OF ADD EDGE FUNCTIONS -------------------------------------//

    // ------------------------------ Performing all the actual data manipulation ------------------------//

    /**
     * Adds a node on the specified location
     *
     * @param {object} clickData
     * @private
     */
  }, {
    key: "_performAddNode",
    value: function _performAddNode(clickData) {
      var _this4 = this;
      var defaultData = {
        id: v4(),
        x: clickData.pointer.canvas.x,
        y: clickData.pointer.canvas.y,
        label: "new"
      };
      if (typeof this.options.addNode === "function") {
        if (this.options.addNode.length === 2) {
          this.options.addNode(defaultData, function (finalizedData) {
            if (finalizedData !== null && finalizedData !== undefined && _this4.inMode === "addNode") {
              // if for whatever reason the mode has changes (due to dataset change) disregard the callback
              _this4.body.data.nodes.getDataSet().add(finalizedData);
            }
            _this4.showManipulatorToolbar();
          });
        } else {
          this.showManipulatorToolbar();
          throw new Error("The function for add does not support two arguments (data,callback)");
        }
      } else {
        this.body.data.nodes.getDataSet().add(defaultData);
        this.showManipulatorToolbar();
      }
    }

    /**
     * connect two nodes with a new edge.
     *
     * @param {Node.id} sourceNodeId
     * @param {Node.id} targetNodeId
     * @private
     */
  }, {
    key: "_performAddEdge",
    value: function _performAddEdge(sourceNodeId, targetNodeId) {
      var _this5 = this;
      var defaultData = {
        from: sourceNodeId,
        to: targetNodeId
      };
      if (typeof this.options.addEdge === "function") {
        if (this.options.addEdge.length === 2) {
          this.options.addEdge(defaultData, function (finalizedData) {
            if (finalizedData !== null && finalizedData !== undefined && _this5.inMode === "addEdge") {
              // if for whatever reason the mode has changes (due to dataset change) disregard the callback
              _this5.body.data.edges.getDataSet().add(finalizedData);
              _this5.selectionHandler.unselectAll();
              _this5.showManipulatorToolbar();
            }
          });
        } else {
          throw new Error("The function for connect does not support two arguments (data,callback)");
        }
      } else {
        this.body.data.edges.getDataSet().add(defaultData);
        this.selectionHandler.unselectAll();
        this.showManipulatorToolbar();
      }
    }

    /**
     * connect two nodes with a new edge.
     *
     * @param {Node.id} sourceNodeId
     * @param {Node.id} targetNodeId
     * @private
     */
  }, {
    key: "_performEditEdge",
    value: function _performEditEdge(sourceNodeId, targetNodeId) {
      var _this6 = this;
      var defaultData = {
        id: this.edgeBeingEditedId,
        from: sourceNodeId,
        to: targetNodeId,
        label: this.body.data.edges.get(this.edgeBeingEditedId).label
      };
      var eeFunct = this.options.editEdge;
      if (_typeof(eeFunct) === "object") {
        eeFunct = eeFunct.editWithoutDrag;
      }
      if (typeof eeFunct === "function") {
        if (eeFunct.length === 2) {
          eeFunct(defaultData, function (finalizedData) {
            if (finalizedData === null || finalizedData === undefined || _this6.inMode !== "editEdge") {
              // if for whatever reason the mode has changes (due to dataset change) disregard the callback) {
              _this6.body.edges[defaultData.id].updateEdgeType();
              _this6.body.emitter.emit("_redraw");
              _this6.showManipulatorToolbar();
            } else {
              _this6.body.data.edges.getDataSet().update(finalizedData);
              _this6.selectionHandler.unselectAll();
              _this6.showManipulatorToolbar();
            }
          });
        } else {
          throw new Error("The function for edit does not support two arguments (data, callback)");
        }
      } else {
        this.body.data.edges.getDataSet().update(defaultData);
        this.selectionHandler.unselectAll();
        this.showManipulatorToolbar();
      }
    }
  }]);
  return ManipulationSystem;
}();

/**
 * This object contains all possible options. It will check if the types are correct, if required if the option is one
 * of the allowed values.
 *
 * __any__ means that the name of the property does not matter.
 * __type__ is a required field for all objects and contains the allowed types of all objects
 */
var string = "string";
var bool = "boolean";
var number = "number";
var array = "array";
var object = "object"; // should only be in a __type__ property
var dom = "dom";
var any = "any";
// List of endpoints
var endPoints = ["arrow", "bar", "box", "circle", "crow", "curve", "diamond", "image", "inv_curve", "inv_triangle", "triangle", "vee"];
/* eslint-disable @typescript-eslint/naming-convention -- The __*__ format is used to prevent collisions with actual option names. */
var nodeOptions = {
  borderWidth: {
    number: number
  },
  borderWidthSelected: {
    number: number,
    undefined: "undefined"
  },
  brokenImage: {
    string: string,
    undefined: "undefined"
  },
  chosen: {
    label: {
      boolean: bool,
      function: "function"
    },
    node: {
      boolean: bool,
      function: "function"
    },
    __type__: {
      object: object,
      boolean: bool
    }
  },
  color: {
    border: {
      string: string
    },
    background: {
      string: string
    },
    highlight: {
      border: {
        string: string
      },
      background: {
        string: string
      },
      __type__: {
        object: object,
        string: string
      }
    },
    hover: {
      border: {
        string: string
      },
      background: {
        string: string
      },
      __type__: {
        object: object,
        string: string
      }
    },
    __type__: {
      object: object,
      string: string
    }
  },
  opacity: {
    number: number,
    undefined: "undefined"
  },
  fixed: {
    x: {
      boolean: bool
    },
    y: {
      boolean: bool
    },
    __type__: {
      object: object,
      boolean: bool
    }
  },
  font: {
    align: {
      string: string
    },
    color: {
      string: string
    },
    size: {
      number: number
    },
    face: {
      string: string
    },
    background: {
      string: string
    },
    strokeWidth: {
      number: number
    },
    strokeColor: {
      string: string
    },
    vadjust: {
      number: number
    },
    multi: {
      boolean: bool,
      string: string
    },
    bold: {
      color: {
        string: string
      },
      size: {
        number: number
      },
      face: {
        string: string
      },
      mod: {
        string: string
      },
      vadjust: {
        number: number
      },
      __type__: {
        object: object,
        string: string
      }
    },
    boldital: {
      color: {
        string: string
      },
      size: {
        number: number
      },
      face: {
        string: string
      },
      mod: {
        string: string
      },
      vadjust: {
        number: number
      },
      __type__: {
        object: object,
        string: string
      }
    },
    ital: {
      color: {
        string: string
      },
      size: {
        number: number
      },
      face: {
        string: string
      },
      mod: {
        string: string
      },
      vadjust: {
        number: number
      },
      __type__: {
        object: object,
        string: string
      }
    },
    mono: {
      color: {
        string: string
      },
      size: {
        number: number
      },
      face: {
        string: string
      },
      mod: {
        string: string
      },
      vadjust: {
        number: number
      },
      __type__: {
        object: object,
        string: string
      }
    },
    __type__: {
      object: object,
      string: string
    }
  },
  group: {
    string: string,
    number: number,
    undefined: "undefined"
  },
  heightConstraint: {
    minimum: {
      number: number
    },
    valign: {
      string: string
    },
    __type__: {
      object: object,
      boolean: bool,
      number: number
    }
  },
  hidden: {
    boolean: bool
  },
  icon: {
    face: {
      string: string
    },
    code: {
      string: string
    },
    size: {
      number: number
    },
    color: {
      string: string
    },
    weight: {
      string: string,
      number: number
    },
    __type__: {
      object: object
    }
  },
  id: {
    string: string,
    number: number
  },
  image: {
    selected: {
      string: string,
      undefined: "undefined"
    },
    unselected: {
      string: string,
      undefined: "undefined"
    },
    __type__: {
      object: object,
      string: string
    }
  },
  imagePadding: {
    top: {
      number: number
    },
    right: {
      number: number
    },
    bottom: {
      number: number
    },
    left: {
      number: number
    },
    __type__: {
      object: object,
      number: number
    }
  },
  label: {
    string: string,
    undefined: "undefined"
  },
  labelHighlightBold: {
    boolean: bool
  },
  level: {
    number: number,
    undefined: "undefined"
  },
  margin: {
    top: {
      number: number
    },
    right: {
      number: number
    },
    bottom: {
      number: number
    },
    left: {
      number: number
    },
    __type__: {
      object: object,
      number: number
    }
  },
  mass: {
    number: number
  },
  physics: {
    boolean: bool
  },
  scaling: {
    min: {
      number: number
    },
    max: {
      number: number
    },
    label: {
      enabled: {
        boolean: bool
      },
      min: {
        number: number
      },
      max: {
        number: number
      },
      maxVisible: {
        number: number
      },
      drawThreshold: {
        number: number
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    customScalingFunction: {
      function: "function"
    },
    __type__: {
      object: object
    }
  },
  shadow: {
    enabled: {
      boolean: bool
    },
    color: {
      string: string
    },
    size: {
      number: number
    },
    x: {
      number: number
    },
    y: {
      number: number
    },
    __type__: {
      object: object,
      boolean: bool
    }
  },
  shape: {
    string: ["custom", "ellipse", "circle", "database", "box", "text", "image", "circularImage", "diamond", "dot", "star", "triangle", "triangleDown", "square", "icon", "hexagon"]
  },
  ctxRenderer: {
    function: "function"
  },
  shapeProperties: {
    borderDashes: {
      boolean: bool,
      array: array
    },
    borderRadius: {
      number: number
    },
    interpolation: {
      boolean: bool
    },
    useImageSize: {
      boolean: bool
    },
    useBorderWithImage: {
      boolean: bool
    },
    coordinateOrigin: {
      string: ["center", "top-left"]
    },
    __type__: {
      object: object
    }
  },
  size: {
    number: number
  },
  title: {
    string: string,
    dom: dom,
    undefined: "undefined"
  },
  value: {
    number: number,
    undefined: "undefined"
  },
  widthConstraint: {
    minimum: {
      number: number
    },
    maximum: {
      number: number
    },
    __type__: {
      object: object,
      boolean: bool,
      number: number
    }
  },
  x: {
    number: number
  },
  y: {
    number: number
  },
  __type__: {
    object: object
  }
};
var allOptions = {
  configure: {
    enabled: {
      boolean: bool
    },
    filter: {
      boolean: bool,
      string: string,
      array: array,
      function: "function"
    },
    container: {
      dom: dom
    },
    showButton: {
      boolean: bool
    },
    __type__: {
      object: object,
      boolean: bool,
      string: string,
      array: array,
      function: "function"
    }
  },
  edges: {
    arrows: {
      to: {
        enabled: {
          boolean: bool
        },
        scaleFactor: {
          number: number
        },
        type: {
          string: endPoints
        },
        imageHeight: {
          number: number
        },
        imageWidth: {
          number: number
        },
        src: {
          string: string
        },
        __type__: {
          object: object,
          boolean: bool
        }
      },
      middle: {
        enabled: {
          boolean: bool
        },
        scaleFactor: {
          number: number
        },
        type: {
          string: endPoints
        },
        imageWidth: {
          number: number
        },
        imageHeight: {
          number: number
        },
        src: {
          string: string
        },
        __type__: {
          object: object,
          boolean: bool
        }
      },
      from: {
        enabled: {
          boolean: bool
        },
        scaleFactor: {
          number: number
        },
        type: {
          string: endPoints
        },
        imageWidth: {
          number: number
        },
        imageHeight: {
          number: number
        },
        src: {
          string: string
        },
        __type__: {
          object: object,
          boolean: bool
        }
      },
      __type__: {
        string: ["from", "to", "middle"],
        object: object
      }
    },
    endPointOffset: {
      from: {
        number: number
      },
      to: {
        number: number
      },
      __type__: {
        object: object,
        number: number
      }
    },
    arrowStrikethrough: {
      boolean: bool
    },
    background: {
      enabled: {
        boolean: bool
      },
      color: {
        string: string
      },
      size: {
        number: number
      },
      dashes: {
        boolean: bool,
        array: array
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    chosen: {
      label: {
        boolean: bool,
        function: "function"
      },
      edge: {
        boolean: bool,
        function: "function"
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    color: {
      color: {
        string: string
      },
      highlight: {
        string: string
      },
      hover: {
        string: string
      },
      inherit: {
        string: ["from", "to", "both"],
        boolean: bool
      },
      opacity: {
        number: number
      },
      __type__: {
        object: object,
        string: string
      }
    },
    dashes: {
      boolean: bool,
      array: array
    },
    font: {
      color: {
        string: string
      },
      size: {
        number: number
      },
      face: {
        string: string
      },
      background: {
        string: string
      },
      strokeWidth: {
        number: number
      },
      strokeColor: {
        string: string
      },
      align: {
        string: ["horizontal", "top", "middle", "bottom"]
      },
      vadjust: {
        number: number
      },
      multi: {
        boolean: bool,
        string: string
      },
      bold: {
        color: {
          string: string
        },
        size: {
          number: number
        },
        face: {
          string: string
        },
        mod: {
          string: string
        },
        vadjust: {
          number: number
        },
        __type__: {
          object: object,
          string: string
        }
      },
      boldital: {
        color: {
          string: string
        },
        size: {
          number: number
        },
        face: {
          string: string
        },
        mod: {
          string: string
        },
        vadjust: {
          number: number
        },
        __type__: {
          object: object,
          string: string
        }
      },
      ital: {
        color: {
          string: string
        },
        size: {
          number: number
        },
        face: {
          string: string
        },
        mod: {
          string: string
        },
        vadjust: {
          number: number
        },
        __type__: {
          object: object,
          string: string
        }
      },
      mono: {
        color: {
          string: string
        },
        size: {
          number: number
        },
        face: {
          string: string
        },
        mod: {
          string: string
        },
        vadjust: {
          number: number
        },
        __type__: {
          object: object,
          string: string
        }
      },
      __type__: {
        object: object,
        string: string
      }
    },
    hidden: {
      boolean: bool
    },
    hoverWidth: {
      function: "function",
      number: number
    },
    label: {
      string: string,
      undefined: "undefined"
    },
    labelHighlightBold: {
      boolean: bool
    },
    length: {
      number: number,
      undefined: "undefined"
    },
    physics: {
      boolean: bool
    },
    scaling: {
      min: {
        number: number
      },
      max: {
        number: number
      },
      label: {
        enabled: {
          boolean: bool
        },
        min: {
          number: number
        },
        max: {
          number: number
        },
        maxVisible: {
          number: number
        },
        drawThreshold: {
          number: number
        },
        __type__: {
          object: object,
          boolean: bool
        }
      },
      customScalingFunction: {
        function: "function"
      },
      __type__: {
        object: object
      }
    },
    selectionWidth: {
      function: "function",
      number: number
    },
    selfReferenceSize: {
      number: number
    },
    selfReference: {
      size: {
        number: number
      },
      angle: {
        number: number
      },
      renderBehindTheNode: {
        boolean: bool
      },
      __type__: {
        object: object
      }
    },
    shadow: {
      enabled: {
        boolean: bool
      },
      color: {
        string: string
      },
      size: {
        number: number
      },
      x: {
        number: number
      },
      y: {
        number: number
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    smooth: {
      enabled: {
        boolean: bool
      },
      type: {
        string: ["dynamic", "continuous", "discrete", "diagonalCross", "straightCross", "horizontal", "vertical", "curvedCW", "curvedCCW", "cubicBezier"]
      },
      roundness: {
        number: number
      },
      forceDirection: {
        string: ["horizontal", "vertical", "none"],
        boolean: bool
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    title: {
      string: string,
      undefined: "undefined"
    },
    width: {
      number: number
    },
    widthConstraint: {
      maximum: {
        number: number
      },
      __type__: {
        object: object,
        boolean: bool,
        number: number
      }
    },
    value: {
      number: number,
      undefined: "undefined"
    },
    __type__: {
      object: object
    }
  },
  groups: {
    useDefaultGroups: {
      boolean: bool
    },
    __any__: nodeOptions,
    __type__: {
      object: object
    }
  },
  interaction: {
    dragNodes: {
      boolean: bool
    },
    dragView: {
      boolean: bool
    },
    hideEdgesOnDrag: {
      boolean: bool
    },
    hideEdgesOnZoom: {
      boolean: bool
    },
    hideNodesOnDrag: {
      boolean: bool
    },
    hover: {
      boolean: bool
    },
    keyboard: {
      enabled: {
        boolean: bool
      },
      speed: {
        x: {
          number: number
        },
        y: {
          number: number
        },
        zoom: {
          number: number
        },
        __type__: {
          object: object
        }
      },
      bindToWindow: {
        boolean: bool
      },
      autoFocus: {
        boolean: bool
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    multiselect: {
      boolean: bool
    },
    navigationButtons: {
      boolean: bool
    },
    selectable: {
      boolean: bool
    },
    selectConnectedEdges: {
      boolean: bool
    },
    hoverConnectedEdges: {
      boolean: bool
    },
    tooltipDelay: {
      number: number
    },
    zoomView: {
      boolean: bool
    },
    zoomSpeed: {
      number: number
    },
    __type__: {
      object: object
    }
  },
  layout: {
    randomSeed: {
      undefined: "undefined",
      number: number,
      string: string
    },
    improvedLayout: {
      boolean: bool
    },
    clusterThreshold: {
      number: number
    },
    hierarchical: {
      enabled: {
        boolean: bool
      },
      levelSeparation: {
        number: number
      },
      nodeSpacing: {
        number: number
      },
      treeSpacing: {
        number: number
      },
      blockShifting: {
        boolean: bool
      },
      edgeMinimization: {
        boolean: bool
      },
      parentCentralization: {
        boolean: bool
      },
      direction: {
        string: ["UD", "DU", "LR", "RL"]
      },
      sortMethod: {
        string: ["hubsize", "directed"]
      },
      shakeTowards: {
        string: ["leaves", "roots"]
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    __type__: {
      object: object
    }
  },
  manipulation: {
    enabled: {
      boolean: bool
    },
    initiallyActive: {
      boolean: bool
    },
    addNode: {
      boolean: bool,
      function: "function"
    },
    addEdge: {
      boolean: bool,
      function: "function"
    },
    editNode: {
      function: "function"
    },
    editEdge: {
      editWithoutDrag: {
        function: "function"
      },
      __type__: {
        object: object,
        boolean: bool,
        function: "function"
      }
    },
    deleteNode: {
      boolean: bool,
      function: "function"
    },
    deleteEdge: {
      boolean: bool,
      function: "function"
    },
    controlNodeStyle: nodeOptions,
    __type__: {
      object: object,
      boolean: bool
    }
  },
  nodes: nodeOptions,
  physics: {
    enabled: {
      boolean: bool
    },
    barnesHut: {
      theta: {
        number: number
      },
      gravitationalConstant: {
        number: number
      },
      centralGravity: {
        number: number
      },
      springLength: {
        number: number
      },
      springConstant: {
        number: number
      },
      damping: {
        number: number
      },
      avoidOverlap: {
        number: number
      },
      __type__: {
        object: object
      }
    },
    forceAtlas2Based: {
      theta: {
        number: number
      },
      gravitationalConstant: {
        number: number
      },
      centralGravity: {
        number: number
      },
      springLength: {
        number: number
      },
      springConstant: {
        number: number
      },
      damping: {
        number: number
      },
      avoidOverlap: {
        number: number
      },
      __type__: {
        object: object
      }
    },
    repulsion: {
      centralGravity: {
        number: number
      },
      springLength: {
        number: number
      },
      springConstant: {
        number: number
      },
      nodeDistance: {
        number: number
      },
      damping: {
        number: number
      },
      __type__: {
        object: object
      }
    },
    hierarchicalRepulsion: {
      centralGravity: {
        number: number
      },
      springLength: {
        number: number
      },
      springConstant: {
        number: number
      },
      nodeDistance: {
        number: number
      },
      damping: {
        number: number
      },
      avoidOverlap: {
        number: number
      },
      __type__: {
        object: object
      }
    },
    maxVelocity: {
      number: number
    },
    minVelocity: {
      number: number
    },
    solver: {
      string: ["barnesHut", "repulsion", "hierarchicalRepulsion", "forceAtlas2Based"]
    },
    stabilization: {
      enabled: {
        boolean: bool
      },
      iterations: {
        number: number
      },
      updateInterval: {
        number: number
      },
      onlyDynamicEdges: {
        boolean: bool
      },
      fit: {
        boolean: bool
      },
      __type__: {
        object: object,
        boolean: bool
      }
    },
    timestep: {
      number: number
    },
    adaptiveTimestep: {
      boolean: bool
    },
    wind: {
      x: {
        number: number
      },
      y: {
        number: number
      },
      __type__: {
        object: object
      }
    },
    __type__: {
      object: object,
      boolean: bool
    }
  },
  //globals :
  autoResize: {
    boolean: bool
  },
  clickToUse: {
    boolean: bool
  },
  locale: {
    string: string
  },
  locales: {
    __any__: {
      any: any
    },
    __type__: {
      object: object
    }
  },
  height: {
    string: string
  },
  width: {
    string: string
  },
  __type__: {
    object: object
  }
};
/* eslint-enable @typescript-eslint/naming-convention */
/**
 * This provides ranges, initial values, steps and dropdown menu choices for the
 * configuration.
 *
 * @remarks
 * Checkbox: `boolean`
 *   The value supllied will be used as the initial value.
 *
 * Text field: `string`
 *   The passed text will be used as the initial value. Any text will be
 *   accepted afterwards.
 *
 * Number range: `[number, number, number, number]`
 *   The meanings are `[initial value, min, max, step]`.
 *
 * Dropdown: `[Exclude<string, "color">, ...(string | number | boolean)[]]`
 *   Translations for people with poor understanding of TypeScript: the first
 *   value always has to be a string but never `"color"`, the rest can be any
 *   combination of strings, numbers and booleans.
 *
 * Color picker: `["color", string]`
 *   The first value says this will be a color picker not a dropdown menu. The
 *   next value is the initial color.
 */
var configureOptions = {
  nodes: {
    borderWidth: [1, 0, 10, 1],
    borderWidthSelected: [2, 0, 10, 1],
    color: {
      border: ["color", "#2B7CE9"],
      background: ["color", "#97C2FC"],
      highlight: {
        border: ["color", "#2B7CE9"],
        background: ["color", "#D2E5FF"]
      },
      hover: {
        border: ["color", "#2B7CE9"],
        background: ["color", "#D2E5FF"]
      }
    },
    opacity: [0, 0, 1, 0.1],
    fixed: {
      x: false,
      y: false
    },
    font: {
      color: ["color", "#343434"],
      size: [14, 0, 100, 1],
      face: ["arial", "verdana", "tahoma"],
      background: ["color", "none"],
      strokeWidth: [0, 0, 50, 1],
      strokeColor: ["color", "#ffffff"]
    },
    //group: 'string',
    hidden: false,
    labelHighlightBold: true,
    //icon: {
    //  face: 'string',  //'FontAwesome',
    //  code: 'string',  //'\uf007',
    //  size: [50, 0, 200, 1],  //50,
    //  color: ['color','#2B7CE9']   //'#aa00ff'
    //},
    //image: 'string', // --> URL
    physics: true,
    scaling: {
      min: [10, 0, 200, 1],
      max: [30, 0, 200, 1],
      label: {
        enabled: false,
        min: [14, 0, 200, 1],
        max: [30, 0, 200, 1],
        maxVisible: [30, 0, 200, 1],
        drawThreshold: [5, 0, 20, 1]
      }
    },
    shadow: {
      enabled: false,
      color: "rgba(0,0,0,0.5)",
      size: [10, 0, 20, 1],
      x: [5, -30, 30, 1],
      y: [5, -30, 30, 1]
    },
    shape: ["ellipse", "box", "circle", "database", "diamond", "dot", "square", "star", "text", "triangle", "triangleDown", "hexagon"],
    shapeProperties: {
      borderDashes: false,
      borderRadius: [6, 0, 20, 1],
      interpolation: true,
      useImageSize: false
    },
    size: [25, 0, 200, 1]
  },
  edges: {
    arrows: {
      to: {
        enabled: false,
        scaleFactor: [1, 0, 3, 0.05],
        type: "arrow"
      },
      middle: {
        enabled: false,
        scaleFactor: [1, 0, 3, 0.05],
        type: "arrow"
      },
      from: {
        enabled: false,
        scaleFactor: [1, 0, 3, 0.05],
        type: "arrow"
      }
    },
    endPointOffset: {
      from: [0, -10, 10, 1],
      to: [0, -10, 10, 1]
    },
    arrowStrikethrough: true,
    color: {
      color: ["color", "#848484"],
      highlight: ["color", "#848484"],
      hover: ["color", "#848484"],
      inherit: ["from", "to", "both", true, false],
      opacity: [1, 0, 1, 0.05]
    },
    dashes: false,
    font: {
      color: ["color", "#343434"],
      size: [14, 0, 100, 1],
      face: ["arial", "verdana", "tahoma"],
      background: ["color", "none"],
      strokeWidth: [2, 0, 50, 1],
      strokeColor: ["color", "#ffffff"],
      align: ["horizontal", "top", "middle", "bottom"]
    },
    hidden: false,
    hoverWidth: [1.5, 0, 5, 0.1],
    labelHighlightBold: true,
    physics: true,
    scaling: {
      min: [1, 0, 100, 1],
      max: [15, 0, 100, 1],
      label: {
        enabled: true,
        min: [14, 0, 200, 1],
        max: [30, 0, 200, 1],
        maxVisible: [30, 0, 200, 1],
        drawThreshold: [5, 0, 20, 1]
      }
    },
    selectionWidth: [1.5, 0, 5, 0.1],
    selfReferenceSize: [20, 0, 200, 1],
    selfReference: {
      size: [20, 0, 200, 1],
      angle: [Math.PI / 2, -6 * Math.PI, 6 * Math.PI, Math.PI / 8],
      renderBehindTheNode: true
    },
    shadow: {
      enabled: false,
      color: "rgba(0,0,0,0.5)",
      size: [10, 0, 20, 1],
      x: [5, -30, 30, 1],
      y: [5, -30, 30, 1]
    },
    smooth: {
      enabled: true,
      type: ["dynamic", "continuous", "discrete", "diagonalCross", "straightCross", "horizontal", "vertical", "curvedCW", "curvedCCW", "cubicBezier"],
      forceDirection: ["horizontal", "vertical", "none"],
      roundness: [0.5, 0, 1, 0.05]
    },
    width: [1, 0, 30, 1]
  },
  layout: {
    //randomSeed: [0, 0, 500, 1],
    //improvedLayout: true,
    hierarchical: {
      enabled: false,
      levelSeparation: [150, 20, 500, 5],
      nodeSpacing: [100, 20, 500, 5],
      treeSpacing: [200, 20, 500, 5],
      blockShifting: true,
      edgeMinimization: true,
      parentCentralization: true,
      direction: ["UD", "DU", "LR", "RL"],
      sortMethod: ["hubsize", "directed"],
      shakeTowards: ["leaves", "roots"] // leaves, roots
    }
  },

  interaction: {
    dragNodes: true,
    dragView: true,
    hideEdgesOnDrag: false,
    hideEdgesOnZoom: false,
    hideNodesOnDrag: false,
    hover: false,
    keyboard: {
      enabled: false,
      speed: {
        x: [10, 0, 40, 1],
        y: [10, 0, 40, 1],
        zoom: [0.02, 0, 0.1, 0.005]
      },
      bindToWindow: true,
      autoFocus: true
    },
    multiselect: false,
    navigationButtons: false,
    selectable: true,
    selectConnectedEdges: true,
    hoverConnectedEdges: true,
    tooltipDelay: [300, 0, 1000, 25],
    zoomView: true,
    zoomSpeed: [1, 0.1, 2, 0.1]
  },
  manipulation: {
    enabled: false,
    initiallyActive: false
  },
  physics: {
    enabled: true,
    barnesHut: {
      theta: [0.5, 0.1, 1, 0.05],
      gravitationalConstant: [-2000, -30000, 0, 50],
      centralGravity: [0.3, 0, 10, 0.05],
      springLength: [95, 0, 500, 5],
      springConstant: [0.04, 0, 1.2, 0.005],
      damping: [0.09, 0, 1, 0.01],
      avoidOverlap: [0, 0, 1, 0.01]
    },
    forceAtlas2Based: {
      theta: [0.5, 0.1, 1, 0.05],
      gravitationalConstant: [-50, -500, 0, 1],
      centralGravity: [0.01, 0, 1, 0.005],
      springLength: [95, 0, 500, 5],
      springConstant: [0.08, 0, 1.2, 0.005],
      damping: [0.4, 0, 1, 0.01],
      avoidOverlap: [0, 0, 1, 0.01]
    },
    repulsion: {
      centralGravity: [0.2, 0, 10, 0.05],
      springLength: [200, 0, 500, 5],
      springConstant: [0.05, 0, 1.2, 0.005],
      nodeDistance: [100, 0, 500, 5],
      damping: [0.09, 0, 1, 0.01]
    },
    hierarchicalRepulsion: {
      centralGravity: [0.2, 0, 10, 0.05],
      springLength: [100, 0, 500, 5],
      springConstant: [0.01, 0, 1.2, 0.005],
      nodeDistance: [120, 0, 500, 5],
      damping: [0.09, 0, 1, 0.01],
      avoidOverlap: [0, 0, 1, 0.01]
    },
    maxVelocity: [50, 0, 150, 1],
    minVelocity: [0.1, 0.01, 0.5, 0.01],
    solver: ["barnesHut", "forceAtlas2Based", "repulsion", "hierarchicalRepulsion"],
    timestep: [0.5, 0.01, 1, 0.01],
    wind: {
      x: [0, -10, 10, 0.1],
      y: [0, -10, 10, 0.1]
    }
    //adaptiveTimestep: true
  }
};

var configuratorHideOption = function configuratorHideOption(parentPath, optionName, options) {
  var _context;
  if (_includesInstanceProperty(parentPath).call(parentPath, "physics") && _includesInstanceProperty(_context = configureOptions.physics.solver).call(_context, optionName) && options.physics.solver !== optionName && optionName !== "wind") {
    return true;
  }
  return false;
};

/**
 *  The Floyd–Warshall algorithm is an algorithm for finding shortest paths in
 *  a weighted graph with positive or negative edge weights (but with no negative
 *  cycles). - https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm
 */
var FloydWarshall = /*#__PURE__*/function () {
  /**
   * @ignore
   */
  function FloydWarshall() {
    _classCallCheck(this, FloydWarshall);
  }

  /**
   *
   * @param {object} body
   * @param {Array.<Node>} nodesArray
   * @param {Array.<Edge>} edgesArray
   * @returns {{}}
   */
  _createClass(FloydWarshall, [{
    key: "getDistances",
    value: function getDistances(body, nodesArray, edgesArray) {
      var D_matrix = {};
      var edges = body.edges;

      // prepare matrix with large numbers
      for (var i = 0; i < nodesArray.length; i++) {
        var node = nodesArray[i];
        var cell = {};
        D_matrix[node] = cell;
        for (var j = 0; j < nodesArray.length; j++) {
          cell[nodesArray[j]] = i == j ? 0 : 1e9;
        }
      }

      // put the weights for the edges in. This assumes unidirectionality.
      for (var _i = 0; _i < edgesArray.length; _i++) {
        var edge = edges[edgesArray[_i]];
        // edge has to be connected if it counts to the distances. If it is connected to inner clusters it will crash so we also check if it is in the D_matrix
        if (edge.connected === true && D_matrix[edge.fromId] !== undefined && D_matrix[edge.toId] !== undefined) {
          D_matrix[edge.fromId][edge.toId] = 1;
          D_matrix[edge.toId][edge.fromId] = 1;
        }
      }
      var nodeCount = nodesArray.length;

      // Adapted FloydWarshall based on unidirectionality to greatly reduce complexity.
      for (var k = 0; k < nodeCount; k++) {
        var knode = nodesArray[k];
        var kcolm = D_matrix[knode];
        for (var _i2 = 0; _i2 < nodeCount - 1; _i2++) {
          var inode = nodesArray[_i2];
          var icolm = D_matrix[inode];
          for (var _j = _i2 + 1; _j < nodeCount; _j++) {
            var jnode = nodesArray[_j];
            var jcolm = D_matrix[jnode];
            var val = Math.min(icolm[jnode], icolm[knode] + kcolm[jnode]);
            icolm[jnode] = val;
            jcolm[inode] = val;
          }
        }
      }
      return D_matrix;
    }
  }]);
  return FloydWarshall;
}();

/**
 * KamadaKawai positions the nodes initially based on
 *
 * "AN ALGORITHM FOR DRAWING GENERAL UNDIRECTED GRAPHS"
 * -- Tomihisa KAMADA and Satoru KAWAI in 1989
 *
 * Possible optimizations in the distance calculation can be implemented.
 */
var KamadaKawai = /*#__PURE__*/function () {
  /**
   * @param {object} body
   * @param {number} edgeLength
   * @param {number} edgeStrength
   */
  function KamadaKawai(body, edgeLength, edgeStrength) {
    _classCallCheck(this, KamadaKawai);
    this.body = body;
    this.springLength = edgeLength;
    this.springConstant = edgeStrength;
    this.distanceSolver = new FloydWarshall();
  }

  /**
   * Not sure if needed but can be used to update the spring length and spring constant
   *
   * @param {object} options
   */
  _createClass(KamadaKawai, [{
    key: "setOptions",
    value: function setOptions(options) {
      if (options) {
        if (options.springLength) {
          this.springLength = options.springLength;
        }
        if (options.springConstant) {
          this.springConstant = options.springConstant;
        }
      }
    }

    /**
     * Position the system
     *
     * @param {Array.<Node>} nodesArray
     * @param {Array.<vis.Edge>} edgesArray
     * @param {boolean} [ignoreClusters=false]
     */
  }, {
    key: "solve",
    value: function solve(nodesArray, edgesArray) {
      var ignoreClusters = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      // get distance matrix
      var D_matrix = this.distanceSolver.getDistances(this.body, nodesArray, edgesArray); // distance matrix

      // get the L Matrix
      this._createL_matrix(D_matrix);

      // get the K Matrix
      this._createK_matrix(D_matrix);

      // initial E Matrix
      this._createE_matrix();

      // calculate positions
      var threshold = 0.01;
      var innerThreshold = 1;
      var iterations = 0;
      var maxIterations = Math.max(1000, Math.min(10 * this.body.nodeIndices.length, 6000));
      var maxInnerIterations = 5;
      var maxEnergy = 1e9;
      var highE_nodeId = 0,
        dE_dx = 0,
        dE_dy = 0,
        delta_m = 0,
        subIterations = 0;
      while (maxEnergy > threshold && iterations < maxIterations) {
        iterations += 1;
        var _this$_getHighestEner = this._getHighestEnergyNode(ignoreClusters);
        var _this$_getHighestEner2 = _slicedToArray(_this$_getHighestEner, 4);
        highE_nodeId = _this$_getHighestEner2[0];
        maxEnergy = _this$_getHighestEner2[1];
        dE_dx = _this$_getHighestEner2[2];
        dE_dy = _this$_getHighestEner2[3];
        delta_m = maxEnergy;
        subIterations = 0;
        while (delta_m > innerThreshold && subIterations < maxInnerIterations) {
          subIterations += 1;
          this._moveNode(highE_nodeId, dE_dx, dE_dy);
          var _this$_getEnergy = this._getEnergy(highE_nodeId);
          var _this$_getEnergy2 = _slicedToArray(_this$_getEnergy, 3);
          delta_m = _this$_getEnergy2[0];
          dE_dx = _this$_getEnergy2[1];
          dE_dy = _this$_getEnergy2[2];
        }
      }
    }

    /**
     * get the node with the highest energy
     *
     * @param {boolean} ignoreClusters
     * @returns {number[]}
     * @private
     */
  }, {
    key: "_getHighestEnergyNode",
    value: function _getHighestEnergyNode(ignoreClusters) {
      var nodesArray = this.body.nodeIndices;
      var nodes = this.body.nodes;
      var maxEnergy = 0;
      var maxEnergyNodeId = nodesArray[0];
      var dE_dx_max = 0,
        dE_dy_max = 0;
      for (var nodeIdx = 0; nodeIdx < nodesArray.length; nodeIdx++) {
        var m = nodesArray[nodeIdx];
        // by not evaluating nodes with predefined positions we should only move nodes that have no positions.
        if (nodes[m].predefinedPosition !== true || nodes[m].isCluster === true && ignoreClusters === true || nodes[m].options.fixed.x !== true || nodes[m].options.fixed.y !== true) {
          var _this$_getEnergy3 = this._getEnergy(m),
            _this$_getEnergy4 = _slicedToArray(_this$_getEnergy3, 3),
            delta_m = _this$_getEnergy4[0],
            dE_dx = _this$_getEnergy4[1],
            dE_dy = _this$_getEnergy4[2];
          if (maxEnergy < delta_m) {
            maxEnergy = delta_m;
            maxEnergyNodeId = m;
            dE_dx_max = dE_dx;
            dE_dy_max = dE_dy;
          }
        }
      }
      return [maxEnergyNodeId, maxEnergy, dE_dx_max, dE_dy_max];
    }

    /**
     * calculate the energy of a single node
     *
     * @param {Node.id} m
     * @returns {number[]}
     * @private
     */
  }, {
    key: "_getEnergy",
    value: function _getEnergy(m) {
      var _this$E_sums$m = _slicedToArray(this.E_sums[m], 2),
        dE_dx = _this$E_sums$m[0],
        dE_dy = _this$E_sums$m[1];
      var delta_m = Math.sqrt(Math.pow(dE_dx, 2) + Math.pow(dE_dy, 2));
      return [delta_m, dE_dx, dE_dy];
    }

    /**
     * move the node based on it's energy
     * the dx and dy are calculated from the linear system proposed by Kamada and Kawai
     *
     * @param {number} m
     * @param {number} dE_dx
     * @param {number} dE_dy
     * @private
     */
  }, {
    key: "_moveNode",
    value: function _moveNode(m, dE_dx, dE_dy) {
      var nodesArray = this.body.nodeIndices;
      var nodes = this.body.nodes;
      var d2E_dx2 = 0;
      var d2E_dxdy = 0;
      var d2E_dy2 = 0;
      var x_m = nodes[m].x;
      var y_m = nodes[m].y;
      var km = this.K_matrix[m];
      var lm = this.L_matrix[m];
      for (var iIdx = 0; iIdx < nodesArray.length; iIdx++) {
        var i = nodesArray[iIdx];
        if (i !== m) {
          var x_i = nodes[i].x;
          var y_i = nodes[i].y;
          var kmat = km[i];
          var lmat = lm[i];
          var denominator = 1.0 / Math.pow(Math.pow(x_m - x_i, 2) + Math.pow(y_m - y_i, 2), 1.5);
          d2E_dx2 += kmat * (1 - lmat * Math.pow(y_m - y_i, 2) * denominator);
          d2E_dxdy += kmat * (lmat * (x_m - x_i) * (y_m - y_i) * denominator);
          d2E_dy2 += kmat * (1 - lmat * Math.pow(x_m - x_i, 2) * denominator);
        }
      }
      // make the variable names easier to make the solving of the linear system easier to read
      var A = d2E_dx2,
        B = d2E_dxdy,
        C = dE_dx,
        D = d2E_dy2,
        E = dE_dy;

      // solve the linear system for dx and dy
      var dy = (C / A + E / B) / (B / A - D / B);
      var dx = -(B * dy + C) / A;

      // move the node
      nodes[m].x += dx;
      nodes[m].y += dy;

      // Recalculate E_matrix (should be incremental)
      this._updateE_matrix(m);
    }

    /**
     * Create the L matrix: edge length times shortest path
     *
     * @param {object} D_matrix
     * @private
     */
  }, {
    key: "_createL_matrix",
    value: function _createL_matrix(D_matrix) {
      var nodesArray = this.body.nodeIndices;
      var edgeLength = this.springLength;
      this.L_matrix = [];
      for (var i = 0; i < nodesArray.length; i++) {
        this.L_matrix[nodesArray[i]] = {};
        for (var j = 0; j < nodesArray.length; j++) {
          this.L_matrix[nodesArray[i]][nodesArray[j]] = edgeLength * D_matrix[nodesArray[i]][nodesArray[j]];
        }
      }
    }

    /**
     * Create the K matrix: spring constants times shortest path
     *
     * @param {object} D_matrix
     * @private
     */
  }, {
    key: "_createK_matrix",
    value: function _createK_matrix(D_matrix) {
      var nodesArray = this.body.nodeIndices;
      var edgeStrength = this.springConstant;
      this.K_matrix = [];
      for (var i = 0; i < nodesArray.length; i++) {
        this.K_matrix[nodesArray[i]] = {};
        for (var j = 0; j < nodesArray.length; j++) {
          this.K_matrix[nodesArray[i]][nodesArray[j]] = edgeStrength * Math.pow(D_matrix[nodesArray[i]][nodesArray[j]], -2);
        }
      }
    }

    /**
     *  Create matrix with all energies between nodes
     *
     *  @private
     */
  }, {
    key: "_createE_matrix",
    value: function _createE_matrix() {
      var nodesArray = this.body.nodeIndices;
      var nodes = this.body.nodes;
      this.E_matrix = {};
      this.E_sums = {};
      for (var mIdx = 0; mIdx < nodesArray.length; mIdx++) {
        this.E_matrix[nodesArray[mIdx]] = [];
      }
      for (var _mIdx = 0; _mIdx < nodesArray.length; _mIdx++) {
        var m = nodesArray[_mIdx];
        var x_m = nodes[m].x;
        var y_m = nodes[m].y;
        var dE_dx = 0;
        var dE_dy = 0;
        for (var iIdx = _mIdx; iIdx < nodesArray.length; iIdx++) {
          var i = nodesArray[iIdx];
          if (i !== m) {
            var x_i = nodes[i].x;
            var y_i = nodes[i].y;
            var denominator = 1.0 / Math.sqrt(Math.pow(x_m - x_i, 2) + Math.pow(y_m - y_i, 2));
            this.E_matrix[m][iIdx] = [this.K_matrix[m][i] * (x_m - x_i - this.L_matrix[m][i] * (x_m - x_i) * denominator), this.K_matrix[m][i] * (y_m - y_i - this.L_matrix[m][i] * (y_m - y_i) * denominator)];
            this.E_matrix[i][_mIdx] = this.E_matrix[m][iIdx];
            dE_dx += this.E_matrix[m][iIdx][0];
            dE_dy += this.E_matrix[m][iIdx][1];
          }
        }
        //Store sum
        this.E_sums[m] = [dE_dx, dE_dy];
      }
    }

    /**
     * Update method, just doing single column (rows are auto-updated) (update all sums)
     *
     * @param {number} m
     * @private
     */
  }, {
    key: "_updateE_matrix",
    value: function _updateE_matrix(m) {
      var nodesArray = this.body.nodeIndices;
      var nodes = this.body.nodes;
      var colm = this.E_matrix[m];
      var kcolm = this.K_matrix[m];
      var lcolm = this.L_matrix[m];
      var x_m = nodes[m].x;
      var y_m = nodes[m].y;
      var dE_dx = 0;
      var dE_dy = 0;
      for (var iIdx = 0; iIdx < nodesArray.length; iIdx++) {
        var i = nodesArray[iIdx];
        if (i !== m) {
          //Keep old energy value for sum modification below
          var cell = colm[iIdx];
          var oldDx = cell[0];
          var oldDy = cell[1];

          //Calc new energy:
          var x_i = nodes[i].x;
          var y_i = nodes[i].y;
          var denominator = 1.0 / Math.sqrt(Math.pow(x_m - x_i, 2) + Math.pow(y_m - y_i, 2));
          var dx = kcolm[i] * (x_m - x_i - lcolm[i] * (x_m - x_i) * denominator);
          var dy = kcolm[i] * (y_m - y_i - lcolm[i] * (y_m - y_i) * denominator);
          colm[iIdx] = [dx, dy];
          dE_dx += dx;
          dE_dy += dy;

          //add new energy to sum of each column
          var sum = this.E_sums[i];
          sum[0] += dx - oldDx;
          sum[1] += dy - oldDy;
        }
      }
      //Store sum at -1 index
      this.E_sums[m] = [dE_dx, dE_dy];
    }
  }]);
  return KamadaKawai;
}();

/**
 * Create a network visualization, displaying nodes and edges.
 *
 * @param {Element} container   The DOM element in which the Network will
 *                                  be created. Normally a div element.
 * @param {object} data         An object containing parameters
 *                              {Array} nodes
 *                              {Array} edges
 * @param {object} options      Options
 * @class Network
 */
function Network(container, data, options) {
  var _context,
    _context2,
    _context3,
    _context4,
    _this = this;
  if (!(this instanceof Network)) {
    throw new SyntaxError("Constructor must be called with the new operator");
  }

  // set constant values
  this.options = {};
  this.defaultOptions = {
    locale: "en",
    locales: locales,
    clickToUse: false
  };
  _Object$assign(this.options, this.defaultOptions);

  /**
   * Containers for nodes and edges.
   *
   * 'edges' and 'nodes' contain the full definitions of all the network elements.
   * 'nodeIndices' and 'edgeIndices' contain the id's of the active elements.
   *
   * The distinction is important, because a defined node need not be active, i.e.
   * visible on the canvas. This happens in particular when clusters are defined, in
   * that case there will be nodes and edges not displayed.
   * The bottom line is that all code with actions related to visibility, *must* use
   * 'nodeIndices' and 'edgeIndices', not 'nodes' and 'edges' directly.
   */
  this.body = {
    container: container,
    // See comment above for following fields
    nodes: {},
    nodeIndices: [],
    edges: {},
    edgeIndices: [],
    emitter: {
      on: _bindInstanceProperty$1(_context = this.on).call(_context, this),
      off: _bindInstanceProperty$1(_context2 = this.off).call(_context2, this),
      emit: _bindInstanceProperty$1(_context3 = this.emit).call(_context3, this),
      once: _bindInstanceProperty$1(_context4 = this.once).call(_context4, this)
    },
    eventListeners: {
      onTap: function onTap() {},
      onTouch: function onTouch() {},
      onDoubleTap: function onDoubleTap() {},
      onHold: function onHold() {},
      onDragStart: function onDragStart() {},
      onDrag: function onDrag() {},
      onDragEnd: function onDragEnd() {},
      onMouseWheel: function onMouseWheel() {},
      onPinch: function onPinch() {},
      onMouseMove: function onMouseMove() {},
      onRelease: function onRelease() {},
      onContext: function onContext() {}
    },
    data: {
      nodes: null,
      // A DataSet or DataView
      edges: null // A DataSet or DataView
    },

    functions: {
      createNode: function createNode() {},
      createEdge: function createEdge() {},
      getPointer: function getPointer() {}
    },
    modules: {},
    view: {
      scale: 1,
      translation: {
        x: 0,
        y: 0
      }
    },
    selectionBox: {
      show: false,
      position: {
        start: {
          x: 0,
          y: 0
        },
        end: {
          x: 0,
          y: 0
        }
      }
    }
  };

  // bind the event listeners
  this.bindEventListeners();

  // setting up all modules
  this.images = new Images(function () {
    return _this.body.emitter.emit("_requestRedraw");
  }); // object with images
  this.groups = new Groups(); // object with groups
  this.canvas = new Canvas(this.body); // DOM handler
  this.selectionHandler = new SelectionHandler(this.body, this.canvas); // Selection handler
  this.interactionHandler = new InteractionHandler(this.body, this.canvas, this.selectionHandler); // Interaction handler handles all the hammer bindings (that are bound by canvas), key
  this.view = new View(this.body, this.canvas); // camera handler, does animations and zooms
  this.renderer = new CanvasRenderer(this.body, this.canvas); // renderer, starts renderloop, has events that modules can hook into
  this.physics = new PhysicsEngine(this.body); // physics engine, does all the simulations
  this.layoutEngine = new LayoutEngine(this.body); // layout engine for inital layout and hierarchical layout
  this.clustering = new ClusterEngine(this.body); // clustering api
  this.manipulation = new ManipulationSystem(this.body, this.canvas, this.selectionHandler, this.interactionHandler); // data manipulation system

  this.nodesHandler = new NodesHandler(this.body, this.images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options
  this.edgesHandler = new EdgesHandler(this.body, this.images, this.groups); // Handle adding, deleting and updating of edges as well as global options

  this.body.modules["kamadaKawai"] = new KamadaKawai(this.body, 150, 0.05); // Layouting algorithm.
  this.body.modules["clustering"] = this.clustering;

  // create the DOM elements
  this.canvas._create();

  // apply options
  this.setOptions(options);

  // load data (the disable start variable will be the same as the enabled clustering)
  this.setData(data);
}

// Extend Network with an Emitter mixin
Emitter(Network.prototype);

/**
 * Set options
 *
 * @param {object} options
 */
Network.prototype.setOptions = function (options) {
  var _this2 = this;
  if (options === null) {
    options = undefined; // This ensures that options handling doesn't crash in the handling
  }

  if (options !== undefined) {
    var errorFound = Validator.validate(options, allOptions);
    if (errorFound === true) {
      console.error("%cErrors have been found in the supplied options object.", VALIDATOR_PRINT_STYLE);
    }

    // copy the global fields over
    var fields = ["locale", "locales", "clickToUse"];
    selectiveDeepExtend(fields, this.options, options);

    // normalize the locale or use English
    if (options.locale !== undefined) {
      options.locale = normalizeLanguageCode(options.locales || this.options.locales, options.locale);
    }

    // the hierarchical system can adapt the edges and the physics to it's own options because not all combinations work with the hierarichical system.
    options = this.layoutEngine.setOptions(options.layout, options);
    this.canvas.setOptions(options); // options for canvas are in globals

    // pass the options to the modules
    this.groups.setOptions(options.groups);
    this.nodesHandler.setOptions(options.nodes);
    this.edgesHandler.setOptions(options.edges);
    this.physics.setOptions(options.physics);
    this.manipulation.setOptions(options.manipulation, options, this.options); // manipulation uses the locales in the globals

    this.interactionHandler.setOptions(options.interaction);
    this.renderer.setOptions(options.interaction); // options for rendering are in interaction
    this.selectionHandler.setOptions(options.interaction); // options for selection are in interaction

    // reload the settings of the nodes to apply changes in groups that are not referenced by pointer.
    if (options.groups !== undefined) {
      this.body.emitter.emit("refreshNodes");
    }
    // these two do not have options at the moment, here for completeness
    //this.view.setOptions(options.view);
    //this.clustering.setOptions(options.clustering);

    if ("configure" in options) {
      if (!this.configurator) {
        this.configurator = new Configurator(this, this.body.container, configureOptions, this.canvas.pixelRatio, configuratorHideOption);
      }
      this.configurator.setOptions(options.configure);
    }

    // if the configuration system is enabled, copy all options and put them into the config system
    if (this.configurator && this.configurator.options.enabled === true) {
      var networkOptions = {
        nodes: {},
        edges: {},
        layout: {},
        interaction: {},
        manipulation: {},
        physics: {},
        global: {}
      };
      deepExtend(networkOptions.nodes, this.nodesHandler.options);
      deepExtend(networkOptions.edges, this.edgesHandler.options);
      deepExtend(networkOptions.layout, this.layoutEngine.options);
      // load the selectionHandler and render default options in to the interaction group
      deepExtend(networkOptions.interaction, this.selectionHandler.options);
      deepExtend(networkOptions.interaction, this.renderer.options);
      deepExtend(networkOptions.interaction, this.interactionHandler.options);
      deepExtend(networkOptions.manipulation, this.manipulation.options);
      deepExtend(networkOptions.physics, this.physics.options);

      // load globals into the global object
      deepExtend(networkOptions.global, this.canvas.options);
      deepExtend(networkOptions.global, this.options);
      this.configurator.setModuleOptions(networkOptions);
    }

    // handle network global options
    if (options.clickToUse !== undefined) {
      if (options.clickToUse === true) {
        if (this.activator === undefined) {
          this.activator = new Activator(this.canvas.frame);
          this.activator.on("change", function () {
            _this2.body.emitter.emit("activate");
          });
        }
      } else {
        if (this.activator !== undefined) {
          this.activator.destroy();
          delete this.activator;
        }
        this.body.emitter.emit("activate");
      }
    } else {
      this.body.emitter.emit("activate");
    }
    this.canvas.setSize();
    // start the physics simulation. Can be safely called multiple times.
    this.body.emitter.emit("startSimulation");
  }
};

/**
 * Update the visible nodes and edges list with the most recent node state.
 *
 * Visible nodes are stored in this.body.nodeIndices.
 * Visible edges are stored in this.body.edgeIndices.
 * A node or edges is visible if it is not hidden or clustered.
 *
 * @private
 */
Network.prototype._updateVisibleIndices = function () {
  var nodes = this.body.nodes;
  var edges = this.body.edges;
  this.body.nodeIndices = [];
  this.body.edgeIndices = [];
  for (var nodeId in nodes) {
    if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
      if (!this.clustering._isClusteredNode(nodeId) && nodes[nodeId].options.hidden === false) {
        this.body.nodeIndices.push(nodes[nodeId].id);
      }
    }
  }
  for (var edgeId in edges) {
    if (Object.prototype.hasOwnProperty.call(edges, edgeId)) {
      var edge = edges[edgeId];

      // It can happen that this is executed *after* a node edge has been removed,
      // but *before* the edge itself has been removed. Taking this into account.
      var fromNode = nodes[edge.fromId];
      var toNode = nodes[edge.toId];
      var edgeNodesPresent = fromNode !== undefined && toNode !== undefined;
      var isVisible = !this.clustering._isClusteredEdge(edgeId) && edge.options.hidden === false && edgeNodesPresent && fromNode.options.hidden === false &&
      // Also hidden if any of its connecting nodes are hidden
      toNode.options.hidden === false; // idem

      if (isVisible) {
        this.body.edgeIndices.push(edge.id);
      }
    }
  }
};

/**
 * Bind all events
 */
Network.prototype.bindEventListeners = function () {
  var _this3 = this;
  // This event will trigger a rebuilding of the cache everything.
  // Used when nodes or edges have been added or removed.
  this.body.emitter.on("_dataChanged", function () {
    _this3.edgesHandler._updateState();
    _this3.body.emitter.emit("_dataUpdated");
  });

  // this is called when options of EXISTING nodes or edges have changed.
  this.body.emitter.on("_dataUpdated", function () {
    // Order important in following block
    _this3.clustering._updateState();
    _this3._updateVisibleIndices();
    _this3._updateValueRange(_this3.body.nodes);
    _this3._updateValueRange(_this3.body.edges);
    // start simulation (can be called safely, even if already running)
    _this3.body.emitter.emit("startSimulation");
    _this3.body.emitter.emit("_requestRedraw");
  });
};

/**
 * Set nodes and edges, and optionally options as well.
 *
 * @param {object} data              Object containing parameters:
 *                                   {Array | DataSet | DataView} [nodes] Array with nodes
 *                                   {Array | DataSet | DataView} [edges] Array with edges
 *                                   {String} [dot] String containing data in DOT format
 *                                   {String} [gephi] String containing data in gephi JSON format
 *                                   {Options} [options] Object with options
 */
Network.prototype.setData = function (data) {
  // reset the physics engine.
  this.body.emitter.emit("resetPhysics");
  this.body.emitter.emit("_resetData");

  // unselect all to ensure no selections from old data are carried over.
  this.selectionHandler.unselectAll();
  if (data && data.dot && (data.nodes || data.edges)) {
    throw new SyntaxError('Data must contain either parameter "dot" or ' + ' parameter pair "nodes" and "edges", but not both.');
  }

  // set options
  this.setOptions(data && data.options);
  // set all data
  if (data && data.dot) {
    console.warn("The dot property has been deprecated. Please use the static convertDot method to convert DOT into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertDot(dotString);");
    // parse DOT file
    var dotData = DOTToGraph(data.dot);
    this.setData(dotData);
    return;
  } else if (data && data.gephi) {
    // parse DOT file
    console.warn("The gephi property has been deprecated. Please use the static convertGephi method to convert gephi into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertGephi(gephiJson);");
    var gephiData = parseGephi(data.gephi);
    this.setData(gephiData);
    return;
  } else {
    this.nodesHandler.setData(data && data.nodes, true);
    this.edgesHandler.setData(data && data.edges, true);
  }

  // emit change in data
  this.body.emitter.emit("_dataChanged");

  // emit data loaded
  this.body.emitter.emit("_dataLoaded");

  // find a stable position or start animating to a stable position
  this.body.emitter.emit("initPhysics");
};

/**
 * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function.
 * var network = new vis.Network(..);
 * network.destroy();
 * network = null;
 */
Network.prototype.destroy = function () {
  this.body.emitter.emit("destroy");
  // clear events
  this.body.emitter.off();
  this.off();

  // delete modules
  delete this.groups;
  delete this.canvas;
  delete this.selectionHandler;
  delete this.interactionHandler;
  delete this.view;
  delete this.renderer;
  delete this.physics;
  delete this.layoutEngine;
  delete this.clustering;
  delete this.manipulation;
  delete this.nodesHandler;
  delete this.edgesHandler;
  delete this.configurator;
  delete this.images;
  for (var nodeId in this.body.nodes) {
    if (!Object.prototype.hasOwnProperty.call(this.body.nodes, nodeId)) continue;
    delete this.body.nodes[nodeId];
  }
  for (var edgeId in this.body.edges) {
    if (!Object.prototype.hasOwnProperty.call(this.body.edges, edgeId)) continue;
    delete this.body.edges[edgeId];
  }

  // remove the container and everything inside it recursively
  recursiveDOMDelete(this.body.container);
};

/**
 * Update the values of all object in the given array according to the current
 * value range of the objects in the array.
 *
 * @param {object} obj    An object containing a set of Edges or Nodes
 *                        The objects must have a method getValue() and
 *                        setValueRange(min, max).
 * @private
 */
Network.prototype._updateValueRange = function (obj) {
  var id;

  // determine the range of the objects
  var valueMin = undefined;
  var valueMax = undefined;
  var valueTotal = 0;
  for (id in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, id)) {
      var value = obj[id].getValue();
      if (value !== undefined) {
        valueMin = valueMin === undefined ? value : Math.min(value, valueMin);
        valueMax = valueMax === undefined ? value : Math.max(value, valueMax);
        valueTotal += value;
      }
    }
  }

  // adjust the range of all objects
  if (valueMin !== undefined && valueMax !== undefined) {
    for (id in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, id)) {
        obj[id].setValueRange(valueMin, valueMax, valueTotal);
      }
    }
  }
};

/**
 * Returns true when the Network is active.
 *
 * @returns {boolean}
 */
Network.prototype.isActive = function () {
  return !this.activator || this.activator.active;
};
Network.prototype.setSize = function () {
  return this.canvas.setSize.apply(this.canvas, arguments);
};
Network.prototype.canvasToDOM = function () {
  return this.canvas.canvasToDOM.apply(this.canvas, arguments);
};
Network.prototype.DOMtoCanvas = function () {
  return this.canvas.DOMtoCanvas.apply(this.canvas, arguments);
};

/**
 * Nodes can be in clusters. Clusters can also be in clusters. This function returns and array of
 * nodeIds showing where the node is.
 *
 * If any nodeId in the chain, especially the first passed in as a parameter, is not present in
 * the current nodes list, an empty array is returned.
 *
 * Example:
 * cluster 'A' contains cluster 'B',
 * cluster 'B' contains cluster 'C',
 * cluster 'C' contains node 'fred'.
 * `jsnetwork.clustering.findNode('fred')` will return `['A','B','C','fred']`.
 *
 * @param {string|number} nodeId
 * @returns {Array}
 */
Network.prototype.findNode = function () {
  return this.clustering.findNode.apply(this.clustering, arguments);
};
Network.prototype.isCluster = function () {
  return this.clustering.isCluster.apply(this.clustering, arguments);
};
Network.prototype.openCluster = function () {
  return this.clustering.openCluster.apply(this.clustering, arguments);
};
Network.prototype.cluster = function () {
  return this.clustering.cluster.apply(this.clustering, arguments);
};
Network.prototype.getNodesInCluster = function () {
  return this.clustering.getNodesInCluster.apply(this.clustering, arguments);
};
Network.prototype.clusterByConnection = function () {
  return this.clustering.clusterByConnection.apply(this.clustering, arguments);
};
Network.prototype.clusterByHubsize = function () {
  return this.clustering.clusterByHubsize.apply(this.clustering, arguments);
};
Network.prototype.updateClusteredNode = function () {
  return this.clustering.updateClusteredNode.apply(this.clustering, arguments);
};
Network.prototype.getClusteredEdges = function () {
  return this.clustering.getClusteredEdges.apply(this.clustering, arguments);
};
Network.prototype.getBaseEdge = function () {
  return this.clustering.getBaseEdge.apply(this.clustering, arguments);
};
Network.prototype.getBaseEdges = function () {
  return this.clustering.getBaseEdges.apply(this.clustering, arguments);
};
Network.prototype.updateEdge = function () {
  return this.clustering.updateEdge.apply(this.clustering, arguments);
};

/**
 * This method will cluster all nodes with 1 edge with their respective connected node.
 * The options object is explained in full <a data-scroll="" data-options="{ &quot;easing&quot;: &quot;easeInCubic&quot; }" href="#optionsObject">below</a>.
 *
 * @param {object} [options]
 * @returns {undefined}
 */
Network.prototype.clusterOutliers = function () {
  return this.clustering.clusterOutliers.apply(this.clustering, arguments);
};
Network.prototype.getSeed = function () {
  return this.layoutEngine.getSeed.apply(this.layoutEngine, arguments);
};
Network.prototype.enableEditMode = function () {
  return this.manipulation.enableEditMode.apply(this.manipulation, arguments);
};
Network.prototype.disableEditMode = function () {
  return this.manipulation.disableEditMode.apply(this.manipulation, arguments);
};
Network.prototype.addNodeMode = function () {
  return this.manipulation.addNodeMode.apply(this.manipulation, arguments);
};
Network.prototype.editNode = function () {
  return this.manipulation.editNode.apply(this.manipulation, arguments);
};
Network.prototype.editNodeMode = function () {
  console.warn("Deprecated: Please use editNode instead of editNodeMode.");
  return this.manipulation.editNode.apply(this.manipulation, arguments);
};
Network.prototype.addEdgeMode = function () {
  return this.manipulation.addEdgeMode.apply(this.manipulation, arguments);
};
Network.prototype.editEdgeMode = function () {
  return this.manipulation.editEdgeMode.apply(this.manipulation, arguments);
};
Network.prototype.deleteSelected = function () {
  return this.manipulation.deleteSelected.apply(this.manipulation, arguments);
};
Network.prototype.getPositions = function () {
  return this.nodesHandler.getPositions.apply(this.nodesHandler, arguments);
};
Network.prototype.getPosition = function () {
  return this.nodesHandler.getPosition.apply(this.nodesHandler, arguments);
};
Network.prototype.storePositions = function () {
  return this.nodesHandler.storePositions.apply(this.nodesHandler, arguments);
};
Network.prototype.moveNode = function () {
  return this.nodesHandler.moveNode.apply(this.nodesHandler, arguments);
};
Network.prototype.getBoundingBox = function () {
  return this.nodesHandler.getBoundingBox.apply(this.nodesHandler, arguments);
};
Network.prototype.getConnectedNodes = function (objectId) {
  if (this.body.nodes[objectId] !== undefined) {
    return this.nodesHandler.getConnectedNodes.apply(this.nodesHandler, arguments);
  } else {
    return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler, arguments);
  }
};
Network.prototype.getConnectedEdges = function () {
  return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler, arguments);
};
Network.prototype.startSimulation = function () {
  return this.physics.startSimulation.apply(this.physics, arguments);
};
Network.prototype.stopSimulation = function () {
  return this.physics.stopSimulation.apply(this.physics, arguments);
};
Network.prototype.stabilize = function () {
  return this.physics.stabilize.apply(this.physics, arguments);
};
Network.prototype.getSelection = function () {
  return this.selectionHandler.getSelection.apply(this.selectionHandler, arguments);
};
Network.prototype.setSelection = function () {
  return this.selectionHandler.setSelection.apply(this.selectionHandler, arguments);
};
Network.prototype.getSelectedNodes = function () {
  return this.selectionHandler.getSelectedNodeIds.apply(this.selectionHandler, arguments);
};
Network.prototype.getSelectedEdges = function () {
  return this.selectionHandler.getSelectedEdgeIds.apply(this.selectionHandler, arguments);
};
Network.prototype.getNodeAt = function () {
  var node = this.selectionHandler.getNodeAt.apply(this.selectionHandler, arguments);
  if (node !== undefined && node.id !== undefined) {
    return node.id;
  }
  return node;
};
Network.prototype.getEdgeAt = function () {
  var edge = this.selectionHandler.getEdgeAt.apply(this.selectionHandler, arguments);
  if (edge !== undefined && edge.id !== undefined) {
    return edge.id;
  }
  return edge;
};
Network.prototype.selectNodes = function () {
  return this.selectionHandler.selectNodes.apply(this.selectionHandler, arguments);
};
Network.prototype.selectEdges = function () {
  return this.selectionHandler.selectEdges.apply(this.selectionHandler, arguments);
};
Network.prototype.unselectAll = function () {
  this.selectionHandler.unselectAll.apply(this.selectionHandler, arguments);
  this.selectionHandler.commitWithoutEmitting.apply(this.selectionHandler);
  this.redraw();
};
Network.prototype.redraw = function () {
  return this.renderer.redraw.apply(this.renderer, arguments);
};
Network.prototype.getScale = function () {
  return this.view.getScale.apply(this.view, arguments);
};
Network.prototype.getViewPosition = function () {
  return this.view.getViewPosition.apply(this.view, arguments);
};
Network.prototype.fit = function () {
  return this.view.fit.apply(this.view, arguments);
};
Network.prototype.moveTo = function () {
  return this.view.moveTo.apply(this.view, arguments);
};
Network.prototype.focus = function () {
  return this.view.focus.apply(this.view, arguments);
};
Network.prototype.releaseNode = function () {
  return this.view.releaseNode.apply(this.view, arguments);
};
Network.prototype.getOptionsFromConfigurator = function () {
  var options = {};
  if (this.configurator) {
    options = this.configurator.getOptions.apply(this.configurator);
  }
  return options;
};


/* Injected with object hook! */

const colors = Object.entries({
  vue: "#42b883",
  ts: "#41b1e0",
  js: "#d6cb2d",
  json: "#cf8f30",
  css: "#e6659a",
  html: "#e34c26",
  svelte: "#ff3e00",
  jsx: "#7d6fe8",
  tsx: "#7d6fe8"
}).map(([type, color]) => ({ type, color }));

/* Injected with object hook! */

const _hoisted_1$c = { key: 0 };
const _hoisted_2$b = {
  border: "~ main",
  flex: "~ col",
  absolute: "",
  "bottom-3": "",
  "right-3": "",
  "w-38": "",
  "select-none": "",
  rounded: "",
  "bg-opacity-75": "",
  p3: "",
  "text-sm": "",
  shadow: "",
  "backdrop-blur-8": "",
  "bg-main": ""
};
const _hoisted_3$8 = /* @__PURE__ */ createBaseVNode("div", {
  border: "t base",
  my3: "",
  "h-1px": ""
}, null, -1);
const _hoisted_4$8 = {
  border: "~ main",
  absolute: "",
  "bottom-3": "",
  "left-3": "",
  rounded: "",
  "bg-opacity-75": "",
  p3: "",
  "text-sm": "",
  shadow: "",
  "backdrop-blur-8": "",
  "bg-main": "",
  flex: "~ col gap-1"
};
const _hoisted_5$8 = /* @__PURE__ */ createBaseVNode("span", {
  "text-sm": "",
  op50: ""
}, "weight by", -1);
const _sfc_main$d = /* @__PURE__ */ defineComponent({
  __name: "Graph",
  props: {
    modules: {}
  },
  setup(__props) {
    const props = __props;
    const container = ref();
    const weightItems = [
      { value: "deps", label: "dependency count" },
      { value: "transform", label: "transform time" },
      { value: "resolveId", label: "resolveId time" }
    ];
    const shapes = [
      { type: "source", icon: "i-ic-outline-circle" },
      { type: "virtual", icon: "i-ic-outline-square rotate-45 scale-85" },
      { type: "node_modules", icon: "i-ic-outline-hexagon" }
    ];
    const router = useRouter();
    const data = computed(() => {
      const modules = props.modules || [];
      const nodes = modules.map((mod) => {
        const path = mod.id.replace(/\?.*$/, "").replace(/\#.*$/, "");
        return {
          id: mod.id,
          label: path.split("/").splice(-1)[0],
          group: path.match(/\.(\w+)$/)?.[1] || "unknown",
          size: getModuleWeight(mod, graphWeightMode.value),
          font: { color: isDark.value ? "white" : "black" },
          shape: mod.id.includes("/node_modules/") ? "hexagon" : mod.virtual ? "diamond" : "dot"
        };
      });
      const edges = modules.flatMap((mod) => mod.deps.map((dep) => ({
        from: mod.id,
        to: dep,
        arrows: {
          to: {
            enabled: true,
            scaleFactor: 0.8
          }
        }
      })));
      return {
        nodes,
        edges
      };
    });
    onMounted(() => {
      const options = {
        nodes: {
          shape: "dot",
          size: 16
        },
        physics: {
          maxVelocity: 146,
          solver: "forceAtlas2Based",
          timestep: 0.35,
          stabilization: {
            enabled: true,
            iterations: 200
          }
        },
        groups: colors.reduce((groups, color) => ({ ...groups, [color.type]: { color: color.color } }), {})
      };
      const network = new Network(container.value, data.value, options);
      const clicking = ref(false);
      network.on("click", () => {
        clicking.value = true;
      });
      network.on("hold", () => {
        clicking.value = false;
      });
      network.on("dragStart", () => {
        clicking.value = false;
      });
      network.on("release", (data2) => {
        const node = data2.nodes?.[0];
        if (clicking.value && node) {
          router.push(`/module?id=${encodeURIComponent(node)}`);
          clicking.value = false;
        }
      });
      watch(data, () => {
        network.setData(data.value);
      });
    });
    return (_ctx, _cache) => {
      const _component_RadioGroup = _sfc_main$e;
      return _ctx.modules ? (openBlock(), createElementBlock("div", _hoisted_1$c, [
        createBaseVNode("div", {
          ref_key: "container",
          ref: container,
          "h-100vh": "",
          "w-full": ""
        }, null, 512),
        createBaseVNode("div", _hoisted_2$b, [
          (openBlock(true), createElementBlock(Fragment, null, renderList(unref(colors), (color) => {
            return openBlock(), createElementBlock("div", {
              key: color.type,
              flex: "~ gap-2 items-center"
            }, [
              createBaseVNode("div", {
                "h-3": "",
                "w-3": "",
                "rounded-full": "",
                style: normalizeStyle$1({ backgroundColor: color.color })
              }, null, 4),
              createBaseVNode("div", null, toDisplayString(color.type), 1)
            ]);
          }), 128)),
          _hoisted_3$8,
          (openBlock(), createElementBlock(Fragment, null, renderList(shapes, (shape) => {
            return createBaseVNode("div", {
              key: shape.type,
              flex: "~ gap-2 items-center"
            }, [
              createBaseVNode("div", {
                class: normalizeClass(shape.icon),
                "flex-none": ""
              }, null, 2),
              createBaseVNode("div", null, toDisplayString(shape.type), 1)
            ]);
          }), 64))
        ]),
        createBaseVNode("div", _hoisted_4$8, [
          _hoisted_5$8,
          createVNode(_component_RadioGroup, {
            modelValue: unref(graphWeightMode),
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(graphWeightMode) ? graphWeightMode.value = $event : null),
            "flex-col": "",
            "text-sm": "",
            name: "weight",
            options: weightItems
          }, null, 8, ["modelValue"])
        ])
      ])) : createCommentVNode("", true);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$b = {
  "h-54px": "",
  flex: "~ none gap-5",
  border: "b main",
  "pl-4": "",
  "pr-6": "",
  "font-light": "",
  "children:my-auto": ""
};
const _hoisted_2$a = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-renew": "" }, null, -1);
const _hoisted_3$7 = [
  _hoisted_2$a
];
const _hoisted_4$7 = /* @__PURE__ */ createBaseVNode("div", {
  "h-full": "",
  "w-1": "",
  border: "r main"
}, null, -1);
const _hoisted_5$7 = /* @__PURE__ */ createBaseVNode("a", {
  "text-lg": "",
  "icon-btn": "",
  href: "https://github.com/antfu/vite-plugin-inspect",
  target: "_blank"
}, [
  /* @__PURE__ */ createBaseVNode("div", { "i-carbon-logo-github": "" })
], -1);
const _hoisted_6$7 = /* @__PURE__ */ createBaseVNode("div", {
  "i-carbon-sun": "",
  "dark:i-carbon-moon": ""
}, null, -1);
const _hoisted_7$6 = [
  _hoisted_6$7
];
const _sfc_main$c = /* @__PURE__ */ defineComponent({
  __name: "NavBar",
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("nav", _hoisted_1$b, [
        renderSlot(_ctx.$slots, "default"),
        renderSlot(_ctx.$slots, "actions", {}, () => [
          !unref(isStaticMode) ? (openBlock(), createElementBlock("button", {
            key: 0,
            class: "text-lg icon-btn",
            title: "Refetch",
            onClick: _cache[0] || (_cache[0] = ($event) => unref(refetch)())
          }, _hoisted_3$7)) : createCommentVNode("", true),
          _hoisted_4$7,
          _hoisted_5$7,
          createBaseVNode("button", {
            class: "text-lg icon-btn",
            title: "Toggle Dark Mode",
            onClick: _cache[1] || (_cache[1] = ($event) => unref(toggleDark)())
          }, _hoisted_7$6)
        ])
      ]);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$a = { class: "h-min flex flex-col select-none gap-1 whitespace-nowrap text-xs" };
const _hoisted_2$9 = { class: "flex" };
const _hoisted_3$6 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "node_modules", -1);
const _hoisted_4$6 = { class: "flex gap-2" };
const _hoisted_5$6 = { class: "flex" };
const _hoisted_6$6 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "virtual", -1);
const _hoisted_7$5 = { class: "flex" };
const _hoisted_8$4 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "ssr", -1);
const _hoisted_9$4 = { class: "flex" };
const _hoisted_10$3 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "exact search", -1);
const _sfc_main$b = /* @__PURE__ */ defineComponent({
  __name: "SearchBox",
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        withDirectives(createBaseVNode("input", {
          "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(searchText) ? searchText.value = $event : null),
          type: "text",
          class: "border border-main rounded bg-transparent px-3 py-1 !outline-none",
          placeholder: "Search..."
        }, null, 512), [
          [vModelText, unref(searchText)]
        ]),
        createBaseVNode("div", _hoisted_1$a, [
          createBaseVNode("label", _hoisted_2$9, [
            withDirectives(createBaseVNode("input", {
              "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => isRef(includeNodeModules) ? includeNodeModules.value = $event : null),
              type: "checkbox",
              class: "my-auto"
            }, null, 512), [
              [vModelCheckbox, unref(includeNodeModules)]
            ]),
            _hoisted_3$6
          ]),
          createBaseVNode("div", _hoisted_4$6, [
            createBaseVNode("label", _hoisted_5$6, [
              withDirectives(createBaseVNode("input", {
                "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isRef(includeVirtual) ? includeVirtual.value = $event : null),
                type: "checkbox",
                class: "my-auto"
              }, null, 512), [
                [vModelCheckbox, unref(includeVirtual)]
              ]),
              _hoisted_6$6
            ]),
            createBaseVNode("label", _hoisted_7$5, [
              withDirectives(createBaseVNode("input", {
                "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => isRef(inspectSSR) ? inspectSSR.value = $event : null),
                type: "checkbox",
                class: "my-auto"
              }, null, 512), [
                [vModelCheckbox, unref(inspectSSR)]
              ]),
              _hoisted_8$4
            ]),
            createBaseVNode("label", _hoisted_9$4, [
              withDirectives(createBaseVNode("input", {
                "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => isRef(exactSearch) ? exactSearch.value = $event : null),
                type: "checkbox",
                class: "my-auto"
              }, null, 512), [
                [vModelCheckbox, unref(exactSearch)]
              ]),
              _hoisted_10$3
            ])
          ])
        ])
      ], 64);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$9 = /* @__PURE__ */ createBaseVNode("div", {
  "i-carbon-ibm-watson-discovery": "",
  title: "Vite Inspect",
  "text-xl": ""
}, null, -1);
const _hoisted_2$8 = /* @__PURE__ */ createBaseVNode("div", { "flex-auto": "" }, null, -1);
const _hoisted_3$5 = ["disabled"];
const _hoisted_4$5 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-search": "" }, null, -1);
const _hoisted_5$5 = /* @__PURE__ */ createBaseVNode("div", {
  "i-carbon-arrow-down": "",
  "text-sm": "",
  op70: ""
}, null, -1);
const _hoisted_6$5 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-time": "" }, null, -1);
const _hoisted_7$4 = /* @__PURE__ */ createBaseVNode("div", {
  "i-carbon-arrow-down": "",
  "text-sm": "",
  op70: ""
}, null, -1);
const _hoisted_8$3 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-time": "" }, null, -1);
const _hoisted_9$3 = /* @__PURE__ */ createBaseVNode("div", {
  "i-carbon-arrow-up": "",
  "text-sm": "",
  op70: ""
}, null, -1);
const _hoisted_10$2 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-menu": "" }, null, -1);
const _hoisted_11$2 = /* @__PURE__ */ createBaseVNode("div", {
  "i-carbon-chevron-sort": "",
  "text-sm": "",
  op70: ""
}, null, -1);
const _hoisted_12$1 = {
  key: 0,
  "i-carbon-list-boxes": ""
};
const _hoisted_13$1 = {
  key: 1,
  "i-carbon-list": ""
};
const _hoisted_14$1 = {
  key: 2,
  "i-carbon-network-4": ""
};
const _hoisted_15$1 = /* @__PURE__ */ createBaseVNode("div", {
  "h-full": "",
  "w-1": "",
  border: "r main"
}, null, -1);
const _hoisted_16$1 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-meter": "" }, null, -1);
const _sfc_main$a = /* @__PURE__ */ defineComponent({
  __name: "index",
  setup(__props) {
    const route = useRoute();
    const isRoot = computed(() => route.path === "/");
    onMounted(() => {
      refetch();
    });
    return (_ctx, _cache) => {
      const _component_SearchBox = _sfc_main$b;
      const _component_RouterLink = resolveComponent("RouterLink");
      const _component_NavBar = _sfc_main$c;
      const _component_Graph = _sfc_main$d;
      const _component_ModuleList = _sfc_main$f;
      const _component_Container = __unplugin_components_7;
      const _component_RouterView = resolveComponent("RouterView");
      return openBlock(), createElementBlock(Fragment, null, [
        createVNode(_component_NavBar, null, {
          default: withCtx(() => [
            _hoisted_1$9,
            createVNode(_component_SearchBox),
            _hoisted_2$8,
            unref(listMode) === "detailed" ? (openBlock(), createElementBlock("button", {
              key: 0,
              "text-lg": "",
              "icon-btn": "",
              title: "Sort",
              flex: "~ items-center",
              disabled: !!unref(searchText),
              class: normalizeClass(unref(searchText) ? "op50 pointer-events-none" : ""),
              onClick: _cache[0] || (_cache[0] = ($event) => unref(toggleSort)())
            }, [
              unref(searchText) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
                _hoisted_4$5,
                _hoisted_5$5
              ], 64)) : unref(sortMode) === "time-asc" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
                _hoisted_6$5,
                _hoisted_7$4
              ], 64)) : unref(sortMode) === "time-desc" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
                _hoisted_8$3,
                _hoisted_9$3
              ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
                _hoisted_10$2,
                _hoisted_11$2
              ], 64))
            ], 10, _hoisted_3$5)) : createCommentVNode("", true),
            createBaseVNode("button", {
              "text-lg": "",
              "icon-btn": "",
              title: "View Mode",
              onClick: _cache[1] || (_cache[1] = ($event) => unref(toggleMode)())
            }, [
              unref(listMode) === "detailed" ? (openBlock(), createElementBlock("div", _hoisted_12$1)) : unref(listMode) === "list" ? (openBlock(), createElementBlock("div", _hoisted_13$1)) : (openBlock(), createElementBlock("div", _hoisted_14$1))
            ]),
            _hoisted_15$1,
            createVNode(_component_RouterLink, {
              "text-lg": "",
              "icon-btn": "",
              to: "/metric",
              title: "Metrics"
            }, {
              default: withCtx(() => [
                _hoisted_16$1
              ]),
              _: 1
            })
          ]),
          _: 1
        }),
        createVNode(_component_Container, { "of-auto": "" }, {
          default: withCtx(() => [
            (openBlock(), createBlock(KeepAlive, null, [
              unref(listMode) === "graph" ? (openBlock(), createBlock(_component_Graph, {
                key: 0,
                modules: unref(searchResults)
              }, null, 8, ["modules"])) : (openBlock(), createBlock(_component_ModuleList, {
                key: 1,
                modules: unref(sortedSearchResults)
              }, null, 8, ["modules"]))
            ], 1024))
          ]),
          _: 1
        }),
        createBaseVNode("div", {
          pos: "fixed bottom-0 left-0 right-0 top-0",
          flex: "",
          "overflow-hidden": "",
          "bg-black:50": "",
          "transition-all": "",
          class: normalizeClass(unref(isRoot) ? "pointer-events-none opacity-0" : "opacity-100")
        }, [
          createVNode(_component_RouterLink, {
            "h-full": "",
            "min-w-70px": "",
            "flex-auto": "",
            to: "/"
          }),
          createBaseVNode("div", {
            class: normalizeClass(["h-full w-[calc(100vw-100px)] transform overflow-hidden shadow-lg transition-transform duration-300 bg-main", unref(isRoot) ? "translate-x-1/2" : "translate-x-0"]),
            border: "l main"
          }, [
            (openBlock(), createBlock(Suspense, null, {
              fallback: withCtx(() => [
                createTextVNode(" Loading... ")
              ]),
              default: withCtx(() => [
                createVNode(_component_RouterView, null, {
                  default: withCtx(({ Component }) => [
                    (openBlock(), createBlock(KeepAlive, null, [
                      (openBlock(), createBlock(resolveDynamicComponent(Component)))
                    ], 1024))
                  ]),
                  _: 1
                })
              ]),
              _: 1
            }))
          ], 2)
        ], 2)
      ], 64);
    };
  }
});

/* Injected with object hook! */

const M = {
  name: "splitpanes",
  emits: ["ready", "resize", "resized", "pane-click", "pane-maximize", "pane-add", "pane-remove", "splitter-click"],
  props: {
    horizontal: { type: Boolean },
    pushOtherPanes: { type: Boolean, default: !0 },
    dblClickSplitter: { type: Boolean, default: !0 },
    rtl: { type: Boolean, default: !1 },
    firstSplitter: { type: Boolean }
  },
  provide() {
    return {
      requestUpdate: this.requestUpdate,
      onPaneAdd: this.onPaneAdd,
      onPaneRemove: this.onPaneRemove,
      onPaneClick: this.onPaneClick
    };
  },
  data: () => ({
    container: null,
    ready: !1,
    panes: [],
    touch: {
      mouseDown: !1,
      dragging: !1,
      activeSplitter: null
    },
    splitterTaps: {
      splitter: null,
      timeoutId: null
    }
  }),
  computed: {
    panesCount() {
      return this.panes.length;
    },
    indexedPanes() {
      return this.panes.reduce((e, i) => (e[i.id] = i) && e, {});
    }
  },
  methods: {
    updatePaneComponents() {
      this.panes.forEach((e) => {
        e.update && e.update({
          [this.horizontal ? "height" : "width"]: `${this.indexedPanes[e.id].size}%`
        });
      });
    },
    bindEvents() {
      document.addEventListener("mousemove", this.onMouseMove, { passive: !1 }), document.addEventListener("mouseup", this.onMouseUp), "ontouchstart" in window && (document.addEventListener("touchmove", this.onMouseMove, { passive: !1 }), document.addEventListener("touchend", this.onMouseUp));
    },
    unbindEvents() {
      document.removeEventListener("mousemove", this.onMouseMove, { passive: !1 }), document.removeEventListener("mouseup", this.onMouseUp), "ontouchstart" in window && (document.removeEventListener("touchmove", this.onMouseMove, { passive: !1 }), document.removeEventListener("touchend", this.onMouseUp));
    },
    onMouseDown(e, i) {
      this.bindEvents(), this.touch.mouseDown = !0, this.touch.activeSplitter = i;
    },
    onMouseMove(e) {
      this.touch.mouseDown && (e.preventDefault(), this.touch.dragging = !0, this.calculatePanesSize(this.getCurrentMouseDrag(e)), this.$emit("resize", this.panes.map((i) => ({ min: i.min, max: i.max, size: i.size }))));
    },
    onMouseUp() {
      this.touch.dragging && this.$emit("resized", this.panes.map((e) => ({ min: e.min, max: e.max, size: e.size }))), this.touch.mouseDown = !1, setTimeout(() => {
        this.touch.dragging = !1, this.unbindEvents();
      }, 100);
    },
    onSplitterClick(e, i) {
      "ontouchstart" in window && (e.preventDefault(), this.dblClickSplitter && (this.splitterTaps.splitter === i ? (clearTimeout(this.splitterTaps.timeoutId), this.splitterTaps.timeoutId = null, this.onSplitterDblClick(e, i), this.splitterTaps.splitter = null) : (this.splitterTaps.splitter = i, this.splitterTaps.timeoutId = setTimeout(() => {
        this.splitterTaps.splitter = null;
      }, 500)))), this.touch.dragging || this.$emit("splitter-click", this.panes[i]);
    },
    onSplitterDblClick(e, i) {
      let s = 0;
      this.panes = this.panes.map((n, t) => (n.size = t === i ? n.max : n.min, t !== i && (s += n.min), n)), this.panes[i].size -= s, this.$emit("pane-maximize", this.panes[i]), this.$emit("resized", this.panes.map((n) => ({ min: n.min, max: n.max, size: n.size })));
    },
    onPaneClick(e, i) {
      this.$emit("pane-click", this.indexedPanes[i]);
    },
    getCurrentMouseDrag(e) {
      const i = this.container.getBoundingClientRect(), { clientX: s, clientY: n } = "ontouchstart" in window && e.touches ? e.touches[0] : e;
      return {
        x: s - i.left,
        y: n - i.top
      };
    },
    getCurrentDragPercentage(e) {
      e = e[this.horizontal ? "y" : "x"];
      const i = this.container[this.horizontal ? "clientHeight" : "clientWidth"];
      return this.rtl && !this.horizontal && (e = i - e), e * 100 / i;
    },
    calculatePanesSize(e) {
      const i = this.touch.activeSplitter;
      let s = {
        prevPanesSize: this.sumPrevPanesSize(i),
        nextPanesSize: this.sumNextPanesSize(i),
        prevReachedMinPanes: 0,
        nextReachedMinPanes: 0
      };
      const n = 0 + (this.pushOtherPanes ? 0 : s.prevPanesSize), t = 100 - (this.pushOtherPanes ? 0 : s.nextPanesSize), a = Math.max(Math.min(this.getCurrentDragPercentage(e), t), n);
      let r = [i, i + 1], o = this.panes[r[0]] || null, h = this.panes[r[1]] || null;
      const l = o.max < 100 && a >= o.max + s.prevPanesSize, u = h.max < 100 && a <= 100 - (h.max + this.sumNextPanesSize(i + 1));
      if (l || u) {
        l ? (o.size = o.max, h.size = Math.max(100 - o.max - s.prevPanesSize - s.nextPanesSize, 0)) : (o.size = Math.max(100 - h.max - s.prevPanesSize - this.sumNextPanesSize(i + 1), 0), h.size = h.max);
        return;
      }
      if (this.pushOtherPanes) {
        const d = this.doPushOtherPanes(s, a);
        if (!d)
          return;
        (({ sums: s, panesToResize: r } = d)), o = this.panes[r[0]] || null, h = this.panes[r[1]] || null;
      }
      o !== null && (o.size = Math.min(Math.max(a - s.prevPanesSize - s.prevReachedMinPanes, o.min), o.max)), h !== null && (h.size = Math.min(Math.max(100 - a - s.nextPanesSize - s.nextReachedMinPanes, h.min), h.max));
    },
    doPushOtherPanes(e, i) {
      const s = this.touch.activeSplitter, n = [s, s + 1];
      return i < e.prevPanesSize + this.panes[n[0]].min && (n[0] = this.findPrevExpandedPane(s).index, e.prevReachedMinPanes = 0, n[0] < s && this.panes.forEach((t, a) => {
        a > n[0] && a <= s && (t.size = t.min, e.prevReachedMinPanes += t.min);
      }), e.prevPanesSize = this.sumPrevPanesSize(n[0]), n[0] === void 0) ? (e.prevReachedMinPanes = 0, this.panes[0].size = this.panes[0].min, this.panes.forEach((t, a) => {
        a > 0 && a <= s && (t.size = t.min, e.prevReachedMinPanes += t.min);
      }), this.panes[n[1]].size = 100 - e.prevReachedMinPanes - this.panes[0].min - e.prevPanesSize - e.nextPanesSize, null) : i > 100 - e.nextPanesSize - this.panes[n[1]].min && (n[1] = this.findNextExpandedPane(s).index, e.nextReachedMinPanes = 0, n[1] > s + 1 && this.panes.forEach((t, a) => {
        a > s && a < n[1] && (t.size = t.min, e.nextReachedMinPanes += t.min);
      }), e.nextPanesSize = this.sumNextPanesSize(n[1] - 1), n[1] === void 0) ? (e.nextReachedMinPanes = 0, this.panes[this.panesCount - 1].size = this.panes[this.panesCount - 1].min, this.panes.forEach((t, a) => {
        a < this.panesCount - 1 && a >= s + 1 && (t.size = t.min, e.nextReachedMinPanes += t.min);
      }), this.panes[n[0]].size = 100 - e.prevPanesSize - e.nextReachedMinPanes - this.panes[this.panesCount - 1].min - e.nextPanesSize, null) : { sums: e, panesToResize: n };
    },
    sumPrevPanesSize(e) {
      return this.panes.reduce((i, s, n) => i + (n < e ? s.size : 0), 0);
    },
    sumNextPanesSize(e) {
      return this.panes.reduce((i, s, n) => i + (n > e + 1 ? s.size : 0), 0);
    },
    findPrevExpandedPane(e) {
      return [...this.panes].reverse().find((s) => s.index < e && s.size > s.min) || {};
    },
    findNextExpandedPane(e) {
      return this.panes.find((s) => s.index > e + 1 && s.size > s.min) || {};
    },
    checkSplitpanesNodes() {
      Array.from(this.container.children).forEach((i) => {
        const s = i.classList.contains("splitpanes__pane"), n = i.classList.contains("splitpanes__splitter");
        !s && !n && (i.parentNode.removeChild(i), console.warn("Splitpanes: Only <pane> elements are allowed at the root of <splitpanes>. One of your DOM nodes was removed."));
      });
    },
    addSplitter(e, i, s = !1) {
      const n = e - 1, t = document.createElement("div");
      t.classList.add("splitpanes__splitter"), s || (t.onmousedown = (a) => this.onMouseDown(a, n), typeof window < "u" && "ontouchstart" in window && (t.ontouchstart = (a) => this.onMouseDown(a, n)), t.onclick = (a) => this.onSplitterClick(a, n + 1)), this.dblClickSplitter && (t.ondblclick = (a) => this.onSplitterDblClick(a, n + 1)), i.parentNode.insertBefore(t, i);
    },
    removeSplitter(e) {
      e.onmousedown = void 0, e.onclick = void 0, e.ondblclick = void 0, e.parentNode.removeChild(e);
    },
    redoSplitters() {
      const e = Array.from(this.container.children);
      e.forEach((s) => {
        s.className.includes("splitpanes__splitter") && this.removeSplitter(s);
      });
      let i = 0;
      e.forEach((s) => {
        s.className.includes("splitpanes__pane") && (!i && this.firstSplitter ? this.addSplitter(i, s, !0) : i && this.addSplitter(i, s), i++);
      });
    },
    requestUpdate({ target: e, ...i }) {
      const s = this.indexedPanes[e._.uid];
      Object.entries(i).forEach(([n, t]) => s[n] = t);
    },
    onPaneAdd(e) {
      let i = -1;
      Array.from(e.$el.parentNode.children).some((t) => (t.className.includes("splitpanes__pane") && i++, t === e.$el));
      const s = parseFloat(e.minSize), n = parseFloat(e.maxSize);
      this.panes.splice(i, 0, {
        id: e._.uid,
        index: i,
        min: isNaN(s) ? 0 : s,
        max: isNaN(n) ? 100 : n,
        size: e.size === null ? null : parseFloat(e.size),
        givenSize: e.size,
        update: e.update
      }), this.panes.forEach((t, a) => t.index = a), this.ready && this.$nextTick(() => {
        this.redoSplitters(), this.resetPaneSizes({ addedPane: this.panes[i] }), this.$emit("pane-add", { index: i, panes: this.panes.map((t) => ({ min: t.min, max: t.max, size: t.size })) });
      });
    },
    onPaneRemove(e) {
      const i = this.panes.findIndex((n) => n.id === e._.uid), s = this.panes.splice(i, 1)[0];
      this.panes.forEach((n, t) => n.index = t), this.$nextTick(() => {
        this.redoSplitters(), this.resetPaneSizes({ removedPane: { ...s, index: i } }), this.$emit("pane-remove", { removed: s, panes: this.panes.map((n) => ({ min: n.min, max: n.max, size: n.size })) });
      });
    },
    resetPaneSizes(e = {}) {
      !e.addedPane && !e.removedPane ? this.initialPanesSizing() : this.panes.some((i) => i.givenSize !== null || i.min || i.max < 100) ? this.equalizeAfterAddOrRemove(e) : this.equalize(), this.ready && this.$emit("resized", this.panes.map((i) => ({ min: i.min, max: i.max, size: i.size })));
    },
    equalize() {
      const e = 100 / this.panesCount;
      let i = 0;
      const s = [], n = [];
      this.panes.forEach((t) => {
        t.size = Math.max(Math.min(e, t.max), t.min), i -= t.size, t.size >= t.max && s.push(t.id), t.size <= t.min && n.push(t.id);
      }), i > 0.1 && this.readjustSizes(i, s, n);
    },
    initialPanesSizing() {
      let e = 100;
      const i = [], s = [];
      let n = 0;
      this.panes.forEach((a) => {
        e -= a.size, a.size !== null && n++, a.size >= a.max && i.push(a.id), a.size <= a.min && s.push(a.id);
      });
      let t = 100;
      e > 0.1 && (this.panes.forEach((a) => {
        a.size === null && (a.size = Math.max(Math.min(e / (this.panesCount - n), a.max), a.min)), t -= a.size;
      }), t > 0.1 && this.readjustSizes(e, i, s));
    },
    equalizeAfterAddOrRemove({ addedPane: e, removedPane: i } = {}) {
      let s = 100 / this.panesCount, n = 0;
      const t = [], a = [];
      e && e.givenSize !== null && (s = (100 - e.givenSize) / (this.panesCount - 1)), this.panes.forEach((r) => {
        n -= r.size, r.size >= r.max && t.push(r.id), r.size <= r.min && a.push(r.id);
      }), !(Math.abs(n) < 0.1) && (this.panes.forEach((r) => {
        e && e.givenSize !== null && e.id === r.id || (r.size = Math.max(Math.min(s, r.max), r.min)), n -= r.size, r.size >= r.max && t.push(r.id), r.size <= r.min && a.push(r.id);
      }), n > 0.1 && this.readjustSizes(n, t, a));
    },
    readjustSizes(e, i, s) {
      let n;
      e > 0 ? n = e / (this.panesCount - i.length) : n = e / (this.panesCount - s.length), this.panes.forEach((t, a) => {
        if (e > 0 && !i.includes(t.id)) {
          const r = Math.max(Math.min(t.size + n, t.max), t.min), o = r - t.size;
          e -= o, t.size = r;
        } else if (!s.includes(t.id)) {
          const r = Math.max(Math.min(t.size + n, t.max), t.min), o = r - t.size;
          e -= o, t.size = r;
        }
        t.update({
          [this.horizontal ? "height" : "width"]: `${this.indexedPanes[t.id].size}%`
        });
      }), Math.abs(e) > 0.1 && this.$nextTick(() => {
        this.ready && console.warn("Splitpanes: Could not resize panes correctly due to their constraints.");
      });
    }
  },
  watch: {
    panes: {
      deep: !0,
      immediate: !1,
      handler() {
        this.updatePaneComponents();
      }
    },
    horizontal() {
      this.updatePaneComponents();
    },
    firstSplitter() {
      this.redoSplitters();
    },
    dblClickSplitter(e) {
      [...this.container.querySelectorAll(".splitpanes__splitter")].forEach((s, n) => {
        s.ondblclick = e ? (t) => this.onSplitterDblClick(t, n) : void 0;
      });
    }
  },
  beforeUnmount() {
    this.ready = !1;
  },
  mounted() {
    this.container = this.$refs.container, this.checkSplitpanesNodes(), this.redoSplitters(), this.resetPaneSizes(), this.$emit("ready"), this.ready = !0;
  },
  render() {
    return h(
      "div",
      {
        ref: "container",
        class: [
          "splitpanes",
          `splitpanes--${this.horizontal ? "horizontal" : "vertical"}`,
          {
            "splitpanes--dragging": this.touch.dragging
          }
        ]
      },
      this.$slots.default()
    );
  }
}, S$1 = (e, i) => {
  const s = e.__vccOpts || e;
  for (const [n, t] of i)
    s[n] = t;
  return s;
}, x$1 = {
  name: "pane",
  inject: ["requestUpdate", "onPaneAdd", "onPaneRemove", "onPaneClick"],
  props: {
    size: { type: [Number, String], default: null },
    minSize: { type: [Number, String], default: 0 },
    maxSize: { type: [Number, String], default: 100 }
  },
  data: () => ({
    style: {}
  }),
  mounted() {
    this.onPaneAdd(this);
  },
  beforeUnmount() {
    this.onPaneRemove(this);
  },
  methods: {
    update(e) {
      this.style = e;
    }
  },
  computed: {
    sizeNumber() {
      return this.size || this.size === 0 ? parseFloat(this.size) : null;
    },
    minSizeNumber() {
      return parseFloat(this.minSize);
    },
    maxSizeNumber() {
      return parseFloat(this.maxSize);
    }
  },
  watch: {
    sizeNumber(e) {
      this.requestUpdate({ target: this, size: e });
    },
    minSizeNumber(e) {
      this.requestUpdate({ target: this, min: e });
    },
    maxSizeNumber(e) {
      this.requestUpdate({ target: this, max: e });
    }
  }
};
function P(e, i, s, n, t, a) {
  return openBlock(), createElementBlock("div", {
    class: "splitpanes__pane",
    onClick: i[0] || (i[0] = (r) => a.onPaneClick(r, e._.uid)),
    style: normalizeStyle$1(e.style)
  }, [
    renderSlot(e.$slots, "default")
  ], 4);
}
const g = /* @__PURE__ */ S$1(x$1, [["render", P]]);

/* Injected with object hook! */

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function getDefaultExportFromCjs (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

/* Injected with object hook! */

var codemirror$1 = {exports: {}};/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	// This is CodeMirror (https://codemirror.net/5), a code editor
	// implemented in JavaScript on top of the browser's DOM.
	//
	// You can find some technical background for some of the code below
	// at http://marijnhaverbeke.nl/blog/#cm-internals .

	(function (global, factory) {
	  module.exports = factory() ;
	}(commonjsGlobal, (function () {
	  // Kludges for bugs and behavior differences that can't be feature
	  // detected are enabled based on userAgent etc sniffing.
	  var userAgent = navigator.userAgent;
	  var platform = navigator.platform;

	  var gecko = /gecko\/\d/i.test(userAgent);
	  var ie_upto10 = /MSIE \d/.test(userAgent);
	  var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
	  var edge = /Edge\/(\d+)/.exec(userAgent);
	  var ie = ie_upto10 || ie_11up || edge;
	  var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]);
	  var webkit = !edge && /WebKit\//.test(userAgent);
	  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
	  var chrome = !edge && /Chrome\/(\d+)/.exec(userAgent);
	  var chrome_version = chrome && +chrome[1];
	  var presto = /Opera\//.test(userAgent);
	  var safari = /Apple Computer/.test(navigator.vendor);
	  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
	  var phantom = /PhantomJS/.test(userAgent);

	  var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2);
	  var android = /Android/.test(userAgent);
	  // This is woefully incomplete. Suggestions for alternative methods welcome.
	  var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
	  var mac = ios || /Mac/.test(platform);
	  var chromeOS = /\bCrOS\b/.test(userAgent);
	  var windows = /win/i.test(platform);

	  var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
	  if (presto_version) { presto_version = Number(presto_version[1]); }
	  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
	  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
	  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
	  var captureRightClick = gecko || (ie && ie_version >= 9);

	  function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }

	  var rmClass = function(node, cls) {
	    var current = node.className;
	    var match = classTest(cls).exec(current);
	    if (match) {
	      var after = current.slice(match.index + match[0].length);
	      node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
	    }
	  };

	  function removeChildren(e) {
	    for (var count = e.childNodes.length; count > 0; --count)
	      { e.removeChild(e.firstChild); }
	    return e
	  }

	  function removeChildrenAndAdd(parent, e) {
	    return removeChildren(parent).appendChild(e)
	  }

	  function elt(tag, content, className, style) {
	    var e = document.createElement(tag);
	    if (className) { e.className = className; }
	    if (style) { e.style.cssText = style; }
	    if (typeof content == "string") { e.appendChild(document.createTextNode(content)); }
	    else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } }
	    return e
	  }
	  // wrapper for elt, which removes the elt from the accessibility tree
	  function eltP(tag, content, className, style) {
	    var e = elt(tag, content, className, style);
	    e.setAttribute("role", "presentation");
	    return e
	  }

	  var range;
	  if (document.createRange) { range = function(node, start, end, endNode) {
	    var r = document.createRange();
	    r.setEnd(endNode || node, end);
	    r.setStart(node, start);
	    return r
	  }; }
	  else { range = function(node, start, end) {
	    var r = document.body.createTextRange();
	    try { r.moveToElementText(node.parentNode); }
	    catch(e) { return r }
	    r.collapse(true);
	    r.moveEnd("character", end);
	    r.moveStart("character", start);
	    return r
	  }; }

	  function contains(parent, child) {
	    if (child.nodeType == 3) // Android browser always returns false when child is a textnode
	      { child = child.parentNode; }
	    if (parent.contains)
	      { return parent.contains(child) }
	    do {
	      if (child.nodeType == 11) { child = child.host; }
	      if (child == parent) { return true }
	    } while (child = child.parentNode)
	  }

	  function activeElt(doc) {
	    // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
	    // IE < 10 will throw when accessed while the page is loading or in an iframe.
	    // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
	    var activeElement;
	    try {
	      activeElement = doc.activeElement;
	    } catch(e) {
	      activeElement = doc.body || null;
	    }
	    while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
	      { activeElement = activeElement.shadowRoot.activeElement; }
	    return activeElement
	  }

	  function addClass(node, cls) {
	    var current = node.className;
	    if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; }
	  }
	  function joinClasses(a, b) {
	    var as = a.split(" ");
	    for (var i = 0; i < as.length; i++)
	      { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } }
	    return b
	  }

	  var selectInput = function(node) { node.select(); };
	  if (ios) // Mobile Safari apparently has a bug where select() is broken.
	    { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; }
	  else if (ie) // Suppress mysterious IE10 errors
	    { selectInput = function(node) { try { node.select(); } catch(_e) {} }; }

	  function doc(cm) { return cm.display.wrapper.ownerDocument }

	  function win(cm) { return doc(cm).defaultView }

	  function bind(f) {
	    var args = Array.prototype.slice.call(arguments, 1);
	    return function(){return f.apply(null, args)}
	  }

	  function copyObj(obj, target, overwrite) {
	    if (!target) { target = {}; }
	    for (var prop in obj)
	      { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
	        { target[prop] = obj[prop]; } }
	    return target
	  }

	  // Counts the column offset in a string, taking tabs into account.
	  // Used mostly to find indentation.
	  function countColumn(string, end, tabSize, startIndex, startValue) {
	    if (end == null) {
	      end = string.search(/[^\s\u00a0]/);
	      if (end == -1) { end = string.length; }
	    }
	    for (var i = startIndex || 0, n = startValue || 0;;) {
	      var nextTab = string.indexOf("\t", i);
	      if (nextTab < 0 || nextTab >= end)
	        { return n + (end - i) }
	      n += nextTab - i;
	      n += tabSize - (n % tabSize);
	      i = nextTab + 1;
	    }
	  }

	  var Delayed = function() {
	    this.id = null;
	    this.f = null;
	    this.time = 0;
	    this.handler = bind(this.onTimeout, this);
	  };
	  Delayed.prototype.onTimeout = function (self) {
	    self.id = 0;
	    if (self.time <= +new Date) {
	      self.f();
	    } else {
	      setTimeout(self.handler, self.time - +new Date);
	    }
	  };
	  Delayed.prototype.set = function (ms, f) {
	    this.f = f;
	    var time = +new Date + ms;
	    if (!this.id || time < this.time) {
	      clearTimeout(this.id);
	      this.id = setTimeout(this.handler, ms);
	      this.time = time;
	    }
	  };

	  function indexOf(array, elt) {
	    for (var i = 0; i < array.length; ++i)
	      { if (array[i] == elt) { return i } }
	    return -1
	  }

	  // Number of pixels added to scroller and sizer to hide scrollbar
	  var scrollerGap = 50;

	  // Returned or thrown by various protocols to signal 'I'm not
	  // handling this'.
	  var Pass = {toString: function(){return "CodeMirror.Pass"}};

	  // Reused option objects for setSelection & friends
	  var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};

	  // The inverse of countColumn -- find the offset that corresponds to
	  // a particular column.
	  function findColumn(string, goal, tabSize) {
	    for (var pos = 0, col = 0;;) {
	      var nextTab = string.indexOf("\t", pos);
	      if (nextTab == -1) { nextTab = string.length; }
	      var skipped = nextTab - pos;
	      if (nextTab == string.length || col + skipped >= goal)
	        { return pos + Math.min(skipped, goal - col) }
	      col += nextTab - pos;
	      col += tabSize - (col % tabSize);
	      pos = nextTab + 1;
	      if (col >= goal) { return pos }
	    }
	  }

	  var spaceStrs = [""];
	  function spaceStr(n) {
	    while (spaceStrs.length <= n)
	      { spaceStrs.push(lst(spaceStrs) + " "); }
	    return spaceStrs[n]
	  }

	  function lst(arr) { return arr[arr.length-1] }

	  function map(array, f) {
	    var out = [];
	    for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); }
	    return out
	  }

	  function insertSorted(array, value, score) {
	    var pos = 0, priority = score(value);
	    while (pos < array.length && score(array[pos]) <= priority) { pos++; }
	    array.splice(pos, 0, value);
	  }

	  function nothing() {}

	  function createObj(base, props) {
	    var inst;
	    if (Object.create) {
	      inst = Object.create(base);
	    } else {
	      nothing.prototype = base;
	      inst = new nothing();
	    }
	    if (props) { copyObj(props, inst); }
	    return inst
	  }

	  var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
	  function isWordCharBasic(ch) {
	    return /\w/.test(ch) || ch > "\x80" &&
	      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
	  }
	  function isWordChar(ch, helper) {
	    if (!helper) { return isWordCharBasic(ch) }
	    if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
	    return helper.test(ch)
	  }

	  function isEmpty(obj) {
	    for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
	    return true
	  }

	  // Extending unicode characters. A series of a non-extending char +
	  // any number of extending chars is treated as a single unit as far
	  // as editing and measuring is concerned. This is not fully correct,
	  // since some scripts/fonts/browsers also treat other configurations
	  // of code points as a group.
	  var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
	  function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }

	  // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range.
	  function skipExtendingChars(str, pos, dir) {
	    while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; }
	    return pos
	  }

	  // Returns the value from the range [`from`; `to`] that satisfies
	  // `pred` and is closest to `from`. Assumes that at least `to`
	  // satisfies `pred`. Supports `from` being greater than `to`.
	  function findFirst(pred, from, to) {
	    // At any point we are certain `to` satisfies `pred`, don't know
	    // whether `from` does.
	    var dir = from > to ? -1 : 1;
	    for (;;) {
	      if (from == to) { return from }
	      var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF);
	      if (mid == from) { return pred(mid) ? from : to }
	      if (pred(mid)) { to = mid; }
	      else { from = mid + dir; }
	    }
	  }

	  // BIDI HELPERS

	  function iterateBidiSections(order, from, to, f) {
	    if (!order) { return f(from, to, "ltr", 0) }
	    var found = false;
	    for (var i = 0; i < order.length; ++i) {
	      var part = order[i];
	      if (part.from < to && part.to > from || from == to && part.to == from) {
	        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i);
	        found = true;
	      }
	    }
	    if (!found) { f(from, to, "ltr"); }
	  }

	  var bidiOther = null;
	  function getBidiPartAt(order, ch, sticky) {
	    var found;
	    bidiOther = null;
	    for (var i = 0; i < order.length; ++i) {
	      var cur = order[i];
	      if (cur.from < ch && cur.to > ch) { return i }
	      if (cur.to == ch) {
	        if (cur.from != cur.to && sticky == "before") { found = i; }
	        else { bidiOther = i; }
	      }
	      if (cur.from == ch) {
	        if (cur.from != cur.to && sticky != "before") { found = i; }
	        else { bidiOther = i; }
	      }
	    }
	    return found != null ? found : bidiOther
	  }

	  // Bidirectional ordering algorithm
	  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
	  // that this (partially) implements.

	  // One-char codes used for character types:
	  // L (L):   Left-to-Right
	  // R (R):   Right-to-Left
	  // r (AL):  Right-to-Left Arabic
	  // 1 (EN):  European Number
	  // + (ES):  European Number Separator
	  // % (ET):  European Number Terminator
	  // n (AN):  Arabic Number
	  // , (CS):  Common Number Separator
	  // m (NSM): Non-Spacing Mark
	  // b (BN):  Boundary Neutral
	  // s (B):   Paragraph Separator
	  // t (S):   Segment Separator
	  // w (WS):  Whitespace
	  // N (ON):  Other Neutrals

	  // Returns null if characters are ordered as they appear
	  // (left-to-right), or an array of sections ({from, to, level}
	  // objects) in the order in which they occur visually.
	  var bidiOrdering = (function() {
	    // Character types for codepoints 0 to 0xff
	    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
	    // Character types for codepoints 0x600 to 0x6f9
	    var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";
	    function charType(code) {
	      if (code <= 0xf7) { return lowTypes.charAt(code) }
	      else if (0x590 <= code && code <= 0x5f4) { return "R" }
	      else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
	      else if (0x6ee <= code && code <= 0x8ac) { return "r" }
	      else if (0x2000 <= code && code <= 0x200b) { return "w" }
	      else if (code == 0x200c) { return "b" }
	      else { return "L" }
	    }

	    var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
	    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;

	    function BidiSpan(level, from, to) {
	      this.level = level;
	      this.from = from; this.to = to;
	    }

	    return function(str, direction) {
	      var outerType = direction == "ltr" ? "L" : "R";

	      if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false }
	      var len = str.length, types = [];
	      for (var i = 0; i < len; ++i)
	        { types.push(charType(str.charCodeAt(i))); }

	      // W1. Examine each non-spacing mark (NSM) in the level run, and
	      // change the type of the NSM to the type of the previous
	      // character. If the NSM is at the start of the level run, it will
	      // get the type of sor.
	      for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
	        var type = types[i$1];
	        if (type == "m") { types[i$1] = prev; }
	        else { prev = type; }
	      }

	      // W2. Search backwards from each instance of a European number
	      // until the first strong type (R, L, AL, or sor) is found. If an
	      // AL is found, change the type of the European number to Arabic
	      // number.
	      // W3. Change all ALs to R.
	      for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
	        var type$1 = types[i$2];
	        if (type$1 == "1" && cur == "r") { types[i$2] = "n"; }
	        else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } }
	      }

	      // W4. A single European separator between two European numbers
	      // changes to a European number. A single common separator between
	      // two numbers of the same type changes to that type.
	      for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
	        var type$2 = types[i$3];
	        if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; }
	        else if (type$2 == "," && prev$1 == types[i$3+1] &&
	                 (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; }
	        prev$1 = type$2;
	      }

	      // W5. A sequence of European terminators adjacent to European
	      // numbers changes to all European numbers.
	      // W6. Otherwise, separators and terminators change to Other
	      // Neutral.
	      for (var i$4 = 0; i$4 < len; ++i$4) {
	        var type$3 = types[i$4];
	        if (type$3 == ",") { types[i$4] = "N"; }
	        else if (type$3 == "%") {
	          var end = (void 0);
	          for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
	          var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
	          for (var j = i$4; j < end; ++j) { types[j] = replace; }
	          i$4 = end - 1;
	        }
	      }

	      // W7. Search backwards from each instance of a European number
	      // until the first strong type (R, L, or sor) is found. If an L is
	      // found, then change the type of the European number to L.
	      for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
	        var type$4 = types[i$5];
	        if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; }
	        else if (isStrong.test(type$4)) { cur$1 = type$4; }
	      }

	      // N1. A sequence of neutrals takes the direction of the
	      // surrounding strong text if the text on both sides has the same
	      // direction. European and Arabic numbers act as if they were R in
	      // terms of their influence on neutrals. Start-of-level-run (sor)
	      // and end-of-level-run (eor) are used at level run boundaries.
	      // N2. Any remaining neutrals take the embedding direction.
	      for (var i$6 = 0; i$6 < len; ++i$6) {
	        if (isNeutral.test(types[i$6])) {
	          var end$1 = (void 0);
	          for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
	          var before = (i$6 ? types[i$6-1] : outerType) == "L";
	          var after = (end$1 < len ? types[end$1] : outerType) == "L";
	          var replace$1 = before == after ? (before ? "L" : "R") : outerType;
	          for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; }
	          i$6 = end$1 - 1;
	        }
	      }

	      // Here we depart from the documented algorithm, in order to avoid
	      // building up an actual levels array. Since there are only three
	      // levels (0, 1, 2) in an implementation that doesn't take
	      // explicit embedding into account, we can build up the order on
	      // the fly, without following the level-based algorithm.
	      var order = [], m;
	      for (var i$7 = 0; i$7 < len;) {
	        if (countsAsLeft.test(types[i$7])) {
	          var start = i$7;
	          for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
	          order.push(new BidiSpan(0, start, i$7));
	        } else {
	          var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0;
	          for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
	          for (var j$2 = pos; j$2 < i$7;) {
	            if (countsAsNum.test(types[j$2])) {
	              if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; }
	              var nstart = j$2;
	              for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
	              order.splice(at, 0, new BidiSpan(2, nstart, j$2));
	              at += isRTL;
	              pos = j$2;
	            } else { ++j$2; }
	          }
	          if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); }
	        }
	      }
	      if (direction == "ltr") {
	        if (order[0].level == 1 && (m = str.match(/^\s+/))) {
	          order[0].from = m[0].length;
	          order.unshift(new BidiSpan(0, 0, m[0].length));
	        }
	        if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
	          lst(order).to -= m[0].length;
	          order.push(new BidiSpan(0, len - m[0].length, len));
	        }
	      }

	      return direction == "rtl" ? order.reverse() : order
	    }
	  })();

	  // Get the bidi ordering for the given line (and cache it). Returns
	  // false for lines that are fully left-to-right, and an array of
	  // BidiSpan objects otherwise.
	  function getOrder(line, direction) {
	    var order = line.order;
	    if (order == null) { order = line.order = bidiOrdering(line.text, direction); }
	    return order
	  }

	  // EVENT HANDLING

	  // Lightweight event framework. on/off also work on DOM nodes,
	  // registering native DOM handlers.

	  var noHandlers = [];

	  var on = function(emitter, type, f) {
	    if (emitter.addEventListener) {
	      emitter.addEventListener(type, f, false);
	    } else if (emitter.attachEvent) {
	      emitter.attachEvent("on" + type, f);
	    } else {
	      var map = emitter._handlers || (emitter._handlers = {});
	      map[type] = (map[type] || noHandlers).concat(f);
	    }
	  };

	  function getHandlers(emitter, type) {
	    return emitter._handlers && emitter._handlers[type] || noHandlers
	  }

	  function off(emitter, type, f) {
	    if (emitter.removeEventListener) {
	      emitter.removeEventListener(type, f, false);
	    } else if (emitter.detachEvent) {
	      emitter.detachEvent("on" + type, f);
	    } else {
	      var map = emitter._handlers, arr = map && map[type];
	      if (arr) {
	        var index = indexOf(arr, f);
	        if (index > -1)
	          { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }
	      }
	    }
	  }

	  function signal(emitter, type /*, values...*/) {
	    var handlers = getHandlers(emitter, type);
	    if (!handlers.length) { return }
	    var args = Array.prototype.slice.call(arguments, 2);
	    for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); }
	  }

	  // The DOM events that CodeMirror handles can be overridden by
	  // registering a (non-DOM) handler on the editor for the event name,
	  // and preventDefault-ing the event in that handler.
	  function signalDOMEvent(cm, e, override) {
	    if (typeof e == "string")
	      { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; }
	    signal(cm, override || e.type, cm, e);
	    return e_defaultPrevented(e) || e.codemirrorIgnore
	  }

	  function signalCursorActivity(cm) {
	    var arr = cm._handlers && cm._handlers.cursorActivity;
	    if (!arr) { return }
	    var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
	    for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
	      { set.push(arr[i]); } }
	  }

	  function hasHandler(emitter, type) {
	    return getHandlers(emitter, type).length > 0
	  }

	  // Add on and off methods to a constructor's prototype, to make
	  // registering events on such objects more convenient.
	  function eventMixin(ctor) {
	    ctor.prototype.on = function(type, f) {on(this, type, f);};
	    ctor.prototype.off = function(type, f) {off(this, type, f);};
	  }

	  // Due to the fact that we still support jurassic IE versions, some
	  // compatibility wrappers are needed.

	  function e_preventDefault(e) {
	    if (e.preventDefault) { e.preventDefault(); }
	    else { e.returnValue = false; }
	  }
	  function e_stopPropagation(e) {
	    if (e.stopPropagation) { e.stopPropagation(); }
	    else { e.cancelBubble = true; }
	  }
	  function e_defaultPrevented(e) {
	    return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
	  }
	  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}

	  function e_target(e) {return e.target || e.srcElement}
	  function e_button(e) {
	    var b = e.which;
	    if (b == null) {
	      if (e.button & 1) { b = 1; }
	      else if (e.button & 2) { b = 3; }
	      else if (e.button & 4) { b = 2; }
	    }
	    if (mac && e.ctrlKey && b == 1) { b = 3; }
	    return b
	  }

	  // Detect drag-and-drop
	  var dragAndDrop = function() {
	    // There is *some* kind of drag-and-drop support in IE6-8, but I
	    // couldn't get it to work yet.
	    if (ie && ie_version < 9) { return false }
	    var div = elt('div');
	    return "draggable" in div || "dragDrop" in div
	  }();

	  var zwspSupported;
	  function zeroWidthElement(measure) {
	    if (zwspSupported == null) {
	      var test = elt("span", "\u200b");
	      removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
	      if (measure.firstChild.offsetHeight != 0)
	        { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); }
	    }
	    var node = zwspSupported ? elt("span", "\u200b") :
	      elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
	    node.setAttribute("cm-text", "");
	    return node
	  }

	  // Feature-detect IE's crummy client rect reporting for bidi text
	  var badBidiRects;
	  function hasBadBidiRects(measure) {
	    if (badBidiRects != null) { return badBidiRects }
	    var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
	    var r0 = range(txt, 0, 1).getBoundingClientRect();
	    var r1 = range(txt, 1, 2).getBoundingClientRect();
	    removeChildren(measure);
	    if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
	    return badBidiRects = (r1.right - r0.right < 3)
	  }

	  // See if "".split is the broken IE version, if so, provide an
	  // alternative way to split lines.
	  var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
	    var pos = 0, result = [], l = string.length;
	    while (pos <= l) {
	      var nl = string.indexOf("\n", pos);
	      if (nl == -1) { nl = string.length; }
	      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
	      var rt = line.indexOf("\r");
	      if (rt != -1) {
	        result.push(line.slice(0, rt));
	        pos += rt + 1;
	      } else {
	        result.push(line);
	        pos = nl + 1;
	      }
	    }
	    return result
	  } : function (string) { return string.split(/\r\n?|\n/); };

	  var hasSelection = window.getSelection ? function (te) {
	    try { return te.selectionStart != te.selectionEnd }
	    catch(e) { return false }
	  } : function (te) {
	    var range;
	    try {range = te.ownerDocument.selection.createRange();}
	    catch(e) {}
	    if (!range || range.parentElement() != te) { return false }
	    return range.compareEndPoints("StartToEnd", range) != 0
	  };

	  var hasCopyEvent = (function () {
	    var e = elt("div");
	    if ("oncopy" in e) { return true }
	    e.setAttribute("oncopy", "return;");
	    return typeof e.oncopy == "function"
	  })();

	  var badZoomedRects = null;
	  function hasBadZoomedRects(measure) {
	    if (badZoomedRects != null) { return badZoomedRects }
	    var node = removeChildrenAndAdd(measure, elt("span", "x"));
	    var normal = node.getBoundingClientRect();
	    var fromRange = range(node, 0, 1).getBoundingClientRect();
	    return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
	  }

	  // Known modes, by name and by MIME
	  var modes = {}, mimeModes = {};

	  // Extra arguments are stored as the mode's dependencies, which is
	  // used by (legacy) mechanisms like loadmode.js to automatically
	  // load a mode. (Preferred mechanism is the require/define calls.)
	  function defineMode(name, mode) {
	    if (arguments.length > 2)
	      { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
	    modes[name] = mode;
	  }

	  function defineMIME(mime, spec) {
	    mimeModes[mime] = spec;
	  }

	  // Given a MIME type, a {name, ...options} config object, or a name
	  // string, return a mode config object.
	  function resolveMode(spec) {
	    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
	      spec = mimeModes[spec];
	    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
	      var found = mimeModes[spec.name];
	      if (typeof found == "string") { found = {name: found}; }
	      spec = createObj(found, spec);
	      spec.name = found.name;
	    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
	      return resolveMode("application/xml")
	    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
	      return resolveMode("application/json")
	    }
	    if (typeof spec == "string") { return {name: spec} }
	    else { return spec || {name: "null"} }
	  }

	  // Given a mode spec (anything that resolveMode accepts), find and
	  // initialize an actual mode object.
	  function getMode(options, spec) {
	    spec = resolveMode(spec);
	    var mfactory = modes[spec.name];
	    if (!mfactory) { return getMode(options, "text/plain") }
	    var modeObj = mfactory(options, spec);
	    if (modeExtensions.hasOwnProperty(spec.name)) {
	      var exts = modeExtensions[spec.name];
	      for (var prop in exts) {
	        if (!exts.hasOwnProperty(prop)) { continue }
	        if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
	        modeObj[prop] = exts[prop];
	      }
	    }
	    modeObj.name = spec.name;
	    if (spec.helperType) { modeObj.helperType = spec.helperType; }
	    if (spec.modeProps) { for (var prop$1 in spec.modeProps)
	      { modeObj[prop$1] = spec.modeProps[prop$1]; } }

	    return modeObj
	  }

	  // This can be used to attach properties to mode objects from
	  // outside the actual mode definition.
	  var modeExtensions = {};
	  function extendMode(mode, properties) {
	    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
	    copyObj(properties, exts);
	  }

	  function copyState(mode, state) {
	    if (state === true) { return state }
	    if (mode.copyState) { return mode.copyState(state) }
	    var nstate = {};
	    for (var n in state) {
	      var val = state[n];
	      if (val instanceof Array) { val = val.concat([]); }
	      nstate[n] = val;
	    }
	    return nstate
	  }

	  // Given a mode and a state (for that mode), find the inner mode and
	  // state at the position that the state refers to.
	  function innerMode(mode, state) {
	    var info;
	    while (mode.innerMode) {
	      info = mode.innerMode(state);
	      if (!info || info.mode == mode) { break }
	      state = info.state;
	      mode = info.mode;
	    }
	    return info || {mode: mode, state: state}
	  }

	  function startState(mode, a1, a2) {
	    return mode.startState ? mode.startState(a1, a2) : true
	  }

	  // STRING STREAM

	  // Fed to the mode parsers, provides helper functions to make
	  // parsers more succinct.

	  var StringStream = function(string, tabSize, lineOracle) {
	    this.pos = this.start = 0;
	    this.string = string;
	    this.tabSize = tabSize || 8;
	    this.lastColumnPos = this.lastColumnValue = 0;
	    this.lineStart = 0;
	    this.lineOracle = lineOracle;
	  };

	  StringStream.prototype.eol = function () {return this.pos >= this.string.length};
	  StringStream.prototype.sol = function () {return this.pos == this.lineStart};
	  StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
	  StringStream.prototype.next = function () {
	    if (this.pos < this.string.length)
	      { return this.string.charAt(this.pos++) }
	  };
	  StringStream.prototype.eat = function (match) {
	    var ch = this.string.charAt(this.pos);
	    var ok;
	    if (typeof match == "string") { ok = ch == match; }
	    else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
	    if (ok) {++this.pos; return ch}
	  };
	  StringStream.prototype.eatWhile = function (match) {
	    var start = this.pos;
	    while (this.eat(match)){}
	    return this.pos > start
	  };
	  StringStream.prototype.eatSpace = function () {
	    var start = this.pos;
	    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
	    return this.pos > start
	  };
	  StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
	  StringStream.prototype.skipTo = function (ch) {
	    var found = this.string.indexOf(ch, this.pos);
	    if (found > -1) {this.pos = found; return true}
	  };
	  StringStream.prototype.backUp = function (n) {this.pos -= n;};
	  StringStream.prototype.column = function () {
	    if (this.lastColumnPos < this.start) {
	      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
	      this.lastColumnPos = this.start;
	    }
	    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
	  };
	  StringStream.prototype.indentation = function () {
	    return countColumn(this.string, null, this.tabSize) -
	      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
	  };
	  StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
	    if (typeof pattern == "string") {
	      var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
	      var substr = this.string.substr(this.pos, pattern.length);
	      if (cased(substr) == cased(pattern)) {
	        if (consume !== false) { this.pos += pattern.length; }
	        return true
	      }
	    } else {
	      var match = this.string.slice(this.pos).match(pattern);
	      if (match && match.index > 0) { return null }
	      if (match && consume !== false) { this.pos += match[0].length; }
	      return match
	    }
	  };
	  StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
	  StringStream.prototype.hideFirstChars = function (n, inner) {
	    this.lineStart += n;
	    try { return inner() }
	    finally { this.lineStart -= n; }
	  };
	  StringStream.prototype.lookAhead = function (n) {
	    var oracle = this.lineOracle;
	    return oracle && oracle.lookAhead(n)
	  };
	  StringStream.prototype.baseToken = function () {
	    var oracle = this.lineOracle;
	    return oracle && oracle.baseToken(this.pos)
	  };

	  // Find the line object corresponding to the given line number.
	  function getLine(doc, n) {
	    n -= doc.first;
	    if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
	    var chunk = doc;
	    while (!chunk.lines) {
	      for (var i = 0;; ++i) {
	        var child = chunk.children[i], sz = child.chunkSize();
	        if (n < sz) { chunk = child; break }
	        n -= sz;
	      }
	    }
	    return chunk.lines[n]
	  }

	  // Get the part of a document between two positions, as an array of
	  // strings.
	  function getBetween(doc, start, end) {
	    var out = [], n = start.line;
	    doc.iter(start.line, end.line + 1, function (line) {
	      var text = line.text;
	      if (n == end.line) { text = text.slice(0, end.ch); }
	      if (n == start.line) { text = text.slice(start.ch); }
	      out.push(text);
	      ++n;
	    });
	    return out
	  }
	  // Get the lines between from and to, as array of strings.
	  function getLines(doc, from, to) {
	    var out = [];
	    doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value
	    return out
	  }

	  // Update the height of a line, propagating the height change
	  // upwards to parent nodes.
	  function updateLineHeight(line, height) {
	    var diff = height - line.height;
	    if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } }
	  }

	  // Given a line object, find its line number by walking up through
	  // its parent links.
	  function lineNo(line) {
	    if (line.parent == null) { return null }
	    var cur = line.parent, no = indexOf(cur.lines, line);
	    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
	      for (var i = 0;; ++i) {
	        if (chunk.children[i] == cur) { break }
	        no += chunk.children[i].chunkSize();
	      }
	    }
	    return no + cur.first
	  }

	  // Find the line at the given vertical position, using the height
	  // information in the document tree.
	  function lineAtHeight(chunk, h) {
	    var n = chunk.first;
	    outer: do {
	      for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
	        var child = chunk.children[i$1], ch = child.height;
	        if (h < ch) { chunk = child; continue outer }
	        h -= ch;
	        n += child.chunkSize();
	      }
	      return n
	    } while (!chunk.lines)
	    var i = 0;
	    for (; i < chunk.lines.length; ++i) {
	      var line = chunk.lines[i], lh = line.height;
	      if (h < lh) { break }
	      h -= lh;
	    }
	    return n + i
	  }

	  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}

	  function lineNumberFor(options, i) {
	    return String(options.lineNumberFormatter(i + options.firstLineNumber))
	  }

	  // A Pos instance represents a position within the text.
	  function Pos(line, ch, sticky) {
	    if ( sticky === void 0 ) sticky = null;

	    if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) }
	    this.line = line;
	    this.ch = ch;
	    this.sticky = sticky;
	  }

	  // Compare two positions, return 0 if they are the same, a negative
	  // number when a is less, and a positive number otherwise.
	  function cmp(a, b) { return a.line - b.line || a.ch - b.ch }

	  function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 }

	  function copyPos(x) {return Pos(x.line, x.ch)}
	  function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
	  function minPos(a, b) { return cmp(a, b) < 0 ? a : b }

	  // Most of the external API clips given positions to make sure they
	  // actually exist within the document.
	  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
	  function clipPos(doc, pos) {
	    if (pos.line < doc.first) { return Pos(doc.first, 0) }
	    var last = doc.first + doc.size - 1;
	    if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
	    return clipToLen(pos, getLine(doc, pos.line).text.length)
	  }
	  function clipToLen(pos, linelen) {
	    var ch = pos.ch;
	    if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
	    else if (ch < 0) { return Pos(pos.line, 0) }
	    else { return pos }
	  }
	  function clipPosArray(doc, array) {
	    var out = [];
	    for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); }
	    return out
	  }

	  var SavedContext = function(state, lookAhead) {
	    this.state = state;
	    this.lookAhead = lookAhead;
	  };

	  var Context = function(doc, state, line, lookAhead) {
	    this.state = state;
	    this.doc = doc;
	    this.line = line;
	    this.maxLookAhead = lookAhead || 0;
	    this.baseTokens = null;
	    this.baseTokenPos = 1;
	  };

	  Context.prototype.lookAhead = function (n) {
	    var line = this.doc.getLine(this.line + n);
	    if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; }
	    return line
	  };

	  Context.prototype.baseToken = function (n) {
	    if (!this.baseTokens) { return null }
	    while (this.baseTokens[this.baseTokenPos] <= n)
	      { this.baseTokenPos += 2; }
	    var type = this.baseTokens[this.baseTokenPos + 1];
	    return {type: type && type.replace(/( |^)overlay .*/, ""),
	            size: this.baseTokens[this.baseTokenPos] - n}
	  };

	  Context.prototype.nextLine = function () {
	    this.line++;
	    if (this.maxLookAhead > 0) { this.maxLookAhead--; }
	  };

	  Context.fromSaved = function (doc, saved, line) {
	    if (saved instanceof SavedContext)
	      { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) }
	    else
	      { return new Context(doc, copyState(doc.mode, saved), line) }
	  };

	  Context.prototype.save = function (copy) {
	    var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state;
	    return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state
	  };


	  // Compute a style array (an array starting with a mode generation
	  // -- for invalidation -- followed by pairs of end positions and
	  // style strings), which is used to highlight the tokens on the
	  // line.
	  function highlightLine(cm, line, context, forceToEnd) {
	    // A styles array always starts with a number identifying the
	    // mode/overlays that it is based on (for easy invalidation).
	    var st = [cm.state.modeGen], lineClasses = {};
	    // Compute the base array of styles
	    runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); },
	            lineClasses, forceToEnd);
	    var state = context.state;

	    // Run overlays, adjust style array.
	    var loop = function ( o ) {
	      context.baseTokens = st;
	      var overlay = cm.state.overlays[o], i = 1, at = 0;
	      context.state = true;
	      runMode(cm, line.text, overlay.mode, context, function (end, style) {
	        var start = i;
	        // Ensure there's a token end at the current position, and that i points at it
	        while (at < end) {
	          var i_end = st[i];
	          if (i_end > end)
	            { st.splice(i, 1, end, st[i+1], i_end); }
	          i += 2;
	          at = Math.min(end, i_end);
	        }
	        if (!style) { return }
	        if (overlay.opaque) {
	          st.splice(start, i - start, end, "overlay " + style);
	          i = start + 2;
	        } else {
	          for (; start < i; start += 2) {
	            var cur = st[start+1];
	            st[start+1] = (cur ? cur + " " : "") + "overlay " + style;
	          }
	        }
	      }, lineClasses);
	      context.state = state;
	      context.baseTokens = null;
	      context.baseTokenPos = 1;
	    };

	    for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );

	    return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
	  }

	  function getLineStyles(cm, line, updateFrontier) {
	    if (!line.styles || line.styles[0] != cm.state.modeGen) {
	      var context = getContextBefore(cm, lineNo(line));
	      var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state);
	      var result = highlightLine(cm, line, context);
	      if (resetState) { context.state = resetState; }
	      line.stateAfter = context.save(!resetState);
	      line.styles = result.styles;
	      if (result.classes) { line.styleClasses = result.classes; }
	      else if (line.styleClasses) { line.styleClasses = null; }
	      if (updateFrontier === cm.doc.highlightFrontier)
	        { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); }
	    }
	    return line.styles
	  }

	  function getContextBefore(cm, n, precise) {
	    var doc = cm.doc, display = cm.display;
	    if (!doc.mode.startState) { return new Context(doc, true, n) }
	    var start = findStartLine(cm, n, precise);
	    var saved = start > doc.first && getLine(doc, start - 1).stateAfter;
	    var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start);

	    doc.iter(start, n, function (line) {
	      processLine(cm, line.text, context);
	      var pos = context.line;
	      line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null;
	      context.nextLine();
	    });
	    if (precise) { doc.modeFrontier = context.line; }
	    return context
	  }

	  // Lightweight form of highlight -- proceed over this line and
	  // update state, but don't save a style array. Used for lines that
	  // aren't currently visible.
	  function processLine(cm, text, context, startAt) {
	    var mode = cm.doc.mode;
	    var stream = new StringStream(text, cm.options.tabSize, context);
	    stream.start = stream.pos = startAt || 0;
	    if (text == "") { callBlankLine(mode, context.state); }
	    while (!stream.eol()) {
	      readToken(mode, stream, context.state);
	      stream.start = stream.pos;
	    }
	  }

	  function callBlankLine(mode, state) {
	    if (mode.blankLine) { return mode.blankLine(state) }
	    if (!mode.innerMode) { return }
	    var inner = innerMode(mode, state);
	    if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
	  }

	  function readToken(mode, stream, state, inner) {
	    for (var i = 0; i < 10; i++) {
	      if (inner) { inner[0] = innerMode(mode, state).mode; }
	      var style = mode.token(stream, state);
	      if (stream.pos > stream.start) { return style }
	    }
	    throw new Error("Mode " + mode.name + " failed to advance stream.")
	  }

	  var Token = function(stream, type, state) {
	    this.start = stream.start; this.end = stream.pos;
	    this.string = stream.current();
	    this.type = type || null;
	    this.state = state;
	  };

	  // Utility for getTokenAt and getLineTokens
	  function takeToken(cm, pos, precise, asArray) {
	    var doc = cm.doc, mode = doc.mode, style;
	    pos = clipPos(doc, pos);
	    var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise);
	    var stream = new StringStream(line.text, cm.options.tabSize, context), tokens;
	    if (asArray) { tokens = []; }
	    while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
	      stream.start = stream.pos;
	      style = readToken(mode, stream, context.state);
	      if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); }
	    }
	    return asArray ? tokens : new Token(stream, style, context.state)
	  }

	  function extractLineClasses(type, output) {
	    if (type) { for (;;) {
	      var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
	      if (!lineClass) { break }
	      type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
	      var prop = lineClass[1] ? "bgClass" : "textClass";
	      if (output[prop] == null)
	        { output[prop] = lineClass[2]; }
	      else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop]))
	        { output[prop] += " " + lineClass[2]; }
	    } }
	    return type
	  }

	  // Run the given mode's parser over a line, calling f for each token.
	  function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) {
	    var flattenSpans = mode.flattenSpans;
	    if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; }
	    var curStart = 0, curStyle = null;
	    var stream = new StringStream(text, cm.options.tabSize, context), style;
	    var inner = cm.options.addModeClass && [null];
	    if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); }
	    while (!stream.eol()) {
	      if (stream.pos > cm.options.maxHighlightLength) {
	        flattenSpans = false;
	        if (forceToEnd) { processLine(cm, text, context, stream.pos); }
	        stream.pos = text.length;
	        style = null;
	      } else {
	        style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses);
	      }
	      if (inner) {
	        var mName = inner[0].name;
	        if (mName) { style = "m-" + (style ? mName + " " + style : mName); }
	      }
	      if (!flattenSpans || curStyle != style) {
	        while (curStart < stream.start) {
	          curStart = Math.min(stream.start, curStart + 5000);
	          f(curStart, curStyle);
	        }
	        curStyle = style;
	      }
	      stream.start = stream.pos;
	    }
	    while (curStart < stream.pos) {
	      // Webkit seems to refuse to render text nodes longer than 57444
	      // characters, and returns inaccurate measurements in nodes
	      // starting around 5000 chars.
	      var pos = Math.min(stream.pos, curStart + 5000);
	      f(pos, curStyle);
	      curStart = pos;
	    }
	  }

	  // Finds the line to start with when starting a parse. Tries to
	  // find a line with a stateAfter, so that it can start with a
	  // valid state. If that fails, it returns the line with the
	  // smallest indentation, which tends to need the least context to
	  // parse correctly.
	  function findStartLine(cm, n, precise) {
	    var minindent, minline, doc = cm.doc;
	    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
	    for (var search = n; search > lim; --search) {
	      if (search <= doc.first) { return doc.first }
	      var line = getLine(doc, search - 1), after = line.stateAfter;
	      if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier))
	        { return search }
	      var indented = countColumn(line.text, null, cm.options.tabSize);
	      if (minline == null || minindent > indented) {
	        minline = search - 1;
	        minindent = indented;
	      }
	    }
	    return minline
	  }

	  function retreatFrontier(doc, n) {
	    doc.modeFrontier = Math.min(doc.modeFrontier, n);
	    if (doc.highlightFrontier < n - 10) { return }
	    var start = doc.first;
	    for (var line = n - 1; line > start; line--) {
	      var saved = getLine(doc, line).stateAfter;
	      // change is on 3
	      // state on line 1 looked ahead 2 -- so saw 3
	      // test 1 + 2 < 3 should cover this
	      if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) {
	        start = line + 1;
	        break
	      }
	    }
	    doc.highlightFrontier = Math.min(doc.highlightFrontier, start);
	  }

	  // Optimize some code when these features are not used.
	  var sawReadOnlySpans = false, sawCollapsedSpans = false;

	  function seeReadOnlySpans() {
	    sawReadOnlySpans = true;
	  }

	  function seeCollapsedSpans() {
	    sawCollapsedSpans = true;
	  }

	  // TEXTMARKER SPANS

	  function MarkedSpan(marker, from, to) {
	    this.marker = marker;
	    this.from = from; this.to = to;
	  }

	  // Search an array of spans for a span matching the given marker.
	  function getMarkedSpanFor(spans, marker) {
	    if (spans) { for (var i = 0; i < spans.length; ++i) {
	      var span = spans[i];
	      if (span.marker == marker) { return span }
	    } }
	  }

	  // Remove a span from an array, returning undefined if no spans are
	  // left (we don't store arrays for lines without spans).
	  function removeMarkedSpan(spans, span) {
	    var r;
	    for (var i = 0; i < spans.length; ++i)
	      { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
	    return r
	  }

	  // Add a span to a line.
	  function addMarkedSpan(line, span, op) {
	    var inThisOp = op && window.WeakSet && (op.markedSpans || (op.markedSpans = new WeakSet));
	    if (inThisOp && line.markedSpans && inThisOp.has(line.markedSpans)) {
	      line.markedSpans.push(span);
	    } else {
	      line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
	      if (inThisOp) { inThisOp.add(line.markedSpans); }
	    }
	    span.marker.attachLine(line);
	  }

	  // Used for the algorithm that adjusts markers for a change in the
	  // document. These functions cut an array of spans at a given
	  // character position, returning an array of remaining chunks (or
	  // undefined if nothing remains).
	  function markedSpansBefore(old, startCh, isInsert) {
	    var nw;
	    if (old) { for (var i = 0; i < old.length; ++i) {
	      var span = old[i], marker = span.marker;
	      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
	      if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
	        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
	        ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
	      }
	    } }
	    return nw
	  }
	  function markedSpansAfter(old, endCh, isInsert) {
	    var nw;
	    if (old) { for (var i = 0; i < old.length; ++i) {
	      var span = old[i], marker = span.marker;
	      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
	      if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
	        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
	        ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
	                                              span.to == null ? null : span.to - endCh));
	      }
	    } }
	    return nw
	  }

	  // Given a change object, compute the new set of marker spans that
	  // cover the line in which the change took place. Removes spans
	  // entirely within the change, reconnects spans belonging to the
	  // same marker that appear on both sides of the change, and cuts off
	  // spans partially within the change. Returns an array of span
	  // arrays with one element for each line in (after) the change.
	  function stretchSpansOverChange(doc, change) {
	    if (change.full) { return null }
	    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
	    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
	    if (!oldFirst && !oldLast) { return null }

	    var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
	    // Get the spans that 'stick out' on both sides
	    var first = markedSpansBefore(oldFirst, startCh, isInsert);
	    var last = markedSpansAfter(oldLast, endCh, isInsert);

	    // Next, merge those two ends
	    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
	    if (first) {
	      // Fix up .to properties of first
	      for (var i = 0; i < first.length; ++i) {
	        var span = first[i];
	        if (span.to == null) {
	          var found = getMarkedSpanFor(last, span.marker);
	          if (!found) { span.to = startCh; }
	          else if (sameLine) { span.to = found.to == null ? null : found.to + offset; }
	        }
	      }
	    }
	    if (last) {
	      // Fix up .from in last (or move them into first in case of sameLine)
	      for (var i$1 = 0; i$1 < last.length; ++i$1) {
	        var span$1 = last[i$1];
	        if (span$1.to != null) { span$1.to += offset; }
	        if (span$1.from == null) {
	          var found$1 = getMarkedSpanFor(first, span$1.marker);
	          if (!found$1) {
	            span$1.from = offset;
	            if (sameLine) { (first || (first = [])).push(span$1); }
	          }
	        } else {
	          span$1.from += offset;
	          if (sameLine) { (first || (first = [])).push(span$1); }
	        }
	      }
	    }
	    // Make sure we didn't create any zero-length spans
	    if (first) { first = clearEmptySpans(first); }
	    if (last && last != first) { last = clearEmptySpans(last); }

	    var newMarkers = [first];
	    if (!sameLine) {
	      // Fill gap with whole-line-spans
	      var gap = change.text.length - 2, gapMarkers;
	      if (gap > 0 && first)
	        { for (var i$2 = 0; i$2 < first.length; ++i$2)
	          { if (first[i$2].to == null)
	            { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } }
	      for (var i$3 = 0; i$3 < gap; ++i$3)
	        { newMarkers.push(gapMarkers); }
	      newMarkers.push(last);
	    }
	    return newMarkers
	  }

	  // Remove spans that are empty and don't have a clearWhenEmpty
	  // option of false.
	  function clearEmptySpans(spans) {
	    for (var i = 0; i < spans.length; ++i) {
	      var span = spans[i];
	      if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
	        { spans.splice(i--, 1); }
	    }
	    if (!spans.length) { return null }
	    return spans
	  }

	  // Used to 'clip' out readOnly ranges when making a change.
	  function removeReadOnlyRanges(doc, from, to) {
	    var markers = null;
	    doc.iter(from.line, to.line + 1, function (line) {
	      if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
	        var mark = line.markedSpans[i].marker;
	        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
	          { (markers || (markers = [])).push(mark); }
	      } }
	    });
	    if (!markers) { return null }
	    var parts = [{from: from, to: to}];
	    for (var i = 0; i < markers.length; ++i) {
	      var mk = markers[i], m = mk.find(0);
	      for (var j = 0; j < parts.length; ++j) {
	        var p = parts[j];
	        if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
	        var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
	        if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
	          { newParts.push({from: p.from, to: m.from}); }
	        if (dto > 0 || !mk.inclusiveRight && !dto)
	          { newParts.push({from: m.to, to: p.to}); }
	        parts.splice.apply(parts, newParts);
	        j += newParts.length - 3;
	      }
	    }
	    return parts
	  }

	  // Connect or disconnect spans from a line.
	  function detachMarkedSpans(line) {
	    var spans = line.markedSpans;
	    if (!spans) { return }
	    for (var i = 0; i < spans.length; ++i)
	      { spans[i].marker.detachLine(line); }
	    line.markedSpans = null;
	  }
	  function attachMarkedSpans(line, spans) {
	    if (!spans) { return }
	    for (var i = 0; i < spans.length; ++i)
	      { spans[i].marker.attachLine(line); }
	    line.markedSpans = spans;
	  }

	  // Helpers used when computing which overlapping collapsed span
	  // counts as the larger one.
	  function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
	  function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }

	  // Returns a number indicating which of two overlapping collapsed
	  // spans is larger (and thus includes the other). Falls back to
	  // comparing ids when the spans cover exactly the same range.
	  function compareCollapsedMarkers(a, b) {
	    var lenDiff = a.lines.length - b.lines.length;
	    if (lenDiff != 0) { return lenDiff }
	    var aPos = a.find(), bPos = b.find();
	    var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
	    if (fromCmp) { return -fromCmp }
	    var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
	    if (toCmp) { return toCmp }
	    return b.id - a.id
	  }

	  // Find out whether a line ends or starts in a collapsed span. If
	  // so, return the marker for that span.
	  function collapsedSpanAtSide(line, start) {
	    var sps = sawCollapsedSpans && line.markedSpans, found;
	    if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
	      sp = sps[i];
	      if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
	          (!found || compareCollapsedMarkers(found, sp.marker) < 0))
	        { found = sp.marker; }
	    } }
	    return found
	  }
	  function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
	  function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }

	  function collapsedSpanAround(line, ch) {
	    var sps = sawCollapsedSpans && line.markedSpans, found;
	    if (sps) { for (var i = 0; i < sps.length; ++i) {
	      var sp = sps[i];
	      if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) &&
	          (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; }
	    } }
	    return found
	  }

	  // Test whether there exists a collapsed span that partially
	  // overlaps (covers the start or end, but not both) of a new span.
	  // Such overlap is not allowed.
	  function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
	    var line = getLine(doc, lineNo);
	    var sps = sawCollapsedSpans && line.markedSpans;
	    if (sps) { for (var i = 0; i < sps.length; ++i) {
	      var sp = sps[i];
	      if (!sp.marker.collapsed) { continue }
	      var found = sp.marker.find(0);
	      var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
	      var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
	      if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
	      if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
	          fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
	        { return true }
	    } }
	  }

	  // A visual line is a line as drawn on the screen. Folding, for
	  // example, can cause multiple logical lines to appear on the same
	  // visual line. This finds the start of the visual line that the
	  // given line is part of (usually that is the line itself).
	  function visualLine(line) {
	    var merged;
	    while (merged = collapsedSpanAtStart(line))
	      { line = merged.find(-1, true).line; }
	    return line
	  }

	  function visualLineEnd(line) {
	    var merged;
	    while (merged = collapsedSpanAtEnd(line))
	      { line = merged.find(1, true).line; }
	    return line
	  }

	  // Returns an array of logical lines that continue the visual line
	  // started by the argument, or undefined if there are no such lines.
	  function visualLineContinued(line) {
	    var merged, lines;
	    while (merged = collapsedSpanAtEnd(line)) {
	      line = merged.find(1, true).line
	      ;(lines || (lines = [])).push(line);
	    }
	    return lines
	  }

	  // Get the line number of the start of the visual line that the
	  // given line number is part of.
	  function visualLineNo(doc, lineN) {
	    var line = getLine(doc, lineN), vis = visualLine(line);
	    if (line == vis) { return lineN }
	    return lineNo(vis)
	  }

	  // Get the line number of the start of the next visual line after
	  // the given line.
	  function visualLineEndNo(doc, lineN) {
	    if (lineN > doc.lastLine()) { return lineN }
	    var line = getLine(doc, lineN), merged;
	    if (!lineIsHidden(doc, line)) { return lineN }
	    while (merged = collapsedSpanAtEnd(line))
	      { line = merged.find(1, true).line; }
	    return lineNo(line) + 1
	  }

	  // Compute whether a line is hidden. Lines count as hidden when they
	  // are part of a visual line that starts with another line, or when
	  // they are entirely covered by collapsed, non-widget span.
	  function lineIsHidden(doc, line) {
	    var sps = sawCollapsedSpans && line.markedSpans;
	    if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
	      sp = sps[i];
	      if (!sp.marker.collapsed) { continue }
	      if (sp.from == null) { return true }
	      if (sp.marker.widgetNode) { continue }
	      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
	        { return true }
	    } }
	  }
	  function lineIsHiddenInner(doc, line, span) {
	    if (span.to == null) {
	      var end = span.marker.find(1, true);
	      return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
	    }
	    if (span.marker.inclusiveRight && span.to == line.text.length)
	      { return true }
	    for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
	      sp = line.markedSpans[i];
	      if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
	          (sp.to == null || sp.to != span.from) &&
	          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
	          lineIsHiddenInner(doc, line, sp)) { return true }
	    }
	  }

	  // Find the height above the given line.
	  function heightAtLine(lineObj) {
	    lineObj = visualLine(lineObj);

	    var h = 0, chunk = lineObj.parent;
	    for (var i = 0; i < chunk.lines.length; ++i) {
	      var line = chunk.lines[i];
	      if (line == lineObj) { break }
	      else { h += line.height; }
	    }
	    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
	      for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
	        var cur = p.children[i$1];
	        if (cur == chunk) { break }
	        else { h += cur.height; }
	      }
	    }
	    return h
	  }

	  // Compute the character length of a line, taking into account
	  // collapsed ranges (see markText) that might hide parts, and join
	  // other lines onto it.
	  function lineLength(line) {
	    if (line.height == 0) { return 0 }
	    var len = line.text.length, merged, cur = line;
	    while (merged = collapsedSpanAtStart(cur)) {
	      var found = merged.find(0, true);
	      cur = found.from.line;
	      len += found.from.ch - found.to.ch;
	    }
	    cur = line;
	    while (merged = collapsedSpanAtEnd(cur)) {
	      var found$1 = merged.find(0, true);
	      len -= cur.text.length - found$1.from.ch;
	      cur = found$1.to.line;
	      len += cur.text.length - found$1.to.ch;
	    }
	    return len
	  }

	  // Find the longest line in the document.
	  function findMaxLine(cm) {
	    var d = cm.display, doc = cm.doc;
	    d.maxLine = getLine(doc, doc.first);
	    d.maxLineLength = lineLength(d.maxLine);
	    d.maxLineChanged = true;
	    doc.iter(function (line) {
	      var len = lineLength(line);
	      if (len > d.maxLineLength) {
	        d.maxLineLength = len;
	        d.maxLine = line;
	      }
	    });
	  }

	  // LINE DATA STRUCTURE

	  // Line objects. These hold state related to a line, including
	  // highlighting info (the styles array).
	  var Line = function(text, markedSpans, estimateHeight) {
	    this.text = text;
	    attachMarkedSpans(this, markedSpans);
	    this.height = estimateHeight ? estimateHeight(this) : 1;
	  };

	  Line.prototype.lineNo = function () { return lineNo(this) };
	  eventMixin(Line);

	  // Change the content (text, markers) of a line. Automatically
	  // invalidates cached information and tries to re-estimate the
	  // line's height.
	  function updateLine(line, text, markedSpans, estimateHeight) {
	    line.text = text;
	    if (line.stateAfter) { line.stateAfter = null; }
	    if (line.styles) { line.styles = null; }
	    if (line.order != null) { line.order = null; }
	    detachMarkedSpans(line);
	    attachMarkedSpans(line, markedSpans);
	    var estHeight = estimateHeight ? estimateHeight(line) : 1;
	    if (estHeight != line.height) { updateLineHeight(line, estHeight); }
	  }

	  // Detach a line from the document tree and its markers.
	  function cleanUpLine(line) {
	    line.parent = null;
	    detachMarkedSpans(line);
	  }

	  // Convert a style as returned by a mode (either null, or a string
	  // containing one or more styles) to a CSS style. This is cached,
	  // and also looks for line-wide styles.
	  var styleToClassCache = {}, styleToClassCacheWithMode = {};
	  function interpretTokenStyle(style, options) {
	    if (!style || /^\s*$/.test(style)) { return null }
	    var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
	    return cache[style] ||
	      (cache[style] = style.replace(/\S+/g, "cm-$&"))
	  }

	  // Render the DOM representation of the text of a line. Also builds
	  // up a 'line map', which points at the DOM nodes that represent
	  // specific stretches of text, and is used by the measuring code.
	  // The returned object contains the DOM node, this map, and
	  // information about line-wide styles that were set by the mode.
	  function buildLineContent(cm, lineView) {
	    // The padding-right forces the element to have a 'border', which
	    // is needed on Webkit to be able to get line-level bounding
	    // rectangles for it (in measureChar).
	    var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null);
	    var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content,
	                   col: 0, pos: 0, cm: cm,
	                   trailingSpace: false,
	                   splitSpaces: cm.getOption("lineWrapping")};
	    lineView.measure = {};

	    // Iterate over the logical lines that make up this visual line.
	    for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
	      var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0);
	      builder.pos = 0;
	      builder.addToken = buildToken;
	      // Optionally wire in some hacks into the token-rendering
	      // algorithm, to deal with browser quirks.
	      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction)))
	        { builder.addToken = buildTokenBadBidi(builder.addToken, order); }
	      builder.map = [];
	      var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
	      insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
	      if (line.styleClasses) {
	        if (line.styleClasses.bgClass)
	          { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); }
	        if (line.styleClasses.textClass)
	          { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); }
	      }

	      // Ensure at least a single node is present, for measuring.
	      if (builder.map.length == 0)
	        { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); }

	      // Store the map and a cache object for the current logical line
	      if (i == 0) {
	        lineView.measure.map = builder.map;
	        lineView.measure.cache = {};
	      } else {
	  (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
	        ;(lineView.measure.caches || (lineView.measure.caches = [])).push({});
	      }
	    }

	    // See issue #2901
	    if (webkit) {
	      var last = builder.content.lastChild;
	      if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
	        { builder.content.className = "cm-tab-wrap-hack"; }
	    }

	    signal(cm, "renderLine", cm, lineView.line, builder.pre);
	    if (builder.pre.className)
	      { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); }

	    return builder
	  }

	  function defaultSpecialCharPlaceholder(ch) {
	    var token = elt("span", "\u2022", "cm-invalidchar");
	    token.title = "\\u" + ch.charCodeAt(0).toString(16);
	    token.setAttribute("aria-label", token.title);
	    return token
	  }

	  // Build up the DOM representation for a single token, and add it to
	  // the line map. Takes care to render special characters separately.
	  function buildToken(builder, text, style, startStyle, endStyle, css, attributes) {
	    if (!text) { return }
	    var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text;
	    var special = builder.cm.state.specialChars, mustWrap = false;
	    var content;
	    if (!special.test(text)) {
	      builder.col += text.length;
	      content = document.createTextNode(displayText);
	      builder.map.push(builder.pos, builder.pos + text.length, content);
	      if (ie && ie_version < 9) { mustWrap = true; }
	      builder.pos += text.length;
	    } else {
	      content = document.createDocumentFragment();
	      var pos = 0;
	      while (true) {
	        special.lastIndex = pos;
	        var m = special.exec(text);
	        var skipped = m ? m.index - pos : text.length - pos;
	        if (skipped) {
	          var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
	          if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); }
	          else { content.appendChild(txt); }
	          builder.map.push(builder.pos, builder.pos + skipped, txt);
	          builder.col += skipped;
	          builder.pos += skipped;
	        }
	        if (!m) { break }
	        pos += skipped + 1;
	        var txt$1 = (void 0);
	        if (m[0] == "\t") {
	          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
	          txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
	          txt$1.setAttribute("role", "presentation");
	          txt$1.setAttribute("cm-text", "\t");
	          builder.col += tabWidth;
	        } else if (m[0] == "\r" || m[0] == "\n") {
	          txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
	          txt$1.setAttribute("cm-text", m[0]);
	          builder.col += 1;
	        } else {
	          txt$1 = builder.cm.options.specialCharPlaceholder(m[0]);
	          txt$1.setAttribute("cm-text", m[0]);
	          if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); }
	          else { content.appendChild(txt$1); }
	          builder.col += 1;
	        }
	        builder.map.push(builder.pos, builder.pos + 1, txt$1);
	        builder.pos++;
	      }
	    }
	    builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
	    if (style || startStyle || endStyle || mustWrap || css || attributes) {
	      var fullStyle = style || "";
	      if (startStyle) { fullStyle += startStyle; }
	      if (endStyle) { fullStyle += endStyle; }
	      var token = elt("span", [content], fullStyle, css);
	      if (attributes) {
	        for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class")
	          { token.setAttribute(attr, attributes[attr]); } }
	      }
	      return builder.content.appendChild(token)
	    }
	    builder.content.appendChild(content);
	  }

	  // Change some spaces to NBSP to prevent the browser from collapsing
	  // trailing spaces at the end of a line when rendering text (issue #1362).
	  function splitSpaces(text, trailingBefore) {
	    if (text.length > 1 && !/  /.test(text)) { return text }
	    var spaceBefore = trailingBefore, result = "";
	    for (var i = 0; i < text.length; i++) {
	      var ch = text.charAt(i);
	      if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
	        { ch = "\u00a0"; }
	      result += ch;
	      spaceBefore = ch == " ";
	    }
	    return result
	  }

	  // Work around nonsense dimensions being reported for stretches of
	  // right-to-left text.
	  function buildTokenBadBidi(inner, order) {
	    return function (builder, text, style, startStyle, endStyle, css, attributes) {
	      style = style ? style + " cm-force-border" : "cm-force-border";
	      var start = builder.pos, end = start + text.length;
	      for (;;) {
	        // Find the part that overlaps with the start of this text
	        var part = (void 0);
	        for (var i = 0; i < order.length; i++) {
	          part = order[i];
	          if (part.to > start && part.from <= start) { break }
	        }
	        if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) }
	        inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes);
	        startStyle = null;
	        text = text.slice(part.to - start);
	        start = part.to;
	      }
	    }
	  }

	  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
	    var widget = !ignoreWidget && marker.widgetNode;
	    if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); }
	    if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
	      if (!widget)
	        { widget = builder.content.appendChild(document.createElement("span")); }
	      widget.setAttribute("cm-marker", marker.id);
	    }
	    if (widget) {
	      builder.cm.display.input.setUneditable(widget);
	      builder.content.appendChild(widget);
	    }
	    builder.pos += size;
	    builder.trailingSpace = false;
	  }

	  // Outputs a number of spans to make up a line, taking highlighting
	  // and marked text into account.
	  function insertLineContent(line, builder, styles) {
	    var spans = line.markedSpans, allText = line.text, at = 0;
	    if (!spans) {
	      for (var i$1 = 1; i$1 < styles.length; i$1+=2)
	        { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); }
	      return
	    }

	    var len = allText.length, pos = 0, i = 1, text = "", style, css;
	    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes;
	    for (;;) {
	      if (nextChange == pos) { // Update current marker set
	        spanStyle = spanEndStyle = spanStartStyle = css = "";
	        attributes = null;
	        collapsed = null; nextChange = Infinity;
	        var foundBookmarks = [], endStyles = (void 0);
	        for (var j = 0; j < spans.length; ++j) {
	          var sp = spans[j], m = sp.marker;
	          if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
	            foundBookmarks.push(m);
	          } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
	            if (sp.to != null && sp.to != pos && nextChange > sp.to) {
	              nextChange = sp.to;
	              spanEndStyle = "";
	            }
	            if (m.className) { spanStyle += " " + m.className; }
	            if (m.css) { css = (css ? css + ";" : "") + m.css; }
	            if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; }
	            if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); }
	            // support for the old title property
	            // https://github.com/codemirror/CodeMirror/pull/5673
	            if (m.title) { (attributes || (attributes = {})).title = m.title; }
	            if (m.attributes) {
	              for (var attr in m.attributes)
	                { (attributes || (attributes = {}))[attr] = m.attributes[attr]; }
	            }
	            if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
	              { collapsed = sp; }
	          } else if (sp.from > pos && nextChange > sp.from) {
	            nextChange = sp.from;
	          }
	        }
	        if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
	          { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } }

	        if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
	          { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } }
	        if (collapsed && (collapsed.from || 0) == pos) {
	          buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
	                             collapsed.marker, collapsed.from == null);
	          if (collapsed.to == null) { return }
	          if (collapsed.to == pos) { collapsed = false; }
	        }
	      }
	      if (pos >= len) { break }

	      var upto = Math.min(len, nextChange);
	      while (true) {
	        if (text) {
	          var end = pos + text.length;
	          if (!collapsed) {
	            var tokenText = end > upto ? text.slice(0, upto - pos) : text;
	            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
	                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes);
	          }
	          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
	          pos = end;
	          spanStartStyle = "";
	        }
	        text = allText.slice(at, at = styles[i++]);
	        style = interpretTokenStyle(styles[i++], builder.cm.options);
	      }
	    }
	  }


	  // These objects are used to represent the visible (currently drawn)
	  // part of the document. A LineView may correspond to multiple
	  // logical lines, if those are connected by collapsed ranges.
	  function LineView(doc, line, lineN) {
	    // The starting line
	    this.line = line;
	    // Continuing lines, if any
	    this.rest = visualLineContinued(line);
	    // Number of logical lines in this visual line
	    this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
	    this.node = this.text = null;
	    this.hidden = lineIsHidden(doc, line);
	  }

	  // Create a range of LineView objects for the given lines.
	  function buildViewArray(cm, from, to) {
	    var array = [], nextPos;
	    for (var pos = from; pos < to; pos = nextPos) {
	      var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
	      nextPos = pos + view.size;
	      array.push(view);
	    }
	    return array
	  }

	  var operationGroup = null;

	  function pushOperation(op) {
	    if (operationGroup) {
	      operationGroup.ops.push(op);
	    } else {
	      op.ownsGroup = operationGroup = {
	        ops: [op],
	        delayedCallbacks: []
	      };
	    }
	  }

	  function fireCallbacksForOps(group) {
	    // Calls delayed callbacks and cursorActivity handlers until no
	    // new ones appear
	    var callbacks = group.delayedCallbacks, i = 0;
	    do {
	      for (; i < callbacks.length; i++)
	        { callbacks[i].call(null); }
	      for (var j = 0; j < group.ops.length; j++) {
	        var op = group.ops[j];
	        if (op.cursorActivityHandlers)
	          { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
	            { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } }
	      }
	    } while (i < callbacks.length)
	  }

	  function finishOperation(op, endCb) {
	    var group = op.ownsGroup;
	    if (!group) { return }

	    try { fireCallbacksForOps(group); }
	    finally {
	      operationGroup = null;
	      endCb(group);
	    }
	  }

	  var orphanDelayedCallbacks = null;

	  // Often, we want to signal events at a point where we are in the
	  // middle of some work, but don't want the handler to start calling
	  // other methods on the editor, which might be in an inconsistent
	  // state or simply not expect any other events to happen.
	  // signalLater looks whether there are any handlers, and schedules
	  // them to be executed when the last operation ends, or, if no
	  // operation is active, when a timeout fires.
	  function signalLater(emitter, type /*, values...*/) {
	    var arr = getHandlers(emitter, type);
	    if (!arr.length) { return }
	    var args = Array.prototype.slice.call(arguments, 2), list;
	    if (operationGroup) {
	      list = operationGroup.delayedCallbacks;
	    } else if (orphanDelayedCallbacks) {
	      list = orphanDelayedCallbacks;
	    } else {
	      list = orphanDelayedCallbacks = [];
	      setTimeout(fireOrphanDelayed, 0);
	    }
	    var loop = function ( i ) {
	      list.push(function () { return arr[i].apply(null, args); });
	    };

	    for (var i = 0; i < arr.length; ++i)
	      loop( i );
	  }

	  function fireOrphanDelayed() {
	    var delayed = orphanDelayedCallbacks;
	    orphanDelayedCallbacks = null;
	    for (var i = 0; i < delayed.length; ++i) { delayed[i](); }
	  }

	  // When an aspect of a line changes, a string is added to
	  // lineView.changes. This updates the relevant part of the line's
	  // DOM structure.
	  function updateLineForChanges(cm, lineView, lineN, dims) {
	    for (var j = 0; j < lineView.changes.length; j++) {
	      var type = lineView.changes[j];
	      if (type == "text") { updateLineText(cm, lineView); }
	      else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); }
	      else if (type == "class") { updateLineClasses(cm, lineView); }
	      else if (type == "widget") { updateLineWidgets(cm, lineView, dims); }
	    }
	    lineView.changes = null;
	  }

	  // Lines with gutter elements, widgets or a background class need to
	  // be wrapped, and have the extra elements added to the wrapper div
	  function ensureLineWrapped(lineView) {
	    if (lineView.node == lineView.text) {
	      lineView.node = elt("div", null, null, "position: relative");
	      if (lineView.text.parentNode)
	        { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); }
	      lineView.node.appendChild(lineView.text);
	      if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; }
	    }
	    return lineView.node
	  }

	  function updateLineBackground(cm, lineView) {
	    var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
	    if (cls) { cls += " CodeMirror-linebackground"; }
	    if (lineView.background) {
	      if (cls) { lineView.background.className = cls; }
	      else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
	    } else if (cls) {
	      var wrap = ensureLineWrapped(lineView);
	      lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
	      cm.display.input.setUneditable(lineView.background);
	    }
	  }

	  // Wrapper around buildLineContent which will reuse the structure
	  // in display.externalMeasured when possible.
	  function getLineContent(cm, lineView) {
	    var ext = cm.display.externalMeasured;
	    if (ext && ext.line == lineView.line) {
	      cm.display.externalMeasured = null;
	      lineView.measure = ext.measure;
	      return ext.built
	    }
	    return buildLineContent(cm, lineView)
	  }

	  // Redraw the line's text. Interacts with the background and text
	  // classes because the mode may output tokens that influence these
	  // classes.
	  function updateLineText(cm, lineView) {
	    var cls = lineView.text.className;
	    var built = getLineContent(cm, lineView);
	    if (lineView.text == lineView.node) { lineView.node = built.pre; }
	    lineView.text.parentNode.replaceChild(built.pre, lineView.text);
	    lineView.text = built.pre;
	    if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
	      lineView.bgClass = built.bgClass;
	      lineView.textClass = built.textClass;
	      updateLineClasses(cm, lineView);
	    } else if (cls) {
	      lineView.text.className = cls;
	    }
	  }

	  function updateLineClasses(cm, lineView) {
	    updateLineBackground(cm, lineView);
	    if (lineView.line.wrapClass)
	      { ensureLineWrapped(lineView).className = lineView.line.wrapClass; }
	    else if (lineView.node != lineView.text)
	      { lineView.node.className = ""; }
	    var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
	    lineView.text.className = textClass || "";
	  }

	  function updateLineGutter(cm, lineView, lineN, dims) {
	    if (lineView.gutter) {
	      lineView.node.removeChild(lineView.gutter);
	      lineView.gutter = null;
	    }
	    if (lineView.gutterBackground) {
	      lineView.node.removeChild(lineView.gutterBackground);
	      lineView.gutterBackground = null;
	    }
	    if (lineView.line.gutterClass) {
	      var wrap = ensureLineWrapped(lineView);
	      lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
	                                      ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"));
	      cm.display.input.setUneditable(lineView.gutterBackground);
	      wrap.insertBefore(lineView.gutterBackground, lineView.text);
	    }
	    var markers = lineView.line.gutterMarkers;
	    if (cm.options.lineNumbers || markers) {
	      var wrap$1 = ensureLineWrapped(lineView);
	      var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
	      gutterWrap.setAttribute("aria-hidden", "true");
	      cm.display.input.setUneditable(gutterWrap);
	      wrap$1.insertBefore(gutterWrap, lineView.text);
	      if (lineView.line.gutterClass)
	        { gutterWrap.className += " " + lineView.line.gutterClass; }
	      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
	        { lineView.lineNumber = gutterWrap.appendChild(
	          elt("div", lineNumberFor(cm.options, lineN),
	              "CodeMirror-linenumber CodeMirror-gutter-elt",
	              ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); }
	      if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) {
	        var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id];
	        if (found)
	          { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
	                                     ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); }
	      } }
	    }
	  }

	  function updateLineWidgets(cm, lineView, dims) {
	    if (lineView.alignable) { lineView.alignable = null; }
	    var isWidget = classTest("CodeMirror-linewidget");
	    for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
	      next = node.nextSibling;
	      if (isWidget.test(node.className)) { lineView.node.removeChild(node); }
	    }
	    insertLineWidgets(cm, lineView, dims);
	  }

	  // Build a line's DOM representation from scratch
	  function buildLineElement(cm, lineView, lineN, dims) {
	    var built = getLineContent(cm, lineView);
	    lineView.text = lineView.node = built.pre;
	    if (built.bgClass) { lineView.bgClass = built.bgClass; }
	    if (built.textClass) { lineView.textClass = built.textClass; }

	    updateLineClasses(cm, lineView);
	    updateLineGutter(cm, lineView, lineN, dims);
	    insertLineWidgets(cm, lineView, dims);
	    return lineView.node
	  }

	  // A lineView may contain multiple logical lines (when merged by
	  // collapsed spans). The widgets for all of them need to be drawn.
	  function insertLineWidgets(cm, lineView, dims) {
	    insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
	    if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
	      { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } }
	  }

	  function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
	    if (!line.widgets) { return }
	    var wrap = ensureLineWrapped(lineView);
	    for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
	      var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : ""));
	      if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); }
	      positionLineWidget(widget, node, lineView, dims);
	      cm.display.input.setUneditable(node);
	      if (allowAbove && widget.above)
	        { wrap.insertBefore(node, lineView.gutter || lineView.text); }
	      else
	        { wrap.appendChild(node); }
	      signalLater(widget, "redraw");
	    }
	  }

	  function positionLineWidget(widget, node, lineView, dims) {
	    if (widget.noHScroll) {
	  (lineView.alignable || (lineView.alignable = [])).push(node);
	      var width = dims.wrapperWidth;
	      node.style.left = dims.fixedPos + "px";
	      if (!widget.coverGutter) {
	        width -= dims.gutterTotalWidth;
	        node.style.paddingLeft = dims.gutterTotalWidth + "px";
	      }
	      node.style.width = width + "px";
	    }
	    if (widget.coverGutter) {
	      node.style.zIndex = 5;
	      node.style.position = "relative";
	      if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; }
	    }
	  }

	  function widgetHeight(widget) {
	    if (widget.height != null) { return widget.height }
	    var cm = widget.doc.cm;
	    if (!cm) { return 0 }
	    if (!contains(document.body, widget.node)) {
	      var parentStyle = "position: relative;";
	      if (widget.coverGutter)
	        { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; }
	      if (widget.noHScroll)
	        { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; }
	      removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
	    }
	    return widget.height = widget.node.parentNode.offsetHeight
	  }

	  // Return true when the given mouse event happened in a widget
	  function eventInWidget(display, e) {
	    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
	      if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
	          (n.parentNode == display.sizer && n != display.mover))
	        { return true }
	    }
	  }

	  // POSITION MEASUREMENT

	  function paddingTop(display) {return display.lineSpace.offsetTop}
	  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
	  function paddingH(display) {
	    if (display.cachedPaddingH) { return display.cachedPaddingH }
	    var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like"));
	    var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
	    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
	    if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; }
	    return data
	  }

	  function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
	  function displayWidth(cm) {
	    return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
	  }
	  function displayHeight(cm) {
	    return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
	  }

	  // Ensure the lineView.wrapping.heights array is populated. This is
	  // an array of bottom offsets for the lines that make up a drawn
	  // line. When lineWrapping is on, there might be more than one
	  // height.
	  function ensureLineHeights(cm, lineView, rect) {
	    var wrapping = cm.options.lineWrapping;
	    var curWidth = wrapping && displayWidth(cm);
	    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
	      var heights = lineView.measure.heights = [];
	      if (wrapping) {
	        lineView.measure.width = curWidth;
	        var rects = lineView.text.firstChild.getClientRects();
	        for (var i = 0; i < rects.length - 1; i++) {
	          var cur = rects[i], next = rects[i + 1];
	          if (Math.abs(cur.bottom - next.bottom) > 2)
	            { heights.push((cur.bottom + next.top) / 2 - rect.top); }
	        }
	      }
	      heights.push(rect.bottom - rect.top);
	    }
	  }

	  // Find a line map (mapping character offsets to text nodes) and a
	  // measurement cache for the given line number. (A line view might
	  // contain multiple lines when collapsed ranges are present.)
	  function mapFromLineView(lineView, line, lineN) {
	    if (lineView.line == line)
	      { return {map: lineView.measure.map, cache: lineView.measure.cache} }
	    if (lineView.rest) {
	      for (var i = 0; i < lineView.rest.length; i++)
	        { if (lineView.rest[i] == line)
	          { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
	      for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
	        { if (lineNo(lineView.rest[i$1]) > lineN)
	          { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
	    }
	  }

	  // Render a line into the hidden node display.externalMeasured. Used
	  // when measurement is needed for a line that's not in the viewport.
	  function updateExternalMeasurement(cm, line) {
	    line = visualLine(line);
	    var lineN = lineNo(line);
	    var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
	    view.lineN = lineN;
	    var built = view.built = buildLineContent(cm, view);
	    view.text = built.pre;
	    removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
	    return view
	  }

	  // Get a {top, bottom, left, right} box (in line-local coordinates)
	  // for a given character.
	  function measureChar(cm, line, ch, bias) {
	    return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
	  }

	  // Find a line view that corresponds to the given line number.
	  function findViewForLine(cm, lineN) {
	    if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
	      { return cm.display.view[findViewIndex(cm, lineN)] }
	    var ext = cm.display.externalMeasured;
	    if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
	      { return ext }
	  }

	  // Measurement can be split in two steps, the set-up work that
	  // applies to the whole line, and the measurement of the actual
	  // character. Functions like coordsChar, that need to do a lot of
	  // measurements in a row, can thus ensure that the set-up work is
	  // only done once.
	  function prepareMeasureForLine(cm, line) {
	    var lineN = lineNo(line);
	    var view = findViewForLine(cm, lineN);
	    if (view && !view.text) {
	      view = null;
	    } else if (view && view.changes) {
	      updateLineForChanges(cm, view, lineN, getDimensions(cm));
	      cm.curOp.forceUpdate = true;
	    }
	    if (!view)
	      { view = updateExternalMeasurement(cm, line); }

	    var info = mapFromLineView(view, line, lineN);
	    return {
	      line: line, view: view, rect: null,
	      map: info.map, cache: info.cache, before: info.before,
	      hasHeights: false
	    }
	  }

	  // Given a prepared measurement object, measures the position of an
	  // actual character (or fetches it from the cache).
	  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
	    if (prepared.before) { ch = -1; }
	    var key = ch + (bias || ""), found;
	    if (prepared.cache.hasOwnProperty(key)) {
	      found = prepared.cache[key];
	    } else {
	      if (!prepared.rect)
	        { prepared.rect = prepared.view.text.getBoundingClientRect(); }
	      if (!prepared.hasHeights) {
	        ensureLineHeights(cm, prepared.view, prepared.rect);
	        prepared.hasHeights = true;
	      }
	      found = measureCharInner(cm, prepared, ch, bias);
	      if (!found.bogus) { prepared.cache[key] = found; }
	    }
	    return {left: found.left, right: found.right,
	            top: varHeight ? found.rtop : found.top,
	            bottom: varHeight ? found.rbottom : found.bottom}
	  }

	  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};

	  function nodeAndOffsetInLineMap(map, ch, bias) {
	    var node, start, end, collapse, mStart, mEnd;
	    // First, search the line map for the text node corresponding to,
	    // or closest to, the target character.
	    for (var i = 0; i < map.length; i += 3) {
	      mStart = map[i];
	      mEnd = map[i + 1];
	      if (ch < mStart) {
	        start = 0; end = 1;
	        collapse = "left";
	      } else if (ch < mEnd) {
	        start = ch - mStart;
	        end = start + 1;
	      } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
	        end = mEnd - mStart;
	        start = end - 1;
	        if (ch >= mEnd) { collapse = "right"; }
	      }
	      if (start != null) {
	        node = map[i + 2];
	        if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
	          { collapse = bias; }
	        if (bias == "left" && start == 0)
	          { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
	            node = map[(i -= 3) + 2];
	            collapse = "left";
	          } }
	        if (bias == "right" && start == mEnd - mStart)
	          { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
	            node = map[(i += 3) + 2];
	            collapse = "right";
	          } }
	        break
	      }
	    }
	    return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
	  }

	  function getUsefulRect(rects, bias) {
	    var rect = nullRect;
	    if (bias == "left") { for (var i = 0; i < rects.length; i++) {
	      if ((rect = rects[i]).left != rect.right) { break }
	    } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
	      if ((rect = rects[i$1]).left != rect.right) { break }
	    } }
	    return rect
	  }

	  function measureCharInner(cm, prepared, ch, bias) {
	    var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
	    var node = place.node, start = place.start, end = place.end, collapse = place.collapse;

	    var rect;
	    if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
	      for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
	        while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; }
	        while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; }
	        if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
	          { rect = node.parentNode.getBoundingClientRect(); }
	        else
	          { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); }
	        if (rect.left || rect.right || start == 0) { break }
	        end = start;
	        start = start - 1;
	        collapse = "right";
	      }
	      if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); }
	    } else { // If it is a widget, simply get the box for the whole widget.
	      if (start > 0) { collapse = bias = "right"; }
	      var rects;
	      if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
	        { rect = rects[bias == "right" ? rects.length - 1 : 0]; }
	      else
	        { rect = node.getBoundingClientRect(); }
	    }
	    if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
	      var rSpan = node.parentNode.getClientRects()[0];
	      if (rSpan)
	        { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; }
	      else
	        { rect = nullRect; }
	    }

	    var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
	    var mid = (rtop + rbot) / 2;
	    var heights = prepared.view.measure.heights;
	    var i = 0;
	    for (; i < heights.length - 1; i++)
	      { if (mid < heights[i]) { break } }
	    var top = i ? heights[i - 1] : 0, bot = heights[i];
	    var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
	                  right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
	                  top: top, bottom: bot};
	    if (!rect.left && !rect.right) { result.bogus = true; }
	    if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }

	    return result
	  }

	  // Work around problem with bounding client rects on ranges being
	  // returned incorrectly when zoomed on IE10 and below.
	  function maybeUpdateRectForZooming(measure, rect) {
	    if (!window.screen || screen.logicalXDPI == null ||
	        screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
	      { return rect }
	    var scaleX = screen.logicalXDPI / screen.deviceXDPI;
	    var scaleY = screen.logicalYDPI / screen.deviceYDPI;
	    return {left: rect.left * scaleX, right: rect.right * scaleX,
	            top: rect.top * scaleY, bottom: rect.bottom * scaleY}
	  }

	  function clearLineMeasurementCacheFor(lineView) {
	    if (lineView.measure) {
	      lineView.measure.cache = {};
	      lineView.measure.heights = null;
	      if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
	        { lineView.measure.caches[i] = {}; } }
	    }
	  }

	  function clearLineMeasurementCache(cm) {
	    cm.display.externalMeasure = null;
	    removeChildren(cm.display.lineMeasure);
	    for (var i = 0; i < cm.display.view.length; i++)
	      { clearLineMeasurementCacheFor(cm.display.view[i]); }
	  }

	  function clearCaches(cm) {
	    clearLineMeasurementCache(cm);
	    cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
	    if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; }
	    cm.display.lineNumChars = null;
	  }

	  function pageScrollX(doc) {
	    // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206
	    // which causes page_Offset and bounding client rects to use
	    // different reference viewports and invalidate our calculations.
	    if (chrome && android) { return -(doc.body.getBoundingClientRect().left - parseInt(getComputedStyle(doc.body).marginLeft)) }
	    return doc.defaultView.pageXOffset || (doc.documentElement || doc.body).scrollLeft
	  }
	  function pageScrollY(doc) {
	    if (chrome && android) { return -(doc.body.getBoundingClientRect().top - parseInt(getComputedStyle(doc.body).marginTop)) }
	    return doc.defaultView.pageYOffset || (doc.documentElement || doc.body).scrollTop
	  }

	  function widgetTopHeight(lineObj) {
	    var ref = visualLine(lineObj);
	    var widgets = ref.widgets;
	    var height = 0;
	    if (widgets) { for (var i = 0; i < widgets.length; ++i) { if (widgets[i].above)
	      { height += widgetHeight(widgets[i]); } } }
	    return height
	  }

	  // Converts a {top, bottom, left, right} box from line-local
	  // coordinates into another coordinate system. Context may be one of
	  // "line", "div" (display.lineDiv), "local"./null (editor), "window",
	  // or "page".
	  function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
	    if (!includeWidgets) {
	      var height = widgetTopHeight(lineObj);
	      rect.top += height; rect.bottom += height;
	    }
	    if (context == "line") { return rect }
	    if (!context) { context = "local"; }
	    var yOff = heightAtLine(lineObj);
	    if (context == "local") { yOff += paddingTop(cm.display); }
	    else { yOff -= cm.display.viewOffset; }
	    if (context == "page" || context == "window") {
	      var lOff = cm.display.lineSpace.getBoundingClientRect();
	      yOff += lOff.top + (context == "window" ? 0 : pageScrollY(doc(cm)));
	      var xOff = lOff.left + (context == "window" ? 0 : pageScrollX(doc(cm)));
	      rect.left += xOff; rect.right += xOff;
	    }
	    rect.top += yOff; rect.bottom += yOff;
	    return rect
	  }

	  // Coverts a box from "div" coords to another coordinate system.
	  // Context may be "window", "page", "div", or "local"./null.
	  function fromCoordSystem(cm, coords, context) {
	    if (context == "div") { return coords }
	    var left = coords.left, top = coords.top;
	    // First move into "page" coordinate system
	    if (context == "page") {
	      left -= pageScrollX(doc(cm));
	      top -= pageScrollY(doc(cm));
	    } else if (context == "local" || !context) {
	      var localBox = cm.display.sizer.getBoundingClientRect();
	      left += localBox.left;
	      top += localBox.top;
	    }

	    var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
	    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
	  }

	  function charCoords(cm, pos, context, lineObj, bias) {
	    if (!lineObj) { lineObj = getLine(cm.doc, pos.line); }
	    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
	  }

	  // Returns a box for a given cursor position, which may have an
	  // 'other' property containing the position of the secondary cursor
	  // on a bidi boundary.
	  // A cursor Pos(line, char, "before") is on the same visual line as `char - 1`
	  // and after `char - 1` in writing order of `char - 1`
	  // A cursor Pos(line, char, "after") is on the same visual line as `char`
	  // and before `char` in writing order of `char`
	  // Examples (upper-case letters are RTL, lower-case are LTR):
	  //     Pos(0, 1, ...)
	  //     before   after
	  // ab     a|b     a|b
	  // aB     a|B     aB|
	  // Ab     |Ab     A|b
	  // AB     B|A     B|A
	  // Every position after the last character on a line is considered to stick
	  // to the last character on the line.
	  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
	    lineObj = lineObj || getLine(cm.doc, pos.line);
	    if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
	    function get(ch, right) {
	      var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
	      if (right) { m.left = m.right; } else { m.right = m.left; }
	      return intoCoordSystem(cm, lineObj, m, context)
	    }
	    var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky;
	    if (ch >= lineObj.text.length) {
	      ch = lineObj.text.length;
	      sticky = "before";
	    } else if (ch <= 0) {
	      ch = 0;
	      sticky = "after";
	    }
	    if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") }

	    function getBidi(ch, partPos, invert) {
	      var part = order[partPos], right = part.level == 1;
	      return get(invert ? ch - 1 : ch, right != invert)
	    }
	    var partPos = getBidiPartAt(order, ch, sticky);
	    var other = bidiOther;
	    var val = getBidi(ch, partPos, sticky == "before");
	    if (other != null) { val.other = getBidi(ch, other, sticky != "before"); }
	    return val
	  }

	  // Used to cheaply estimate the coordinates for a position. Used for
	  // intermediate scroll updates.
	  function estimateCoords(cm, pos) {
	    var left = 0;
	    pos = clipPos(cm.doc, pos);
	    if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; }
	    var lineObj = getLine(cm.doc, pos.line);
	    var top = heightAtLine(lineObj) + paddingTop(cm.display);
	    return {left: left, right: left, top: top, bottom: top + lineObj.height}
	  }

	  // Positions returned by coordsChar contain some extra information.
	  // xRel is the relative x position of the input coordinates compared
	  // to the found position (so xRel > 0 means the coordinates are to
	  // the right of the character position, for example). When outside
	  // is true, that means the coordinates lie outside the line's
	  // vertical range.
	  function PosWithInfo(line, ch, sticky, outside, xRel) {
	    var pos = Pos(line, ch, sticky);
	    pos.xRel = xRel;
	    if (outside) { pos.outside = outside; }
	    return pos
	  }

	  // Compute the character position closest to the given coordinates.
	  // Input must be lineSpace-local ("div" coordinate system).
	  function coordsChar(cm, x, y) {
	    var doc = cm.doc;
	    y += cm.display.viewOffset;
	    if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) }
	    var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
	    if (lineN > last)
	      { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) }
	    if (x < 0) { x = 0; }

	    var lineObj = getLine(doc, lineN);
	    for (;;) {
	      var found = coordsCharInner(cm, lineObj, lineN, x, y);
	      var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0));
	      if (!collapsed) { return found }
	      var rangeEnd = collapsed.find(1);
	      if (rangeEnd.line == lineN) { return rangeEnd }
	      lineObj = getLine(doc, lineN = rangeEnd.line);
	    }
	  }

	  function wrappedLineExtent(cm, lineObj, preparedMeasure, y) {
	    y -= widgetTopHeight(lineObj);
	    var end = lineObj.text.length;
	    var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0);
	    end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end);
	    return {begin: begin, end: end}
	  }

	  function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {
	    if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
	    var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top;
	    return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)
	  }

	  // Returns true if the given side of a box is after the given
	  // coordinates, in top-to-bottom, left-to-right order.
	  function boxIsAfter(box, x, y, left) {
	    return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x
	  }

	  function coordsCharInner(cm, lineObj, lineNo, x, y) {
	    // Move y into line-local coordinate space
	    y -= heightAtLine(lineObj);
	    var preparedMeasure = prepareMeasureForLine(cm, lineObj);
	    // When directly calling `measureCharPrepared`, we have to adjust
	    // for the widgets at this line.
	    var widgetHeight = widgetTopHeight(lineObj);
	    var begin = 0, end = lineObj.text.length, ltr = true;

	    var order = getOrder(lineObj, cm.doc.direction);
	    // If the line isn't plain left-to-right text, first figure out
	    // which bidi section the coordinates fall into.
	    if (order) {
	      var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)
	                   (cm, lineObj, lineNo, preparedMeasure, order, x, y);
	      ltr = part.level != 1;
	      // The awkward -1 offsets are needed because findFirst (called
	      // on these below) will treat its first bound as inclusive,
	      // second as exclusive, but we want to actually address the
	      // characters in the part's range
	      begin = ltr ? part.from : part.to - 1;
	      end = ltr ? part.to : part.from - 1;
	    }

	    // A binary search to find the first character whose bounding box
	    // starts after the coordinates. If we run across any whose box wrap
	    // the coordinates, store that.
	    var chAround = null, boxAround = null;
	    var ch = findFirst(function (ch) {
	      var box = measureCharPrepared(cm, preparedMeasure, ch);
	      box.top += widgetHeight; box.bottom += widgetHeight;
	      if (!boxIsAfter(box, x, y, false)) { return false }
	      if (box.top <= y && box.left <= x) {
	        chAround = ch;
	        boxAround = box;
	      }
	      return true
	    }, begin, end);

	    var baseX, sticky, outside = false;
	    // If a box around the coordinates was found, use that
	    if (boxAround) {
	      // Distinguish coordinates nearer to the left or right side of the box
	      var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr;
	      ch = chAround + (atStart ? 0 : 1);
	      sticky = atStart ? "after" : "before";
	      baseX = atLeft ? boxAround.left : boxAround.right;
	    } else {
	      // (Adjust for extended bound, if necessary.)
	      if (!ltr && (ch == end || ch == begin)) { ch++; }
	      // To determine which side to associate with, get the box to the
	      // left of the character and compare it's vertical position to the
	      // coordinates
	      sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" :
	        (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ?
	        "after" : "before";
	      // Now get accurate coordinates for this place, in order to get a
	      // base X position
	      var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure);
	      baseX = coords.left;
	      outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0;
	    }

	    ch = skipExtendingChars(lineObj.text, ch, 1);
	    return PosWithInfo(lineNo, ch, sticky, outside, x - baseX)
	  }

	  function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) {
	    // Bidi parts are sorted left-to-right, and in a non-line-wrapping
	    // situation, we can take this ordering to correspond to the visual
	    // ordering. This finds the first part whose end is after the given
	    // coordinates.
	    var index = findFirst(function (i) {
	      var part = order[i], ltr = part.level != 1;
	      return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"),
	                                     "line", lineObj, preparedMeasure), x, y, true)
	    }, 0, order.length - 1);
	    var part = order[index];
	    // If this isn't the first part, the part's start is also after
	    // the coordinates, and the coordinates aren't on the same line as
	    // that start, move one part back.
	    if (index > 0) {
	      var ltr = part.level != 1;
	      var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"),
	                               "line", lineObj, preparedMeasure);
	      if (boxIsAfter(start, x, y, true) && start.top > y)
	        { part = order[index - 1]; }
	    }
	    return part
	  }

	  function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) {
	    // In a wrapped line, rtl text on wrapping boundaries can do things
	    // that don't correspond to the ordering in our `order` array at
	    // all, so a binary search doesn't work, and we want to return a
	    // part that only spans one line so that the binary search in
	    // coordsCharInner is safe. As such, we first find the extent of the
	    // wrapped line, and then do a flat search in which we discard any
	    // spans that aren't on the line.
	    var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y);
	    var begin = ref.begin;
	    var end = ref.end;
	    if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; }
	    var part = null, closestDist = null;
	    for (var i = 0; i < order.length; i++) {
	      var p = order[i];
	      if (p.from >= end || p.to <= begin) { continue }
	      var ltr = p.level != 1;
	      var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right;
	      // Weigh against spans ending before this, so that they are only
	      // picked if nothing ends after
	      var dist = endX < x ? x - endX + 1e9 : endX - x;
	      if (!part || closestDist > dist) {
	        part = p;
	        closestDist = dist;
	      }
	    }
	    if (!part) { part = order[order.length - 1]; }
	    // Clip the part to the wrapped line.
	    if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; }
	    if (part.to > end) { part = {from: part.from, to: end, level: part.level}; }
	    return part
	  }

	  var measureText;
	  // Compute the default text height.
	  function textHeight(display) {
	    if (display.cachedTextHeight != null) { return display.cachedTextHeight }
	    if (measureText == null) {
	      measureText = elt("pre", null, "CodeMirror-line-like");
	      // Measure a bunch of lines, for browsers that compute
	      // fractional heights.
	      for (var i = 0; i < 49; ++i) {
	        measureText.appendChild(document.createTextNode("x"));
	        measureText.appendChild(elt("br"));
	      }
	      measureText.appendChild(document.createTextNode("x"));
	    }
	    removeChildrenAndAdd(display.measure, measureText);
	    var height = measureText.offsetHeight / 50;
	    if (height > 3) { display.cachedTextHeight = height; }
	    removeChildren(display.measure);
	    return height || 1
	  }

	  // Compute the default character width.
	  function charWidth(display) {
	    if (display.cachedCharWidth != null) { return display.cachedCharWidth }
	    var anchor = elt("span", "xxxxxxxxxx");
	    var pre = elt("pre", [anchor], "CodeMirror-line-like");
	    removeChildrenAndAdd(display.measure, pre);
	    var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
	    if (width > 2) { display.cachedCharWidth = width; }
	    return width || 10
	  }

	  // Do a bulk-read of the DOM positions and sizes needed to draw the
	  // view, so that we don't interleave reading and writing to the DOM.
	  function getDimensions(cm) {
	    var d = cm.display, left = {}, width = {};
	    var gutterLeft = d.gutters.clientLeft;
	    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
	      var id = cm.display.gutterSpecs[i].className;
	      left[id] = n.offsetLeft + n.clientLeft + gutterLeft;
	      width[id] = n.clientWidth;
	    }
	    return {fixedPos: compensateForHScroll(d),
	            gutterTotalWidth: d.gutters.offsetWidth,
	            gutterLeft: left,
	            gutterWidth: width,
	            wrapperWidth: d.wrapper.clientWidth}
	  }

	  // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
	  // but using getBoundingClientRect to get a sub-pixel-accurate
	  // result.
	  function compensateForHScroll(display) {
	    return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
	  }

	  // Returns a function that estimates the height of a line, to use as
	  // first approximation until the line becomes visible (and is thus
	  // properly measurable).
	  function estimateHeight(cm) {
	    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
	    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
	    return function (line) {
	      if (lineIsHidden(cm.doc, line)) { return 0 }

	      var widgetsHeight = 0;
	      if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
	        if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; }
	      } }

	      if (wrapping)
	        { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
	      else
	        { return widgetsHeight + th }
	    }
	  }

	  function estimateLineHeights(cm) {
	    var doc = cm.doc, est = estimateHeight(cm);
	    doc.iter(function (line) {
	      var estHeight = est(line);
	      if (estHeight != line.height) { updateLineHeight(line, estHeight); }
	    });
	  }

	  // Given a mouse event, find the corresponding position. If liberal
	  // is false, it checks whether a gutter or scrollbar was clicked,
	  // and returns null if it was. forRect is used by rectangular
	  // selections, and tries to estimate a character position even for
	  // coordinates beyond the right of the text.
	  function posFromMouse(cm, e, liberal, forRect) {
	    var display = cm.display;
	    if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }

	    var x, y, space = display.lineSpace.getBoundingClientRect();
	    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
	    try { x = e.clientX - space.left; y = e.clientY - space.top; }
	    catch (e$1) { return null }
	    var coords = coordsChar(cm, x, y), line;
	    if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
	      var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
	      coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
	    }
	    return coords
	  }

	  // Find the view element corresponding to a given line. Return null
	  // when the line isn't visible.
	  function findViewIndex(cm, n) {
	    if (n >= cm.display.viewTo) { return null }
	    n -= cm.display.viewFrom;
	    if (n < 0) { return null }
	    var view = cm.display.view;
	    for (var i = 0; i < view.length; i++) {
	      n -= view[i].size;
	      if (n < 0) { return i }
	    }
	  }

	  // Updates the display.view data structure for a given change to the
	  // document. From and to are in pre-change coordinates. Lendiff is
	  // the amount of lines added or subtracted by the change. This is
	  // used for changes that span multiple lines, or change the way
	  // lines are divided into visual lines. regLineChange (below)
	  // registers single-line changes.
	  function regChange(cm, from, to, lendiff) {
	    if (from == null) { from = cm.doc.first; }
	    if (to == null) { to = cm.doc.first + cm.doc.size; }
	    if (!lendiff) { lendiff = 0; }

	    var display = cm.display;
	    if (lendiff && to < display.viewTo &&
	        (display.updateLineNumbers == null || display.updateLineNumbers > from))
	      { display.updateLineNumbers = from; }

	    cm.curOp.viewChanged = true;

	    if (from >= display.viewTo) { // Change after
	      if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
	        { resetView(cm); }
	    } else if (to <= display.viewFrom) { // Change before
	      if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
	        resetView(cm);
	      } else {
	        display.viewFrom += lendiff;
	        display.viewTo += lendiff;
	      }
	    } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
	      resetView(cm);
	    } else if (from <= display.viewFrom) { // Top overlap
	      var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
	      if (cut) {
	        display.view = display.view.slice(cut.index);
	        display.viewFrom = cut.lineN;
	        display.viewTo += lendiff;
	      } else {
	        resetView(cm);
	      }
	    } else if (to >= display.viewTo) { // Bottom overlap
	      var cut$1 = viewCuttingPoint(cm, from, from, -1);
	      if (cut$1) {
	        display.view = display.view.slice(0, cut$1.index);
	        display.viewTo = cut$1.lineN;
	      } else {
	        resetView(cm);
	      }
	    } else { // Gap in the middle
	      var cutTop = viewCuttingPoint(cm, from, from, -1);
	      var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
	      if (cutTop && cutBot) {
	        display.view = display.view.slice(0, cutTop.index)
	          .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
	          .concat(display.view.slice(cutBot.index));
	        display.viewTo += lendiff;
	      } else {
	        resetView(cm);
	      }
	    }

	    var ext = display.externalMeasured;
	    if (ext) {
	      if (to < ext.lineN)
	        { ext.lineN += lendiff; }
	      else if (from < ext.lineN + ext.size)
	        { display.externalMeasured = null; }
	    }
	  }

	  // Register a change to a single line. Type must be one of "text",
	  // "gutter", "class", "widget"
	  function regLineChange(cm, line, type) {
	    cm.curOp.viewChanged = true;
	    var display = cm.display, ext = cm.display.externalMeasured;
	    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
	      { display.externalMeasured = null; }

	    if (line < display.viewFrom || line >= display.viewTo) { return }
	    var lineView = display.view[findViewIndex(cm, line)];
	    if (lineView.node == null) { return }
	    var arr = lineView.changes || (lineView.changes = []);
	    if (indexOf(arr, type) == -1) { arr.push(type); }
	  }

	  // Clear the view.
	  function resetView(cm) {
	    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
	    cm.display.view = [];
	    cm.display.viewOffset = 0;
	  }

	  function viewCuttingPoint(cm, oldN, newN, dir) {
	    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
	    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
	      { return {index: index, lineN: newN} }
	    var n = cm.display.viewFrom;
	    for (var i = 0; i < index; i++)
	      { n += view[i].size; }
	    if (n != oldN) {
	      if (dir > 0) {
	        if (index == view.length - 1) { return null }
	        diff = (n + view[index].size) - oldN;
	        index++;
	      } else {
	        diff = n - oldN;
	      }
	      oldN += diff; newN += diff;
	    }
	    while (visualLineNo(cm.doc, newN) != newN) {
	      if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
	      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
	      index += dir;
	    }
	    return {index: index, lineN: newN}
	  }

	  // Force the view to cover a given range, adding empty view element
	  // or clipping off existing ones as needed.
	  function adjustView(cm, from, to) {
	    var display = cm.display, view = display.view;
	    if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
	      display.view = buildViewArray(cm, from, to);
	      display.viewFrom = from;
	    } else {
	      if (display.viewFrom > from)
	        { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); }
	      else if (display.viewFrom < from)
	        { display.view = display.view.slice(findViewIndex(cm, from)); }
	      display.viewFrom = from;
	      if (display.viewTo < to)
	        { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); }
	      else if (display.viewTo > to)
	        { display.view = display.view.slice(0, findViewIndex(cm, to)); }
	    }
	    display.viewTo = to;
	  }

	  // Count the number of lines in the view whose DOM representation is
	  // out of date (or nonexistent).
	  function countDirtyView(cm) {
	    var view = cm.display.view, dirty = 0;
	    for (var i = 0; i < view.length; i++) {
	      var lineView = view[i];
	      if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; }
	    }
	    return dirty
	  }

	  function updateSelection(cm) {
	    cm.display.input.showSelection(cm.display.input.prepareSelection());
	  }

	  function prepareSelection(cm, primary) {
	    if ( primary === void 0 ) primary = true;

	    var doc = cm.doc, result = {};
	    var curFragment = result.cursors = document.createDocumentFragment();
	    var selFragment = result.selection = document.createDocumentFragment();

	    var customCursor = cm.options.$customCursor;
	    if (customCursor) { primary = true; }
	    for (var i = 0; i < doc.sel.ranges.length; i++) {
	      if (!primary && i == doc.sel.primIndex) { continue }
	      var range = doc.sel.ranges[i];
	      if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
	      var collapsed = range.empty();
	      if (customCursor) {
	        var head = customCursor(cm, range);
	        if (head) { drawSelectionCursor(cm, head, curFragment); }
	      } else if (collapsed || cm.options.showCursorWhenSelecting) {
	        drawSelectionCursor(cm, range.head, curFragment);
	      }
	      if (!collapsed)
	        { drawSelectionRange(cm, range, selFragment); }
	    }
	    return result
	  }

	  // Draws a cursor for the given range
	  function drawSelectionCursor(cm, head, output) {
	    var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);

	    var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
	    cursor.style.left = pos.left + "px";
	    cursor.style.top = pos.top + "px";
	    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";

	    if (/\bcm-fat-cursor\b/.test(cm.getWrapperElement().className)) {
	      var charPos = charCoords(cm, head, "div", null, null);
	      var width = charPos.right - charPos.left;
	      cursor.style.width = (width > 0 ? width : cm.defaultCharWidth()) + "px";
	    }

	    if (pos.other) {
	      // Secondary cursor, shown when on a 'jump' in bi-directional text
	      var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
	      otherCursor.style.display = "";
	      otherCursor.style.left = pos.other.left + "px";
	      otherCursor.style.top = pos.other.top + "px";
	      otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
	    }
	  }

	  function cmpCoords(a, b) { return a.top - b.top || a.left - b.left }

	  // Draws the given range as a highlighted selection
	  function drawSelectionRange(cm, range, output) {
	    var display = cm.display, doc = cm.doc;
	    var fragment = document.createDocumentFragment();
	    var padding = paddingH(cm.display), leftSide = padding.left;
	    var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
	    var docLTR = doc.direction == "ltr";

	    function add(left, top, width, bottom) {
	      if (top < 0) { top = 0; }
	      top = Math.round(top);
	      bottom = Math.round(bottom);
	      fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n                             top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n                             height: " + (bottom - top) + "px")));
	    }

	    function drawForLine(line, fromArg, toArg) {
	      var lineObj = getLine(doc, line);
	      var lineLen = lineObj.text.length;
	      var start, end;
	      function coords(ch, bias) {
	        return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
	      }

	      function wrapX(pos, dir, side) {
	        var extent = wrappedLineExtentChar(cm, lineObj, null, pos);
	        var prop = (dir == "ltr") == (side == "after") ? "left" : "right";
	        var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1);
	        return coords(ch, prop)[prop]
	      }

	      var order = getOrder(lineObj, doc.direction);
	      iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) {
	        var ltr = dir == "ltr";
	        var fromPos = coords(from, ltr ? "left" : "right");
	        var toPos = coords(to - 1, ltr ? "right" : "left");

	        var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen;
	        var first = i == 0, last = !order || i == order.length - 1;
	        if (toPos.top - fromPos.top <= 3) { // Single line
	          var openLeft = (docLTR ? openStart : openEnd) && first;
	          var openRight = (docLTR ? openEnd : openStart) && last;
	          var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left;
	          var right = openRight ? rightSide : (ltr ? toPos : fromPos).right;
	          add(left, fromPos.top, right - left, fromPos.bottom);
	        } else { // Multiple lines
	          var topLeft, topRight, botLeft, botRight;
	          if (ltr) {
	            topLeft = docLTR && openStart && first ? leftSide : fromPos.left;
	            topRight = docLTR ? rightSide : wrapX(from, dir, "before");
	            botLeft = docLTR ? leftSide : wrapX(to, dir, "after");
	            botRight = docLTR && openEnd && last ? rightSide : toPos.right;
	          } else {
	            topLeft = !docLTR ? leftSide : wrapX(from, dir, "before");
	            topRight = !docLTR && openStart && first ? rightSide : fromPos.right;
	            botLeft = !docLTR && openEnd && last ? leftSide : toPos.left;
	            botRight = !docLTR ? rightSide : wrapX(to, dir, "after");
	          }
	          add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom);
	          if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); }
	          add(botLeft, toPos.top, botRight - botLeft, toPos.bottom);
	        }

	        if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; }
	        if (cmpCoords(toPos, start) < 0) { start = toPos; }
	        if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; }
	        if (cmpCoords(toPos, end) < 0) { end = toPos; }
	      });
	      return {start: start, end: end}
	    }

	    var sFrom = range.from(), sTo = range.to();
	    if (sFrom.line == sTo.line) {
	      drawForLine(sFrom.line, sFrom.ch, sTo.ch);
	    } else {
	      var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
	      var singleVLine = visualLine(fromLine) == visualLine(toLine);
	      var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
	      var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
	      if (singleVLine) {
	        if (leftEnd.top < rightStart.top - 2) {
	          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
	          add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
	        } else {
	          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
	        }
	      }
	      if (leftEnd.bottom < rightStart.top)
	        { add(leftSide, leftEnd.bottom, null, rightStart.top); }
	    }

	    output.appendChild(fragment);
	  }

	  // Cursor-blinking
	  function restartBlink(cm) {
	    if (!cm.state.focused) { return }
	    var display = cm.display;
	    clearInterval(display.blinker);
	    var on = true;
	    display.cursorDiv.style.visibility = "";
	    if (cm.options.cursorBlinkRate > 0)
	      { display.blinker = setInterval(function () {
	        if (!cm.hasFocus()) { onBlur(cm); }
	        display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
	      }, cm.options.cursorBlinkRate); }
	    else if (cm.options.cursorBlinkRate < 0)
	      { display.cursorDiv.style.visibility = "hidden"; }
	  }

	  function ensureFocus(cm) {
	    if (!cm.hasFocus()) {
	      cm.display.input.focus();
	      if (!cm.state.focused) { onFocus(cm); }
	    }
	  }

	  function delayBlurEvent(cm) {
	    cm.state.delayingBlurEvent = true;
	    setTimeout(function () { if (cm.state.delayingBlurEvent) {
	      cm.state.delayingBlurEvent = false;
	      if (cm.state.focused) { onBlur(cm); }
	    } }, 100);
	  }

	  function onFocus(cm, e) {
	    if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; }

	    if (cm.options.readOnly == "nocursor") { return }
	    if (!cm.state.focused) {
	      signal(cm, "focus", cm, e);
	      cm.state.focused = true;
	      addClass(cm.display.wrapper, "CodeMirror-focused");
	      // This test prevents this from firing when a context
	      // menu is closed (since the input reset would kill the
	      // select-all detection hack)
	      if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
	        cm.display.input.reset();
	        if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730
	      }
	      cm.display.input.receivedFocus();
	    }
	    restartBlink(cm);
	  }
	  function onBlur(cm, e) {
	    if (cm.state.delayingBlurEvent) { return }

	    if (cm.state.focused) {
	      signal(cm, "blur", cm, e);
	      cm.state.focused = false;
	      rmClass(cm.display.wrapper, "CodeMirror-focused");
	    }
	    clearInterval(cm.display.blinker);
	    setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);
	  }

	  // Read the actual heights of the rendered lines, and update their
	  // stored heights to match.
	  function updateHeightsInViewport(cm) {
	    var display = cm.display;
	    var prevBottom = display.lineDiv.offsetTop;
	    var viewTop = Math.max(0, display.scroller.getBoundingClientRect().top);
	    var oldHeight = display.lineDiv.getBoundingClientRect().top;
	    var mustScroll = 0;
	    for (var i = 0; i < display.view.length; i++) {
	      var cur = display.view[i], wrapping = cm.options.lineWrapping;
	      var height = (void 0), width = 0;
	      if (cur.hidden) { continue }
	      oldHeight += cur.line.height;
	      if (ie && ie_version < 8) {
	        var bot = cur.node.offsetTop + cur.node.offsetHeight;
	        height = bot - prevBottom;
	        prevBottom = bot;
	      } else {
	        var box = cur.node.getBoundingClientRect();
	        height = box.bottom - box.top;
	        // Check that lines don't extend past the right of the current
	        // editor width
	        if (!wrapping && cur.text.firstChild)
	          { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; }
	      }
	      var diff = cur.line.height - height;
	      if (diff > .005 || diff < -.005) {
	        if (oldHeight < viewTop) { mustScroll -= diff; }
	        updateLineHeight(cur.line, height);
	        updateWidgetHeight(cur.line);
	        if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
	          { updateWidgetHeight(cur.rest[j]); } }
	      }
	      if (width > cm.display.sizerWidth) {
	        var chWidth = Math.ceil(width / charWidth(cm.display));
	        if (chWidth > cm.display.maxLineLength) {
	          cm.display.maxLineLength = chWidth;
	          cm.display.maxLine = cur.line;
	          cm.display.maxLineChanged = true;
	        }
	      }
	    }
	    if (Math.abs(mustScroll) > 2) { display.scroller.scrollTop += mustScroll; }
	  }

	  // Read and store the height of line widgets associated with the
	  // given line.
	  function updateWidgetHeight(line) {
	    if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) {
	      var w = line.widgets[i], parent = w.node.parentNode;
	      if (parent) { w.height = parent.offsetHeight; }
	    } }
	  }

	  // Compute the lines that are visible in a given viewport (defaults
	  // the the current scroll position). viewport may contain top,
	  // height, and ensure (see op.scrollToPos) properties.
	  function visibleLines(display, doc, viewport) {
	    var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
	    top = Math.floor(top - paddingTop(display));
	    var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;

	    var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
	    // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
	    // forces those lines into the viewport (if possible).
	    if (viewport && viewport.ensure) {
	      var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
	      if (ensureFrom < from) {
	        from = ensureFrom;
	        to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
	      } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
	        from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
	        to = ensureTo;
	      }
	    }
	    return {from: from, to: Math.max(to, from + 1)}
	  }

	  // SCROLLING THINGS INTO VIEW

	  // If an editor sits on the top or bottom of the window, partially
	  // scrolled out of view, this ensures that the cursor is visible.
	  function maybeScrollWindow(cm, rect) {
	    if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }

	    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
	    var doc = display.wrapper.ownerDocument;
	    if (rect.top + box.top < 0) { doScroll = true; }
	    else if (rect.bottom + box.top > (doc.defaultView.innerHeight || doc.documentElement.clientHeight)) { doScroll = false; }
	    if (doScroll != null && !phantom) {
	      var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n                         top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n                         height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n                         left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
	      cm.display.lineSpace.appendChild(scrollNode);
	      scrollNode.scrollIntoView(doScroll);
	      cm.display.lineSpace.removeChild(scrollNode);
	    }
	  }

	  // Scroll a given position into view (immediately), verifying that
	  // it actually became visible (as line heights are accurately
	  // measured, the position of something may 'drift' during drawing).
	  function scrollPosIntoView(cm, pos, end, margin) {
	    if (margin == null) { margin = 0; }
	    var rect;
	    if (!cm.options.lineWrapping && pos == end) {
	      // Set pos and end to the cursor positions around the character pos sticks to
	      // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
	      // If pos == Pos(_, 0, "before"), pos and end are unchanged
	      end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
	      pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
	    }
	    for (var limit = 0; limit < 5; limit++) {
	      var changed = false;
	      var coords = cursorCoords(cm, pos);
	      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
	      rect = {left: Math.min(coords.left, endCoords.left),
	              top: Math.min(coords.top, endCoords.top) - margin,
	              right: Math.max(coords.left, endCoords.left),
	              bottom: Math.max(coords.bottom, endCoords.bottom) + margin};
	      var scrollPos = calculateScrollPos(cm, rect);
	      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
	      if (scrollPos.scrollTop != null) {
	        updateScrollTop(cm, scrollPos.scrollTop);
	        if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }
	      }
	      if (scrollPos.scrollLeft != null) {
	        setScrollLeft(cm, scrollPos.scrollLeft);
	        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }
	      }
	      if (!changed) { break }
	    }
	    return rect
	  }

	  // Scroll a given set of coordinates into view (immediately).
	  function scrollIntoView(cm, rect) {
	    var scrollPos = calculateScrollPos(cm, rect);
	    if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); }
	    if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }
	  }

	  // Calculate a new scroll position needed to scroll the given
	  // rectangle into view. Returns an object with scrollTop and
	  // scrollLeft properties. When these are undefined, the
	  // vertical/horizontal position does not need to be adjusted.
	  function calculateScrollPos(cm, rect) {
	    var display = cm.display, snapMargin = textHeight(cm.display);
	    if (rect.top < 0) { rect.top = 0; }
	    var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
	    var screen = displayHeight(cm), result = {};
	    if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }
	    var docBottom = cm.doc.height + paddingVert(display);
	    var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;
	    if (rect.top < screentop) {
	      result.scrollTop = atTop ? 0 : rect.top;
	    } else if (rect.bottom > screentop + screen) {
	      var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
	      if (newTop != screentop) { result.scrollTop = newTop; }
	    }

	    var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth;
	    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace;
	    var screenw = displayWidth(cm) - display.gutters.offsetWidth;
	    var tooWide = rect.right - rect.left > screenw;
	    if (tooWide) { rect.right = rect.left + screenw; }
	    if (rect.left < 10)
	      { result.scrollLeft = 0; }
	    else if (rect.left < screenleft)
	      { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); }
	    else if (rect.right > screenw + screenleft - 3)
	      { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
	    return result
	  }

	  // Store a relative adjustment to the scroll position in the current
	  // operation (to be applied when the operation finishes).
	  function addToScrollTop(cm, top) {
	    if (top == null) { return }
	    resolveScrollToPos(cm);
	    cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
	  }

	  // Make sure that at the end of the operation the current cursor is
	  // shown.
	  function ensureCursorVisible(cm) {
	    resolveScrollToPos(cm);
	    var cur = cm.getCursor();
	    cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin};
	  }

	  function scrollToCoords(cm, x, y) {
	    if (x != null || y != null) { resolveScrollToPos(cm); }
	    if (x != null) { cm.curOp.scrollLeft = x; }
	    if (y != null) { cm.curOp.scrollTop = y; }
	  }

	  function scrollToRange(cm, range) {
	    resolveScrollToPos(cm);
	    cm.curOp.scrollToPos = range;
	  }

	  // When an operation has its scrollToPos property set, and another
	  // scroll action is applied before the end of the operation, this
	  // 'simulates' scrolling that position into view in a cheap way, so
	  // that the effect of intermediate scroll commands is not ignored.
	  function resolveScrollToPos(cm) {
	    var range = cm.curOp.scrollToPos;
	    if (range) {
	      cm.curOp.scrollToPos = null;
	      var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
	      scrollToCoordsRange(cm, from, to, range.margin);
	    }
	  }

	  function scrollToCoordsRange(cm, from, to, margin) {
	    var sPos = calculateScrollPos(cm, {
	      left: Math.min(from.left, to.left),
	      top: Math.min(from.top, to.top) - margin,
	      right: Math.max(from.right, to.right),
	      bottom: Math.max(from.bottom, to.bottom) + margin
	    });
	    scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop);
	  }

	  // Sync the scrollable area and scrollbars, ensure the viewport
	  // covers the visible area.
	  function updateScrollTop(cm, val) {
	    if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
	    if (!gecko) { updateDisplaySimple(cm, {top: val}); }
	    setScrollTop(cm, val, true);
	    if (gecko) { updateDisplaySimple(cm); }
	    startWorker(cm, 100);
	  }

	  function setScrollTop(cm, val, forceScroll) {
	    val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val));
	    if (cm.display.scroller.scrollTop == val && !forceScroll) { return }
	    cm.doc.scrollTop = val;
	    cm.display.scrollbars.setScrollTop(val);
	    if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }
	  }

	  // Sync scroller and scrollbar, ensure the gutter elements are
	  // aligned.
	  function setScrollLeft(cm, val, isScroller, forceScroll) {
	    val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth));
	    if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return }
	    cm.doc.scrollLeft = val;
	    alignHorizontally(cm);
	    if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }
	    cm.display.scrollbars.setScrollLeft(val);
	  }

	  // SCROLLBARS

	  // Prepare DOM reads needed to update the scrollbars. Done in one
	  // shot to minimize update/measure roundtrips.
	  function measureForScrollbars(cm) {
	    var d = cm.display, gutterW = d.gutters.offsetWidth;
	    var docH = Math.round(cm.doc.height + paddingVert(cm.display));
	    return {
	      clientHeight: d.scroller.clientHeight,
	      viewHeight: d.wrapper.clientHeight,
	      scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
	      viewWidth: d.wrapper.clientWidth,
	      barLeft: cm.options.fixedGutter ? gutterW : 0,
	      docHeight: docH,
	      scrollHeight: docH + scrollGap(cm) + d.barHeight,
	      nativeBarWidth: d.nativeBarWidth,
	      gutterWidth: gutterW
	    }
	  }

	  var NativeScrollbars = function(place, scroll, cm) {
	    this.cm = cm;
	    var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
	    var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
	    vert.tabIndex = horiz.tabIndex = -1;
	    place(vert); place(horiz);

	    on(vert, "scroll", function () {
	      if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); }
	    });
	    on(horiz, "scroll", function () {
	      if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); }
	    });

	    this.checkedZeroWidth = false;
	    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
	    if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; }
	  };

	  NativeScrollbars.prototype.update = function (measure) {
	    var needsH = measure.scrollWidth > measure.clientWidth + 1;
	    var needsV = measure.scrollHeight > measure.clientHeight + 1;
	    var sWidth = measure.nativeBarWidth;

	    if (needsV) {
	      this.vert.style.display = "block";
	      this.vert.style.bottom = needsH ? sWidth + "px" : "0";
	      var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
	      // A bug in IE8 can cause this value to be negative, so guard it.
	      this.vert.firstChild.style.height =
	        Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
	    } else {
	      this.vert.scrollTop = 0;
	      this.vert.style.display = "";
	      this.vert.firstChild.style.height = "0";
	    }

	    if (needsH) {
	      this.horiz.style.display = "block";
	      this.horiz.style.right = needsV ? sWidth + "px" : "0";
	      this.horiz.style.left = measure.barLeft + "px";
	      var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
	      this.horiz.firstChild.style.width =
	        Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
	    } else {
	      this.horiz.style.display = "";
	      this.horiz.firstChild.style.width = "0";
	    }

	    if (!this.checkedZeroWidth && measure.clientHeight > 0) {
	      if (sWidth == 0) { this.zeroWidthHack(); }
	      this.checkedZeroWidth = true;
	    }

	    return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
	  };

	  NativeScrollbars.prototype.setScrollLeft = function (pos) {
	    if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; }
	    if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); }
	  };

	  NativeScrollbars.prototype.setScrollTop = function (pos) {
	    if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; }
	    if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); }
	  };

	  NativeScrollbars.prototype.zeroWidthHack = function () {
	    var w = mac && !mac_geMountainLion ? "12px" : "18px";
	    this.horiz.style.height = this.vert.style.width = w;
	    this.horiz.style.visibility = this.vert.style.visibility = "hidden";
	    this.disableHoriz = new Delayed;
	    this.disableVert = new Delayed;
	  };

	  NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) {
	    bar.style.visibility = "";
	    function maybeDisable() {
	      // To find out whether the scrollbar is still visible, we
	      // check whether the element under the pixel in the bottom
	      // right corner of the scrollbar box is the scrollbar box
	      // itself (when the bar is still visible) or its filler child
	      // (when the bar is hidden). If it is still visible, we keep
	      // it enabled, if it's hidden, we disable pointer events.
	      var box = bar.getBoundingClientRect();
	      var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)
	          : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1);
	      if (elt != bar) { bar.style.visibility = "hidden"; }
	      else { delay.set(1000, maybeDisable); }
	    }
	    delay.set(1000, maybeDisable);
	  };

	  NativeScrollbars.prototype.clear = function () {
	    var parent = this.horiz.parentNode;
	    parent.removeChild(this.horiz);
	    parent.removeChild(this.vert);
	  };

	  var NullScrollbars = function () {};

	  NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
	  NullScrollbars.prototype.setScrollLeft = function () {};
	  NullScrollbars.prototype.setScrollTop = function () {};
	  NullScrollbars.prototype.clear = function () {};

	  function updateScrollbars(cm, measure) {
	    if (!measure) { measure = measureForScrollbars(cm); }
	    var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
	    updateScrollbarsInner(cm, measure);
	    for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
	      if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
	        { updateHeightsInViewport(cm); }
	      updateScrollbarsInner(cm, measureForScrollbars(cm));
	      startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
	    }
	  }

	  // Re-synchronize the fake scrollbars with the actual size of the
	  // content.
	  function updateScrollbarsInner(cm, measure) {
	    var d = cm.display;
	    var sizes = d.scrollbars.update(measure);

	    d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
	    d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
	    d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent";

	    if (sizes.right && sizes.bottom) {
	      d.scrollbarFiller.style.display = "block";
	      d.scrollbarFiller.style.height = sizes.bottom + "px";
	      d.scrollbarFiller.style.width = sizes.right + "px";
	    } else { d.scrollbarFiller.style.display = ""; }
	    if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
	      d.gutterFiller.style.display = "block";
	      d.gutterFiller.style.height = sizes.bottom + "px";
	      d.gutterFiller.style.width = measure.gutterWidth + "px";
	    } else { d.gutterFiller.style.display = ""; }
	  }

	  var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};

	  function initScrollbars(cm) {
	    if (cm.display.scrollbars) {
	      cm.display.scrollbars.clear();
	      if (cm.display.scrollbars.addClass)
	        { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
	    }

	    cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
	      cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
	      // Prevent clicks in the scrollbars from killing focus
	      on(node, "mousedown", function () {
	        if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); }
	      });
	      node.setAttribute("cm-not-content", "true");
	    }, function (pos, axis) {
	      if (axis == "horizontal") { setScrollLeft(cm, pos); }
	      else { updateScrollTop(cm, pos); }
	    }, cm);
	    if (cm.display.scrollbars.addClass)
	      { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
	  }

	  // Operations are used to wrap a series of changes to the editor
	  // state in such a way that each change won't have to update the
	  // cursor and display (which would be awkward, slow, and
	  // error-prone). Instead, display updates are batched and then all
	  // combined and executed at once.

	  var nextOpId = 0;
	  // Start a new operation.
	  function startOperation(cm) {
	    cm.curOp = {
	      cm: cm,
	      viewChanged: false,      // Flag that indicates that lines might need to be redrawn
	      startHeight: cm.doc.height, // Used to detect need to update scrollbar
	      forceUpdate: false,      // Used to force a redraw
	      updateInput: 0,       // Whether to reset the input textarea
	      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)
	      changeObjs: null,        // Accumulated changes, for firing change events
	      cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
	      cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
	      selectionChanged: false, // Whether the selection needs to be redrawn
	      updateMaxLine: false,    // Set when the widest line needs to be determined anew
	      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
	      scrollToPos: null,       // Used to scroll to a specific position
	      focus: false,
	      id: ++nextOpId,          // Unique ID
	      markArrays: null         // Used by addMarkedSpan
	    };
	    pushOperation(cm.curOp);
	  }

	  // Finish an operation, updating the display and signalling delayed events
	  function endOperation(cm) {
	    var op = cm.curOp;
	    if (op) { finishOperation(op, function (group) {
	      for (var i = 0; i < group.ops.length; i++)
	        { group.ops[i].cm.curOp = null; }
	      endOperations(group);
	    }); }
	  }

	  // The DOM updates done when an operation finishes are batched so
	  // that the minimum number of relayouts are required.
	  function endOperations(group) {
	    var ops = group.ops;
	    for (var i = 0; i < ops.length; i++) // Read DOM
	      { endOperation_R1(ops[i]); }
	    for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
	      { endOperation_W1(ops[i$1]); }
	    for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
	      { endOperation_R2(ops[i$2]); }
	    for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
	      { endOperation_W2(ops[i$3]); }
	    for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
	      { endOperation_finish(ops[i$4]); }
	  }

	  function endOperation_R1(op) {
	    var cm = op.cm, display = cm.display;
	    maybeClipScrollbars(cm);
	    if (op.updateMaxLine) { findMaxLine(cm); }

	    op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
	      op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
	                         op.scrollToPos.to.line >= display.viewTo) ||
	      display.maxLineChanged && cm.options.lineWrapping;
	    op.update = op.mustUpdate &&
	      new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
	  }

	  function endOperation_W1(op) {
	    op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
	  }

	  function endOperation_R2(op) {
	    var cm = op.cm, display = cm.display;
	    if (op.updatedDisplay) { updateHeightsInViewport(cm); }

	    op.barMeasure = measureForScrollbars(cm);

	    // If the max line changed since it was last measured, measure it,
	    // and ensure the document's width matches it.
	    // updateDisplay_W2 will use these properties to do the actual resizing
	    if (display.maxLineChanged && !cm.options.lineWrapping) {
	      op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
	      cm.display.sizerWidth = op.adjustWidthTo;
	      op.barMeasure.scrollWidth =
	        Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
	      op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
	    }

	    if (op.updatedDisplay || op.selectionChanged)
	      { op.preparedSelection = display.input.prepareSelection(); }
	  }

	  function endOperation_W2(op) {
	    var cm = op.cm;

	    if (op.adjustWidthTo != null) {
	      cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
	      if (op.maxScrollLeft < cm.doc.scrollLeft)
	        { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); }
	      cm.display.maxLineChanged = false;
	    }

	    var takeFocus = op.focus && op.focus == activeElt(doc(cm));
	    if (op.preparedSelection)
	      { cm.display.input.showSelection(op.preparedSelection, takeFocus); }
	    if (op.updatedDisplay || op.startHeight != cm.doc.height)
	      { updateScrollbars(cm, op.barMeasure); }
	    if (op.updatedDisplay)
	      { setDocumentHeight(cm, op.barMeasure); }

	    if (op.selectionChanged) { restartBlink(cm); }

	    if (cm.state.focused && op.updateInput)
	      { cm.display.input.reset(op.typing); }
	    if (takeFocus) { ensureFocus(op.cm); }
	  }

	  function endOperation_finish(op) {
	    var cm = op.cm, display = cm.display, doc = cm.doc;

	    if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); }

	    // Abort mouse wheel delta measurement, when scrolling explicitly
	    if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
	      { display.wheelStartX = display.wheelStartY = null; }

	    // Propagate the scroll position to the actual DOM scroller
	    if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); }

	    if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); }
	    // If we need to scroll a specific position into view, do so.
	    if (op.scrollToPos) {
	      var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
	                                   clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
	      maybeScrollWindow(cm, rect);
	    }

	    // Fire events for markers that are hidden/unidden by editing or
	    // undoing
	    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
	    if (hidden) { for (var i = 0; i < hidden.length; ++i)
	      { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } }
	    if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
	      { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } }

	    if (display.wrapper.offsetHeight)
	      { doc.scrollTop = cm.display.scroller.scrollTop; }

	    // Fire change events, and delayed event handlers
	    if (op.changeObjs)
	      { signal(cm, "changes", cm, op.changeObjs); }
	    if (op.update)
	      { op.update.finish(); }
	  }

	  // Run the given function in an operation
	  function runInOp(cm, f) {
	    if (cm.curOp) { return f() }
	    startOperation(cm);
	    try { return f() }
	    finally { endOperation(cm); }
	  }
	  // Wraps a function in an operation. Returns the wrapped function.
	  function operation(cm, f) {
	    return function() {
	      if (cm.curOp) { return f.apply(cm, arguments) }
	      startOperation(cm);
	      try { return f.apply(cm, arguments) }
	      finally { endOperation(cm); }
	    }
	  }
	  // Used to add methods to editor and doc instances, wrapping them in
	  // operations.
	  function methodOp(f) {
	    return function() {
	      if (this.curOp) { return f.apply(this, arguments) }
	      startOperation(this);
	      try { return f.apply(this, arguments) }
	      finally { endOperation(this); }
	    }
	  }
	  function docMethodOp(f) {
	    return function() {
	      var cm = this.cm;
	      if (!cm || cm.curOp) { return f.apply(this, arguments) }
	      startOperation(cm);
	      try { return f.apply(this, arguments) }
	      finally { endOperation(cm); }
	    }
	  }

	  // HIGHLIGHT WORKER

	  function startWorker(cm, time) {
	    if (cm.doc.highlightFrontier < cm.display.viewTo)
	      { cm.state.highlight.set(time, bind(highlightWorker, cm)); }
	  }

	  function highlightWorker(cm) {
	    var doc = cm.doc;
	    if (doc.highlightFrontier >= cm.display.viewTo) { return }
	    var end = +new Date + cm.options.workTime;
	    var context = getContextBefore(cm, doc.highlightFrontier);
	    var changedLines = [];

	    doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
	      if (context.line >= cm.display.viewFrom) { // Visible
	        var oldStyles = line.styles;
	        var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null;
	        var highlighted = highlightLine(cm, line, context, true);
	        if (resetState) { context.state = resetState; }
	        line.styles = highlighted.styles;
	        var oldCls = line.styleClasses, newCls = highlighted.classes;
	        if (newCls) { line.styleClasses = newCls; }
	        else if (oldCls) { line.styleClasses = null; }
	        var ischange = !oldStyles || oldStyles.length != line.styles.length ||
	          oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
	        for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; }
	        if (ischange) { changedLines.push(context.line); }
	        line.stateAfter = context.save();
	        context.nextLine();
	      } else {
	        if (line.text.length <= cm.options.maxHighlightLength)
	          { processLine(cm, line.text, context); }
	        line.stateAfter = context.line % 5 == 0 ? context.save() : null;
	        context.nextLine();
	      }
	      if (+new Date > end) {
	        startWorker(cm, cm.options.workDelay);
	        return true
	      }
	    });
	    doc.highlightFrontier = context.line;
	    doc.modeFrontier = Math.max(doc.modeFrontier, context.line);
	    if (changedLines.length) { runInOp(cm, function () {
	      for (var i = 0; i < changedLines.length; i++)
	        { regLineChange(cm, changedLines[i], "text"); }
	    }); }
	  }

	  // DISPLAY DRAWING

	  var DisplayUpdate = function(cm, viewport, force) {
	    var display = cm.display;

	    this.viewport = viewport;
	    // Store some values that we'll need later (but don't want to force a relayout for)
	    this.visible = visibleLines(display, cm.doc, viewport);
	    this.editorIsHidden = !display.wrapper.offsetWidth;
	    this.wrapperHeight = display.wrapper.clientHeight;
	    this.wrapperWidth = display.wrapper.clientWidth;
	    this.oldDisplayWidth = displayWidth(cm);
	    this.force = force;
	    this.dims = getDimensions(cm);
	    this.events = [];
	  };

	  DisplayUpdate.prototype.signal = function (emitter, type) {
	    if (hasHandler(emitter, type))
	      { this.events.push(arguments); }
	  };
	  DisplayUpdate.prototype.finish = function () {
	    for (var i = 0; i < this.events.length; i++)
	      { signal.apply(null, this.events[i]); }
	  };

	  function maybeClipScrollbars(cm) {
	    var display = cm.display;
	    if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
	      display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
	      display.heightForcer.style.height = scrollGap(cm) + "px";
	      display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
	      display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
	      display.scrollbarsClipped = true;
	    }
	  }

	  function selectionSnapshot(cm) {
	    if (cm.hasFocus()) { return null }
	    var active = activeElt(doc(cm));
	    if (!active || !contains(cm.display.lineDiv, active)) { return null }
	    var result = {activeElt: active};
	    if (window.getSelection) {
	      var sel = win(cm).getSelection();
	      if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {
	        result.anchorNode = sel.anchorNode;
	        result.anchorOffset = sel.anchorOffset;
	        result.focusNode = sel.focusNode;
	        result.focusOffset = sel.focusOffset;
	      }
	    }
	    return result
	  }

	  function restoreSelection(snapshot) {
	    if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt(snapshot.activeElt.ownerDocument)) { return }
	    snapshot.activeElt.focus();
	    if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) &&
	        snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
	      var doc = snapshot.activeElt.ownerDocument;
	      var sel = doc.defaultView.getSelection(), range = doc.createRange();
	      range.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
	      range.collapse(false);
	      sel.removeAllRanges();
	      sel.addRange(range);
	      sel.extend(snapshot.focusNode, snapshot.focusOffset);
	    }
	  }

	  // Does the actual updating of the line display. Bails out
	  // (returning false) when there is nothing to be done and forced is
	  // false.
	  function updateDisplayIfNeeded(cm, update) {
	    var display = cm.display, doc = cm.doc;

	    if (update.editorIsHidden) {
	      resetView(cm);
	      return false
	    }

	    // Bail out if the visible area is already rendered and nothing changed.
	    if (!update.force &&
	        update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
	        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
	        display.renderedView == display.view && countDirtyView(cm) == 0)
	      { return false }

	    if (maybeUpdateLineNumberWidth(cm)) {
	      resetView(cm);
	      update.dims = getDimensions(cm);
	    }

	    // Compute a suitable new viewport (from & to)
	    var end = doc.first + doc.size;
	    var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
	    var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
	    if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); }
	    if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); }
	    if (sawCollapsedSpans) {
	      from = visualLineNo(cm.doc, from);
	      to = visualLineEndNo(cm.doc, to);
	    }

	    var different = from != display.viewFrom || to != display.viewTo ||
	      display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
	    adjustView(cm, from, to);

	    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
	    // Position the mover div to align with the current scroll position
	    cm.display.mover.style.top = display.viewOffset + "px";

	    var toUpdate = countDirtyView(cm);
	    if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
	        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
	      { return false }

	    // For big changes, we hide the enclosing element during the
	    // update, since that speeds up the operations on most browsers.
	    var selSnapshot = selectionSnapshot(cm);
	    if (toUpdate > 4) { display.lineDiv.style.display = "none"; }
	    patchDisplay(cm, display.updateLineNumbers, update.dims);
	    if (toUpdate > 4) { display.lineDiv.style.display = ""; }
	    display.renderedView = display.view;
	    // There might have been a widget with a focused element that got
	    // hidden or updated, if so re-focus it.
	    restoreSelection(selSnapshot);

	    // Prevent selection and cursors from interfering with the scroll
	    // width and height.
	    removeChildren(display.cursorDiv);
	    removeChildren(display.selectionDiv);
	    display.gutters.style.height = display.sizer.style.minHeight = 0;

	    if (different) {
	      display.lastWrapHeight = update.wrapperHeight;
	      display.lastWrapWidth = update.wrapperWidth;
	      startWorker(cm, 400);
	    }

	    display.updateLineNumbers = null;

	    return true
	  }

	  function postUpdateDisplay(cm, update) {
	    var viewport = update.viewport;

	    for (var first = true;; first = false) {
	      if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
	        // Clip forced viewport to actual scrollable area.
	        if (viewport && viewport.top != null)
	          { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; }
	        // Updated line heights might result in the drawn area not
	        // actually covering the viewport. Keep looping until it does.
	        update.visible = visibleLines(cm.display, cm.doc, viewport);
	        if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
	          { break }
	      } else if (first) {
	        update.visible = visibleLines(cm.display, cm.doc, viewport);
	      }
	      if (!updateDisplayIfNeeded(cm, update)) { break }
	      updateHeightsInViewport(cm);
	      var barMeasure = measureForScrollbars(cm);
	      updateSelection(cm);
	      updateScrollbars(cm, barMeasure);
	      setDocumentHeight(cm, barMeasure);
	      update.force = false;
	    }

	    update.signal(cm, "update", cm);
	    if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
	      update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
	      cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
	    }
	  }

	  function updateDisplaySimple(cm, viewport) {
	    var update = new DisplayUpdate(cm, viewport);
	    if (updateDisplayIfNeeded(cm, update)) {
	      updateHeightsInViewport(cm);
	      postUpdateDisplay(cm, update);
	      var barMeasure = measureForScrollbars(cm);
	      updateSelection(cm);
	      updateScrollbars(cm, barMeasure);
	      setDocumentHeight(cm, barMeasure);
	      update.finish();
	    }
	  }

	  // Sync the actual display DOM structure with display.view, removing
	  // nodes for lines that are no longer in view, and creating the ones
	  // that are not there yet, and updating the ones that are out of
	  // date.
	  function patchDisplay(cm, updateNumbersFrom, dims) {
	    var display = cm.display, lineNumbers = cm.options.lineNumbers;
	    var container = display.lineDiv, cur = container.firstChild;

	    function rm(node) {
	      var next = node.nextSibling;
	      // Works around a throw-scroll bug in OS X Webkit
	      if (webkit && mac && cm.display.currentWheelTarget == node)
	        { node.style.display = "none"; }
	      else
	        { node.parentNode.removeChild(node); }
	      return next
	    }

	    var view = display.view, lineN = display.viewFrom;
	    // Loop over the elements in the view, syncing cur (the DOM nodes
	    // in display.lineDiv) with the view as we go.
	    for (var i = 0; i < view.length; i++) {
	      var lineView = view[i];
	      if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
	        var node = buildLineElement(cm, lineView, lineN, dims);
	        container.insertBefore(node, cur);
	      } else { // Already drawn
	        while (cur != lineView.node) { cur = rm(cur); }
	        var updateNumber = lineNumbers && updateNumbersFrom != null &&
	          updateNumbersFrom <= lineN && lineView.lineNumber;
	        if (lineView.changes) {
	          if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; }
	          updateLineForChanges(cm, lineView, lineN, dims);
	        }
	        if (updateNumber) {
	          removeChildren(lineView.lineNumber);
	          lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
	        }
	        cur = lineView.node.nextSibling;
	      }
	      lineN += lineView.size;
	    }
	    while (cur) { cur = rm(cur); }
	  }

	  function updateGutterSpace(display) {
	    var width = display.gutters.offsetWidth;
	    display.sizer.style.marginLeft = width + "px";
	    // Send an event to consumers responding to changes in gutter width.
	    signalLater(display, "gutterChanged", display);
	  }

	  function setDocumentHeight(cm, measure) {
	    cm.display.sizer.style.minHeight = measure.docHeight + "px";
	    cm.display.heightForcer.style.top = measure.docHeight + "px";
	    cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px";
	  }

	  // Re-align line numbers and gutter marks to compensate for
	  // horizontal scrolling.
	  function alignHorizontally(cm) {
	    var display = cm.display, view = display.view;
	    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
	    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
	    var gutterW = display.gutters.offsetWidth, left = comp + "px";
	    for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
	      if (cm.options.fixedGutter) {
	        if (view[i].gutter)
	          { view[i].gutter.style.left = left; }
	        if (view[i].gutterBackground)
	          { view[i].gutterBackground.style.left = left; }
	      }
	      var align = view[i].alignable;
	      if (align) { for (var j = 0; j < align.length; j++)
	        { align[j].style.left = left; } }
	    } }
	    if (cm.options.fixedGutter)
	      { display.gutters.style.left = (comp + gutterW) + "px"; }
	  }

	  // Used to ensure that the line number gutter is still the right
	  // size for the current document size. Returns true when an update
	  // is needed.
	  function maybeUpdateLineNumberWidth(cm) {
	    if (!cm.options.lineNumbers) { return false }
	    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
	    if (last.length != display.lineNumChars) {
	      var test = display.measure.appendChild(elt("div", [elt("div", last)],
	                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
	      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
	      display.lineGutter.style.width = "";
	      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
	      display.lineNumWidth = display.lineNumInnerWidth + padding;
	      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
	      display.lineGutter.style.width = display.lineNumWidth + "px";
	      updateGutterSpace(cm.display);
	      return true
	    }
	    return false
	  }

	  function getGutters(gutters, lineNumbers) {
	    var result = [], sawLineNumbers = false;
	    for (var i = 0; i < gutters.length; i++) {
	      var name = gutters[i], style = null;
	      if (typeof name != "string") { style = name.style; name = name.className; }
	      if (name == "CodeMirror-linenumbers") {
	        if (!lineNumbers) { continue }
	        else { sawLineNumbers = true; }
	      }
	      result.push({className: name, style: style});
	    }
	    if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); }
	    return result
	  }

	  // Rebuild the gutter elements, ensure the margin to the left of the
	  // code matches their width.
	  function renderGutters(display) {
	    var gutters = display.gutters, specs = display.gutterSpecs;
	    removeChildren(gutters);
	    display.lineGutter = null;
	    for (var i = 0; i < specs.length; ++i) {
	      var ref = specs[i];
	      var className = ref.className;
	      var style = ref.style;
	      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className));
	      if (style) { gElt.style.cssText = style; }
	      if (className == "CodeMirror-linenumbers") {
	        display.lineGutter = gElt;
	        gElt.style.width = (display.lineNumWidth || 1) + "px";
	      }
	    }
	    gutters.style.display = specs.length ? "" : "none";
	    updateGutterSpace(display);
	  }

	  function updateGutters(cm) {
	    renderGutters(cm.display);
	    regChange(cm);
	    alignHorizontally(cm);
	  }

	  // The display handles the DOM integration, both for input reading
	  // and content drawing. It holds references to DOM nodes and
	  // display-related state.

	  function Display(place, doc, input, options) {
	    var d = this;
	    this.input = input;

	    // Covers bottom-right square when both scrollbars are present.
	    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
	    d.scrollbarFiller.setAttribute("cm-not-content", "true");
	    // Covers bottom of gutter when coverGutterNextToScrollbar is on
	    // and h scrollbar is present.
	    d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
	    d.gutterFiller.setAttribute("cm-not-content", "true");
	    // Will contain the actual code, positioned to cover the viewport.
	    d.lineDiv = eltP("div", null, "CodeMirror-code");
	    // Elements are added to these to represent selection and cursors.
	    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
	    d.cursorDiv = elt("div", null, "CodeMirror-cursors");
	    // A visibility: hidden element used to find the size of things.
	    d.measure = elt("div", null, "CodeMirror-measure");
	    // When lines outside of the viewport are measured, they are drawn in this.
	    d.lineMeasure = elt("div", null, "CodeMirror-measure");
	    // Wraps everything that needs to exist inside the vertically-padded coordinate system
	    d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
	                      null, "position: relative; outline: none");
	    var lines = eltP("div", [d.lineSpace], "CodeMirror-lines");
	    // Moved around its parent to cover visible view.
	    d.mover = elt("div", [lines], null, "position: relative");
	    // Set to the height of the document, allowing scrolling.
	    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
	    d.sizerWidth = null;
	    // Behavior of elts with overflow: auto and padding is
	    // inconsistent across browsers. This is used to ensure the
	    // scrollable area is big enough.
	    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
	    // Will contain the gutters, if any.
	    d.gutters = elt("div", null, "CodeMirror-gutters");
	    d.lineGutter = null;
	    // Actual scrollable element.
	    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
	    d.scroller.setAttribute("tabIndex", "-1");
	    // The element in which the editor lives.
	    d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");

	    // This attribute is respected by automatic translation systems such as Google Translate,
	    // and may also be respected by tools used by human translators.
	    d.wrapper.setAttribute('translate', 'no');

	    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
	    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
	    if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }

	    if (place) {
	      if (place.appendChild) { place.appendChild(d.wrapper); }
	      else { place(d.wrapper); }
	    }

	    // Current rendered range (may be bigger than the view window).
	    d.viewFrom = d.viewTo = doc.first;
	    d.reportedViewFrom = d.reportedViewTo = doc.first;
	    // Information about the rendered lines.
	    d.view = [];
	    d.renderedView = null;
	    // Holds info about a single rendered line when it was rendered
	    // for measurement, while not in view.
	    d.externalMeasured = null;
	    // Empty space (in pixels) above the view
	    d.viewOffset = 0;
	    d.lastWrapHeight = d.lastWrapWidth = 0;
	    d.updateLineNumbers = null;

	    d.nativeBarWidth = d.barHeight = d.barWidth = 0;
	    d.scrollbarsClipped = false;

	    // Used to only resize the line number gutter when necessary (when
	    // the amount of lines crosses a boundary that makes its width change)
	    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
	    // Set to true when a non-horizontal-scrolling line widget is
	    // added. As an optimization, line widget aligning is skipped when
	    // this is false.
	    d.alignWidgets = false;

	    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;

	    // Tracks the maximum line length so that the horizontal scrollbar
	    // can be kept static when scrolling.
	    d.maxLine = null;
	    d.maxLineLength = 0;
	    d.maxLineChanged = false;

	    // Used for measuring wheel scrolling granularity
	    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;

	    // True when shift is held down.
	    d.shift = false;

	    // Used to track whether anything happened since the context menu
	    // was opened.
	    d.selForContextMenu = null;

	    d.activeTouch = null;

	    d.gutterSpecs = getGutters(options.gutters, options.lineNumbers);
	    renderGutters(d);

	    input.init(d);
	  }

	  // Since the delta values reported on mouse wheel events are
	  // unstandardized between browsers and even browser versions, and
	  // generally horribly unpredictable, this code starts by measuring
	  // the scroll effect that the first few mouse wheel events have,
	  // and, from that, detects the way it can convert deltas to pixel
	  // offsets afterwards.
	  //
	  // The reason we want to know the amount a wheel event will scroll
	  // is that it gives us a chance to update the display before the
	  // actual scrolling happens, reducing flickering.

	  var wheelSamples = 0, wheelPixelsPerUnit = null;
	  // Fill in a browser-detected starting value on browsers where we
	  // know one. These don't have to be accurate -- the result of them
	  // being wrong would just be a slight flicker on the first wheel
	  // scroll (if it is large enough).
	  if (ie) { wheelPixelsPerUnit = -.53; }
	  else if (gecko) { wheelPixelsPerUnit = 15; }
	  else if (chrome) { wheelPixelsPerUnit = -.7; }
	  else if (safari) { wheelPixelsPerUnit = -1/3; }

	  function wheelEventDelta(e) {
	    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
	    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }
	    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }
	    else if (dy == null) { dy = e.wheelDelta; }
	    return {x: dx, y: dy}
	  }
	  function wheelEventPixels(e) {
	    var delta = wheelEventDelta(e);
	    delta.x *= wheelPixelsPerUnit;
	    delta.y *= wheelPixelsPerUnit;
	    return delta
	  }

	  function onScrollWheel(cm, e) {
	    // On Chrome 102, viewport updates somehow stop wheel-based
	    // scrolling. Turning off pointer events during the scroll seems
	    // to avoid the issue.
	    if (chrome && chrome_version == 102) {
	      if (cm.display.chromeScrollHack == null) { cm.display.sizer.style.pointerEvents = "none"; }
	      else { clearTimeout(cm.display.chromeScrollHack); }
	      cm.display.chromeScrollHack = setTimeout(function () {
	        cm.display.chromeScrollHack = null;
	        cm.display.sizer.style.pointerEvents = "";
	      }, 100);
	    }
	    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
	    var pixelsPerUnit = wheelPixelsPerUnit;
	    if (e.deltaMode === 0) {
	      dx = e.deltaX;
	      dy = e.deltaY;
	      pixelsPerUnit = 1;
	    }

	    var display = cm.display, scroll = display.scroller;
	    // Quit if there's nothing to scroll here
	    var canScrollX = scroll.scrollWidth > scroll.clientWidth;
	    var canScrollY = scroll.scrollHeight > scroll.clientHeight;
	    if (!(dx && canScrollX || dy && canScrollY)) { return }

	    // Webkit browsers on OS X abort momentum scrolls when the target
	    // of the scroll event is removed from the scrollable element.
	    // This hack (see related code in patchDisplay) makes sure the
	    // element is kept around.
	    if (dy && mac && webkit) {
	      outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
	        for (var i = 0; i < view.length; i++) {
	          if (view[i].node == cur) {
	            cm.display.currentWheelTarget = cur;
	            break outer
	          }
	        }
	      }
	    }

	    // On some browsers, horizontal scrolling will cause redraws to
	    // happen before the gutter has been realigned, causing it to
	    // wriggle around in a most unseemly way. When we have an
	    // estimated pixels/delta value, we just handle horizontal
	    // scrolling entirely here. It'll be slightly off from native, but
	    // better than glitching out.
	    if (dx && !gecko && !presto && pixelsPerUnit != null) {
	      if (dy && canScrollY)
	        { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * pixelsPerUnit)); }
	      setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * pixelsPerUnit));
	      // Only prevent default scrolling if vertical scrolling is
	      // actually possible. Otherwise, it causes vertical scroll
	      // jitter on OSX trackpads when deltaX is small and deltaY
	      // is large (issue #3579)
	      if (!dy || (dy && canScrollY))
	        { e_preventDefault(e); }
	      display.wheelStartX = null; // Abort measurement, if in progress
	      return
	    }

	    // 'Project' the visible viewport to cover the area that is being
	    // scrolled into view (if we know enough to estimate it).
	    if (dy && pixelsPerUnit != null) {
	      var pixels = dy * pixelsPerUnit;
	      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
	      if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
	      else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
	      updateDisplaySimple(cm, {top: top, bottom: bot});
	    }

	    if (wheelSamples < 20 && e.deltaMode !== 0) {
	      if (display.wheelStartX == null) {
	        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
	        display.wheelDX = dx; display.wheelDY = dy;
	        setTimeout(function () {
	          if (display.wheelStartX == null) { return }
	          var movedX = scroll.scrollLeft - display.wheelStartX;
	          var movedY = scroll.scrollTop - display.wheelStartY;
	          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
	            (movedX && display.wheelDX && movedX / display.wheelDX);
	          display.wheelStartX = display.wheelStartY = null;
	          if (!sample) { return }
	          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
	          ++wheelSamples;
	        }, 200);
	      } else {
	        display.wheelDX += dx; display.wheelDY += dy;
	      }
	    }
	  }

	  // Selection objects are immutable. A new one is created every time
	  // the selection changes. A selection is one or more non-overlapping
	  // (and non-touching) ranges, sorted, and an integer that indicates
	  // which one is the primary selection (the one that's scrolled into
	  // view, that getCursor returns, etc).
	  var Selection = function(ranges, primIndex) {
	    this.ranges = ranges;
	    this.primIndex = primIndex;
	  };

	  Selection.prototype.primary = function () { return this.ranges[this.primIndex] };

	  Selection.prototype.equals = function (other) {
	    if (other == this) { return true }
	    if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
	    for (var i = 0; i < this.ranges.length; i++) {
	      var here = this.ranges[i], there = other.ranges[i];
	      if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false }
	    }
	    return true
	  };

	  Selection.prototype.deepCopy = function () {
	    var out = [];
	    for (var i = 0; i < this.ranges.length; i++)
	      { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); }
	    return new Selection(out, this.primIndex)
	  };

	  Selection.prototype.somethingSelected = function () {
	    for (var i = 0; i < this.ranges.length; i++)
	      { if (!this.ranges[i].empty()) { return true } }
	    return false
	  };

	  Selection.prototype.contains = function (pos, end) {
	    if (!end) { end = pos; }
	    for (var i = 0; i < this.ranges.length; i++) {
	      var range = this.ranges[i];
	      if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
	        { return i }
	    }
	    return -1
	  };

	  var Range = function(anchor, head) {
	    this.anchor = anchor; this.head = head;
	  };

	  Range.prototype.from = function () { return minPos(this.anchor, this.head) };
	  Range.prototype.to = function () { return maxPos(this.anchor, this.head) };
	  Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch };

	  // Take an unsorted, potentially overlapping set of ranges, and
	  // build a selection out of it. 'Consumes' ranges array (modifying
	  // it).
	  function normalizeSelection(cm, ranges, primIndex) {
	    var mayTouch = cm && cm.options.selectionsMayTouch;
	    var prim = ranges[primIndex];
	    ranges.sort(function (a, b) { return cmp(a.from(), b.from()); });
	    primIndex = indexOf(ranges, prim);
	    for (var i = 1; i < ranges.length; i++) {
	      var cur = ranges[i], prev = ranges[i - 1];
	      var diff = cmp(prev.to(), cur.from());
	      if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) {
	        var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
	        var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
	        if (i <= primIndex) { --primIndex; }
	        ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
	      }
	    }
	    return new Selection(ranges, primIndex)
	  }

	  function simpleSelection(anchor, head) {
	    return new Selection([new Range(anchor, head || anchor)], 0)
	  }

	  // Compute the position of the end of a change (its 'to' property
	  // refers to the pre-change end).
	  function changeEnd(change) {
	    if (!change.text) { return change.to }
	    return Pos(change.from.line + change.text.length - 1,
	               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
	  }

	  // Adjust a position to refer to the post-change position of the
	  // same text, or the end of the change if the change covers it.
	  function adjustForChange(pos, change) {
	    if (cmp(pos, change.from) < 0) { return pos }
	    if (cmp(pos, change.to) <= 0) { return changeEnd(change) }

	    var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
	    if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; }
	    return Pos(line, ch)
	  }

	  function computeSelAfterChange(doc, change) {
	    var out = [];
	    for (var i = 0; i < doc.sel.ranges.length; i++) {
	      var range = doc.sel.ranges[i];
	      out.push(new Range(adjustForChange(range.anchor, change),
	                         adjustForChange(range.head, change)));
	    }
	    return normalizeSelection(doc.cm, out, doc.sel.primIndex)
	  }

	  function offsetPos(pos, old, nw) {
	    if (pos.line == old.line)
	      { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
	    else
	      { return Pos(nw.line + (pos.line - old.line), pos.ch) }
	  }

	  // Used by replaceSelections to allow moving the selection to the
	  // start or around the replaced test. Hint may be "start" or "around".
	  function computeReplacedSel(doc, changes, hint) {
	    var out = [];
	    var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
	    for (var i = 0; i < changes.length; i++) {
	      var change = changes[i];
	      var from = offsetPos(change.from, oldPrev, newPrev);
	      var to = offsetPos(changeEnd(change), oldPrev, newPrev);
	      oldPrev = change.to;
	      newPrev = to;
	      if (hint == "around") {
	        var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
	        out[i] = new Range(inv ? to : from, inv ? from : to);
	      } else {
	        out[i] = new Range(from, from);
	      }
	    }
	    return new Selection(out, doc.sel.primIndex)
	  }

	  // Used to get the editor into a consistent state again when options change.

	  function loadMode(cm) {
	    cm.doc.mode = getMode(cm.options, cm.doc.modeOption);
	    resetModeState(cm);
	  }

	  function resetModeState(cm) {
	    cm.doc.iter(function (line) {
	      if (line.stateAfter) { line.stateAfter = null; }
	      if (line.styles) { line.styles = null; }
	    });
	    cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first;
	    startWorker(cm, 100);
	    cm.state.modeGen++;
	    if (cm.curOp) { regChange(cm); }
	  }

	  // DOCUMENT DATA STRUCTURE

	  // By default, updates that start and end at the beginning of a line
	  // are treated specially, in order to make the association of line
	  // widgets and marker elements with the text behave more intuitive.
	  function isWholeLineUpdate(doc, change) {
	    return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
	      (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
	  }

	  // Perform a change on the document data structure.
	  function updateDoc(doc, change, markedSpans, estimateHeight) {
	    function spansFor(n) {return markedSpans ? markedSpans[n] : null}
	    function update(line, text, spans) {
	      updateLine(line, text, spans, estimateHeight);
	      signalLater(line, "change", line, change);
	    }
	    function linesFor(start, end) {
	      var result = [];
	      for (var i = start; i < end; ++i)
	        { result.push(new Line(text[i], spansFor(i), estimateHeight)); }
	      return result
	    }

	    var from = change.from, to = change.to, text = change.text;
	    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
	    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;

	    // Adjust the line structure
	    if (change.full) {
	      doc.insert(0, linesFor(0, text.length));
	      doc.remove(text.length, doc.size - text.length);
	    } else if (isWholeLineUpdate(doc, change)) {
	      // This is a whole-line replace. Treated specially to make
	      // sure line objects move the way they are supposed to.
	      var added = linesFor(0, text.length - 1);
	      update(lastLine, lastLine.text, lastSpans);
	      if (nlines) { doc.remove(from.line, nlines); }
	      if (added.length) { doc.insert(from.line, added); }
	    } else if (firstLine == lastLine) {
	      if (text.length == 1) {
	        update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
	      } else {
	        var added$1 = linesFor(1, text.length - 1);
	        added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
	        update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
	        doc.insert(from.line + 1, added$1);
	      }
	    } else if (text.length == 1) {
	      update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
	      doc.remove(from.line + 1, nlines);
	    } else {
	      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
	      update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
	      var added$2 = linesFor(1, text.length - 1);
	      if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); }
	      doc.insert(from.line + 1, added$2);
	    }

	    signalLater(doc, "change", doc, change);
	  }

	  // Call f for all linked documents.
	  function linkedDocs(doc, f, sharedHistOnly) {
	    function propagate(doc, skip, sharedHist) {
	      if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
	        var rel = doc.linked[i];
	        if (rel.doc == skip) { continue }
	        var shared = sharedHist && rel.sharedHist;
	        if (sharedHistOnly && !shared) { continue }
	        f(rel.doc, shared);
	        propagate(rel.doc, doc, shared);
	      } }
	    }
	    propagate(doc, null, true);
	  }

	  // Attach a document to an editor.
	  function attachDoc(cm, doc) {
	    if (doc.cm) { throw new Error("This document is already in use.") }
	    cm.doc = doc;
	    doc.cm = cm;
	    estimateLineHeights(cm);
	    loadMode(cm);
	    setDirectionClass(cm);
	    cm.options.direction = doc.direction;
	    if (!cm.options.lineWrapping) { findMaxLine(cm); }
	    cm.options.mode = doc.modeOption;
	    regChange(cm);
	  }

	  function setDirectionClass(cm) {
	  (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl");
	  }

	  function directionChanged(cm) {
	    runInOp(cm, function () {
	      setDirectionClass(cm);
	      regChange(cm);
	    });
	  }

	  function History(prev) {
	    // Arrays of change events and selections. Doing something adds an
	    // event to done and clears undo. Undoing moves events from done
	    // to undone, redoing moves them in the other direction.
	    this.done = []; this.undone = [];
	    this.undoDepth = prev ? prev.undoDepth : Infinity;
	    // Used to track when changes can be merged into a single undo
	    // event
	    this.lastModTime = this.lastSelTime = 0;
	    this.lastOp = this.lastSelOp = null;
	    this.lastOrigin = this.lastSelOrigin = null;
	    // Used by the isClean() method
	    this.generation = this.maxGeneration = prev ? prev.maxGeneration : 1;
	  }

	  // Create a history change event from an updateDoc-style change
	  // object.
	  function historyChangeFromChange(doc, change) {
	    var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
	    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
	    linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true);
	    return histChange
	  }

	  // Pop all selection events off the end of a history array. Stop at
	  // a change event.
	  function clearSelectionEvents(array) {
	    while (array.length) {
	      var last = lst(array);
	      if (last.ranges) { array.pop(); }
	      else { break }
	    }
	  }

	  // Find the top change event in the history. Pop off selection
	  // events that are in the way.
	  function lastChangeEvent(hist, force) {
	    if (force) {
	      clearSelectionEvents(hist.done);
	      return lst(hist.done)
	    } else if (hist.done.length && !lst(hist.done).ranges) {
	      return lst(hist.done)
	    } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
	      hist.done.pop();
	      return lst(hist.done)
	    }
	  }

	  // Register a change in the history. Merges changes that are within
	  // a single operation, or are close together with an origin that
	  // allows merging (starting with "+") into a single event.
	  function addChangeToHistory(doc, change, selAfter, opId) {
	    var hist = doc.history;
	    hist.undone.length = 0;
	    var time = +new Date, cur;
	    var last;

	    if ((hist.lastOp == opId ||
	         hist.lastOrigin == change.origin && change.origin &&
	         ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
	          change.origin.charAt(0) == "*")) &&
	        (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
	      // Merge this change into the last event
	      last = lst(cur.changes);
	      if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
	        // Optimized case for simple insertion -- don't want to add
	        // new changesets for every character typed
	        last.to = changeEnd(change);
	      } else {
	        // Add new sub-event
	        cur.changes.push(historyChangeFromChange(doc, change));
	      }
	    } else {
	      // Can not be merged, start a new event.
	      var before = lst(hist.done);
	      if (!before || !before.ranges)
	        { pushSelectionToHistory(doc.sel, hist.done); }
	      cur = {changes: [historyChangeFromChange(doc, change)],
	             generation: hist.generation};
	      hist.done.push(cur);
	      while (hist.done.length > hist.undoDepth) {
	        hist.done.shift();
	        if (!hist.done[0].ranges) { hist.done.shift(); }
	      }
	    }
	    hist.done.push(selAfter);
	    hist.generation = ++hist.maxGeneration;
	    hist.lastModTime = hist.lastSelTime = time;
	    hist.lastOp = hist.lastSelOp = opId;
	    hist.lastOrigin = hist.lastSelOrigin = change.origin;

	    if (!last) { signal(doc, "historyAdded"); }
	  }

	  function selectionEventCanBeMerged(doc, origin, prev, sel) {
	    var ch = origin.charAt(0);
	    return ch == "*" ||
	      ch == "+" &&
	      prev.ranges.length == sel.ranges.length &&
	      prev.somethingSelected() == sel.somethingSelected() &&
	      new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
	  }

	  // Called whenever the selection changes, sets the new selection as
	  // the pending selection in the history, and pushes the old pending
	  // selection into the 'done' array when it was significantly
	  // different (in number of selected ranges, emptiness, or time).
	  function addSelectionToHistory(doc, sel, opId, options) {
	    var hist = doc.history, origin = options && options.origin;

	    // A new event is started when the previous origin does not match
	    // the current, or the origins don't allow matching. Origins
	    // starting with * are always merged, those starting with + are
	    // merged when similar and close together in time.
	    if (opId == hist.lastSelOp ||
	        (origin && hist.lastSelOrigin == origin &&
	         (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
	          selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
	      { hist.done[hist.done.length - 1] = sel; }
	    else
	      { pushSelectionToHistory(sel, hist.done); }

	    hist.lastSelTime = +new Date;
	    hist.lastSelOrigin = origin;
	    hist.lastSelOp = opId;
	    if (options && options.clearRedo !== false)
	      { clearSelectionEvents(hist.undone); }
	  }

	  function pushSelectionToHistory(sel, dest) {
	    var top = lst(dest);
	    if (!(top && top.ranges && top.equals(sel)))
	      { dest.push(sel); }
	  }

	  // Used to store marked span information in the history.
	  function attachLocalSpans(doc, change, from, to) {
	    var existing = change["spans_" + doc.id], n = 0;
	    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
	      if (line.markedSpans)
	        { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; }
	      ++n;
	    });
	  }

	  // When un/re-doing restores text containing marked spans, those
	  // that have been explicitly cleared should not be restored.
	  function removeClearedSpans(spans) {
	    if (!spans) { return null }
	    var out;
	    for (var i = 0; i < spans.length; ++i) {
	      if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } }
	      else if (out) { out.push(spans[i]); }
	    }
	    return !out ? spans : out.length ? out : null
	  }

	  // Retrieve and filter the old marked spans stored in a change event.
	  function getOldSpans(doc, change) {
	    var found = change["spans_" + doc.id];
	    if (!found) { return null }
	    var nw = [];
	    for (var i = 0; i < change.text.length; ++i)
	      { nw.push(removeClearedSpans(found[i])); }
	    return nw
	  }

	  // Used for un/re-doing changes from the history. Combines the
	  // result of computing the existing spans with the set of spans that
	  // existed in the history (so that deleting around a span and then
	  // undoing brings back the span).
	  function mergeOldSpans(doc, change) {
	    var old = getOldSpans(doc, change);
	    var stretched = stretchSpansOverChange(doc, change);
	    if (!old) { return stretched }
	    if (!stretched) { return old }

	    for (var i = 0; i < old.length; ++i) {
	      var oldCur = old[i], stretchCur = stretched[i];
	      if (oldCur && stretchCur) {
	        spans: for (var j = 0; j < stretchCur.length; ++j) {
	          var span = stretchCur[j];
	          for (var k = 0; k < oldCur.length; ++k)
	            { if (oldCur[k].marker == span.marker) { continue spans } }
	          oldCur.push(span);
	        }
	      } else if (stretchCur) {
	        old[i] = stretchCur;
	      }
	    }
	    return old
	  }

	  // Used both to provide a JSON-safe object in .getHistory, and, when
	  // detaching a document, to split the history in two
	  function copyHistoryArray(events, newGroup, instantiateSel) {
	    var copy = [];
	    for (var i = 0; i < events.length; ++i) {
	      var event = events[i];
	      if (event.ranges) {
	        copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
	        continue
	      }
	      var changes = event.changes, newChanges = [];
	      copy.push({changes: newChanges});
	      for (var j = 0; j < changes.length; ++j) {
	        var change = changes[j], m = (void 0);
	        newChanges.push({from: change.from, to: change.to, text: change.text});
	        if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
	          if (indexOf(newGroup, Number(m[1])) > -1) {
	            lst(newChanges)[prop] = change[prop];
	            delete change[prop];
	          }
	        } } }
	      }
	    }
	    return copy
	  }

	  // The 'scroll' parameter given to many of these indicated whether
	  // the new cursor position should be scrolled into view after
	  // modifying the selection.

	  // If shift is held or the extend flag is set, extends a range to
	  // include a given position (and optionally a second position).
	  // Otherwise, simply returns the range between the given positions.
	  // Used for cursor motion and such.
	  function extendRange(range, head, other, extend) {
	    if (extend) {
	      var anchor = range.anchor;
	      if (other) {
	        var posBefore = cmp(head, anchor) < 0;
	        if (posBefore != (cmp(other, anchor) < 0)) {
	          anchor = head;
	          head = other;
	        } else if (posBefore != (cmp(head, other) < 0)) {
	          head = other;
	        }
	      }
	      return new Range(anchor, head)
	    } else {
	      return new Range(other || head, head)
	    }
	  }

	  // Extend the primary selection range, discard the rest.
	  function extendSelection(doc, head, other, options, extend) {
	    if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); }
	    setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options);
	  }

	  // Extend all selections (pos is an array of selections with length
	  // equal the number of selections)
	  function extendSelections(doc, heads, options) {
	    var out = [];
	    var extend = doc.cm && (doc.cm.display.shift || doc.extend);
	    for (var i = 0; i < doc.sel.ranges.length; i++)
	      { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); }
	    var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex);
	    setSelection(doc, newSel, options);
	  }

	  // Updates a single range in the selection.
	  function replaceOneSelection(doc, i, range, options) {
	    var ranges = doc.sel.ranges.slice(0);
	    ranges[i] = range;
	    setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options);
	  }

	  // Reset the selection to a single range.
	  function setSimpleSelection(doc, anchor, head, options) {
	    setSelection(doc, simpleSelection(anchor, head), options);
	  }

	  // Give beforeSelectionChange handlers a change to influence a
	  // selection update.
	  function filterSelectionChange(doc, sel, options) {
	    var obj = {
	      ranges: sel.ranges,
	      update: function(ranges) {
	        this.ranges = [];
	        for (var i = 0; i < ranges.length; i++)
	          { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
	                                     clipPos(doc, ranges[i].head)); }
	      },
	      origin: options && options.origin
	    };
	    signal(doc, "beforeSelectionChange", doc, obj);
	    if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); }
	    if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) }
	    else { return sel }
	  }

	  function setSelectionReplaceHistory(doc, sel, options) {
	    var done = doc.history.done, last = lst(done);
	    if (last && last.ranges) {
	      done[done.length - 1] = sel;
	      setSelectionNoUndo(doc, sel, options);
	    } else {
	      setSelection(doc, sel, options);
	    }
	  }

	  // Set a new selection.
	  function setSelection(doc, sel, options) {
	    setSelectionNoUndo(doc, sel, options);
	    addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
	  }

	  function setSelectionNoUndo(doc, sel, options) {
	    if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
	      { sel = filterSelectionChange(doc, sel, options); }

	    var bias = options && options.bias ||
	      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
	    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));

	    if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor")
	      { ensureCursorVisible(doc.cm); }
	  }

	  function setSelectionInner(doc, sel) {
	    if (sel.equals(doc.sel)) { return }

	    doc.sel = sel;

	    if (doc.cm) {
	      doc.cm.curOp.updateInput = 1;
	      doc.cm.curOp.selectionChanged = true;
	      signalCursorActivity(doc.cm);
	    }
	    signalLater(doc, "cursorActivity", doc);
	  }

	  // Verify that the selection does not partially select any atomic
	  // marked ranges.
	  function reCheckSelection(doc) {
	    setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false));
	  }

	  // Return a selection that does not partially select any atomic
	  // ranges.
	  function skipAtomicInSelection(doc, sel, bias, mayClear) {
	    var out;
	    for (var i = 0; i < sel.ranges.length; i++) {
	      var range = sel.ranges[i];
	      var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
	      var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
	      var newHead = range.head == range.anchor ? newAnchor : skipAtomic(doc, range.head, old && old.head, bias, mayClear);
	      if (out || newAnchor != range.anchor || newHead != range.head) {
	        if (!out) { out = sel.ranges.slice(0, i); }
	        out[i] = new Range(newAnchor, newHead);
	      }
	    }
	    return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel
	  }

	  function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
	    var line = getLine(doc, pos.line);
	    if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
	      var sp = line.markedSpans[i], m = sp.marker;

	      // Determine if we should prevent the cursor being placed to the left/right of an atomic marker
	      // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it
	      // is with selectLeft/Right
	      var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft;
	      var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight;

	      if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
	          (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
	        if (mayClear) {
	          signal(m, "beforeCursorEnter");
	          if (m.explicitlyCleared) {
	            if (!line.markedSpans) { break }
	            else {--i; continue}
	          }
	        }
	        if (!m.atomic) { continue }

	        if (oldPos) {
	          var near = m.find(dir < 0 ? 1 : -1), diff = (void 0);
	          if (dir < 0 ? preventCursorRight : preventCursorLeft)
	            { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); }
	          if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
	            { return skipAtomicInner(doc, near, pos, dir, mayClear) }
	        }

	        var far = m.find(dir < 0 ? -1 : 1);
	        if (dir < 0 ? preventCursorLeft : preventCursorRight)
	          { far = movePos(doc, far, dir, far.line == pos.line ? line : null); }
	        return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
	      }
	    } }
	    return pos
	  }

	  // Ensure a given position is not inside an atomic range.
	  function skipAtomic(doc, pos, oldPos, bias, mayClear) {
	    var dir = bias || 1;
	    var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
	        (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
	        skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
	        (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
	    if (!found) {
	      doc.cantEdit = true;
	      return Pos(doc.first, 0)
	    }
	    return found
	  }

	  function movePos(doc, pos, dir, line) {
	    if (dir < 0 && pos.ch == 0) {
	      if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
	      else { return null }
	    } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
	      if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
	      else { return null }
	    } else {
	      return new Pos(pos.line, pos.ch + dir)
	    }
	  }

	  function selectAll(cm) {
	    cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);
	  }

	  // UPDATING

	  // Allow "beforeChange" event handlers to influence a change
	  function filterChange(doc, change, update) {
	    var obj = {
	      canceled: false,
	      from: change.from,
	      to: change.to,
	      text: change.text,
	      origin: change.origin,
	      cancel: function () { return obj.canceled = true; }
	    };
	    if (update) { obj.update = function (from, to, text, origin) {
	      if (from) { obj.from = clipPos(doc, from); }
	      if (to) { obj.to = clipPos(doc, to); }
	      if (text) { obj.text = text; }
	      if (origin !== undefined) { obj.origin = origin; }
	    }; }
	    signal(doc, "beforeChange", doc, obj);
	    if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); }

	    if (obj.canceled) {
	      if (doc.cm) { doc.cm.curOp.updateInput = 2; }
	      return null
	    }
	    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
	  }

	  // Apply a change to a document, and add it to the document's
	  // history, and propagating it to all linked documents.
	  function makeChange(doc, change, ignoreReadOnly) {
	    if (doc.cm) {
	      if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
	      if (doc.cm.state.suppressEdits) { return }
	    }

	    if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
	      change = filterChange(doc, change, true);
	      if (!change) { return }
	    }

	    // Possibly split or suppress the update based on the presence
	    // of read-only spans in its range.
	    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
	    if (split) {
	      for (var i = split.length - 1; i >= 0; --i)
	        { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); }
	    } else {
	      makeChangeInner(doc, change);
	    }
	  }

	  function makeChangeInner(doc, change) {
	    if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
	    var selAfter = computeSelAfterChange(doc, change);
	    addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);

	    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
	    var rebased = [];

	    linkedDocs(doc, function (doc, sharedHist) {
	      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
	        rebaseHist(doc.history, change);
	        rebased.push(doc.history);
	      }
	      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
	    });
	  }

	  // Revert a change stored in a document's history.
	  function makeChangeFromHistory(doc, type, allowSelectionOnly) {
	    var suppress = doc.cm && doc.cm.state.suppressEdits;
	    if (suppress && !allowSelectionOnly) { return }

	    var hist = doc.history, event, selAfter = doc.sel;
	    var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;

	    // Verify that there is a useable event (so that ctrl-z won't
	    // needlessly clear selection events)
	    var i = 0;
	    for (; i < source.length; i++) {
	      event = source[i];
	      if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
	        { break }
	    }
	    if (i == source.length) { return }
	    hist.lastOrigin = hist.lastSelOrigin = null;

	    for (;;) {
	      event = source.pop();
	      if (event.ranges) {
	        pushSelectionToHistory(event, dest);
	        if (allowSelectionOnly && !event.equals(doc.sel)) {
	          setSelection(doc, event, {clearRedo: false});
	          return
	        }
	        selAfter = event;
	      } else if (suppress) {
	        source.push(event);
	        return
	      } else { break }
	    }

	    // Build up a reverse change object to add to the opposite history
	    // stack (redo when undoing, and vice versa).
	    var antiChanges = [];
	    pushSelectionToHistory(selAfter, dest);
	    dest.push({changes: antiChanges, generation: hist.generation});
	    hist.generation = event.generation || ++hist.maxGeneration;

	    var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");

	    var loop = function ( i ) {
	      var change = event.changes[i];
	      change.origin = type;
	      if (filter && !filterChange(doc, change, false)) {
	        source.length = 0;
	        return {}
	      }

	      antiChanges.push(historyChangeFromChange(doc, change));

	      var after = i ? computeSelAfterChange(doc, change) : lst(source);
	      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
	      if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); }
	      var rebased = [];

	      // Propagate to the linked documents
	      linkedDocs(doc, function (doc, sharedHist) {
	        if (!sharedHist && indexOf(rebased, doc.history) == -1) {
	          rebaseHist(doc.history, change);
	          rebased.push(doc.history);
	        }
	        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
	      });
	    };

	    for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
	      var returned = loop( i$1 );

	      if ( returned ) return returned.v;
	    }
	  }

	  // Sub-views need their line numbers shifted when text is added
	  // above or below them in the parent document.
	  function shiftDoc(doc, distance) {
	    if (distance == 0) { return }
	    doc.first += distance;
	    doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
	      Pos(range.anchor.line + distance, range.anchor.ch),
	      Pos(range.head.line + distance, range.head.ch)
	    ); }), doc.sel.primIndex);
	    if (doc.cm) {
	      regChange(doc.cm, doc.first, doc.first - distance, distance);
	      for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
	        { regLineChange(doc.cm, l, "gutter"); }
	    }
	  }

	  // More lower-level change function, handling only a single document
	  // (not linked ones).
	  function makeChangeSingleDoc(doc, change, selAfter, spans) {
	    if (doc.cm && !doc.cm.curOp)
	      { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }

	    if (change.to.line < doc.first) {
	      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
	      return
	    }
	    if (change.from.line > doc.lastLine()) { return }

	    // Clip the change to the size of this doc
	    if (change.from.line < doc.first) {
	      var shift = change.text.length - 1 - (doc.first - change.from.line);
	      shiftDoc(doc, shift);
	      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
	                text: [lst(change.text)], origin: change.origin};
	    }
	    var last = doc.lastLine();
	    if (change.to.line > last) {
	      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
	                text: [change.text[0]], origin: change.origin};
	    }

	    change.removed = getBetween(doc, change.from, change.to);

	    if (!selAfter) { selAfter = computeSelAfterChange(doc, change); }
	    if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); }
	    else { updateDoc(doc, change, spans); }
	    setSelectionNoUndo(doc, selAfter, sel_dontScroll);

	    if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0)))
	      { doc.cantEdit = false; }
	  }

	  // Handle the interaction of a change to a document with the editor
	  // that this document is part of.
	  function makeChangeSingleDocInEditor(cm, change, spans) {
	    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;

	    var recomputeMaxLength = false, checkWidthStart = from.line;
	    if (!cm.options.lineWrapping) {
	      checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
	      doc.iter(checkWidthStart, to.line + 1, function (line) {
	        if (line == display.maxLine) {
	          recomputeMaxLength = true;
	          return true
	        }
	      });
	    }

	    if (doc.sel.contains(change.from, change.to) > -1)
	      { signalCursorActivity(cm); }

	    updateDoc(doc, change, spans, estimateHeight(cm));

	    if (!cm.options.lineWrapping) {
	      doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
	        var len = lineLength(line);
	        if (len > display.maxLineLength) {
	          display.maxLine = line;
	          display.maxLineLength = len;
	          display.maxLineChanged = true;
	          recomputeMaxLength = false;
	        }
	      });
	      if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; }
	    }

	    retreatFrontier(doc, from.line);
	    startWorker(cm, 400);

	    var lendiff = change.text.length - (to.line - from.line) - 1;
	    // Remember that these lines changed, for updating the display
	    if (change.full)
	      { regChange(cm); }
	    else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
	      { regLineChange(cm, from.line, "text"); }
	    else
	      { regChange(cm, from.line, to.line + 1, lendiff); }

	    var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
	    if (changeHandler || changesHandler) {
	      var obj = {
	        from: from, to: to,
	        text: change.text,
	        removed: change.removed,
	        origin: change.origin
	      };
	      if (changeHandler) { signalLater(cm, "change", cm, obj); }
	      if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); }
	    }
	    cm.display.selForContextMenu = null;
	  }

	  function replaceRange(doc, code, from, to, origin) {
	    var assign;

	    if (!to) { to = from; }
	    if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); }
	    if (typeof code == "string") { code = doc.splitLines(code); }
	    makeChange(doc, {from: from, to: to, text: code, origin: origin});
	  }

	  // Rebasing/resetting history to deal with externally-sourced changes

	  function rebaseHistSelSingle(pos, from, to, diff) {
	    if (to < pos.line) {
	      pos.line += diff;
	    } else if (from < pos.line) {
	      pos.line = from;
	      pos.ch = 0;
	    }
	  }

	  // Tries to rebase an array of history events given a change in the
	  // document. If the change touches the same lines as the event, the
	  // event, and everything 'behind' it, is discarded. If the change is
	  // before the event, the event's positions are updated. Uses a
	  // copy-on-write scheme for the positions, to avoid having to
	  // reallocate them all on every rebase, but also avoid problems with
	  // shared position objects being unsafely updated.
	  function rebaseHistArray(array, from, to, diff) {
	    for (var i = 0; i < array.length; ++i) {
	      var sub = array[i], ok = true;
	      if (sub.ranges) {
	        if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
	        for (var j = 0; j < sub.ranges.length; j++) {
	          rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
	          rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
	        }
	        continue
	      }
	      for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
	        var cur = sub.changes[j$1];
	        if (to < cur.from.line) {
	          cur.from = Pos(cur.from.line + diff, cur.from.ch);
	          cur.to = Pos(cur.to.line + diff, cur.to.ch);
	        } else if (from <= cur.to.line) {
	          ok = false;
	          break
	        }
	      }
	      if (!ok) {
	        array.splice(0, i + 1);
	        i = 0;
	      }
	    }
	  }

	  function rebaseHist(hist, change) {
	    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
	    rebaseHistArray(hist.done, from, to, diff);
	    rebaseHistArray(hist.undone, from, to, diff);
	  }

	  // Utility for applying a change to a line by handle or number,
	  // returning the number and optionally registering the line as
	  // changed.
	  function changeLine(doc, handle, changeType, op) {
	    var no = handle, line = handle;
	    if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); }
	    else { no = lineNo(handle); }
	    if (no == null) { return null }
	    if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); }
	    return line
	  }

	  // The document is represented as a BTree consisting of leaves, with
	  // chunk of lines in them, and branches, with up to ten leaves or
	  // other branch nodes below them. The top node is always a branch
	  // node, and is the document object itself (meaning it has
	  // additional methods and properties).
	  //
	  // All nodes have parent links. The tree is used both to go from
	  // line numbers to line objects, and to go from objects to numbers.
	  // It also indexes by height, and is used to convert between height
	  // and line object, and to find the total height of the document.
	  //
	  // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html

	  function LeafChunk(lines) {
	    this.lines = lines;
	    this.parent = null;
	    var height = 0;
	    for (var i = 0; i < lines.length; ++i) {
	      lines[i].parent = this;
	      height += lines[i].height;
	    }
	    this.height = height;
	  }

	  LeafChunk.prototype = {
	    chunkSize: function() { return this.lines.length },

	    // Remove the n lines at offset 'at'.
	    removeInner: function(at, n) {
	      for (var i = at, e = at + n; i < e; ++i) {
	        var line = this.lines[i];
	        this.height -= line.height;
	        cleanUpLine(line);
	        signalLater(line, "delete");
	      }
	      this.lines.splice(at, n);
	    },

	    // Helper used to collapse a small branch into a single leaf.
	    collapse: function(lines) {
	      lines.push.apply(lines, this.lines);
	    },

	    // Insert the given array of lines at offset 'at', count them as
	    // having the given height.
	    insertInner: function(at, lines, height) {
	      this.height += height;
	      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
	      for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; }
	    },

	    // Used to iterate over a part of the tree.
	    iterN: function(at, n, op) {
	      for (var e = at + n; at < e; ++at)
	        { if (op(this.lines[at])) { return true } }
	    }
	  };

	  function BranchChunk(children) {
	    this.children = children;
	    var size = 0, height = 0;
	    for (var i = 0; i < children.length; ++i) {
	      var ch = children[i];
	      size += ch.chunkSize(); height += ch.height;
	      ch.parent = this;
	    }
	    this.size = size;
	    this.height = height;
	    this.parent = null;
	  }

	  BranchChunk.prototype = {
	    chunkSize: function() { return this.size },

	    removeInner: function(at, n) {
	      this.size -= n;
	      for (var i = 0; i < this.children.length; ++i) {
	        var child = this.children[i], sz = child.chunkSize();
	        if (at < sz) {
	          var rm = Math.min(n, sz - at), oldHeight = child.height;
	          child.removeInner(at, rm);
	          this.height -= oldHeight - child.height;
	          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
	          if ((n -= rm) == 0) { break }
	          at = 0;
	        } else { at -= sz; }
	      }
	      // If the result is smaller than 25 lines, ensure that it is a
	      // single leaf node.
	      if (this.size - n < 25 &&
	          (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
	        var lines = [];
	        this.collapse(lines);
	        this.children = [new LeafChunk(lines)];
	        this.children[0].parent = this;
	      }
	    },

	    collapse: function(lines) {
	      for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); }
	    },

	    insertInner: function(at, lines, height) {
	      this.size += lines.length;
	      this.height += height;
	      for (var i = 0; i < this.children.length; ++i) {
	        var child = this.children[i], sz = child.chunkSize();
	        if (at <= sz) {
	          child.insertInner(at, lines, height);
	          if (child.lines && child.lines.length > 50) {
	            // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
	            // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
	            var remaining = child.lines.length % 25 + 25;
	            for (var pos = remaining; pos < child.lines.length;) {
	              var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));
	              child.height -= leaf.height;
	              this.children.splice(++i, 0, leaf);
	              leaf.parent = this;
	            }
	            child.lines = child.lines.slice(0, remaining);
	            this.maybeSpill();
	          }
	          break
	        }
	        at -= sz;
	      }
	    },

	    // When a node has grown, check whether it should be split.
	    maybeSpill: function() {
	      if (this.children.length <= 10) { return }
	      var me = this;
	      do {
	        var spilled = me.children.splice(me.children.length - 5, 5);
	        var sibling = new BranchChunk(spilled);
	        if (!me.parent) { // Become the parent node
	          var copy = new BranchChunk(me.children);
	          copy.parent = me;
	          me.children = [copy, sibling];
	          me = copy;
	       } else {
	          me.size -= sibling.size;
	          me.height -= sibling.height;
	          var myIndex = indexOf(me.parent.children, me);
	          me.parent.children.splice(myIndex + 1, 0, sibling);
	        }
	        sibling.parent = me.parent;
	      } while (me.children.length > 10)
	      me.parent.maybeSpill();
	    },

	    iterN: function(at, n, op) {
	      for (var i = 0; i < this.children.length; ++i) {
	        var child = this.children[i], sz = child.chunkSize();
	        if (at < sz) {
	          var used = Math.min(n, sz - at);
	          if (child.iterN(at, used, op)) { return true }
	          if ((n -= used) == 0) { break }
	          at = 0;
	        } else { at -= sz; }
	      }
	    }
	  };

	  // Line widgets are block elements displayed above or below a line.

	  var LineWidget = function(doc, node, options) {
	    if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
	      { this[opt] = options[opt]; } } }
	    this.doc = doc;
	    this.node = node;
	  };

	  LineWidget.prototype.clear = function () {
	    var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
	    if (no == null || !ws) { return }
	    for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } }
	    if (!ws.length) { line.widgets = null; }
	    var height = widgetHeight(this);
	    updateLineHeight(line, Math.max(0, line.height - height));
	    if (cm) {
	      runInOp(cm, function () {
	        adjustScrollWhenAboveVisible(cm, line, -height);
	        regLineChange(cm, no, "widget");
	      });
	      signalLater(cm, "lineWidgetCleared", cm, this, no);
	    }
	  };

	  LineWidget.prototype.changed = function () {
	      var this$1$1 = this;

	    var oldH = this.height, cm = this.doc.cm, line = this.line;
	    this.height = null;
	    var diff = widgetHeight(this) - oldH;
	    if (!diff) { return }
	    if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); }
	    if (cm) {
	      runInOp(cm, function () {
	        cm.curOp.forceUpdate = true;
	        adjustScrollWhenAboveVisible(cm, line, diff);
	        signalLater(cm, "lineWidgetChanged", cm, this$1$1, lineNo(line));
	      });
	    }
	  };
	  eventMixin(LineWidget);

	  function adjustScrollWhenAboveVisible(cm, line, diff) {
	    if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
	      { addToScrollTop(cm, diff); }
	  }

	  function addLineWidget(doc, handle, node, options) {
	    var widget = new LineWidget(doc, node, options);
	    var cm = doc.cm;
	    if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }
	    changeLine(doc, handle, "widget", function (line) {
	      var widgets = line.widgets || (line.widgets = []);
	      if (widget.insertAt == null) { widgets.push(widget); }
	      else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); }
	      widget.line = line;
	      if (cm && !lineIsHidden(doc, line)) {
	        var aboveVisible = heightAtLine(line) < doc.scrollTop;
	        updateLineHeight(line, line.height + widgetHeight(widget));
	        if (aboveVisible) { addToScrollTop(cm, widget.height); }
	        cm.curOp.forceUpdate = true;
	      }
	      return true
	    });
	    if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); }
	    return widget
	  }

	  // TEXTMARKERS

	  // Created with markText and setBookmark methods. A TextMarker is a
	  // handle that can be used to clear or find a marked position in the
	  // document. Line objects hold arrays (markedSpans) containing
	  // {from, to, marker} object pointing to such marker objects, and
	  // indicating that such a marker is present on that line. Multiple
	  // lines may point to the same marker when it spans across lines.
	  // The spans will have null for their from/to properties when the
	  // marker continues beyond the start/end of the line. Markers have
	  // links back to the lines they currently touch.

	  // Collapsed markers have unique ids, in order to be able to order
	  // them, which is needed for uniquely determining an outer marker
	  // when they overlap (they may nest, but not partially overlap).
	  var nextMarkerId = 0;

	  var TextMarker = function(doc, type) {
	    this.lines = [];
	    this.type = type;
	    this.doc = doc;
	    this.id = ++nextMarkerId;
	  };

	  // Clear the marker.
	  TextMarker.prototype.clear = function () {
	    if (this.explicitlyCleared) { return }
	    var cm = this.doc.cm, withOp = cm && !cm.curOp;
	    if (withOp) { startOperation(cm); }
	    if (hasHandler(this, "clear")) {
	      var found = this.find();
	      if (found) { signalLater(this, "clear", found.from, found.to); }
	    }
	    var min = null, max = null;
	    for (var i = 0; i < this.lines.length; ++i) {
	      var line = this.lines[i];
	      var span = getMarkedSpanFor(line.markedSpans, this);
	      if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); }
	      else if (cm) {
	        if (span.to != null) { max = lineNo(line); }
	        if (span.from != null) { min = lineNo(line); }
	      }
	      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
	      if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
	        { updateLineHeight(line, textHeight(cm.display)); }
	    }
	    if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
	      var visual = visualLine(this.lines[i$1]), len = lineLength(visual);
	      if (len > cm.display.maxLineLength) {
	        cm.display.maxLine = visual;
	        cm.display.maxLineLength = len;
	        cm.display.maxLineChanged = true;
	      }
	    } }

	    if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); }
	    this.lines.length = 0;
	    this.explicitlyCleared = true;
	    if (this.atomic && this.doc.cantEdit) {
	      this.doc.cantEdit = false;
	      if (cm) { reCheckSelection(cm.doc); }
	    }
	    if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); }
	    if (withOp) { endOperation(cm); }
	    if (this.parent) { this.parent.clear(); }
	  };

	  // Find the position of the marker in the document. Returns a {from,
	  // to} object by default. Side can be passed to get a specific side
	  // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
	  // Pos objects returned contain a line object, rather than a line
	  // number (used to prevent looking up the same line twice).
	  TextMarker.prototype.find = function (side, lineObj) {
	    if (side == null && this.type == "bookmark") { side = 1; }
	    var from, to;
	    for (var i = 0; i < this.lines.length; ++i) {
	      var line = this.lines[i];
	      var span = getMarkedSpanFor(line.markedSpans, this);
	      if (span.from != null) {
	        from = Pos(lineObj ? line : lineNo(line), span.from);
	        if (side == -1) { return from }
	      }
	      if (span.to != null) {
	        to = Pos(lineObj ? line : lineNo(line), span.to);
	        if (side == 1) { return to }
	      }
	    }
	    return from && {from: from, to: to}
	  };

	  // Signals that the marker's widget changed, and surrounding layout
	  // should be recomputed.
	  TextMarker.prototype.changed = function () {
	      var this$1$1 = this;

	    var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
	    if (!pos || !cm) { return }
	    runInOp(cm, function () {
	      var line = pos.line, lineN = lineNo(pos.line);
	      var view = findViewForLine(cm, lineN);
	      if (view) {
	        clearLineMeasurementCacheFor(view);
	        cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
	      }
	      cm.curOp.updateMaxLine = true;
	      if (!lineIsHidden(widget.doc, line) && widget.height != null) {
	        var oldHeight = widget.height;
	        widget.height = null;
	        var dHeight = widgetHeight(widget) - oldHeight;
	        if (dHeight)
	          { updateLineHeight(line, line.height + dHeight); }
	      }
	      signalLater(cm, "markerChanged", cm, this$1$1);
	    });
	  };

	  TextMarker.prototype.attachLine = function (line) {
	    if (!this.lines.length && this.doc.cm) {
	      var op = this.doc.cm.curOp;
	      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
	        { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); }
	    }
	    this.lines.push(line);
	  };

	  TextMarker.prototype.detachLine = function (line) {
	    this.lines.splice(indexOf(this.lines, line), 1);
	    if (!this.lines.length && this.doc.cm) {
	      var op = this.doc.cm.curOp
	      ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
	    }
	  };
	  eventMixin(TextMarker);

	  // Create a marker, wire it up to the right lines, and
	  function markText(doc, from, to, options, type) {
	    // Shared markers (across linked documents) are handled separately
	    // (markTextShared will call out to this again, once per
	    // document).
	    if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
	    // Ensure we are in an operation.
	    if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }

	    var marker = new TextMarker(doc, type), diff = cmp(from, to);
	    if (options) { copyObj(options, marker, false); }
	    // Don't connect empty markers unless clearWhenEmpty is false
	    if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
	      { return marker }
	    if (marker.replacedWith) {
	      // Showing up as a widget implies collapsed (widget replaces text)
	      marker.collapsed = true;
	      marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget");
	      if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); }
	      if (options.insertLeft) { marker.widgetNode.insertLeft = true; }
	    }
	    if (marker.collapsed) {
	      if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
	          from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
	        { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
	      seeCollapsedSpans();
	    }

	    if (marker.addToHistory)
	      { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); }

	    var curLine = from.line, cm = doc.cm, updateMaxLine;
	    doc.iter(curLine, to.line + 1, function (line) {
	      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
	        { updateMaxLine = true; }
	      if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
	      addMarkedSpan(line, new MarkedSpan(marker,
	                                         curLine == from.line ? from.ch : null,
	                                         curLine == to.line ? to.ch : null), doc.cm && doc.cm.curOp);
	      ++curLine;
	    });
	    // lineIsHidden depends on the presence of the spans, so needs a second pass
	    if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
	      if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }
	    }); }

	    if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); }

	    if (marker.readOnly) {
	      seeReadOnlySpans();
	      if (doc.history.done.length || doc.history.undone.length)
	        { doc.clearHistory(); }
	    }
	    if (marker.collapsed) {
	      marker.id = ++nextMarkerId;
	      marker.atomic = true;
	    }
	    if (cm) {
	      // Sync editor state
	      if (updateMaxLine) { cm.curOp.updateMaxLine = true; }
	      if (marker.collapsed)
	        { regChange(cm, from.line, to.line + 1); }
	      else if (marker.className || marker.startStyle || marker.endStyle || marker.css ||
	               marker.attributes || marker.title)
	        { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } }
	      if (marker.atomic) { reCheckSelection(cm.doc); }
	      signalLater(cm, "markerAdded", cm, marker);
	    }
	    return marker
	  }

	  // SHARED TEXTMARKERS

	  // A shared marker spans multiple linked documents. It is
	  // implemented as a meta-marker-object controlling multiple normal
	  // markers.
	  var SharedTextMarker = function(markers, primary) {
	    this.markers = markers;
	    this.primary = primary;
	    for (var i = 0; i < markers.length; ++i)
	      { markers[i].parent = this; }
	  };

	  SharedTextMarker.prototype.clear = function () {
	    if (this.explicitlyCleared) { return }
	    this.explicitlyCleared = true;
	    for (var i = 0; i < this.markers.length; ++i)
	      { this.markers[i].clear(); }
	    signalLater(this, "clear");
	  };

	  SharedTextMarker.prototype.find = function (side, lineObj) {
	    return this.primary.find(side, lineObj)
	  };
	  eventMixin(SharedTextMarker);

	  function markTextShared(doc, from, to, options, type) {
	    options = copyObj(options);
	    options.shared = false;
	    var markers = [markText(doc, from, to, options, type)], primary = markers[0];
	    var widget = options.widgetNode;
	    linkedDocs(doc, function (doc) {
	      if (widget) { options.widgetNode = widget.cloneNode(true); }
	      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
	      for (var i = 0; i < doc.linked.length; ++i)
	        { if (doc.linked[i].isParent) { return } }
	      primary = lst(markers);
	    });
	    return new SharedTextMarker(markers, primary)
	  }

	  function findSharedMarkers(doc) {
	    return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
	  }

	  function copySharedMarkers(doc, markers) {
	    for (var i = 0; i < markers.length; i++) {
	      var marker = markers[i], pos = marker.find();
	      var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
	      if (cmp(mFrom, mTo)) {
	        var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
	        marker.markers.push(subMark);
	        subMark.parent = marker;
	      }
	    }
	  }

	  function detachSharedMarkers(markers) {
	    var loop = function ( i ) {
	      var marker = markers[i], linked = [marker.primary.doc];
	      linkedDocs(marker.primary.doc, function (d) { return linked.push(d); });
	      for (var j = 0; j < marker.markers.length; j++) {
	        var subMarker = marker.markers[j];
	        if (indexOf(linked, subMarker.doc) == -1) {
	          subMarker.parent = null;
	          marker.markers.splice(j--, 1);
	        }
	      }
	    };

	    for (var i = 0; i < markers.length; i++) loop( i );
	  }

	  var nextDocId = 0;
	  var Doc = function(text, mode, firstLine, lineSep, direction) {
	    if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) }
	    if (firstLine == null) { firstLine = 0; }

	    BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
	    this.first = firstLine;
	    this.scrollTop = this.scrollLeft = 0;
	    this.cantEdit = false;
	    this.cleanGeneration = 1;
	    this.modeFrontier = this.highlightFrontier = firstLine;
	    var start = Pos(firstLine, 0);
	    this.sel = simpleSelection(start);
	    this.history = new History(null);
	    this.id = ++nextDocId;
	    this.modeOption = mode;
	    this.lineSep = lineSep;
	    this.direction = (direction == "rtl") ? "rtl" : "ltr";
	    this.extend = false;

	    if (typeof text == "string") { text = this.splitLines(text); }
	    updateDoc(this, {from: start, to: start, text: text});
	    setSelection(this, simpleSelection(start), sel_dontScroll);
	  };

	  Doc.prototype = createObj(BranchChunk.prototype, {
	    constructor: Doc,
	    // Iterate over the document. Supports two forms -- with only one
	    // argument, it calls that for each line in the document. With
	    // three, it iterates over the range given by the first two (with
	    // the second being non-inclusive).
	    iter: function(from, to, op) {
	      if (op) { this.iterN(from - this.first, to - from, op); }
	      else { this.iterN(this.first, this.first + this.size, from); }
	    },

	    // Non-public interface for adding and removing lines.
	    insert: function(at, lines) {
	      var height = 0;
	      for (var i = 0; i < lines.length; ++i) { height += lines[i].height; }
	      this.insertInner(at - this.first, lines, height);
	    },
	    remove: function(at, n) { this.removeInner(at - this.first, n); },

	    // From here, the methods are part of the public interface. Most
	    // are also available from CodeMirror (editor) instances.

	    getValue: function(lineSep) {
	      var lines = getLines(this, this.first, this.first + this.size);
	      if (lineSep === false) { return lines }
	      return lines.join(lineSep || this.lineSeparator())
	    },
	    setValue: docMethodOp(function(code) {
	      var top = Pos(this.first, 0), last = this.first + this.size - 1;
	      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
	                        text: this.splitLines(code), origin: "setValue", full: true}, true);
	      if (this.cm) { scrollToCoords(this.cm, 0, 0); }
	      setSelection(this, simpleSelection(top), sel_dontScroll);
	    }),
	    replaceRange: function(code, from, to, origin) {
	      from = clipPos(this, from);
	      to = to ? clipPos(this, to) : from;
	      replaceRange(this, code, from, to, origin);
	    },
	    getRange: function(from, to, lineSep) {
	      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
	      if (lineSep === false) { return lines }
	      if (lineSep === '') { return lines.join('') }
	      return lines.join(lineSep || this.lineSeparator())
	    },

	    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},

	    getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
	    getLineNumber: function(line) {return lineNo(line)},

	    getLineHandleVisualStart: function(line) {
	      if (typeof line == "number") { line = getLine(this, line); }
	      return visualLine(line)
	    },

	    lineCount: function() {return this.size},
	    firstLine: function() {return this.first},
	    lastLine: function() {return this.first + this.size - 1},

	    clipPos: function(pos) {return clipPos(this, pos)},

	    getCursor: function(start) {
	      var range = this.sel.primary(), pos;
	      if (start == null || start == "head") { pos = range.head; }
	      else if (start == "anchor") { pos = range.anchor; }
	      else if (start == "end" || start == "to" || start === false) { pos = range.to(); }
	      else { pos = range.from(); }
	      return pos
	    },
	    listSelections: function() { return this.sel.ranges },
	    somethingSelected: function() {return this.sel.somethingSelected()},

	    setCursor: docMethodOp(function(line, ch, options) {
	      setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
	    }),
	    setSelection: docMethodOp(function(anchor, head, options) {
	      setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
	    }),
	    extendSelection: docMethodOp(function(head, other, options) {
	      extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
	    }),
	    extendSelections: docMethodOp(function(heads, options) {
	      extendSelections(this, clipPosArray(this, heads), options);
	    }),
	    extendSelectionsBy: docMethodOp(function(f, options) {
	      var heads = map(this.sel.ranges, f);
	      extendSelections(this, clipPosArray(this, heads), options);
	    }),
	    setSelections: docMethodOp(function(ranges, primary, options) {
	      if (!ranges.length) { return }
	      var out = [];
	      for (var i = 0; i < ranges.length; i++)
	        { out[i] = new Range(clipPos(this, ranges[i].anchor),
	                           clipPos(this, ranges[i].head || ranges[i].anchor)); }
	      if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
	      setSelection(this, normalizeSelection(this.cm, out, primary), options);
	    }),
	    addSelection: docMethodOp(function(anchor, head, options) {
	      var ranges = this.sel.ranges.slice(0);
	      ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
	      setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options);
	    }),

	    getSelection: function(lineSep) {
	      var ranges = this.sel.ranges, lines;
	      for (var i = 0; i < ranges.length; i++) {
	        var sel = getBetween(this, ranges[i].from(), ranges[i].to());
	        lines = lines ? lines.concat(sel) : sel;
	      }
	      if (lineSep === false) { return lines }
	      else { return lines.join(lineSep || this.lineSeparator()) }
	    },
	    getSelections: function(lineSep) {
	      var parts = [], ranges = this.sel.ranges;
	      for (var i = 0; i < ranges.length; i++) {
	        var sel = getBetween(this, ranges[i].from(), ranges[i].to());
	        if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); }
	        parts[i] = sel;
	      }
	      return parts
	    },
	    replaceSelection: function(code, collapse, origin) {
	      var dup = [];
	      for (var i = 0; i < this.sel.ranges.length; i++)
	        { dup[i] = code; }
	      this.replaceSelections(dup, collapse, origin || "+input");
	    },
	    replaceSelections: docMethodOp(function(code, collapse, origin) {
	      var changes = [], sel = this.sel;
	      for (var i = 0; i < sel.ranges.length; i++) {
	        var range = sel.ranges[i];
	        changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
	      }
	      var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
	      for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
	        { makeChange(this, changes[i$1]); }
	      if (newSel) { setSelectionReplaceHistory(this, newSel); }
	      else if (this.cm) { ensureCursorVisible(this.cm); }
	    }),
	    undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
	    redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
	    undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
	    redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),

	    setExtending: function(val) {this.extend = val;},
	    getExtending: function() {return this.extend},

	    historySize: function() {
	      var hist = this.history, done = 0, undone = 0;
	      for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } }
	      for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } }
	      return {undo: done, redo: undone}
	    },
	    clearHistory: function() {
	      var this$1$1 = this;

	      this.history = new History(this.history);
	      linkedDocs(this, function (doc) { return doc.history = this$1$1.history; }, true);
	    },

	    markClean: function() {
	      this.cleanGeneration = this.changeGeneration(true);
	    },
	    changeGeneration: function(forceSplit) {
	      if (forceSplit)
	        { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; }
	      return this.history.generation
	    },
	    isClean: function (gen) {
	      return this.history.generation == (gen || this.cleanGeneration)
	    },

	    getHistory: function() {
	      return {done: copyHistoryArray(this.history.done),
	              undone: copyHistoryArray(this.history.undone)}
	    },
	    setHistory: function(histData) {
	      var hist = this.history = new History(this.history);
	      hist.done = copyHistoryArray(histData.done.slice(0), null, true);
	      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
	    },

	    setGutterMarker: docMethodOp(function(line, gutterID, value) {
	      return changeLine(this, line, "gutter", function (line) {
	        var markers = line.gutterMarkers || (line.gutterMarkers = {});
	        markers[gutterID] = value;
	        if (!value && isEmpty(markers)) { line.gutterMarkers = null; }
	        return true
	      })
	    }),

	    clearGutter: docMethodOp(function(gutterID) {
	      var this$1$1 = this;

	      this.iter(function (line) {
	        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
	          changeLine(this$1$1, line, "gutter", function () {
	            line.gutterMarkers[gutterID] = null;
	            if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; }
	            return true
	          });
	        }
	      });
	    }),

	    lineInfo: function(line) {
	      var n;
	      if (typeof line == "number") {
	        if (!isLine(this, line)) { return null }
	        n = line;
	        line = getLine(this, line);
	        if (!line) { return null }
	      } else {
	        n = lineNo(line);
	        if (n == null) { return null }
	      }
	      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
	              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
	              widgets: line.widgets}
	    },

	    addLineClass: docMethodOp(function(handle, where, cls) {
	      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
	        var prop = where == "text" ? "textClass"
	                 : where == "background" ? "bgClass"
	                 : where == "gutter" ? "gutterClass" : "wrapClass";
	        if (!line[prop]) { line[prop] = cls; }
	        else if (classTest(cls).test(line[prop])) { return false }
	        else { line[prop] += " " + cls; }
	        return true
	      })
	    }),
	    removeLineClass: docMethodOp(function(handle, where, cls) {
	      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
	        var prop = where == "text" ? "textClass"
	                 : where == "background" ? "bgClass"
	                 : where == "gutter" ? "gutterClass" : "wrapClass";
	        var cur = line[prop];
	        if (!cur) { return false }
	        else if (cls == null) { line[prop] = null; }
	        else {
	          var found = cur.match(classTest(cls));
	          if (!found) { return false }
	          var end = found.index + found[0].length;
	          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
	        }
	        return true
	      })
	    }),

	    addLineWidget: docMethodOp(function(handle, node, options) {
	      return addLineWidget(this, handle, node, options)
	    }),
	    removeLineWidget: function(widget) { widget.clear(); },

	    markText: function(from, to, options) {
	      return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
	    },
	    setBookmark: function(pos, options) {
	      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
	                      insertLeft: options && options.insertLeft,
	                      clearWhenEmpty: false, shared: options && options.shared,
	                      handleMouseEvents: options && options.handleMouseEvents};
	      pos = clipPos(this, pos);
	      return markText(this, pos, pos, realOpts, "bookmark")
	    },
	    findMarksAt: function(pos) {
	      pos = clipPos(this, pos);
	      var markers = [], spans = getLine(this, pos.line).markedSpans;
	      if (spans) { for (var i = 0; i < spans.length; ++i) {
	        var span = spans[i];
	        if ((span.from == null || span.from <= pos.ch) &&
	            (span.to == null || span.to >= pos.ch))
	          { markers.push(span.marker.parent || span.marker); }
	      } }
	      return markers
	    },
	    findMarks: function(from, to, filter) {
	      from = clipPos(this, from); to = clipPos(this, to);
	      var found = [], lineNo = from.line;
	      this.iter(from.line, to.line + 1, function (line) {
	        var spans = line.markedSpans;
	        if (spans) { for (var i = 0; i < spans.length; i++) {
	          var span = spans[i];
	          if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
	                span.from == null && lineNo != from.line ||
	                span.from != null && lineNo == to.line && span.from >= to.ch) &&
	              (!filter || filter(span.marker)))
	            { found.push(span.marker.parent || span.marker); }
	        } }
	        ++lineNo;
	      });
	      return found
	    },
	    getAllMarks: function() {
	      var markers = [];
	      this.iter(function (line) {
	        var sps = line.markedSpans;
	        if (sps) { for (var i = 0; i < sps.length; ++i)
	          { if (sps[i].from != null) { markers.push(sps[i].marker); } } }
	      });
	      return markers
	    },

	    posFromIndex: function(off) {
	      var ch, lineNo = this.first, sepSize = this.lineSeparator().length;
	      this.iter(function (line) {
	        var sz = line.text.length + sepSize;
	        if (sz > off) { ch = off; return true }
	        off -= sz;
	        ++lineNo;
	      });
	      return clipPos(this, Pos(lineNo, ch))
	    },
	    indexFromPos: function (coords) {
	      coords = clipPos(this, coords);
	      var index = coords.ch;
	      if (coords.line < this.first || coords.ch < 0) { return 0 }
	      var sepSize = this.lineSeparator().length;
	      this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
	        index += line.text.length + sepSize;
	      });
	      return index
	    },

	    copy: function(copyHistory) {
	      var doc = new Doc(getLines(this, this.first, this.first + this.size),
	                        this.modeOption, this.first, this.lineSep, this.direction);
	      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
	      doc.sel = this.sel;
	      doc.extend = false;
	      if (copyHistory) {
	        doc.history.undoDepth = this.history.undoDepth;
	        doc.setHistory(this.getHistory());
	      }
	      return doc
	    },

	    linkedDoc: function(options) {
	      if (!options) { options = {}; }
	      var from = this.first, to = this.first + this.size;
	      if (options.from != null && options.from > from) { from = options.from; }
	      if (options.to != null && options.to < to) { to = options.to; }
	      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction);
	      if (options.sharedHist) { copy.history = this.history
	      ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
	      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
	      copySharedMarkers(copy, findSharedMarkers(this));
	      return copy
	    },
	    unlinkDoc: function(other) {
	      if (other instanceof CodeMirror) { other = other.doc; }
	      if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
	        var link = this.linked[i];
	        if (link.doc != other) { continue }
	        this.linked.splice(i, 1);
	        other.unlinkDoc(this);
	        detachSharedMarkers(findSharedMarkers(this));
	        break
	      } }
	      // If the histories were shared, split them again
	      if (other.history == this.history) {
	        var splitIds = [other.id];
	        linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true);
	        other.history = new History(null);
	        other.history.done = copyHistoryArray(this.history.done, splitIds);
	        other.history.undone = copyHistoryArray(this.history.undone, splitIds);
	      }
	    },
	    iterLinkedDocs: function(f) {linkedDocs(this, f);},

	    getMode: function() {return this.mode},
	    getEditor: function() {return this.cm},

	    splitLines: function(str) {
	      if (this.lineSep) { return str.split(this.lineSep) }
	      return splitLinesAuto(str)
	    },
	    lineSeparator: function() { return this.lineSep || "\n" },

	    setDirection: docMethodOp(function (dir) {
	      if (dir != "rtl") { dir = "ltr"; }
	      if (dir == this.direction) { return }
	      this.direction = dir;
	      this.iter(function (line) { return line.order = null; });
	      if (this.cm) { directionChanged(this.cm); }
	    })
	  });

	  // Public alias.
	  Doc.prototype.eachLine = Doc.prototype.iter;

	  // Kludge to work around strange IE behavior where it'll sometimes
	  // re-fire a series of drag-related events right after the drop (#1551)
	  var lastDrop = 0;

	  function onDrop(e) {
	    var cm = this;
	    clearDragCursor(cm);
	    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
	      { return }
	    e_preventDefault(e);
	    if (ie) { lastDrop = +new Date; }
	    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
	    if (!pos || cm.isReadOnly()) { return }
	    // Might be a file drop, in which case we simply extract the text
	    // and insert it.
	    if (files && files.length && window.FileReader && window.File) {
	      var n = files.length, text = Array(n), read = 0;
	      var markAsReadAndPasteIfAllFilesAreRead = function () {
	        if (++read == n) {
	          operation(cm, function () {
	            pos = clipPos(cm.doc, pos);
	            var change = {from: pos, to: pos,
	                          text: cm.doc.splitLines(
	                              text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())),
	                          origin: "paste"};
	            makeChange(cm.doc, change);
	            setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change))));
	          })();
	        }
	      };
	      var readTextFromFile = function (file, i) {
	        if (cm.options.allowDropFileTypes &&
	            indexOf(cm.options.allowDropFileTypes, file.type) == -1) {
	          markAsReadAndPasteIfAllFilesAreRead();
	          return
	        }
	        var reader = new FileReader;
	        reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); };
	        reader.onload = function () {
	          var content = reader.result;
	          if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) {
	            markAsReadAndPasteIfAllFilesAreRead();
	            return
	          }
	          text[i] = content;
	          markAsReadAndPasteIfAllFilesAreRead();
	        };
	        reader.readAsText(file);
	      };
	      for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); }
	    } else { // Normal drop
	      // Don't do a replace if the drop happened inside of the selected text.
	      if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
	        cm.state.draggingText(e);
	        // Ensure the editor is re-focused
	        setTimeout(function () { return cm.display.input.focus(); }, 20);
	        return
	      }
	      try {
	        var text$1 = e.dataTransfer.getData("Text");
	        if (text$1) {
	          var selected;
	          if (cm.state.draggingText && !cm.state.draggingText.copy)
	            { selected = cm.listSelections(); }
	          setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
	          if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
	            { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } }
	          cm.replaceSelection(text$1, "around", "paste");
	          cm.display.input.focus();
	        }
	      }
	      catch(e$1){}
	    }
	  }

	  function onDragStart(cm, e) {
	    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
	    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }

	    e.dataTransfer.setData("Text", cm.getSelection());
	    e.dataTransfer.effectAllowed = "copyMove";

	    // Use dummy image instead of default browsers image.
	    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
	    if (e.dataTransfer.setDragImage && !safari) {
	      var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
	      img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
	      if (presto) {
	        img.width = img.height = 1;
	        cm.display.wrapper.appendChild(img);
	        // Force a relayout, or Opera won't use our image for some obscure reason
	        img._top = img.offsetTop;
	      }
	      e.dataTransfer.setDragImage(img, 0, 0);
	      if (presto) { img.parentNode.removeChild(img); }
	    }
	  }

	  function onDragOver(cm, e) {
	    var pos = posFromMouse(cm, e);
	    if (!pos) { return }
	    var frag = document.createDocumentFragment();
	    drawSelectionCursor(cm, pos, frag);
	    if (!cm.display.dragCursor) {
	      cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
	      cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
	    }
	    removeChildrenAndAdd(cm.display.dragCursor, frag);
	  }

	  function clearDragCursor(cm) {
	    if (cm.display.dragCursor) {
	      cm.display.lineSpace.removeChild(cm.display.dragCursor);
	      cm.display.dragCursor = null;
	    }
	  }

	  // These must be handled carefully, because naively registering a
	  // handler for each editor will cause the editors to never be
	  // garbage collected.

	  function forEachCodeMirror(f) {
	    if (!document.getElementsByClassName) { return }
	    var byClass = document.getElementsByClassName("CodeMirror"), editors = [];
	    for (var i = 0; i < byClass.length; i++) {
	      var cm = byClass[i].CodeMirror;
	      if (cm) { editors.push(cm); }
	    }
	    if (editors.length) { editors[0].operation(function () {
	      for (var i = 0; i < editors.length; i++) { f(editors[i]); }
	    }); }
	  }

	  var globalsRegistered = false;
	  function ensureGlobalHandlers() {
	    if (globalsRegistered) { return }
	    registerGlobalHandlers();
	    globalsRegistered = true;
	  }
	  function registerGlobalHandlers() {
	    // When the window resizes, we need to refresh active editors.
	    var resizeTimer;
	    on(window, "resize", function () {
	      if (resizeTimer == null) { resizeTimer = setTimeout(function () {
	        resizeTimer = null;
	        forEachCodeMirror(onResize);
	      }, 100); }
	    });
	    // When the window loses focus, we want to show the editor as blurred
	    on(window, "blur", function () { return forEachCodeMirror(onBlur); });
	  }
	  // Called when the window resizes
	  function onResize(cm) {
	    var d = cm.display;
	    // Might be a text scaling operation, clear size caches.
	    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
	    d.scrollbarsClipped = false;
	    cm.setSize();
	  }

	  var keyNames = {
	    3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
	    19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
	    36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
	    46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
	    106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock",
	    173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
	    221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
	    63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
	  };

	  // Number keys
	  for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); }
	  // Alphabetic keys
	  for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); }
	  // Function keys
	  for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; }

	  var keyMap = {};

	  keyMap.basic = {
	    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
	    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
	    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
	    "Tab": "defaultTab", "Shift-Tab": "indentAuto",
	    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
	    "Esc": "singleSelection"
	  };
	  // Note that the save and find-related commands aren't defined by
	  // default. User code or addons can define them. Unknown commands
	  // are simply ignored.
	  keyMap.pcDefault = {
	    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
	    "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
	    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
	    "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
	    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
	    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
	    "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
	    "fallthrough": "basic"
	  };
	  // Very basic readline/emacs-style bindings, which are standard on Mac.
	  keyMap.emacsy = {
	    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
	    "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp",
	    "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine",
	    "Ctrl-T": "transposeChars", "Ctrl-O": "openLine"
	  };
	  keyMap.macDefault = {
	    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
	    "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
	    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
	    "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
	    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
	    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
	    "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
	    "fallthrough": ["basic", "emacsy"]
	  };
	  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;

	  // KEYMAP DISPATCH

	  function normalizeKeyName(name) {
	    var parts = name.split(/-(?!$)/);
	    name = parts[parts.length - 1];
	    var alt, ctrl, shift, cmd;
	    for (var i = 0; i < parts.length - 1; i++) {
	      var mod = parts[i];
	      if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; }
	      else if (/^a(lt)?$/i.test(mod)) { alt = true; }
	      else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; }
	      else if (/^s(hift)?$/i.test(mod)) { shift = true; }
	      else { throw new Error("Unrecognized modifier name: " + mod) }
	    }
	    if (alt) { name = "Alt-" + name; }
	    if (ctrl) { name = "Ctrl-" + name; }
	    if (cmd) { name = "Cmd-" + name; }
	    if (shift) { name = "Shift-" + name; }
	    return name
	  }

	  // This is a kludge to keep keymaps mostly working as raw objects
	  // (backwards compatibility) while at the same time support features
	  // like normalization and multi-stroke key bindings. It compiles a
	  // new normalized keymap, and then updates the old object to reflect
	  // this.
	  function normalizeKeyMap(keymap) {
	    var copy = {};
	    for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
	      var value = keymap[keyname];
	      if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
	      if (value == "...") { delete keymap[keyname]; continue }

	      var keys = map(keyname.split(" "), normalizeKeyName);
	      for (var i = 0; i < keys.length; i++) {
	        var val = (void 0), name = (void 0);
	        if (i == keys.length - 1) {
	          name = keys.join(" ");
	          val = value;
	        } else {
	          name = keys.slice(0, i + 1).join(" ");
	          val = "...";
	        }
	        var prev = copy[name];
	        if (!prev) { copy[name] = val; }
	        else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
	      }
	      delete keymap[keyname];
	    } }
	    for (var prop in copy) { keymap[prop] = copy[prop]; }
	    return keymap
	  }

	  function lookupKey(key, map, handle, context) {
	    map = getKeyMap(map);
	    var found = map.call ? map.call(key, context) : map[key];
	    if (found === false) { return "nothing" }
	    if (found === "...") { return "multi" }
	    if (found != null && handle(found)) { return "handled" }

	    if (map.fallthrough) {
	      if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
	        { return lookupKey(key, map.fallthrough, handle, context) }
	      for (var i = 0; i < map.fallthrough.length; i++) {
	        var result = lookupKey(key, map.fallthrough[i], handle, context);
	        if (result) { return result }
	      }
	    }
	  }

	  // Modifier key presses don't count as 'real' key presses for the
	  // purpose of keymap fallthrough.
	  function isModifierKey(value) {
	    var name = typeof value == "string" ? value : keyNames[value.keyCode];
	    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
	  }

	  function addModifierNames(name, event, noShift) {
	    var base = name;
	    if (event.altKey && base != "Alt") { name = "Alt-" + name; }
	    if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; }
	    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; }
	    if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; }
	    return name
	  }

	  // Look up the name of a key as indicated by an event object.
	  function keyName(event, noShift) {
	    if (presto && event.keyCode == 34 && event["char"]) { return false }
	    var name = keyNames[event.keyCode];
	    if (name == null || event.altGraphKey) { return false }
	    // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause,
	    // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+)
	    if (event.keyCode == 3 && event.code) { name = event.code; }
	    return addModifierNames(name, event, noShift)
	  }

	  function getKeyMap(val) {
	    return typeof val == "string" ? keyMap[val] : val
	  }

	  // Helper for deleting text near the selection(s), used to implement
	  // backspace, delete, and similar functionality.
	  function deleteNearSelection(cm, compute) {
	    var ranges = cm.doc.sel.ranges, kill = [];
	    // Build up a set of ranges to kill first, merging overlapping
	    // ranges.
	    for (var i = 0; i < ranges.length; i++) {
	      var toKill = compute(ranges[i]);
	      while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
	        var replaced = kill.pop();
	        if (cmp(replaced.from, toKill.from) < 0) {
	          toKill.from = replaced.from;
	          break
	        }
	      }
	      kill.push(toKill);
	    }
	    // Next, remove those actual ranges.
	    runInOp(cm, function () {
	      for (var i = kill.length - 1; i >= 0; i--)
	        { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); }
	      ensureCursorVisible(cm);
	    });
	  }

	  function moveCharLogically(line, ch, dir) {
	    var target = skipExtendingChars(line.text, ch + dir, dir);
	    return target < 0 || target > line.text.length ? null : target
	  }

	  function moveLogically(line, start, dir) {
	    var ch = moveCharLogically(line, start.ch, dir);
	    return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before")
	  }

	  function endOfLine(visually, cm, lineObj, lineNo, dir) {
	    if (visually) {
	      if (cm.doc.direction == "rtl") { dir = -dir; }
	      var order = getOrder(lineObj, cm.doc.direction);
	      if (order) {
	        var part = dir < 0 ? lst(order) : order[0];
	        var moveInStorageOrder = (dir < 0) == (part.level == 1);
	        var sticky = moveInStorageOrder ? "after" : "before";
	        var ch;
	        // With a wrapped rtl chunk (possibly spanning multiple bidi parts),
	        // it could be that the last bidi part is not on the last visual line,
	        // since visual lines contain content order-consecutive chunks.
	        // Thus, in rtl, we are looking for the first (content-order) character
	        // in the rtl chunk that is on the last line (that is, the same line
	        // as the last (content-order) character).
	        if (part.level > 0 || cm.doc.direction == "rtl") {
	          var prep = prepareMeasureForLine(cm, lineObj);
	          ch = dir < 0 ? lineObj.text.length - 1 : 0;
	          var targetTop = measureCharPrepared(cm, prep, ch).top;
	          ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
	          if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
	        } else { ch = dir < 0 ? part.to : part.from; }
	        return new Pos(lineNo, ch, sticky)
	      }
	    }
	    return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after")
	  }

	  function moveVisually(cm, line, start, dir) {
	    var bidi = getOrder(line, cm.doc.direction);
	    if (!bidi) { return moveLogically(line, start, dir) }
	    if (start.ch >= line.text.length) {
	      start.ch = line.text.length;
	      start.sticky = "before";
	    } else if (start.ch <= 0) {
	      start.ch = 0;
	      start.sticky = "after";
	    }
	    var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];
	    if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {
	      // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,
	      // nothing interesting happens.
	      return moveLogically(line, start, dir)
	    }

	    var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };
	    var prep;
	    var getWrappedLineExtent = function (ch) {
	      if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }
	      prep = prep || prepareMeasureForLine(cm, line);
	      return wrappedLineExtentChar(cm, line, prep, ch)
	    };
	    var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch);

	    if (cm.doc.direction == "rtl" || part.level == 1) {
	      var moveInStorageOrder = (part.level == 1) == (dir < 0);
	      var ch = mv(start, moveInStorageOrder ? 1 : -1);
	      if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {
	        // Case 2: We move within an rtl part or in an rtl editor on the same visual line
	        var sticky = moveInStorageOrder ? "before" : "after";
	        return new Pos(start.line, ch, sticky)
	      }
	    }

	    // Case 3: Could not move within this bidi part in this visual line, so leave
	    // the current bidi part

	    var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {
	      var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder
	        ? new Pos(start.line, mv(ch, 1), "before")
	        : new Pos(start.line, ch, "after"); };

	      for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {
	        var part = bidi[partPos];
	        var moveInStorageOrder = (dir > 0) == (part.level != 1);
	        var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);
	        if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }
	        ch = moveInStorageOrder ? part.from : mv(part.to, -1);
	        if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }
	      }
	    };

	    // Case 3a: Look for other bidi parts on the same visual line
	    var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);
	    if (res) { return res }

	    // Case 3b: Look for other bidi parts on the next visual line
	    var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);
	    if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {
	      res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));
	      if (res) { return res }
	    }

	    // Case 4: Nowhere to move
	    return null
	  }

	  // Commands are parameter-less actions that can be performed on an
	  // editor, mostly used for keybindings.
	  var commands = {
	    selectAll: selectAll,
	    singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
	    killLine: function (cm) { return deleteNearSelection(cm, function (range) {
	      if (range.empty()) {
	        var len = getLine(cm.doc, range.head.line).text.length;
	        if (range.head.ch == len && range.head.line < cm.lastLine())
	          { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
	        else
	          { return {from: range.head, to: Pos(range.head.line, len)} }
	      } else {
	        return {from: range.from(), to: range.to()}
	      }
	    }); },
	    deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
	      from: Pos(range.from().line, 0),
	      to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
	    }); }); },
	    delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
	      from: Pos(range.from().line, 0), to: range.from()
	    }); }); },
	    delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
	      var top = cm.charCoords(range.head, "div").top + 5;
	      var leftPos = cm.coordsChar({left: 0, top: top}, "div");
	      return {from: leftPos, to: range.from()}
	    }); },
	    delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
	      var top = cm.charCoords(range.head, "div").top + 5;
	      var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
	      return {from: range.from(), to: rightPos }
	    }); },
	    undo: function (cm) { return cm.undo(); },
	    redo: function (cm) { return cm.redo(); },
	    undoSelection: function (cm) { return cm.undoSelection(); },
	    redoSelection: function (cm) { return cm.redoSelection(); },
	    goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
	    goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
	    goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
	      {origin: "+move", bias: 1}
	    ); },
	    goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
	      {origin: "+move", bias: 1}
	    ); },
	    goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
	      {origin: "+move", bias: -1}
	    ); },
	    goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
	      var top = cm.cursorCoords(range.head, "div").top + 5;
	      return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
	    }, sel_move); },
	    goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
	      var top = cm.cursorCoords(range.head, "div").top + 5;
	      return cm.coordsChar({left: 0, top: top}, "div")
	    }, sel_move); },
	    goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
	      var top = cm.cursorCoords(range.head, "div").top + 5;
	      var pos = cm.coordsChar({left: 0, top: top}, "div");
	      if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
	      return pos
	    }, sel_move); },
	    goLineUp: function (cm) { return cm.moveV(-1, "line"); },
	    goLineDown: function (cm) { return cm.moveV(1, "line"); },
	    goPageUp: function (cm) { return cm.moveV(-1, "page"); },
	    goPageDown: function (cm) { return cm.moveV(1, "page"); },
	    goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
	    goCharRight: function (cm) { return cm.moveH(1, "char"); },
	    goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
	    goColumnRight: function (cm) { return cm.moveH(1, "column"); },
	    goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
	    goGroupRight: function (cm) { return cm.moveH(1, "group"); },
	    goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
	    goWordRight: function (cm) { return cm.moveH(1, "word"); },
	    delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); },
	    delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
	    delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
	    delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
	    delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
	    delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
	    indentAuto: function (cm) { return cm.indentSelection("smart"); },
	    indentMore: function (cm) { return cm.indentSelection("add"); },
	    indentLess: function (cm) { return cm.indentSelection("subtract"); },
	    insertTab: function (cm) { return cm.replaceSelection("\t"); },
	    insertSoftTab: function (cm) {
	      var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
	      for (var i = 0; i < ranges.length; i++) {
	        var pos = ranges[i].from();
	        var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
	        spaces.push(spaceStr(tabSize - col % tabSize));
	      }
	      cm.replaceSelections(spaces);
	    },
	    defaultTab: function (cm) {
	      if (cm.somethingSelected()) { cm.indentSelection("add"); }
	      else { cm.execCommand("insertTab"); }
	    },
	    // Swap the two chars left and right of each selection's head.
	    // Move cursor behind the two swapped characters afterwards.
	    //
	    // Doesn't consider line feeds a character.
	    // Doesn't scan more than one line above to find a character.
	    // Doesn't do anything on an empty line.
	    // Doesn't do anything with non-empty selections.
	    transposeChars: function (cm) { return runInOp(cm, function () {
	      var ranges = cm.listSelections(), newSel = [];
	      for (var i = 0; i < ranges.length; i++) {
	        if (!ranges[i].empty()) { continue }
	        var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
	        if (line) {
	          if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); }
	          if (cur.ch > 0) {
	            cur = new Pos(cur.line, cur.ch + 1);
	            cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
	                            Pos(cur.line, cur.ch - 2), cur, "+transpose");
	          } else if (cur.line > cm.doc.first) {
	            var prev = getLine(cm.doc, cur.line - 1).text;
	            if (prev) {
	              cur = new Pos(cur.line, 1);
	              cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
	                              prev.charAt(prev.length - 1),
	                              Pos(cur.line - 1, prev.length - 1), cur, "+transpose");
	            }
	          }
	        }
	        newSel.push(new Range(cur, cur));
	      }
	      cm.setSelections(newSel);
	    }); },
	    newlineAndIndent: function (cm) { return runInOp(cm, function () {
	      var sels = cm.listSelections();
	      for (var i = sels.length - 1; i >= 0; i--)
	        { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); }
	      sels = cm.listSelections();
	      for (var i$1 = 0; i$1 < sels.length; i$1++)
	        { cm.indentLine(sels[i$1].from().line, null, true); }
	      ensureCursorVisible(cm);
	    }); },
	    openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
	    toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
	  };


	  function lineStart(cm, lineN) {
	    var line = getLine(cm.doc, lineN);
	    var visual = visualLine(line);
	    if (visual != line) { lineN = lineNo(visual); }
	    return endOfLine(true, cm, visual, lineN, 1)
	  }
	  function lineEnd(cm, lineN) {
	    var line = getLine(cm.doc, lineN);
	    var visual = visualLineEnd(line);
	    if (visual != line) { lineN = lineNo(visual); }
	    return endOfLine(true, cm, line, lineN, -1)
	  }
	  function lineStartSmart(cm, pos) {
	    var start = lineStart(cm, pos.line);
	    var line = getLine(cm.doc, start.line);
	    var order = getOrder(line, cm.doc.direction);
	    if (!order || order[0].level == 0) {
	      var firstNonWS = Math.max(start.ch, line.text.search(/\S/));
	      var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
	      return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky)
	    }
	    return start
	  }

	  // Run a handler that was bound to a key.
	  function doHandleBinding(cm, bound, dropShift) {
	    if (typeof bound == "string") {
	      bound = commands[bound];
	      if (!bound) { return false }
	    }
	    // Ensure previous input has been read, so that the handler sees a
	    // consistent view of the document
	    cm.display.input.ensurePolled();
	    var prevShift = cm.display.shift, done = false;
	    try {
	      if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
	      if (dropShift) { cm.display.shift = false; }
	      done = bound(cm) != Pass;
	    } finally {
	      cm.display.shift = prevShift;
	      cm.state.suppressEdits = false;
	    }
	    return done
	  }

	  function lookupKeyForEditor(cm, name, handle) {
	    for (var i = 0; i < cm.state.keyMaps.length; i++) {
	      var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
	      if (result) { return result }
	    }
	    return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
	      || lookupKey(name, cm.options.keyMap, handle, cm)
	  }

	  // Note that, despite the name, this function is also used to check
	  // for bound mouse clicks.

	  var stopSeq = new Delayed;

	  function dispatchKey(cm, name, e, handle) {
	    var seq = cm.state.keySeq;
	    if (seq) {
	      if (isModifierKey(name)) { return "handled" }
	      if (/\'$/.test(name))
	        { cm.state.keySeq = null; }
	      else
	        { stopSeq.set(50, function () {
	          if (cm.state.keySeq == seq) {
	            cm.state.keySeq = null;
	            cm.display.input.reset();
	          }
	        }); }
	      if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true }
	    }
	    return dispatchKeyInner(cm, name, e, handle)
	  }

	  function dispatchKeyInner(cm, name, e, handle) {
	    var result = lookupKeyForEditor(cm, name, handle);

	    if (result == "multi")
	      { cm.state.keySeq = name; }
	    if (result == "handled")
	      { signalLater(cm, "keyHandled", cm, name, e); }

	    if (result == "handled" || result == "multi") {
	      e_preventDefault(e);
	      restartBlink(cm);
	    }

	    return !!result
	  }

	  // Handle a key from the keydown event.
	  function handleKeyBinding(cm, e) {
	    var name = keyName(e, true);
	    if (!name) { return false }

	    if (e.shiftKey && !cm.state.keySeq) {
	      // First try to resolve full name (including 'Shift-'). Failing
	      // that, see if there is a cursor-motion command (starting with
	      // 'go') bound to the keyname without 'Shift-'.
	      return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
	          || dispatchKey(cm, name, e, function (b) {
	               if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
	                 { return doHandleBinding(cm, b) }
	             })
	    } else {
	      return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
	    }
	  }

	  // Handle a key from the keypress event
	  function handleCharBinding(cm, e, ch) {
	    return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
	  }

	  var lastStoppedKey = null;
	  function onKeyDown(e) {
	    var cm = this;
	    if (e.target && e.target != cm.display.input.getField()) { return }
	    cm.curOp.focus = activeElt(doc(cm));
	    if (signalDOMEvent(cm, e)) { return }
	    // IE does strange things with escape.
	    if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; }
	    var code = e.keyCode;
	    cm.display.shift = code == 16 || e.shiftKey;
	    var handled = handleKeyBinding(cm, e);
	    if (presto) {
	      lastStoppedKey = handled ? code : null;
	      // Opera has no cut event... we try to at least catch the key combo
	      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
	        { cm.replaceSelection("", null, "cut"); }
	    }
	    if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand)
	      { document.execCommand("cut"); }

	    // Turn mouse into crosshair when Alt is held on Mac.
	    if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
	      { showCrossHair(cm); }
	  }

	  function showCrossHair(cm) {
	    var lineDiv = cm.display.lineDiv;
	    addClass(lineDiv, "CodeMirror-crosshair");

	    function up(e) {
	      if (e.keyCode == 18 || !e.altKey) {
	        rmClass(lineDiv, "CodeMirror-crosshair");
	        off(document, "keyup", up);
	        off(document, "mouseover", up);
	      }
	    }
	    on(document, "keyup", up);
	    on(document, "mouseover", up);
	  }

	  function onKeyUp(e) {
	    if (e.keyCode == 16) { this.doc.sel.shift = false; }
	    signalDOMEvent(this, e);
	  }

	  function onKeyPress(e) {
	    var cm = this;
	    if (e.target && e.target != cm.display.input.getField()) { return }
	    if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
	    var keyCode = e.keyCode, charCode = e.charCode;
	    if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
	    if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
	    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
	    // Some browsers fire keypress events for backspace
	    if (ch == "\x08") { return }
	    if (handleCharBinding(cm, e, ch)) { return }
	    cm.display.input.onKeyPress(e);
	  }

	  var DOUBLECLICK_DELAY = 400;

	  var PastClick = function(time, pos, button) {
	    this.time = time;
	    this.pos = pos;
	    this.button = button;
	  };

	  PastClick.prototype.compare = function (time, pos, button) {
	    return this.time + DOUBLECLICK_DELAY > time &&
	      cmp(pos, this.pos) == 0 && button == this.button
	  };

	  var lastClick, lastDoubleClick;
	  function clickRepeat(pos, button) {
	    var now = +new Date;
	    if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) {
	      lastClick = lastDoubleClick = null;
	      return "triple"
	    } else if (lastClick && lastClick.compare(now, pos, button)) {
	      lastDoubleClick = new PastClick(now, pos, button);
	      lastClick = null;
	      return "double"
	    } else {
	      lastClick = new PastClick(now, pos, button);
	      lastDoubleClick = null;
	      return "single"
	    }
	  }

	  // A mouse down can be a single click, double click, triple click,
	  // start of selection drag, start of text drag, new cursor
	  // (ctrl-click), rectangle drag (alt-drag), or xwin
	  // middle-click-paste. Or it might be a click on something we should
	  // not interfere with, such as a scrollbar or widget.
	  function onMouseDown(e) {
	    var cm = this, display = cm.display;
	    if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
	    display.input.ensurePolled();
	    display.shift = e.shiftKey;

	    if (eventInWidget(display, e)) {
	      if (!webkit) {
	        // Briefly turn off draggability, to allow widgets to do
	        // normal dragging things.
	        display.scroller.draggable = false;
	        setTimeout(function () { return display.scroller.draggable = true; }, 100);
	      }
	      return
	    }
	    if (clickInGutter(cm, e)) { return }
	    var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single";
	    win(cm).focus();

	    // #3261: make sure, that we're not starting a second selection
	    if (button == 1 && cm.state.selectingText)
	      { cm.state.selectingText(e); }

	    if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return }

	    if (button == 1) {
	      if (pos) { leftButtonDown(cm, pos, repeat, e); }
	      else if (e_target(e) == display.scroller) { e_preventDefault(e); }
	    } else if (button == 2) {
	      if (pos) { extendSelection(cm.doc, pos); }
	      setTimeout(function () { return display.input.focus(); }, 20);
	    } else if (button == 3) {
	      if (captureRightClick) { cm.display.input.onContextMenu(e); }
	      else { delayBlurEvent(cm); }
	    }
	  }

	  function handleMappedButton(cm, button, pos, repeat, event) {
	    var name = "Click";
	    if (repeat == "double") { name = "Double" + name; }
	    else if (repeat == "triple") { name = "Triple" + name; }
	    name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name;

	    return dispatchKey(cm,  addModifierNames(name, event), event, function (bound) {
	      if (typeof bound == "string") { bound = commands[bound]; }
	      if (!bound) { return false }
	      var done = false;
	      try {
	        if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
	        done = bound(cm, pos) != Pass;
	      } finally {
	        cm.state.suppressEdits = false;
	      }
	      return done
	    })
	  }

	  function configureMouse(cm, repeat, event) {
	    var option = cm.getOption("configureMouse");
	    var value = option ? option(cm, repeat, event) : {};
	    if (value.unit == null) {
	      var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey;
	      value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line";
	    }
	    if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; }
	    if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; }
	    if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); }
	    return value
	  }

	  function leftButtonDown(cm, pos, repeat, event) {
	    if (ie) { setTimeout(bind(ensureFocus, cm), 0); }
	    else { cm.curOp.focus = activeElt(doc(cm)); }

	    var behavior = configureMouse(cm, repeat, event);

	    var sel = cm.doc.sel, contained;
	    if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
	        repeat == "single" && (contained = sel.contains(pos)) > -1 &&
	        (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) &&
	        (cmp(contained.to(), pos) > 0 || pos.xRel < 0))
	      { leftButtonStartDrag(cm, event, pos, behavior); }
	    else
	      { leftButtonSelect(cm, event, pos, behavior); }
	  }

	  // Start a text drag. When it ends, see if any dragging actually
	  // happen, and treat as a click if it didn't.
	  function leftButtonStartDrag(cm, event, pos, behavior) {
	    var display = cm.display, moved = false;
	    var dragEnd = operation(cm, function (e) {
	      if (webkit) { display.scroller.draggable = false; }
	      cm.state.draggingText = false;
	      if (cm.state.delayingBlurEvent) {
	        if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; }
	        else { delayBlurEvent(cm); }
	      }
	      off(display.wrapper.ownerDocument, "mouseup", dragEnd);
	      off(display.wrapper.ownerDocument, "mousemove", mouseMove);
	      off(display.scroller, "dragstart", dragStart);
	      off(display.scroller, "drop", dragEnd);
	      if (!moved) {
	        e_preventDefault(e);
	        if (!behavior.addNew)
	          { extendSelection(cm.doc, pos, null, null, behavior.extend); }
	        // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
	        if ((webkit && !safari) || ie && ie_version == 9)
	          { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); }
	        else
	          { display.input.focus(); }
	      }
	    });
	    var mouseMove = function(e2) {
	      moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10;
	    };
	    var dragStart = function () { return moved = true; };
	    // Let the drag handler handle this.
	    if (webkit) { display.scroller.draggable = true; }
	    cm.state.draggingText = dragEnd;
	    dragEnd.copy = !behavior.moveOnDrag;
	    on(display.wrapper.ownerDocument, "mouseup", dragEnd);
	    on(display.wrapper.ownerDocument, "mousemove", mouseMove);
	    on(display.scroller, "dragstart", dragStart);
	    on(display.scroller, "drop", dragEnd);

	    cm.state.delayingBlurEvent = true;
	    setTimeout(function () { return display.input.focus(); }, 20);
	    // IE's approach to draggable
	    if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
	  }

	  function rangeForUnit(cm, pos, unit) {
	    if (unit == "char") { return new Range(pos, pos) }
	    if (unit == "word") { return cm.findWordAt(pos) }
	    if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
	    var result = unit(cm, pos);
	    return new Range(result.from, result.to)
	  }

	  // Normal selection, as opposed to text dragging.
	  function leftButtonSelect(cm, event, start, behavior) {
	    if (ie) { delayBlurEvent(cm); }
	    var display = cm.display, doc$1 = cm.doc;
	    e_preventDefault(event);

	    var ourRange, ourIndex, startSel = doc$1.sel, ranges = startSel.ranges;
	    if (behavior.addNew && !behavior.extend) {
	      ourIndex = doc$1.sel.contains(start);
	      if (ourIndex > -1)
	        { ourRange = ranges[ourIndex]; }
	      else
	        { ourRange = new Range(start, start); }
	    } else {
	      ourRange = doc$1.sel.primary();
	      ourIndex = doc$1.sel.primIndex;
	    }

	    if (behavior.unit == "rectangle") {
	      if (!behavior.addNew) { ourRange = new Range(start, start); }
	      start = posFromMouse(cm, event, true, true);
	      ourIndex = -1;
	    } else {
	      var range = rangeForUnit(cm, start, behavior.unit);
	      if (behavior.extend)
	        { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); }
	      else
	        { ourRange = range; }
	    }

	    if (!behavior.addNew) {
	      ourIndex = 0;
	      setSelection(doc$1, new Selection([ourRange], 0), sel_mouse);
	      startSel = doc$1.sel;
	    } else if (ourIndex == -1) {
	      ourIndex = ranges.length;
	      setSelection(doc$1, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex),
	                   {scroll: false, origin: "*mouse"});
	    } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) {
	      setSelection(doc$1, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
	                   {scroll: false, origin: "*mouse"});
	      startSel = doc$1.sel;
	    } else {
	      replaceOneSelection(doc$1, ourIndex, ourRange, sel_mouse);
	    }

	    var lastPos = start;
	    function extendTo(pos) {
	      if (cmp(lastPos, pos) == 0) { return }
	      lastPos = pos;

	      if (behavior.unit == "rectangle") {
	        var ranges = [], tabSize = cm.options.tabSize;
	        var startCol = countColumn(getLine(doc$1, start.line).text, start.ch, tabSize);
	        var posCol = countColumn(getLine(doc$1, pos.line).text, pos.ch, tabSize);
	        var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
	        for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
	             line <= end; line++) {
	          var text = getLine(doc$1, line).text, leftPos = findColumn(text, left, tabSize);
	          if (left == right)
	            { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); }
	          else if (text.length > leftPos)
	            { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); }
	        }
	        if (!ranges.length) { ranges.push(new Range(start, start)); }
	        setSelection(doc$1, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
	                     {origin: "*mouse", scroll: false});
	        cm.scrollIntoView(pos);
	      } else {
	        var oldRange = ourRange;
	        var range = rangeForUnit(cm, pos, behavior.unit);
	        var anchor = oldRange.anchor, head;
	        if (cmp(range.anchor, anchor) > 0) {
	          head = range.head;
	          anchor = minPos(oldRange.from(), range.anchor);
	        } else {
	          head = range.anchor;
	          anchor = maxPos(oldRange.to(), range.head);
	        }
	        var ranges$1 = startSel.ranges.slice(0);
	        ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc$1, anchor), head));
	        setSelection(doc$1, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse);
	      }
	    }

	    var editorSize = display.wrapper.getBoundingClientRect();
	    // Used to ensure timeout re-tries don't fire when another extend
	    // happened in the meantime (clearTimeout isn't reliable -- at
	    // least on Chrome, the timeouts still happen even when cleared,
	    // if the clear happens after their scheduled firing time).
	    var counter = 0;

	    function extend(e) {
	      var curCount = ++counter;
	      var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle");
	      if (!cur) { return }
	      if (cmp(cur, lastPos) != 0) {
	        cm.curOp.focus = activeElt(doc(cm));
	        extendTo(cur);
	        var visible = visibleLines(display, doc$1);
	        if (cur.line >= visible.to || cur.line < visible.from)
	          { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); }
	      } else {
	        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
	        if (outside) { setTimeout(operation(cm, function () {
	          if (counter != curCount) { return }
	          display.scroller.scrollTop += outside;
	          extend(e);
	        }), 50); }
	      }
	    }

	    function done(e) {
	      cm.state.selectingText = false;
	      counter = Infinity;
	      // If e is null or undefined we interpret this as someone trying
	      // to explicitly cancel the selection rather than the user
	      // letting go of the mouse button.
	      if (e) {
	        e_preventDefault(e);
	        display.input.focus();
	      }
	      off(display.wrapper.ownerDocument, "mousemove", move);
	      off(display.wrapper.ownerDocument, "mouseup", up);
	      doc$1.history.lastSelOrigin = null;
	    }

	    var move = operation(cm, function (e) {
	      if (e.buttons === 0 || !e_button(e)) { done(e); }
	      else { extend(e); }
	    });
	    var up = operation(cm, done);
	    cm.state.selectingText = up;
	    on(display.wrapper.ownerDocument, "mousemove", move);
	    on(display.wrapper.ownerDocument, "mouseup", up);
	  }

	  // Used when mouse-selecting to adjust the anchor to the proper side
	  // of a bidi jump depending on the visual position of the head.
	  function bidiSimplify(cm, range) {
	    var anchor = range.anchor;
	    var head = range.head;
	    var anchorLine = getLine(cm.doc, anchor.line);
	    if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range }
	    var order = getOrder(anchorLine);
	    if (!order) { return range }
	    var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index];
	    if (part.from != anchor.ch && part.to != anchor.ch) { return range }
	    var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1);
	    if (boundary == 0 || boundary == order.length) { return range }

	    // Compute the relative visual position of the head compared to the
	    // anchor (<0 is to the left, >0 to the right)
	    var leftSide;
	    if (head.line != anchor.line) {
	      leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0;
	    } else {
	      var headIndex = getBidiPartAt(order, head.ch, head.sticky);
	      var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1);
	      if (headIndex == boundary - 1 || headIndex == boundary)
	        { leftSide = dir < 0; }
	      else
	        { leftSide = dir > 0; }
	    }

	    var usePart = order[boundary + (leftSide ? -1 : 0)];
	    var from = leftSide == (usePart.level == 1);
	    var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before";
	    return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head)
	  }


	  // Determines whether an event happened in the gutter, and fires the
	  // handlers for the corresponding event.
	  function gutterEvent(cm, e, type, prevent) {
	    var mX, mY;
	    if (e.touches) {
	      mX = e.touches[0].clientX;
	      mY = e.touches[0].clientY;
	    } else {
	      try { mX = e.clientX; mY = e.clientY; }
	      catch(e$1) { return false }
	    }
	    if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
	    if (prevent) { e_preventDefault(e); }

	    var display = cm.display;
	    var lineBox = display.lineDiv.getBoundingClientRect();

	    if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
	    mY -= lineBox.top - display.viewOffset;

	    for (var i = 0; i < cm.display.gutterSpecs.length; ++i) {
	      var g = display.gutters.childNodes[i];
	      if (g && g.getBoundingClientRect().right >= mX) {
	        var line = lineAtHeight(cm.doc, mY);
	        var gutter = cm.display.gutterSpecs[i];
	        signal(cm, type, cm, line, gutter.className, e);
	        return e_defaultPrevented(e)
	      }
	    }
	  }

	  function clickInGutter(cm, e) {
	    return gutterEvent(cm, e, "gutterClick", true)
	  }

	  // CONTEXT MENU HANDLING

	  // To make the context menu work, we need to briefly unhide the
	  // textarea (making it as unobtrusive as possible) to let the
	  // right-click take effect on it.
	  function onContextMenu(cm, e) {
	    if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
	    if (signalDOMEvent(cm, e, "contextmenu")) { return }
	    if (!captureRightClick) { cm.display.input.onContextMenu(e); }
	  }

	  function contextMenuInGutter(cm, e) {
	    if (!hasHandler(cm, "gutterContextMenu")) { return false }
	    return gutterEvent(cm, e, "gutterContextMenu", false)
	  }

	  function themeChanged(cm) {
	    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
	      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
	    clearCaches(cm);
	  }

	  var Init = {toString: function(){return "CodeMirror.Init"}};

	  var defaults = {};
	  var optionHandlers = {};

	  function defineOptions(CodeMirror) {
	    var optionHandlers = CodeMirror.optionHandlers;

	    function option(name, deflt, handle, notOnInit) {
	      CodeMirror.defaults[name] = deflt;
	      if (handle) { optionHandlers[name] =
	        notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; }
	    }

	    CodeMirror.defineOption = option;

	    // Passed to option handlers when there is no old value.
	    CodeMirror.Init = Init;

	    // These two are, on init, called from the constructor because they
	    // have to be initialized before the editor can start at all.
	    option("value", "", function (cm, val) { return cm.setValue(val); }, true);
	    option("mode", null, function (cm, val) {
	      cm.doc.modeOption = val;
	      loadMode(cm);
	    }, true);

	    option("indentUnit", 2, loadMode, true);
	    option("indentWithTabs", false);
	    option("smartIndent", true);
	    option("tabSize", 4, function (cm) {
	      resetModeState(cm);
	      clearCaches(cm);
	      regChange(cm);
	    }, true);

	    option("lineSeparator", null, function (cm, val) {
	      cm.doc.lineSep = val;
	      if (!val) { return }
	      var newBreaks = [], lineNo = cm.doc.first;
	      cm.doc.iter(function (line) {
	        for (var pos = 0;;) {
	          var found = line.text.indexOf(val, pos);
	          if (found == -1) { break }
	          pos = found + val.length;
	          newBreaks.push(Pos(lineNo, found));
	        }
	        lineNo++;
	      });
	      for (var i = newBreaks.length - 1; i >= 0; i--)
	        { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
	    });
	    option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
	      cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
	      if (old != Init) { cm.refresh(); }
	    });
	    option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);
	    option("electricChars", true);
	    option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
	      throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
	    }, true);
	    option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true);
	    option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true);
	    option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true);
	    option("rtlMoveVisually", !windows);
	    option("wholeLineUpdateBefore", true);

	    option("theme", "default", function (cm) {
	      themeChanged(cm);
	      updateGutters(cm);
	    }, true);
	    option("keyMap", "default", function (cm, val, old) {
	      var next = getKeyMap(val);
	      var prev = old != Init && getKeyMap(old);
	      if (prev && prev.detach) { prev.detach(cm, next); }
	      if (next.attach) { next.attach(cm, prev || null); }
	    });
	    option("extraKeys", null);
	    option("configureMouse", null);

	    option("lineWrapping", false, wrappingChanged, true);
	    option("gutters", [], function (cm, val) {
	      cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers);
	      updateGutters(cm);
	    }, true);
	    option("fixedGutter", true, function (cm, val) {
	      cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
	      cm.refresh();
	    }, true);
	    option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true);
	    option("scrollbarStyle", "native", function (cm) {
	      initScrollbars(cm);
	      updateScrollbars(cm);
	      cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
	      cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
	    }, true);
	    option("lineNumbers", false, function (cm, val) {
	      cm.display.gutterSpecs = getGutters(cm.options.gutters, val);
	      updateGutters(cm);
	    }, true);
	    option("firstLineNumber", 1, updateGutters, true);
	    option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true);
	    option("showCursorWhenSelecting", false, updateSelection, true);

	    option("resetSelectionOnContextMenu", true);
	    option("lineWiseCopyCut", true);
	    option("pasteLinesPerSelection", true);
	    option("selectionsMayTouch", false);

	    option("readOnly", false, function (cm, val) {
	      if (val == "nocursor") {
	        onBlur(cm);
	        cm.display.input.blur();
	      }
	      cm.display.input.readOnlyChanged(val);
	    });

	    option("screenReaderLabel", null, function (cm, val) {
	      val = (val === '') ? null : val;
	      cm.display.input.screenReaderLabelChanged(val);
	    });

	    option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true);
	    option("dragDrop", true, dragDropChanged);
	    option("allowDropFileTypes", null);

	    option("cursorBlinkRate", 530);
	    option("cursorScrollMargin", 0);
	    option("cursorHeight", 1, updateSelection, true);
	    option("singleCursorHeightPerLine", true, updateSelection, true);
	    option("workTime", 100);
	    option("workDelay", 100);
	    option("flattenSpans", true, resetModeState, true);
	    option("addModeClass", false, resetModeState, true);
	    option("pollInterval", 100);
	    option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; });
	    option("historyEventDelay", 1250);
	    option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true);
	    option("maxHighlightLength", 10000, resetModeState, true);
	    option("moveInputWithCursor", true, function (cm, val) {
	      if (!val) { cm.display.input.resetPosition(); }
	    });

	    option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; });
	    option("autofocus", null);
	    option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true);
	    option("phrases", null);
	  }

	  function dragDropChanged(cm, value, old) {
	    var wasOn = old && old != Init;
	    if (!value != !wasOn) {
	      var funcs = cm.display.dragFunctions;
	      var toggle = value ? on : off;
	      toggle(cm.display.scroller, "dragstart", funcs.start);
	      toggle(cm.display.scroller, "dragenter", funcs.enter);
	      toggle(cm.display.scroller, "dragover", funcs.over);
	      toggle(cm.display.scroller, "dragleave", funcs.leave);
	      toggle(cm.display.scroller, "drop", funcs.drop);
	    }
	  }

	  function wrappingChanged(cm) {
	    if (cm.options.lineWrapping) {
	      addClass(cm.display.wrapper, "CodeMirror-wrap");
	      cm.display.sizer.style.minWidth = "";
	      cm.display.sizerWidth = null;
	    } else {
	      rmClass(cm.display.wrapper, "CodeMirror-wrap");
	      findMaxLine(cm);
	    }
	    estimateLineHeights(cm);
	    regChange(cm);
	    clearCaches(cm);
	    setTimeout(function () { return updateScrollbars(cm); }, 100);
	  }

	  // A CodeMirror instance represents an editor. This is the object
	  // that user code is usually dealing with.

	  function CodeMirror(place, options) {
	    var this$1$1 = this;

	    if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }

	    this.options = options = options ? copyObj(options) : {};
	    // Determine effective options based on given values and defaults.
	    copyObj(defaults, options, false);

	    var doc = options.value;
	    if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); }
	    else if (options.mode) { doc.modeOption = options.mode; }
	    this.doc = doc;

	    var input = new CodeMirror.inputStyles[options.inputStyle](this);
	    var display = this.display = new Display(place, doc, input, options);
	    display.wrapper.CodeMirror = this;
	    themeChanged(this);
	    if (options.lineWrapping)
	      { this.display.wrapper.className += " CodeMirror-wrap"; }
	    initScrollbars(this);

	    this.state = {
	      keyMaps: [],  // stores maps added by addKeyMap
	      overlays: [], // highlighting overlays, as added by addOverlay
	      modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
	      overwrite: false,
	      delayingBlurEvent: false,
	      focused: false,
	      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
	      pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll
	      selectingText: false,
	      draggingText: false,
	      highlight: new Delayed(), // stores highlight worker timeout
	      keySeq: null,  // Unfinished key sequence
	      specialChars: null
	    };

	    if (options.autofocus && !mobile) { display.input.focus(); }

	    // Override magic textarea content restore that IE sometimes does
	    // on our hidden textarea on reload
	    if (ie && ie_version < 11) { setTimeout(function () { return this$1$1.display.input.reset(true); }, 20); }

	    registerEventHandlers(this);
	    ensureGlobalHandlers();

	    startOperation(this);
	    this.curOp.forceUpdate = true;
	    attachDoc(this, doc);

	    if ((options.autofocus && !mobile) || this.hasFocus())
	      { setTimeout(function () {
	        if (this$1$1.hasFocus() && !this$1$1.state.focused) { onFocus(this$1$1); }
	      }, 20); }
	    else
	      { onBlur(this); }

	    for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
	      { optionHandlers[opt](this, options[opt], Init); } }
	    maybeUpdateLineNumberWidth(this);
	    if (options.finishInit) { options.finishInit(this); }
	    for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); }
	    endOperation(this);
	    // Suppress optimizelegibility in Webkit, since it breaks text
	    // measuring on line wrapping boundaries.
	    if (webkit && options.lineWrapping &&
	        getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
	      { display.lineDiv.style.textRendering = "auto"; }
	  }

	  // The default configuration options.
	  CodeMirror.defaults = defaults;
	  // Functions to run when options are changed.
	  CodeMirror.optionHandlers = optionHandlers;

	  // Attach the necessary event handlers when initializing the editor
	  function registerEventHandlers(cm) {
	    var d = cm.display;
	    on(d.scroller, "mousedown", operation(cm, onMouseDown));
	    // Older IE's will not fire a second mousedown for a double click
	    if (ie && ie_version < 11)
	      { on(d.scroller, "dblclick", operation(cm, function (e) {
	        if (signalDOMEvent(cm, e)) { return }
	        var pos = posFromMouse(cm, e);
	        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
	        e_preventDefault(e);
	        var word = cm.findWordAt(pos);
	        extendSelection(cm.doc, word.anchor, word.head);
	      })); }
	    else
	      { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); }
	    // Some browsers fire contextmenu *after* opening the menu, at
	    // which point we can't mess with it anymore. Context menu is
	    // handled in onMouseDown for these browsers.
	    on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); });
	    on(d.input.getField(), "contextmenu", function (e) {
	      if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); }
	    });

	    // Used to suppress mouse event handling when a touch happens
	    var touchFinished, prevTouch = {end: 0};
	    function finishTouch() {
	      if (d.activeTouch) {
	        touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000);
	        prevTouch = d.activeTouch;
	        prevTouch.end = +new Date;
	      }
	    }
	    function isMouseLikeTouchEvent(e) {
	      if (e.touches.length != 1) { return false }
	      var touch = e.touches[0];
	      return touch.radiusX <= 1 && touch.radiusY <= 1
	    }
	    function farAway(touch, other) {
	      if (other.left == null) { return true }
	      var dx = other.left - touch.left, dy = other.top - touch.top;
	      return dx * dx + dy * dy > 20 * 20
	    }
	    on(d.scroller, "touchstart", function (e) {
	      if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) {
	        d.input.ensurePolled();
	        clearTimeout(touchFinished);
	        var now = +new Date;
	        d.activeTouch = {start: now, moved: false,
	                         prev: now - prevTouch.end <= 300 ? prevTouch : null};
	        if (e.touches.length == 1) {
	          d.activeTouch.left = e.touches[0].pageX;
	          d.activeTouch.top = e.touches[0].pageY;
	        }
	      }
	    });
	    on(d.scroller, "touchmove", function () {
	      if (d.activeTouch) { d.activeTouch.moved = true; }
	    });
	    on(d.scroller, "touchend", function (e) {
	      var touch = d.activeTouch;
	      if (touch && !eventInWidget(d, e) && touch.left != null &&
	          !touch.moved && new Date - touch.start < 300) {
	        var pos = cm.coordsChar(d.activeTouch, "page"), range;
	        if (!touch.prev || farAway(touch, touch.prev)) // Single tap
	          { range = new Range(pos, pos); }
	        else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
	          { range = cm.findWordAt(pos); }
	        else // Triple tap
	          { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); }
	        cm.setSelection(range.anchor, range.head);
	        cm.focus();
	        e_preventDefault(e);
	      }
	      finishTouch();
	    });
	    on(d.scroller, "touchcancel", finishTouch);

	    // Sync scrolling between fake scrollbars and real scrollable
	    // area, ensure viewport is updated when scrolling.
	    on(d.scroller, "scroll", function () {
	      if (d.scroller.clientHeight) {
	        updateScrollTop(cm, d.scroller.scrollTop);
	        setScrollLeft(cm, d.scroller.scrollLeft, true);
	        signal(cm, "scroll", cm);
	      }
	    });

	    // Listen to wheel events in order to try and update the viewport on time.
	    on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); });
	    on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); });

	    // Prevent wrapper from ever scrolling
	    on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });

	    d.dragFunctions = {
	      enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }},
	      over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
	      start: function (e) { return onDragStart(cm, e); },
	      drop: operation(cm, onDrop),
	      leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}
	    };

	    var inp = d.input.getField();
	    on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); });
	    on(inp, "keydown", operation(cm, onKeyDown));
	    on(inp, "keypress", operation(cm, onKeyPress));
	    on(inp, "focus", function (e) { return onFocus(cm, e); });
	    on(inp, "blur", function (e) { return onBlur(cm, e); });
	  }

	  var initHooks = [];
	  CodeMirror.defineInitHook = function (f) { return initHooks.push(f); };

	  // Indent the given line. The how parameter can be "smart",
	  // "add"/null, "subtract", or "prev". When aggressive is false
	  // (typically set to true for forced single-line indents), empty
	  // lines are not indented, and places where the mode returns Pass
	  // are left alone.
	  function indentLine(cm, n, how, aggressive) {
	    var doc = cm.doc, state;
	    if (how == null) { how = "add"; }
	    if (how == "smart") {
	      // Fall back to "prev" when the mode doesn't have an indentation
	      // method.
	      if (!doc.mode.indent) { how = "prev"; }
	      else { state = getContextBefore(cm, n).state; }
	    }

	    var tabSize = cm.options.tabSize;
	    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
	    if (line.stateAfter) { line.stateAfter = null; }
	    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
	    if (!aggressive && !/\S/.test(line.text)) {
	      indentation = 0;
	      how = "not";
	    } else if (how == "smart") {
	      indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
	      if (indentation == Pass || indentation > 150) {
	        if (!aggressive) { return }
	        how = "prev";
	      }
	    }
	    if (how == "prev") {
	      if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); }
	      else { indentation = 0; }
	    } else if (how == "add") {
	      indentation = curSpace + cm.options.indentUnit;
	    } else if (how == "subtract") {
	      indentation = curSpace - cm.options.indentUnit;
	    } else if (typeof how == "number") {
	      indentation = curSpace + how;
	    }
	    indentation = Math.max(0, indentation);

	    var indentString = "", pos = 0;
	    if (cm.options.indentWithTabs)
	      { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} }
	    if (pos < indentation) { indentString += spaceStr(indentation - pos); }

	    if (indentString != curSpaceString) {
	      replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
	      line.stateAfter = null;
	      return true
	    } else {
	      // Ensure that, if the cursor was in the whitespace at the start
	      // of the line, it is moved to the end of that space.
	      for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
	        var range = doc.sel.ranges[i$1];
	        if (range.head.line == n && range.head.ch < curSpaceString.length) {
	          var pos$1 = Pos(n, curSpaceString.length);
	          replaceOneSelection(doc, i$1, new Range(pos$1, pos$1));
	          break
	        }
	      }
	    }
	  }

	  // This will be set to a {lineWise: bool, text: [string]} object, so
	  // that, when pasting, we know what kind of selections the copied
	  // text was made out of.
	  var lastCopied = null;

	  function setLastCopied(newLastCopied) {
	    lastCopied = newLastCopied;
	  }

	  function applyTextInput(cm, inserted, deleted, sel, origin) {
	    var doc = cm.doc;
	    cm.display.shift = false;
	    if (!sel) { sel = doc.sel; }

	    var recent = +new Date - 200;
	    var paste = origin == "paste" || cm.state.pasteIncoming > recent;
	    var textLines = splitLinesAuto(inserted), multiPaste = null;
	    // When pasting N lines into N selections, insert one line per selection
	    if (paste && sel.ranges.length > 1) {
	      if (lastCopied && lastCopied.text.join("\n") == inserted) {
	        if (sel.ranges.length % lastCopied.text.length == 0) {
	          multiPaste = [];
	          for (var i = 0; i < lastCopied.text.length; i++)
	            { multiPaste.push(doc.splitLines(lastCopied.text[i])); }
	        }
	      } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) {
	        multiPaste = map(textLines, function (l) { return [l]; });
	      }
	    }

	    var updateInput = cm.curOp.updateInput;
	    // Normal behavior is to insert the new text into every selection
	    for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
	      var range = sel.ranges[i$1];
	      var from = range.from(), to = range.to();
	      if (range.empty()) {
	        if (deleted && deleted > 0) // Handle deletion
	          { from = Pos(from.line, from.ch - deleted); }
	        else if (cm.state.overwrite && !paste) // Handle overwrite
	          { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }
	        else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n"))
	          { from = to = Pos(from.line, 0); }
	      }
	      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
	                         origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")};
	      makeChange(cm.doc, changeEvent);
	      signalLater(cm, "inputRead", cm, changeEvent);
	    }
	    if (inserted && !paste)
	      { triggerElectric(cm, inserted); }

	    ensureCursorVisible(cm);
	    if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; }
	    cm.curOp.typing = true;
	    cm.state.pasteIncoming = cm.state.cutIncoming = -1;
	  }

	  function handlePaste(e, cm) {
	    var pasted = e.clipboardData && e.clipboardData.getData("Text");
	    if (pasted) {
	      e.preventDefault();
	      if (!cm.isReadOnly() && !cm.options.disableInput && cm.hasFocus())
	        { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); }
	      return true
	    }
	  }

	  function triggerElectric(cm, inserted) {
	    // When an 'electric' character is inserted, immediately trigger a reindent
	    if (!cm.options.electricChars || !cm.options.smartIndent) { return }
	    var sel = cm.doc.sel;

	    for (var i = sel.ranges.length - 1; i >= 0; i--) {
	      var range = sel.ranges[i];
	      if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
	      var mode = cm.getModeAt(range.head);
	      var indented = false;
	      if (mode.electricChars) {
	        for (var j = 0; j < mode.electricChars.length; j++)
	          { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
	            indented = indentLine(cm, range.head.line, "smart");
	            break
	          } }
	      } else if (mode.electricInput) {
	        if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
	          { indented = indentLine(cm, range.head.line, "smart"); }
	      }
	      if (indented) { signalLater(cm, "electricInput", cm, range.head.line); }
	    }
	  }

	  function copyableRanges(cm) {
	    var text = [], ranges = [];
	    for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
	      var line = cm.doc.sel.ranges[i].head.line;
	      var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
	      ranges.push(lineRange);
	      text.push(cm.getRange(lineRange.anchor, lineRange.head));
	    }
	    return {text: text, ranges: ranges}
	  }

	  function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) {
	    field.setAttribute("autocorrect", autocorrect ? "" : "off");
	    field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
	    field.setAttribute("spellcheck", !!spellcheck);
	  }

	  function hiddenTextarea() {
	    var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none");
	    var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
	    // The textarea is kept positioned near the cursor to prevent the
	    // fact that it'll be scrolled into view on input from scrolling
	    // our fake cursor out of view. On webkit, when wrap=off, paste is
	    // very slow. So make the area wide instead.
	    if (webkit) { te.style.width = "1000px"; }
	    else { te.setAttribute("wrap", "off"); }
	    // If border: 0; -- iOS fails to open keyboard (issue #1287)
	    if (ios) { te.style.border = "1px solid black"; }
	    disableBrowserMagic(te);
	    return div
	  }

	  // The publicly visible API. Note that methodOp(f) means
	  // 'wrap f in an operation, performed on its `this` parameter'.

	  // This is not the complete set of editor methods. Most of the
	  // methods defined on the Doc type are also injected into
	  // CodeMirror.prototype, for backwards compatibility and
	  // convenience.

	  function addEditorMethods(CodeMirror) {
	    var optionHandlers = CodeMirror.optionHandlers;

	    var helpers = CodeMirror.helpers = {};

	    CodeMirror.prototype = {
	      constructor: CodeMirror,
	      focus: function(){win(this).focus(); this.display.input.focus();},

	      setOption: function(option, value) {
	        var options = this.options, old = options[option];
	        if (options[option] == value && option != "mode") { return }
	        options[option] = value;
	        if (optionHandlers.hasOwnProperty(option))
	          { operation(this, optionHandlers[option])(this, value, old); }
	        signal(this, "optionChange", this, option);
	      },

	      getOption: function(option) {return this.options[option]},
	      getDoc: function() {return this.doc},

	      addKeyMap: function(map, bottom) {
	        this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
	      },
	      removeKeyMap: function(map) {
	        var maps = this.state.keyMaps;
	        for (var i = 0; i < maps.length; ++i)
	          { if (maps[i] == map || maps[i].name == map) {
	            maps.splice(i, 1);
	            return true
	          } }
	      },

	      addOverlay: methodOp(function(spec, options) {
	        var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
	        if (mode.startState) { throw new Error("Overlays may not be stateful.") }
	        insertSorted(this.state.overlays,
	                     {mode: mode, modeSpec: spec, opaque: options && options.opaque,
	                      priority: (options && options.priority) || 0},
	                     function (overlay) { return overlay.priority; });
	        this.state.modeGen++;
	        regChange(this);
	      }),
	      removeOverlay: methodOp(function(spec) {
	        var overlays = this.state.overlays;
	        for (var i = 0; i < overlays.length; ++i) {
	          var cur = overlays[i].modeSpec;
	          if (cur == spec || typeof spec == "string" && cur.name == spec) {
	            overlays.splice(i, 1);
	            this.state.modeGen++;
	            regChange(this);
	            return
	          }
	        }
	      }),

	      indentLine: methodOp(function(n, dir, aggressive) {
	        if (typeof dir != "string" && typeof dir != "number") {
	          if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; }
	          else { dir = dir ? "add" : "subtract"; }
	        }
	        if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); }
	      }),
	      indentSelection: methodOp(function(how) {
	        var ranges = this.doc.sel.ranges, end = -1;
	        for (var i = 0; i < ranges.length; i++) {
	          var range = ranges[i];
	          if (!range.empty()) {
	            var from = range.from(), to = range.to();
	            var start = Math.max(end, from.line);
	            end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
	            for (var j = start; j < end; ++j)
	              { indentLine(this, j, how); }
	            var newRanges = this.doc.sel.ranges;
	            if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
	              { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }
	          } else if (range.head.line > end) {
	            indentLine(this, range.head.line, how, true);
	            end = range.head.line;
	            if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); }
	          }
	        }
	      }),

	      // Fetch the parser token for a given character. Useful for hacks
	      // that want to inspect the mode state (say, for completion).
	      getTokenAt: function(pos, precise) {
	        return takeToken(this, pos, precise)
	      },

	      getLineTokens: function(line, precise) {
	        return takeToken(this, Pos(line), precise, true)
	      },

	      getTokenTypeAt: function(pos) {
	        pos = clipPos(this.doc, pos);
	        var styles = getLineStyles(this, getLine(this.doc, pos.line));
	        var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
	        var type;
	        if (ch == 0) { type = styles[2]; }
	        else { for (;;) {
	          var mid = (before + after) >> 1;
	          if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; }
	          else if (styles[mid * 2 + 1] < ch) { before = mid + 1; }
	          else { type = styles[mid * 2 + 2]; break }
	        } }
	        var cut = type ? type.indexOf("overlay ") : -1;
	        return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
	      },

	      getModeAt: function(pos) {
	        var mode = this.doc.mode;
	        if (!mode.innerMode) { return mode }
	        return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
	      },

	      getHelper: function(pos, type) {
	        return this.getHelpers(pos, type)[0]
	      },

	      getHelpers: function(pos, type) {
	        var found = [];
	        if (!helpers.hasOwnProperty(type)) { return found }
	        var help = helpers[type], mode = this.getModeAt(pos);
	        if (typeof mode[type] == "string") {
	          if (help[mode[type]]) { found.push(help[mode[type]]); }
	        } else if (mode[type]) {
	          for (var i = 0; i < mode[type].length; i++) {
	            var val = help[mode[type][i]];
	            if (val) { found.push(val); }
	          }
	        } else if (mode.helperType && help[mode.helperType]) {
	          found.push(help[mode.helperType]);
	        } else if (help[mode.name]) {
	          found.push(help[mode.name]);
	        }
	        for (var i$1 = 0; i$1 < help._global.length; i$1++) {
	          var cur = help._global[i$1];
	          if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
	            { found.push(cur.val); }
	        }
	        return found
	      },

	      getStateAfter: function(line, precise) {
	        var doc = this.doc;
	        line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
	        return getContextBefore(this, line + 1, precise).state
	      },

	      cursorCoords: function(start, mode) {
	        var pos, range = this.doc.sel.primary();
	        if (start == null) { pos = range.head; }
	        else if (typeof start == "object") { pos = clipPos(this.doc, start); }
	        else { pos = start ? range.from() : range.to(); }
	        return cursorCoords(this, pos, mode || "page")
	      },

	      charCoords: function(pos, mode) {
	        return charCoords(this, clipPos(this.doc, pos), mode || "page")
	      },

	      coordsChar: function(coords, mode) {
	        coords = fromCoordSystem(this, coords, mode || "page");
	        return coordsChar(this, coords.left, coords.top)
	      },

	      lineAtHeight: function(height, mode) {
	        height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
	        return lineAtHeight(this.doc, height + this.display.viewOffset)
	      },
	      heightAtLine: function(line, mode, includeWidgets) {
	        var end = false, lineObj;
	        if (typeof line == "number") {
	          var last = this.doc.first + this.doc.size - 1;
	          if (line < this.doc.first) { line = this.doc.first; }
	          else if (line > last) { line = last; end = true; }
	          lineObj = getLine(this.doc, line);
	        } else {
	          lineObj = line;
	        }
	        return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top +
	          (end ? this.doc.height - heightAtLine(lineObj) : 0)
	      },

	      defaultTextHeight: function() { return textHeight(this.display) },
	      defaultCharWidth: function() { return charWidth(this.display) },

	      getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},

	      addWidget: function(pos, node, scroll, vert, horiz) {
	        var display = this.display;
	        pos = cursorCoords(this, clipPos(this.doc, pos));
	        var top = pos.bottom, left = pos.left;
	        node.style.position = "absolute";
	        node.setAttribute("cm-ignore-events", "true");
	        this.display.input.setUneditable(node);
	        display.sizer.appendChild(node);
	        if (vert == "over") {
	          top = pos.top;
	        } else if (vert == "above" || vert == "near") {
	          var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
	          hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
	          // Default to positioning above (if specified and possible); otherwise default to positioning below
	          if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
	            { top = pos.top - node.offsetHeight; }
	          else if (pos.bottom + node.offsetHeight <= vspace)
	            { top = pos.bottom; }
	          if (left + node.offsetWidth > hspace)
	            { left = hspace - node.offsetWidth; }
	        }
	        node.style.top = top + "px";
	        node.style.left = node.style.right = "";
	        if (horiz == "right") {
	          left = display.sizer.clientWidth - node.offsetWidth;
	          node.style.right = "0px";
	        } else {
	          if (horiz == "left") { left = 0; }
	          else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; }
	          node.style.left = left + "px";
	        }
	        if (scroll)
	          { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); }
	      },

	      triggerOnKeyDown: methodOp(onKeyDown),
	      triggerOnKeyPress: methodOp(onKeyPress),
	      triggerOnKeyUp: onKeyUp,
	      triggerOnMouseDown: methodOp(onMouseDown),

	      execCommand: function(cmd) {
	        if (commands.hasOwnProperty(cmd))
	          { return commands[cmd].call(null, this) }
	      },

	      triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),

	      findPosH: function(from, amount, unit, visually) {
	        var dir = 1;
	        if (amount < 0) { dir = -1; amount = -amount; }
	        var cur = clipPos(this.doc, from);
	        for (var i = 0; i < amount; ++i) {
	          cur = findPosH(this.doc, cur, dir, unit, visually);
	          if (cur.hitSide) { break }
	        }
	        return cur
	      },

	      moveH: methodOp(function(dir, unit) {
	        var this$1$1 = this;

	        this.extendSelectionsBy(function (range) {
	          if (this$1$1.display.shift || this$1$1.doc.extend || range.empty())
	            { return findPosH(this$1$1.doc, range.head, dir, unit, this$1$1.options.rtlMoveVisually) }
	          else
	            { return dir < 0 ? range.from() : range.to() }
	        }, sel_move);
	      }),

	      deleteH: methodOp(function(dir, unit) {
	        var sel = this.doc.sel, doc = this.doc;
	        if (sel.somethingSelected())
	          { doc.replaceSelection("", null, "+delete"); }
	        else
	          { deleteNearSelection(this, function (range) {
	            var other = findPosH(doc, range.head, dir, unit, false);
	            return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
	          }); }
	      }),

	      findPosV: function(from, amount, unit, goalColumn) {
	        var dir = 1, x = goalColumn;
	        if (amount < 0) { dir = -1; amount = -amount; }
	        var cur = clipPos(this.doc, from);
	        for (var i = 0; i < amount; ++i) {
	          var coords = cursorCoords(this, cur, "div");
	          if (x == null) { x = coords.left; }
	          else { coords.left = x; }
	          cur = findPosV(this, coords, dir, unit);
	          if (cur.hitSide) { break }
	        }
	        return cur
	      },

	      moveV: methodOp(function(dir, unit) {
	        var this$1$1 = this;

	        var doc = this.doc, goals = [];
	        var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected();
	        doc.extendSelectionsBy(function (range) {
	          if (collapse)
	            { return dir < 0 ? range.from() : range.to() }
	          var headPos = cursorCoords(this$1$1, range.head, "div");
	          if (range.goalColumn != null) { headPos.left = range.goalColumn; }
	          goals.push(headPos.left);
	          var pos = findPosV(this$1$1, headPos, dir, unit);
	          if (unit == "page" && range == doc.sel.primary())
	            { addToScrollTop(this$1$1, charCoords(this$1$1, pos, "div").top - headPos.top); }
	          return pos
	        }, sel_move);
	        if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
	          { doc.sel.ranges[i].goalColumn = goals[i]; } }
	      }),

	      // Find the word at the given position (as returned by coordsChar).
	      findWordAt: function(pos) {
	        var doc = this.doc, line = getLine(doc, pos.line).text;
	        var start = pos.ch, end = pos.ch;
	        if (line) {
	          var helper = this.getHelper(pos, "wordChars");
	          if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; }
	          var startChar = line.charAt(start);
	          var check = isWordChar(startChar, helper)
	            ? function (ch) { return isWordChar(ch, helper); }
	            : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
	            : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); };
	          while (start > 0 && check(line.charAt(start - 1))) { --start; }
	          while (end < line.length && check(line.charAt(end))) { ++end; }
	        }
	        return new Range(Pos(pos.line, start), Pos(pos.line, end))
	      },

	      toggleOverwrite: function(value) {
	        if (value != null && value == this.state.overwrite) { return }
	        if (this.state.overwrite = !this.state.overwrite)
	          { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); }
	        else
	          { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); }

	        signal(this, "overwriteToggle", this, this.state.overwrite);
	      },
	      hasFocus: function() { return this.display.input.getField() == activeElt(doc(this)) },
	      isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },

	      scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),
	      getScrollInfo: function() {
	        var scroller = this.display.scroller;
	        return {left: scroller.scrollLeft, top: scroller.scrollTop,
	                height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
	                width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
	                clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
	      },

	      scrollIntoView: methodOp(function(range, margin) {
	        if (range == null) {
	          range = {from: this.doc.sel.primary().head, to: null};
	          if (margin == null) { margin = this.options.cursorScrollMargin; }
	        } else if (typeof range == "number") {
	          range = {from: Pos(range, 0), to: null};
	        } else if (range.from == null) {
	          range = {from: range, to: null};
	        }
	        if (!range.to) { range.to = range.from; }
	        range.margin = margin || 0;

	        if (range.from.line != null) {
	          scrollToRange(this, range);
	        } else {
	          scrollToCoordsRange(this, range.from, range.to, range.margin);
	        }
	      }),

	      setSize: methodOp(function(width, height) {
	        var this$1$1 = this;

	        var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; };
	        if (width != null) { this.display.wrapper.style.width = interpret(width); }
	        if (height != null) { this.display.wrapper.style.height = interpret(height); }
	        if (this.options.lineWrapping) { clearLineMeasurementCache(this); }
	        var lineNo = this.display.viewFrom;
	        this.doc.iter(lineNo, this.display.viewTo, function (line) {
	          if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
	            { if (line.widgets[i].noHScroll) { regLineChange(this$1$1, lineNo, "widget"); break } } }
	          ++lineNo;
	        });
	        this.curOp.forceUpdate = true;
	        signal(this, "refresh", this);
	      }),

	      operation: function(f){return runInOp(this, f)},
	      startOperation: function(){return startOperation(this)},
	      endOperation: function(){return endOperation(this)},

	      refresh: methodOp(function() {
	        var oldHeight = this.display.cachedTextHeight;
	        regChange(this);
	        this.curOp.forceUpdate = true;
	        clearCaches(this);
	        scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);
	        updateGutterSpace(this.display);
	        if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping)
	          { estimateLineHeights(this); }
	        signal(this, "refresh", this);
	      }),

	      swapDoc: methodOp(function(doc) {
	        var old = this.doc;
	        old.cm = null;
	        // Cancel the current text selection if any (#5821)
	        if (this.state.selectingText) { this.state.selectingText(); }
	        attachDoc(this, doc);
	        clearCaches(this);
	        this.display.input.reset();
	        scrollToCoords(this, doc.scrollLeft, doc.scrollTop);
	        this.curOp.forceScroll = true;
	        signalLater(this, "swapDoc", this, old);
	        return old
	      }),

	      phrase: function(phraseText) {
	        var phrases = this.options.phrases;
	        return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText
	      },

	      getInputField: function(){return this.display.input.getField()},
	      getWrapperElement: function(){return this.display.wrapper},
	      getScrollerElement: function(){return this.display.scroller},
	      getGutterElement: function(){return this.display.gutters}
	    };
	    eventMixin(CodeMirror);

	    CodeMirror.registerHelper = function(type, name, value) {
	      if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; }
	      helpers[type][name] = value;
	    };
	    CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
	      CodeMirror.registerHelper(type, name, value);
	      helpers[type]._global.push({pred: predicate, val: value});
	    };
	  }

	  // Used for horizontal relative motion. Dir is -1 or 1 (left or
	  // right), unit can be "codepoint", "char", "column" (like char, but
	  // doesn't cross line boundaries), "word" (across next word), or
	  // "group" (to the start of next group of word or
	  // non-word-non-whitespace chars). The visually param controls
	  // whether, in right-to-left text, direction 1 means to move towards
	  // the next index in the string, or towards the character to the right
	  // of the current position. The resulting position will have a
	  // hitSide=true property if it reached the end of the document.
	  function findPosH(doc, pos, dir, unit, visually) {
	    var oldPos = pos;
	    var origDir = dir;
	    var lineObj = getLine(doc, pos.line);
	    var lineDir = visually && doc.direction == "rtl" ? -dir : dir;
	    function findNextLine() {
	      var l = pos.line + lineDir;
	      if (l < doc.first || l >= doc.first + doc.size) { return false }
	      pos = new Pos(l, pos.ch, pos.sticky);
	      return lineObj = getLine(doc, l)
	    }
	    function moveOnce(boundToLine) {
	      var next;
	      if (unit == "codepoint") {
	        var ch = lineObj.text.charCodeAt(pos.ch + (dir > 0 ? 0 : -1));
	        if (isNaN(ch)) {
	          next = null;
	        } else {
	          var astral = dir > 0 ? ch >= 0xD800 && ch < 0xDC00 : ch >= 0xDC00 && ch < 0xDFFF;
	          next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (astral ? 2 : 1))), -dir);
	        }
	      } else if (visually) {
	        next = moveVisually(doc.cm, lineObj, pos, dir);
	      } else {
	        next = moveLogically(lineObj, pos, dir);
	      }
	      if (next == null) {
	        if (!boundToLine && findNextLine())
	          { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); }
	        else
	          { return false }
	      } else {
	        pos = next;
	      }
	      return true
	    }

	    if (unit == "char" || unit == "codepoint") {
	      moveOnce();
	    } else if (unit == "column") {
	      moveOnce(true);
	    } else if (unit == "word" || unit == "group") {
	      var sawType = null, group = unit == "group";
	      var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
	      for (var first = true;; first = false) {
	        if (dir < 0 && !moveOnce(!first)) { break }
	        var cur = lineObj.text.charAt(pos.ch) || "\n";
	        var type = isWordChar(cur, helper) ? "w"
	          : group && cur == "\n" ? "n"
	          : !group || /\s/.test(cur) ? null
	          : "p";
	        if (group && !first && !type) { type = "s"; }
	        if (sawType && sawType != type) {
	          if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";}
	          break
	        }

	        if (type) { sawType = type; }
	        if (dir > 0 && !moveOnce(!first)) { break }
	      }
	    }
	    var result = skipAtomic(doc, pos, oldPos, origDir, true);
	    if (equalCursorPos(oldPos, result)) { result.hitSide = true; }
	    return result
	  }

	  // For relative vertical movement. Dir may be -1 or 1. Unit can be
	  // "page" or "line". The resulting position will have a hitSide=true
	  // property if it reached the end of the document.
	  function findPosV(cm, pos, dir, unit) {
	    var doc = cm.doc, x = pos.left, y;
	    if (unit == "page") {
	      var pageSize = Math.min(cm.display.wrapper.clientHeight, win(cm).innerHeight || doc(cm).documentElement.clientHeight);
	      var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3);
	      y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount;

	    } else if (unit == "line") {
	      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
	    }
	    var target;
	    for (;;) {
	      target = coordsChar(cm, x, y);
	      if (!target.outside) { break }
	      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
	      y += dir * 5;
	    }
	    return target
	  }

	  // CONTENTEDITABLE INPUT STYLE

	  var ContentEditableInput = function(cm) {
	    this.cm = cm;
	    this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
	    this.polling = new Delayed();
	    this.composing = null;
	    this.gracePeriod = false;
	    this.readDOMTimeout = null;
	  };

	  ContentEditableInput.prototype.init = function (display) {
	      var this$1$1 = this;

	    var input = this, cm = input.cm;
	    var div = input.div = display.lineDiv;
	    div.contentEditable = true;
	    disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize);

	    function belongsToInput(e) {
	      for (var t = e.target; t; t = t.parentNode) {
	        if (t == div) { return true }
	        if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break }
	      }
	      return false
	    }

	    on(div, "paste", function (e) {
	      if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
	      // IE doesn't fire input events, so we schedule a read for the pasted content in this way
	      if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1$1.updateFromDOM(); }), 20); }
	    });

	    on(div, "compositionstart", function (e) {
	      this$1$1.composing = {data: e.data, done: false};
	    });
	    on(div, "compositionupdate", function (e) {
	      if (!this$1$1.composing) { this$1$1.composing = {data: e.data, done: false}; }
	    });
	    on(div, "compositionend", function (e) {
	      if (this$1$1.composing) {
	        if (e.data != this$1$1.composing.data) { this$1$1.readFromDOMSoon(); }
	        this$1$1.composing.done = true;
	      }
	    });

	    on(div, "touchstart", function () { return input.forceCompositionEnd(); });

	    on(div, "input", function () {
	      if (!this$1$1.composing) { this$1$1.readFromDOMSoon(); }
	    });

	    function onCopyCut(e) {
	      if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return }
	      if (cm.somethingSelected()) {
	        setLastCopied({lineWise: false, text: cm.getSelections()});
	        if (e.type == "cut") { cm.replaceSelection("", null, "cut"); }
	      } else if (!cm.options.lineWiseCopyCut) {
	        return
	      } else {
	        var ranges = copyableRanges(cm);
	        setLastCopied({lineWise: true, text: ranges.text});
	        if (e.type == "cut") {
	          cm.operation(function () {
	            cm.setSelections(ranges.ranges, 0, sel_dontScroll);
	            cm.replaceSelection("", null, "cut");
	          });
	        }
	      }
	      if (e.clipboardData) {
	        e.clipboardData.clearData();
	        var content = lastCopied.text.join("\n");
	        // iOS exposes the clipboard API, but seems to discard content inserted into it
	        e.clipboardData.setData("Text", content);
	        if (e.clipboardData.getData("Text") == content) {
	          e.preventDefault();
	          return
	        }
	      }
	      // Old-fashioned briefly-focus-a-textarea hack
	      var kludge = hiddenTextarea(), te = kludge.firstChild;
	      cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
	      te.value = lastCopied.text.join("\n");
	      var hadFocus = activeElt(div.ownerDocument);
	      selectInput(te);
	      setTimeout(function () {
	        cm.display.lineSpace.removeChild(kludge);
	        hadFocus.focus();
	        if (hadFocus == div) { input.showPrimarySelection(); }
	      }, 50);
	    }
	    on(div, "copy", onCopyCut);
	    on(div, "cut", onCopyCut);
	  };

	  ContentEditableInput.prototype.screenReaderLabelChanged = function (label) {
	    // Label for screenreaders, accessibility
	    if(label) {
	      this.div.setAttribute('aria-label', label);
	    } else {
	      this.div.removeAttribute('aria-label');
	    }
	  };

	  ContentEditableInput.prototype.prepareSelection = function () {
	    var result = prepareSelection(this.cm, false);
	    result.focus = activeElt(this.div.ownerDocument) == this.div;
	    return result
	  };

	  ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
	    if (!info || !this.cm.display.view.length) { return }
	    if (info.focus || takeFocus) { this.showPrimarySelection(); }
	    this.showMultipleSelections(info);
	  };

	  ContentEditableInput.prototype.getSelection = function () {
	    return this.cm.display.wrapper.ownerDocument.getSelection()
	  };

	  ContentEditableInput.prototype.showPrimarySelection = function () {
	    var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary();
	    var from = prim.from(), to = prim.to();

	    if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) {
	      sel.removeAllRanges();
	      return
	    }

	    var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
	    var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset);
	    if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
	        cmp(minPos(curAnchor, curFocus), from) == 0 &&
	        cmp(maxPos(curAnchor, curFocus), to) == 0)
	      { return }

	    var view = cm.display.view;
	    var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) ||
	        {node: view[0].measure.map[2], offset: 0};
	    var end = to.line < cm.display.viewTo && posToDOM(cm, to);
	    if (!end) {
	      var measure = view[view.length - 1].measure;
	      var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
	      end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
	    }

	    if (!start || !end) {
	      sel.removeAllRanges();
	      return
	    }

	    var old = sel.rangeCount && sel.getRangeAt(0), rng;
	    try { rng = range(start.node, start.offset, end.offset, end.node); }
	    catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
	    if (rng) {
	      if (!gecko && cm.state.focused) {
	        sel.collapse(start.node, start.offset);
	        if (!rng.collapsed) {
	          sel.removeAllRanges();
	          sel.addRange(rng);
	        }
	      } else {
	        sel.removeAllRanges();
	        sel.addRange(rng);
	      }
	      if (old && sel.anchorNode == null) { sel.addRange(old); }
	      else if (gecko) { this.startGracePeriod(); }
	    }
	    this.rememberSelection();
	  };

	  ContentEditableInput.prototype.startGracePeriod = function () {
	      var this$1$1 = this;

	    clearTimeout(this.gracePeriod);
	    this.gracePeriod = setTimeout(function () {
	      this$1$1.gracePeriod = false;
	      if (this$1$1.selectionChanged())
	        { this$1$1.cm.operation(function () { return this$1$1.cm.curOp.selectionChanged = true; }); }
	    }, 20);
	  };

	  ContentEditableInput.prototype.showMultipleSelections = function (info) {
	    removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
	    removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
	  };

	  ContentEditableInput.prototype.rememberSelection = function () {
	    var sel = this.getSelection();
	    this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
	    this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
	  };

	  ContentEditableInput.prototype.selectionInEditor = function () {
	    var sel = this.getSelection();
	    if (!sel.rangeCount) { return false }
	    var node = sel.getRangeAt(0).commonAncestorContainer;
	    return contains(this.div, node)
	  };

	  ContentEditableInput.prototype.focus = function () {
	    if (this.cm.options.readOnly != "nocursor") {
	      if (!this.selectionInEditor() || activeElt(this.div.ownerDocument) != this.div)
	        { this.showSelection(this.prepareSelection(), true); }
	      this.div.focus();
	    }
	  };
	  ContentEditableInput.prototype.blur = function () { this.div.blur(); };
	  ContentEditableInput.prototype.getField = function () { return this.div };

	  ContentEditableInput.prototype.supportsTouch = function () { return true };

	  ContentEditableInput.prototype.receivedFocus = function () {
	      var this$1$1 = this;

	    var input = this;
	    if (this.selectionInEditor())
	      { setTimeout(function () { return this$1$1.pollSelection(); }, 20); }
	    else
	      { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }

	    function poll() {
	      if (input.cm.state.focused) {
	        input.pollSelection();
	        input.polling.set(input.cm.options.pollInterval, poll);
	      }
	    }
	    this.polling.set(this.cm.options.pollInterval, poll);
	  };

	  ContentEditableInput.prototype.selectionChanged = function () {
	    var sel = this.getSelection();
	    return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
	      sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
	  };

	  ContentEditableInput.prototype.pollSelection = function () {
	    if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return }
	    var sel = this.getSelection(), cm = this.cm;
	    // On Android Chrome (version 56, at least), backspacing into an
	    // uneditable block element will put the cursor in that element,
	    // and then, because it's not editable, hide the virtual keyboard.
	    // Because Android doesn't allow us to actually detect backspace
	    // presses in a sane way, this code checks for when that happens
	    // and simulates a backspace press in this case.
	    if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) {
	      this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs});
	      this.blur();
	      this.focus();
	      return
	    }
	    if (this.composing) { return }
	    this.rememberSelection();
	    var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
	    var head = domToPos(cm, sel.focusNode, sel.focusOffset);
	    if (anchor && head) { runInOp(cm, function () {
	      setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
	      if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; }
	    }); }
	  };

	  ContentEditableInput.prototype.pollContent = function () {
	    if (this.readDOMTimeout != null) {
	      clearTimeout(this.readDOMTimeout);
	      this.readDOMTimeout = null;
	    }

	    var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
	    var from = sel.from(), to = sel.to();
	    if (from.ch == 0 && from.line > cm.firstLine())
	      { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); }
	    if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
	      { to = Pos(to.line + 1, 0); }
	    if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }

	    var fromIndex, fromLine, fromNode;
	    if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
	      fromLine = lineNo(display.view[0].line);
	      fromNode = display.view[0].node;
	    } else {
	      fromLine = lineNo(display.view[fromIndex].line);
	      fromNode = display.view[fromIndex - 1].node.nextSibling;
	    }
	    var toIndex = findViewIndex(cm, to.line);
	    var toLine, toNode;
	    if (toIndex == display.view.length - 1) {
	      toLine = display.viewTo - 1;
	      toNode = display.lineDiv.lastChild;
	    } else {
	      toLine = lineNo(display.view[toIndex + 1].line) - 1;
	      toNode = display.view[toIndex + 1].node.previousSibling;
	    }

	    if (!fromNode) { return false }
	    var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
	    var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
	    while (newText.length > 1 && oldText.length > 1) {
	      if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
	      else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
	      else { break }
	    }

	    var cutFront = 0, cutEnd = 0;
	    var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
	    while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
	      { ++cutFront; }
	    var newBot = lst(newText), oldBot = lst(oldText);
	    var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
	                             oldBot.length - (oldText.length == 1 ? cutFront : 0));
	    while (cutEnd < maxCutEnd &&
	           newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
	      { ++cutEnd; }
	    // Try to move start of change to start of selection if ambiguous
	    if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) {
	      while (cutFront && cutFront > from.ch &&
	             newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) {
	        cutFront--;
	        cutEnd++;
	      }
	    }

	    newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "");
	    newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "");

	    var chFrom = Pos(fromLine, cutFront);
	    var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
	    if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
	      replaceRange(cm.doc, newText, chFrom, chTo, "+input");
	      return true
	    }
	  };

	  ContentEditableInput.prototype.ensurePolled = function () {
	    this.forceCompositionEnd();
	  };
	  ContentEditableInput.prototype.reset = function () {
	    this.forceCompositionEnd();
	  };
	  ContentEditableInput.prototype.forceCompositionEnd = function () {
	    if (!this.composing) { return }
	    clearTimeout(this.readDOMTimeout);
	    this.composing = null;
	    this.updateFromDOM();
	    this.div.blur();
	    this.div.focus();
	  };
	  ContentEditableInput.prototype.readFromDOMSoon = function () {
	      var this$1$1 = this;

	    if (this.readDOMTimeout != null) { return }
	    this.readDOMTimeout = setTimeout(function () {
	      this$1$1.readDOMTimeout = null;
	      if (this$1$1.composing) {
	        if (this$1$1.composing.done) { this$1$1.composing = null; }
	        else { return }
	      }
	      this$1$1.updateFromDOM();
	    }, 80);
	  };

	  ContentEditableInput.prototype.updateFromDOM = function () {
	      var this$1$1 = this;

	    if (this.cm.isReadOnly() || !this.pollContent())
	      { runInOp(this.cm, function () { return regChange(this$1$1.cm); }); }
	  };

	  ContentEditableInput.prototype.setUneditable = function (node) {
	    node.contentEditable = "false";
	  };

	  ContentEditableInput.prototype.onKeyPress = function (e) {
	    if (e.charCode == 0 || this.composing) { return }
	    e.preventDefault();
	    if (!this.cm.isReadOnly())
	      { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); }
	  };

	  ContentEditableInput.prototype.readOnlyChanged = function (val) {
	    this.div.contentEditable = String(val != "nocursor");
	  };

	  ContentEditableInput.prototype.onContextMenu = function () {};
	  ContentEditableInput.prototype.resetPosition = function () {};

	  ContentEditableInput.prototype.needsContentAttribute = true;

	  function posToDOM(cm, pos) {
	    var view = findViewForLine(cm, pos.line);
	    if (!view || view.hidden) { return null }
	    var line = getLine(cm.doc, pos.line);
	    var info = mapFromLineView(view, line, pos.line);

	    var order = getOrder(line, cm.doc.direction), side = "left";
	    if (order) {
	      var partPos = getBidiPartAt(order, pos.ch);
	      side = partPos % 2 ? "right" : "left";
	    }
	    var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
	    result.offset = result.collapse == "right" ? result.end : result.start;
	    return result
	  }

	  function isInGutter(node) {
	    for (var scan = node; scan; scan = scan.parentNode)
	      { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } }
	    return false
	  }

	  function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }

	  function domTextBetween(cm, from, to, fromLine, toLine) {
	    var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false;
	    function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
	    function close() {
	      if (closing) {
	        text += lineSep;
	        if (extraLinebreak) { text += lineSep; }
	        closing = extraLinebreak = false;
	      }
	    }
	    function addText(str) {
	      if (str) {
	        close();
	        text += str;
	      }
	    }
	    function walk(node) {
	      if (node.nodeType == 1) {
	        var cmText = node.getAttribute("cm-text");
	        if (cmText) {
	          addText(cmText);
	          return
	        }
	        var markerID = node.getAttribute("cm-marker"), range;
	        if (markerID) {
	          var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
	          if (found.length && (range = found[0].find(0)))
	            { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); }
	          return
	        }
	        if (node.getAttribute("contenteditable") == "false") { return }
	        var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName);
	        if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return }

	        if (isBlock) { close(); }
	        for (var i = 0; i < node.childNodes.length; i++)
	          { walk(node.childNodes[i]); }

	        if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; }
	        if (isBlock) { closing = true; }
	      } else if (node.nodeType == 3) {
	        addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " "));
	      }
	    }
	    for (;;) {
	      walk(from);
	      if (from == to) { break }
	      from = from.nextSibling;
	      extraLinebreak = false;
	    }
	    return text
	  }

	  function domToPos(cm, node, offset) {
	    var lineNode;
	    if (node == cm.display.lineDiv) {
	      lineNode = cm.display.lineDiv.childNodes[offset];
	      if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
	      node = null; offset = 0;
	    } else {
	      for (lineNode = node;; lineNode = lineNode.parentNode) {
	        if (!lineNode || lineNode == cm.display.lineDiv) { return null }
	        if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
	      }
	    }
	    for (var i = 0; i < cm.display.view.length; i++) {
	      var lineView = cm.display.view[i];
	      if (lineView.node == lineNode)
	        { return locateNodeInLineView(lineView, node, offset) }
	    }
	  }

	  function locateNodeInLineView(lineView, node, offset) {
	    var wrapper = lineView.text.firstChild, bad = false;
	    if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
	    if (node == wrapper) {
	      bad = true;
	      node = wrapper.childNodes[offset];
	      offset = 0;
	      if (!node) {
	        var line = lineView.rest ? lst(lineView.rest) : lineView.line;
	        return badPos(Pos(lineNo(line), line.text.length), bad)
	      }
	    }

	    var textNode = node.nodeType == 3 ? node : null, topNode = node;
	    if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
	      textNode = node.firstChild;
	      if (offset) { offset = textNode.nodeValue.length; }
	    }
	    while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; }
	    var measure = lineView.measure, maps = measure.maps;

	    function find(textNode, topNode, offset) {
	      for (var i = -1; i < (maps ? maps.length : 0); i++) {
	        var map = i < 0 ? measure.map : maps[i];
	        for (var j = 0; j < map.length; j += 3) {
	          var curNode = map[j + 2];
	          if (curNode == textNode || curNode == topNode) {
	            var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
	            var ch = map[j] + offset;
	            if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; }
	            return Pos(line, ch)
	          }
	        }
	      }
	    }
	    var found = find(textNode, topNode, offset);
	    if (found) { return badPos(found, bad) }

	    // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
	    for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
	      found = find(after, after.firstChild, 0);
	      if (found)
	        { return badPos(Pos(found.line, found.ch - dist), bad) }
	      else
	        { dist += after.textContent.length; }
	    }
	    for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
	      found = find(before, before.firstChild, -1);
	      if (found)
	        { return badPos(Pos(found.line, found.ch + dist$1), bad) }
	      else
	        { dist$1 += before.textContent.length; }
	    }
	  }

	  // TEXTAREA INPUT STYLE

	  var TextareaInput = function(cm) {
	    this.cm = cm;
	    // See input.poll and input.reset
	    this.prevInput = "";

	    // Flag that indicates whether we expect input to appear real soon
	    // now (after some event like 'keypress' or 'input') and are
	    // polling intensively.
	    this.pollingFast = false;
	    // Self-resetting timeout for the poller
	    this.polling = new Delayed();
	    // Used to work around IE issue with selection being forgotten when focus moves away from textarea
	    this.hasSelection = false;
	    this.composing = null;
	    this.resetting = false;
	  };

	  TextareaInput.prototype.init = function (display) {
	      var this$1$1 = this;

	    var input = this, cm = this.cm;
	    this.createField(display);
	    var te = this.textarea;

	    display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild);

	    // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
	    if (ios) { te.style.width = "0px"; }

	    on(te, "input", function () {
	      if (ie && ie_version >= 9 && this$1$1.hasSelection) { this$1$1.hasSelection = null; }
	      input.poll();
	    });

	    on(te, "paste", function (e) {
	      if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }

	      cm.state.pasteIncoming = +new Date;
	      input.fastPoll();
	    });

	    function prepareCopyCut(e) {
	      if (signalDOMEvent(cm, e)) { return }
	      if (cm.somethingSelected()) {
	        setLastCopied({lineWise: false, text: cm.getSelections()});
	      } else if (!cm.options.lineWiseCopyCut) {
	        return
	      } else {
	        var ranges = copyableRanges(cm);
	        setLastCopied({lineWise: true, text: ranges.text});
	        if (e.type == "cut") {
	          cm.setSelections(ranges.ranges, null, sel_dontScroll);
	        } else {
	          input.prevInput = "";
	          te.value = ranges.text.join("\n");
	          selectInput(te);
	        }
	      }
	      if (e.type == "cut") { cm.state.cutIncoming = +new Date; }
	    }
	    on(te, "cut", prepareCopyCut);
	    on(te, "copy", prepareCopyCut);

	    on(display.scroller, "paste", function (e) {
	      if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
	      if (!te.dispatchEvent) {
	        cm.state.pasteIncoming = +new Date;
	        input.focus();
	        return
	      }

	      // Pass the `paste` event to the textarea so it's handled by its event listener.
	      var event = new Event("paste");
	      event.clipboardData = e.clipboardData;
	      te.dispatchEvent(event);
	    });

	    // Prevent normal selection in the editor (we handle our own)
	    on(display.lineSpace, "selectstart", function (e) {
	      if (!eventInWidget(display, e)) { e_preventDefault(e); }
	    });

	    on(te, "compositionstart", function () {
	      var start = cm.getCursor("from");
	      if (input.composing) { input.composing.range.clear(); }
	      input.composing = {
	        start: start,
	        range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
	      };
	    });
	    on(te, "compositionend", function () {
	      if (input.composing) {
	        input.poll();
	        input.composing.range.clear();
	        input.composing = null;
	      }
	    });
	  };

	  TextareaInput.prototype.createField = function (_display) {
	    // Wraps and hides input textarea
	    this.wrapper = hiddenTextarea();
	    // The semihidden textarea that is focused when the editor is
	    // focused, and receives input.
	    this.textarea = this.wrapper.firstChild;
	  };

	  TextareaInput.prototype.screenReaderLabelChanged = function (label) {
	    // Label for screenreaders, accessibility
	    if(label) {
	      this.textarea.setAttribute('aria-label', label);
	    } else {
	      this.textarea.removeAttribute('aria-label');
	    }
	  };

	  TextareaInput.prototype.prepareSelection = function () {
	    // Redraw the selection and/or cursor
	    var cm = this.cm, display = cm.display, doc = cm.doc;
	    var result = prepareSelection(cm);

	    // Move the hidden textarea near the cursor to prevent scrolling artifacts
	    if (cm.options.moveInputWithCursor) {
	      var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
	      var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
	      result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
	                                          headPos.top + lineOff.top - wrapOff.top));
	      result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
	                                           headPos.left + lineOff.left - wrapOff.left));
	    }

	    return result
	  };

	  TextareaInput.prototype.showSelection = function (drawn) {
	    var cm = this.cm, display = cm.display;
	    removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
	    removeChildrenAndAdd(display.selectionDiv, drawn.selection);
	    if (drawn.teTop != null) {
	      this.wrapper.style.top = drawn.teTop + "px";
	      this.wrapper.style.left = drawn.teLeft + "px";
	    }
	  };

	  // Reset the input to correspond to the selection (or to be empty,
	  // when not typing and nothing is selected)
	  TextareaInput.prototype.reset = function (typing) {
	    if (this.contextMenuPending || this.composing && typing) { return }
	    var cm = this.cm;
	    this.resetting = true;
	    if (cm.somethingSelected()) {
	      this.prevInput = "";
	      var content = cm.getSelection();
	      this.textarea.value = content;
	      if (cm.state.focused) { selectInput(this.textarea); }
	      if (ie && ie_version >= 9) { this.hasSelection = content; }
	    } else if (!typing) {
	      this.prevInput = this.textarea.value = "";
	      if (ie && ie_version >= 9) { this.hasSelection = null; }
	    }
	    this.resetting = false;
	  };

	  TextareaInput.prototype.getField = function () { return this.textarea };

	  TextareaInput.prototype.supportsTouch = function () { return false };

	  TextareaInput.prototype.focus = function () {
	    if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt(this.textarea.ownerDocument) != this.textarea)) {
	      try { this.textarea.focus(); }
	      catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
	    }
	  };

	  TextareaInput.prototype.blur = function () { this.textarea.blur(); };

	  TextareaInput.prototype.resetPosition = function () {
	    this.wrapper.style.top = this.wrapper.style.left = 0;
	  };

	  TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); };

	  // Poll for input changes, using the normal rate of polling. This
	  // runs as long as the editor is focused.
	  TextareaInput.prototype.slowPoll = function () {
	      var this$1$1 = this;

	    if (this.pollingFast) { return }
	    this.polling.set(this.cm.options.pollInterval, function () {
	      this$1$1.poll();
	      if (this$1$1.cm.state.focused) { this$1$1.slowPoll(); }
	    });
	  };

	  // When an event has just come in that is likely to add or change
	  // something in the input textarea, we poll faster, to ensure that
	  // the change appears on the screen quickly.
	  TextareaInput.prototype.fastPoll = function () {
	    var missed = false, input = this;
	    input.pollingFast = true;
	    function p() {
	      var changed = input.poll();
	      if (!changed && !missed) {missed = true; input.polling.set(60, p);}
	      else {input.pollingFast = false; input.slowPoll();}
	    }
	    input.polling.set(20, p);
	  };

	  // Read input from the textarea, and update the document to match.
	  // When something is selected, it is present in the textarea, and
	  // selected (unless it is huge, in which case a placeholder is
	  // used). When nothing is selected, the cursor sits after previously
	  // seen text (can be empty), which is stored in prevInput (we must
	  // not reset the textarea when typing, because that breaks IME).
	  TextareaInput.prototype.poll = function () {
	      var this$1$1 = this;

	    var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
	    // Since this is called a *lot*, try to bail out as cheaply as
	    // possible when it is clear that nothing happened. hasSelection
	    // will be the case when there is a lot of text in the textarea,
	    // in which case reading its value would be expensive.
	    if (this.contextMenuPending || this.resetting || !cm.state.focused ||
	        (hasSelection(input) && !prevInput && !this.composing) ||
	        cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
	      { return false }

	    var text = input.value;
	    // If nothing changed, bail.
	    if (text == prevInput && !cm.somethingSelected()) { return false }
	    // Work around nonsensical selection resetting in IE9/10, and
	    // inexplicable appearance of private area unicode characters on
	    // some key combos in Mac (#2689).
	    if (ie && ie_version >= 9 && this.hasSelection === text ||
	        mac && /[\uf700-\uf7ff]/.test(text)) {
	      cm.display.input.reset();
	      return false
	    }

	    if (cm.doc.sel == cm.display.selForContextMenu) {
	      var first = text.charCodeAt(0);
	      if (first == 0x200b && !prevInput) { prevInput = "\u200b"; }
	      if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
	    }
	    // Find the part of the input that is actually new
	    var same = 0, l = Math.min(prevInput.length, text.length);
	    while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; }

	    runInOp(cm, function () {
	      applyTextInput(cm, text.slice(same), prevInput.length - same,
	                     null, this$1$1.composing ? "*compose" : null);

	      // Don't leave long text in the textarea, since it makes further polling slow
	      if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1$1.prevInput = ""; }
	      else { this$1$1.prevInput = text; }

	      if (this$1$1.composing) {
	        this$1$1.composing.range.clear();
	        this$1$1.composing.range = cm.markText(this$1$1.composing.start, cm.getCursor("to"),
	                                           {className: "CodeMirror-composing"});
	      }
	    });
	    return true
	  };

	  TextareaInput.prototype.ensurePolled = function () {
	    if (this.pollingFast && this.poll()) { this.pollingFast = false; }
	  };

	  TextareaInput.prototype.onKeyPress = function () {
	    if (ie && ie_version >= 9) { this.hasSelection = null; }
	    this.fastPoll();
	  };

	  TextareaInput.prototype.onContextMenu = function (e) {
	    var input = this, cm = input.cm, display = cm.display, te = input.textarea;
	    if (input.contextMenuPending) { input.contextMenuPending(); }
	    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
	    if (!pos || presto) { return } // Opera is difficult.

	    // Reset the current text selection only if the click is done outside of the selection
	    // and 'resetSelectionOnContextMenu' option is true.
	    var reset = cm.options.resetSelectionOnContextMenu;
	    if (reset && cm.doc.sel.contains(pos) == -1)
	      { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); }

	    var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;
	    var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect();
	    input.wrapper.style.cssText = "position: static";
	    te.style.cssText = "position: absolute; width: 30px; height: 30px;\n      top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n      z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
	    var oldScrollY;
	    if (webkit) { oldScrollY = te.ownerDocument.defaultView.scrollY; } // Work around Chrome issue (#2712)
	    display.input.focus();
	    if (webkit) { te.ownerDocument.defaultView.scrollTo(null, oldScrollY); }
	    display.input.reset();
	    // Adds "Select all" to context menu in FF
	    if (!cm.somethingSelected()) { te.value = input.prevInput = " "; }
	    input.contextMenuPending = rehide;
	    display.selForContextMenu = cm.doc.sel;
	    clearTimeout(display.detectingSelectAll);

	    // Select-all will be greyed out if there's nothing to select, so
	    // this adds a zero-width space so that we can later check whether
	    // it got selected.
	    function prepareSelectAllHack() {
	      if (te.selectionStart != null) {
	        var selected = cm.somethingSelected();
	        var extval = "\u200b" + (selected ? te.value : "");
	        te.value = "\u21da"; // Used to catch context-menu undo
	        te.value = extval;
	        input.prevInput = selected ? "" : "\u200b";
	        te.selectionStart = 1; te.selectionEnd = extval.length;
	        // Re-set this, in case some other handler touched the
	        // selection in the meantime.
	        display.selForContextMenu = cm.doc.sel;
	      }
	    }
	    function rehide() {
	      if (input.contextMenuPending != rehide) { return }
	      input.contextMenuPending = false;
	      input.wrapper.style.cssText = oldWrapperCSS;
	      te.style.cssText = oldCSS;
	      if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); }

	      // Try to detect the user choosing select-all
	      if (te.selectionStart != null) {
	        if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); }
	        var i = 0, poll = function () {
	          if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
	              te.selectionEnd > 0 && input.prevInput == "\u200b") {
	            operation(cm, selectAll)(cm);
	          } else if (i++ < 10) {
	            display.detectingSelectAll = setTimeout(poll, 500);
	          } else {
	            display.selForContextMenu = null;
	            display.input.reset();
	          }
	        };
	        display.detectingSelectAll = setTimeout(poll, 200);
	      }
	    }

	    if (ie && ie_version >= 9) { prepareSelectAllHack(); }
	    if (captureRightClick) {
	      e_stop(e);
	      var mouseup = function () {
	        off(window, "mouseup", mouseup);
	        setTimeout(rehide, 20);
	      };
	      on(window, "mouseup", mouseup);
	    } else {
	      setTimeout(rehide, 50);
	    }
	  };

	  TextareaInput.prototype.readOnlyChanged = function (val) {
	    if (!val) { this.reset(); }
	    this.textarea.disabled = val == "nocursor";
	    this.textarea.readOnly = !!val;
	  };

	  TextareaInput.prototype.setUneditable = function () {};

	  TextareaInput.prototype.needsContentAttribute = false;

	  function fromTextArea(textarea, options) {
	    options = options ? copyObj(options) : {};
	    options.value = textarea.value;
	    if (!options.tabindex && textarea.tabIndex)
	      { options.tabindex = textarea.tabIndex; }
	    if (!options.placeholder && textarea.placeholder)
	      { options.placeholder = textarea.placeholder; }
	    // Set autofocus to true if this textarea is focused, or if it has
	    // autofocus and no other element is focused.
	    if (options.autofocus == null) {
	      var hasFocus = activeElt(textarea.ownerDocument);
	      options.autofocus = hasFocus == textarea ||
	        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
	    }

	    function save() {textarea.value = cm.getValue();}

	    var realSubmit;
	    if (textarea.form) {
	      on(textarea.form, "submit", save);
	      // Deplorable hack to make the submit method do the right thing.
	      if (!options.leaveSubmitMethodAlone) {
	        var form = textarea.form;
	        realSubmit = form.submit;
	        try {
	          var wrappedSubmit = form.submit = function () {
	            save();
	            form.submit = realSubmit;
	            form.submit();
	            form.submit = wrappedSubmit;
	          };
	        } catch(e) {}
	      }
	    }

	    options.finishInit = function (cm) {
	      cm.save = save;
	      cm.getTextArea = function () { return textarea; };
	      cm.toTextArea = function () {
	        cm.toTextArea = isNaN; // Prevent this from being ran twice
	        save();
	        textarea.parentNode.removeChild(cm.getWrapperElement());
	        textarea.style.display = "";
	        if (textarea.form) {
	          off(textarea.form, "submit", save);
	          if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function")
	            { textarea.form.submit = realSubmit; }
	        }
	      };
	    };

	    textarea.style.display = "none";
	    var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
	      options);
	    return cm
	  }

	  function addLegacyProps(CodeMirror) {
	    CodeMirror.off = off;
	    CodeMirror.on = on;
	    CodeMirror.wheelEventPixels = wheelEventPixels;
	    CodeMirror.Doc = Doc;
	    CodeMirror.splitLines = splitLinesAuto;
	    CodeMirror.countColumn = countColumn;
	    CodeMirror.findColumn = findColumn;
	    CodeMirror.isWordChar = isWordCharBasic;
	    CodeMirror.Pass = Pass;
	    CodeMirror.signal = signal;
	    CodeMirror.Line = Line;
	    CodeMirror.changeEnd = changeEnd;
	    CodeMirror.scrollbarModel = scrollbarModel;
	    CodeMirror.Pos = Pos;
	    CodeMirror.cmpPos = cmp;
	    CodeMirror.modes = modes;
	    CodeMirror.mimeModes = mimeModes;
	    CodeMirror.resolveMode = resolveMode;
	    CodeMirror.getMode = getMode;
	    CodeMirror.modeExtensions = modeExtensions;
	    CodeMirror.extendMode = extendMode;
	    CodeMirror.copyState = copyState;
	    CodeMirror.startState = startState;
	    CodeMirror.innerMode = innerMode;
	    CodeMirror.commands = commands;
	    CodeMirror.keyMap = keyMap;
	    CodeMirror.keyName = keyName;
	    CodeMirror.isModifierKey = isModifierKey;
	    CodeMirror.lookupKey = lookupKey;
	    CodeMirror.normalizeKeyMap = normalizeKeyMap;
	    CodeMirror.StringStream = StringStream;
	    CodeMirror.SharedTextMarker = SharedTextMarker;
	    CodeMirror.TextMarker = TextMarker;
	    CodeMirror.LineWidget = LineWidget;
	    CodeMirror.e_preventDefault = e_preventDefault;
	    CodeMirror.e_stopPropagation = e_stopPropagation;
	    CodeMirror.e_stop = e_stop;
	    CodeMirror.addClass = addClass;
	    CodeMirror.contains = contains;
	    CodeMirror.rmClass = rmClass;
	    CodeMirror.keyNames = keyNames;
	  }

	  // EDITOR CONSTRUCTOR

	  defineOptions(CodeMirror);

	  addEditorMethods(CodeMirror);

	  // Set up methods on CodeMirror's prototype to redirect to the editor's document.
	  var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
	  for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
	    { CodeMirror.prototype[prop] = (function(method) {
	      return function() {return method.apply(this.doc, arguments)}
	    })(Doc.prototype[prop]); } }

	  eventMixin(Doc);
	  CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};

	  // Extra arguments are stored as the mode's dependencies, which is
	  // used by (legacy) mechanisms like loadmode.js to automatically
	  // load a mode. (Preferred mechanism is the require/define calls.)
	  CodeMirror.defineMode = function(name/*, mode, …*/) {
	    if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; }
	    defineMode.apply(this, arguments);
	  };

	  CodeMirror.defineMIME = defineMIME;

	  // Minimal default mode.
	  CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
	  CodeMirror.defineMIME("text/plain", "null");

	  // EXTENSIONS

	  CodeMirror.defineExtension = function (name, func) {
	    CodeMirror.prototype[name] = func;
	  };
	  CodeMirror.defineDocExtension = function (name, func) {
	    Doc.prototype[name] = func;
	  };

	  CodeMirror.fromTextArea = fromTextArea;

	  addLegacyProps(CodeMirror);

	  CodeMirror.version = "5.65.8";

	  return CodeMirror;

	}))); 
} (codemirror$1));

var codemirrorExports = codemirror$1.exports;
const CodeMirror = /*@__PURE__*/getDefaultExportFromCjs(codemirrorExports);
/* Injected with object hook! */

var javascript = {exports: {}};/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	(function(mod) {
	  mod(codemirrorExports);
	})(function(CodeMirror) {

	CodeMirror.defineMode("javascript", function(config, parserConfig) {
	  var indentUnit = config.indentUnit;
	  var statementIndent = parserConfig.statementIndent;
	  var jsonldMode = parserConfig.jsonld;
	  var jsonMode = parserConfig.json || jsonldMode;
	  var trackScope = parserConfig.trackScope !== false;
	  var isTS = parserConfig.typescript;
	  var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;

	  // Tokenizer

	  var keywords = function(){
	    function kw(type) {return {type: type, style: "keyword"};}
	    var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
	    var operator = kw("operator"), atom = {type: "atom", style: "atom"};

	    return {
	      "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
	      "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
	      "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
	      "function": kw("function"), "catch": kw("catch"),
	      "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
	      "in": operator, "typeof": operator, "instanceof": operator,
	      "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
	      "this": kw("this"), "class": kw("class"), "super": kw("atom"),
	      "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
	      "await": C
	    };
	  }();

	  var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
	  var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;

	  function readRegexp(stream) {
	    var escaped = false, next, inSet = false;
	    while ((next = stream.next()) != null) {
	      if (!escaped) {
	        if (next == "/" && !inSet) return;
	        if (next == "[") inSet = true;
	        else if (inSet && next == "]") inSet = false;
	      }
	      escaped = !escaped && next == "\\";
	    }
	  }

	  // Used as scratch variables to communicate multiple values without
	  // consing up tons of objects.
	  var type, content;
	  function ret(tp, style, cont) {
	    type = tp; content = cont;
	    return style;
	  }
	  function tokenBase(stream, state) {
	    var ch = stream.next();
	    if (ch == '"' || ch == "'") {
	      state.tokenize = tokenString(ch);
	      return state.tokenize(stream, state);
	    } else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
	      return ret("number", "number");
	    } else if (ch == "." && stream.match("..")) {
	      return ret("spread", "meta");
	    } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
	      return ret(ch);
	    } else if (ch == "=" && stream.eat(">")) {
	      return ret("=>", "operator");
	    } else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
	      return ret("number", "number");
	    } else if (/\d/.test(ch)) {
	      stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
	      return ret("number", "number");
	    } else if (ch == "/") {
	      if (stream.eat("*")) {
	        state.tokenize = tokenComment;
	        return tokenComment(stream, state);
	      } else if (stream.eat("/")) {
	        stream.skipToEnd();
	        return ret("comment", "comment");
	      } else if (expressionAllowed(stream, state, 1)) {
	        readRegexp(stream);
	        stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
	        return ret("regexp", "string-2");
	      } else {
	        stream.eat("=");
	        return ret("operator", "operator", stream.current());
	      }
	    } else if (ch == "`") {
	      state.tokenize = tokenQuasi;
	      return tokenQuasi(stream, state);
	    } else if (ch == "#" && stream.peek() == "!") {
	      stream.skipToEnd();
	      return ret("meta", "meta");
	    } else if (ch == "#" && stream.eatWhile(wordRE)) {
	      return ret("variable", "property")
	    } else if (ch == "<" && stream.match("!--") ||
	               (ch == "-" && stream.match("->") && !/\S/.test(stream.string.slice(0, stream.start)))) {
	      stream.skipToEnd();
	      return ret("comment", "comment")
	    } else if (isOperatorChar.test(ch)) {
	      if (ch != ">" || !state.lexical || state.lexical.type != ">") {
	        if (stream.eat("=")) {
	          if (ch == "!" || ch == "=") stream.eat("=");
	        } else if (/[<>*+\-|&?]/.test(ch)) {
	          stream.eat(ch);
	          if (ch == ">") stream.eat(ch);
	        }
	      }
	      if (ch == "?" && stream.eat(".")) return ret(".")
	      return ret("operator", "operator", stream.current());
	    } else if (wordRE.test(ch)) {
	      stream.eatWhile(wordRE);
	      var word = stream.current();
	      if (state.lastType != ".") {
	        if (keywords.propertyIsEnumerable(word)) {
	          var kw = keywords[word];
	          return ret(kw.type, kw.style, word)
	        }
	        if (word == "async" && stream.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/, false))
	          return ret("async", "keyword", word)
	      }
	      return ret("variable", "variable", word)
	    }
	  }

	  function tokenString(quote) {
	    return function(stream, state) {
	      var escaped = false, next;
	      if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
	        state.tokenize = tokenBase;
	        return ret("jsonld-keyword", "meta");
	      }
	      while ((next = stream.next()) != null) {
	        if (next == quote && !escaped) break;
	        escaped = !escaped && next == "\\";
	      }
	      if (!escaped) state.tokenize = tokenBase;
	      return ret("string", "string");
	    };
	  }

	  function tokenComment(stream, state) {
	    var maybeEnd = false, ch;
	    while (ch = stream.next()) {
	      if (ch == "/" && maybeEnd) {
	        state.tokenize = tokenBase;
	        break;
	      }
	      maybeEnd = (ch == "*");
	    }
	    return ret("comment", "comment");
	  }

	  function tokenQuasi(stream, state) {
	    var escaped = false, next;
	    while ((next = stream.next()) != null) {
	      if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
	        state.tokenize = tokenBase;
	        break;
	      }
	      escaped = !escaped && next == "\\";
	    }
	    return ret("quasi", "string-2", stream.current());
	  }

	  var brackets = "([{}])";
	  // This is a crude lookahead trick to try and notice that we're
	  // parsing the argument patterns for a fat-arrow function before we
	  // actually hit the arrow token. It only works if the arrow is on
	  // the same line as the arguments and there's no strange noise
	  // (comments) in between. Fallback is to only notice when we hit the
	  // arrow, and not declare the arguments as locals for the arrow
	  // body.
	  function findFatArrow(stream, state) {
	    if (state.fatArrowAt) state.fatArrowAt = null;
	    var arrow = stream.string.indexOf("=>", stream.start);
	    if (arrow < 0) return;

	    if (isTS) { // Try to skip TypeScript return type declarations after the arguments
	      var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow));
	      if (m) arrow = m.index;
	    }

	    var depth = 0, sawSomething = false;
	    for (var pos = arrow - 1; pos >= 0; --pos) {
	      var ch = stream.string.charAt(pos);
	      var bracket = brackets.indexOf(ch);
	      if (bracket >= 0 && bracket < 3) {
	        if (!depth) { ++pos; break; }
	        if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
	      } else if (bracket >= 3 && bracket < 6) {
	        ++depth;
	      } else if (wordRE.test(ch)) {
	        sawSomething = true;
	      } else if (/["'\/`]/.test(ch)) {
	        for (;; --pos) {
	          if (pos == 0) return
	          var next = stream.string.charAt(pos - 1);
	          if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
	        }
	      } else if (sawSomething && !depth) {
	        ++pos;
	        break;
	      }
	    }
	    if (sawSomething && !depth) state.fatArrowAt = pos;
	  }

	  // Parser

	  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true,
	                     "regexp": true, "this": true, "import": true, "jsonld-keyword": true};

	  function JSLexical(indented, column, type, align, prev, info) {
	    this.indented = indented;
	    this.column = column;
	    this.type = type;
	    this.prev = prev;
	    this.info = info;
	    if (align != null) this.align = align;
	  }

	  function inScope(state, varname) {
	    if (!trackScope) return false
	    for (var v = state.localVars; v; v = v.next)
	      if (v.name == varname) return true;
	    for (var cx = state.context; cx; cx = cx.prev) {
	      for (var v = cx.vars; v; v = v.next)
	        if (v.name == varname) return true;
	    }
	  }

	  function parseJS(state, style, type, content, stream) {
	    var cc = state.cc;
	    // Communicate our context to the combinators.
	    // (Less wasteful than consing up a hundred closures on every call.)
	    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;

	    if (!state.lexical.hasOwnProperty("align"))
	      state.lexical.align = true;

	    while(true) {
	      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
	      if (combinator(type, content)) {
	        while(cc.length && cc[cc.length - 1].lex)
	          cc.pop()();
	        if (cx.marked) return cx.marked;
	        if (type == "variable" && inScope(state, content)) return "variable-2";
	        return style;
	      }
	    }
	  }

	  // Combinator utils

	  var cx = {state: null, column: null, marked: null, cc: null};
	  function pass() {
	    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
	  }
	  function cont() {
	    pass.apply(null, arguments);
	    return true;
	  }
	  function inList(name, list) {
	    for (var v = list; v; v = v.next) if (v.name == name) return true
	    return false;
	  }
	  function register(varname) {
	    var state = cx.state;
	    cx.marked = "def";
	    if (!trackScope) return
	    if (state.context) {
	      if (state.lexical.info == "var" && state.context && state.context.block) {
	        // FIXME function decls are also not block scoped
	        var newContext = registerVarScoped(varname, state.context);
	        if (newContext != null) {
	          state.context = newContext;
	          return
	        }
	      } else if (!inList(varname, state.localVars)) {
	        state.localVars = new Var(varname, state.localVars);
	        return
	      }
	    }
	    // Fall through means this is global
	    if (parserConfig.globalVars && !inList(varname, state.globalVars))
	      state.globalVars = new Var(varname, state.globalVars);
	  }
	  function registerVarScoped(varname, context) {
	    if (!context) {
	      return null
	    } else if (context.block) {
	      var inner = registerVarScoped(varname, context.prev);
	      if (!inner) return null
	      if (inner == context.prev) return context
	      return new Context(inner, context.vars, true)
	    } else if (inList(varname, context.vars)) {
	      return context
	    } else {
	      return new Context(context.prev, new Var(varname, context.vars), false)
	    }
	  }

	  function isModifier(name) {
	    return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
	  }

	  // Combinators

	  function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block; }
	  function Var(name, next) { this.name = name; this.next = next; }

	  var defaultVars = new Var("this", new Var("arguments", null));
	  function pushcontext() {
	    cx.state.context = new Context(cx.state.context, cx.state.localVars, false);
	    cx.state.localVars = defaultVars;
	  }
	  function pushblockcontext() {
	    cx.state.context = new Context(cx.state.context, cx.state.localVars, true);
	    cx.state.localVars = null;
	  }
	  pushcontext.lex = pushblockcontext.lex = true;
	  function popcontext() {
	    cx.state.localVars = cx.state.context.vars;
	    cx.state.context = cx.state.context.prev;
	  }
	  popcontext.lex = true;
	  function pushlex(type, info) {
	    var result = function() {
	      var state = cx.state, indent = state.indented;
	      if (state.lexical.type == "stat") indent = state.lexical.indented;
	      else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
	        indent = outer.indented;
	      state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
	    };
	    result.lex = true;
	    return result;
	  }
	  function poplex() {
	    var state = cx.state;
	    if (state.lexical.prev) {
	      if (state.lexical.type == ")")
	        state.indented = state.lexical.indented;
	      state.lexical = state.lexical.prev;
	    }
	  }
	  poplex.lex = true;

	  function expect(wanted) {
	    function exp(type) {
	      if (type == wanted) return cont();
	      else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
	      else return cont(exp);
	    }	    return exp;
	  }

	  function statement(type, value) {
	    if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
	    if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
	    if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
	    if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
	    if (type == "debugger") return cont(expect(";"));
	    if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
	    if (type == ";") return cont();
	    if (type == "if") {
	      if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
	        cx.state.cc.pop()();
	      return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
	    }
	    if (type == "function") return cont(functiondef);
	    if (type == "for") return cont(pushlex("form"), pushblockcontext, forspec, statement, popcontext, poplex);
	    if (type == "class" || (isTS && value == "interface")) {
	      cx.marked = "keyword";
	      return cont(pushlex("form", type == "class" ? type : value), className, poplex)
	    }
	    if (type == "variable") {
	      if (isTS && value == "declare") {
	        cx.marked = "keyword";
	        return cont(statement)
	      } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
	        cx.marked = "keyword";
	        if (value == "enum") return cont(enumdef);
	        else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
	        else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
	      } else if (isTS && value == "namespace") {
	        cx.marked = "keyword";
	        return cont(pushlex("form"), expression, statement, poplex)
	      } else if (isTS && value == "abstract") {
	        cx.marked = "keyword";
	        return cont(statement)
	      } else {
	        return cont(pushlex("stat"), maybelabel);
	      }
	    }
	    if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
	                                      block, poplex, poplex, popcontext);
	    if (type == "case") return cont(expression, expect(":"));
	    if (type == "default") return cont(expect(":"));
	    if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
	    if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
	    if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
	    if (type == "async") return cont(statement)
	    if (value == "@") return cont(expression, statement)
	    return pass(pushlex("stat"), expression, expect(";"), poplex);
	  }
	  function maybeCatchBinding(type) {
	    if (type == "(") return cont(funarg, expect(")"))
	  }
	  function expression(type, value) {
	    return expressionInner(type, value, false);
	  }
	  function expressionNoComma(type, value) {
	    return expressionInner(type, value, true);
	  }
	  function parenExpr(type) {
	    if (type != "(") return pass()
	    return cont(pushlex(")"), maybeexpression, expect(")"), poplex)
	  }
	  function expressionInner(type, value, noComma) {
	    if (cx.state.fatArrowAt == cx.stream.start) {
	      var body = noComma ? arrowBodyNoComma : arrowBody;
	      if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
	      else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
	    }

	    var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
	    if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
	    if (type == "function") return cont(functiondef, maybeop);
	    if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
	    if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
	    if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
	    if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
	    if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
	    if (type == "{") return contCommasep(objprop, "}", null, maybeop);
	    if (type == "quasi") return pass(quasi, maybeop);
	    if (type == "new") return cont(maybeTarget(noComma));
	    return cont();
	  }
	  function maybeexpression(type) {
	    if (type.match(/[;\}\)\],]/)) return pass();
	    return pass(expression);
	  }

	  function maybeoperatorComma(type, value) {
	    if (type == ",") return cont(maybeexpression);
	    return maybeoperatorNoComma(type, value, false);
	  }
	  function maybeoperatorNoComma(type, value, noComma) {
	    var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
	    var expr = noComma == false ? expression : expressionNoComma;
	    if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
	    if (type == "operator") {
	      if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
	      if (isTS && value == "<" && cx.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/, false))
	        return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
	      if (value == "?") return cont(expression, expect(":"), expr);
	      return cont(expr);
	    }
	    if (type == "quasi") { return pass(quasi, me); }
	    if (type == ";") return;
	    if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
	    if (type == ".") return cont(property, me);
	    if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
	    if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
	    if (type == "regexp") {
	      cx.state.lastType = cx.marked = "operator";
	      cx.stream.backUp(cx.stream.pos - cx.stream.start - 1);
	      return cont(expr)
	    }
	  }
	  function quasi(type, value) {
	    if (type != "quasi") return pass();
	    if (value.slice(value.length - 2) != "${") return cont(quasi);
	    return cont(maybeexpression, continueQuasi);
	  }
	  function continueQuasi(type) {
	    if (type == "}") {
	      cx.marked = "string-2";
	      cx.state.tokenize = tokenQuasi;
	      return cont(quasi);
	    }
	  }
	  function arrowBody(type) {
	    findFatArrow(cx.stream, cx.state);
	    return pass(type == "{" ? statement : expression);
	  }
	  function arrowBodyNoComma(type) {
	    findFatArrow(cx.stream, cx.state);
	    return pass(type == "{" ? statement : expressionNoComma);
	  }
	  function maybeTarget(noComma) {
	    return function(type) {
	      if (type == ".") return cont(noComma ? targetNoComma : target);
	      else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
	      else return pass(noComma ? expressionNoComma : expression);
	    };
	  }
	  function target(_, value) {
	    if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
	  }
	  function targetNoComma(_, value) {
	    if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
	  }
	  function maybelabel(type) {
	    if (type == ":") return cont(poplex, statement);
	    return pass(maybeoperatorComma, expect(";"), poplex);
	  }
	  function property(type) {
	    if (type == "variable") {cx.marked = "property"; return cont();}
	  }
	  function objprop(type, value) {
	    if (type == "async") {
	      cx.marked = "property";
	      return cont(objprop);
	    } else if (type == "variable" || cx.style == "keyword") {
	      cx.marked = "property";
	      if (value == "get" || value == "set") return cont(getterSetter);
	      var m; // Work around fat-arrow-detection complication for detecting typescript typed arrow params
	      if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
	        cx.state.fatArrowAt = cx.stream.pos + m[0].length;
	      return cont(afterprop);
	    } else if (type == "number" || type == "string") {
	      cx.marked = jsonldMode ? "property" : (cx.style + " property");
	      return cont(afterprop);
	    } else if (type == "jsonld-keyword") {
	      return cont(afterprop);
	    } else if (isTS && isModifier(value)) {
	      cx.marked = "keyword";
	      return cont(objprop)
	    } else if (type == "[") {
	      return cont(expression, maybetype, expect("]"), afterprop);
	    } else if (type == "spread") {
	      return cont(expressionNoComma, afterprop);
	    } else if (value == "*") {
	      cx.marked = "keyword";
	      return cont(objprop);
	    } else if (type == ":") {
	      return pass(afterprop)
	    }
	  }
	  function getterSetter(type) {
	    if (type != "variable") return pass(afterprop);
	    cx.marked = "property";
	    return cont(functiondef);
	  }
	  function afterprop(type) {
	    if (type == ":") return cont(expressionNoComma);
	    if (type == "(") return pass(functiondef);
	  }
	  function commasep(what, end, sep) {
	    function proceed(type, value) {
	      if (sep ? sep.indexOf(type) > -1 : type == ",") {
	        var lex = cx.state.lexical;
	        if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
	        return cont(function(type, value) {
	          if (type == end || value == end) return pass()
	          return pass(what)
	        }, proceed);
	      }
	      if (type == end || value == end) return cont();
	      if (sep && sep.indexOf(";") > -1) return pass(what)
	      return cont(expect(end));
	    }
	    return function(type, value) {
	      if (type == end || value == end) return cont();
	      return pass(what, proceed);
	    };
	  }
	  function contCommasep(what, end, info) {
	    for (var i = 3; i < arguments.length; i++)
	      cx.cc.push(arguments[i]);
	    return cont(pushlex(end, info), commasep(what, end), poplex);
	  }
	  function block(type) {
	    if (type == "}") return cont();
	    return pass(statement, block);
	  }
	  function maybetype(type, value) {
	    if (isTS) {
	      if (type == ":") return cont(typeexpr);
	      if (value == "?") return cont(maybetype);
	    }
	  }
	  function maybetypeOrIn(type, value) {
	    if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
	  }
	  function mayberettype(type) {
	    if (isTS && type == ":") {
	      if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
	      else return cont(typeexpr)
	    }
	  }
	  function isKW(_, value) {
	    if (value == "is") {
	      cx.marked = "keyword";
	      return cont()
	    }
	  }
	  function typeexpr(type, value) {
	    if (value == "keyof" || value == "typeof" || value == "infer" || value == "readonly") {
	      cx.marked = "keyword";
	      return cont(value == "typeof" ? expressionNoComma : typeexpr)
	    }
	    if (type == "variable" || value == "void") {
	      cx.marked = "type";
	      return cont(afterType)
	    }
	    if (value == "|" || value == "&") return cont(typeexpr)
	    if (type == "string" || type == "number" || type == "atom") return cont(afterType);
	    if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
	    if (type == "{") return cont(pushlex("}"), typeprops, poplex, afterType)
	    if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
	    if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
	    if (type == "quasi") { return pass(quasiType, afterType); }
	  }
	  function maybeReturnType(type) {
	    if (type == "=>") return cont(typeexpr)
	  }
	  function typeprops(type) {
	    if (type.match(/[\}\)\]]/)) return cont()
	    if (type == "," || type == ";") return cont(typeprops)
	    return pass(typeprop, typeprops)
	  }
	  function typeprop(type, value) {
	    if (type == "variable" || cx.style == "keyword") {
	      cx.marked = "property";
	      return cont(typeprop)
	    } else if (value == "?" || type == "number" || type == "string") {
	      return cont(typeprop)
	    } else if (type == ":") {
	      return cont(typeexpr)
	    } else if (type == "[") {
	      return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
	    } else if (type == "(") {
	      return pass(functiondecl, typeprop)
	    } else if (!type.match(/[;\}\)\],]/)) {
	      return cont()
	    }
	  }
	  function quasiType(type, value) {
	    if (type != "quasi") return pass();
	    if (value.slice(value.length - 2) != "${") return cont(quasiType);
	    return cont(typeexpr, continueQuasiType);
	  }
	  function continueQuasiType(type) {
	    if (type == "}") {
	      cx.marked = "string-2";
	      cx.state.tokenize = tokenQuasi;
	      return cont(quasiType);
	    }
	  }
	  function typearg(type, value) {
	    if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
	    if (type == ":") return cont(typeexpr)
	    if (type == "spread") return cont(typearg)
	    return pass(typeexpr)
	  }
	  function afterType(type, value) {
	    if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
	    if (value == "|" || type == "." || value == "&") return cont(typeexpr)
	    if (type == "[") return cont(typeexpr, expect("]"), afterType)
	    if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
	    if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
	  }
	  function maybeTypeArgs(_, value) {
	    if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
	  }
	  function typeparam() {
	    return pass(typeexpr, maybeTypeDefault)
	  }
	  function maybeTypeDefault(_, value) {
	    if (value == "=") return cont(typeexpr)
	  }
	  function vardef(_, value) {
	    if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
	    return pass(pattern, maybetype, maybeAssign, vardefCont);
	  }
	  function pattern(type, value) {
	    if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
	    if (type == "variable") { register(value); return cont(); }
	    if (type == "spread") return cont(pattern);
	    if (type == "[") return contCommasep(eltpattern, "]");
	    if (type == "{") return contCommasep(proppattern, "}");
	  }
	  function proppattern(type, value) {
	    if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
	      register(value);
	      return cont(maybeAssign);
	    }
	    if (type == "variable") cx.marked = "property";
	    if (type == "spread") return cont(pattern);
	    if (type == "}") return pass();
	    if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
	    return cont(expect(":"), pattern, maybeAssign);
	  }
	  function eltpattern() {
	    return pass(pattern, maybeAssign)
	  }
	  function maybeAssign(_type, value) {
	    if (value == "=") return cont(expressionNoComma);
	  }
	  function vardefCont(type) {
	    if (type == ",") return cont(vardef);
	  }
	  function maybeelse(type, value) {
	    if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
	  }
	  function forspec(type, value) {
	    if (value == "await") return cont(forspec);
	    if (type == "(") return cont(pushlex(")"), forspec1, poplex);
	  }
	  function forspec1(type) {
	    if (type == "var") return cont(vardef, forspec2);
	    if (type == "variable") return cont(forspec2);
	    return pass(forspec2)
	  }
	  function forspec2(type, value) {
	    if (type == ")") return cont()
	    if (type == ";") return cont(forspec2)
	    if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
	    return pass(expression, forspec2)
	  }
	  function functiondef(type, value) {
	    if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
	    if (type == "variable") {register(value); return cont(functiondef);}
	    if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
	    if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
	  }
	  function functiondecl(type, value) {
	    if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
	    if (type == "variable") {register(value); return cont(functiondecl);}
	    if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
	    if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
	  }
	  function typename(type, value) {
	    if (type == "keyword" || type == "variable") {
	      cx.marked = "type";
	      return cont(typename)
	    } else if (value == "<") {
	      return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
	    }
	  }
	  function funarg(type, value) {
	    if (value == "@") cont(expression, funarg);
	    if (type == "spread") return cont(funarg);
	    if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
	    if (isTS && type == "this") return cont(maybetype, maybeAssign)
	    return pass(pattern, maybetype, maybeAssign);
	  }
	  function classExpression(type, value) {
	    // Class expressions may have an optional name.
	    if (type == "variable") return className(type, value);
	    return classNameAfter(type, value);
	  }
	  function className(type, value) {
	    if (type == "variable") {register(value); return cont(classNameAfter);}
	  }
	  function classNameAfter(type, value) {
	    if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
	    if (value == "extends" || value == "implements" || (isTS && type == ",")) {
	      if (value == "implements") cx.marked = "keyword";
	      return cont(isTS ? typeexpr : expression, classNameAfter);
	    }
	    if (type == "{") return cont(pushlex("}"), classBody, poplex);
	  }
	  function classBody(type, value) {
	    if (type == "async" ||
	        (type == "variable" &&
	         (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
	         cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
	      cx.marked = "keyword";
	      return cont(classBody);
	    }
	    if (type == "variable" || cx.style == "keyword") {
	      cx.marked = "property";
	      return cont(classfield, classBody);
	    }
	    if (type == "number" || type == "string") return cont(classfield, classBody);
	    if (type == "[")
	      return cont(expression, maybetype, expect("]"), classfield, classBody)
	    if (value == "*") {
	      cx.marked = "keyword";
	      return cont(classBody);
	    }
	    if (isTS && type == "(") return pass(functiondecl, classBody)
	    if (type == ";" || type == ",") return cont(classBody);
	    if (type == "}") return cont();
	    if (value == "@") return cont(expression, classBody)
	  }
	  function classfield(type, value) {
	    if (value == "!") return cont(classfield)
	    if (value == "?") return cont(classfield)
	    if (type == ":") return cont(typeexpr, maybeAssign)
	    if (value == "=") return cont(expressionNoComma)
	    var context = cx.state.lexical.prev, isInterface = context && context.info == "interface";
	    return pass(isInterface ? functiondecl : functiondef)
	  }
	  function afterExport(type, value) {
	    if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
	    if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
	    if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
	    return pass(statement);
	  }
	  function exportField(type, value) {
	    if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
	    if (type == "variable") return pass(expressionNoComma, exportField);
	  }
	  function afterImport(type) {
	    if (type == "string") return cont();
	    if (type == "(") return pass(expression);
	    if (type == ".") return pass(maybeoperatorComma);
	    return pass(importSpec, maybeMoreImports, maybeFrom);
	  }
	  function importSpec(type, value) {
	    if (type == "{") return contCommasep(importSpec, "}");
	    if (type == "variable") register(value);
	    if (value == "*") cx.marked = "keyword";
	    return cont(maybeAs);
	  }
	  function maybeMoreImports(type) {
	    if (type == ",") return cont(importSpec, maybeMoreImports)
	  }
	  function maybeAs(_type, value) {
	    if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
	  }
	  function maybeFrom(_type, value) {
	    if (value == "from") { cx.marked = "keyword"; return cont(expression); }
	  }
	  function arrayLiteral(type) {
	    if (type == "]") return cont();
	    return pass(commasep(expressionNoComma, "]"));
	  }
	  function enumdef() {
	    return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
	  }
	  function enummember() {
	    return pass(pattern, maybeAssign);
	  }

	  function isContinuedStatement(state, textAfter) {
	    return state.lastType == "operator" || state.lastType == "," ||
	      isOperatorChar.test(textAfter.charAt(0)) ||
	      /[,.]/.test(textAfter.charAt(0));
	  }

	  function expressionAllowed(stream, state, backUp) {
	    return state.tokenize == tokenBase &&
	      /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
	      (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
	  }

	  // Interface

	  return {
	    startState: function(basecolumn) {
	      var state = {
	        tokenize: tokenBase,
	        lastType: "sof",
	        cc: [],
	        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
	        localVars: parserConfig.localVars,
	        context: parserConfig.localVars && new Context(null, null, false),
	        indented: basecolumn || 0
	      };
	      if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
	        state.globalVars = parserConfig.globalVars;
	      return state;
	    },

	    token: function(stream, state) {
	      if (stream.sol()) {
	        if (!state.lexical.hasOwnProperty("align"))
	          state.lexical.align = false;
	        state.indented = stream.indentation();
	        findFatArrow(stream, state);
	      }
	      if (state.tokenize != tokenComment && stream.eatSpace()) return null;
	      var style = state.tokenize(stream, state);
	      if (type == "comment") return style;
	      state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
	      return parseJS(state, style, type, content, stream);
	    },

	    indent: function(state, textAfter) {
	      if (state.tokenize == tokenComment || state.tokenize == tokenQuasi) return CodeMirror.Pass;
	      if (state.tokenize != tokenBase) return 0;
	      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top;
	      // Kludge to prevent 'maybelse' from blocking lexical scope pops
	      if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
	        var c = state.cc[i];
	        if (c == poplex) lexical = lexical.prev;
	        else if (c != maybeelse && c != popcontext) break;
	      }
	      while ((lexical.type == "stat" || lexical.type == "form") &&
	             (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
	                                   (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
	                                   !/^[,\.=+\-*:?[\(]/.test(textAfter))))
	        lexical = lexical.prev;
	      if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
	        lexical = lexical.prev;
	      var type = lexical.type, closing = firstChar == type;

	      if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
	      else if (type == "form" && firstChar == "{") return lexical.indented;
	      else if (type == "form") return lexical.indented + indentUnit;
	      else if (type == "stat")
	        return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
	      else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
	        return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
	      else if (lexical.align) return lexical.column + (closing ? 0 : 1);
	      else return lexical.indented + (closing ? 0 : indentUnit);
	    },

	    electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
	    blockCommentStart: jsonMode ? null : "/*",
	    blockCommentEnd: jsonMode ? null : "*/",
	    blockCommentContinue: jsonMode ? null : " * ",
	    lineComment: jsonMode ? null : "//",
	    fold: "brace",
	    closeBrackets: "()[]{}''\"\"``",

	    helperType: jsonMode ? "json" : "javascript",
	    jsonldMode: jsonldMode,
	    jsonMode: jsonMode,

	    expressionAllowed: expressionAllowed,

	    skipExpression: function(state) {
	      parseJS(state, "atom", "atom", "true", new CodeMirror.StringStream("", 2, null));
	    }
	  };
	});

	CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);

	CodeMirror.defineMIME("text/javascript", "javascript");
	CodeMirror.defineMIME("text/ecmascript", "javascript");
	CodeMirror.defineMIME("application/javascript", "javascript");
	CodeMirror.defineMIME("application/x-javascript", "javascript");
	CodeMirror.defineMIME("application/ecmascript", "javascript");
	CodeMirror.defineMIME("application/json", { name: "javascript", json: true });
	CodeMirror.defineMIME("application/x-json", { name: "javascript", json: true });
	CodeMirror.defineMIME("application/manifest+json", { name: "javascript", json: true });
	CodeMirror.defineMIME("application/ld+json", { name: "javascript", jsonld: true });
	CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
	CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });

	}); 
} ());

var javascriptExports = javascript.exports;
/* Injected with object hook! */

var css = {exports: {}};/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	(function(mod) {
	  mod(codemirrorExports);
	})(function(CodeMirror) {

	CodeMirror.defineMode("css", function(config, parserConfig) {
	  var inline = parserConfig.inline;
	  if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");

	  var indentUnit = config.indentUnit,
	      tokenHooks = parserConfig.tokenHooks,
	      documentTypes = parserConfig.documentTypes || {},
	      mediaTypes = parserConfig.mediaTypes || {},
	      mediaFeatures = parserConfig.mediaFeatures || {},
	      mediaValueKeywords = parserConfig.mediaValueKeywords || {},
	      propertyKeywords = parserConfig.propertyKeywords || {},
	      nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
	      fontProperties = parserConfig.fontProperties || {},
	      counterDescriptors = parserConfig.counterDescriptors || {},
	      colorKeywords = parserConfig.colorKeywords || {},
	      valueKeywords = parserConfig.valueKeywords || {},
	      allowNested = parserConfig.allowNested,
	      lineComment = parserConfig.lineComment,
	      supportsAtComponent = parserConfig.supportsAtComponent === true,
	      highlightNonStandardPropertyKeywords = config.highlightNonStandardPropertyKeywords !== false;

	  var type, override;
	  function ret(style, tp) { type = tp; return style; }

	  // Tokenizers

	  function tokenBase(stream, state) {
	    var ch = stream.next();
	    if (tokenHooks[ch]) {
	      var result = tokenHooks[ch](stream, state);
	      if (result !== false) return result;
	    }
	    if (ch == "@") {
	      stream.eatWhile(/[\w\\\-]/);
	      return ret("def", stream.current());
	    } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
	      return ret(null, "compare");
	    } else if (ch == "\"" || ch == "'") {
	      state.tokenize = tokenString(ch);
	      return state.tokenize(stream, state);
	    } else if (ch == "#") {
	      stream.eatWhile(/[\w\\\-]/);
	      return ret("atom", "hash");
	    } else if (ch == "!") {
	      stream.match(/^\s*\w*/);
	      return ret("keyword", "important");
	    } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
	      stream.eatWhile(/[\w.%]/);
	      return ret("number", "unit");
	    } else if (ch === "-") {
	      if (/[\d.]/.test(stream.peek())) {
	        stream.eatWhile(/[\w.%]/);
	        return ret("number", "unit");
	      } else if (stream.match(/^-[\w\\\-]*/)) {
	        stream.eatWhile(/[\w\\\-]/);
	        if (stream.match(/^\s*:/, false))
	          return ret("variable-2", "variable-definition");
	        return ret("variable-2", "variable");
	      } else if (stream.match(/^\w+-/)) {
	        return ret("meta", "meta");
	      }
	    } else if (/[,+>*\/]/.test(ch)) {
	      return ret(null, "select-op");
	    } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
	      return ret("qualifier", "qualifier");
	    } else if (/[:;{}\[\]\(\)]/.test(ch)) {
	      return ret(null, ch);
	    } else if (stream.match(/^[\w-.]+(?=\()/)) {
	      if (/^(url(-prefix)?|domain|regexp)$/i.test(stream.current())) {
	        state.tokenize = tokenParenthesized;
	      }
	      return ret("variable callee", "variable");
	    } else if (/[\w\\\-]/.test(ch)) {
	      stream.eatWhile(/[\w\\\-]/);
	      return ret("property", "word");
	    } else {
	      return ret(null, null);
	    }
	  }

	  function tokenString(quote) {
	    return function(stream, state) {
	      var escaped = false, ch;
	      while ((ch = stream.next()) != null) {
	        if (ch == quote && !escaped) {
	          if (quote == ")") stream.backUp(1);
	          break;
	        }
	        escaped = !escaped && ch == "\\";
	      }
	      if (ch == quote || !escaped && quote != ")") state.tokenize = null;
	      return ret("string", "string");
	    };
	  }

	  function tokenParenthesized(stream, state) {
	    stream.next(); // Must be '('
	    if (!stream.match(/^\s*[\"\')]/, false))
	      state.tokenize = tokenString(")");
	    else
	      state.tokenize = null;
	    return ret(null, "(");
	  }

	  // Context management

	  function Context(type, indent, prev) {
	    this.type = type;
	    this.indent = indent;
	    this.prev = prev;
	  }

	  function pushContext(state, stream, type, indent) {
	    state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
	    return type;
	  }

	  function popContext(state) {
	    if (state.context.prev)
	      state.context = state.context.prev;
	    return state.context.type;
	  }

	  function pass(type, stream, state) {
	    return states[state.context.type](type, stream, state);
	  }
	  function popAndPass(type, stream, state, n) {
	    for (var i = n || 1; i > 0; i--)
	      state.context = state.context.prev;
	    return pass(type, stream, state);
	  }

	  // Parser

	  function wordAsValue(stream) {
	    var word = stream.current().toLowerCase();
	    if (valueKeywords.hasOwnProperty(word))
	      override = "atom";
	    else if (colorKeywords.hasOwnProperty(word))
	      override = "keyword";
	    else
	      override = "variable";
	  }

	  var states = {};

	  states.top = function(type, stream, state) {
	    if (type == "{") {
	      return pushContext(state, stream, "block");
	    } else if (type == "}" && state.context.prev) {
	      return popContext(state);
	    } else if (supportsAtComponent && /@component/i.test(type)) {
	      return pushContext(state, stream, "atComponentBlock");
	    } else if (/^@(-moz-)?document$/i.test(type)) {
	      return pushContext(state, stream, "documentTypes");
	    } else if (/^@(media|supports|(-moz-)?document|import)$/i.test(type)) {
	      return pushContext(state, stream, "atBlock");
	    } else if (/^@(font-face|counter-style)/i.test(type)) {
	      state.stateArg = type;
	      return "restricted_atBlock_before";
	    } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(type)) {
	      return "keyframes";
	    } else if (type && type.charAt(0) == "@") {
	      return pushContext(state, stream, "at");
	    } else if (type == "hash") {
	      override = "builtin";
	    } else if (type == "word") {
	      override = "tag";
	    } else if (type == "variable-definition") {
	      return "maybeprop";
	    } else if (type == "interpolation") {
	      return pushContext(state, stream, "interpolation");
	    } else if (type == ":") {
	      return "pseudo";
	    } else if (allowNested && type == "(") {
	      return pushContext(state, stream, "parens");
	    }
	    return state.context.type;
	  };

	  states.block = function(type, stream, state) {
	    if (type == "word") {
	      var word = stream.current().toLowerCase();
	      if (propertyKeywords.hasOwnProperty(word)) {
	        override = "property";
	        return "maybeprop";
	      } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
	        override = highlightNonStandardPropertyKeywords ? "string-2" : "property";
	        return "maybeprop";
	      } else if (allowNested) {
	        override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
	        return "block";
	      } else {
	        override += " error";
	        return "maybeprop";
	      }
	    } else if (type == "meta") {
	      return "block";
	    } else if (!allowNested && (type == "hash" || type == "qualifier")) {
	      override = "error";
	      return "block";
	    } else {
	      return states.top(type, stream, state);
	    }
	  };

	  states.maybeprop = function(type, stream, state) {
	    if (type == ":") return pushContext(state, stream, "prop");
	    return pass(type, stream, state);
	  };

	  states.prop = function(type, stream, state) {
	    if (type == ";") return popContext(state);
	    if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
	    if (type == "}" || type == "{") return popAndPass(type, stream, state);
	    if (type == "(") return pushContext(state, stream, "parens");

	    if (type == "hash" && !/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(stream.current())) {
	      override += " error";
	    } else if (type == "word") {
	      wordAsValue(stream);
	    } else if (type == "interpolation") {
	      return pushContext(state, stream, "interpolation");
	    }
	    return "prop";
	  };

	  states.propBlock = function(type, _stream, state) {
	    if (type == "}") return popContext(state);
	    if (type == "word") { override = "property"; return "maybeprop"; }
	    return state.context.type;
	  };

	  states.parens = function(type, stream, state) {
	    if (type == "{" || type == "}") return popAndPass(type, stream, state);
	    if (type == ")") return popContext(state);
	    if (type == "(") return pushContext(state, stream, "parens");
	    if (type == "interpolation") return pushContext(state, stream, "interpolation");
	    if (type == "word") wordAsValue(stream);
	    return "parens";
	  };

	  states.pseudo = function(type, stream, state) {
	    if (type == "meta") return "pseudo";

	    if (type == "word") {
	      override = "variable-3";
	      return state.context.type;
	    }
	    return pass(type, stream, state);
	  };

	  states.documentTypes = function(type, stream, state) {
	    if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
	      override = "tag";
	      return state.context.type;
	    } else {
	      return states.atBlock(type, stream, state);
	    }
	  };

	  states.atBlock = function(type, stream, state) {
	    if (type == "(") return pushContext(state, stream, "atBlock_parens");
	    if (type == "}" || type == ";") return popAndPass(type, stream, state);
	    if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");

	    if (type == "interpolation") return pushContext(state, stream, "interpolation");

	    if (type == "word") {
	      var word = stream.current().toLowerCase();
	      if (word == "only" || word == "not" || word == "and" || word == "or")
	        override = "keyword";
	      else if (mediaTypes.hasOwnProperty(word))
	        override = "attribute";
	      else if (mediaFeatures.hasOwnProperty(word))
	        override = "property";
	      else if (mediaValueKeywords.hasOwnProperty(word))
	        override = "keyword";
	      else if (propertyKeywords.hasOwnProperty(word))
	        override = "property";
	      else if (nonStandardPropertyKeywords.hasOwnProperty(word))
	        override = highlightNonStandardPropertyKeywords ? "string-2" : "property";
	      else if (valueKeywords.hasOwnProperty(word))
	        override = "atom";
	      else if (colorKeywords.hasOwnProperty(word))
	        override = "keyword";
	      else
	        override = "error";
	    }
	    return state.context.type;
	  };

	  states.atComponentBlock = function(type, stream, state) {
	    if (type == "}")
	      return popAndPass(type, stream, state);
	    if (type == "{")
	      return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
	    if (type == "word")
	      override = "error";
	    return state.context.type;
	  };

	  states.atBlock_parens = function(type, stream, state) {
	    if (type == ")") return popContext(state);
	    if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
	    return states.atBlock(type, stream, state);
	  };

	  states.restricted_atBlock_before = function(type, stream, state) {
	    if (type == "{")
	      return pushContext(state, stream, "restricted_atBlock");
	    if (type == "word" && state.stateArg == "@counter-style") {
	      override = "variable";
	      return "restricted_atBlock_before";
	    }
	    return pass(type, stream, state);
	  };

	  states.restricted_atBlock = function(type, stream, state) {
	    if (type == "}") {
	      state.stateArg = null;
	      return popContext(state);
	    }
	    if (type == "word") {
	      if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
	          (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
	        override = "error";
	      else
	        override = "property";
	      return "maybeprop";
	    }
	    return "restricted_atBlock";
	  };

	  states.keyframes = function(type, stream, state) {
	    if (type == "word") { override = "variable"; return "keyframes"; }
	    if (type == "{") return pushContext(state, stream, "top");
	    return pass(type, stream, state);
	  };

	  states.at = function(type, stream, state) {
	    if (type == ";") return popContext(state);
	    if (type == "{" || type == "}") return popAndPass(type, stream, state);
	    if (type == "word") override = "tag";
	    else if (type == "hash") override = "builtin";
	    return "at";
	  };

	  states.interpolation = function(type, stream, state) {
	    if (type == "}") return popContext(state);
	    if (type == "{" || type == ";") return popAndPass(type, stream, state);
	    if (type == "word") override = "variable";
	    else if (type != "variable" && type != "(" && type != ")") override = "error";
	    return "interpolation";
	  };

	  return {
	    startState: function(base) {
	      return {tokenize: null,
	              state: inline ? "block" : "top",
	              stateArg: null,
	              context: new Context(inline ? "block" : "top", base || 0, null)};
	    },

	    token: function(stream, state) {
	      if (!state.tokenize && stream.eatSpace()) return null;
	      var style = (state.tokenize || tokenBase)(stream, state);
	      if (style && typeof style == "object") {
	        type = style[1];
	        style = style[0];
	      }
	      override = style;
	      if (type != "comment")
	        state.state = states[state.state](type, stream, state);
	      return override;
	    },

	    indent: function(state, textAfter) {
	      var cx = state.context, ch = textAfter && textAfter.charAt(0);
	      var indent = cx.indent;
	      if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
	      if (cx.prev) {
	        if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
	                          cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
	          // Resume indentation from parent context.
	          cx = cx.prev;
	          indent = cx.indent;
	        } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
	            ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
	          // Dedent relative to current context.
	          indent = Math.max(0, cx.indent - indentUnit);
	        }
	      }
	      return indent;
	    },

	    electricChars: "}",
	    blockCommentStart: "/*",
	    blockCommentEnd: "*/",
	    blockCommentContinue: " * ",
	    lineComment: lineComment,
	    fold: "brace"
	  };
	});

	  function keySet(array) {
	    var keys = {};
	    for (var i = 0; i < array.length; ++i) {
	      keys[array[i].toLowerCase()] = true;
	    }
	    return keys;
	  }

	  var documentTypes_ = [
	    "domain", "regexp", "url", "url-prefix"
	  ], documentTypes = keySet(documentTypes_);

	  var mediaTypes_ = [
	    "all", "aural", "braille", "handheld", "print", "projection", "screen",
	    "tty", "tv", "embossed"
	  ], mediaTypes = keySet(mediaTypes_);

	  var mediaFeatures_ = [
	    "width", "min-width", "max-width", "height", "min-height", "max-height",
	    "device-width", "min-device-width", "max-device-width", "device-height",
	    "min-device-height", "max-device-height", "aspect-ratio",
	    "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
	    "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
	    "max-color", "color-index", "min-color-index", "max-color-index",
	    "monochrome", "min-monochrome", "max-monochrome", "resolution",
	    "min-resolution", "max-resolution", "scan", "grid", "orientation",
	    "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
	    "pointer", "any-pointer", "hover", "any-hover", "prefers-color-scheme",
	    "dynamic-range", "video-dynamic-range"
	  ], mediaFeatures = keySet(mediaFeatures_);

	  var mediaValueKeywords_ = [
	    "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
	    "interlace", "progressive",
	    "dark", "light",
	    "standard", "high"
	  ], mediaValueKeywords = keySet(mediaValueKeywords_);

	  var propertyKeywords_ = [
	    "align-content", "align-items", "align-self", "alignment-adjust",
	    "alignment-baseline", "all", "anchor-point", "animation", "animation-delay",
	    "animation-direction", "animation-duration", "animation-fill-mode",
	    "animation-iteration-count", "animation-name", "animation-play-state",
	    "animation-timing-function", "appearance", "azimuth", "backdrop-filter",
	    "backface-visibility", "background", "background-attachment",
	    "background-blend-mode", "background-clip", "background-color",
	    "background-image", "background-origin", "background-position",
	    "background-position-x", "background-position-y", "background-repeat",
	    "background-size", "baseline-shift", "binding", "bleed", "block-size",
	    "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target",
	    "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius",
	    "border-bottom-right-radius", "border-bottom-style", "border-bottom-width",
	    "border-collapse", "border-color", "border-image", "border-image-outset",
	    "border-image-repeat", "border-image-slice", "border-image-source",
	    "border-image-width", "border-left", "border-left-color", "border-left-style",
	    "border-left-width", "border-radius", "border-right", "border-right-color",
	    "border-right-style", "border-right-width", "border-spacing", "border-style",
	    "border-top", "border-top-color", "border-top-left-radius",
	    "border-top-right-radius", "border-top-style", "border-top-width",
	    "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing",
	    "break-after", "break-before", "break-inside", "caption-side", "caret-color",
	    "clear", "clip", "color", "color-profile", "column-count", "column-fill",
	    "column-gap", "column-rule", "column-rule-color", "column-rule-style",
	    "column-rule-width", "column-span", "column-width", "columns", "contain",
	    "content", "counter-increment", "counter-reset", "crop", "cue", "cue-after",
	    "cue-before", "cursor", "direction", "display", "dominant-baseline",
	    "drop-initial-after-adjust", "drop-initial-after-align",
	    "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size",
	    "drop-initial-value", "elevation", "empty-cells", "fit", "fit-content", "fit-position",
	    "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow",
	    "flex-shrink", "flex-wrap", "float", "float-offset", "flow-from", "flow-into",
	    "font", "font-family", "font-feature-settings", "font-kerning",
	    "font-language-override", "font-optical-sizing", "font-size",
	    "font-size-adjust", "font-stretch", "font-style", "font-synthesis",
	    "font-variant", "font-variant-alternates", "font-variant-caps",
	    "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric",
	    "font-variant-position", "font-variation-settings", "font-weight", "gap",
	    "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "grid-auto-rows",
	    "grid-column", "grid-column-end", "grid-column-gap", "grid-column-start",
	    "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-row-start",
	    "grid-template", "grid-template-areas", "grid-template-columns",
	    "grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon",
	    "image-orientation", "image-rendering", "image-resolution", "inline-box-align",
	    "inset", "inset-block", "inset-block-end", "inset-block-start", "inset-inline",
	    "inset-inline-end", "inset-inline-start", "isolation", "justify-content",
	    "justify-items", "justify-self", "left", "letter-spacing", "line-break",
	    "line-height", "line-height-step", "line-stacking", "line-stacking-ruby",
	    "line-stacking-shift", "line-stacking-strategy", "list-style",
	    "list-style-image", "list-style-position", "list-style-type", "margin",
	    "margin-bottom", "margin-left", "margin-right", "margin-top", "marks",
	    "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed",
	    "marquee-style", "mask-clip", "mask-composite", "mask-image", "mask-mode",
	    "mask-origin", "mask-position", "mask-repeat", "mask-size","mask-type",
	    "max-block-size", "max-height", "max-inline-size",
	    "max-width", "min-block-size", "min-height", "min-inline-size", "min-width",
	    "mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right",
	    "nav-up", "object-fit", "object-position", "offset", "offset-anchor",
	    "offset-distance", "offset-path", "offset-position", "offset-rotate",
	    "opacity", "order", "orphans", "outline", "outline-color", "outline-offset",
	    "outline-style", "outline-width", "overflow", "overflow-style",
	    "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom",
	    "padding-left", "padding-right", "padding-top", "page", "page-break-after",
	    "page-break-before", "page-break-inside", "page-policy", "pause",
	    "pause-after", "pause-before", "perspective", "perspective-origin", "pitch",
	    "pitch-range", "place-content", "place-items", "place-self", "play-during",
	    "position", "presentation-level", "punctuation-trim", "quotes",
	    "region-break-after", "region-break-before", "region-break-inside",
	    "region-fragment", "rendering-intent", "resize", "rest", "rest-after",
	    "rest-before", "richness", "right", "rotate", "rotation", "rotation-point",
	    "row-gap", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span",
	    "scale", "scroll-behavior", "scroll-margin", "scroll-margin-block",
	    "scroll-margin-block-end", "scroll-margin-block-start", "scroll-margin-bottom",
	    "scroll-margin-inline", "scroll-margin-inline-end",
	    "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right",
	    "scroll-margin-top", "scroll-padding", "scroll-padding-block",
	    "scroll-padding-block-end", "scroll-padding-block-start",
	    "scroll-padding-bottom", "scroll-padding-inline", "scroll-padding-inline-end",
	    "scroll-padding-inline-start", "scroll-padding-left", "scroll-padding-right",
	    "scroll-padding-top", "scroll-snap-align", "scroll-snap-type",
	    "shape-image-threshold", "shape-inside", "shape-margin", "shape-outside",
	    "size", "speak", "speak-as", "speak-header", "speak-numeral",
	    "speak-punctuation", "speech-rate", "stress", "string-set", "tab-size",
	    "table-layout", "target", "target-name", "target-new", "target-position",
	    "text-align", "text-align-last", "text-combine-upright", "text-decoration",
	    "text-decoration-color", "text-decoration-line", "text-decoration-skip",
	    "text-decoration-skip-ink", "text-decoration-style", "text-emphasis",
	    "text-emphasis-color", "text-emphasis-position", "text-emphasis-style",
	    "text-height", "text-indent", "text-justify", "text-orientation",
	    "text-outline", "text-overflow", "text-rendering", "text-shadow",
	    "text-size-adjust", "text-space-collapse", "text-transform",
	    "text-underline-position", "text-wrap", "top", "touch-action", "transform", "transform-origin",
	    "transform-style", "transition", "transition-delay", "transition-duration",
	    "transition-property", "transition-timing-function", "translate",
	    "unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance",
	    "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate",
	    "voice-stress", "voice-volume", "volume", "white-space", "widows", "width",
	    "will-change", "word-break", "word-spacing", "word-wrap", "writing-mode", "z-index",
	    // SVG-specific
	    "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
	    "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
	    "color-interpolation", "color-interpolation-filters",
	    "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
	    "marker", "marker-end", "marker-mid", "marker-start", "paint-order", "shape-rendering", "stroke",
	    "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
	    "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
	    "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
	    "glyph-orientation-vertical", "text-anchor", "writing-mode",
	  ], propertyKeywords = keySet(propertyKeywords_);

	  var nonStandardPropertyKeywords_ = [
	    "accent-color", "aspect-ratio", "border-block", "border-block-color", "border-block-end",
	    "border-block-end-color", "border-block-end-style", "border-block-end-width",
	    "border-block-start", "border-block-start-color", "border-block-start-style",
	    "border-block-start-width", "border-block-style", "border-block-width",
	    "border-inline", "border-inline-color", "border-inline-end",
	    "border-inline-end-color", "border-inline-end-style",
	    "border-inline-end-width", "border-inline-start", "border-inline-start-color",
	    "border-inline-start-style", "border-inline-start-width",
	    "border-inline-style", "border-inline-width", "content-visibility", "margin-block",
	    "margin-block-end", "margin-block-start", "margin-inline", "margin-inline-end",
	    "margin-inline-start", "overflow-anchor", "overscroll-behavior", "padding-block", "padding-block-end",
	    "padding-block-start", "padding-inline", "padding-inline-end",
	    "padding-inline-start", "scroll-snap-stop", "scrollbar-3d-light-color",
	    "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
	    "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
	    "scrollbar-track-color", "searchfield-cancel-button", "searchfield-decoration",
	    "searchfield-results-button", "searchfield-results-decoration", "shape-inside", "zoom"
	  ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);

	  var fontProperties_ = [
	    "font-display", "font-family", "src", "unicode-range", "font-variant",
	     "font-feature-settings", "font-stretch", "font-weight", "font-style"
	  ], fontProperties = keySet(fontProperties_);

	  var counterDescriptors_ = [
	    "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
	    "speak-as", "suffix", "symbols", "system"
	  ], counterDescriptors = keySet(counterDescriptors_);

	  var colorKeywords_ = [
	    "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
	    "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
	    "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
	    "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
	    "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen",
	    "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
	    "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet",
	    "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick",
	    "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
	    "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
	    "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
	    "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
	    "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink",
	    "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey",
	    "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
	    "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
	    "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
	    "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
	    "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
	    "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
	    "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
	    "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
	    "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
	    "slateblue", "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan",
	    "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
	    "whitesmoke", "yellow", "yellowgreen"
	  ], colorKeywords = keySet(colorKeywords_);

	  var valueKeywords_ = [
	    "above", "absolute", "activeborder", "additive", "activecaption", "afar",
	    "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
	    "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
	    "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
	    "avoid-region", "axis-pan", "background", "backwards", "baseline", "below", "bidi-override", "binary",
	    "bengali", "blink", "block", "block-axis", "blur", "bold", "bolder", "border", "border-box",
	    "both", "bottom", "break", "break-all", "break-word", "brightness", "bullets", "button",
	    "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
	    "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
	    "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
	    "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
	    "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
	    "compact", "condensed", "conic-gradient", "contain", "content", "contents",
	    "content-box", "context-menu", "continuous", "contrast", "copy", "counter", "counters", "cover", "crop",
	    "cross", "crosshair", "cubic-bezier", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
	    "decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
	    "destination-in", "destination-out", "destination-over", "devanagari", "difference",
	    "disc", "discard", "disclosure-closed", "disclosure-open", "document",
	    "dot-dash", "dot-dot-dash",
	    "dotted", "double", "down", "drop-shadow", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
	    "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
	    "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
	    "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
	    "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
	    "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
	    "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
	    "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
	    "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
	    "extra-expanded", "fantasy", "fast", "fill", "fill-box", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
	    "forwards", "from", "geometricPrecision", "georgian", "grayscale", "graytext", "grid", "groove",
	    "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
	    "help", "hidden", "hide", "higher", "highlight", "highlighttext",
	    "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "hue-rotate", "icon", "ignore",
	    "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
	    "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
	    "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
	    "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
	    "katakana", "katakana-iroha", "keep-all", "khmer",
	    "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
	    "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
	    "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
	    "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
	    "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
	    "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "manipulation", "match", "matrix", "matrix3d",
	    "media-play-button", "media-slider", "media-sliderthumb",
	    "media-volume-slider", "media-volume-sliderthumb", "medium",
	    "menu", "menulist", "menulist-button",
	    "menutext", "message-box", "middle", "min-intrinsic",
	    "mix", "mongolian", "monospace", "move", "multiple", "multiple_mask_images", "multiply", "myanmar", "n-resize",
	    "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
	    "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
	    "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
	    "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
	    "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
	    "painted", "page", "paused", "persian", "perspective", "pinch-zoom", "plus-darker", "plus-lighter",
	    "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
	    "progress", "push-button", "radial-gradient", "radio", "read-only",
	    "read-write", "read-write-plaintext-only", "rectangle", "region",
	    "relative", "repeat", "repeating-linear-gradient", "repeating-radial-gradient",
	    "repeating-conic-gradient", "repeat-x", "repeat-y", "reset", "reverse",
	    "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
	    "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
	    "s-resize", "sans-serif", "saturate", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
	    "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
	    "searchfield-cancel-button", "searchfield-decoration",
	    "searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end",
	    "semi-condensed", "semi-expanded", "separate", "sepia", "serif", "show", "sidama",
	    "simp-chinese-formal", "simp-chinese-informal", "single",
	    "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
	    "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
	    "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
	    "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
	    "square-button", "start", "static", "status-bar", "stretch", "stroke", "stroke-box", "sub",
	    "subpixel-antialiased", "svg_masks", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
	    "table-caption", "table-cell", "table-column", "table-column-group",
	    "table-footer-group", "table-header-group", "table-row", "table-row-group",
	    "tamil",
	    "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
	    "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
	    "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
	    "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
	    "trad-chinese-formal", "trad-chinese-informal", "transform",
	    "translate", "translate3d", "translateX", "translateY", "translateZ",
	    "transparent", "ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up",
	    "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
	    "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
	    "var", "vertical", "vertical-text", "view-box", "visible", "visibleFill", "visiblePainted",
	    "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
	    "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
	    "xx-large", "xx-small"
	  ], valueKeywords = keySet(valueKeywords_);

	  var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
	    .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
	    .concat(valueKeywords_);
	  CodeMirror.registerHelper("hintWords", "css", allWords);

	  function tokenCComment(stream, state) {
	    var maybeEnd = false, ch;
	    while ((ch = stream.next()) != null) {
	      if (maybeEnd && ch == "/") {
	        state.tokenize = null;
	        break;
	      }
	      maybeEnd = (ch == "*");
	    }
	    return ["comment", "comment"];
	  }

	  CodeMirror.defineMIME("text/css", {
	    documentTypes: documentTypes,
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    mediaValueKeywords: mediaValueKeywords,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    fontProperties: fontProperties,
	    counterDescriptors: counterDescriptors,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (!stream.eat("*")) return false;
	        state.tokenize = tokenCComment;
	        return tokenCComment(stream, state);
	      }
	    },
	    name: "css"
	  });

	  CodeMirror.defineMIME("text/x-scss", {
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    mediaValueKeywords: mediaValueKeywords,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    fontProperties: fontProperties,
	    allowNested: true,
	    lineComment: "//",
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (stream.eat("/")) {
	          stream.skipToEnd();
	          return ["comment", "comment"];
	        } else if (stream.eat("*")) {
	          state.tokenize = tokenCComment;
	          return tokenCComment(stream, state);
	        } else {
	          return ["operator", "operator"];
	        }
	      },
	      ":": function(stream) {
	        if (stream.match(/^\s*\{/, false))
	          return [null, null]
	        return false;
	      },
	      "$": function(stream) {
	        stream.match(/^[\w-]+/);
	        if (stream.match(/^\s*:/, false))
	          return ["variable-2", "variable-definition"];
	        return ["variable-2", "variable"];
	      },
	      "#": function(stream) {
	        if (!stream.eat("{")) return false;
	        return [null, "interpolation"];
	      }
	    },
	    name: "css",
	    helperType: "scss"
	  });

	  CodeMirror.defineMIME("text/x-less", {
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    mediaValueKeywords: mediaValueKeywords,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    fontProperties: fontProperties,
	    allowNested: true,
	    lineComment: "//",
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (stream.eat("/")) {
	          stream.skipToEnd();
	          return ["comment", "comment"];
	        } else if (stream.eat("*")) {
	          state.tokenize = tokenCComment;
	          return tokenCComment(stream, state);
	        } else {
	          return ["operator", "operator"];
	        }
	      },
	      "@": function(stream) {
	        if (stream.eat("{")) return [null, "interpolation"];
	        if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i, false)) return false;
	        stream.eatWhile(/[\w\\\-]/);
	        if (stream.match(/^\s*:/, false))
	          return ["variable-2", "variable-definition"];
	        return ["variable-2", "variable"];
	      },
	      "&": function() {
	        return ["atom", "atom"];
	      }
	    },
	    name: "css",
	    helperType: "less"
	  });

	  CodeMirror.defineMIME("text/x-gss", {
	    documentTypes: documentTypes,
	    mediaTypes: mediaTypes,
	    mediaFeatures: mediaFeatures,
	    propertyKeywords: propertyKeywords,
	    nonStandardPropertyKeywords: nonStandardPropertyKeywords,
	    fontProperties: fontProperties,
	    counterDescriptors: counterDescriptors,
	    colorKeywords: colorKeywords,
	    valueKeywords: valueKeywords,
	    supportsAtComponent: true,
	    tokenHooks: {
	      "/": function(stream, state) {
	        if (!stream.eat("*")) return false;
	        state.tokenize = tokenCComment;
	        return tokenCComment(stream, state);
	      }
	    },
	    name: "css",
	    helperType: "gss"
	  });

	}); 
} ());

var cssExports = css.exports;
/* Injected with object hook! */

var xml = {exports: {}};/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	(function(mod) {
	  mod(codemirrorExports);
	})(function(CodeMirror) {

	var htmlConfig = {
	  autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
	                    'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
	                    'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
	                    'track': true, 'wbr': true, 'menuitem': true},
	  implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
	                     'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
	                     'th': true, 'tr': true},
	  contextGrabbers: {
	    'dd': {'dd': true, 'dt': true},
	    'dt': {'dd': true, 'dt': true},
	    'li': {'li': true},
	    'option': {'option': true, 'optgroup': true},
	    'optgroup': {'optgroup': true},
	    'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
	          'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
	          'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
	          'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
	          'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
	    'rp': {'rp': true, 'rt': true},
	    'rt': {'rp': true, 'rt': true},
	    'tbody': {'tbody': true, 'tfoot': true},
	    'td': {'td': true, 'th': true},
	    'tfoot': {'tbody': true},
	    'th': {'td': true, 'th': true},
	    'thead': {'tbody': true, 'tfoot': true},
	    'tr': {'tr': true}
	  },
	  doNotIndent: {"pre": true},
	  allowUnquoted: true,
	  allowMissing: true,
	  caseFold: true
	};

	var xmlConfig = {
	  autoSelfClosers: {},
	  implicitlyClosed: {},
	  contextGrabbers: {},
	  doNotIndent: {},
	  allowUnquoted: false,
	  allowMissing: false,
	  allowMissingTagName: false,
	  caseFold: false
	};

	CodeMirror.defineMode("xml", function(editorConf, config_) {
	  var indentUnit = editorConf.indentUnit;
	  var config = {};
	  var defaults = config_.htmlMode ? htmlConfig : xmlConfig;
	  for (var prop in defaults) config[prop] = defaults[prop];
	  for (var prop in config_) config[prop] = config_[prop];

	  // Return variables for tokenizers
	  var type, setStyle;

	  function inText(stream, state) {
	    function chain(parser) {
	      state.tokenize = parser;
	      return parser(stream, state);
	    }

	    var ch = stream.next();
	    if (ch == "<") {
	      if (stream.eat("!")) {
	        if (stream.eat("[")) {
	          if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
	          else return null;
	        } else if (stream.match("--")) {
	          return chain(inBlock("comment", "-->"));
	        } else if (stream.match("DOCTYPE", true, true)) {
	          stream.eatWhile(/[\w\._\-]/);
	          return chain(doctype(1));
	        } else {
	          return null;
	        }
	      } else if (stream.eat("?")) {
	        stream.eatWhile(/[\w\._\-]/);
	        state.tokenize = inBlock("meta", "?>");
	        return "meta";
	      } else {
	        type = stream.eat("/") ? "closeTag" : "openTag";
	        state.tokenize = inTag;
	        return "tag bracket";
	      }
	    } else if (ch == "&") {
	      var ok;
	      if (stream.eat("#")) {
	        if (stream.eat("x")) {
	          ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
	        } else {
	          ok = stream.eatWhile(/[\d]/) && stream.eat(";");
	        }
	      } else {
	        ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
	      }
	      return ok ? "atom" : "error";
	    } else {
	      stream.eatWhile(/[^&<]/);
	      return null;
	    }
	  }
	  inText.isInText = true;

	  function inTag(stream, state) {
	    var ch = stream.next();
	    if (ch == ">" || (ch == "/" && stream.eat(">"))) {
	      state.tokenize = inText;
	      type = ch == ">" ? "endTag" : "selfcloseTag";
	      return "tag bracket";
	    } else if (ch == "=") {
	      type = "equals";
	      return null;
	    } else if (ch == "<") {
	      state.tokenize = inText;
	      state.state = baseState;
	      state.tagName = state.tagStart = null;
	      var next = state.tokenize(stream, state);
	      return next ? next + " tag error" : "tag error";
	    } else if (/[\'\"]/.test(ch)) {
	      state.tokenize = inAttribute(ch);
	      state.stringStartCol = stream.column();
	      return state.tokenize(stream, state);
	    } else {
	      stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
	      return "word";
	    }
	  }

	  function inAttribute(quote) {
	    var closure = function(stream, state) {
	      while (!stream.eol()) {
	        if (stream.next() == quote) {
	          state.tokenize = inTag;
	          break;
	        }
	      }
	      return "string";
	    };
	    closure.isInAttribute = true;
	    return closure;
	  }

	  function inBlock(style, terminator) {
	    return function(stream, state) {
	      while (!stream.eol()) {
	        if (stream.match(terminator)) {
	          state.tokenize = inText;
	          break;
	        }
	        stream.next();
	      }
	      return style;
	    }
	  }

	  function doctype(depth) {
	    return function(stream, state) {
	      var ch;
	      while ((ch = stream.next()) != null) {
	        if (ch == "<") {
	          state.tokenize = doctype(depth + 1);
	          return state.tokenize(stream, state);
	        } else if (ch == ">") {
	          if (depth == 1) {
	            state.tokenize = inText;
	            break;
	          } else {
	            state.tokenize = doctype(depth - 1);
	            return state.tokenize(stream, state);
	          }
	        }
	      }
	      return "meta";
	    };
	  }

	  function lower(tagName) {
	    return tagName && tagName.toLowerCase();
	  }

	  function Context(state, tagName, startOfLine) {
	    this.prev = state.context;
	    this.tagName = tagName || "";
	    this.indent = state.indented;
	    this.startOfLine = startOfLine;
	    if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
	      this.noIndent = true;
	  }
	  function popContext(state) {
	    if (state.context) state.context = state.context.prev;
	  }
	  function maybePopContext(state, nextTagName) {
	    var parentTagName;
	    while (true) {
	      if (!state.context) {
	        return;
	      }
	      parentTagName = state.context.tagName;
	      if (!config.contextGrabbers.hasOwnProperty(lower(parentTagName)) ||
	          !config.contextGrabbers[lower(parentTagName)].hasOwnProperty(lower(nextTagName))) {
	        return;
	      }
	      popContext(state);
	    }
	  }

	  function baseState(type, stream, state) {
	    if (type == "openTag") {
	      state.tagStart = stream.column();
	      return tagNameState;
	    } else if (type == "closeTag") {
	      return closeTagNameState;
	    } else {
	      return baseState;
	    }
	  }
	  function tagNameState(type, stream, state) {
	    if (type == "word") {
	      state.tagName = stream.current();
	      setStyle = "tag";
	      return attrState;
	    } else if (config.allowMissingTagName && type == "endTag") {
	      setStyle = "tag bracket";
	      return attrState(type, stream, state);
	    } else {
	      setStyle = "error";
	      return tagNameState;
	    }
	  }
	  function closeTagNameState(type, stream, state) {
	    if (type == "word") {
	      var tagName = stream.current();
	      if (state.context && state.context.tagName != tagName &&
	          config.implicitlyClosed.hasOwnProperty(lower(state.context.tagName)))
	        popContext(state);
	      if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
	        setStyle = "tag";
	        return closeState;
	      } else {
	        setStyle = "tag error";
	        return closeStateErr;
	      }
	    } else if (config.allowMissingTagName && type == "endTag") {
	      setStyle = "tag bracket";
	      return closeState(type, stream, state);
	    } else {
	      setStyle = "error";
	      return closeStateErr;
	    }
	  }

	  function closeState(type, _stream, state) {
	    if (type != "endTag") {
	      setStyle = "error";
	      return closeState;
	    }
	    popContext(state);
	    return baseState;
	  }
	  function closeStateErr(type, stream, state) {
	    setStyle = "error";
	    return closeState(type, stream, state);
	  }

	  function attrState(type, _stream, state) {
	    if (type == "word") {
	      setStyle = "attribute";
	      return attrEqState;
	    } else if (type == "endTag" || type == "selfcloseTag") {
	      var tagName = state.tagName, tagStart = state.tagStart;
	      state.tagName = state.tagStart = null;
	      if (type == "selfcloseTag" ||
	          config.autoSelfClosers.hasOwnProperty(lower(tagName))) {
	        maybePopContext(state, tagName);
	      } else {
	        maybePopContext(state, tagName);
	        state.context = new Context(state, tagName, tagStart == state.indented);
	      }
	      return baseState;
	    }
	    setStyle = "error";
	    return attrState;
	  }
	  function attrEqState(type, stream, state) {
	    if (type == "equals") return attrValueState;
	    if (!config.allowMissing) setStyle = "error";
	    return attrState(type, stream, state);
	  }
	  function attrValueState(type, stream, state) {
	    if (type == "string") return attrContinuedState;
	    if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
	    setStyle = "error";
	    return attrState(type, stream, state);
	  }
	  function attrContinuedState(type, stream, state) {
	    if (type == "string") return attrContinuedState;
	    return attrState(type, stream, state);
	  }

	  return {
	    startState: function(baseIndent) {
	      var state = {tokenize: inText,
	                   state: baseState,
	                   indented: baseIndent || 0,
	                   tagName: null, tagStart: null,
	                   context: null};
	      if (baseIndent != null) state.baseIndent = baseIndent;
	      return state
	    },

	    token: function(stream, state) {
	      if (!state.tagName && stream.sol())
	        state.indented = stream.indentation();

	      if (stream.eatSpace()) return null;
	      type = null;
	      var style = state.tokenize(stream, state);
	      if ((style || type) && style != "comment") {
	        setStyle = null;
	        state.state = state.state(type || style, stream, state);
	        if (setStyle)
	          style = setStyle == "error" ? style + " error" : setStyle;
	      }
	      return style;
	    },

	    indent: function(state, textAfter, fullLine) {
	      var context = state.context;
	      // Indent multi-line strings (e.g. css).
	      if (state.tokenize.isInAttribute) {
	        if (state.tagStart == state.indented)
	          return state.stringStartCol + 1;
	        else
	          return state.indented + indentUnit;
	      }
	      if (context && context.noIndent) return CodeMirror.Pass;
	      if (state.tokenize != inTag && state.tokenize != inText)
	        return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
	      // Indent the starts of attribute names.
	      if (state.tagName) {
	        if (config.multilineTagIndentPastTag !== false)
	          return state.tagStart + state.tagName.length + 2;
	        else
	          return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
	      }
	      if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
	      var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
	      if (tagAfter && tagAfter[1]) { // Closing tag spotted
	        while (context) {
	          if (context.tagName == tagAfter[2]) {
	            context = context.prev;
	            break;
	          } else if (config.implicitlyClosed.hasOwnProperty(lower(context.tagName))) {
	            context = context.prev;
	          } else {
	            break;
	          }
	        }
	      } else if (tagAfter) { // Opening tag spotted
	        while (context) {
	          var grabbers = config.contextGrabbers[lower(context.tagName)];
	          if (grabbers && grabbers.hasOwnProperty(lower(tagAfter[2])))
	            context = context.prev;
	          else
	            break;
	        }
	      }
	      while (context && context.prev && !context.startOfLine)
	        context = context.prev;
	      if (context) return context.indent + indentUnit;
	      else return state.baseIndent || 0;
	    },

	    electricInput: /<\/[\s\w:]+>$/,
	    blockCommentStart: "<!--",
	    blockCommentEnd: "-->",

	    configuration: config.htmlMode ? "html" : "xml",
	    helperType: config.htmlMode ? "html" : "xml",

	    skipAttribute: function(state) {
	      if (state.state == attrValueState)
	        state.state = attrState;
	    },

	    xmlCurrentTag: function(state) {
	      return state.tagName ? {name: state.tagName, close: state.type == "closeTag"} : null
	    },

	    xmlCurrentContext: function(state) {
	      var context = [];
	      for (var cx = state.context; cx; cx = cx.prev)
	        context.push(cx.tagName);
	      return context.reverse()
	    }
	  };
	});

	CodeMirror.defineMIME("text/xml", "xml");
	CodeMirror.defineMIME("application/xml", "xml");
	if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
	  CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});

	}); 
} ());

var xmlExports = xml.exports;
/* Injected with object hook! */

var meta = {exports: {}};/* Injected with object hook! */

var hasRequiredMeta;

function requireMeta () {
	if (hasRequiredMeta) return meta.exports;
	hasRequiredMeta = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports);
		})(function(CodeMirror) {

		  CodeMirror.modeInfo = [
		    {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
		    {name: "PGP", mimes: ["application/pgp", "application/pgp-encrypted", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["asc", "pgp", "sig"]},
		    {name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]},
		    {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
		    {name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]},
		    {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h", "ino"]},
		    {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
		    {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy", "cbl"]},
		    {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp", "cs"]},
		    {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj", "cljc", "cljx"]},
		    {name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]},
		    {name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]},
		    {name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists\.txt$/},
		    {name: "CoffeeScript", mimes: ["application/vnd.coffeescript", "text/coffeescript", "text/x-coffeescript"], mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
		    {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
		    {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
		    {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
		    {name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]},
		    {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
		    {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
		    {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
		    {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
		    {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
		    {name: "Django", mime: "text/x-django", mode: "django"},
		    {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
		    {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
		    {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
		    {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
		    {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
		    {name: "edn", mime: "application/edn", mode: "clojure", ext: ["edn"]},
		    {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
		    {name: "Elm", mime: "text/x-elm", mode: "elm", ext: ["elm"]},
		    {name: "Embedded JavaScript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
		    {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
		    {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
		    {name: "Esper", mime: "text/x-esper", mode: "sql"},
		    {name: "Factor", mime: "text/x-factor", mode: "factor", ext: ["factor"]},
		    {name: "FCL", mime: "text/x-fcl", mode: "fcl"},
		    {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
		    {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90", "f95"]},
		    {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
		    {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
		    {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
		    {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history)\.md$/i},
		    {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
		    {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy", "gradle"], file: /^Jenkinsfile$/},
		    {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
		    {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
		    {name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]},
		    {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
		    {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
		    {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
		    {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm", "handlebars", "hbs"], alias: ["xhtml"]},
		    {name: "HTTP", mime: "message/http", mode: "http"},
		    {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
		    {name: "Pug", mime: "text/x-pug", mode: "pug", ext: ["jade", "pug"], alias: ["jade"]},
		    {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
		    {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
		    {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
		     mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
		    {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
		    {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
		    {name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]},
		    {name: "Jinja2", mime: "text/jinja2", mode: "jinja2", ext: ["j2", "jinja", "jinja2"]},
		    {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"], alias: ["jl"]},
		    {name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
		    {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
		    {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
		    {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
		    {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
		    {name: "mIRC", mime: "text/mirc", mode: "mirc"},
		    {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
		    {name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb", "wl", "wls"]},
		    {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
		    {name: "MUMPS", mime: "text/x-mumps", mode: "mumps", ext: ["mps"]},
		    {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
		    {name: "mbox", mime: "application/mbox", mode: "mbox", ext: ["mbox"]},
		    {name: "MySQL", mime: "text/x-mysql", mode: "sql"},
		    {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
		    {name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
		    {name: "NTriples", mimes: ["application/n-triples", "application/n-quads", "text/n-triples"],
		     mode: "ntriples", ext: ["nt", "nq"]},
		    {name: "Objective-C", mime: "text/x-objectivec", mode: "clike", ext: ["m"], alias: ["objective-c", "objc"]},
		    {name: "Objective-C++", mime: "text/x-objectivec++", mode: "clike", ext: ["mm"], alias: ["objective-c++", "objc++"]},
		    {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
		    {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
		    {name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
		    {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
		    {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
		    {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
		    {name: "PHP", mimes: ["text/x-php", "application/x-httpd-php", "application/x-httpd-php-open"], mode: "php", ext: ["php", "php3", "php4", "php5", "php7", "phtml"]},
		    {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
		    {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
		    {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
		    {name: "PostgreSQL", mime: "text/x-pgsql", mode: "sql"},
		    {name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]},
		    {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
		    {name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]},
		    {name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/},
		    {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
		    {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
		    {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r", "R"], alias: ["rscript"]},
		    {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
		    {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
		    {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
		    {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
		    {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
		    {name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]},
		    {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
		    {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
		    {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
		    {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
		    {name: "Shell", mimes: ["text/x-sh", "application/x-sh"], mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
		    {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
		    {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
		    {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
		    {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
		    {name: "Solr", mime: "text/x-solr", mode: "solr"},
		    {name: "SML", mime: "text/x-sml", mode: "mllike", ext: ["sml", "sig", "fun", "smackspec"]},
		    {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
		    {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
		    {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
		    {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
		    {name: "SQLite", mime: "text/x-sqlite", mode: "sql"},
		    {name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
		    {name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]},
		    {name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
		    {name: "sTeX", mime: "text/x-stex", mode: "stex"},
		    {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx", "tex"], alias: ["tex"]},
		    {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v", "sv", "svh"]},
		    {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
		    {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
		    {name: "TiddlyWiki", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
		    {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
		    {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
		    {name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
		    {name: "troff", mime: "text/troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]},
		    {name: "TTCN", mime: "text/x-ttcn", mode: "ttcn", ext: ["ttcn", "ttcn3", "ttcnpp"]},
		    {name: "TTCN_CFG", mime: "text/x-ttcn-cfg", mode: "ttcn-cfg", ext: ["cfg"]},
		    {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
		    {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
		    {name: "TypeScript-JSX", mime: "text/typescript-jsx", mode: "jsx", ext: ["tsx"], alias: ["tsx"]},
		    {name: "Twig", mime: "text/x-twig", mode: "twig"},
		    {name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]},
		    {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
		    {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
		    {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
		    {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
		    {name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
		    {name: "Vue.js Component", mimes: ["script/x-vue", "text/x-vue"], mode: "vue", ext: ["vue"]},
		    {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd", "svg"], alias: ["rss", "wsdl", "xsd"]},
		    {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
		    {name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]},
		    {name: "YAML", mimes: ["text/x-yaml", "text/yaml"], mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
		    {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
		    {name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
		    {name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]},
		    {name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]},
		    {name: "WebAssembly", mime: "text/webassembly", mode: "wast", ext: ["wat", "wast"]},
		  ];
		  // Ensure all modes have a mime property for backwards compatibility
		  for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
		    var info = CodeMirror.modeInfo[i];
		    if (info.mimes) info.mime = info.mimes[0];
		  }

		  CodeMirror.findModeByMIME = function(mime) {
		    mime = mime.toLowerCase();
		    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
		      var info = CodeMirror.modeInfo[i];
		      if (info.mime == mime) return info;
		      if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
		        if (info.mimes[j] == mime) return info;
		    }
		    if (/\+xml$/.test(mime)) return CodeMirror.findModeByMIME("application/xml")
		    if (/\+json$/.test(mime)) return CodeMirror.findModeByMIME("application/json")
		  };

		  CodeMirror.findModeByExtension = function(ext) {
		    ext = ext.toLowerCase();
		    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
		      var info = CodeMirror.modeInfo[i];
		      if (info.ext) for (var j = 0; j < info.ext.length; j++)
		        if (info.ext[j] == ext) return info;
		    }
		  };

		  CodeMirror.findModeByFileName = function(filename) {
		    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
		      var info = CodeMirror.modeInfo[i];
		      if (info.file && info.file.test(filename)) return info;
		    }
		    var dot = filename.lastIndexOf(".");
		    var ext = dot > -1 && filename.substring(dot + 1, filename.length);
		    if (ext) return CodeMirror.findModeByExtension(ext);
		  };

		  CodeMirror.findModeByName = function(name) {
		    name = name.toLowerCase();
		    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
		      var info = CodeMirror.modeInfo[i];
		      if (info.name.toLowerCase() == name) return info;
		      if (info.alias) for (var j = 0; j < info.alias.length; j++)
		        if (info.alias[j].toLowerCase() == name) return info;
		    }
		  };
		}); 
	} ());
	return meta.exports;
}
/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	(function(mod) {
	  mod(codemirrorExports, xmlExports, requireMeta());
	})(function(CodeMirror) {

	CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {

	  var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
	  var htmlModeMissing = htmlMode.name == "null";

	  function getMode(name) {
	    if (CodeMirror.findModeByName) {
	      var found = CodeMirror.findModeByName(name);
	      if (found) name = found.mime || found.mimes[0];
	    }
	    var mode = CodeMirror.getMode(cmCfg, name);
	    return mode.name == "null" ? null : mode;
	  }

	  // Should characters that affect highlighting be highlighted separate?
	  // Does not include characters that will be output (such as `1.` and `-` for lists)
	  if (modeCfg.highlightFormatting === undefined)
	    modeCfg.highlightFormatting = false;

	  // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
	  // Excess `>` will emit `error` token.
	  if (modeCfg.maxBlockquoteDepth === undefined)
	    modeCfg.maxBlockquoteDepth = 0;

	  // Turn on task lists? ("- [ ] " and "- [x] ")
	  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;

	  // Turn on strikethrough syntax
	  if (modeCfg.strikethrough === undefined)
	    modeCfg.strikethrough = false;

	  if (modeCfg.emoji === undefined)
	    modeCfg.emoji = false;

	  if (modeCfg.fencedCodeBlockHighlighting === undefined)
	    modeCfg.fencedCodeBlockHighlighting = true;

	  if (modeCfg.fencedCodeBlockDefaultMode === undefined)
	    modeCfg.fencedCodeBlockDefaultMode = 'text/plain';

	  if (modeCfg.xml === undefined)
	    modeCfg.xml = true;

	  // Allow token types to be overridden by user-provided token types.
	  if (modeCfg.tokenTypeOverrides === undefined)
	    modeCfg.tokenTypeOverrides = {};

	  var tokenTypes = {
	    header: "header",
	    code: "comment",
	    quote: "quote",
	    list1: "variable-2",
	    list2: "variable-3",
	    list3: "keyword",
	    hr: "hr",
	    image: "image",
	    imageAltText: "image-alt-text",
	    imageMarker: "image-marker",
	    formatting: "formatting",
	    linkInline: "link",
	    linkEmail: "link",
	    linkText: "link",
	    linkHref: "string",
	    em: "em",
	    strong: "strong",
	    strikethrough: "strikethrough",
	    emoji: "builtin"
	  };

	  for (var tokenType in tokenTypes) {
	    if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
	      tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
	    }
	  }

	  var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
	  ,   listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/
	  ,   taskListRE = /^\[(x| )\](?=\s)/i // Must follow listRE
	  ,   atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
	  ,   setextHeaderRE = /^ {0,3}(?:\={1,}|-{2,})\s*$/
	  ,   textRE = /^[^#!\[\]*_\\<>` "'(~:]+/
	  ,   fencedCodeRE = /^(~~~+|```+)[ \t]*([\w\/+#-]*)[^\n`]*$/
	  ,   linkDefRE = /^\s*\[[^\]]+?\]:.*$/ // naive link-definition
	  ,   punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/
	  ,   expandedTab = "    "; // CommonMark specifies tab as 4 spaces

	  function switchInline(stream, state, f) {
	    state.f = state.inline = f;
	    return f(stream, state);
	  }

	  function switchBlock(stream, state, f) {
	    state.f = state.block = f;
	    return f(stream, state);
	  }

	  function lineIsEmpty(line) {
	    return !line || !/\S/.test(line.string)
	  }

	  // Blocks

	  function blankLine(state) {
	    // Reset linkTitle state
	    state.linkTitle = false;
	    state.linkHref = false;
	    state.linkText = false;
	    // Reset EM state
	    state.em = false;
	    // Reset STRONG state
	    state.strong = false;
	    // Reset strikethrough state
	    state.strikethrough = false;
	    // Reset state.quote
	    state.quote = 0;
	    // Reset state.indentedCode
	    state.indentedCode = false;
	    if (state.f == htmlBlock) {
	      var exit = htmlModeMissing;
	      if (!exit) {
	        var inner = CodeMirror.innerMode(htmlMode, state.htmlState);
	        exit = inner.mode.name == "xml" && inner.state.tagStart === null &&
	          (!inner.state.context && inner.state.tokenize.isInText);
	      }
	      if (exit) {
	        state.f = inlineNormal;
	        state.block = blockNormal;
	        state.htmlState = null;
	      }
	    }
	    // Reset state.trailingSpace
	    state.trailingSpace = 0;
	    state.trailingSpaceNewLine = false;
	    // Mark this line as blank
	    state.prevLine = state.thisLine;
	    state.thisLine = {stream: null};
	    return null;
	  }

	  function blockNormal(stream, state) {
	    var firstTokenOnLine = stream.column() === state.indentation;
	    var prevLineLineIsEmpty = lineIsEmpty(state.prevLine.stream);
	    var prevLineIsIndentedCode = state.indentedCode;
	    var prevLineIsHr = state.prevLine.hr;
	    var prevLineIsList = state.list !== false;
	    var maxNonCodeIndentation = (state.listStack[state.listStack.length - 1] || 0) + 3;

	    state.indentedCode = false;

	    var lineIndentation = state.indentation;
	    // compute once per line (on first token)
	    if (state.indentationDiff === null) {
	      state.indentationDiff = state.indentation;
	      if (prevLineIsList) {
	        state.list = null;
	        // While this list item's marker's indentation is less than the deepest
	        //  list item's content's indentation,pop the deepest list item
	        //  indentation off the stack, and update block indentation state
	        while (lineIndentation < state.listStack[state.listStack.length - 1]) {
	          state.listStack.pop();
	          if (state.listStack.length) {
	            state.indentation = state.listStack[state.listStack.length - 1];
	          // less than the first list's indent -> the line is no longer a list
	          } else {
	            state.list = false;
	          }
	        }
	        if (state.list !== false) {
	          state.indentationDiff = lineIndentation - state.listStack[state.listStack.length - 1];
	        }
	      }
	    }

	    // not comprehensive (currently only for setext detection purposes)
	    var allowsInlineContinuation = (
	        !prevLineLineIsEmpty && !prevLineIsHr && !state.prevLine.header &&
	        (!prevLineIsList || !prevLineIsIndentedCode) &&
	        !state.prevLine.fencedCodeEnd
	    );

	    var isHr = (state.list === false || prevLineIsHr || prevLineLineIsEmpty) &&
	      state.indentation <= maxNonCodeIndentation && stream.match(hrRE);

	    var match = null;
	    if (state.indentationDiff >= 4 && (prevLineIsIndentedCode || state.prevLine.fencedCodeEnd ||
	         state.prevLine.header || prevLineLineIsEmpty)) {
	      stream.skipToEnd();
	      state.indentedCode = true;
	      return tokenTypes.code;
	    } else if (stream.eatSpace()) {
	      return null;
	    } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
	      state.quote = 0;
	      state.header = match[1].length;
	      state.thisLine.header = true;
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      state.f = state.inline;
	      return getType(state);
	    } else if (state.indentation <= maxNonCodeIndentation && stream.eat('>')) {
	      state.quote = firstTokenOnLine ? 1 : state.quote + 1;
	      if (modeCfg.highlightFormatting) state.formatting = "quote";
	      stream.eatSpace();
	      return getType(state);
	    } else if (!isHr && !state.setext && firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(listRE))) {
	      var listType = match[1] ? "ol" : "ul";

	      state.indentation = lineIndentation + stream.current().length;
	      state.list = true;
	      state.quote = 0;

	      // Add this list item's content's indentation to the stack
	      state.listStack.push(state.indentation);
	      // Reset inline styles which shouldn't propagate across list items
	      state.em = false;
	      state.strong = false;
	      state.code = false;
	      state.strikethrough = false;

	      if (modeCfg.taskLists && stream.match(taskListRE, false)) {
	        state.taskList = true;
	      }
	      state.f = state.inline;
	      if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
	      return getType(state);
	    } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(fencedCodeRE, true))) {
	      state.quote = 0;
	      state.fencedEndRE = new RegExp(match[1] + "+ *$");
	      // try switching mode
	      state.localMode = modeCfg.fencedCodeBlockHighlighting && getMode(match[2] || modeCfg.fencedCodeBlockDefaultMode );
	      if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
	      state.f = state.block = local;
	      if (modeCfg.highlightFormatting) state.formatting = "code-block";
	      state.code = -1;
	      return getType(state);
	    // SETEXT has lowest block-scope precedence after HR, so check it after
	    //  the others (code, blockquote, list...)
	    } else if (
	      // if setext set, indicates line after ---/===
	      state.setext || (
	        // line before ---/===
	        (!allowsInlineContinuation || !prevLineIsList) && !state.quote && state.list === false &&
	        !state.code && !isHr && !linkDefRE.test(stream.string) &&
	        (match = stream.lookAhead(1)) && (match = match.match(setextHeaderRE))
	      )
	    ) {
	      if ( !state.setext ) {
	        state.header = match[0].charAt(0) == '=' ? 1 : 2;
	        state.setext = state.header;
	      } else {
	        state.header = state.setext;
	        // has no effect on type so we can reset it now
	        state.setext = 0;
	        stream.skipToEnd();
	        if (modeCfg.highlightFormatting) state.formatting = "header";
	      }
	      state.thisLine.header = true;
	      state.f = state.inline;
	      return getType(state);
	    } else if (isHr) {
	      stream.skipToEnd();
	      state.hr = true;
	      state.thisLine.hr = true;
	      return tokenTypes.hr;
	    } else if (stream.peek() === '[') {
	      return switchInline(stream, state, footnoteLink);
	    }

	    return switchInline(stream, state, state.inline);
	  }

	  function htmlBlock(stream, state) {
	    var style = htmlMode.token(stream, state.htmlState);
	    if (!htmlModeMissing) {
	      var inner = CodeMirror.innerMode(htmlMode, state.htmlState);
	      if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
	           (!inner.state.context && inner.state.tokenize.isInText)) ||
	          (state.md_inside && stream.current().indexOf(">") > -1)) {
	        state.f = inlineNormal;
	        state.block = blockNormal;
	        state.htmlState = null;
	      }
	    }
	    return style;
	  }

	  function local(stream, state) {
	    var currListInd = state.listStack[state.listStack.length - 1] || 0;
	    var hasExitedList = state.indentation < currListInd;
	    var maxFencedEndInd = currListInd + 3;
	    if (state.fencedEndRE && state.indentation <= maxFencedEndInd && (hasExitedList || stream.match(state.fencedEndRE))) {
	      if (modeCfg.highlightFormatting) state.formatting = "code-block";
	      var returnType;
	      if (!hasExitedList) returnType = getType(state);
	      state.localMode = state.localState = null;
	      state.block = blockNormal;
	      state.f = inlineNormal;
	      state.fencedEndRE = null;
	      state.code = 0;
	      state.thisLine.fencedCodeEnd = true;
	      if (hasExitedList) return switchBlock(stream, state, state.block);
	      return returnType;
	    } else if (state.localMode) {
	      return state.localMode.token(stream, state.localState);
	    } else {
	      stream.skipToEnd();
	      return tokenTypes.code;
	    }
	  }

	  // Inline
	  function getType(state) {
	    var styles = [];

	    if (state.formatting) {
	      styles.push(tokenTypes.formatting);

	      if (typeof state.formatting === "string") state.formatting = [state.formatting];

	      for (var i = 0; i < state.formatting.length; i++) {
	        styles.push(tokenTypes.formatting + "-" + state.formatting[i]);

	        if (state.formatting[i] === "header") {
	          styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
	        }

	        // Add `formatting-quote` and `formatting-quote-#` for blockquotes
	        // Add `error` instead if the maximum blockquote nesting depth is passed
	        if (state.formatting[i] === "quote") {
	          if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
	            styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
	          } else {
	            styles.push("error");
	          }
	        }
	      }
	    }

	    if (state.taskOpen) {
	      styles.push("meta");
	      return styles.length ? styles.join(' ') : null;
	    }
	    if (state.taskClosed) {
	      styles.push("property");
	      return styles.length ? styles.join(' ') : null;
	    }

	    if (state.linkHref) {
	      styles.push(tokenTypes.linkHref, "url");
	    } else { // Only apply inline styles to non-url text
	      if (state.strong) { styles.push(tokenTypes.strong); }
	      if (state.em) { styles.push(tokenTypes.em); }
	      if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
	      if (state.emoji) { styles.push(tokenTypes.emoji); }
	      if (state.linkText) { styles.push(tokenTypes.linkText); }
	      if (state.code) { styles.push(tokenTypes.code); }
	      if (state.image) { styles.push(tokenTypes.image); }
	      if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); }
	      if (state.imageMarker) { styles.push(tokenTypes.imageMarker); }
	    }

	    if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }

	    if (state.quote) {
	      styles.push(tokenTypes.quote);

	      // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
	      if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
	        styles.push(tokenTypes.quote + "-" + state.quote);
	      } else {
	        styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
	      }
	    }

	    if (state.list !== false) {
	      var listMod = (state.listStack.length - 1) % 3;
	      if (!listMod) {
	        styles.push(tokenTypes.list1);
	      } else if (listMod === 1) {
	        styles.push(tokenTypes.list2);
	      } else {
	        styles.push(tokenTypes.list3);
	      }
	    }

	    if (state.trailingSpaceNewLine) {
	      styles.push("trailing-space-new-line");
	    } else if (state.trailingSpace) {
	      styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
	    }

	    return styles.length ? styles.join(' ') : null;
	  }

	  function handleText(stream, state) {
	    if (stream.match(textRE, true)) {
	      return getType(state);
	    }
	    return undefined;
	  }

	  function inlineNormal(stream, state) {
	    var style = state.text(stream, state);
	    if (typeof style !== 'undefined')
	      return style;

	    if (state.list) { // List marker (*, +, -, 1., etc)
	      state.list = null;
	      return getType(state);
	    }

	    if (state.taskList) {
	      var taskOpen = stream.match(taskListRE, true)[1] === " ";
	      if (taskOpen) state.taskOpen = true;
	      else state.taskClosed = true;
	      if (modeCfg.highlightFormatting) state.formatting = "task";
	      state.taskList = false;
	      return getType(state);
	    }

	    state.taskOpen = false;
	    state.taskClosed = false;

	    if (state.header && stream.match(/^#+$/, true)) {
	      if (modeCfg.highlightFormatting) state.formatting = "header";
	      return getType(state);
	    }

	    var ch = stream.next();

	    // Matches link titles present on next line
	    if (state.linkTitle) {
	      state.linkTitle = false;
	      var matchCh = ch;
	      if (ch === '(') {
	        matchCh = ')';
	      }
	      matchCh = (matchCh+'').replace(/([.?*+^\[\]\\(){}|-])/g, "\\$1");
	      var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
	      if (stream.match(new RegExp(regex), true)) {
	        return tokenTypes.linkHref;
	      }
	    }

	    // If this block is changed, it may need to be updated in GFM mode
	    if (ch === '`') {
	      var previousFormatting = state.formatting;
	      if (modeCfg.highlightFormatting) state.formatting = "code";
	      stream.eatWhile('`');
	      var count = stream.current().length;
	      if (state.code == 0 && (!state.quote || count == 1)) {
	        state.code = count;
	        return getType(state)
	      } else if (count == state.code) { // Must be exact
	        var t = getType(state);
	        state.code = 0;
	        return t
	      } else {
	        state.formatting = previousFormatting;
	        return getType(state)
	      }
	    } else if (state.code) {
	      return getType(state);
	    }

	    if (ch === '\\') {
	      stream.next();
	      if (modeCfg.highlightFormatting) {
	        var type = getType(state);
	        var formattingEscape = tokenTypes.formatting + "-escape";
	        return type ? type + " " + formattingEscape : formattingEscape;
	      }
	    }

	    if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
	      state.imageMarker = true;
	      state.image = true;
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      return getType(state);
	    }

	    if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) {
	      state.imageMarker = false;
	      state.imageAltText = true;
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      return getType(state);
	    }

	    if (ch === ']' && state.imageAltText) {
	      if (modeCfg.highlightFormatting) state.formatting = "image";
	      var type = getType(state);
	      state.imageAltText = false;
	      state.image = false;
	      state.inline = state.f = linkHref;
	      return type;
	    }

	    if (ch === '[' && !state.image) {
	      if (state.linkText && stream.match(/^.*?\]/)) return getType(state)
	      state.linkText = true;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      return getType(state);
	    }

	    if (ch === ']' && state.linkText) {
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      state.linkText = false;
	      state.inline = state.f = stream.match(/\(.*?\)| ?\[.*?\]/, false) ? linkHref : inlineNormal;
	      return type;
	    }

	    if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
	      state.f = state.inline = linkInline;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkInline;
	    }

	    if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
	      state.f = state.inline = linkInline;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkEmail;
	    }

	    if (modeCfg.xml && ch === '<' && stream.match(/^(!--|\?|!\[CDATA\[|[a-z][a-z0-9-]*(?:\s+[a-z_:.\-]+(?:\s*=\s*[^>]+)?)*\s*(?:>|$))/i, false)) {
	      var end = stream.string.indexOf(">", stream.pos);
	      if (end != -1) {
	        var atts = stream.string.substring(stream.start, end);
	        if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
	      }
	      stream.backUp(1);
	      state.htmlState = CodeMirror.startState(htmlMode);
	      return switchBlock(stream, state, htmlBlock);
	    }

	    if (modeCfg.xml && ch === '<' && stream.match(/^\/\w*?>/)) {
	      state.md_inside = false;
	      return "tag";
	    } else if (ch === "*" || ch === "_") {
	      var len = 1, before = stream.pos == 1 ? " " : stream.string.charAt(stream.pos - 2);
	      while (len < 3 && stream.eat(ch)) len++;
	      var after = stream.peek() || " ";
	      // See http://spec.commonmark.org/0.27/#emphasis-and-strong-emphasis
	      var leftFlanking = !/\s/.test(after) && (!punctuation.test(after) || /\s/.test(before) || punctuation.test(before));
	      var rightFlanking = !/\s/.test(before) && (!punctuation.test(before) || /\s/.test(after) || punctuation.test(after));
	      var setEm = null, setStrong = null;
	      if (len % 2) { // Em
	        if (!state.em && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
	          setEm = true;
	        else if (state.em == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
	          setEm = false;
	      }
	      if (len > 1) { // Strong
	        if (!state.strong && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
	          setStrong = true;
	        else if (state.strong == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
	          setStrong = false;
	      }
	      if (setStrong != null || setEm != null) {
	        if (modeCfg.highlightFormatting) state.formatting = setEm == null ? "strong" : setStrong == null ? "em" : "strong em";
	        if (setEm === true) state.em = ch;
	        if (setStrong === true) state.strong = ch;
	        var t = getType(state);
	        if (setEm === false) state.em = false;
	        if (setStrong === false) state.strong = false;
	        return t
	      }
	    } else if (ch === ' ') {
	      if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
	        if (stream.peek() === ' ') { // Surrounded by spaces, ignore
	          return getType(state);
	        } else { // Not surrounded by spaces, back up pointer
	          stream.backUp(1);
	        }
	      }
	    }

	    if (modeCfg.strikethrough) {
	      if (ch === '~' && stream.eatWhile(ch)) {
	        if (state.strikethrough) {// Remove strikethrough
	          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
	          var t = getType(state);
	          state.strikethrough = false;
	          return t;
	        } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
	          state.strikethrough = true;
	          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
	          return getType(state);
	        }
	      } else if (ch === ' ') {
	        if (stream.match('~~', true)) { // Probably surrounded by space
	          if (stream.peek() === ' ') { // Surrounded by spaces, ignore
	            return getType(state);
	          } else { // Not surrounded by spaces, back up pointer
	            stream.backUp(2);
	          }
	        }
	      }
	    }

	    if (modeCfg.emoji && ch === ":" && stream.match(/^(?:[a-z_\d+][a-z_\d+-]*|\-[a-z_\d+][a-z_\d+-]*):/)) {
	      state.emoji = true;
	      if (modeCfg.highlightFormatting) state.formatting = "emoji";
	      var retType = getType(state);
	      state.emoji = false;
	      return retType;
	    }

	    if (ch === ' ') {
	      if (stream.match(/^ +$/, false)) {
	        state.trailingSpace++;
	      } else if (state.trailingSpace) {
	        state.trailingSpaceNewLine = true;
	      }
	    }

	    return getType(state);
	  }

	  function linkInline(stream, state) {
	    var ch = stream.next();

	    if (ch === ">") {
	      state.f = state.inline = inlineNormal;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var type = getType(state);
	      if (type){
	        type += " ";
	      } else {
	        type = "";
	      }
	      return type + tokenTypes.linkInline;
	    }

	    stream.match(/^[^>]+/, true);

	    return tokenTypes.linkInline;
	  }

	  function linkHref(stream, state) {
	    // Check if space, and return NULL if so (to avoid marking the space)
	    if(stream.eatSpace()){
	      return null;
	    }
	    var ch = stream.next();
	    if (ch === '(' || ch === '[') {
	      state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
	      if (modeCfg.highlightFormatting) state.formatting = "link-string";
	      state.linkHref = true;
	      return getType(state);
	    }
	    return 'error';
	  }

	  var linkRE = {
	    ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
	    "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/
	  };

	  function getLinkHrefInside(endChar) {
	    return function(stream, state) {
	      var ch = stream.next();

	      if (ch === endChar) {
	        state.f = state.inline = inlineNormal;
	        if (modeCfg.highlightFormatting) state.formatting = "link-string";
	        var returnState = getType(state);
	        state.linkHref = false;
	        return returnState;
	      }

	      stream.match(linkRE[endChar]);
	      state.linkHref = true;
	      return getType(state);
	    };
	  }

	  function footnoteLink(stream, state) {
	    if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
	      state.f = footnoteLinkInside;
	      stream.next(); // Consume [
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      state.linkText = true;
	      return getType(state);
	    }
	    return switchInline(stream, state, inlineNormal);
	  }

	  function footnoteLinkInside(stream, state) {
	    if (stream.match(']:', true)) {
	      state.f = state.inline = footnoteUrl;
	      if (modeCfg.highlightFormatting) state.formatting = "link";
	      var returnType = getType(state);
	      state.linkText = false;
	      return returnType;
	    }

	    stream.match(/^([^\]\\]|\\.)+/, true);

	    return tokenTypes.linkText;
	  }

	  function footnoteUrl(stream, state) {
	    // Check if space, and return NULL if so (to avoid marking the space)
	    if(stream.eatSpace()){
	      return null;
	    }
	    // Match URL
	    stream.match(/^[^\s]+/, true);
	    // Check for link title
	    if (stream.peek() === undefined) { // End of line, set flag to check next line
	      state.linkTitle = true;
	    } else { // More content on line, check if link title
	      stream.match(/^(?:\s+(?:"(?:[^"\\]|\\.)+"|'(?:[^'\\]|\\.)+'|\((?:[^)\\]|\\.)+\)))?/, true);
	    }
	    state.f = state.inline = inlineNormal;
	    return tokenTypes.linkHref + " url";
	  }

	  var mode = {
	    startState: function() {
	      return {
	        f: blockNormal,

	        prevLine: {stream: null},
	        thisLine: {stream: null},

	        block: blockNormal,
	        htmlState: null,
	        indentation: 0,

	        inline: inlineNormal,
	        text: handleText,

	        formatting: false,
	        linkText: false,
	        linkHref: false,
	        linkTitle: false,
	        code: 0,
	        em: false,
	        strong: false,
	        header: 0,
	        setext: 0,
	        hr: false,
	        taskList: false,
	        list: false,
	        listStack: [],
	        quote: 0,
	        trailingSpace: 0,
	        trailingSpaceNewLine: false,
	        strikethrough: false,
	        emoji: false,
	        fencedEndRE: null
	      };
	    },

	    copyState: function(s) {
	      return {
	        f: s.f,

	        prevLine: s.prevLine,
	        thisLine: s.thisLine,

	        block: s.block,
	        htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
	        indentation: s.indentation,

	        localMode: s.localMode,
	        localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,

	        inline: s.inline,
	        text: s.text,
	        formatting: false,
	        linkText: s.linkText,
	        linkTitle: s.linkTitle,
	        linkHref: s.linkHref,
	        code: s.code,
	        em: s.em,
	        strong: s.strong,
	        strikethrough: s.strikethrough,
	        emoji: s.emoji,
	        header: s.header,
	        setext: s.setext,
	        hr: s.hr,
	        taskList: s.taskList,
	        list: s.list,
	        listStack: s.listStack.slice(0),
	        quote: s.quote,
	        indentedCode: s.indentedCode,
	        trailingSpace: s.trailingSpace,
	        trailingSpaceNewLine: s.trailingSpaceNewLine,
	        md_inside: s.md_inside,
	        fencedEndRE: s.fencedEndRE
	      };
	    },

	    token: function(stream, state) {

	      // Reset state.formatting
	      state.formatting = false;

	      if (stream != state.thisLine.stream) {
	        state.header = 0;
	        state.hr = false;

	        if (stream.match(/^\s*$/, true)) {
	          blankLine(state);
	          return null;
	        }

	        state.prevLine = state.thisLine;
	        state.thisLine = {stream: stream};

	        // Reset state.taskList
	        state.taskList = false;

	        // Reset state.trailingSpace
	        state.trailingSpace = 0;
	        state.trailingSpaceNewLine = false;

	        if (!state.localState) {
	          state.f = state.block;
	          if (state.f != htmlBlock) {
	            var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, expandedTab).length;
	            state.indentation = indentation;
	            state.indentationDiff = null;
	            if (indentation > 0) return null;
	          }
	        }
	      }
	      return state.f(stream, state);
	    },

	    innerMode: function(state) {
	      if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
	      if (state.localState) return {state: state.localState, mode: state.localMode};
	      return {state: state, mode: mode};
	    },

	    indent: function(state, textAfter, line) {
	      if (state.block == htmlBlock && htmlMode.indent) return htmlMode.indent(state.htmlState, textAfter, line)
	      if (state.localState && state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line)
	      return CodeMirror.Pass
	    },

	    blankLine: blankLine,

	    getType: getType,

	    blockCommentStart: "<!--",
	    blockCommentEnd: "-->",
	    closeBrackets: "()[]{}''\"\"``",
	    fold: "markdown"
	  };
	  return mode;
	}, "xml");

	CodeMirror.defineMIME("text/markdown", "markdown");

	CodeMirror.defineMIME("text/x-markdown", "markdown");

	}); 
} ());
/* Injected with object hook! */

var pug = {exports: {}};/* Injected with object hook! */

var htmlmixed = {exports: {}};/* Injected with object hook! */

var hasRequiredHtmlmixed;

function requireHtmlmixed () {
	if (hasRequiredHtmlmixed) return htmlmixed.exports;
	hasRequiredHtmlmixed = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports, xmlExports, javascriptExports, cssExports);
		})(function(CodeMirror) {

		  var defaultTags = {
		    script: [
		      ["lang", /(javascript|babel)/i, "javascript"],
		      ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, "javascript"],
		      ["type", /./, "text/plain"],
		      [null, null, "javascript"]
		    ],
		    style:  [
		      ["lang", /^css$/i, "css"],
		      ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
		      ["type", /./, "text/plain"],
		      [null, null, "css"]
		    ]
		  };

		  function maybeBackup(stream, pat, style) {
		    var cur = stream.current(), close = cur.search(pat);
		    if (close > -1) {
		      stream.backUp(cur.length - close);
		    } else if (cur.match(/<\/?$/)) {
		      stream.backUp(cur.length);
		      if (!stream.match(pat, false)) stream.match(cur);
		    }
		    return style;
		  }

		  var attrRegexpCache = {};
		  function getAttrRegexp(attr) {
		    var regexp = attrRegexpCache[attr];
		    if (regexp) return regexp;
		    return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
		  }

		  function getAttrValue(text, attr) {
		    var match = text.match(getAttrRegexp(attr));
		    return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : ""
		  }

		  function getTagRegexp(tagName, anchored) {
		    return new RegExp((anchored ? "^" : "") + "<\/\\s*" + tagName + "\\s*>", "i");
		  }

		  function addTags(from, to) {
		    for (var tag in from) {
		      var dest = to[tag] || (to[tag] = []);
		      var source = from[tag];
		      for (var i = source.length - 1; i >= 0; i--)
		        dest.unshift(source[i]);
		    }
		  }

		  function findMatchingMode(tagInfo, tagText) {
		    for (var i = 0; i < tagInfo.length; i++) {
		      var spec = tagInfo[i];
		      if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
		    }
		  }

		  CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
		    var htmlMode = CodeMirror.getMode(config, {
		      name: "xml",
		      htmlMode: true,
		      multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
		      multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag,
		      allowMissingTagName: parserConfig.allowMissingTagName,
		    });

		    var tags = {};
		    var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
		    addTags(defaultTags, tags);
		    if (configTags) addTags(configTags, tags);
		    if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
		      tags.script.unshift(["type", configScript[i].matches, configScript[i].mode]);

		    function html(stream, state) {
		      var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName;
		      if (tag && !/[<>\s\/]/.test(stream.current()) &&
		          (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
		          tags.hasOwnProperty(tagName)) {
		        state.inTag = tagName + " ";
		      } else if (state.inTag && tag && />$/.test(stream.current())) {
		        var inTag = /^([\S]+) (.*)/.exec(state.inTag);
		        state.inTag = null;
		        var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2]);
		        var mode = CodeMirror.getMode(config, modeSpec);
		        var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
		        state.token = function (stream, state) {
		          if (stream.match(endTagA, false)) {
		            state.token = html;
		            state.localState = state.localMode = null;
		            return null;
		          }
		          return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
		        };
		        state.localMode = mode;
		        state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "", ""));
		      } else if (state.inTag) {
		        state.inTag += stream.current();
		        if (stream.eol()) state.inTag += " ";
		      }
		      return style;
		    }
		    return {
		      startState: function () {
		        var state = CodeMirror.startState(htmlMode);
		        return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
		      },

		      copyState: function (state) {
		        var local;
		        if (state.localState) {
		          local = CodeMirror.copyState(state.localMode, state.localState);
		        }
		        return {token: state.token, inTag: state.inTag,
		                localMode: state.localMode, localState: local,
		                htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
		      },

		      token: function (stream, state) {
		        return state.token(stream, state);
		      },

		      indent: function (state, textAfter, line) {
		        if (!state.localMode || /^\s*<\//.test(textAfter))
		          return htmlMode.indent(state.htmlState, textAfter, line);
		        else if (state.localMode.indent)
		          return state.localMode.indent(state.localState, textAfter, line);
		        else
		          return CodeMirror.Pass;
		      },

		      innerMode: function (state) {
		        return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
		      }
		    };
		  }, "xml", "javascript", "css");

		  CodeMirror.defineMIME("text/html", "htmlmixed");
		}); 
	} ());
	return htmlmixed.exports;
}
/* Injected with object hook! */

var hasRequiredPug;

function requirePug () {
	if (hasRequiredPug) return pug.exports;
	hasRequiredPug = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports, javascriptExports, cssExports, requireHtmlmixed());
		})(function(CodeMirror) {

		CodeMirror.defineMode("pug", function (config) {
		  // token types
		  var KEYWORD = 'keyword';
		  var DOCTYPE = 'meta';
		  var ID = 'builtin';
		  var CLASS = 'qualifier';

		  var ATTRS_NEST = {
		    '{': '}',
		    '(': ')',
		    '[': ']'
		  };

		  var jsMode = CodeMirror.getMode(config, 'javascript');

		  function State() {
		    this.javaScriptLine = false;
		    this.javaScriptLineExcludesColon = false;

		    this.javaScriptArguments = false;
		    this.javaScriptArgumentsDepth = 0;

		    this.isInterpolating = false;
		    this.interpolationNesting = 0;

		    this.jsState = CodeMirror.startState(jsMode);

		    this.restOfLine = '';

		    this.isIncludeFiltered = false;
		    this.isEach = false;

		    this.lastTag = '';
		    this.scriptType = '';

		    // Attributes Mode
		    this.isAttrs = false;
		    this.attrsNest = [];
		    this.inAttributeName = true;
		    this.attributeIsType = false;
		    this.attrValue = '';

		    // Indented Mode
		    this.indentOf = Infinity;
		    this.indentToken = '';

		    this.innerMode = null;
		    this.innerState = null;

		    this.innerModeForLine = false;
		  }
		  /**
		   * Safely copy a state
		   *
		   * @return {State}
		   */
		  State.prototype.copy = function () {
		    var res = new State();
		    res.javaScriptLine = this.javaScriptLine;
		    res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon;
		    res.javaScriptArguments = this.javaScriptArguments;
		    res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;
		    res.isInterpolating = this.isInterpolating;
		    res.interpolationNesting = this.interpolationNesting;

		    res.jsState = CodeMirror.copyState(jsMode, this.jsState);

		    res.innerMode = this.innerMode;
		    if (this.innerMode && this.innerState) {
		      res.innerState = CodeMirror.copyState(this.innerMode, this.innerState);
		    }

		    res.restOfLine = this.restOfLine;

		    res.isIncludeFiltered = this.isIncludeFiltered;
		    res.isEach = this.isEach;
		    res.lastTag = this.lastTag;
		    res.scriptType = this.scriptType;
		    res.isAttrs = this.isAttrs;
		    res.attrsNest = this.attrsNest.slice();
		    res.inAttributeName = this.inAttributeName;
		    res.attributeIsType = this.attributeIsType;
		    res.attrValue = this.attrValue;
		    res.indentOf = this.indentOf;
		    res.indentToken = this.indentToken;

		    res.innerModeForLine = this.innerModeForLine;

		    return res;
		  };

		  function javaScript(stream, state) {
		    if (stream.sol()) {
		      // if javaScriptLine was set at end of line, ignore it
		      state.javaScriptLine = false;
		      state.javaScriptLineExcludesColon = false;
		    }
		    if (state.javaScriptLine) {
		      if (state.javaScriptLineExcludesColon && stream.peek() === ':') {
		        state.javaScriptLine = false;
		        state.javaScriptLineExcludesColon = false;
		        return;
		      }
		      var tok = jsMode.token(stream, state.jsState);
		      if (stream.eol()) state.javaScriptLine = false;
		      return tok || true;
		    }
		  }
		  function javaScriptArguments(stream, state) {
		    if (state.javaScriptArguments) {
		      if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') {
		        state.javaScriptArguments = false;
		        return;
		      }
		      if (stream.peek() === '(') {
		        state.javaScriptArgumentsDepth++;
		      } else if (stream.peek() === ')') {
		        state.javaScriptArgumentsDepth--;
		      }
		      if (state.javaScriptArgumentsDepth === 0) {
		        state.javaScriptArguments = false;
		        return;
		      }

		      var tok = jsMode.token(stream, state.jsState);
		      return tok || true;
		    }
		  }

		  function yieldStatement(stream) {
		    if (stream.match(/^yield\b/)) {
		        return 'keyword';
		    }
		  }

		  function doctype(stream) {
		    if (stream.match(/^(?:doctype) *([^\n]+)?/)) {
		        return DOCTYPE;
		    }
		  }

		  function interpolation(stream, state) {
		    if (stream.match('#{')) {
		      state.isInterpolating = true;
		      state.interpolationNesting = 0;
		      return 'punctuation';
		    }
		  }

		  function interpolationContinued(stream, state) {
		    if (state.isInterpolating) {
		      if (stream.peek() === '}') {
		        state.interpolationNesting--;
		        if (state.interpolationNesting < 0) {
		          stream.next();
		          state.isInterpolating = false;
		          return 'punctuation';
		        }
		      } else if (stream.peek() === '{') {
		        state.interpolationNesting++;
		      }
		      return jsMode.token(stream, state.jsState) || true;
		    }
		  }

		  function caseStatement(stream, state) {
		    if (stream.match(/^case\b/)) {
		      state.javaScriptLine = true;
		      return KEYWORD;
		    }
		  }

		  function when(stream, state) {
		    if (stream.match(/^when\b/)) {
		      state.javaScriptLine = true;
		      state.javaScriptLineExcludesColon = true;
		      return KEYWORD;
		    }
		  }

		  function defaultStatement(stream) {
		    if (stream.match(/^default\b/)) {
		      return KEYWORD;
		    }
		  }

		  function extendsStatement(stream, state) {
		    if (stream.match(/^extends?\b/)) {
		      state.restOfLine = 'string';
		      return KEYWORD;
		    }
		  }

		  function append(stream, state) {
		    if (stream.match(/^append\b/)) {
		      state.restOfLine = 'variable';
		      return KEYWORD;
		    }
		  }
		  function prepend(stream, state) {
		    if (stream.match(/^prepend\b/)) {
		      state.restOfLine = 'variable';
		      return KEYWORD;
		    }
		  }
		  function block(stream, state) {
		    if (stream.match(/^block\b *(?:(prepend|append)\b)?/)) {
		      state.restOfLine = 'variable';
		      return KEYWORD;
		    }
		  }

		  function include(stream, state) {
		    if (stream.match(/^include\b/)) {
		      state.restOfLine = 'string';
		      return KEYWORD;
		    }
		  }

		  function includeFiltered(stream, state) {
		    if (stream.match(/^include:([a-zA-Z0-9\-]+)/, false) && stream.match('include')) {
		      state.isIncludeFiltered = true;
		      return KEYWORD;
		    }
		  }

		  function includeFilteredContinued(stream, state) {
		    if (state.isIncludeFiltered) {
		      var tok = filter(stream, state);
		      state.isIncludeFiltered = false;
		      state.restOfLine = 'string';
		      return tok;
		    }
		  }

		  function mixin(stream, state) {
		    if (stream.match(/^mixin\b/)) {
		      state.javaScriptLine = true;
		      return KEYWORD;
		    }
		  }

		  function call(stream, state) {
		    if (stream.match(/^\+([-\w]+)/)) {
		      if (!stream.match(/^\( *[-\w]+ *=/, false)) {
		        state.javaScriptArguments = true;
		        state.javaScriptArgumentsDepth = 0;
		      }
		      return 'variable';
		    }
		    if (stream.match('+#{', false)) {
		      stream.next();
		      state.mixinCallAfter = true;
		      return interpolation(stream, state);
		    }
		  }
		  function callArguments(stream, state) {
		    if (state.mixinCallAfter) {
		      state.mixinCallAfter = false;
		      if (!stream.match(/^\( *[-\w]+ *=/, false)) {
		        state.javaScriptArguments = true;
		        state.javaScriptArgumentsDepth = 0;
		      }
		      return true;
		    }
		  }

		  function conditional(stream, state) {
		    if (stream.match(/^(if|unless|else if|else)\b/)) {
		      state.javaScriptLine = true;
		      return KEYWORD;
		    }
		  }

		  function each(stream, state) {
		    if (stream.match(/^(- *)?(each|for)\b/)) {
		      state.isEach = true;
		      return KEYWORD;
		    }
		  }
		  function eachContinued(stream, state) {
		    if (state.isEach) {
		      if (stream.match(/^ in\b/)) {
		        state.javaScriptLine = true;
		        state.isEach = false;
		        return KEYWORD;
		      } else if (stream.sol() || stream.eol()) {
		        state.isEach = false;
		      } else if (stream.next()) {
		        while (!stream.match(/^ in\b/, false) && stream.next());
		        return 'variable';
		      }
		    }
		  }

		  function whileStatement(stream, state) {
		    if (stream.match(/^while\b/)) {
		      state.javaScriptLine = true;
		      return KEYWORD;
		    }
		  }

		  function tag(stream, state) {
		    var captures;
		    if (captures = stream.match(/^(\w(?:[-:\w]*\w)?)\/?/)) {
		      state.lastTag = captures[1].toLowerCase();
		      if (state.lastTag === 'script') {
		        state.scriptType = 'application/javascript';
		      }
		      return 'tag';
		    }
		  }

		  function filter(stream, state) {
		    if (stream.match(/^:([\w\-]+)/)) {
		      var innerMode;
		      if (config && config.innerModes) {
		        innerMode = config.innerModes(stream.current().substring(1));
		      }
		      if (!innerMode) {
		        innerMode = stream.current().substring(1);
		      }
		      if (typeof innerMode === 'string') {
		        innerMode = CodeMirror.getMode(config, innerMode);
		      }
		      setInnerMode(stream, state, innerMode);
		      return 'atom';
		    }
		  }

		  function code(stream, state) {
		    if (stream.match(/^(!?=|-)/)) {
		      state.javaScriptLine = true;
		      return 'punctuation';
		    }
		  }

		  function id(stream) {
		    if (stream.match(/^#([\w-]+)/)) {
		      return ID;
		    }
		  }

		  function className(stream) {
		    if (stream.match(/^\.([\w-]+)/)) {
		      return CLASS;
		    }
		  }

		  function attrs(stream, state) {
		    if (stream.peek() == '(') {
		      stream.next();
		      state.isAttrs = true;
		      state.attrsNest = [];
		      state.inAttributeName = true;
		      state.attrValue = '';
		      state.attributeIsType = false;
		      return 'punctuation';
		    }
		  }

		  function attrsContinued(stream, state) {
		    if (state.isAttrs) {
		      if (ATTRS_NEST[stream.peek()]) {
		        state.attrsNest.push(ATTRS_NEST[stream.peek()]);
		      }
		      if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) {
		        state.attrsNest.pop();
		      } else  if (stream.eat(')')) {
		        state.isAttrs = false;
		        return 'punctuation';
		      }
		      if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) {
		        if (stream.peek() === '=' || stream.peek() === '!') {
		          state.inAttributeName = false;
		          state.jsState = CodeMirror.startState(jsMode);
		          if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') {
		            state.attributeIsType = true;
		          } else {
		            state.attributeIsType = false;
		          }
		        }
		        return 'attribute';
		      }

		      var tok = jsMode.token(stream, state.jsState);
		      if (state.attributeIsType && tok === 'string') {
		        state.scriptType = stream.current().toString();
		      }
		      if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) {
		        try {
		          Function('', 'var x ' + state.attrValue.replace(/,\s*$/, '').replace(/^!/, ''));
		          state.inAttributeName = true;
		          state.attrValue = '';
		          stream.backUp(stream.current().length);
		          return attrsContinued(stream, state);
		        } catch (ex) {
		          //not the end of an attribute
		        }
		      }
		      state.attrValue += stream.current();
		      return tok || true;
		    }
		  }

		  function attributesBlock(stream, state) {
		    if (stream.match(/^&attributes\b/)) {
		      state.javaScriptArguments = true;
		      state.javaScriptArgumentsDepth = 0;
		      return 'keyword';
		    }
		  }

		  function indent(stream) {
		    if (stream.sol() && stream.eatSpace()) {
		      return 'indent';
		    }
		  }

		  function comment(stream, state) {
		    if (stream.match(/^ *\/\/(-)?([^\n]*)/)) {
		      state.indentOf = stream.indentation();
		      state.indentToken = 'comment';
		      return 'comment';
		    }
		  }

		  function colon(stream) {
		    if (stream.match(/^: */)) {
		      return 'colon';
		    }
		  }

		  function text(stream, state) {
		    if (stream.match(/^(?:\| ?| )([^\n]+)/)) {
		      return 'string';
		    }
		    if (stream.match(/^(<[^\n]*)/, false)) {
		      // html string
		      setInnerMode(stream, state, 'htmlmixed');
		      state.innerModeForLine = true;
		      return innerMode(stream, state, true);
		    }
		  }

		  function dot(stream, state) {
		    if (stream.eat('.')) {
		      var innerMode = null;
		      if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) {
		        innerMode = state.scriptType.toLowerCase().replace(/"|'/g, '');
		      } else if (state.lastTag === 'style') {
		        innerMode = 'css';
		      }
		      setInnerMode(stream, state, innerMode);
		      return 'dot';
		    }
		  }

		  function fail(stream) {
		    stream.next();
		    return null;
		  }


		  function setInnerMode(stream, state, mode) {
		    mode = CodeMirror.mimeModes[mode] || mode;
		    mode = config.innerModes ? config.innerModes(mode) || mode : mode;
		    mode = CodeMirror.mimeModes[mode] || mode;
		    mode = CodeMirror.getMode(config, mode);
		    state.indentOf = stream.indentation();

		    if (mode && mode.name !== 'null') {
		      state.innerMode = mode;
		    } else {
		      state.indentToken = 'string';
		    }
		  }
		  function innerMode(stream, state, force) {
		    if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {
		      if (state.innerMode) {
		        if (!state.innerState) {
		          state.innerState = state.innerMode.startState ? CodeMirror.startState(state.innerMode, stream.indentation()) : {};
		        }
		        return stream.hideFirstChars(state.indentOf + 2, function () {
		          return state.innerMode.token(stream, state.innerState) || true;
		        });
		      } else {
		        stream.skipToEnd();
		        return state.indentToken;
		      }
		    } else if (stream.sol()) {
		      state.indentOf = Infinity;
		      state.indentToken = null;
		      state.innerMode = null;
		      state.innerState = null;
		    }
		  }
		  function restOfLine(stream, state) {
		    if (stream.sol()) {
		      // if restOfLine was set at end of line, ignore it
		      state.restOfLine = '';
		    }
		    if (state.restOfLine) {
		      stream.skipToEnd();
		      var tok = state.restOfLine;
		      state.restOfLine = '';
		      return tok;
		    }
		  }


		  function startState() {
		    return new State();
		  }
		  function copyState(state) {
		    return state.copy();
		  }
		  /**
		   * Get the next token in the stream
		   *
		   * @param {Stream} stream
		   * @param {State} state
		   */
		  function nextToken(stream, state) {
		    var tok = innerMode(stream, state)
		      || restOfLine(stream, state)
		      || interpolationContinued(stream, state)
		      || includeFilteredContinued(stream, state)
		      || eachContinued(stream, state)
		      || attrsContinued(stream, state)
		      || javaScript(stream, state)
		      || javaScriptArguments(stream, state)
		      || callArguments(stream, state)

		      || yieldStatement(stream)
		      || doctype(stream)
		      || interpolation(stream, state)
		      || caseStatement(stream, state)
		      || when(stream, state)
		      || defaultStatement(stream)
		      || extendsStatement(stream, state)
		      || append(stream, state)
		      || prepend(stream, state)
		      || block(stream, state)
		      || include(stream, state)
		      || includeFiltered(stream, state)
		      || mixin(stream, state)
		      || call(stream, state)
		      || conditional(stream, state)
		      || each(stream, state)
		      || whileStatement(stream, state)
		      || tag(stream, state)
		      || filter(stream, state)
		      || code(stream, state)
		      || id(stream)
		      || className(stream)
		      || attrs(stream, state)
		      || attributesBlock(stream, state)
		      || indent(stream)
		      || text(stream, state)
		      || comment(stream, state)
		      || colon(stream)
		      || dot(stream, state)
		      || fail(stream);

		    return tok === true ? null : tok;
		  }
		  return {
		    startState: startState,
		    copyState: copyState,
		    token: nextToken
		  };
		}, 'javascript', 'css', 'htmlmixed');

		CodeMirror.defineMIME('text/x-pug', 'pug');
		CodeMirror.defineMIME('text/x-jade', 'pug');

		}); 
	} ());
	return pug.exports;
}
/* Injected with object hook! */

requirePug();
/* Injected with object hook! */

var sass = {exports: {}};/* Injected with object hook! */

var hasRequiredSass;

function requireSass () {
	if (hasRequiredSass) return sass.exports;
	hasRequiredSass = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports, cssExports);
		})(function(CodeMirror) {

		CodeMirror.defineMode("sass", function(config) {
		  var cssMode = CodeMirror.mimeModes["text/css"];
		  var propertyKeywords = cssMode.propertyKeywords || {},
		      colorKeywords = cssMode.colorKeywords || {},
		      valueKeywords = cssMode.valueKeywords || {},
		      fontProperties = cssMode.fontProperties || {};

		  function tokenRegexp(words) {
		    return new RegExp("^" + words.join("|"));
		  }

		  var keywords = ["true", "false", "null", "auto"];
		  var keywordsRegexp = new RegExp("^" + keywords.join("|"));

		  var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-",
		                   "\\!=", "/", "\\*", "%", "and", "or", "not", ";","\\{","\\}",":"];
		  var opRegexp = tokenRegexp(operators);

		  var pseudoElementsRegexp = /^::?[a-zA-Z_][\w\-]*/;

		  var word;

		  function isEndLine(stream) {
		    return !stream.peek() || stream.match(/\s+$/, false);
		  }

		  function urlTokens(stream, state) {
		    var ch = stream.peek();

		    if (ch === ")") {
		      stream.next();
		      state.tokenizer = tokenBase;
		      return "operator";
		    } else if (ch === "(") {
		      stream.next();
		      stream.eatSpace();

		      return "operator";
		    } else if (ch === "'" || ch === '"') {
		      state.tokenizer = buildStringTokenizer(stream.next());
		      return "string";
		    } else {
		      state.tokenizer = buildStringTokenizer(")", false);
		      return "string";
		    }
		  }
		  function comment(indentation, multiLine) {
		    return function(stream, state) {
		      if (stream.sol() && stream.indentation() <= indentation) {
		        state.tokenizer = tokenBase;
		        return tokenBase(stream, state);
		      }

		      if (multiLine && stream.skipTo("*/")) {
		        stream.next();
		        stream.next();
		        state.tokenizer = tokenBase;
		      } else {
		        stream.skipToEnd();
		      }

		      return "comment";
		    };
		  }

		  function buildStringTokenizer(quote, greedy) {
		    if (greedy == null) { greedy = true; }

		    function stringTokenizer(stream, state) {
		      var nextChar = stream.next();
		      var peekChar = stream.peek();
		      var previousChar = stream.string.charAt(stream.pos-2);

		      var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\"));

		      if (endingString) {
		        if (nextChar !== quote && greedy) { stream.next(); }
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        state.tokenizer = tokenBase;
		        return "string";
		      } else if (nextChar === "#" && peekChar === "{") {
		        state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
		        stream.next();
		        return "operator";
		      } else {
		        return "string";
		      }
		    }

		    return stringTokenizer;
		  }

		  function buildInterpolationTokenizer(currentTokenizer) {
		    return function(stream, state) {
		      if (stream.peek() === "}") {
		        stream.next();
		        state.tokenizer = currentTokenizer;
		        return "operator";
		      } else {
		        return tokenBase(stream, state);
		      }
		    };
		  }

		  function indent(state) {
		    if (state.indentCount == 0) {
		      state.indentCount++;
		      var lastScopeOffset = state.scopes[0].offset;
		      var currentOffset = lastScopeOffset + config.indentUnit;
		      state.scopes.unshift({ offset:currentOffset });
		    }
		  }

		  function dedent(state) {
		    if (state.scopes.length == 1) return;

		    state.scopes.shift();
		  }

		  function tokenBase(stream, state) {
		    var ch = stream.peek();

		    // Comment
		    if (stream.match("/*")) {
		      state.tokenizer = comment(stream.indentation(), true);
		      return state.tokenizer(stream, state);
		    }
		    if (stream.match("//")) {
		      state.tokenizer = comment(stream.indentation(), false);
		      return state.tokenizer(stream, state);
		    }

		    // Interpolation
		    if (stream.match("#{")) {
		      state.tokenizer = buildInterpolationTokenizer(tokenBase);
		      return "operator";
		    }

		    // Strings
		    if (ch === '"' || ch === "'") {
		      stream.next();
		      state.tokenizer = buildStringTokenizer(ch);
		      return "string";
		    }

		    if(!state.cursorHalf){// state.cursorHalf === 0
		    // first half i.e. before : for key-value pairs
		    // including selectors

		      if (ch === "-") {
		        if (stream.match(/^-\w+-/)) {
		          return "meta";
		        }
		      }

		      if (ch === ".") {
		        stream.next();
		        if (stream.match(/^[\w-]+/)) {
		          indent(state);
		          return "qualifier";
		        } else if (stream.peek() === "#") {
		          indent(state);
		          return "tag";
		        }
		      }

		      if (ch === "#") {
		        stream.next();
		        // ID selectors
		        if (stream.match(/^[\w-]+/)) {
		          indent(state);
		          return "builtin";
		        }
		        if (stream.peek() === "#") {
		          indent(state);
		          return "tag";
		        }
		      }

		      // Variables
		      if (ch === "$") {
		        stream.next();
		        stream.eatWhile(/[\w-]/);
		        return "variable-2";
		      }

		      // Numbers
		      if (stream.match(/^-?[0-9\.]+/))
		        return "number";

		      // Units
		      if (stream.match(/^(px|em|in)\b/))
		        return "unit";

		      if (stream.match(keywordsRegexp))
		        return "keyword";

		      if (stream.match(/^url/) && stream.peek() === "(") {
		        state.tokenizer = urlTokens;
		        return "atom";
		      }

		      if (ch === "=") {
		        // Match shortcut mixin definition
		        if (stream.match(/^=[\w-]+/)) {
		          indent(state);
		          return "meta";
		        }
		      }

		      if (ch === "+") {
		        // Match shortcut mixin definition
		        if (stream.match(/^\+[\w-]+/)){
		          return "variable-3";
		        }
		      }

		      if(ch === "@"){
		        if(stream.match('@extend')){
		          if(!stream.match(/\s*[\w]/))
		            dedent(state);
		        }
		      }


		      // Indent Directives
		      if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) {
		        indent(state);
		        return "def";
		      }

		      // Other Directives
		      if (ch === "@") {
		        stream.next();
		        stream.eatWhile(/[\w-]/);
		        return "def";
		      }

		      if (stream.eatWhile(/[\w-]/)){
		        if(stream.match(/ *: *[\w-\+\$#!\("']/,false)){
		          word = stream.current().toLowerCase();
		          var prop = state.prevProp + "-" + word;
		          if (propertyKeywords.hasOwnProperty(prop)) {
		            return "property";
		          } else if (propertyKeywords.hasOwnProperty(word)) {
		            state.prevProp = word;
		            return "property";
		          } else if (fontProperties.hasOwnProperty(word)) {
		            return "property";
		          }
		          return "tag";
		        }
		        else if(stream.match(/ *:/,false)){
		          indent(state);
		          state.cursorHalf = 1;
		          state.prevProp = stream.current().toLowerCase();
		          return "property";
		        }
		        else if(stream.match(/ *,/,false)){
		          return "tag";
		        }
		        else {
		          indent(state);
		          return "tag";
		        }
		      }

		      if(ch === ":"){
		        if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element
		          return "variable-3";
		        }
		        stream.next();
		        state.cursorHalf=1;
		        return "operator";
		      }

		    } // cursorHalf===0 ends here
		    else {

		      if (ch === "#") {
		        stream.next();
		        // Hex numbers
		        if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){
		          if (isEndLine(stream)) {
		            state.cursorHalf = 0;
		          }
		          return "number";
		        }
		      }

		      // Numbers
		      if (stream.match(/^-?[0-9\.]+/)){
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        return "number";
		      }

		      // Units
		      if (stream.match(/^(px|em|in)\b/)){
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        return "unit";
		      }

		      if (stream.match(keywordsRegexp)){
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        return "keyword";
		      }

		      if (stream.match(/^url/) && stream.peek() === "(") {
		        state.tokenizer = urlTokens;
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        return "atom";
		      }

		      // Variables
		      if (ch === "$") {
		        stream.next();
		        stream.eatWhile(/[\w-]/);
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        return "variable-2";
		      }

		      // bang character for !important, !default, etc.
		      if (ch === "!") {
		        stream.next();
		        state.cursorHalf = 0;
		        return stream.match(/^[\w]+/) ? "keyword": "operator";
		      }

		      if (stream.match(opRegexp)){
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        return "operator";
		      }

		      // attributes
		      if (stream.eatWhile(/[\w-]/)) {
		        if (isEndLine(stream)) {
		          state.cursorHalf = 0;
		        }
		        word = stream.current().toLowerCase();
		        if (valueKeywords.hasOwnProperty(word)) {
		          return "atom";
		        } else if (colorKeywords.hasOwnProperty(word)) {
		          return "keyword";
		        } else if (propertyKeywords.hasOwnProperty(word)) {
		          state.prevProp = stream.current().toLowerCase();
		          return "property";
		        } else {
		          return "tag";
		        }
		      }

		      //stream.eatSpace();
		      if (isEndLine(stream)) {
		        state.cursorHalf = 0;
		        return null;
		      }

		    } // else ends here

		    if (stream.match(opRegexp))
		      return "operator";

		    // If we haven't returned by now, we move 1 character
		    // and return an error
		    stream.next();
		    return null;
		  }

		  function tokenLexer(stream, state) {
		    if (stream.sol()) state.indentCount = 0;
		    var style = state.tokenizer(stream, state);
		    var current = stream.current();

		    if (current === "@return" || current === "}"){
		      dedent(state);
		    }

		    if (style !== null) {
		      var startOfToken = stream.pos - current.length;

		      var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);

		      var newScopes = [];

		      for (var i = 0; i < state.scopes.length; i++) {
		        var scope = state.scopes[i];

		        if (scope.offset <= withCurrentIndent)
		          newScopes.push(scope);
		      }

		      state.scopes = newScopes;
		    }


		    return style;
		  }

		  return {
		    startState: function() {
		      return {
		        tokenizer: tokenBase,
		        scopes: [{offset: 0, type: "sass"}],
		        indentCount: 0,
		        cursorHalf: 0,  // cursor half tells us if cursor lies after (1)
		                        // or before (0) colon (well... more or less)
		        definedVars: [],
		        definedMixins: []
		      };
		    },
		    token: function(stream, state) {
		      var style = tokenLexer(stream, state);

		      state.lastToken = { style: style, content: stream.current() };

		      return style;
		    },

		    indent: function(state) {
		      return state.scopes[0].offset;
		    },

		    blockCommentStart: "/*",
		    blockCommentEnd: "*/",
		    lineComment: "//",
		    fold: "indent"
		  };
		}, "css");

		CodeMirror.defineMIME("text/x-sass", "sass");

		}); 
	} ());
	return sass.exports;
}
/* Injected with object hook! */

requireSass();
/* Injected with object hook! */

var overlay = {exports: {}};/* Injected with object hook! */

var hasRequiredOverlay;

function requireOverlay () {
	if (hasRequiredOverlay) return overlay.exports;
	hasRequiredOverlay = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		// Utility function that allows modes to be combined. The mode given
		// as the base argument takes care of most of the normal mode
		// functionality, but a second (typically simple) mode is used, which
		// can override the style of text. Both modes get to parse all of the
		// text, but when both assign a non-null style to a piece of code, the
		// overlay wins, unless the combine argument was true and not overridden,
		// or state.overlay.combineTokens was true, in which case the styles are
		// combined.

		(function(mod) {
		  mod(codemirrorExports);
		})(function(CodeMirror) {

		CodeMirror.overlayMode = function(base, overlay, combine) {
		  return {
		    startState: function() {
		      return {
		        base: CodeMirror.startState(base),
		        overlay: CodeMirror.startState(overlay),
		        basePos: 0, baseCur: null,
		        overlayPos: 0, overlayCur: null,
		        streamSeen: null
		      };
		    },
		    copyState: function(state) {
		      return {
		        base: CodeMirror.copyState(base, state.base),
		        overlay: CodeMirror.copyState(overlay, state.overlay),
		        basePos: state.basePos, baseCur: null,
		        overlayPos: state.overlayPos, overlayCur: null
		      };
		    },

		    token: function(stream, state) {
		      if (stream != state.streamSeen ||
		          Math.min(state.basePos, state.overlayPos) < stream.start) {
		        state.streamSeen = stream;
		        state.basePos = state.overlayPos = stream.start;
		      }

		      if (stream.start == state.basePos) {
		        state.baseCur = base.token(stream, state.base);
		        state.basePos = stream.pos;
		      }
		      if (stream.start == state.overlayPos) {
		        stream.pos = stream.start;
		        state.overlayCur = overlay.token(stream, state.overlay);
		        state.overlayPos = stream.pos;
		      }
		      stream.pos = Math.min(state.basePos, state.overlayPos);

		      // state.overlay.combineTokens always takes precedence over combine,
		      // unless set to null
		      if (state.overlayCur == null) return state.baseCur;
		      else if (state.baseCur != null &&
		               state.overlay.combineTokens ||
		               combine && state.overlay.combineTokens == null)
		        return state.baseCur + " " + state.overlayCur;
		      else return state.overlayCur;
		    },

		    indent: base.indent && function(state, textAfter, line) {
		      return base.indent(state.base, textAfter, line);
		    },
		    electricChars: base.electricChars,

		    innerMode: function(state) { return {state: state.base, mode: base}; },

		    blankLine: function(state) {
		      var baseToken, overlayToken;
		      if (base.blankLine) baseToken = base.blankLine(state.base);
		      if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay);

		      return overlayToken == null ?
		        baseToken :
		        (combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken);
		    }
		  };
		};

		}); 
	} ());
	return overlay.exports;
}
/* Injected with object hook! */

var coffeescript = {exports: {}};/* Injected with object hook! */

var hasRequiredCoffeescript;

function requireCoffeescript () {
	if (hasRequiredCoffeescript) return coffeescript.exports;
	hasRequiredCoffeescript = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		/**
		 * Link to the project's GitHub page:
		 * https://github.com/pickhardt/coffeescript-codemirror-mode
		 */
		(function(mod) {
		  mod(codemirrorExports);
		})(function(CodeMirror) {

		CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
		  var ERRORCLASS = "error";

		  function wordRegexp(words) {
		    return new RegExp("^((" + words.join(")|(") + "))\\b");
		  }

		  var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
		  var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
		  var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
		  var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/;

		  var wordOperators = wordRegexp(["and", "or", "not",
		                                  "is", "isnt", "in",
		                                  "instanceof", "typeof"]);
		  var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
		                        "switch", "try", "catch", "finally", "class"];
		  var commonKeywords = ["break", "by", "continue", "debugger", "delete",
		                        "do", "in", "of", "new", "return", "then",
		                        "this", "@", "throw", "when", "until", "extends"];

		  var keywords = wordRegexp(indentKeywords.concat(commonKeywords));

		  indentKeywords = wordRegexp(indentKeywords);


		  var stringPrefixes = /^('{3}|\"{3}|['\"])/;
		  var regexPrefixes = /^(\/{3}|\/)/;
		  var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
		  var constants = wordRegexp(commonConstants);

		  // Tokenizers
		  function tokenBase(stream, state) {
		    // Handle scope changes
		    if (stream.sol()) {
		      if (state.scope.align === null) state.scope.align = false;
		      var scopeOffset = state.scope.offset;
		      if (stream.eatSpace()) {
		        var lineOffset = stream.indentation();
		        if (lineOffset > scopeOffset && state.scope.type == "coffee") {
		          return "indent";
		        } else if (lineOffset < scopeOffset) {
		          return "dedent";
		        }
		        return null;
		      } else {
		        if (scopeOffset > 0) {
		          dedent(stream, state);
		        }
		      }
		    }
		    if (stream.eatSpace()) {
		      return null;
		    }

		    var ch = stream.peek();

		    // Handle docco title comment (single line)
		    if (stream.match("####")) {
		      stream.skipToEnd();
		      return "comment";
		    }

		    // Handle multi line comments
		    if (stream.match("###")) {
		      state.tokenize = longComment;
		      return state.tokenize(stream, state);
		    }

		    // Single line comment
		    if (ch === "#") {
		      stream.skipToEnd();
		      return "comment";
		    }

		    // Handle number literals
		    if (stream.match(/^-?[0-9\.]/, false)) {
		      var floatLiteral = false;
		      // Floats
		      if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
		        floatLiteral = true;
		      }
		      if (stream.match(/^-?\d+\.\d*/)) {
		        floatLiteral = true;
		      }
		      if (stream.match(/^-?\.\d+/)) {
		        floatLiteral = true;
		      }

		      if (floatLiteral) {
		        // prevent from getting extra . on 1..
		        if (stream.peek() == "."){
		          stream.backUp(1);
		        }
		        return "number";
		      }
		      // Integers
		      var intLiteral = false;
		      // Hex
		      if (stream.match(/^-?0x[0-9a-f]+/i)) {
		        intLiteral = true;
		      }
		      // Decimal
		      if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
		        intLiteral = true;
		      }
		      // Zero by itself with no other piece of number.
		      if (stream.match(/^-?0(?![\dx])/i)) {
		        intLiteral = true;
		      }
		      if (intLiteral) {
		        return "number";
		      }
		    }

		    // Handle strings
		    if (stream.match(stringPrefixes)) {
		      state.tokenize = tokenFactory(stream.current(), false, "string");
		      return state.tokenize(stream, state);
		    }
		    // Handle regex literals
		    if (stream.match(regexPrefixes)) {
		      if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
		        state.tokenize = tokenFactory(stream.current(), true, "string-2");
		        return state.tokenize(stream, state);
		      } else {
		        stream.backUp(1);
		      }
		    }



		    // Handle operators and delimiters
		    if (stream.match(operators) || stream.match(wordOperators)) {
		      return "operator";
		    }
		    if (stream.match(delimiters)) {
		      return "punctuation";
		    }

		    if (stream.match(constants)) {
		      return "atom";
		    }

		    if (stream.match(atProp) || state.prop && stream.match(identifiers)) {
		      return "property";
		    }

		    if (stream.match(keywords)) {
		      return "keyword";
		    }

		    if (stream.match(identifiers)) {
		      return "variable";
		    }

		    // Handle non-detected items
		    stream.next();
		    return ERRORCLASS;
		  }

		  function tokenFactory(delimiter, singleline, outclass) {
		    return function(stream, state) {
		      while (!stream.eol()) {
		        stream.eatWhile(/[^'"\/\\]/);
		        if (stream.eat("\\")) {
		          stream.next();
		          if (singleline && stream.eol()) {
		            return outclass;
		          }
		        } else if (stream.match(delimiter)) {
		          state.tokenize = tokenBase;
		          return outclass;
		        } else {
		          stream.eat(/['"\/]/);
		        }
		      }
		      if (singleline) {
		        if (parserConf.singleLineStringErrors) {
		          outclass = ERRORCLASS;
		        } else {
		          state.tokenize = tokenBase;
		        }
		      }
		      return outclass;
		    };
		  }

		  function longComment(stream, state) {
		    while (!stream.eol()) {
		      stream.eatWhile(/[^#]/);
		      if (stream.match("###")) {
		        state.tokenize = tokenBase;
		        break;
		      }
		      stream.eatWhile("#");
		    }
		    return "comment";
		  }

		  function indent(stream, state, type) {
		    type = type || "coffee";
		    var offset = 0, align = false, alignOffset = null;
		    for (var scope = state.scope; scope; scope = scope.prev) {
		      if (scope.type === "coffee" || scope.type == "}") {
		        offset = scope.offset + conf.indentUnit;
		        break;
		      }
		    }
		    if (type !== "coffee") {
		      align = null;
		      alignOffset = stream.column() + stream.current().length;
		    } else if (state.scope.align) {
		      state.scope.align = false;
		    }
		    state.scope = {
		      offset: offset,
		      type: type,
		      prev: state.scope,
		      align: align,
		      alignOffset: alignOffset
		    };
		  }

		  function dedent(stream, state) {
		    if (!state.scope.prev) return;
		    if (state.scope.type === "coffee") {
		      var _indent = stream.indentation();
		      var matched = false;
		      for (var scope = state.scope; scope; scope = scope.prev) {
		        if (_indent === scope.offset) {
		          matched = true;
		          break;
		        }
		      }
		      if (!matched) {
		        return true;
		      }
		      while (state.scope.prev && state.scope.offset !== _indent) {
		        state.scope = state.scope.prev;
		      }
		      return false;
		    } else {
		      state.scope = state.scope.prev;
		      return false;
		    }
		  }

		  function tokenLexer(stream, state) {
		    var style = state.tokenize(stream, state);
		    var current = stream.current();

		    // Handle scope changes.
		    if (current === "return") {
		      state.dedent = true;
		    }
		    if (((current === "->" || current === "=>") && stream.eol())
		        || style === "indent") {
		      indent(stream, state);
		    }
		    var delimiter_index = "[({".indexOf(current);
		    if (delimiter_index !== -1) {
		      indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
		    }
		    if (indentKeywords.exec(current)){
		      indent(stream, state);
		    }
		    if (current == "then"){
		      dedent(stream, state);
		    }


		    if (style === "dedent") {
		      if (dedent(stream, state)) {
		        return ERRORCLASS;
		      }
		    }
		    delimiter_index = "])}".indexOf(current);
		    if (delimiter_index !== -1) {
		      while (state.scope.type == "coffee" && state.scope.prev)
		        state.scope = state.scope.prev;
		      if (state.scope.type == current)
		        state.scope = state.scope.prev;
		    }
		    if (state.dedent && stream.eol()) {
		      if (state.scope.type == "coffee" && state.scope.prev)
		        state.scope = state.scope.prev;
		      state.dedent = false;
		    }

		    return style;
		  }

		  var external = {
		    startState: function(basecolumn) {
		      return {
		        tokenize: tokenBase,
		        scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
		        prop: false,
		        dedent: 0
		      };
		    },

		    token: function(stream, state) {
		      var fillAlign = state.scope.align === null && state.scope;
		      if (fillAlign && stream.sol()) fillAlign.align = false;

		      var style = tokenLexer(stream, state);
		      if (style && style != "comment") {
		        if (fillAlign) fillAlign.align = true;
		        state.prop = style == "punctuation" && stream.current() == ".";
		      }

		      return style;
		    },

		    indent: function(state, text) {
		      if (state.tokenize != tokenBase) return 0;
		      var scope = state.scope;
		      var closer = text && "])}".indexOf(text.charAt(0)) > -1;
		      if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
		      var closes = closer && scope.type === text.charAt(0);
		      if (scope.align)
		        return scope.alignOffset - (closes ? 1 : 0);
		      else
		        return (closes ? scope.prev : scope).offset;
		    },

		    lineComment: "#",
		    fold: "indent"
		  };
		  return external;
		});

		// IANA registered media type
		// https://www.iana.org/assignments/media-types/
		CodeMirror.defineMIME("application/vnd.coffeescript", "coffeescript");

		CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
		CodeMirror.defineMIME("text/coffeescript", "coffeescript");

		}); 
	} ());
	return coffeescript.exports;
}
/* Injected with object hook! */

var stylus = {exports: {}};/* Injected with object hook! */

var hasRequiredStylus;

function requireStylus () {
	if (hasRequiredStylus) return stylus.exports;
	hasRequiredStylus = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		// Stylus mode created by Dmitry Kiselyov http://git.io/AaRB

		(function(mod) {
		  mod(codemirrorExports);
		})(function(CodeMirror) {

		  CodeMirror.defineMode("stylus", function(config) {
		    var indentUnit = config.indentUnit,
		        indentUnitString = '',
		        tagKeywords = keySet(tagKeywords_),
		        tagVariablesRegexp = /^(a|b|i|s|col|em)$/i,
		        propertyKeywords = keySet(propertyKeywords_),
		        nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_),
		        valueKeywords = keySet(valueKeywords_),
		        colorKeywords = keySet(colorKeywords_),
		        documentTypes = keySet(documentTypes_),
		        documentTypesRegexp = wordRegexp(documentTypes_),
		        mediaFeatures = keySet(mediaFeatures_),
		        mediaTypes = keySet(mediaTypes_),
		        fontProperties = keySet(fontProperties_),
		        operatorsRegexp = /^\s*([.]{2,3}|&&|\|\||\*\*|[?!=:]?=|[-+*\/%<>]=?|\?:|\~)/,
		        wordOperatorKeywordsRegexp = wordRegexp(wordOperatorKeywords_),
		        blockKeywords = keySet(blockKeywords_),
		        vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/i),
		        commonAtoms = keySet(commonAtoms_),
		        firstWordMatch = "",
		        states = {},
		        ch,
		        style,
		        type,
		        override;

		    while (indentUnitString.length < indentUnit) indentUnitString += ' ';

		    /**
		     * Tokenizers
		     */
		    function tokenBase(stream, state) {
		      firstWordMatch = stream.string.match(/(^[\w-]+\s*=\s*$)|(^\s*[\w-]+\s*=\s*[\w-])|(^\s*(\.|#|@|\$|\&|\[|\d|\+|::?|\{|\>|~|\/)?\s*[\w-]*([a-z0-9-]|\*|\/\*)(\(|,)?)/);
		      state.context.line.firstWord = firstWordMatch ? firstWordMatch[0].replace(/^\s*/, "") : "";
		      state.context.line.indent = stream.indentation();
		      ch = stream.peek();

		      // Line comment
		      if (stream.match("//")) {
		        stream.skipToEnd();
		        return ["comment", "comment"];
		      }
		      // Block comment
		      if (stream.match("/*")) {
		        state.tokenize = tokenCComment;
		        return tokenCComment(stream, state);
		      }
		      // String
		      if (ch == "\"" || ch == "'") {
		        stream.next();
		        state.tokenize = tokenString(ch);
		        return state.tokenize(stream, state);
		      }
		      // Def
		      if (ch == "@") {
		        stream.next();
		        stream.eatWhile(/[\w\\-]/);
		        return ["def", stream.current()];
		      }
		      // ID selector or Hex color
		      if (ch == "#") {
		        stream.next();
		        // Hex color
		        if (stream.match(/^[0-9a-f]{3}([0-9a-f]([0-9a-f]{2}){0,2})?\b(?!-)/i)) {
		          return ["atom", "atom"];
		        }
		        // ID selector
		        if (stream.match(/^[a-z][\w-]*/i)) {
		          return ["builtin", "hash"];
		        }
		      }
		      // Vendor prefixes
		      if (stream.match(vendorPrefixesRegexp)) {
		        return ["meta", "vendor-prefixes"];
		      }
		      // Numbers
		      if (stream.match(/^-?[0-9]?\.?[0-9]/)) {
		        stream.eatWhile(/[a-z%]/i);
		        return ["number", "unit"];
		      }
		      // !important|optional
		      if (ch == "!") {
		        stream.next();
		        return [stream.match(/^(important|optional)/i) ? "keyword": "operator", "important"];
		      }
		      // Class
		      if (ch == "." && stream.match(/^\.[a-z][\w-]*/i)) {
		        return ["qualifier", "qualifier"];
		      }
		      // url url-prefix domain regexp
		      if (stream.match(documentTypesRegexp)) {
		        if (stream.peek() == "(") state.tokenize = tokenParenthesized;
		        return ["property", "word"];
		      }
		      // Mixins / Functions
		      if (stream.match(/^[a-z][\w-]*\(/i)) {
		        stream.backUp(1);
		        return ["keyword", "mixin"];
		      }
		      // Block mixins
		      if (stream.match(/^(\+|-)[a-z][\w-]*\(/i)) {
		        stream.backUp(1);
		        return ["keyword", "block-mixin"];
		      }
		      // Parent Reference BEM naming
		      if (stream.string.match(/^\s*&/) && stream.match(/^[-_]+[a-z][\w-]*/)) {
		        return ["qualifier", "qualifier"];
		      }
		      // / Root Reference & Parent Reference
		      if (stream.match(/^(\/|&)(-|_|:|\.|#|[a-z])/)) {
		        stream.backUp(1);
		        return ["variable-3", "reference"];
		      }
		      if (stream.match(/^&{1}\s*$/)) {
		        return ["variable-3", "reference"];
		      }
		      // Word operator
		      if (stream.match(wordOperatorKeywordsRegexp)) {
		        return ["operator", "operator"];
		      }
		      // Word
		      if (stream.match(/^\$?[-_]*[a-z0-9]+[\w-]*/i)) {
		        // Variable
		        if (stream.match(/^(\.|\[)[\w-\'\"\]]+/i, false)) {
		          if (!wordIsTag(stream.current())) {
		            stream.match('.');
		            return ["variable-2", "variable-name"];
		          }
		        }
		        return ["variable-2", "word"];
		      }
		      // Operators
		      if (stream.match(operatorsRegexp)) {
		        return ["operator", stream.current()];
		      }
		      // Delimiters
		      if (/[:;,{}\[\]\(\)]/.test(ch)) {
		        stream.next();
		        return [null, ch];
		      }
		      // Non-detected items
		      stream.next();
		      return [null, null];
		    }

		    /**
		     * Token comment
		     */
		    function tokenCComment(stream, state) {
		      var maybeEnd = false, ch;
		      while ((ch = stream.next()) != null) {
		        if (maybeEnd && ch == "/") {
		          state.tokenize = null;
		          break;
		        }
		        maybeEnd = (ch == "*");
		      }
		      return ["comment", "comment"];
		    }

		    /**
		     * Token string
		     */
		    function tokenString(quote) {
		      return function(stream, state) {
		        var escaped = false, ch;
		        while ((ch = stream.next()) != null) {
		          if (ch == quote && !escaped) {
		            if (quote == ")") stream.backUp(1);
		            break;
		          }
		          escaped = !escaped && ch == "\\";
		        }
		        if (ch == quote || !escaped && quote != ")") state.tokenize = null;
		        return ["string", "string"];
		      };
		    }

		    /**
		     * Token parenthesized
		     */
		    function tokenParenthesized(stream, state) {
		      stream.next(); // Must be "("
		      if (!stream.match(/\s*[\"\')]/, false))
		        state.tokenize = tokenString(")");
		      else
		        state.tokenize = null;
		      return [null, "("];
		    }

		    /**
		     * Context management
		     */
		    function Context(type, indent, prev, line) {
		      this.type = type;
		      this.indent = indent;
		      this.prev = prev;
		      this.line = line || {firstWord: "", indent: 0};
		    }

		    function pushContext(state, stream, type, indent) {
		      indent = indent >= 0 ? indent : indentUnit;
		      state.context = new Context(type, stream.indentation() + indent, state.context);
		      return type;
		    }

		    function popContext(state, currentIndent) {
		      var contextIndent = state.context.indent - indentUnit;
		      currentIndent = currentIndent || false;
		      state.context = state.context.prev;
		      if (currentIndent) state.context.indent = contextIndent;
		      return state.context.type;
		    }

		    function pass(type, stream, state) {
		      return states[state.context.type](type, stream, state);
		    }

		    function popAndPass(type, stream, state, n) {
		      for (var i = n || 1; i > 0; i--)
		        state.context = state.context.prev;
		      return pass(type, stream, state);
		    }


		    /**
		     * Parser
		     */
		    function wordIsTag(word) {
		      return word.toLowerCase() in tagKeywords;
		    }

		    function wordIsProperty(word) {
		      word = word.toLowerCase();
		      return word in propertyKeywords || word in fontProperties;
		    }

		    function wordIsBlock(word) {
		      return word.toLowerCase() in blockKeywords;
		    }

		    function wordIsVendorPrefix(word) {
		      return word.toLowerCase().match(vendorPrefixesRegexp);
		    }

		    function wordAsValue(word) {
		      var wordLC = word.toLowerCase();
		      var override = "variable-2";
		      if (wordIsTag(word)) override = "tag";
		      else if (wordIsBlock(word)) override = "block-keyword";
		      else if (wordIsProperty(word)) override = "property";
		      else if (wordLC in valueKeywords || wordLC in commonAtoms) override = "atom";
		      else if (wordLC == "return" || wordLC in colorKeywords) override = "keyword";

		      // Font family
		      else if (word.match(/^[A-Z]/)) override = "string";
		      return override;
		    }

		    function typeIsBlock(type, stream) {
		      return ((endOfLine(stream) && (type == "{" || type == "]" || type == "hash" || type == "qualifier")) || type == "block-mixin");
		    }

		    function typeIsInterpolation(type, stream) {
		      return type == "{" && stream.match(/^\s*\$?[\w-]+/i, false);
		    }

		    function typeIsPseudo(type, stream) {
		      return type == ":" && stream.match(/^[a-z-]+/, false);
		    }

		    function startOfLine(stream) {
		      return stream.sol() || stream.string.match(new RegExp("^\\s*" + escapeRegExp(stream.current())));
		    }

		    function endOfLine(stream) {
		      return stream.eol() || stream.match(/^\s*$/, false);
		    }

		    function firstWordOfLine(line) {
		      var re = /^\s*[-_]*[a-z0-9]+[\w-]*/i;
		      var result = typeof line == "string" ? line.match(re) : line.string.match(re);
		      return result ? result[0].replace(/^\s*/, "") : "";
		    }


		    /**
		     * Block
		     */
		    states.block = function(type, stream, state) {
		      if ((type == "comment" && startOfLine(stream)) ||
		          (type == "," && endOfLine(stream)) ||
		          type == "mixin") {
		        return pushContext(state, stream, "block", 0);
		      }
		      if (typeIsInterpolation(type, stream)) {
		        return pushContext(state, stream, "interpolation");
		      }
		      if (endOfLine(stream) && type == "]") {
		        if (!/^\s*(\.|#|:|\[|\*|&)/.test(stream.string) && !wordIsTag(firstWordOfLine(stream))) {
		          return pushContext(state, stream, "block", 0);
		        }
		      }
		      if (typeIsBlock(type, stream)) {
		        return pushContext(state, stream, "block");
		      }
		      if (type == "}" && endOfLine(stream)) {
		        return pushContext(state, stream, "block", 0);
		      }
		      if (type == "variable-name") {
		        if (stream.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/) || wordIsBlock(firstWordOfLine(stream))) {
		          return pushContext(state, stream, "variableName");
		        }
		        else {
		          return pushContext(state, stream, "variableName", 0);
		        }
		      }
		      if (type == "=") {
		        if (!endOfLine(stream) && !wordIsBlock(firstWordOfLine(stream))) {
		          return pushContext(state, stream, "block", 0);
		        }
		        return pushContext(state, stream, "block");
		      }
		      if (type == "*") {
		        if (endOfLine(stream) || stream.match(/\s*(,|\.|#|\[|:|{)/,false)) {
		          override = "tag";
		          return pushContext(state, stream, "block");
		        }
		      }
		      if (typeIsPseudo(type, stream)) {
		        return pushContext(state, stream, "pseudo");
		      }
		      if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {
		        return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock");
		      }
		      if (/@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
		        return pushContext(state, stream, "keyframes");
		      }
		      if (/@extends?/.test(type)) {
		        return pushContext(state, stream, "extend", 0);
		      }
		      if (type && type.charAt(0) == "@") {

		        // Property Lookup
		        if (stream.indentation() > 0 && wordIsProperty(stream.current().slice(1))) {
		          override = "variable-2";
		          return "block";
		        }
		        if (/(@import|@require|@charset)/.test(type)) {
		          return pushContext(state, stream, "block", 0);
		        }
		        return pushContext(state, stream, "block");
		      }
		      if (type == "reference" && endOfLine(stream)) {
		        return pushContext(state, stream, "block");
		      }
		      if (type == "(") {
		        return pushContext(state, stream, "parens");
		      }

		      if (type == "vendor-prefixes") {
		        return pushContext(state, stream, "vendorPrefixes");
		      }
		      if (type == "word") {
		        var word = stream.current();
		        override = wordAsValue(word);

		        if (override == "property") {
		          if (startOfLine(stream)) {
		            return pushContext(state, stream, "block", 0);
		          } else {
		            override = "atom";
		            return "block";
		          }
		        }

		        if (override == "tag") {

		          // tag is a css value
		          if (/embed|menu|pre|progress|sub|table/.test(word)) {
		            if (wordIsProperty(firstWordOfLine(stream))) {
		              override = "atom";
		              return "block";
		            }
		          }

		          // tag is an attribute
		          if (stream.string.match(new RegExp("\\[\\s*" + word + "|" + word +"\\s*\\]"))) {
		            override = "atom";
		            return "block";
		          }

		          // tag is a variable
		          if (tagVariablesRegexp.test(word)) {
		            if ((startOfLine(stream) && stream.string.match(/=/)) ||
		                (!startOfLine(stream) &&
		                 !stream.string.match(/^(\s*\.|#|\&|\[|\/|>|\*)/) &&
		                 !wordIsTag(firstWordOfLine(stream)))) {
		              override = "variable-2";
		              if (wordIsBlock(firstWordOfLine(stream)))  return "block";
		              return pushContext(state, stream, "block", 0);
		            }
		          }

		          if (endOfLine(stream)) return pushContext(state, stream, "block");
		        }
		        if (override == "block-keyword") {
		          override = "keyword";

		          // Postfix conditionals
		          if (stream.current(/(if|unless)/) && !startOfLine(stream)) {
		            return "block";
		          }
		          return pushContext(state, stream, "block");
		        }
		        if (word == "return") return pushContext(state, stream, "block", 0);

		        // Placeholder selector
		        if (override == "variable-2" && stream.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/)) {
		          return pushContext(state, stream, "block");
		        }
		      }
		      return state.context.type;
		    };


		    /**
		     * Parens
		     */
		    states.parens = function(type, stream, state) {
		      if (type == "(") return pushContext(state, stream, "parens");
		      if (type == ")") {
		        if (state.context.prev.type == "parens") {
		          return popContext(state);
		        }
		        if ((stream.string.match(/^[a-z][\w-]*\(/i) && endOfLine(stream)) ||
		            wordIsBlock(firstWordOfLine(stream)) ||
		            /(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(firstWordOfLine(stream)) ||
		            (!stream.string.match(/^-?[a-z][\w-\.\[\]\'\"]*\s*=/) &&
		             wordIsTag(firstWordOfLine(stream)))) {
		          return pushContext(state, stream, "block");
		        }
		        if (stream.string.match(/^[\$-]?[a-z][\w-\.\[\]\'\"]*\s*=/) ||
		            stream.string.match(/^\s*(\(|\)|[0-9])/) ||
		            stream.string.match(/^\s+[a-z][\w-]*\(/i) ||
		            stream.string.match(/^\s+[\$-]?[a-z]/i)) {
		          return pushContext(state, stream, "block", 0);
		        }
		        if (endOfLine(stream)) return pushContext(state, stream, "block");
		        else return pushContext(state, stream, "block", 0);
		      }
		      if (type && type.charAt(0) == "@" && wordIsProperty(stream.current().slice(1))) {
		        override = "variable-2";
		      }
		      if (type == "word") {
		        var word = stream.current();
		        override = wordAsValue(word);
		        if (override == "tag" && tagVariablesRegexp.test(word)) {
		          override = "variable-2";
		        }
		        if (override == "property" || word == "to") override = "atom";
		      }
		      if (type == "variable-name") {
		        return pushContext(state, stream, "variableName");
		      }
		      if (typeIsPseudo(type, stream)) {
		        return pushContext(state, stream, "pseudo");
		      }
		      return state.context.type;
		    };


		    /**
		     * Vendor prefixes
		     */
		    states.vendorPrefixes = function(type, stream, state) {
		      if (type == "word") {
		        override = "property";
		        return pushContext(state, stream, "block", 0);
		      }
		      return popContext(state);
		    };


		    /**
		     * Pseudo
		     */
		    states.pseudo = function(type, stream, state) {
		      if (!wordIsProperty(firstWordOfLine(stream.string))) {
		        stream.match(/^[a-z-]+/);
		        override = "variable-3";
		        if (endOfLine(stream)) return pushContext(state, stream, "block");
		        return popContext(state);
		      }
		      return popAndPass(type, stream, state);
		    };


		    /**
		     * atBlock
		     */
		    states.atBlock = function(type, stream, state) {
		      if (type == "(") return pushContext(state, stream, "atBlock_parens");
		      if (typeIsBlock(type, stream)) {
		        return pushContext(state, stream, "block");
		      }
		      if (typeIsInterpolation(type, stream)) {
		        return pushContext(state, stream, "interpolation");
		      }
		      if (type == "word") {
		        var word = stream.current().toLowerCase();
		        if (/^(only|not|and|or)$/.test(word))
		          override = "keyword";
		        else if (documentTypes.hasOwnProperty(word))
		          override = "tag";
		        else if (mediaTypes.hasOwnProperty(word))
		          override = "attribute";
		        else if (mediaFeatures.hasOwnProperty(word))
		          override = "property";
		        else if (nonStandardPropertyKeywords.hasOwnProperty(word))
		          override = "string-2";
		        else override = wordAsValue(stream.current());
		        if (override == "tag" && endOfLine(stream)) {
		          return pushContext(state, stream, "block");
		        }
		      }
		      if (type == "operator" && /^(not|and|or)$/.test(stream.current())) {
		        override = "keyword";
		      }
		      return state.context.type;
		    };

		    states.atBlock_parens = function(type, stream, state) {
		      if (type == "{" || type == "}") return state.context.type;
		      if (type == ")") {
		        if (endOfLine(stream)) return pushContext(state, stream, "block");
		        else return pushContext(state, stream, "atBlock");
		      }
		      if (type == "word") {
		        var word = stream.current().toLowerCase();
		        override = wordAsValue(word);
		        if (/^(max|min)/.test(word)) override = "property";
		        if (override == "tag") {
		          tagVariablesRegexp.test(word) ? override = "variable-2" : override = "atom";
		        }
		        return state.context.type;
		      }
		      return states.atBlock(type, stream, state);
		    };


		    /**
		     * Keyframes
		     */
		    states.keyframes = function(type, stream, state) {
		      if (stream.indentation() == "0" && ((type == "}" && startOfLine(stream)) || type == "]" || type == "hash"
		                                          || type == "qualifier" || wordIsTag(stream.current()))) {
		        return popAndPass(type, stream, state);
		      }
		      if (type == "{") return pushContext(state, stream, "keyframes");
		      if (type == "}") {
		        if (startOfLine(stream)) return popContext(state, true);
		        else return pushContext(state, stream, "keyframes");
		      }
		      if (type == "unit" && /^[0-9]+\%$/.test(stream.current())) {
		        return pushContext(state, stream, "keyframes");
		      }
		      if (type == "word") {
		        override = wordAsValue(stream.current());
		        if (override == "block-keyword") {
		          override = "keyword";
		          return pushContext(state, stream, "keyframes");
		        }
		      }
		      if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {
		        return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock");
		      }
		      if (type == "mixin") {
		        return pushContext(state, stream, "block", 0);
		      }
		      return state.context.type;
		    };


		    /**
		     * Interpolation
		     */
		    states.interpolation = function(type, stream, state) {
		      if (type == "{") popContext(state) && pushContext(state, stream, "block");
		      if (type == "}") {
		        if (stream.string.match(/^\s*(\.|#|:|\[|\*|&|>|~|\+|\/)/i) ||
		            (stream.string.match(/^\s*[a-z]/i) && wordIsTag(firstWordOfLine(stream)))) {
		          return pushContext(state, stream, "block");
		        }
		        if (!stream.string.match(/^(\{|\s*\&)/) ||
		            stream.match(/\s*[\w-]/,false)) {
		          return pushContext(state, stream, "block", 0);
		        }
		        return pushContext(state, stream, "block");
		      }
		      if (type == "variable-name") {
		        return pushContext(state, stream, "variableName", 0);
		      }
		      if (type == "word") {
		        override = wordAsValue(stream.current());
		        if (override == "tag") override = "atom";
		      }
		      return state.context.type;
		    };


		    /**
		     * Extend/s
		     */
		    states.extend = function(type, stream, state) {
		      if (type == "[" || type == "=") return "extend";
		      if (type == "]") return popContext(state);
		      if (type == "word") {
		        override = wordAsValue(stream.current());
		        return "extend";
		      }
		      return popContext(state);
		    };


		    /**
		     * Variable name
		     */
		    states.variableName = function(type, stream, state) {
		      if (type == "string" || type == "[" || type == "]" || stream.current().match(/^(\.|\$)/)) {
		        if (stream.current().match(/^\.[\w-]+/i)) override = "variable-2";
		        return "variableName";
		      }
		      return popAndPass(type, stream, state);
		    };


		    return {
		      startState: function(base) {
		        return {
		          tokenize: null,
		          state: "block",
		          context: new Context("block", base || 0, null)
		        };
		      },
		      token: function(stream, state) {
		        if (!state.tokenize && stream.eatSpace()) return null;
		        style = (state.tokenize || tokenBase)(stream, state);
		        if (style && typeof style == "object") {
		          type = style[1];
		          style = style[0];
		        }
		        override = style;
		        state.state = states[state.state](type, stream, state);
		        return override;
		      },
		      indent: function(state, textAfter, line) {

		        var cx = state.context,
		            ch = textAfter && textAfter.charAt(0),
		            indent = cx.indent,
		            lineFirstWord = firstWordOfLine(textAfter),
		            lineIndent = line.match(/^\s*/)[0].replace(/\t/g, indentUnitString).length,
		            prevLineFirstWord = state.context.prev ? state.context.prev.line.firstWord : "",
		            prevLineIndent = state.context.prev ? state.context.prev.line.indent : lineIndent;

		        if (cx.prev &&
		            (ch == "}" && (cx.type == "block" || cx.type == "atBlock" || cx.type == "keyframes") ||
		             ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
		             ch == "{" && (cx.type == "at"))) {
		          indent = cx.indent - indentUnit;
		        } else if (!(/(\})/.test(ch))) {
		          if (/@|\$|\d/.test(ch) ||
		              /^\{/.test(textAfter) ||
		/^\s*\/(\/|\*)/.test(textAfter) ||
		              /^\s*\/\*/.test(prevLineFirstWord) ||
		              /^\s*[\w-\.\[\]\'\"]+\s*(\?|:|\+)?=/i.test(textAfter) ||
		/^(\+|-)?[a-z][\w-]*\(/i.test(textAfter) ||
		/^return/.test(textAfter) ||
		              wordIsBlock(lineFirstWord)) {
		            indent = lineIndent;
		          } else if (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(ch) || wordIsTag(lineFirstWord)) {
		            if (/\,\s*$/.test(prevLineFirstWord)) {
		              indent = prevLineIndent;
		            } else if (/^\s+/.test(line) && (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(prevLineFirstWord) || wordIsTag(prevLineFirstWord))) {
		              indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit;
		            } else {
		              indent = lineIndent;
		            }
		          } else if (!/,\s*$/.test(line) && (wordIsVendorPrefix(lineFirstWord) || wordIsProperty(lineFirstWord))) {
		            if (wordIsBlock(prevLineFirstWord)) {
		              indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit;
		            } else if (/^\{/.test(prevLineFirstWord)) {
		              indent = lineIndent <= prevLineIndent ? lineIndent : prevLineIndent + indentUnit;
		            } else if (wordIsVendorPrefix(prevLineFirstWord) || wordIsProperty(prevLineFirstWord)) {
		              indent = lineIndent >= prevLineIndent ? prevLineIndent : lineIndent;
		            } else if (/^(\.|#|:|\[|\*|&|@|\+|\-|>|~|\/)/.test(prevLineFirstWord) ||
		                      /=\s*$/.test(prevLineFirstWord) ||
		                      wordIsTag(prevLineFirstWord) ||
		                      /^\$[\w-\.\[\]\'\"]/.test(prevLineFirstWord)) {
		              indent = prevLineIndent + indentUnit;
		            } else {
		              indent = lineIndent;
		            }
		          }
		        }
		        return indent;
		      },
		      electricChars: "}",
		      blockCommentStart: "/*",
		      blockCommentEnd: "*/",
		      blockCommentContinue: " * ",
		      lineComment: "//",
		      fold: "indent"
		    };
		  });

		  // developer.mozilla.org/en-US/docs/Web/HTML/Element
		  var tagKeywords_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi", "bdo","bgsound","blockquote","body","br","button","canvas","caption","cite", "code","col","colgroup","data","datalist","dd","del","details","dfn","div", "dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1", "h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe", "img","input","ins","kbd","keygen","label","legend","li","link","main","map", "mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes", "noscript","object","ol","optgroup","option","output","p","param","pre", "progress","q","rp","rt","ruby","s","samp","script","section","select", "small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","track", "u","ul","var","video"];

		  // github.com/codemirror/CodeMirror/blob/master/mode/css/css.js
		  // Note, "url-prefix" should precede "url" in order to match correctly in documentTypesRegexp
		  var documentTypes_ = ["domain", "regexp", "url-prefix", "url"];
		  var mediaTypes_ = ["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"];
		  var mediaFeatures_ = ["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","dynamic-range","video-dynamic-range"];
		  var propertyKeywords_ = ["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode","font-smoothing","osx-font-smoothing"];
		  var nonStandardPropertyKeywords_ = ["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"];
		  var fontProperties_ = ["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"];
		  var colorKeywords_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"];
		  var valueKeywords_ = ["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","conic-gradient","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","high","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-play-button","media-slider","media-sliderthumb","media-volume-slider","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeating-conic-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","standard","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale","row","row-reverse","wrap","wrap-reverse","column-reverse","flex-start","flex-end","space-between","space-around", "unset"];

		  var wordOperatorKeywords_ = ["in","and","or","not","is not","is a","is","isnt","defined","if unless"],
		      blockKeywords_ = ["for","if","else","unless", "from", "to"],
		      commonAtoms_ = ["null","true","false","href","title","type","not-allowed","readonly","disabled"],
		      commonDef_ = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"];

		  var hintWords = tagKeywords_.concat(documentTypes_,mediaTypes_,mediaFeatures_,
		                                      propertyKeywords_,nonStandardPropertyKeywords_,
		                                      colorKeywords_,valueKeywords_,fontProperties_,
		                                      wordOperatorKeywords_,blockKeywords_,
		                                      commonAtoms_,commonDef_);

		  function wordRegexp(words) {
		    words = words.sort(function(a,b){return b > a;});
		    return new RegExp("^((" + words.join(")|(") + "))\\b");
		  }

		  function keySet(array) {
		    var keys = {};
		    for (var i = 0; i < array.length; ++i) keys[array[i]] = true;
		    return keys;
		  }

		  function escapeRegExp(text) {
		    return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
		  }

		  CodeMirror.registerHelper("hintWords", "stylus", hintWords);
		  CodeMirror.defineMIME("text/x-styl", "stylus");
		}); 
	} ());
	return stylus.exports;
}
/* Injected with object hook! */

var handlebars = {exports: {}};/* Injected with object hook! */

var simple = {exports: {}};/* Injected with object hook! */

var hasRequiredSimple;

function requireSimple () {
	if (hasRequiredSimple) return simple.exports;
	hasRequiredSimple = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports);
		})(function(CodeMirror) {

		  CodeMirror.defineSimpleMode = function(name, states) {
		    CodeMirror.defineMode(name, function(config) {
		      return CodeMirror.simpleMode(config, states);
		    });
		  };

		  CodeMirror.simpleMode = function(config, states) {
		    ensureState(states, "start");
		    var states_ = {}, meta = states.meta || {}, hasIndentation = false;
		    for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
		      var list = states_[state] = [], orig = states[state];
		      for (var i = 0; i < orig.length; i++) {
		        var data = orig[i];
		        list.push(new Rule(data, states));
		        if (data.indent || data.dedent) hasIndentation = true;
		      }
		    }
		    var mode = {
		      startState: function() {
		        return {state: "start", pending: null,
		                local: null, localState: null,
		                indent: hasIndentation ? [] : null};
		      },
		      copyState: function(state) {
		        var s = {state: state.state, pending: state.pending,
		                 local: state.local, localState: null,
		                 indent: state.indent && state.indent.slice(0)};
		        if (state.localState)
		          s.localState = CodeMirror.copyState(state.local.mode, state.localState);
		        if (state.stack)
		          s.stack = state.stack.slice(0);
		        for (var pers = state.persistentStates; pers; pers = pers.next)
		          s.persistentStates = {mode: pers.mode,
		                                spec: pers.spec,
		                                state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
		                                next: s.persistentStates};
		        return s;
		      },
		      token: tokenFunction(states_, config),
		      innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
		      indent: indentFunction(states_, meta)
		    };
		    if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
		      mode[prop] = meta[prop];
		    return mode;
		  };

		  function ensureState(states, name) {
		    if (!states.hasOwnProperty(name))
		      throw new Error("Undefined state " + name + " in simple mode");
		  }

		  function toRegex(val, caret) {
		    if (!val) return /(?:)/;
		    var flags = "";
		    if (val instanceof RegExp) {
		      if (val.ignoreCase) flags = "i";
		      if (val.unicode) flags += "u";
		      val = val.source;
		    } else {
		      val = String(val);
		    }
		    return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
		  }

		  function asToken(val) {
		    if (!val) return null;
		    if (val.apply) return val
		    if (typeof val == "string") return val.replace(/\./g, " ");
		    var result = [];
		    for (var i = 0; i < val.length; i++)
		      result.push(val[i] && val[i].replace(/\./g, " "));
		    return result;
		  }

		  function Rule(data, states) {
		    if (data.next || data.push) ensureState(states, data.next || data.push);
		    this.regex = toRegex(data.regex);
		    this.token = asToken(data.token);
		    this.data = data;
		  }

		  function tokenFunction(states, config) {
		    return function(stream, state) {
		      if (state.pending) {
		        var pend = state.pending.shift();
		        if (state.pending.length == 0) state.pending = null;
		        stream.pos += pend.text.length;
		        return pend.token;
		      }

		      if (state.local) {
		        if (state.local.end && stream.match(state.local.end)) {
		          var tok = state.local.endToken || null;
		          state.local = state.localState = null;
		          return tok;
		        } else {
		          var tok = state.local.mode.token(stream, state.localState), m;
		          if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
		            stream.pos = stream.start + m.index;
		          return tok;
		        }
		      }

		      var curState = states[state.state];
		      for (var i = 0; i < curState.length; i++) {
		        var rule = curState[i];
		        var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
		        if (matches) {
		          if (rule.data.next) {
		            state.state = rule.data.next;
		          } else if (rule.data.push) {
		            (state.stack || (state.stack = [])).push(state.state);
		            state.state = rule.data.push;
		          } else if (rule.data.pop && state.stack && state.stack.length) {
		            state.state = state.stack.pop();
		          }

		          if (rule.data.mode)
		            enterLocalMode(config, state, rule.data.mode, rule.token);
		          if (rule.data.indent)
		            state.indent.push(stream.indentation() + config.indentUnit);
		          if (rule.data.dedent)
		            state.indent.pop();
		          var token = rule.token;
		          if (token && token.apply) token = token(matches);
		          if (matches.length > 2 && rule.token && typeof rule.token != "string") {
		            for (var j = 2; j < matches.length; j++)
		              if (matches[j])
		                (state.pending || (state.pending = [])).push({text: matches[j], token: rule.token[j - 1]});
		            stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
		            return token[0];
		          } else if (token && token.join) {
		            return token[0];
		          } else {
		            return token;
		          }
		        }
		      }
		      stream.next();
		      return null;
		    };
		  }

		  function cmp(a, b) {
		    if (a === b) return true;
		    if (!a || typeof a != "object" || !b || typeof b != "object") return false;
		    var props = 0;
		    for (var prop in a) if (a.hasOwnProperty(prop)) {
		      if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
		      props++;
		    }
		    for (var prop in b) if (b.hasOwnProperty(prop)) props--;
		    return props == 0;
		  }

		  function enterLocalMode(config, state, spec, token) {
		    var pers;
		    if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
		      if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
		    var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
		    var lState = pers ? pers.state : CodeMirror.startState(mode);
		    if (spec.persistent && !pers)
		      state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};

		    state.localState = lState;
		    state.local = {mode: mode,
		                   end: spec.end && toRegex(spec.end),
		                   endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
		                   endToken: token && token.join ? token[token.length - 1] : token};
		  }

		  function indexOf(val, arr) {
		    for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
		  }

		  function indentFunction(states, meta) {
		    return function(state, textAfter, line) {
		      if (state.local && state.local.mode.indent)
		        return state.local.mode.indent(state.localState, textAfter, line);
		      if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
		        return CodeMirror.Pass;

		      var pos = state.indent.length - 1, rules = states[state.state];
		      scan: for (;;) {
		        for (var i = 0; i < rules.length; i++) {
		          var rule = rules[i];
		          if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
		            var m = rule.regex.exec(textAfter);
		            if (m && m[0]) {
		              pos--;
		              if (rule.next || rule.push) rules = states[rule.next || rule.push];
		              textAfter = textAfter.slice(m[0].length);
		              continue scan;
		            }
		          }
		        }
		        break;
		      }
		      return pos < 0 ? 0 : state.indent[pos];
		    };
		  }
		}); 
	} ());
	return simple.exports;
}
/* Injected with object hook! */

var multiplex = {exports: {}};/* Injected with object hook! */

var hasRequiredMultiplex;

function requireMultiplex () {
	if (hasRequiredMultiplex) return multiplex.exports;
	hasRequiredMultiplex = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports);
		})(function(CodeMirror) {

		CodeMirror.multiplexingMode = function(outer /*, others */) {
		  // Others should be {open, close, mode [, delimStyle] [, innerStyle] [, parseDelimiters]} objects
		  var others = Array.prototype.slice.call(arguments, 1);

		  function indexOf(string, pattern, from, returnEnd) {
		    if (typeof pattern == "string") {
		      var found = string.indexOf(pattern, from);
		      return returnEnd && found > -1 ? found + pattern.length : found;
		    }
		    var m = pattern.exec(from ? string.slice(from) : string);
		    return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
		  }

		  return {
		    startState: function() {
		      return {
		        outer: CodeMirror.startState(outer),
		        innerActive: null,
		        inner: null,
		        startingInner: false
		      };
		    },

		    copyState: function(state) {
		      return {
		        outer: CodeMirror.copyState(outer, state.outer),
		        innerActive: state.innerActive,
		        inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner),
		        startingInner: state.startingInner
		      };
		    },

		    token: function(stream, state) {
		      if (!state.innerActive) {
		        var cutOff = Infinity, oldContent = stream.string;
		        for (var i = 0; i < others.length; ++i) {
		          var other = others[i];
		          var found = indexOf(oldContent, other.open, stream.pos);
		          if (found == stream.pos) {
		            if (!other.parseDelimiters) stream.match(other.open);
		            state.startingInner = !!other.parseDelimiters;
		            state.innerActive = other;

		            // Get the outer indent, making sure to handle CodeMirror.Pass
		            var outerIndent = 0;
		            if (outer.indent) {
		              var possibleOuterIndent = outer.indent(state.outer, "", "");
		              if (possibleOuterIndent !== CodeMirror.Pass) outerIndent = possibleOuterIndent;
		            }

		            state.inner = CodeMirror.startState(other.mode, outerIndent);
		            return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
		          } else if (found != -1 && found < cutOff) {
		            cutOff = found;
		          }
		        }
		        if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
		        var outerToken = outer.token(stream, state.outer);
		        if (cutOff != Infinity) stream.string = oldContent;
		        return outerToken;
		      } else {
		        var curInner = state.innerActive, oldContent = stream.string;
		        if (!curInner.close && stream.sol()) {
		          state.innerActive = state.inner = null;
		          return this.token(stream, state);
		        }
		        var found = curInner.close && !state.startingInner ?
		            indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
		        if (found == stream.pos && !curInner.parseDelimiters) {
		          stream.match(curInner.close);
		          state.innerActive = state.inner = null;
		          return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
		        }
		        if (found > -1) stream.string = oldContent.slice(0, found);
		        var innerToken = curInner.mode.token(stream, state.inner);
		        if (found > -1) stream.string = oldContent;
		        else if (stream.pos > stream.start) state.startingInner = false;

		        if (found == stream.pos && curInner.parseDelimiters)
		          state.innerActive = state.inner = null;

		        if (curInner.innerStyle) {
		          if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
		          else innerToken = curInner.innerStyle;
		        }

		        return innerToken;
		      }
		    },

		    indent: function(state, textAfter, line) {
		      var mode = state.innerActive ? state.innerActive.mode : outer;
		      if (!mode.indent) return CodeMirror.Pass;
		      return mode.indent(state.innerActive ? state.inner : state.outer, textAfter, line);
		    },

		    blankLine: function(state) {
		      var mode = state.innerActive ? state.innerActive.mode : outer;
		      if (mode.blankLine) {
		        mode.blankLine(state.innerActive ? state.inner : state.outer);
		      }
		      if (!state.innerActive) {
		        for (var i = 0; i < others.length; ++i) {
		          var other = others[i];
		          if (other.open === "\n") {
		            state.innerActive = other;
		            state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "", "") : 0);
		          }
		        }
		      } else if (state.innerActive.close === "\n") {
		        state.innerActive = state.inner = null;
		      }
		    },

		    electricChars: outer.electricChars,

		    innerMode: function(state) {
		      return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
		    }
		  };
		};

		}); 
	} ());
	return multiplex.exports;
}
/* Injected with object hook! */

var hasRequiredHandlebars;

function requireHandlebars () {
	if (hasRequiredHandlebars) return handlebars.exports;
	hasRequiredHandlebars = 1;
	(function (module, exports) {
		// CodeMirror, copyright (c) by Marijn Haverbeke and others
		// Distributed under an MIT license: https://codemirror.net/5/LICENSE

		(function(mod) {
		  mod(codemirrorExports, requireSimple(), requireMultiplex());
		})(function(CodeMirror) {

		  CodeMirror.defineSimpleMode("handlebars-tags", {
		    start: [
		      { regex: /\{\{\{/, push: "handlebars_raw", token: "tag" },
		      { regex: /\{\{!--/, push: "dash_comment", token: "comment" },
		      { regex: /\{\{!/,   push: "comment", token: "comment" },
		      { regex: /\{\{/,    push: "handlebars", token: "tag" }
		    ],
		    handlebars_raw: [
		      { regex: /\}\}\}/, pop: true, token: "tag" },
		    ],
		    handlebars: [
		      { regex: /\}\}/, pop: true, token: "tag" },

		      // Double and single quotes
		      { regex: /"(?:[^\\"]|\\.)*"?/, token: "string" },
		      { regex: /'(?:[^\\']|\\.)*'?/, token: "string" },

		      // Handlebars keywords
		      { regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" },
		      { regex: /(?:else|this)\b/, token: "keyword" },

		      // Numeral
		      { regex: /\d+/i, token: "number" },

		      // Atoms like = and .
		      { regex: /=|~|@|true|false/, token: "atom" },

		      // Paths
		      { regex: /(?:\.\.\/)*(?:[A-Za-z_][\w\.]*)+/, token: "variable-2" }
		    ],
		    dash_comment: [
		      { regex: /--\}\}/, pop: true, token: "comment" },

		      // Commented code
		      { regex: /./, token: "comment"}
		    ],
		    comment: [
		      { regex: /\}\}/, pop: true, token: "comment" },
		      { regex: /./, token: "comment" }
		    ],
		    meta: {
		      blockCommentStart: "{{--",
		      blockCommentEnd: "--}}"
		    }
		  });

		  CodeMirror.defineMode("handlebars", function(config, parserConfig) {
		    var handlebars = CodeMirror.getMode(config, "handlebars-tags");
		    if (!parserConfig || !parserConfig.base) return handlebars;
		    return CodeMirror.multiplexingMode(
		      CodeMirror.getMode(config, parserConfig.base),
		      {open: "{{", close: /\}\}\}?/, mode: handlebars, parseDelimiters: true}
		    );
		  });

		  CodeMirror.defineMIME("text/x-handlebars-template", "handlebars");
		}); 
	} ());
	return handlebars.exports;
}
/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	(function (mod) {
	  {// CommonJS
	    mod(codemirrorExports,
	        requireOverlay(),
	        xmlExports,
	        javascriptExports,
	        requireCoffeescript(),
	        cssExports,
	        requireSass(),
	        requireStylus(),
	        requirePug(),
	        requireHandlebars());
	  }
	})(function (CodeMirror) {
	  var tagLanguages = {
	    script: [
	      ["lang", /coffee(script)?/, "coffeescript"],
	      ["type", /^(?:text|application)\/(?:x-)?coffee(?:script)?$/, "coffeescript"],
	      ["lang", /^babel$/, "javascript"],
	      ["type", /^text\/babel$/, "javascript"],
	      ["type", /^text\/ecmascript-\d+$/, "javascript"]
	    ],
	    style: [
	      ["lang", /^stylus$/i, "stylus"],
	      ["lang", /^sass$/i, "sass"],
	      ["lang", /^less$/i, "text/x-less"],
	      ["lang", /^scss$/i, "text/x-scss"],
	      ["type", /^(text\/)?(x-)?styl(us)?$/i, "stylus"],
	      ["type", /^text\/sass/i, "sass"],
	      ["type", /^(text\/)?(x-)?scss$/i, "text/x-scss"],
	      ["type", /^(text\/)?(x-)?less$/i, "text/x-less"]
	    ],
	    template: [
	      ["lang", /^vue-template$/i, "vue"],
	      ["lang", /^pug$/i, "pug"],
	      ["lang", /^handlebars$/i, "handlebars"],
	      ["type", /^(text\/)?(x-)?pug$/i, "pug"],
	      ["type", /^text\/x-handlebars-template$/i, "handlebars"],
	      [null, null, "vue-template"]
	    ]
	  };

	  CodeMirror.defineMode("vue-template", function (config, parserConfig) {
	    var mustacheOverlay = {
	      token: function (stream) {
	        if (stream.match(/^\{\{.*?\}\}/)) return "meta mustache";
	        while (stream.next() && !stream.match("{{", false)) {}
	        return null;
	      }
	    };
	    return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), mustacheOverlay);
	  });

	  CodeMirror.defineMode("vue", function (config) {
	    return CodeMirror.getMode(config, {name: "htmlmixed", tags: tagLanguages});
	  }, "htmlmixed", "xml", "javascript", "coffeescript", "css", "sass", "stylus", "pug", "handlebars");

	  CodeMirror.defineMIME("script/x-vue", "vue");
	  CodeMirror.defineMIME("text/x-vue", "vue");
	}); 
} ());
/* Injected with object hook! */

requireHandlebars();
/* Injected with object hook! */

requireHtmlmixed();
/* Injected with object hook! */

(function (module, exports) {
	// CodeMirror, copyright (c) by Marijn Haverbeke and others
	// Distributed under an MIT license: https://codemirror.net/5/LICENSE

	(function(mod) {
	  mod(codemirrorExports);
	})(function(CodeMirror) {
	  CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
	    var prev = old && old != CodeMirror.Init;
	    if (val && !prev) {
	      cm.on("blur", onBlur);
	      cm.on("change", onChange);
	      cm.on("swapDoc", onChange);
	      CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function() { onComposition(cm); });
	      onChange(cm);
	    } else if (!val && prev) {
	      cm.off("blur", onBlur);
	      cm.off("change", onChange);
	      cm.off("swapDoc", onChange);
	      CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose);
	      clearPlaceholder(cm);
	      var wrapper = cm.getWrapperElement();
	      wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
	    }

	    if (val && !cm.hasFocus()) onBlur(cm);
	  });

	  function clearPlaceholder(cm) {
	    if (cm.state.placeholder) {
	      cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
	      cm.state.placeholder = null;
	    }
	  }
	  function setPlaceholder(cm) {
	    clearPlaceholder(cm);
	    var elt = cm.state.placeholder = document.createElement("pre");
	    elt.style.cssText = "height: 0; overflow: visible";
	    elt.style.direction = cm.getOption("direction");
	    elt.className = "CodeMirror-placeholder CodeMirror-line-like";
	    var placeHolder = cm.getOption("placeholder");
	    if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder);
	    elt.appendChild(placeHolder);
	    cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
	  }

	  function onComposition(cm) {
	    setTimeout(function() {
	      var empty = false;
	      if (cm.lineCount() == 1) {
	        var input = cm.getInputField();
	        empty = input.nodeName == "TEXTAREA" ? !cm.getLine(0).length
	          : !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent);
	      }
	      if (empty) setPlaceholder(cm);
	      else clearPlaceholder(cm);
	    }, 20);
	  }

	  function onBlur(cm) {
	    if (isEmpty(cm)) setPlaceholder(cm);
	  }
	  function onChange(cm) {
	    var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
	    wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");

	    if (empty) setPlaceholder(cm);
	    else clearPlaceholder(cm);
	  }

	  function isEmpty(cm) {
	    return (cm.lineCount() === 1) && (cm.getLine(0) === "");
	  }
	}); 
} ());
/* Injected with object hook! */

const codemirror = '';
/* Injected with object hook! */

function useCodeMirror(textarea, input, options = {}) {
  const cm = CodeMirror.fromTextArea(
    textarea.value,
    {
      theme: "vars",
      ...options
    }
  );
  let skip = false;
  cm.on("change", () => {
    if (skip) {
      skip = false;
      return;
    }
    input.value = cm.getValue();
  });
  watch(
    input,
    (v) => {
      if (v !== cm.getValue()) {
        skip = true;
        const selections = cm.listSelections();
        cm.replaceRange(v, cm.posFromIndex(0), cm.posFromIndex(Number.POSITIVE_INFINITY));
        cm.setSelections(selections);
      }
    },
    { immediate: true }
  );
  return cm;
}
function syncCmHorizontalScrolling(cm1, cm2) {
  let activeCm = 1;
  cm1.getWrapperElement().addEventListener("mouseenter", () => {
    activeCm = 1;
  });
  cm2.getWrapperElement().addEventListener("mouseenter", () => {
    activeCm = 2;
  });
  cm1.on("scroll", (editor) => {
    if (activeCm === 1)
      cm2.scrollTo(editor.getScrollInfo().left);
  });
  cm2.on("scroll", (editor) => {
    if (activeCm === 2)
      cm1.scrollTo(editor.getScrollInfo().left);
  });
}

/* Injected with object hook! */

/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
const proxyMarker = Symbol("Comlink.proxy");
const createEndpoint = Symbol("Comlink.endpoint");
const releaseProxy = Symbol("Comlink.releaseProxy");
const finalizer = Symbol("Comlink.finalizer");
const throwMarker = Symbol("Comlink.thrown");
const isObject$3 = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
/**
 * Internal transfer handle to handle objects marked to proxy.
 */
const proxyTransferHandler = {
    canHandle: (val) => isObject$3(val) && val[proxyMarker],
    serialize(obj) {
        const { port1, port2 } = new MessageChannel();
        expose(obj, port1);
        return [port2, [port2]];
    },
    deserialize(port) {
        port.start();
        return wrap(port);
    },
};
/**
 * Internal transfer handler to handle thrown exceptions.
 */
const throwTransferHandler = {
    canHandle: (value) => isObject$3(value) && throwMarker in value,
    serialize({ value }) {
        let serialized;
        if (value instanceof Error) {
            serialized = {
                isError: true,
                value: {
                    message: value.message,
                    name: value.name,
                    stack: value.stack,
                },
            };
        }
        else {
            serialized = { isError: false, value };
        }
        return [serialized, []];
    },
    deserialize(serialized) {
        if (serialized.isError) {
            throw Object.assign(new Error(serialized.value.message), serialized.value);
        }
        throw serialized.value;
    },
};
/**
 * Allows customizing the serialization of certain values.
 */
const transferHandlers = new Map([
    ["proxy", proxyTransferHandler],
    ["throw", throwTransferHandler],
]);
function isAllowedOrigin(allowedOrigins, origin) {
    for (const allowedOrigin of allowedOrigins) {
        if (origin === allowedOrigin || allowedOrigin === "*") {
            return true;
        }
        if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
            return true;
        }
    }
    return false;
}
function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
    ep.addEventListener("message", function callback(ev) {
        if (!ev || !ev.data) {
            return;
        }
        if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
            console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
            return;
        }
        const { id, type, path } = Object.assign({ path: [] }, ev.data);
        const argumentList = (ev.data.argumentList || []).map(fromWireValue);
        let returnValue;
        try {
            const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
            const rawValue = path.reduce((obj, prop) => obj[prop], obj);
            switch (type) {
                case "GET" /* MessageType.GET */:
                    {
                        returnValue = rawValue;
                    }
                    break;
                case "SET" /* MessageType.SET */:
                    {
                        parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
                        returnValue = true;
                    }
                    break;
                case "APPLY" /* MessageType.APPLY */:
                    {
                        returnValue = rawValue.apply(parent, argumentList);
                    }
                    break;
                case "CONSTRUCT" /* MessageType.CONSTRUCT */:
                    {
                        const value = new rawValue(...argumentList);
                        returnValue = proxy(value);
                    }
                    break;
                case "ENDPOINT" /* MessageType.ENDPOINT */:
                    {
                        const { port1, port2 } = new MessageChannel();
                        expose(obj, port2);
                        returnValue = transfer(port1, [port1]);
                    }
                    break;
                case "RELEASE" /* MessageType.RELEASE */:
                    {
                        returnValue = undefined;
                    }
                    break;
                default:
                    return;
            }
        }
        catch (value) {
            returnValue = { value, [throwMarker]: 0 };
        }
        Promise.resolve(returnValue)
            .catch((value) => {
            return { value, [throwMarker]: 0 };
        })
            .then((returnValue) => {
            const [wireValue, transferables] = toWireValue(returnValue);
            ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
            if (type === "RELEASE" /* MessageType.RELEASE */) {
                // detach and deactive after sending release response above.
                ep.removeEventListener("message", callback);
                closeEndPoint(ep);
                if (finalizer in obj && typeof obj[finalizer] === "function") {
                    obj[finalizer]();
                }
            }
        })
            .catch((error) => {
            // Send Serialization Error To Caller
            const [wireValue, transferables] = toWireValue({
                value: new TypeError("Unserializable return value"),
                [throwMarker]: 0,
            });
            ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
        });
    });
    if (ep.start) {
        ep.start();
    }
}
function isMessagePort(endpoint) {
    return endpoint.constructor.name === "MessagePort";
}
function closeEndPoint(endpoint) {
    if (isMessagePort(endpoint))
        endpoint.close();
}
function wrap(ep, target) {
    return createProxy(ep, [], target);
}
function throwIfProxyReleased(isReleased) {
    if (isReleased) {
        throw new Error("Proxy has been released and is not useable");
    }
}
function releaseEndpoint(ep) {
    return requestResponseMessage(ep, {
        type: "RELEASE" /* MessageType.RELEASE */,
    }).then(() => {
        closeEndPoint(ep);
    });
}
const proxyCounter = new WeakMap();
const proxyFinalizers = "FinalizationRegistry" in globalThis &&
    new FinalizationRegistry((ep) => {
        const newCount = (proxyCounter.get(ep) || 0) - 1;
        proxyCounter.set(ep, newCount);
        if (newCount === 0) {
            releaseEndpoint(ep);
        }
    });
function registerProxy(proxy, ep) {
    const newCount = (proxyCounter.get(ep) || 0) + 1;
    proxyCounter.set(ep, newCount);
    if (proxyFinalizers) {
        proxyFinalizers.register(proxy, ep, proxy);
    }
}
function unregisterProxy(proxy) {
    if (proxyFinalizers) {
        proxyFinalizers.unregister(proxy);
    }
}
function createProxy(ep, path = [], target = function () { }) {
    let isProxyReleased = false;
    const proxy = new Proxy(target, {
        get(_target, prop) {
            throwIfProxyReleased(isProxyReleased);
            if (prop === releaseProxy) {
                return () => {
                    unregisterProxy(proxy);
                    releaseEndpoint(ep);
                    isProxyReleased = true;
                };
            }
            if (prop === "then") {
                if (path.length === 0) {
                    return { then: () => proxy };
                }
                const r = requestResponseMessage(ep, {
                    type: "GET" /* MessageType.GET */,
                    path: path.map((p) => p.toString()),
                }).then(fromWireValue);
                return r.then.bind(r);
            }
            return createProxy(ep, [...path, prop]);
        },
        set(_target, prop, rawValue) {
            throwIfProxyReleased(isProxyReleased);
            // FIXME: ES6 Proxy Handler `set` methods are supposed to return a
            // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
            const [value, transferables] = toWireValue(rawValue);
            return requestResponseMessage(ep, {
                type: "SET" /* MessageType.SET */,
                path: [...path, prop].map((p) => p.toString()),
                value,
            }, transferables).then(fromWireValue);
        },
        apply(_target, _thisArg, rawArgumentList) {
            throwIfProxyReleased(isProxyReleased);
            const last = path[path.length - 1];
            if (last === createEndpoint) {
                return requestResponseMessage(ep, {
                    type: "ENDPOINT" /* MessageType.ENDPOINT */,
                }).then(fromWireValue);
            }
            // We just pretend that `bind()` didn’t happen.
            if (last === "bind") {
                return createProxy(ep, path.slice(0, -1));
            }
            const [argumentList, transferables] = processArguments(rawArgumentList);
            return requestResponseMessage(ep, {
                type: "APPLY" /* MessageType.APPLY */,
                path: path.map((p) => p.toString()),
                argumentList,
            }, transferables).then(fromWireValue);
        },
        construct(_target, rawArgumentList) {
            throwIfProxyReleased(isProxyReleased);
            const [argumentList, transferables] = processArguments(rawArgumentList);
            return requestResponseMessage(ep, {
                type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
                path: path.map((p) => p.toString()),
                argumentList,
            }, transferables).then(fromWireValue);
        },
    });
    registerProxy(proxy, ep);
    return proxy;
}
function myFlat(arr) {
    return Array.prototype.concat.apply([], arr);
}
function processArguments(argumentList) {
    const processed = argumentList.map(toWireValue);
    return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
}
const transferCache = new WeakMap();
function transfer(obj, transfers) {
    transferCache.set(obj, transfers);
    return obj;
}
function proxy(obj) {
    return Object.assign(obj, { [proxyMarker]: true });
}
function toWireValue(value) {
    for (const [name, handler] of transferHandlers) {
        if (handler.canHandle(value)) {
            const [serializedValue, transferables] = handler.serialize(value);
            return [
                {
                    type: "HANDLER" /* WireValueType.HANDLER */,
                    name,
                    value: serializedValue,
                },
                transferables,
            ];
        }
    }
    return [
        {
            type: "RAW" /* WireValueType.RAW */,
            value,
        },
        transferCache.get(value) || [],
    ];
}
function fromWireValue(value) {
    switch (value.type) {
        case "HANDLER" /* WireValueType.HANDLER */:
            return transferHandlers.get(value.name).deserialize(value.value);
        case "RAW" /* WireValueType.RAW */:
            return value.value;
    }
}
function requestResponseMessage(ep, msg, transfers) {
    return new Promise((resolve) => {
        const id = generateUUID();
        ep.addEventListener("message", function l(ev) {
            if (!ev.data || !ev.data.id || ev.data.id !== id) {
                return;
            }
            ep.removeEventListener("message", l);
            resolve(ev.data);
        });
        if (ep.start) {
            ep.start();
        }
        ep.postMessage(Object.assign({ id }, msg), transfers);
    });
}
function generateUUID() {
    return new Array(4)
        .fill(0)
        .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
        .join("-");
}


/* Injected with object hook! */

let diffWorker;
async function calculateDiffWithWorker(left, right) {
  if (!diffWorker) {
    diffWorker = wrap(
      new Worker(new URL(""+new URL('diff.worker-0f10460a.js', import.meta.url).href+"", self.location), {
        type: "module"
      })
    );
  }
  const result = await diffWorker.calculateDiff(left, right);
  return result;
}

/* Injected with object hook! */

const _hoisted_1$8 = ["textContent"];
const _hoisted_2$7 = ["textContent"];
const _sfc_main$9 = /* @__PURE__ */ defineComponent({
  __name: "DiffEditor",
  props: {
    from: {},
    to: {},
    oneColumn: { type: Boolean },
    diff: { type: Boolean }
  },
  setup(__props) {
    const props = __props;
    const { from, to } = toRefs(props);
    const panelSize = useLocalStorage("vite-inspect-diff-panel-size", 30);
    const fromEl = ref();
    const toEl = ref();
    onMounted(() => {
      const cm1 = useCodeMirror(
        fromEl,
        from,
        {
          mode: "javascript",
          readOnly: true,
          lineNumbers: true,
          scrollbarStyle: "null"
        }
      );
      const cm2 = useCodeMirror(
        toEl,
        to,
        {
          mode: "javascript",
          readOnly: true,
          lineNumbers: true,
          scrollbarStyle: "null"
        }
      );
      syncCmHorizontalScrolling(cm1, cm2);
      watchEffect(() => {
        cm1.setOption("lineWrapping", lineWrapping.value);
        cm2.setOption("lineWrapping", lineWrapping.value);
      });
      watchEffect(() => {
        cm1.display.wrapper.style.display = props.oneColumn ? "none" : "";
      });
      watchEffect(async () => {
        const l = from.value;
        const r = to.value;
        cm1.setOption("mode", guessMode(l));
        cm2.setOption("mode", guessMode(r));
        await nextTick();
        cm1.startOperation();
        cm2.startOperation();
        cm1.getAllMarks().forEach((i) => i.clear());
        cm2.getAllMarks().forEach((i) => i.clear());
        for (let i = 0; i < cm1.lineCount() + 2; i++)
          cm1.removeLineClass(i, "background", "diff-removed");
        for (let i = 0; i < cm2.lineCount() + 2; i++)
          cm2.removeLineClass(i, "background", "diff-added");
        if (props.diff && from.value) {
          const changes = await calculateDiffWithWorker(l, r);
          const addedLines = /* @__PURE__ */ new Set();
          const removedLines = /* @__PURE__ */ new Set();
          let indexL = 0;
          let indexR = 0;
          changes.forEach(([type, change]) => {
            if (type === 1) {
              const start = cm2.posFromIndex(indexR);
              indexR += change.length;
              const end = cm2.posFromIndex(indexR);
              cm2.markText(start, end, { className: "diff-added-inline" });
              for (let i = start.line; i <= end.line; i++)
                addedLines.add(i);
            } else if (type === -1) {
              const start = cm1.posFromIndex(indexL);
              indexL += change.length;
              const end = cm1.posFromIndex(indexL);
              cm1.markText(start, end, { className: "diff-removed-inline" });
              for (let i = start.line; i <= end.line; i++)
                removedLines.add(i);
            } else {
              indexL += change.length;
              indexR += change.length;
            }
          });
          Array.from(removedLines).forEach(
            (i) => cm1.addLineClass(i, "background", "diff-removed")
          );
          Array.from(addedLines).forEach(
            (i) => cm2.addLineClass(i, "background", "diff-added")
          );
        }
        cm1.endOperation();
        cm2.endOperation();
      });
    });
    const leftPanelSize = computed(() => {
      return props.oneColumn ? 0 : panelSize.value;
    });
    function onUpdate(size) {
      if (props.oneColumn)
        return;
      panelSize.value = size;
    }
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(M), {
        onResize: _cache[0] || (_cache[0] = ($event) => onUpdate($event[0].size))
      }, {
        default: withCtx(() => [
          withDirectives(createVNode(unref(g), {
            "min-size": "10",
            size: unref(leftPanelSize),
            class: "h-max min-h-screen",
            border: "main r"
          }, {
            default: withCtx(() => [
              createBaseVNode("textarea", {
                ref_key: "fromEl",
                ref: fromEl,
                textContent: toDisplayString(unref(from))
              }, null, 8, _hoisted_1$8)
            ]),
            _: 1
          }, 8, ["size"]), [
            [vShow, !_ctx.oneColumn]
          ]),
          createVNode(unref(g), {
            "min-size": "10",
            size: 100 - unref(leftPanelSize),
            class: "h-max min-h-screen"
          }, {
            default: withCtx(() => [
              createBaseVNode("textarea", {
                ref_key: "toEl",
                ref: toEl,
                textContent: toDisplayString(unref(to))
              }, null, 8, _hoisted_2$7)
            ]),
            _: 1
          }, 8, ["size"])
        ]),
        _: 1
      });
    };
  }
});

/* Injected with object hook! */

/* unplugin-vue-components disabled */const DiffEditor_vue_vue_type_style_index_0_lang = '';
/* Injected with object hook! */

const _hoisted_1$7 = { op60: "" };
const _hoisted_2$6 = {
  key: 0,
  op50: ""
};
const _sfc_main$8 = /* @__PURE__ */ defineComponent({
  __name: "FilepathItem",
  props: {
    filepath: {},
    line: {},
    column: {}
  },
  setup(__props) {
    const props = __props;
    async function openInEditor() {
      await fetch(`/__open-in-editor?file=${encodeURI(props.filepath)}:${props.line}:${props.column}`);
    }
    const display = computed(() => {
      const path = props.filepath.replace(/\\/g, "/");
      if (props.filepath.includes("/node_modules/")) {
        const match = path.match(/.*\/node_modules\/(@[^/]+\/[^/]+|[^/]+)(\/.*)?$/);
        if (match)
          return [match[1], match[2]];
      }
      return [path];
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("button", {
        flex: "~",
        hover: "underline",
        onClick: openInEditor
      }, [
        createBaseVNode("span", null, toDisplayString(unref(display)[0]), 1),
        createBaseVNode("span", _hoisted_1$7, toDisplayString(unref(display)[1]), 1),
        props.line != null && props.column != null ? (openBlock(), createElementBlock("span", _hoisted_2$6, ":" + toDisplayString(props.line) + ":" + toDisplayString(props.column), 1)) : createCommentVNode("", true)
      ]);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$6 = {
  "of-auto": "",
  p4: "",
  "font-mono": "",
  flex: "~ col gap-4"
};
const _hoisted_2$5 = /* @__PURE__ */ createBaseVNode("div", {
  "text-xl": "",
  "text-red7": "",
  "dark:text-red": "",
  flex: "~ gap-2 items-center"
}, [
  /* @__PURE__ */ createBaseVNode("div", { "i-carbon:warning-square": "" }),
  /* @__PURE__ */ createTextVNode(" Error ")
], -1);
const _hoisted_3$4 = {
  "text-sm": "",
  "text-red7": "",
  "dark:text-red": ""
};
const _hoisted_4$4 = /* @__PURE__ */ createBaseVNode("div", {
  border: "t main",
  "h-1px": "",
  "w-full": ""
}, null, -1);
const _hoisted_5$4 = {
  class: "text-xs",
  mt2: "",
  grid: "~ cols-[max-content_1fr] gap-x-4 gap-y-1",
  "font-mono": ""
};
const _hoisted_6$4 = {
  "text-right": "",
  op50: ""
};
const _hoisted_7$3 = { "ws-nowrap": "" };
const _sfc_main$7 = /* @__PURE__ */ defineComponent({
  __name: "ErrorDisplay",
  props: {
    error: {}
  },
  setup(__props) {
    function normalizeFilename(filename) {
      return (filename || "").replace(/^async\s+/, "").replace(/^file:\/\//, "");
    }
    return (_ctx, _cache) => {
      const _component_FilepathItem = _sfc_main$8;
      return openBlock(), createElementBlock("div", _hoisted_1$6, [
        _hoisted_2$5,
        createBaseVNode("pre", _hoisted_3$4, toDisplayString(_ctx.error.message), 1),
        _hoisted_4$4,
        createBaseVNode("div", _hoisted_5$4, [
          (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.error.stack, (item, idx) => {
            return openBlock(), createElementBlock(Fragment, { key: idx }, [
              createBaseVNode("div", _hoisted_6$4, toDisplayString(item.functionName || `(anonymous)`), 1),
              createBaseVNode("div", _hoisted_7$3, [
                createVNode(_component_FilepathItem, {
                  filepath: normalizeFilename(item.fileName),
                  line: item.lineNumber,
                  column: item.columnNumber
                }, null, 8, ["filepath", "line", "column"])
              ])
            ], 64);
          }), 128))
        ])
      ]);
    };
  }
});

/* Injected with object hook! */

const _cache = /* @__PURE__ */ new WeakMap();
function useRouteQuery(name, defaultValue, options = {}) {
  const {
    mode = "replace",
    route = useRoute(),
    router = useRouter(),
    transform = (value) => value
  } = options;
  if (!_cache.has(route))
    _cache.set(route, /* @__PURE__ */ new Map());
  const _query = _cache.get(route);
  tryOnScopeDispose(() => {
    _query.delete(name);
  });
  _query.set(name, route.query[name]);
  let _trigger;
  const proxy = customRef((track, trigger) => {
    _trigger = trigger;
    return {
      get() {
        track();
        const data = _query.get(name);
        return transform(data !== void 0 ? data : toValue(defaultValue));
      },
      set(v) {
        if (_query.get(name) === v)
          return;
        _query.set(name, v);
        trigger();
        nextTick(() => {
          const { params, query, hash } = route;
          router[toValue(mode)]({
            params,
            query: { ...query, ...Object.fromEntries(_query.entries()) },
            hash
          });
        });
      }
    };
  });
  watch(
    () => route.query[name],
    (v) => {
      _query.set(name, v);
      _trigger();
    },
    { flush: "sync" }
  );
  return proxy;
}

/* Injected with object hook! */

const hotContext = createHotContext();
async function getHot() {
  return await hotContext;
}

/* Injected with object hook! */

const _hoisted_1$5 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-arrow-left": "" }, null, -1);
const _hoisted_2$4 = /* @__PURE__ */ createBaseVNode("div", { "flex-auto": "" }, null, -1);
const _hoisted_3$3 = ["title", "disabled"];
const _hoisted_4$3 = {
  key: 0,
  "i-carbon-side-panel-open": ""
};
const _hoisted_5$3 = {
  key: 1,
  "i-carbon-side-panel-close": ""
};
const _hoisted_6$3 = {
  flex: "~ gap2 items-center",
  p2: "",
  "tracking-widest": "",
  class: "op75 dark:op50"
};
const _hoisted_7$2 = {
  "flex-auto": "",
  "text-center": "",
  "text-sm": ""
};
const _hoisted_8$2 = /* @__PURE__ */ createBaseVNode("div", { border: "b main" }, null, -1);
const _hoisted_9$2 = ["onClick"];
const _hoisted_10$1 = /* @__PURE__ */ createBaseVNode("div", { "flex-auto": "" }, null, -1);
const _hoisted_11$1 = {
  "h-full": "",
  "of-auto": ""
};
const _sfc_main$6 = /* @__PURE__ */ defineComponent({
  __name: "module",
  async setup(__props) {
    let __temp, __restore;
    function getModuleId(fullPath) {
      if (!fullPath)
        return void 0;
      return new URL(fullPath, "http://localhost").searchParams.get("id") || void 0;
    }
    const route = useRoute();
    const module = getModuleId(route.fullPath);
    const id = computed(() => getModuleId(route.fullPath));
    const data = ref(module ? ([__temp, __restore] = withAsyncContext(() => rpc.getIdInfo(module, inspectSSR.value)), __temp = await __temp, __restore(), __temp) : void 0);
    const index = useRouteQuery("index");
    const currentIndex = computed(() => (index.value != null ? +index.value : null) ?? (data.value?.transforms.length || 1) - 1);
    const panelSize = useLocalStorage("vite-inspect-module-panel-size", "10");
    const transforms = computed(() => {
      const trs = data.value?.transforms;
      if (!trs)
        return void 0;
      let load = false;
      return trs.map((tr, index2) => ({
        ...tr,
        noChange: !!tr.result && index2 > 0 && tr.result === trs[index2 - 1]?.result,
        load: tr.result && (load ? false : load = true),
        index: index2
      }));
    });
    const filteredTransforms = computed(
      () => transforms.value?.filter((tr) => showBailout.value || tr.result)
    );
    async function refetch() {
      if (id.value)
        data.value = await rpc.getIdInfo(id.value, inspectSSR.value, true);
    }
    onRefetch.on(async () => {
      await refetch();
    });
    watch([id, inspectSSR], refetch);
    const lastTransform = computed(
      () => transforms.value?.slice(0, currentIndex.value).reverse().find((tr) => tr.result)
    );
    const currentTransform = computed(() => transforms.value?.find((tr) => tr.index === currentIndex.value));
    const from = computed(() => lastTransform.value?.result || "");
    const to = computed(() => currentTransform.value?.result || from.value);
    const sourcemaps = computed(() => {
      let sourcemaps2 = currentTransform.value?.sourcemaps;
      if (!sourcemaps2)
        return void 0;
      if (typeof sourcemaps2 === "string")
        sourcemaps2 = safeJsonParse(sourcemaps2);
      if (!sourcemaps2?.mappings)
        return;
      if (sourcemaps2 && !sourcemaps2.sourcesContent?.filter(Boolean)?.length)
        sourcemaps2.sourcesContent = [from.value];
      if (sourcemaps2 && !sourcemaps2.sources?.filter(Boolean)?.length)
        sourcemaps2.sources = ["index.js"];
      return JSON.stringify(sourcemaps2);
    });
    getHot().then((hot) => {
      if (hot) {
        hot.on("vite-plugin-inspect:update", ({ ids }) => {
          if (id.value && ids.includes(id.value))
            refetch();
        });
      }
    });
    return (_ctx, _cache) => {
      const _component_RouterLink = resolveComponent("RouterLink");
      const _component_ModuleId = _sfc_main$g;
      const _component_Badge = __unplugin_components_5;
      const _component_NavBar = _sfc_main$c;
      const _component_PluginName = _sfc_main$i;
      const _component_DurationDisplay = _sfc_main$j;
      const _component_ErrorDisplay = _sfc_main$7;
      const _component_DiffEditor = _sfc_main$9;
      const _component_Container = __unplugin_components_7;
      return openBlock(), createElementBlock(Fragment, null, [
        createVNode(_component_NavBar, null, {
          default: withCtx(() => [
            createVNode(_component_RouterLink, {
              "my-auto": "",
              "outline-none": "",
              "icon-btn": "",
              to: "/"
            }, {
              default: withCtx(() => [
                _hoisted_1$5
              ]),
              _: 1
            }),
            unref(id) ? (openBlock(), createBlock(_component_ModuleId, {
              key: 0,
              id: unref(id)
            }, null, 8, ["id"])) : createCommentVNode("", true),
            unref(inspectSSR) ? (openBlock(), createBlock(_component_Badge, {
              key: 1,
              class: "bg-teal-400:10 font-bold text-green-700 dark:text-teal-400"
            }, {
              default: withCtx(() => [
                createTextVNode(" SSR ")
              ]),
              _: 1
            })) : createCommentVNode("", true),
            _hoisted_2$4,
            createBaseVNode("button", {
              "text-lg": "",
              "icon-btn": "",
              title: "Inspect SSR",
              onClick: _cache[0] || (_cache[0] = ($event) => inspectSSR.value = !unref(inspectSSR))
            }, [
              createBaseVNode("div", {
                "i-carbon-cloud-services": "",
                class: normalizeClass(unref(inspectSSR) ? "opacity-100" : "opacity-25")
              }, null, 2)
            ]),
            createBaseVNode("button", {
              "text-lg": "",
              "icon-btn": "",
              title: unref(sourcemaps) ? "Inspect sourcemaps" : "Sourcemap is not available",
              disabled: !unref(sourcemaps),
              onClick: _cache[1] || (_cache[1] = ($event) => unref(inspectSourcemaps)({ code: unref(to), sourcemaps: unref(sourcemaps) }))
            }, [
              createBaseVNode("div", {
                "i-carbon-choropleth-map": "",
                class: normalizeClass(unref(sourcemaps) ? "opacity-100" : "opacity-25")
              }, null, 2)
            ], 8, _hoisted_3$3),
            createBaseVNode("button", {
              "text-lg": "",
              "icon-btn": "",
              title: "Line Wrapping",
              onClick: _cache[2] || (_cache[2] = ($event) => lineWrapping.value = !unref(lineWrapping))
            }, [
              createBaseVNode("div", {
                "i-carbon-text-wrap": "",
                class: normalizeClass(unref(lineWrapping) ? "opacity-100" : "opacity-25")
              }, null, 2)
            ]),
            createBaseVNode("button", {
              "text-lg": "",
              "icon-btn": "",
              title: "Toggle one column",
              onClick: _cache[3] || (_cache[3] = ($event) => showOneColumn.value = !unref(showOneColumn))
            }, [
              unref(showOneColumn) ? (openBlock(), createElementBlock("div", _hoisted_4$3)) : (openBlock(), createElementBlock("div", _hoisted_5$3))
            ]),
            createBaseVNode("button", {
              class: "text-lg icon-btn",
              title: "Toggle Diff",
              onClick: _cache[4] || (_cache[4] = ($event) => enableDiff.value = !unref(enableDiff))
            }, [
              createBaseVNode("div", {
                "i-carbon-compare": "",
                class: normalizeClass(unref(enableDiff) ? "opacity-100" : "opacity-25")
              }, null, 2)
            ])
          ]),
          _: 1
        }),
        unref(data) && unref(filteredTransforms) ? (openBlock(), createBlock(_component_Container, {
          key: 0,
          flex: "",
          "overflow-hidden": ""
        }, {
          default: withCtx(() => [
            createVNode(unref(M), {
              "h-full": "",
              "of-hidden": "",
              onResize: _cache[6] || (_cache[6] = ($event) => panelSize.value = $event[0].size)
            }, {
              default: withCtx(() => [
                createVNode(unref(g), {
                  size: unref(panelSize),
                  "min-size": "10",
                  flex: "~ col",
                  border: "r main",
                  "overflow-y-auto": ""
                }, {
                  default: withCtx(() => [
                    createBaseVNode("div", _hoisted_6$3, [
                      createBaseVNode("span", _hoisted_7$2, toDisplayString(unref(inspectSSR) ? "SSR " : "") + "TRANSFORM STACK", 1),
                      createBaseVNode("button", {
                        class: "icon-btn",
                        title: "Toggle bailout plugins",
                        onClick: _cache[5] || (_cache[5] = ($event) => showBailout.value = !unref(showBailout))
                      }, [
                        createBaseVNode("div", {
                          class: normalizeClass(unref(showBailout) ? "opacity-100 i-carbon-view" : "opacity-50 i-carbon-view-off")
                        }, null, 2)
                      ])
                    ]),
                    _hoisted_8$2,
                    (openBlock(true), createElementBlock(Fragment, null, renderList(unref(filteredTransforms), (tr) => {
                      return openBlock(), createElementBlock("button", {
                        key: tr.index,
                        border: "b main",
                        flex: "~ gap-1 wrap",
                        "items-center": "",
                        "px-2": "",
                        "py-2": "",
                        "text-left": "",
                        "text-xs": "",
                        "font-mono": "",
                        class: normalizeClass(
                          unref(currentIndex) === tr.index ? "bg-active" : tr.noChange || !tr.result ? "op50" : ""
                        ),
                        onClick: ($event) => index.value = tr.index.toString()
                      }, [
                        createBaseVNode("span", {
                          class: normalizeClass(unref(currentIndex) === tr.index ? "font-bold" : "")
                        }, [
                          createVNode(_component_PluginName, {
                            name: tr.name
                          }, null, 8, ["name"])
                        ], 2),
                        !tr.result ? (openBlock(), createBlock(_component_Badge, {
                          key: 0,
                          class: "bg-gray-400:10 text-gray-700 dark:text-gray-400",
                          textContent: "bailout"
                        })) : tr.noChange ? (openBlock(), createBlock(_component_Badge, {
                          key: 1,
                          class: "bg-orange-400:10 text-orange-800 dark:text-orange-400",
                          textContent: "no change"
                        })) : createCommentVNode("", true),
                        tr.load ? (openBlock(), createBlock(_component_Badge, {
                          key: 2,
                          class: "bg-light-blue-400/10 text-blue-700 dark:text-light-blue-400",
                          textContent: "load"
                        })) : createCommentVNode("", true),
                        tr.order && tr.order !== "normal" ? (openBlock(), createBlock(_component_Badge, {
                          key: 3,
                          class: "bg-violet-400:10 text-violet-700 dark:text-violet-400",
                          title: tr.order.includes("-") ? `Using object hooks ${tr.order}` : tr.order,
                          textContent: toDisplayString(tr.order)
                        }, null, 8, ["title", "textContent"])) : createCommentVNode("", true),
                        tr.error ? (openBlock(), createBlock(_component_Badge, {
                          key: 4,
                          class: "bg-red-400:10 text-red7 dark:text-red-400",
                          textContent: "error"
                        })) : createCommentVNode("", true),
                        _hoisted_10$1,
                        createVNode(_component_DurationDisplay, {
                          duration: tr.end - tr.start
                        }, null, 8, ["duration"])
                      ], 10, _hoisted_9$2);
                    }), 128))
                  ]),
                  _: 1
                }, 8, ["size"]),
                createVNode(unref(g), { "min-size": "5" }, {
                  default: withCtx(() => [
                    createBaseVNode("div", _hoisted_11$1, [
                      unref(currentTransform)?.error ? (openBlock(), createBlock(_component_ErrorDisplay, {
                        key: `error-${unref(id)}`,
                        error: unref(currentTransform).error
                      }, null, 8, ["error"])) : (openBlock(), createBlock(_component_DiffEditor, {
                        key: unref(id),
                        "one-column": unref(showOneColumn) || !!unref(currentTransform)?.error,
                        diff: unref(enableDiff) && !unref(currentTransform)?.error,
                        from: unref(from),
                        to: unref(to),
                        "h-unset": ""
                      }, null, 8, ["one-column", "diff", "from", "to"]))
                    ])
                  ]),
                  _: 1
                })
              ]),
              _: 1
            })
          ]),
          _: 1
        })) : createCommentVNode("", true)
      ], 64);
    };
  }
});

/* Injected with object hook! */

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */

var extendStatics = function(d, b) {
    extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
    return extendStatics(d, b);
};

function __extends(d, b) {
    if (typeof b !== "function" && b !== null)
        throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

/* Injected with object hook! */

var Browser = (function () {
    function Browser() {
        this.firefox = false;
        this.ie = false;
        this.edge = false;
        this.newEdge = false;
        this.weChat = false;
    }
    return Browser;
}());
var Env = (function () {
    function Env() {
        this.browser = new Browser();
        this.node = false;
        this.wxa = false;
        this.worker = false;
        this.svgSupported = false;
        this.touchEventsSupported = false;
        this.pointerEventsSupported = false;
        this.domSupported = false;
        this.transformSupported = false;
        this.transform3dSupported = false;
        this.hasGlobalWindow = typeof window !== 'undefined';
    }
    return Env;
}());
var env = new Env();
if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') {
    env.wxa = true;
    env.touchEventsSupported = true;
}
else if (typeof document === 'undefined' && typeof self !== 'undefined') {
    env.worker = true;
}
else if (typeof navigator === 'undefined') {
    env.node = true;
    env.svgSupported = true;
}
else {
    detect(navigator.userAgent, env);
}
function detect(ua, env) {
    var browser = env.browser;
    var firefox = ua.match(/Firefox\/([\d.]+)/);
    var ie = ua.match(/MSIE\s([\d.]+)/)
        || ua.match(/Trident\/.+?rv:(([\d.]+))/);
    var edge = ua.match(/Edge?\/([\d.]+)/);
    var weChat = (/micromessenger/i).test(ua);
    if (firefox) {
        browser.firefox = true;
        browser.version = firefox[1];
    }
    if (ie) {
        browser.ie = true;
        browser.version = ie[1];
    }
    if (edge) {
        browser.edge = true;
        browser.version = edge[1];
        browser.newEdge = +edge[1].split('.')[0] > 18;
    }
    if (weChat) {
        browser.weChat = true;
    }
    env.svgSupported = typeof SVGRect !== 'undefined';
    env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge;
    env.pointerEventsSupported = 'onpointerdown' in window
        && (browser.edge || (browser.ie && +browser.version >= 11));
    env.domSupported = typeof document !== 'undefined';
    var style = document.documentElement.style;
    env.transform3dSupported = ((browser.ie && 'transition' in style)
        || browser.edge
        || (('WebKitCSSMatrix' in window) && ('m11' in new WebKitCSSMatrix()))
        || 'MozPerspective' in style)
        && !('OTransition' in style);
    env.transformSupported = env.transform3dSupported
        || (browser.ie && +browser.version >= 9);
}
const env$1 = env;

/* Injected with object hook! */

var DEFAULT_FONT_SIZE = 12;
var DEFAULT_FONT_FAMILY = 'sans-serif';
var DEFAULT_FONT = DEFAULT_FONT_SIZE + "px " + DEFAULT_FONT_FAMILY;
var OFFSET = 20;
var SCALE = 100;
var defaultWidthMapStr = "007LLmW'55;N0500LLLLLLLLLL00NNNLzWW\\\\WQb\\0FWLg\\bWb\\WQ\\WrWWQ000CL5LLFLL0LL**F*gLLLL5F0LF\\FFF5.5N";
function getTextWidthMap(mapStr) {
    var map = {};
    if (typeof JSON === 'undefined') {
        return map;
    }
    for (var i = 0; i < mapStr.length; i++) {
        var char = String.fromCharCode(i + 32);
        var size = (mapStr.charCodeAt(i) - OFFSET) / SCALE;
        map[char] = size;
    }
    return map;
}
var DEFAULT_TEXT_WIDTH_MAP = getTextWidthMap(defaultWidthMapStr);
var platformApi = {
    createCanvas: function () {
        return typeof document !== 'undefined'
            && document.createElement('canvas');
    },
    measureText: (function () {
        var _ctx;
        var _cachedFont;
        return function (text, font) {
            if (!_ctx) {
                var canvas = platformApi.createCanvas();
                _ctx = canvas && canvas.getContext('2d');
            }
            if (_ctx) {
                if (_cachedFont !== font) {
                    _cachedFont = _ctx.font = font || DEFAULT_FONT;
                }
                return _ctx.measureText(text);
            }
            else {
                text = text || '';
                font = font || DEFAULT_FONT;
                var res = /(\d+)px/.exec(font);
                var fontSize = res && +res[1] || DEFAULT_FONT_SIZE;
                var width = 0;
                if (font.indexOf('mono') >= 0) {
                    width = fontSize * text.length;
                }
                else {
                    for (var i = 0; i < text.length; i++) {
                        var preCalcWidth = DEFAULT_TEXT_WIDTH_MAP[text[i]];
                        width += preCalcWidth == null ? fontSize : (preCalcWidth * fontSize);
                    }
                }
                return { width: width };
            }
        };
    })(),
    loadImage: function (src, onload, onerror) {
        var image = new Image();
        image.onload = onload;
        image.onerror = onerror;
        image.src = src;
        return image;
    }
};

/* Injected with object hook! */

var BUILTIN_OBJECT = reduce([
    'Function',
    'RegExp',
    'Date',
    'Error',
    'CanvasGradient',
    'CanvasPattern',
    'Image',
    'Canvas'
], function (obj, val) {
    obj['[object ' + val + ']'] = true;
    return obj;
}, {});
var TYPED_ARRAY = reduce([
    'Int8',
    'Uint8',
    'Uint8Clamped',
    'Int16',
    'Uint16',
    'Int32',
    'Uint32',
    'Float32',
    'Float64'
], function (obj, val) {
    obj['[object ' + val + 'Array]'] = true;
    return obj;
}, {});
var objToString = Object.prototype.toString;
var arrayProto = Array.prototype;
var nativeForEach = arrayProto.forEach;
var nativeFilter = arrayProto.filter;
var nativeSlice = arrayProto.slice;
var nativeMap = arrayProto.map;
var ctorFunction = function () { }.constructor;
var protoFunction = ctorFunction ? ctorFunction.prototype : null;
var protoKey = '__proto__';
var idStart = 0x0907;
function guid() {
    return idStart++;
}
function logError() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    if (typeof console !== 'undefined') {
        console.error.apply(console, args);
    }
}
function clone$2(source) {
    if (source == null || typeof source !== 'object') {
        return source;
    }
    var result = source;
    var typeStr = objToString.call(source);
    if (typeStr === '[object Array]') {
        if (!isPrimitive(source)) {
            result = [];
            for (var i = 0, len = source.length; i < len; i++) {
                result[i] = clone$2(source[i]);
            }
        }
    }
    else if (TYPED_ARRAY[typeStr]) {
        if (!isPrimitive(source)) {
            var Ctor = source.constructor;
            if (Ctor.from) {
                result = Ctor.from(source);
            }
            else {
                result = new Ctor(source.length);
                for (var i = 0, len = source.length; i < len; i++) {
                    result[i] = source[i];
                }
            }
        }
    }
    else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
        result = {};
        for (var key in source) {
            if (source.hasOwnProperty(key) && key !== protoKey) {
                result[key] = clone$2(source[key]);
            }
        }
    }
    return result;
}
function merge(target, source, overwrite) {
    if (!isObject$2(source) || !isObject$2(target)) {
        return overwrite ? clone$2(source) : target;
    }
    for (var key in source) {
        if (source.hasOwnProperty(key) && key !== protoKey) {
            var targetProp = target[key];
            var sourceProp = source[key];
            if (isObject$2(sourceProp)
                && isObject$2(targetProp)
                && !isArray(sourceProp)
                && !isArray(targetProp)
                && !isDom(sourceProp)
                && !isDom(targetProp)
                && !isBuiltInObject(sourceProp)
                && !isBuiltInObject(targetProp)
                && !isPrimitive(sourceProp)
                && !isPrimitive(targetProp)) {
                merge(targetProp, sourceProp, overwrite);
            }
            else if (overwrite || !(key in target)) {
                target[key] = clone$2(source[key]);
            }
        }
    }
    return target;
}
function extend(target, source) {
    if (Object.assign) {
        Object.assign(target, source);
    }
    else {
        for (var key in source) {
            if (source.hasOwnProperty(key) && key !== protoKey) {
                target[key] = source[key];
            }
        }
    }
    return target;
}
function defaults(target, source, overlay) {
    var keysArr = keys(source);
    for (var i = 0; i < keysArr.length; i++) {
        var key = keysArr[i];
        if ((overlay ? source[key] != null : target[key] == null)) {
            target[key] = source[key];
        }
    }
    return target;
}
function indexOf(array, value) {
    if (array) {
        if (array.indexOf) {
            return array.indexOf(value);
        }
        for (var i = 0, len = array.length; i < len; i++) {
            if (array[i] === value) {
                return i;
            }
        }
    }
    return -1;
}
function inherits(clazz, baseClazz) {
    var clazzPrototype = clazz.prototype;
    function F() { }
    F.prototype = baseClazz.prototype;
    clazz.prototype = new F();
    for (var prop in clazzPrototype) {
        if (clazzPrototype.hasOwnProperty(prop)) {
            clazz.prototype[prop] = clazzPrototype[prop];
        }
    }
    clazz.prototype.constructor = clazz;
    clazz.superClass = baseClazz;
}
function mixin(target, source, override) {
    target = 'prototype' in target ? target.prototype : target;
    source = 'prototype' in source ? source.prototype : source;
    if (Object.getOwnPropertyNames) {
        var keyList = Object.getOwnPropertyNames(source);
        for (var i = 0; i < keyList.length; i++) {
            var key = keyList[i];
            if (key !== 'constructor') {
                if ((override ? source[key] != null : target[key] == null)) {
                    target[key] = source[key];
                }
            }
        }
    }
    else {
        defaults(target, source, override);
    }
}
function isArrayLike(data) {
    if (!data) {
        return false;
    }
    if (typeof data === 'string') {
        return false;
    }
    return typeof data.length === 'number';
}
function each$4(arr, cb, context) {
    if (!(arr && cb)) {
        return;
    }
    if (arr.forEach && arr.forEach === nativeForEach) {
        arr.forEach(cb, context);
    }
    else if (arr.length === +arr.length) {
        for (var i = 0, len = arr.length; i < len; i++) {
            cb.call(context, arr[i], i, arr);
        }
    }
    else {
        for (var key in arr) {
            if (arr.hasOwnProperty(key)) {
                cb.call(context, arr[key], key, arr);
            }
        }
    }
}
function map$1(arr, cb, context) {
    if (!arr) {
        return [];
    }
    if (!cb) {
        return slice(arr);
    }
    if (arr.map && arr.map === nativeMap) {
        return arr.map(cb, context);
    }
    else {
        var result = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            result.push(cb.call(context, arr[i], i, arr));
        }
        return result;
    }
}
function reduce(arr, cb, memo, context) {
    if (!(arr && cb)) {
        return;
    }
    for (var i = 0, len = arr.length; i < len; i++) {
        memo = cb.call(context, memo, arr[i], i, arr);
    }
    return memo;
}
function filter(arr, cb, context) {
    if (!arr) {
        return [];
    }
    if (!cb) {
        return slice(arr);
    }
    if (arr.filter && arr.filter === nativeFilter) {
        return arr.filter(cb, context);
    }
    else {
        var result = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            if (cb.call(context, arr[i], i, arr)) {
                result.push(arr[i]);
            }
        }
        return result;
    }
}
function keys(obj) {
    if (!obj) {
        return [];
    }
    if (Object.keys) {
        return Object.keys(obj);
    }
    var keyList = [];
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            keyList.push(key);
        }
    }
    return keyList;
}
function bindPolyfill(func, context) {
    var args = [];
    for (var _i = 2; _i < arguments.length; _i++) {
        args[_i - 2] = arguments[_i];
    }
    return function () {
        return func.apply(context, args.concat(nativeSlice.call(arguments)));
    };
}
var bind$1 = (protoFunction && isFunction(protoFunction.bind))
    ? protoFunction.call.bind(protoFunction.bind)
    : bindPolyfill;
function curry$1(func) {
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
    }
    return function () {
        return func.apply(this, args.concat(nativeSlice.call(arguments)));
    };
}
function isArray(value) {
    if (Array.isArray) {
        return Array.isArray(value);
    }
    return objToString.call(value) === '[object Array]';
}
function isFunction(value) {
    return typeof value === 'function';
}
function isString(value) {
    return typeof value === 'string';
}
function isStringSafe(value) {
    return objToString.call(value) === '[object String]';
}
function isNumber(value) {
    return typeof value === 'number';
}
function isObject$2(value) {
    var type = typeof value;
    return type === 'function' || (!!value && type === 'object');
}
function isBuiltInObject(value) {
    return !!BUILTIN_OBJECT[objToString.call(value)];
}
function isTypedArray(value) {
    return !!TYPED_ARRAY[objToString.call(value)];
}
function isDom(value) {
    return typeof value === 'object'
        && typeof value.nodeType === 'number'
        && typeof value.ownerDocument === 'object';
}
function isGradientObject(value) {
    return value.colorStops != null;
}
function isImagePatternObject(value) {
    return value.image != null;
}
function eqNaN(value) {
    return value !== value;
}
function retrieve() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    for (var i = 0, len = args.length; i < len; i++) {
        if (args[i] != null) {
            return args[i];
        }
    }
}
function retrieve2(value0, value1) {
    return value0 != null
        ? value0
        : value1;
}
function retrieve3(value0, value1, value2) {
    return value0 != null
        ? value0
        : value1 != null
            ? value1
            : value2;
}
function slice(arr) {
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
    }
    return nativeSlice.apply(arr, args);
}
function normalizeCssArray$1(val) {
    if (typeof (val) === 'number') {
        return [val, val, val, val];
    }
    var len = val.length;
    if (len === 2) {
        return [val[0], val[1], val[0], val[1]];
    }
    else if (len === 3) {
        return [val[0], val[1], val[2], val[1]];
    }
    return val;
}
function assert(condition, message) {
    if (!condition) {
        throw new Error(message);
    }
}
function trim(str) {
    if (str == null) {
        return null;
    }
    else if (typeof str.trim === 'function') {
        return str.trim();
    }
    else {
        return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
    }
}
var primitiveKey = '__ec_primitive__';
function setAsPrimitive(obj) {
    obj[primitiveKey] = true;
}
function isPrimitive(obj) {
    return obj[primitiveKey];
}
var MapPolyfill = (function () {
    function MapPolyfill() {
        this.data = {};
    }
    MapPolyfill.prototype["delete"] = function (key) {
        var existed = this.has(key);
        if (existed) {
            delete this.data[key];
        }
        return existed;
    };
    MapPolyfill.prototype.has = function (key) {
        return this.data.hasOwnProperty(key);
    };
    MapPolyfill.prototype.get = function (key) {
        return this.data[key];
    };
    MapPolyfill.prototype.set = function (key, value) {
        this.data[key] = value;
        return this;
    };
    MapPolyfill.prototype.keys = function () {
        return keys(this.data);
    };
    MapPolyfill.prototype.forEach = function (callback) {
        var data = this.data;
        for (var key in data) {
            if (data.hasOwnProperty(key)) {
                callback(data[key], key);
            }
        }
    };
    return MapPolyfill;
}());
var isNativeMapSupported = typeof Map === 'function';
function maybeNativeMap() {
    return (isNativeMapSupported ? new Map() : new MapPolyfill());
}
var HashMap = (function () {
    function HashMap(obj) {
        var isArr = isArray(obj);
        this.data = maybeNativeMap();
        var thisMap = this;
        (obj instanceof HashMap)
            ? obj.each(visit)
            : (obj && each$4(obj, visit));
        function visit(value, key) {
            isArr ? thisMap.set(value, key) : thisMap.set(key, value);
        }
    }
    HashMap.prototype.hasKey = function (key) {
        return this.data.has(key);
    };
    HashMap.prototype.get = function (key) {
        return this.data.get(key);
    };
    HashMap.prototype.set = function (key, value) {
        this.data.set(key, value);
        return value;
    };
    HashMap.prototype.each = function (cb, context) {
        this.data.forEach(function (value, key) {
            cb.call(context, value, key);
        });
    };
    HashMap.prototype.keys = function () {
        var keys = this.data.keys();
        return isNativeMapSupported
            ? Array.from(keys)
            : keys;
    };
    HashMap.prototype.removeKey = function (key) {
        this.data["delete"](key);
    };
    return HashMap;
}());
function createHashMap(obj) {
    return new HashMap(obj);
}
function concatArray(a, b) {
    var newArray = new a.constructor(a.length + b.length);
    for (var i = 0; i < a.length; i++) {
        newArray[i] = a[i];
    }
    var offset = a.length;
    for (var i = 0; i < b.length; i++) {
        newArray[i + offset] = b[i];
    }
    return newArray;
}
function createObject(proto, properties) {
    var obj;
    if (Object.create) {
        obj = Object.create(proto);
    }
    else {
        var StyleCtor = function () { };
        StyleCtor.prototype = proto;
        obj = new StyleCtor();
    }
    if (properties) {
        extend(obj, properties);
    }
    return obj;
}
function disableUserSelect(dom) {
    var domStyle = dom.style;
    domStyle.webkitUserSelect = 'none';
    domStyle.userSelect = 'none';
    domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)';
    domStyle['-webkit-touch-callout'] = 'none';
}
function hasOwn(own, prop) {
    return own.hasOwnProperty(prop);
}
function noop() { }
var RADIAN_TO_DEGREE = 180 / Math.PI;

/* Injected with object hook! */

function create$1(x, y) {
    if (x == null) {
        x = 0;
    }
    if (y == null) {
        y = 0;
    }
    return [x, y];
}
function clone$1(v) {
    return [v[0], v[1]];
}
function add(out, v1, v2) {
    out[0] = v1[0] + v2[0];
    out[1] = v1[1] + v2[1];
    return out;
}
function sub(out, v1, v2) {
    out[0] = v1[0] - v2[0];
    out[1] = v1[1] - v2[1];
    return out;
}
function len(v) {
    return Math.sqrt(lenSquare(v));
}
function lenSquare(v) {
    return v[0] * v[0] + v[1] * v[1];
}
function scale$2(out, v, s) {
    out[0] = v[0] * s;
    out[1] = v[1] * s;
    return out;
}
function normalize$1(out, v) {
    var d = len(v);
    if (d === 0) {
        out[0] = 0;
        out[1] = 0;
    }
    else {
        out[0] = v[0] / d;
        out[1] = v[1] / d;
    }
    return out;
}
function distance(v1, v2) {
    return Math.sqrt((v1[0] - v2[0]) * (v1[0] - v2[0])
        + (v1[1] - v2[1]) * (v1[1] - v2[1]));
}
var dist$1 = distance;
function distanceSquare(v1, v2) {
    return (v1[0] - v2[0]) * (v1[0] - v2[0])
        + (v1[1] - v2[1]) * (v1[1] - v2[1]);
}
var distSquare = distanceSquare;
function applyTransform$1(out, v, m) {
    var x = v[0];
    var y = v[1];
    out[0] = m[0] * x + m[2] * y + m[4];
    out[1] = m[1] * x + m[3] * y + m[5];
    return out;
}
function min$1(out, v1, v2) {
    out[0] = Math.min(v1[0], v2[0]);
    out[1] = Math.min(v1[1], v2[1]);
    return out;
}
function max$1(out, v1, v2) {
    out[0] = Math.max(v1[0], v2[0]);
    out[1] = Math.max(v1[1], v2[1]);
    return out;
}

/* Injected with object hook! */

var Param = (function () {
    function Param(target, e) {
        this.target = target;
        this.topTarget = e && e.topTarget;
    }
    return Param;
}());
var Draggable = (function () {
    function Draggable(handler) {
        this.handler = handler;
        handler.on('mousedown', this._dragStart, this);
        handler.on('mousemove', this._drag, this);
        handler.on('mouseup', this._dragEnd, this);
    }
    Draggable.prototype._dragStart = function (e) {
        var draggingTarget = e.target;
        while (draggingTarget && !draggingTarget.draggable) {
            draggingTarget = draggingTarget.parent || draggingTarget.__hostTarget;
        }
        if (draggingTarget) {
            this._draggingTarget = draggingTarget;
            draggingTarget.dragging = true;
            this._x = e.offsetX;
            this._y = e.offsetY;
            this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragstart', e.event);
        }
    };
    Draggable.prototype._drag = function (e) {
        var draggingTarget = this._draggingTarget;
        if (draggingTarget) {
            var x = e.offsetX;
            var y = e.offsetY;
            var dx = x - this._x;
            var dy = y - this._y;
            this._x = x;
            this._y = y;
            draggingTarget.drift(dx, dy, e);
            this.handler.dispatchToElement(new Param(draggingTarget, e), 'drag', e.event);
            var dropTarget = this.handler.findHover(x, y, draggingTarget).target;
            var lastDropTarget = this._dropTarget;
            this._dropTarget = dropTarget;
            if (draggingTarget !== dropTarget) {
                if (lastDropTarget && dropTarget !== lastDropTarget) {
                    this.handler.dispatchToElement(new Param(lastDropTarget, e), 'dragleave', e.event);
                }
                if (dropTarget && dropTarget !== lastDropTarget) {
                    this.handler.dispatchToElement(new Param(dropTarget, e), 'dragenter', e.event);
                }
            }
        }
    };
    Draggable.prototype._dragEnd = function (e) {
        var draggingTarget = this._draggingTarget;
        if (draggingTarget) {
            draggingTarget.dragging = false;
        }
        this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragend', e.event);
        if (this._dropTarget) {
            this.handler.dispatchToElement(new Param(this._dropTarget, e), 'drop', e.event);
        }
        this._draggingTarget = null;
        this._dropTarget = null;
    };
    return Draggable;
}());
const Draggable$1 = Draggable;

/* Injected with object hook! */

var Eventful = (function () {
    function Eventful(eventProcessors) {
        if (eventProcessors) {
            this._$eventProcessor = eventProcessors;
        }
    }
    Eventful.prototype.on = function (event, query, handler, context) {
        if (!this._$handlers) {
            this._$handlers = {};
        }
        var _h = this._$handlers;
        if (typeof query === 'function') {
            context = handler;
            handler = query;
            query = null;
        }
        if (!handler || !event) {
            return this;
        }
        var eventProcessor = this._$eventProcessor;
        if (query != null && eventProcessor && eventProcessor.normalizeQuery) {
            query = eventProcessor.normalizeQuery(query);
        }
        if (!_h[event]) {
            _h[event] = [];
        }
        for (var i = 0; i < _h[event].length; i++) {
            if (_h[event][i].h === handler) {
                return this;
            }
        }
        var wrap = {
            h: handler,
            query: query,
            ctx: (context || this),
            callAtLast: handler.zrEventfulCallAtLast
        };
        var lastIndex = _h[event].length - 1;
        var lastWrap = _h[event][lastIndex];
        (lastWrap && lastWrap.callAtLast)
            ? _h[event].splice(lastIndex, 0, wrap)
            : _h[event].push(wrap);
        return this;
    };
    Eventful.prototype.isSilent = function (eventName) {
        var _h = this._$handlers;
        return !_h || !_h[eventName] || !_h[eventName].length;
    };
    Eventful.prototype.off = function (eventType, handler) {
        var _h = this._$handlers;
        if (!_h) {
            return this;
        }
        if (!eventType) {
            this._$handlers = {};
            return this;
        }
        if (handler) {
            if (_h[eventType]) {
                var newList = [];
                for (var i = 0, l = _h[eventType].length; i < l; i++) {
                    if (_h[eventType][i].h !== handler) {
                        newList.push(_h[eventType][i]);
                    }
                }
                _h[eventType] = newList;
            }
            if (_h[eventType] && _h[eventType].length === 0) {
                delete _h[eventType];
            }
        }
        else {
            delete _h[eventType];
        }
        return this;
    };
    Eventful.prototype.trigger = function (eventType) {
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        if (!this._$handlers) {
            return this;
        }
        var _h = this._$handlers[eventType];
        var eventProcessor = this._$eventProcessor;
        if (_h) {
            var argLen = args.length;
            var len = _h.length;
            for (var i = 0; i < len; i++) {
                var hItem = _h[i];
                if (eventProcessor
                    && eventProcessor.filter
                    && hItem.query != null
                    && !eventProcessor.filter(eventType, hItem.query)) {
                    continue;
                }
                switch (argLen) {
                    case 0:
                        hItem.h.call(hItem.ctx);
                        break;
                    case 1:
                        hItem.h.call(hItem.ctx, args[0]);
                        break;
                    case 2:
                        hItem.h.call(hItem.ctx, args[0], args[1]);
                        break;
                    default:
                        hItem.h.apply(hItem.ctx, args);
                        break;
                }
            }
        }
        eventProcessor && eventProcessor.afterTrigger
            && eventProcessor.afterTrigger(eventType);
        return this;
    };
    Eventful.prototype.triggerWithContext = function (type) {
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        if (!this._$handlers) {
            return this;
        }
        var _h = this._$handlers[type];
        var eventProcessor = this._$eventProcessor;
        if (_h) {
            var argLen = args.length;
            var ctx = args[argLen - 1];
            var len = _h.length;
            for (var i = 0; i < len; i++) {
                var hItem = _h[i];
                if (eventProcessor
                    && eventProcessor.filter
                    && hItem.query != null
                    && !eventProcessor.filter(type, hItem.query)) {
                    continue;
                }
                switch (argLen) {
                    case 0:
                        hItem.h.call(ctx);
                        break;
                    case 1:
                        hItem.h.call(ctx, args[0]);
                        break;
                    case 2:
                        hItem.h.call(ctx, args[0], args[1]);
                        break;
                    default:
                        hItem.h.apply(ctx, args.slice(1, argLen - 1));
                        break;
                }
            }
        }
        eventProcessor && eventProcessor.afterTrigger
            && eventProcessor.afterTrigger(type);
        return this;
    };
    return Eventful;
}());
const Eventful$1 = Eventful;

/* Injected with object hook! */

var LN2 = Math.log(2);
function determinant(rows, rank, rowStart, rowMask, colMask, detCache) {
    var cacheKey = rowMask + '-' + colMask;
    var fullRank = rows.length;
    if (detCache.hasOwnProperty(cacheKey)) {
        return detCache[cacheKey];
    }
    if (rank === 1) {
        var colStart = Math.round(Math.log(((1 << fullRank) - 1) & ~colMask) / LN2);
        return rows[rowStart][colStart];
    }
    var subRowMask = rowMask | (1 << rowStart);
    var subRowStart = rowStart + 1;
    while (rowMask & (1 << subRowStart)) {
        subRowStart++;
    }
    var sum = 0;
    for (var j = 0, colLocalIdx = 0; j < fullRank; j++) {
        var colTag = 1 << j;
        if (!(colTag & colMask)) {
            sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j]
                * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache);
            colLocalIdx++;
        }
    }
    detCache[cacheKey] = sum;
    return sum;
}
function buildTransformer(src, dest) {
    var mA = [
        [src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]],
        [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]],
        [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]],
        [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]],
        [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]],
        [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]],
        [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]],
        [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]]
    ];
    var detCache = {};
    var det = determinant(mA, 8, 0, 0, 0, detCache);
    if (det === 0) {
        return;
    }
    var vh = [];
    for (var i = 0; i < 8; i++) {
        for (var j = 0; j < 8; j++) {
            vh[j] == null && (vh[j] = 0);
            vh[j] += ((i + j) % 2 ? -1 : 1)
                * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache)
                / det * dest[i];
        }
    }
    return function (out, srcPointX, srcPointY) {
        var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1;
        out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk;
        out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk;
    };
}

/* Injected with object hook! */

var EVENT_SAVED_PROP = '___zrEVENTSAVED';
var _calcOut$1 = [];
function transformLocalCoord(out, elFrom, elTarget, inX, inY) {
    return transformCoordWithViewport(_calcOut$1, elFrom, inX, inY, true)
        && transformCoordWithViewport(out, elTarget, _calcOut$1[0], _calcOut$1[1]);
}
function transformCoordWithViewport(out, el, inX, inY, inverse) {
    if (el.getBoundingClientRect && env$1.domSupported && !isCanvasEl(el)) {
        var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {});
        var markers = prepareCoordMarkers(el, saved);
        var transformer = preparePointerTransformer(markers, saved, inverse);
        if (transformer) {
            transformer(out, inX, inY);
            return true;
        }
    }
    return false;
}
function prepareCoordMarkers(el, saved) {
    var markers = saved.markers;
    if (markers) {
        return markers;
    }
    markers = saved.markers = [];
    var propLR = ['left', 'right'];
    var propTB = ['top', 'bottom'];
    for (var i = 0; i < 4; i++) {
        var marker = document.createElement('div');
        var stl = marker.style;
        var idxLR = i % 2;
        var idxTB = (i >> 1) % 2;
        stl.cssText = [
            'position: absolute',
            'visibility: hidden',
            'padding: 0',
            'margin: 0',
            'border-width: 0',
            'user-select: none',
            'width:0',
            'height:0',
            propLR[idxLR] + ':0',
            propTB[idxTB] + ':0',
            propLR[1 - idxLR] + ':auto',
            propTB[1 - idxTB] + ':auto',
            ''
        ].join('!important;');
        el.appendChild(marker);
        markers.push(marker);
    }
    return markers;
}
function preparePointerTransformer(markers, saved, inverse) {
    var transformerName = inverse ? 'invTrans' : 'trans';
    var transformer = saved[transformerName];
    var oldSrcCoords = saved.srcCoords;
    var srcCoords = [];
    var destCoords = [];
    var oldCoordTheSame = true;
    for (var i = 0; i < 4; i++) {
        var rect = markers[i].getBoundingClientRect();
        var ii = 2 * i;
        var x = rect.left;
        var y = rect.top;
        srcCoords.push(x, y);
        oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1];
        destCoords.push(markers[i].offsetLeft, markers[i].offsetTop);
    }
    return (oldCoordTheSame && transformer)
        ? transformer
        : (saved.srcCoords = srcCoords,
            saved[transformerName] = inverse
                ? buildTransformer(destCoords, srcCoords)
                : buildTransformer(srcCoords, destCoords));
}
function isCanvasEl(el) {
    return el.nodeName.toUpperCase() === 'CANVAS';
}
var replaceReg = /([&<>"'])/g;
var replaceMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    '\'': '&#39;'
};
function encodeHTML(source) {
    return source == null
        ? ''
        : (source + '').replace(replaceReg, function (str, c) {
            return replaceMap[c];
        });
}

/* Injected with object hook! */

var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/;
var _calcOut = [];
var firefoxNotSupportOffsetXY = env$1.browser.firefox
    && +env$1.browser.version.split('.')[0] < 39;
function clientToLocal(el, e, out, calculate) {
    out = out || {};
    if (calculate) {
        calculateZrXY(el, e, out);
    }
    else if (firefoxNotSupportOffsetXY
        && e.layerX != null
        && e.layerX !== e.offsetX) {
        out.zrX = e.layerX;
        out.zrY = e.layerY;
    }
    else if (e.offsetX != null) {
        out.zrX = e.offsetX;
        out.zrY = e.offsetY;
    }
    else {
        calculateZrXY(el, e, out);
    }
    return out;
}
function calculateZrXY(el, e, out) {
    if (env$1.domSupported && el.getBoundingClientRect) {
        var ex = e.clientX;
        var ey = e.clientY;
        if (isCanvasEl(el)) {
            var box = el.getBoundingClientRect();
            out.zrX = ex - box.left;
            out.zrY = ey - box.top;
            return;
        }
        else {
            if (transformCoordWithViewport(_calcOut, el, ex, ey)) {
                out.zrX = _calcOut[0];
                out.zrY = _calcOut[1];
                return;
            }
        }
    }
    out.zrX = out.zrY = 0;
}
function getNativeEvent(e) {
    return e
        || window.event;
}
function normalizeEvent(el, e, calculate) {
    e = getNativeEvent(e);
    if (e.zrX != null) {
        return e;
    }
    var eventType = e.type;
    var isTouch = eventType && eventType.indexOf('touch') >= 0;
    if (!isTouch) {
        clientToLocal(el, e, e, calculate);
        var wheelDelta = getWheelDeltaMayPolyfill(e);
        e.zrDelta = wheelDelta ? wheelDelta / 120 : -(e.detail || 0) / 3;
    }
    else {
        var touch = eventType !== 'touchend'
            ? e.targetTouches[0]
            : e.changedTouches[0];
        touch && clientToLocal(el, touch, e, calculate);
    }
    var button = e.button;
    if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) {
        e.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0)));
    }
    return e;
}
function getWheelDeltaMayPolyfill(e) {
    var rawWheelDelta = e.wheelDelta;
    if (rawWheelDelta) {
        return rawWheelDelta;
    }
    var deltaX = e.deltaX;
    var deltaY = e.deltaY;
    if (deltaX == null || deltaY == null) {
        return rawWheelDelta;
    }
    var delta = deltaY !== 0 ? Math.abs(deltaY) : Math.abs(deltaX);
    var sign = deltaY > 0 ? -1
        : deltaY < 0 ? 1
            : deltaX > 0 ? -1
                : 1;
    return 3 * delta * sign;
}
function addEventListener(el, name, handler, opt) {
    el.addEventListener(name, handler, opt);
}
function removeEventListener(el, name, handler, opt) {
    el.removeEventListener(name, handler, opt);
}
var stop = function (e) {
    e.preventDefault();
    e.stopPropagation();
    e.cancelBubble = true;
};

/* Injected with object hook! */

var GestureMgr = (function () {
    function GestureMgr() {
        this._track = [];
    }
    GestureMgr.prototype.recognize = function (event, target, root) {
        this._doTrack(event, target, root);
        return this._recognize(event);
    };
    GestureMgr.prototype.clear = function () {
        this._track.length = 0;
        return this;
    };
    GestureMgr.prototype._doTrack = function (event, target, root) {
        var touches = event.touches;
        if (!touches) {
            return;
        }
        var trackItem = {
            points: [],
            touches: [],
            target: target,
            event: event
        };
        for (var i = 0, len = touches.length; i < len; i++) {
            var touch = touches[i];
            var pos = clientToLocal(root, touch, {});
            trackItem.points.push([pos.zrX, pos.zrY]);
            trackItem.touches.push(touch);
        }
        this._track.push(trackItem);
    };
    GestureMgr.prototype._recognize = function (event) {
        for (var eventName in recognizers) {
            if (recognizers.hasOwnProperty(eventName)) {
                var gestureInfo = recognizers[eventName](this._track, event);
                if (gestureInfo) {
                    return gestureInfo;
                }
            }
        }
    };
    return GestureMgr;
}());
function dist(pointPair) {
    var dx = pointPair[1][0] - pointPair[0][0];
    var dy = pointPair[1][1] - pointPair[0][1];
    return Math.sqrt(dx * dx + dy * dy);
}
function center(pointPair) {
    return [
        (pointPair[0][0] + pointPair[1][0]) / 2,
        (pointPair[0][1] + pointPair[1][1]) / 2
    ];
}
var recognizers = {
    pinch: function (tracks, event) {
        var trackLen = tracks.length;
        if (!trackLen) {
            return;
        }
        var pinchEnd = (tracks[trackLen - 1] || {}).points;
        var pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd;
        if (pinchPre
            && pinchPre.length > 1
            && pinchEnd
            && pinchEnd.length > 1) {
            var pinchScale = dist(pinchEnd) / dist(pinchPre);
            !isFinite(pinchScale) && (pinchScale = 1);
            event.pinchScale = pinchScale;
            var pinchCenter = center(pinchEnd);
            event.pinchX = pinchCenter[0];
            event.pinchY = pinchCenter[1];
            return {
                type: 'pinch',
                target: tracks[0].target,
                event: event
            };
        }
    }
};

/* Injected with object hook! */

function create() {
    return [1, 0, 0, 1, 0, 0];
}
function identity(out) {
    out[0] = 1;
    out[1] = 0;
    out[2] = 0;
    out[3] = 1;
    out[4] = 0;
    out[5] = 0;
    return out;
}
function copy(out, m) {
    out[0] = m[0];
    out[1] = m[1];
    out[2] = m[2];
    out[3] = m[3];
    out[4] = m[4];
    out[5] = m[5];
    return out;
}
function mul(out, m1, m2) {
    var out0 = m1[0] * m2[0] + m1[2] * m2[1];
    var out1 = m1[1] * m2[0] + m1[3] * m2[1];
    var out2 = m1[0] * m2[2] + m1[2] * m2[3];
    var out3 = m1[1] * m2[2] + m1[3] * m2[3];
    var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
    var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
    out[0] = out0;
    out[1] = out1;
    out[2] = out2;
    out[3] = out3;
    out[4] = out4;
    out[5] = out5;
    return out;
}
function translate(out, a, v) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[4] = a[4] + v[0];
    out[5] = a[5] + v[1];
    return out;
}
function rotate(out, a, rad) {
    var aa = a[0];
    var ac = a[2];
    var atx = a[4];
    var ab = a[1];
    var ad = a[3];
    var aty = a[5];
    var st = Math.sin(rad);
    var ct = Math.cos(rad);
    out[0] = aa * ct + ab * st;
    out[1] = -aa * st + ab * ct;
    out[2] = ac * ct + ad * st;
    out[3] = -ac * st + ct * ad;
    out[4] = ct * atx + st * aty;
    out[5] = ct * aty - st * atx;
    return out;
}
function scale$1(out, a, v) {
    var vx = v[0];
    var vy = v[1];
    out[0] = a[0] * vx;
    out[1] = a[1] * vy;
    out[2] = a[2] * vx;
    out[3] = a[3] * vy;
    out[4] = a[4] * vx;
    out[5] = a[5] * vy;
    return out;
}
function invert(out, a) {
    var aa = a[0];
    var ac = a[2];
    var atx = a[4];
    var ab = a[1];
    var ad = a[3];
    var aty = a[5];
    var det = aa * ad - ab * ac;
    if (!det) {
        return null;
    }
    det = 1.0 / det;
    out[0] = ad * det;
    out[1] = -ab * det;
    out[2] = -ac * det;
    out[3] = aa * det;
    out[4] = (ac * aty - ad * atx) * det;
    out[5] = (ab * atx - aa * aty) * det;
    return out;
}

/* Injected with object hook! */

var Point = (function () {
    function Point(x, y) {
        this.x = x || 0;
        this.y = y || 0;
    }
    Point.prototype.copy = function (other) {
        this.x = other.x;
        this.y = other.y;
        return this;
    };
    Point.prototype.clone = function () {
        return new Point(this.x, this.y);
    };
    Point.prototype.set = function (x, y) {
        this.x = x;
        this.y = y;
        return this;
    };
    Point.prototype.equal = function (other) {
        return other.x === this.x && other.y === this.y;
    };
    Point.prototype.add = function (other) {
        this.x += other.x;
        this.y += other.y;
        return this;
    };
    Point.prototype.scale = function (scalar) {
        this.x *= scalar;
        this.y *= scalar;
    };
    Point.prototype.scaleAndAdd = function (other, scalar) {
        this.x += other.x * scalar;
        this.y += other.y * scalar;
    };
    Point.prototype.sub = function (other) {
        this.x -= other.x;
        this.y -= other.y;
        return this;
    };
    Point.prototype.dot = function (other) {
        return this.x * other.x + this.y * other.y;
    };
    Point.prototype.len = function () {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    };
    Point.prototype.lenSquare = function () {
        return this.x * this.x + this.y * this.y;
    };
    Point.prototype.normalize = function () {
        var len = this.len();
        this.x /= len;
        this.y /= len;
        return this;
    };
    Point.prototype.distance = function (other) {
        var dx = this.x - other.x;
        var dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    };
    Point.prototype.distanceSquare = function (other) {
        var dx = this.x - other.x;
        var dy = this.y - other.y;
        return dx * dx + dy * dy;
    };
    Point.prototype.negate = function () {
        this.x = -this.x;
        this.y = -this.y;
        return this;
    };
    Point.prototype.transform = function (m) {
        if (!m) {
            return;
        }
        var x = this.x;
        var y = this.y;
        this.x = m[0] * x + m[2] * y + m[4];
        this.y = m[1] * x + m[3] * y + m[5];
        return this;
    };
    Point.prototype.toArray = function (out) {
        out[0] = this.x;
        out[1] = this.y;
        return out;
    };
    Point.prototype.fromArray = function (input) {
        this.x = input[0];
        this.y = input[1];
    };
    Point.set = function (p, x, y) {
        p.x = x;
        p.y = y;
    };
    Point.copy = function (p, p2) {
        p.x = p2.x;
        p.y = p2.y;
    };
    Point.len = function (p) {
        return Math.sqrt(p.x * p.x + p.y * p.y);
    };
    Point.lenSquare = function (p) {
        return p.x * p.x + p.y * p.y;
    };
    Point.dot = function (p0, p1) {
        return p0.x * p1.x + p0.y * p1.y;
    };
    Point.add = function (out, p0, p1) {
        out.x = p0.x + p1.x;
        out.y = p0.y + p1.y;
    };
    Point.sub = function (out, p0, p1) {
        out.x = p0.x - p1.x;
        out.y = p0.y - p1.y;
    };
    Point.scale = function (out, p0, scalar) {
        out.x = p0.x * scalar;
        out.y = p0.y * scalar;
    };
    Point.scaleAndAdd = function (out, p0, p1, scalar) {
        out.x = p0.x + p1.x * scalar;
        out.y = p0.y + p1.y * scalar;
    };
    Point.lerp = function (out, p0, p1, t) {
        var onet = 1 - t;
        out.x = onet * p0.x + t * p1.x;
        out.y = onet * p0.y + t * p1.y;
    };
    return Point;
}());
const Point$1 = Point;

/* Injected with object hook! */

var mathMin$5 = Math.min;
var mathMax$5 = Math.max;
var lt = new Point$1();
var rb = new Point$1();
var lb = new Point$1();
var rt = new Point$1();
var minTv$1 = new Point$1();
var maxTv$1 = new Point$1();
var BoundingRect = (function () {
    function BoundingRect(x, y, width, height) {
        if (width < 0) {
            x = x + width;
            width = -width;
        }
        if (height < 0) {
            y = y + height;
            height = -height;
        }
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
    BoundingRect.prototype.union = function (other) {
        var x = mathMin$5(other.x, this.x);
        var y = mathMin$5(other.y, this.y);
        if (isFinite(this.x) && isFinite(this.width)) {
            this.width = mathMax$5(other.x + other.width, this.x + this.width) - x;
        }
        else {
            this.width = other.width;
        }
        if (isFinite(this.y) && isFinite(this.height)) {
            this.height = mathMax$5(other.y + other.height, this.y + this.height) - y;
        }
        else {
            this.height = other.height;
        }
        this.x = x;
        this.y = y;
    };
    BoundingRect.prototype.applyTransform = function (m) {
        BoundingRect.applyTransform(this, this, m);
    };
    BoundingRect.prototype.calculateTransform = function (b) {
        var a = this;
        var sx = b.width / a.width;
        var sy = b.height / a.height;
        var m = create();
        translate(m, m, [-a.x, -a.y]);
        scale$1(m, m, [sx, sy]);
        translate(m, m, [b.x, b.y]);
        return m;
    };
    BoundingRect.prototype.intersect = function (b, mtv) {
        if (!b) {
            return false;
        }
        if (!(b instanceof BoundingRect)) {
            b = BoundingRect.create(b);
        }
        var a = this;
        var ax0 = a.x;
        var ax1 = a.x + a.width;
        var ay0 = a.y;
        var ay1 = a.y + a.height;
        var bx0 = b.x;
        var bx1 = b.x + b.width;
        var by0 = b.y;
        var by1 = b.y + b.height;
        var overlap = !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
        if (mtv) {
            var dMin = Infinity;
            var dMax = 0;
            var d0 = Math.abs(ax1 - bx0);
            var d1 = Math.abs(bx1 - ax0);
            var d2 = Math.abs(ay1 - by0);
            var d3 = Math.abs(by1 - ay0);
            var dx = Math.min(d0, d1);
            var dy = Math.min(d2, d3);
            if (ax1 < bx0 || bx1 < ax0) {
                if (dx > dMax) {
                    dMax = dx;
                    if (d0 < d1) {
                        Point$1.set(maxTv$1, -d0, 0);
                    }
                    else {
                        Point$1.set(maxTv$1, d1, 0);
                    }
                }
            }
            else {
                if (dx < dMin) {
                    dMin = dx;
                    if (d0 < d1) {
                        Point$1.set(minTv$1, d0, 0);
                    }
                    else {
                        Point$1.set(minTv$1, -d1, 0);
                    }
                }
            }
            if (ay1 < by0 || by1 < ay0) {
                if (dy > dMax) {
                    dMax = dy;
                    if (d2 < d3) {
                        Point$1.set(maxTv$1, 0, -d2);
                    }
                    else {
                        Point$1.set(maxTv$1, 0, d3);
                    }
                }
            }
            else {
                if (dx < dMin) {
                    dMin = dx;
                    if (d2 < d3) {
                        Point$1.set(minTv$1, 0, d2);
                    }
                    else {
                        Point$1.set(minTv$1, 0, -d3);
                    }
                }
            }
        }
        if (mtv) {
            Point$1.copy(mtv, overlap ? minTv$1 : maxTv$1);
        }
        return overlap;
    };
    BoundingRect.prototype.contain = function (x, y) {
        var rect = this;
        return x >= rect.x
            && x <= (rect.x + rect.width)
            && y >= rect.y
            && y <= (rect.y + rect.height);
    };
    BoundingRect.prototype.clone = function () {
        return new BoundingRect(this.x, this.y, this.width, this.height);
    };
    BoundingRect.prototype.copy = function (other) {
        BoundingRect.copy(this, other);
    };
    BoundingRect.prototype.plain = function () {
        return {
            x: this.x,
            y: this.y,
            width: this.width,
            height: this.height
        };
    };
    BoundingRect.prototype.isFinite = function () {
        return isFinite(this.x)
            && isFinite(this.y)
            && isFinite(this.width)
            && isFinite(this.height);
    };
    BoundingRect.prototype.isZero = function () {
        return this.width === 0 || this.height === 0;
    };
    BoundingRect.create = function (rect) {
        return new BoundingRect(rect.x, rect.y, rect.width, rect.height);
    };
    BoundingRect.copy = function (target, source) {
        target.x = source.x;
        target.y = source.y;
        target.width = source.width;
        target.height = source.height;
    };
    BoundingRect.applyTransform = function (target, source, m) {
        if (!m) {
            if (target !== source) {
                BoundingRect.copy(target, source);
            }
            return;
        }
        if (m[1] < 1e-5 && m[1] > -1e-5 && m[2] < 1e-5 && m[2] > -1e-5) {
            var sx = m[0];
            var sy = m[3];
            var tx = m[4];
            var ty = m[5];
            target.x = source.x * sx + tx;
            target.y = source.y * sy + ty;
            target.width = source.width * sx;
            target.height = source.height * sy;
            if (target.width < 0) {
                target.x += target.width;
                target.width = -target.width;
            }
            if (target.height < 0) {
                target.y += target.height;
                target.height = -target.height;
            }
            return;
        }
        lt.x = lb.x = source.x;
        lt.y = rt.y = source.y;
        rb.x = rt.x = source.x + source.width;
        rb.y = lb.y = source.y + source.height;
        lt.transform(m);
        rt.transform(m);
        rb.transform(m);
        lb.transform(m);
        target.x = mathMin$5(lt.x, rb.x, lb.x, rt.x);
        target.y = mathMin$5(lt.y, rb.y, lb.y, rt.y);
        var maxX = mathMax$5(lt.x, rb.x, lb.x, rt.x);
        var maxY = mathMax$5(lt.y, rb.y, lb.y, rt.y);
        target.width = maxX - target.x;
        target.height = maxY - target.y;
    };
    return BoundingRect;
}());
const BoundingRect$1 = BoundingRect;

/* Injected with object hook! */

var SILENT = 'silent';
function makeEventPacket(eveType, targetInfo, event) {
    return {
        type: eveType,
        event: event,
        target: targetInfo.target,
        topTarget: targetInfo.topTarget,
        cancelBubble: false,
        offsetX: event.zrX,
        offsetY: event.zrY,
        gestureEvent: event.gestureEvent,
        pinchX: event.pinchX,
        pinchY: event.pinchY,
        pinchScale: event.pinchScale,
        wheelDelta: event.zrDelta,
        zrByTouch: event.zrByTouch,
        which: event.which,
        stop: stopEvent
    };
}
function stopEvent() {
    stop(this.event);
}
var EmptyProxy = (function (_super) {
    __extends(EmptyProxy, _super);
    function EmptyProxy() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.handler = null;
        return _this;
    }
    EmptyProxy.prototype.dispose = function () { };
    EmptyProxy.prototype.setCursor = function () { };
    return EmptyProxy;
}(Eventful$1));
var HoveredResult = (function () {
    function HoveredResult(x, y) {
        this.x = x;
        this.y = y;
    }
    return HoveredResult;
}());
var handlerNames = [
    'click', 'dblclick', 'mousewheel', 'mouseout',
    'mouseup', 'mousedown', 'mousemove', 'contextmenu'
];
var tmpRect$1 = new BoundingRect$1(0, 0, 0, 0);
var Handler = (function (_super) {
    __extends(Handler, _super);
    function Handler(storage, painter, proxy, painterRoot, pointerSize) {
        var _this = _super.call(this) || this;
        _this._hovered = new HoveredResult(0, 0);
        _this.storage = storage;
        _this.painter = painter;
        _this.painterRoot = painterRoot;
        _this._pointerSize = pointerSize;
        proxy = proxy || new EmptyProxy();
        _this.proxy = null;
        _this.setHandlerProxy(proxy);
        _this._draggingMgr = new Draggable$1(_this);
        return _this;
    }
    Handler.prototype.setHandlerProxy = function (proxy) {
        if (this.proxy) {
            this.proxy.dispose();
        }
        if (proxy) {
            each$4(handlerNames, function (name) {
                proxy.on && proxy.on(name, this[name], this);
            }, this);
            proxy.handler = this;
        }
        this.proxy = proxy;
    };
    Handler.prototype.mousemove = function (event) {
        var x = event.zrX;
        var y = event.zrY;
        var isOutside = isOutsideBoundary(this, x, y);
        var lastHovered = this._hovered;
        var lastHoveredTarget = lastHovered.target;
        if (lastHoveredTarget && !lastHoveredTarget.__zr) {
            lastHovered = this.findHover(lastHovered.x, lastHovered.y);
            lastHoveredTarget = lastHovered.target;
        }
        var hovered = this._hovered = isOutside ? new HoveredResult(x, y) : this.findHover(x, y);
        var hoveredTarget = hovered.target;
        var proxy = this.proxy;
        proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default');
        if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) {
            this.dispatchToElement(lastHovered, 'mouseout', event);
        }
        this.dispatchToElement(hovered, 'mousemove', event);
        if (hoveredTarget && hoveredTarget !== lastHoveredTarget) {
            this.dispatchToElement(hovered, 'mouseover', event);
        }
    };
    Handler.prototype.mouseout = function (event) {
        var eventControl = event.zrEventControl;
        if (eventControl !== 'only_globalout') {
            this.dispatchToElement(this._hovered, 'mouseout', event);
        }
        if (eventControl !== 'no_globalout') {
            this.trigger('globalout', { type: 'globalout', event: event });
        }
    };
    Handler.prototype.resize = function () {
        this._hovered = new HoveredResult(0, 0);
    };
    Handler.prototype.dispatch = function (eventName, eventArgs) {
        var handler = this[eventName];
        handler && handler.call(this, eventArgs);
    };
    Handler.prototype.dispose = function () {
        this.proxy.dispose();
        this.storage = null;
        this.proxy = null;
        this.painter = null;
    };
    Handler.prototype.setCursorStyle = function (cursorStyle) {
        var proxy = this.proxy;
        proxy.setCursor && proxy.setCursor(cursorStyle);
    };
    Handler.prototype.dispatchToElement = function (targetInfo, eventName, event) {
        targetInfo = targetInfo || {};
        var el = targetInfo.target;
        if (el && el.silent) {
            return;
        }
        var eventKey = ('on' + eventName);
        var eventPacket = makeEventPacket(eventName, targetInfo, event);
        while (el) {
            el[eventKey]
                && (eventPacket.cancelBubble = !!el[eventKey].call(el, eventPacket));
            el.trigger(eventName, eventPacket);
            el = el.__hostTarget ? el.__hostTarget : el.parent;
            if (eventPacket.cancelBubble) {
                break;
            }
        }
        if (!eventPacket.cancelBubble) {
            this.trigger(eventName, eventPacket);
            if (this.painter && this.painter.eachOtherLayer) {
                this.painter.eachOtherLayer(function (layer) {
                    if (typeof (layer[eventKey]) === 'function') {
                        layer[eventKey].call(layer, eventPacket);
                    }
                    if (layer.trigger) {
                        layer.trigger(eventName, eventPacket);
                    }
                });
            }
        }
    };
    Handler.prototype.findHover = function (x, y, exclude) {
        var list = this.storage.getDisplayList();
        var out = new HoveredResult(x, y);
        setHoverTarget(list, out, x, y, exclude);
        if (this._pointerSize && !out.target) {
            var candidates = [];
            var pointerSize = this._pointerSize;
            var targetSizeHalf = pointerSize / 2;
            var pointerRect = new BoundingRect$1(x - targetSizeHalf, y - targetSizeHalf, pointerSize, pointerSize);
            for (var i = list.length - 1; i >= 0; i--) {
                var el = list[i];
                if (el !== exclude
                    && !el.ignore
                    && !el.ignoreCoarsePointer
                    && (!el.parent || !el.parent.ignoreCoarsePointer)) {
                    tmpRect$1.copy(el.getBoundingRect());
                    if (el.transform) {
                        tmpRect$1.applyTransform(el.transform);
                    }
                    if (tmpRect$1.intersect(pointerRect)) {
                        candidates.push(el);
                    }
                }
            }
            if (candidates.length) {
                var rStep = 4;
                var thetaStep = Math.PI / 12;
                var PI2 = Math.PI * 2;
                for (var r = 0; r < targetSizeHalf; r += rStep) {
                    for (var theta = 0; theta < PI2; theta += thetaStep) {
                        var x1 = x + r * Math.cos(theta);
                        var y1 = y + r * Math.sin(theta);
                        setHoverTarget(candidates, out, x1, y1, exclude);
                        if (out.target) {
                            return out;
                        }
                    }
                }
            }
        }
        return out;
    };
    Handler.prototype.processGesture = function (event, stage) {
        if (!this._gestureMgr) {
            this._gestureMgr = new GestureMgr();
        }
        var gestureMgr = this._gestureMgr;
        stage === 'start' && gestureMgr.clear();
        var gestureInfo = gestureMgr.recognize(event, this.findHover(event.zrX, event.zrY, null).target, this.proxy.dom);
        stage === 'end' && gestureMgr.clear();
        if (gestureInfo) {
            var type = gestureInfo.type;
            event.gestureEvent = type;
            var res = new HoveredResult();
            res.target = gestureInfo.target;
            this.dispatchToElement(res, type, gestureInfo.event);
        }
    };
    return Handler;
}(Eventful$1));
each$4(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
    Handler.prototype[name] = function (event) {
        var x = event.zrX;
        var y = event.zrY;
        var isOutside = isOutsideBoundary(this, x, y);
        var hovered;
        var hoveredTarget;
        if (name !== 'mouseup' || !isOutside) {
            hovered = this.findHover(x, y);
            hoveredTarget = hovered.target;
        }
        if (name === 'mousedown') {
            this._downEl = hoveredTarget;
            this._downPoint = [event.zrX, event.zrY];
            this._upEl = hoveredTarget;
        }
        else if (name === 'mouseup') {
            this._upEl = hoveredTarget;
        }
        else if (name === 'click') {
            if (this._downEl !== this._upEl
                || !this._downPoint
                || dist$1(this._downPoint, [event.zrX, event.zrY]) > 4) {
                return;
            }
            this._downPoint = null;
        }
        this.dispatchToElement(hovered, name, event);
    };
});
function isHover(displayable, x, y) {
    if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) {
        var el = displayable;
        var isSilent = void 0;
        var ignoreClip = false;
        while (el) {
            if (el.ignoreClip) {
                ignoreClip = true;
            }
            if (!ignoreClip) {
                var clipPath = el.getClipPath();
                if (clipPath && !clipPath.contain(x, y)) {
                    return false;
                }
                if (el.silent) {
                    isSilent = true;
                }
            }
            var hostEl = el.__hostTarget;
            el = hostEl ? hostEl : el.parent;
        }
        return isSilent ? SILENT : true;
    }
    return false;
}
function setHoverTarget(list, out, x, y, exclude) {
    for (var i = list.length - 1; i >= 0; i--) {
        var el = list[i];
        var hoverCheckResult = void 0;
        if (el !== exclude
            && !el.ignore
            && (hoverCheckResult = isHover(el, x, y))) {
            !out.topTarget && (out.topTarget = el);
            if (hoverCheckResult !== SILENT) {
                out.target = el;
                break;
            }
        }
    }
}
function isOutsideBoundary(handlerInstance, x, y) {
    var painter = handlerInstance.painter;
    return x < 0 || x > painter.getWidth() || y < 0 || y > painter.getHeight();
}
const Handler$1 = Handler;

/* Injected with object hook! */

var DEFAULT_MIN_MERGE = 32;
var DEFAULT_MIN_GALLOPING = 7;
function minRunLength(n) {
    var r = 0;
    while (n >= DEFAULT_MIN_MERGE) {
        r |= n & 1;
        n >>= 1;
    }
    return n + r;
}
function makeAscendingRun(array, lo, hi, compare) {
    var runHi = lo + 1;
    if (runHi === hi) {
        return 1;
    }
    if (compare(array[runHi++], array[lo]) < 0) {
        while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
            runHi++;
        }
        reverseRun(array, lo, runHi);
    }
    else {
        while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
            runHi++;
        }
    }
    return runHi - lo;
}
function reverseRun(array, lo, hi) {
    hi--;
    while (lo < hi) {
        var t = array[lo];
        array[lo++] = array[hi];
        array[hi--] = t;
    }
}
function binaryInsertionSort(array, lo, hi, start, compare) {
    if (start === lo) {
        start++;
    }
    for (; start < hi; start++) {
        var pivot = array[start];
        var left = lo;
        var right = start;
        var mid;
        while (left < right) {
            mid = left + right >>> 1;
            if (compare(pivot, array[mid]) < 0) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }
        var n = start - left;
        switch (n) {
            case 3:
                array[left + 3] = array[left + 2];
            case 2:
                array[left + 2] = array[left + 1];
            case 1:
                array[left + 1] = array[left];
                break;
            default:
                while (n > 0) {
                    array[left + n] = array[left + n - 1];
                    n--;
                }
        }
        array[left] = pivot;
    }
}
function gallopLeft(value, array, start, length, hint, compare) {
    var lastOffset = 0;
    var maxOffset = 0;
    var offset = 1;
    if (compare(value, array[start + hint]) > 0) {
        maxOffset = length - hint;
        while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;
            if (offset <= 0) {
                offset = maxOffset;
            }
        }
        if (offset > maxOffset) {
            offset = maxOffset;
        }
        lastOffset += hint;
        offset += hint;
    }
    else {
        maxOffset = hint + 1;
        while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;
            if (offset <= 0) {
                offset = maxOffset;
            }
        }
        if (offset > maxOffset) {
            offset = maxOffset;
        }
        var tmp = lastOffset;
        lastOffset = hint - offset;
        offset = hint - tmp;
    }
    lastOffset++;
    while (lastOffset < offset) {
        var m = lastOffset + (offset - lastOffset >>> 1);
        if (compare(value, array[start + m]) > 0) {
            lastOffset = m + 1;
        }
        else {
            offset = m;
        }
    }
    return offset;
}
function gallopRight(value, array, start, length, hint, compare) {
    var lastOffset = 0;
    var maxOffset = 0;
    var offset = 1;
    if (compare(value, array[start + hint]) < 0) {
        maxOffset = hint + 1;
        while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;
            if (offset <= 0) {
                offset = maxOffset;
            }
        }
        if (offset > maxOffset) {
            offset = maxOffset;
        }
        var tmp = lastOffset;
        lastOffset = hint - offset;
        offset = hint - tmp;
    }
    else {
        maxOffset = length - hint;
        while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
            lastOffset = offset;
            offset = (offset << 1) + 1;
            if (offset <= 0) {
                offset = maxOffset;
            }
        }
        if (offset > maxOffset) {
            offset = maxOffset;
        }
        lastOffset += hint;
        offset += hint;
    }
    lastOffset++;
    while (lastOffset < offset) {
        var m = lastOffset + (offset - lastOffset >>> 1);
        if (compare(value, array[start + m]) < 0) {
            offset = m;
        }
        else {
            lastOffset = m + 1;
        }
    }
    return offset;
}
function TimSort(array, compare) {
    var minGallop = DEFAULT_MIN_GALLOPING;
    var runStart;
    var runLength;
    var stackSize = 0;
    array.length;
    var tmp = [];
    runStart = [];
    runLength = [];
    function pushRun(_runStart, _runLength) {
        runStart[stackSize] = _runStart;
        runLength[stackSize] = _runLength;
        stackSize += 1;
    }
    function mergeRuns() {
        while (stackSize > 1) {
            var n = stackSize - 2;
            if ((n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1])
                || (n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1])) {
                if (runLength[n - 1] < runLength[n + 1]) {
                    n--;
                }
            }
            else if (runLength[n] > runLength[n + 1]) {
                break;
            }
            mergeAt(n);
        }
    }
    function forceMergeRuns() {
        while (stackSize > 1) {
            var n = stackSize - 2;
            if (n > 0 && runLength[n - 1] < runLength[n + 1]) {
                n--;
            }
            mergeAt(n);
        }
    }
    function mergeAt(i) {
        var start1 = runStart[i];
        var length1 = runLength[i];
        var start2 = runStart[i + 1];
        var length2 = runLength[i + 1];
        runLength[i] = length1 + length2;
        if (i === stackSize - 3) {
            runStart[i + 1] = runStart[i + 2];
            runLength[i + 1] = runLength[i + 2];
        }
        stackSize--;
        var k = gallopRight(array[start2], array, start1, length1, 0, compare);
        start1 += k;
        length1 -= k;
        if (length1 === 0) {
            return;
        }
        length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
        if (length2 === 0) {
            return;
        }
        if (length1 <= length2) {
            mergeLow(start1, length1, start2, length2);
        }
        else {
            mergeHigh(start1, length1, start2, length2);
        }
    }
    function mergeLow(start1, length1, start2, length2) {
        var i = 0;
        for (i = 0; i < length1; i++) {
            tmp[i] = array[start1 + i];
        }
        var cursor1 = 0;
        var cursor2 = start2;
        var dest = start1;
        array[dest++] = array[cursor2++];
        if (--length2 === 0) {
            for (i = 0; i < length1; i++) {
                array[dest + i] = tmp[cursor1 + i];
            }
            return;
        }
        if (length1 === 1) {
            for (i = 0; i < length2; i++) {
                array[dest + i] = array[cursor2 + i];
            }
            array[dest + length2] = tmp[cursor1];
            return;
        }
        var _minGallop = minGallop;
        var count1;
        var count2;
        var exit;
        while (1) {
            count1 = 0;
            count2 = 0;
            exit = false;
            do {
                if (compare(array[cursor2], tmp[cursor1]) < 0) {
                    array[dest++] = array[cursor2++];
                    count2++;
                    count1 = 0;
                    if (--length2 === 0) {
                        exit = true;
                        break;
                    }
                }
                else {
                    array[dest++] = tmp[cursor1++];
                    count1++;
                    count2 = 0;
                    if (--length1 === 1) {
                        exit = true;
                        break;
                    }
                }
            } while ((count1 | count2) < _minGallop);
            if (exit) {
                break;
            }
            do {
                count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
                if (count1 !== 0) {
                    for (i = 0; i < count1; i++) {
                        array[dest + i] = tmp[cursor1 + i];
                    }
                    dest += count1;
                    cursor1 += count1;
                    length1 -= count1;
                    if (length1 <= 1) {
                        exit = true;
                        break;
                    }
                }
                array[dest++] = array[cursor2++];
                if (--length2 === 0) {
                    exit = true;
                    break;
                }
                count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
                if (count2 !== 0) {
                    for (i = 0; i < count2; i++) {
                        array[dest + i] = array[cursor2 + i];
                    }
                    dest += count2;
                    cursor2 += count2;
                    length2 -= count2;
                    if (length2 === 0) {
                        exit = true;
                        break;
                    }
                }
                array[dest++] = tmp[cursor1++];
                if (--length1 === 1) {
                    exit = true;
                    break;
                }
                _minGallop--;
            } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
            if (exit) {
                break;
            }
            if (_minGallop < 0) {
                _minGallop = 0;
            }
            _minGallop += 2;
        }
        minGallop = _minGallop;
        minGallop < 1 && (minGallop = 1);
        if (length1 === 1) {
            for (i = 0; i < length2; i++) {
                array[dest + i] = array[cursor2 + i];
            }
            array[dest + length2] = tmp[cursor1];
        }
        else if (length1 === 0) {
            throw new Error();
        }
        else {
            for (i = 0; i < length1; i++) {
                array[dest + i] = tmp[cursor1 + i];
            }
        }
    }
    function mergeHigh(start1, length1, start2, length2) {
        var i = 0;
        for (i = 0; i < length2; i++) {
            tmp[i] = array[start2 + i];
        }
        var cursor1 = start1 + length1 - 1;
        var cursor2 = length2 - 1;
        var dest = start2 + length2 - 1;
        var customCursor = 0;
        var customDest = 0;
        array[dest--] = array[cursor1--];
        if (--length1 === 0) {
            customCursor = dest - (length2 - 1);
            for (i = 0; i < length2; i++) {
                array[customCursor + i] = tmp[i];
            }
            return;
        }
        if (length2 === 1) {
            dest -= length1;
            cursor1 -= length1;
            customDest = dest + 1;
            customCursor = cursor1 + 1;
            for (i = length1 - 1; i >= 0; i--) {
                array[customDest + i] = array[customCursor + i];
            }
            array[dest] = tmp[cursor2];
            return;
        }
        var _minGallop = minGallop;
        while (true) {
            var count1 = 0;
            var count2 = 0;
            var exit = false;
            do {
                if (compare(tmp[cursor2], array[cursor1]) < 0) {
                    array[dest--] = array[cursor1--];
                    count1++;
                    count2 = 0;
                    if (--length1 === 0) {
                        exit = true;
                        break;
                    }
                }
                else {
                    array[dest--] = tmp[cursor2--];
                    count2++;
                    count1 = 0;
                    if (--length2 === 1) {
                        exit = true;
                        break;
                    }
                }
            } while ((count1 | count2) < _minGallop);
            if (exit) {
                break;
            }
            do {
                count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
                if (count1 !== 0) {
                    dest -= count1;
                    cursor1 -= count1;
                    length1 -= count1;
                    customDest = dest + 1;
                    customCursor = cursor1 + 1;
                    for (i = count1 - 1; i >= 0; i--) {
                        array[customDest + i] = array[customCursor + i];
                    }
                    if (length1 === 0) {
                        exit = true;
                        break;
                    }
                }
                array[dest--] = tmp[cursor2--];
                if (--length2 === 1) {
                    exit = true;
                    break;
                }
                count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
                if (count2 !== 0) {
                    dest -= count2;
                    cursor2 -= count2;
                    length2 -= count2;
                    customDest = dest + 1;
                    customCursor = cursor2 + 1;
                    for (i = 0; i < count2; i++) {
                        array[customDest + i] = tmp[customCursor + i];
                    }
                    if (length2 <= 1) {
                        exit = true;
                        break;
                    }
                }
                array[dest--] = array[cursor1--];
                if (--length1 === 0) {
                    exit = true;
                    break;
                }
                _minGallop--;
            } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
            if (exit) {
                break;
            }
            if (_minGallop < 0) {
                _minGallop = 0;
            }
            _minGallop += 2;
        }
        minGallop = _minGallop;
        if (minGallop < 1) {
            minGallop = 1;
        }
        if (length2 === 1) {
            dest -= length1;
            cursor1 -= length1;
            customDest = dest + 1;
            customCursor = cursor1 + 1;
            for (i = length1 - 1; i >= 0; i--) {
                array[customDest + i] = array[customCursor + i];
            }
            array[dest] = tmp[cursor2];
        }
        else if (length2 === 0) {
            throw new Error();
        }
        else {
            customCursor = dest - (length2 - 1);
            for (i = 0; i < length2; i++) {
                array[customCursor + i] = tmp[i];
            }
        }
    }
    return {
        mergeRuns: mergeRuns,
        forceMergeRuns: forceMergeRuns,
        pushRun: pushRun
    };
}
function sort(array, compare, lo, hi) {
    if (!lo) {
        lo = 0;
    }
    if (!hi) {
        hi = array.length;
    }
    var remaining = hi - lo;
    if (remaining < 2) {
        return;
    }
    var runLength = 0;
    if (remaining < DEFAULT_MIN_MERGE) {
        runLength = makeAscendingRun(array, lo, hi, compare);
        binaryInsertionSort(array, lo, hi, lo + runLength, compare);
        return;
    }
    var ts = TimSort(array, compare);
    var minRun = minRunLength(remaining);
    do {
        runLength = makeAscendingRun(array, lo, hi, compare);
        if (runLength < minRun) {
            var force = remaining;
            if (force > minRun) {
                force = minRun;
            }
            binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
            runLength = force;
        }
        ts.pushRun(lo, runLength);
        ts.mergeRuns();
        remaining -= runLength;
        lo += runLength;
    } while (remaining !== 0);
    ts.forceMergeRuns();
}

/* Injected with object hook! */

var REDRAW_BIT = 1;
var STYLE_CHANGED_BIT = 2;
var SHAPE_CHANGED_BIT = 4;

/* Injected with object hook! */

var invalidZErrorLogged = false;
function logInvalidZError() {
    if (invalidZErrorLogged) {
        return;
    }
    invalidZErrorLogged = true;
    console.warn('z / z2 / zlevel of displayable is invalid, which may cause unexpected errors');
}
function shapeCompareFunc(a, b) {
    if (a.zlevel === b.zlevel) {
        if (a.z === b.z) {
            return a.z2 - b.z2;
        }
        return a.z - b.z;
    }
    return a.zlevel - b.zlevel;
}
var Storage = (function () {
    function Storage() {
        this._roots = [];
        this._displayList = [];
        this._displayListLen = 0;
        this.displayableSortFunc = shapeCompareFunc;
    }
    Storage.prototype.traverse = function (cb, context) {
        for (var i = 0; i < this._roots.length; i++) {
            this._roots[i].traverse(cb, context);
        }
    };
    Storage.prototype.getDisplayList = function (update, includeIgnore) {
        includeIgnore = includeIgnore || false;
        var displayList = this._displayList;
        if (update || !displayList.length) {
            this.updateDisplayList(includeIgnore);
        }
        return displayList;
    };
    Storage.prototype.updateDisplayList = function (includeIgnore) {
        this._displayListLen = 0;
        var roots = this._roots;
        var displayList = this._displayList;
        for (var i = 0, len = roots.length; i < len; i++) {
            this._updateAndAddDisplayable(roots[i], null, includeIgnore);
        }
        displayList.length = this._displayListLen;
        sort(displayList, shapeCompareFunc);
    };
    Storage.prototype._updateAndAddDisplayable = function (el, clipPaths, includeIgnore) {
        if (el.ignore && !includeIgnore) {
            return;
        }
        el.beforeUpdate();
        el.update();
        el.afterUpdate();
        var userSetClipPath = el.getClipPath();
        if (el.ignoreClip) {
            clipPaths = null;
        }
        else if (userSetClipPath) {
            if (clipPaths) {
                clipPaths = clipPaths.slice();
            }
            else {
                clipPaths = [];
            }
            var currentClipPath = userSetClipPath;
            var parentClipPath = el;
            while (currentClipPath) {
                currentClipPath.parent = parentClipPath;
                currentClipPath.updateTransform();
                clipPaths.push(currentClipPath);
                parentClipPath = currentClipPath;
                currentClipPath = currentClipPath.getClipPath();
            }
        }
        if (el.childrenRef) {
            var children = el.childrenRef();
            for (var i = 0; i < children.length; i++) {
                var child = children[i];
                if (el.__dirty) {
                    child.__dirty |= REDRAW_BIT;
                }
                this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
            }
            el.__dirty = 0;
        }
        else {
            var disp = el;
            if (clipPaths && clipPaths.length) {
                disp.__clipPaths = clipPaths;
            }
            else if (disp.__clipPaths && disp.__clipPaths.length > 0) {
                disp.__clipPaths = [];
            }
            if (isNaN(disp.z)) {
                logInvalidZError();
                disp.z = 0;
            }
            if (isNaN(disp.z2)) {
                logInvalidZError();
                disp.z2 = 0;
            }
            if (isNaN(disp.zlevel)) {
                logInvalidZError();
                disp.zlevel = 0;
            }
            this._displayList[this._displayListLen++] = disp;
        }
        var decalEl = el.getDecalElement && el.getDecalElement();
        if (decalEl) {
            this._updateAndAddDisplayable(decalEl, clipPaths, includeIgnore);
        }
        var textGuide = el.getTextGuideLine();
        if (textGuide) {
            this._updateAndAddDisplayable(textGuide, clipPaths, includeIgnore);
        }
        var textEl = el.getTextContent();
        if (textEl) {
            this._updateAndAddDisplayable(textEl, clipPaths, includeIgnore);
        }
    };
    Storage.prototype.addRoot = function (el) {
        if (el.__zr && el.__zr.storage === this) {
            return;
        }
        this._roots.push(el);
    };
    Storage.prototype.delRoot = function (el) {
        if (el instanceof Array) {
            for (var i = 0, l = el.length; i < l; i++) {
                this.delRoot(el[i]);
            }
            return;
        }
        var idx = indexOf(this._roots, el);
        if (idx >= 0) {
            this._roots.splice(idx, 1);
        }
    };
    Storage.prototype.delAllRoots = function () {
        this._roots = [];
        this._displayList = [];
        this._displayListLen = 0;
        return;
    };
    Storage.prototype.getRoots = function () {
        return this._roots;
    };
    Storage.prototype.dispose = function () {
        this._displayList = null;
        this._roots = null;
    };
    return Storage;
}());
const Storage$1 = Storage;

/* Injected with object hook! */

var requestAnimationFrame$1;
requestAnimationFrame$1 = (env$1.hasGlobalWindow
    && ((window.requestAnimationFrame && window.requestAnimationFrame.bind(window))
        || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window))
        || window.mozRequestAnimationFrame
        || window.webkitRequestAnimationFrame)) || function (func) {
    return setTimeout(func, 16);
};
const requestAnimationFrame$2 = requestAnimationFrame$1;

/* Injected with object hook! */

var easingFuncs = {
    linear: function (k) {
        return k;
    },
    quadraticIn: function (k) {
        return k * k;
    },
    quadraticOut: function (k) {
        return k * (2 - k);
    },
    quadraticInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k;
        }
        return -0.5 * (--k * (k - 2) - 1);
    },
    cubicIn: function (k) {
        return k * k * k;
    },
    cubicOut: function (k) {
        return --k * k * k + 1;
    },
    cubicInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k * k;
        }
        return 0.5 * ((k -= 2) * k * k + 2);
    },
    quarticIn: function (k) {
        return k * k * k * k;
    },
    quarticOut: function (k) {
        return 1 - (--k * k * k * k);
    },
    quarticInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k * k * k;
        }
        return -0.5 * ((k -= 2) * k * k * k - 2);
    },
    quinticIn: function (k) {
        return k * k * k * k * k;
    },
    quinticOut: function (k) {
        return --k * k * k * k * k + 1;
    },
    quinticInOut: function (k) {
        if ((k *= 2) < 1) {
            return 0.5 * k * k * k * k * k;
        }
        return 0.5 * ((k -= 2) * k * k * k * k + 2);
    },
    sinusoidalIn: function (k) {
        return 1 - Math.cos(k * Math.PI / 2);
    },
    sinusoidalOut: function (k) {
        return Math.sin(k * Math.PI / 2);
    },
    sinusoidalInOut: function (k) {
        return 0.5 * (1 - Math.cos(Math.PI * k));
    },
    exponentialIn: function (k) {
        return k === 0 ? 0 : Math.pow(1024, k - 1);
    },
    exponentialOut: function (k) {
        return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
    },
    exponentialInOut: function (k) {
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if ((k *= 2) < 1) {
            return 0.5 * Math.pow(1024, k - 1);
        }
        return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
    },
    circularIn: function (k) {
        return 1 - Math.sqrt(1 - k * k);
    },
    circularOut: function (k) {
        return Math.sqrt(1 - (--k * k));
    },
    circularInOut: function (k) {
        if ((k *= 2) < 1) {
            return -0.5 * (Math.sqrt(1 - k * k) - 1);
        }
        return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
    },
    elasticIn: function (k) {
        var s;
        var a = 0.1;
        var p = 0.4;
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if (!a || a < 1) {
            a = 1;
            s = p / 4;
        }
        else {
            s = p * Math.asin(1 / a) / (2 * Math.PI);
        }
        return -(a * Math.pow(2, 10 * (k -= 1))
            * Math.sin((k - s) * (2 * Math.PI) / p));
    },
    elasticOut: function (k) {
        var s;
        var a = 0.1;
        var p = 0.4;
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if (!a || a < 1) {
            a = 1;
            s = p / 4;
        }
        else {
            s = p * Math.asin(1 / a) / (2 * Math.PI);
        }
        return (a * Math.pow(2, -10 * k)
            * Math.sin((k - s) * (2 * Math.PI) / p) + 1);
    },
    elasticInOut: function (k) {
        var s;
        var a = 0.1;
        var p = 0.4;
        if (k === 0) {
            return 0;
        }
        if (k === 1) {
            return 1;
        }
        if (!a || a < 1) {
            a = 1;
            s = p / 4;
        }
        else {
            s = p * Math.asin(1 / a) / (2 * Math.PI);
        }
        if ((k *= 2) < 1) {
            return -0.5 * (a * Math.pow(2, 10 * (k -= 1))
                * Math.sin((k - s) * (2 * Math.PI) / p));
        }
        return a * Math.pow(2, -10 * (k -= 1))
            * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;
    },
    backIn: function (k) {
        var s = 1.70158;
        return k * k * ((s + 1) * k - s);
    },
    backOut: function (k) {
        var s = 1.70158;
        return --k * k * ((s + 1) * k + s) + 1;
    },
    backInOut: function (k) {
        var s = 1.70158 * 1.525;
        if ((k *= 2) < 1) {
            return 0.5 * (k * k * ((s + 1) * k - s));
        }
        return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
    },
    bounceIn: function (k) {
        return 1 - easingFuncs.bounceOut(1 - k);
    },
    bounceOut: function (k) {
        if (k < (1 / 2.75)) {
            return 7.5625 * k * k;
        }
        else if (k < (2 / 2.75)) {
            return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
        }
        else if (k < (2.5 / 2.75)) {
            return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
        }
        else {
            return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
        }
    },
    bounceInOut: function (k) {
        if (k < 0.5) {
            return easingFuncs.bounceIn(k * 2) * 0.5;
        }
        return easingFuncs.bounceOut(k * 2 - 1) * 0.5 + 0.5;
    }
};
const easingFuncs$1 = easingFuncs;

/* Injected with object hook! */

var mathPow$1 = Math.pow;
var mathSqrt$3 = Math.sqrt;
var EPSILON$2 = 1e-8;
var EPSILON_NUMERIC = 1e-4;
var THREE_SQRT = mathSqrt$3(3);
var ONE_THIRD = 1 / 3;
var _v0 = create$1();
var _v1 = create$1();
var _v2 = create$1();
function isAroundZero(val) {
    return val > -EPSILON$2 && val < EPSILON$2;
}
function isNotAroundZero$1(val) {
    return val > EPSILON$2 || val < -EPSILON$2;
}
function cubicAt(p0, p1, p2, p3, t) {
    var onet = 1 - t;
    return onet * onet * (onet * p0 + 3 * t * p1)
        + t * t * (t * p3 + 3 * onet * p2);
}
function cubicDerivativeAt(p0, p1, p2, p3, t) {
    var onet = 1 - t;
    return 3 * (((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet
        + (p3 - p2) * t * t);
}
function cubicRootAt(p0, p1, p2, p3, val, roots) {
    var a = p3 + 3 * (p1 - p2) - p0;
    var b = 3 * (p2 - p1 * 2 + p0);
    var c = 3 * (p1 - p0);
    var d = p0 - val;
    var A = b * b - 3 * a * c;
    var B = b * c - 9 * a * d;
    var C = c * c - 3 * b * d;
    var n = 0;
    if (isAroundZero(A) && isAroundZero(B)) {
        if (isAroundZero(b)) {
            roots[0] = 0;
        }
        else {
            var t1 = -c / b;
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
    }
    else {
        var disc = B * B - 4 * A * C;
        if (isAroundZero(disc)) {
            var K = B / A;
            var t1 = -b / a + K;
            var t2 = -K / 2;
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                roots[n++] = t2;
            }
        }
        else if (disc > 0) {
            var discSqrt = mathSqrt$3(disc);
            var Y1 = A * b + 1.5 * a * (-B + discSqrt);
            var Y2 = A * b + 1.5 * a * (-B - discSqrt);
            if (Y1 < 0) {
                Y1 = -mathPow$1(-Y1, ONE_THIRD);
            }
            else {
                Y1 = mathPow$1(Y1, ONE_THIRD);
            }
            if (Y2 < 0) {
                Y2 = -mathPow$1(-Y2, ONE_THIRD);
            }
            else {
                Y2 = mathPow$1(Y2, ONE_THIRD);
            }
            var t1 = (-b - (Y1 + Y2)) / (3 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
        else {
            var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt$3(A * A * A));
            var theta = Math.acos(T) / 3;
            var ASqrt = mathSqrt$3(A);
            var tmp = Math.cos(theta);
            var t1 = (-b - 2 * ASqrt * tmp) / (3 * a);
            var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a);
            var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                roots[n++] = t2;
            }
            if (t3 >= 0 && t3 <= 1) {
                roots[n++] = t3;
            }
        }
    }
    return n;
}
function cubicExtrema(p0, p1, p2, p3, extrema) {
    var b = 6 * p2 - 12 * p1 + 6 * p0;
    var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2;
    var c = 3 * p1 - 3 * p0;
    var n = 0;
    if (isAroundZero(a)) {
        if (isNotAroundZero$1(b)) {
            var t1 = -c / b;
            if (t1 >= 0 && t1 <= 1) {
                extrema[n++] = t1;
            }
        }
    }
    else {
        var disc = b * b - 4 * a * c;
        if (isAroundZero(disc)) {
            extrema[0] = -b / (2 * a);
        }
        else if (disc > 0) {
            var discSqrt = mathSqrt$3(disc);
            var t1 = (-b + discSqrt) / (2 * a);
            var t2 = (-b - discSqrt) / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                extrema[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                extrema[n++] = t2;
            }
        }
    }
    return n;
}
function cubicSubdivide(p0, p1, p2, p3, t, out) {
    var p01 = (p1 - p0) * t + p0;
    var p12 = (p2 - p1) * t + p1;
    var p23 = (p3 - p2) * t + p2;
    var p012 = (p12 - p01) * t + p01;
    var p123 = (p23 - p12) * t + p12;
    var p0123 = (p123 - p012) * t + p012;
    out[0] = p0;
    out[1] = p01;
    out[2] = p012;
    out[3] = p0123;
    out[4] = p0123;
    out[5] = p123;
    out[6] = p23;
    out[7] = p3;
}
function cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, out) {
    var t;
    var interval = 0.005;
    var d = Infinity;
    var prev;
    var next;
    var d1;
    var d2;
    _v0[0] = x;
    _v0[1] = y;
    for (var _t = 0; _t < 1; _t += 0.05) {
        _v1[0] = cubicAt(x0, x1, x2, x3, _t);
        _v1[1] = cubicAt(y0, y1, y2, y3, _t);
        d1 = distSquare(_v0, _v1);
        if (d1 < d) {
            t = _t;
            d = d1;
        }
    }
    d = Infinity;
    for (var i = 0; i < 32; i++) {
        if (interval < EPSILON_NUMERIC) {
            break;
        }
        prev = t - interval;
        next = t + interval;
        _v1[0] = cubicAt(x0, x1, x2, x3, prev);
        _v1[1] = cubicAt(y0, y1, y2, y3, prev);
        d1 = distSquare(_v1, _v0);
        if (prev >= 0 && d1 < d) {
            t = prev;
            d = d1;
        }
        else {
            _v2[0] = cubicAt(x0, x1, x2, x3, next);
            _v2[1] = cubicAt(y0, y1, y2, y3, next);
            d2 = distSquare(_v2, _v0);
            if (next <= 1 && d2 < d) {
                t = next;
                d = d2;
            }
            else {
                interval *= 0.5;
            }
        }
    }
    if (out) {
        out[0] = cubicAt(x0, x1, x2, x3, t);
        out[1] = cubicAt(y0, y1, y2, y3, t);
    }
    return mathSqrt$3(d);
}
function cubicLength(x0, y0, x1, y1, x2, y2, x3, y3, iteration) {
    var px = x0;
    var py = y0;
    var d = 0;
    var step = 1 / iteration;
    for (var i = 1; i <= iteration; i++) {
        var t = i * step;
        var x = cubicAt(x0, x1, x2, x3, t);
        var y = cubicAt(y0, y1, y2, y3, t);
        var dx = x - px;
        var dy = y - py;
        d += Math.sqrt(dx * dx + dy * dy);
        px = x;
        py = y;
    }
    return d;
}
function quadraticAt(p0, p1, p2, t) {
    var onet = 1 - t;
    return onet * (onet * p0 + 2 * t * p1) + t * t * p2;
}
function quadraticDerivativeAt(p0, p1, p2, t) {
    return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1));
}
function quadraticRootAt(p0, p1, p2, val, roots) {
    var a = p0 - 2 * p1 + p2;
    var b = 2 * (p1 - p0);
    var c = p0 - val;
    var n = 0;
    if (isAroundZero(a)) {
        if (isNotAroundZero$1(b)) {
            var t1 = -c / b;
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
    }
    else {
        var disc = b * b - 4 * a * c;
        if (isAroundZero(disc)) {
            var t1 = -b / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
        }
        else if (disc > 0) {
            var discSqrt = mathSqrt$3(disc);
            var t1 = (-b + discSqrt) / (2 * a);
            var t2 = (-b - discSqrt) / (2 * a);
            if (t1 >= 0 && t1 <= 1) {
                roots[n++] = t1;
            }
            if (t2 >= 0 && t2 <= 1) {
                roots[n++] = t2;
            }
        }
    }
    return n;
}
function quadraticExtremum(p0, p1, p2) {
    var divider = p0 + p2 - 2 * p1;
    if (divider === 0) {
        return 0.5;
    }
    else {
        return (p0 - p1) / divider;
    }
}
function quadraticSubdivide(p0, p1, p2, t, out) {
    var p01 = (p1 - p0) * t + p0;
    var p12 = (p2 - p1) * t + p1;
    var p012 = (p12 - p01) * t + p01;
    out[0] = p0;
    out[1] = p01;
    out[2] = p012;
    out[3] = p012;
    out[4] = p12;
    out[5] = p2;
}
function quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, out) {
    var t;
    var interval = 0.005;
    var d = Infinity;
    _v0[0] = x;
    _v0[1] = y;
    for (var _t = 0; _t < 1; _t += 0.05) {
        _v1[0] = quadraticAt(x0, x1, x2, _t);
        _v1[1] = quadraticAt(y0, y1, y2, _t);
        var d1 = distSquare(_v0, _v1);
        if (d1 < d) {
            t = _t;
            d = d1;
        }
    }
    d = Infinity;
    for (var i = 0; i < 32; i++) {
        if (interval < EPSILON_NUMERIC) {
            break;
        }
        var prev = t - interval;
        var next = t + interval;
        _v1[0] = quadraticAt(x0, x1, x2, prev);
        _v1[1] = quadraticAt(y0, y1, y2, prev);
        var d1 = distSquare(_v1, _v0);
        if (prev >= 0 && d1 < d) {
            t = prev;
            d = d1;
        }
        else {
            _v2[0] = quadraticAt(x0, x1, x2, next);
            _v2[1] = quadraticAt(y0, y1, y2, next);
            var d2 = distSquare(_v2, _v0);
            if (next <= 1 && d2 < d) {
                t = next;
                d = d2;
            }
            else {
                interval *= 0.5;
            }
        }
    }
    if (out) {
        out[0] = quadraticAt(x0, x1, x2, t);
        out[1] = quadraticAt(y0, y1, y2, t);
    }
    return mathSqrt$3(d);
}
function quadraticLength(x0, y0, x1, y1, x2, y2, iteration) {
    var px = x0;
    var py = y0;
    var d = 0;
    var step = 1 / iteration;
    for (var i = 1; i <= iteration; i++) {
        var t = i * step;
        var x = quadraticAt(x0, x1, x2, t);
        var y = quadraticAt(y0, y1, y2, t);
        var dx = x - px;
        var dy = y - py;
        d += Math.sqrt(dx * dx + dy * dy);
        px = x;
        py = y;
    }
    return d;
}

/* Injected with object hook! */

var regexp = /cubic-bezier\(([0-9,\.e ]+)\)/;
function createCubicEasingFunc(cubicEasingStr) {
    var cubic = cubicEasingStr && regexp.exec(cubicEasingStr);
    if (cubic) {
        var points = cubic[1].split(',');
        var a_1 = +trim(points[0]);
        var b_1 = +trim(points[1]);
        var c_1 = +trim(points[2]);
        var d_1 = +trim(points[3]);
        if (isNaN(a_1 + b_1 + c_1 + d_1)) {
            return;
        }
        var roots_1 = [];
        return function (p) {
            return p <= 0
                ? 0 : p >= 1
                ? 1
                : cubicRootAt(0, a_1, c_1, 1, p, roots_1) && cubicAt(0, b_1, d_1, 1, roots_1[0]);
        };
    }
}

/* Injected with object hook! */

var Clip = (function () {
    function Clip(opts) {
        this._inited = false;
        this._startTime = 0;
        this._pausedTime = 0;
        this._paused = false;
        this._life = opts.life || 1000;
        this._delay = opts.delay || 0;
        this.loop = opts.loop || false;
        this.onframe = opts.onframe || noop;
        this.ondestroy = opts.ondestroy || noop;
        this.onrestart = opts.onrestart || noop;
        opts.easing && this.setEasing(opts.easing);
    }
    Clip.prototype.step = function (globalTime, deltaTime) {
        if (!this._inited) {
            this._startTime = globalTime + this._delay;
            this._inited = true;
        }
        if (this._paused) {
            this._pausedTime += deltaTime;
            return;
        }
        var life = this._life;
        var elapsedTime = globalTime - this._startTime - this._pausedTime;
        var percent = elapsedTime / life;
        if (percent < 0) {
            percent = 0;
        }
        percent = Math.min(percent, 1);
        var easingFunc = this.easingFunc;
        var schedule = easingFunc ? easingFunc(percent) : percent;
        this.onframe(schedule);
        if (percent === 1) {
            if (this.loop) {
                var remainder = elapsedTime % life;
                this._startTime = globalTime - remainder;
                this._pausedTime = 0;
                this.onrestart();
            }
            else {
                return true;
            }
        }
        return false;
    };
    Clip.prototype.pause = function () {
        this._paused = true;
    };
    Clip.prototype.resume = function () {
        this._paused = false;
    };
    Clip.prototype.setEasing = function (easing) {
        this.easing = easing;
        this.easingFunc = isFunction(easing)
            ? easing
            : easingFuncs$1[easing] || createCubicEasingFunc(easing);
    };
    return Clip;
}());
const Clip$1 = Clip;

/* Injected with object hook! */

var Entry = (function () {
    function Entry(val) {
        this.value = val;
    }
    return Entry;
}());
var LinkedList = (function () {
    function LinkedList() {
        this._len = 0;
    }
    LinkedList.prototype.insert = function (val) {
        var entry = new Entry(val);
        this.insertEntry(entry);
        return entry;
    };
    LinkedList.prototype.insertEntry = function (entry) {
        if (!this.head) {
            this.head = this.tail = entry;
        }
        else {
            this.tail.next = entry;
            entry.prev = this.tail;
            entry.next = null;
            this.tail = entry;
        }
        this._len++;
    };
    LinkedList.prototype.remove = function (entry) {
        var prev = entry.prev;
        var next = entry.next;
        if (prev) {
            prev.next = next;
        }
        else {
            this.head = next;
        }
        if (next) {
            next.prev = prev;
        }
        else {
            this.tail = prev;
        }
        entry.next = entry.prev = null;
        this._len--;
    };
    LinkedList.prototype.len = function () {
        return this._len;
    };
    LinkedList.prototype.clear = function () {
        this.head = this.tail = null;
        this._len = 0;
    };
    return LinkedList;
}());
var LRU = (function () {
    function LRU(maxSize) {
        this._list = new LinkedList();
        this._maxSize = 10;
        this._map = {};
        this._maxSize = maxSize;
    }
    LRU.prototype.put = function (key, value) {
        var list = this._list;
        var map = this._map;
        var removed = null;
        if (map[key] == null) {
            var len = list.len();
            var entry = this._lastRemovedEntry;
            if (len >= this._maxSize && len > 0) {
                var leastUsedEntry = list.head;
                list.remove(leastUsedEntry);
                delete map[leastUsedEntry.key];
                removed = leastUsedEntry.value;
                this._lastRemovedEntry = leastUsedEntry;
            }
            if (entry) {
                entry.value = value;
            }
            else {
                entry = new Entry(value);
            }
            entry.key = key;
            list.insertEntry(entry);
            map[key] = entry;
        }
        return removed;
    };
    LRU.prototype.get = function (key) {
        var entry = this._map[key];
        var list = this._list;
        if (entry != null) {
            if (entry !== list.tail) {
                list.remove(entry);
                list.insertEntry(entry);
            }
            return entry.value;
        }
    };
    LRU.prototype.clear = function () {
        this._list.clear();
        this._map = {};
    };
    LRU.prototype.len = function () {
        return this._list.len();
    };
    return LRU;
}());
const LRU$1 = LRU;

/* Injected with object hook! */

var kCSSColorTable = {
    'transparent': [0, 0, 0, 0], 'aliceblue': [240, 248, 255, 1],
    'antiquewhite': [250, 235, 215, 1], 'aqua': [0, 255, 255, 1],
    'aquamarine': [127, 255, 212, 1], 'azure': [240, 255, 255, 1],
    'beige': [245, 245, 220, 1], 'bisque': [255, 228, 196, 1],
    'black': [0, 0, 0, 1], 'blanchedalmond': [255, 235, 205, 1],
    'blue': [0, 0, 255, 1], 'blueviolet': [138, 43, 226, 1],
    'brown': [165, 42, 42, 1], 'burlywood': [222, 184, 135, 1],
    'cadetblue': [95, 158, 160, 1], 'chartreuse': [127, 255, 0, 1],
    'chocolate': [210, 105, 30, 1], 'coral': [255, 127, 80, 1],
    'cornflowerblue': [100, 149, 237, 1], 'cornsilk': [255, 248, 220, 1],
    'crimson': [220, 20, 60, 1], 'cyan': [0, 255, 255, 1],
    'darkblue': [0, 0, 139, 1], 'darkcyan': [0, 139, 139, 1],
    'darkgoldenrod': [184, 134, 11, 1], 'darkgray': [169, 169, 169, 1],
    'darkgreen': [0, 100, 0, 1], 'darkgrey': [169, 169, 169, 1],
    'darkkhaki': [189, 183, 107, 1], 'darkmagenta': [139, 0, 139, 1],
    'darkolivegreen': [85, 107, 47, 1], 'darkorange': [255, 140, 0, 1],
    'darkorchid': [153, 50, 204, 1], 'darkred': [139, 0, 0, 1],
    'darksalmon': [233, 150, 122, 1], 'darkseagreen': [143, 188, 143, 1],
    'darkslateblue': [72, 61, 139, 1], 'darkslategray': [47, 79, 79, 1],
    'darkslategrey': [47, 79, 79, 1], 'darkturquoise': [0, 206, 209, 1],
    'darkviolet': [148, 0, 211, 1], 'deeppink': [255, 20, 147, 1],
    'deepskyblue': [0, 191, 255, 1], 'dimgray': [105, 105, 105, 1],
    'dimgrey': [105, 105, 105, 1], 'dodgerblue': [30, 144, 255, 1],
    'firebrick': [178, 34, 34, 1], 'floralwhite': [255, 250, 240, 1],
    'forestgreen': [34, 139, 34, 1], 'fuchsia': [255, 0, 255, 1],
    'gainsboro': [220, 220, 220, 1], 'ghostwhite': [248, 248, 255, 1],
    'gold': [255, 215, 0, 1], 'goldenrod': [218, 165, 32, 1],
    'gray': [128, 128, 128, 1], 'green': [0, 128, 0, 1],
    'greenyellow': [173, 255, 47, 1], 'grey': [128, 128, 128, 1],
    'honeydew': [240, 255, 240, 1], 'hotpink': [255, 105, 180, 1],
    'indianred': [205, 92, 92, 1], 'indigo': [75, 0, 130, 1],
    'ivory': [255, 255, 240, 1], 'khaki': [240, 230, 140, 1],
    'lavender': [230, 230, 250, 1], 'lavenderblush': [255, 240, 245, 1],
    'lawngreen': [124, 252, 0, 1], 'lemonchiffon': [255, 250, 205, 1],
    'lightblue': [173, 216, 230, 1], 'lightcoral': [240, 128, 128, 1],
    'lightcyan': [224, 255, 255, 1], 'lightgoldenrodyellow': [250, 250, 210, 1],
    'lightgray': [211, 211, 211, 1], 'lightgreen': [144, 238, 144, 1],
    'lightgrey': [211, 211, 211, 1], 'lightpink': [255, 182, 193, 1],
    'lightsalmon': [255, 160, 122, 1], 'lightseagreen': [32, 178, 170, 1],
    'lightskyblue': [135, 206, 250, 1], 'lightslategray': [119, 136, 153, 1],
    'lightslategrey': [119, 136, 153, 1], 'lightsteelblue': [176, 196, 222, 1],
    'lightyellow': [255, 255, 224, 1], 'lime': [0, 255, 0, 1],
    'limegreen': [50, 205, 50, 1], 'linen': [250, 240, 230, 1],
    'magenta': [255, 0, 255, 1], 'maroon': [128, 0, 0, 1],
    'mediumaquamarine': [102, 205, 170, 1], 'mediumblue': [0, 0, 205, 1],
    'mediumorchid': [186, 85, 211, 1], 'mediumpurple': [147, 112, 219, 1],
    'mediumseagreen': [60, 179, 113, 1], 'mediumslateblue': [123, 104, 238, 1],
    'mediumspringgreen': [0, 250, 154, 1], 'mediumturquoise': [72, 209, 204, 1],
    'mediumvioletred': [199, 21, 133, 1], 'midnightblue': [25, 25, 112, 1],
    'mintcream': [245, 255, 250, 1], 'mistyrose': [255, 228, 225, 1],
    'moccasin': [255, 228, 181, 1], 'navajowhite': [255, 222, 173, 1],
    'navy': [0, 0, 128, 1], 'oldlace': [253, 245, 230, 1],
    'olive': [128, 128, 0, 1], 'olivedrab': [107, 142, 35, 1],
    'orange': [255, 165, 0, 1], 'orangered': [255, 69, 0, 1],
    'orchid': [218, 112, 214, 1], 'palegoldenrod': [238, 232, 170, 1],
    'palegreen': [152, 251, 152, 1], 'paleturquoise': [175, 238, 238, 1],
    'palevioletred': [219, 112, 147, 1], 'papayawhip': [255, 239, 213, 1],
    'peachpuff': [255, 218, 185, 1], 'peru': [205, 133, 63, 1],
    'pink': [255, 192, 203, 1], 'plum': [221, 160, 221, 1],
    'powderblue': [176, 224, 230, 1], 'purple': [128, 0, 128, 1],
    'red': [255, 0, 0, 1], 'rosybrown': [188, 143, 143, 1],
    'royalblue': [65, 105, 225, 1], 'saddlebrown': [139, 69, 19, 1],
    'salmon': [250, 128, 114, 1], 'sandybrown': [244, 164, 96, 1],
    'seagreen': [46, 139, 87, 1], 'seashell': [255, 245, 238, 1],
    'sienna': [160, 82, 45, 1], 'silver': [192, 192, 192, 1],
    'skyblue': [135, 206, 235, 1], 'slateblue': [106, 90, 205, 1],
    'slategray': [112, 128, 144, 1], 'slategrey': [112, 128, 144, 1],
    'snow': [255, 250, 250, 1], 'springgreen': [0, 255, 127, 1],
    'steelblue': [70, 130, 180, 1], 'tan': [210, 180, 140, 1],
    'teal': [0, 128, 128, 1], 'thistle': [216, 191, 216, 1],
    'tomato': [255, 99, 71, 1], 'turquoise': [64, 224, 208, 1],
    'violet': [238, 130, 238, 1], 'wheat': [245, 222, 179, 1],
    'white': [255, 255, 255, 1], 'whitesmoke': [245, 245, 245, 1],
    'yellow': [255, 255, 0, 1], 'yellowgreen': [154, 205, 50, 1]
};
function clampCssByte(i) {
    i = Math.round(i);
    return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clampCssFloat(f) {
    return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parseCssInt(val) {
    var str = val;
    if (str.length && str.charAt(str.length - 1) === '%') {
        return clampCssByte(parseFloat(str) / 100 * 255);
    }
    return clampCssByte(parseInt(str, 10));
}
function parseCssFloat(val) {
    var str = val;
    if (str.length && str.charAt(str.length - 1) === '%') {
        return clampCssFloat(parseFloat(str) / 100);
    }
    return clampCssFloat(parseFloat(str));
}
function cssHueToRgb(m1, m2, h) {
    if (h < 0) {
        h += 1;
    }
    else if (h > 1) {
        h -= 1;
    }
    if (h * 6 < 1) {
        return m1 + (m2 - m1) * h * 6;
    }
    if (h * 2 < 1) {
        return m2;
    }
    if (h * 3 < 2) {
        return m1 + (m2 - m1) * (2 / 3 - h) * 6;
    }
    return m1;
}
function setRgba(out, r, g, b, a) {
    out[0] = r;
    out[1] = g;
    out[2] = b;
    out[3] = a;
    return out;
}
function copyRgba(out, a) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    return out;
}
var colorCache = new LRU$1(20);
var lastRemovedArr = null;
function putToCache(colorStr, rgbaArr) {
    if (lastRemovedArr) {
        copyRgba(lastRemovedArr, rgbaArr);
    }
    lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice()));
}
function parse(colorStr, rgbaArr) {
    if (!colorStr) {
        return;
    }
    rgbaArr = rgbaArr || [];
    var cached = colorCache.get(colorStr);
    if (cached) {
        return copyRgba(rgbaArr, cached);
    }
    colorStr = colorStr + '';
    var str = colorStr.replace(/ /g, '').toLowerCase();
    if (str in kCSSColorTable) {
        copyRgba(rgbaArr, kCSSColorTable[str]);
        putToCache(colorStr, rgbaArr);
        return rgbaArr;
    }
    var strLen = str.length;
    if (str.charAt(0) === '#') {
        if (strLen === 4 || strLen === 5) {
            var iv = parseInt(str.slice(1, 4), 16);
            if (!(iv >= 0 && iv <= 0xfff)) {
                setRgba(rgbaArr, 0, 0, 0, 1);
                return;
            }
            setRgba(rgbaArr, ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), strLen === 5 ? parseInt(str.slice(4), 16) / 0xf : 1);
            putToCache(colorStr, rgbaArr);
            return rgbaArr;
        }
        else if (strLen === 7 || strLen === 9) {
            var iv = parseInt(str.slice(1, 7), 16);
            if (!(iv >= 0 && iv <= 0xffffff)) {
                setRgba(rgbaArr, 0, 0, 0, 1);
                return;
            }
            setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, strLen === 9 ? parseInt(str.slice(7), 16) / 0xff : 1);
            putToCache(colorStr, rgbaArr);
            return rgbaArr;
        }
        return;
    }
    var op = str.indexOf('(');
    var ep = str.indexOf(')');
    if (op !== -1 && ep + 1 === strLen) {
        var fname = str.substr(0, op);
        var params = str.substr(op + 1, ep - (op + 1)).split(',');
        var alpha = 1;
        switch (fname) {
            case 'rgba':
                if (params.length !== 4) {
                    return params.length === 3
                        ? setRgba(rgbaArr, +params[0], +params[1], +params[2], 1)
                        : setRgba(rgbaArr, 0, 0, 0, 1);
                }
                alpha = parseCssFloat(params.pop());
            case 'rgb':
                if (params.length >= 3) {
                    setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), params.length === 3 ? alpha : parseCssFloat(params[3]));
                    putToCache(colorStr, rgbaArr);
                    return rgbaArr;
                }
                else {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
            case 'hsla':
                if (params.length !== 4) {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
                params[3] = parseCssFloat(params[3]);
                hsla2rgba(params, rgbaArr);
                putToCache(colorStr, rgbaArr);
                return rgbaArr;
            case 'hsl':
                if (params.length !== 3) {
                    setRgba(rgbaArr, 0, 0, 0, 1);
                    return;
                }
                hsla2rgba(params, rgbaArr);
                putToCache(colorStr, rgbaArr);
                return rgbaArr;
            default:
                return;
        }
    }
    setRgba(rgbaArr, 0, 0, 0, 1);
    return;
}
function hsla2rgba(hsla, rgba) {
    var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360;
    var s = parseCssFloat(hsla[1]);
    var l = parseCssFloat(hsla[2]);
    var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
    var m1 = l * 2 - m2;
    rgba = rgba || [];
    setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1);
    if (hsla.length === 4) {
        rgba[3] = hsla[3];
    }
    return rgba;
}
function lift(color, level) {
    var colorArr = parse(color);
    if (colorArr) {
        for (var i = 0; i < 3; i++) {
            if (level < 0) {
                colorArr[i] = colorArr[i] * (1 - level) | 0;
            }
            else {
                colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0;
            }
            if (colorArr[i] > 255) {
                colorArr[i] = 255;
            }
            else if (colorArr[i] < 0) {
                colorArr[i] = 0;
            }
        }
        return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb');
    }
}
function stringify(arrColor, type) {
    if (!arrColor || !arrColor.length) {
        return;
    }
    var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2];
    if (type === 'rgba' || type === 'hsva' || type === 'hsla') {
        colorStr += ',' + arrColor[3];
    }
    return type + '(' + colorStr + ')';
}
function lum(color, backgroundLum) {
    var arr = parse(color);
    return arr
        ? (0.299 * arr[0] + 0.587 * arr[1] + 0.114 * arr[2]) * arr[3] / 255
            + (1 - arr[3]) * backgroundLum
        : 0;
}

/* Injected with object hook! */

function isLinearGradient(val) {
    return val.type === 'linear';
}
function isRadialGradient(val) {
    return val.type === 'radial';
}
((function () {
    if (env$1.hasGlobalWindow && isFunction(window.btoa)) {
        return function (str) {
            return window.btoa(unescape(encodeURIComponent(str)));
        };
    }
    if (typeof Buffer !== 'undefined') {
        return function (str) {
            return Buffer.from(str).toString('base64');
        };
    }
    return function (str) {
        return null;
    };
}))();

/* Injected with object hook! */

var arraySlice = Array.prototype.slice;
function interpolateNumber(p0, p1, percent) {
    return (p1 - p0) * percent + p0;
}
function interpolate1DArray(out, p0, p1, percent) {
    var len = p0.length;
    for (var i = 0; i < len; i++) {
        out[i] = interpolateNumber(p0[i], p1[i], percent);
    }
    return out;
}
function interpolate2DArray(out, p0, p1, percent) {
    var len = p0.length;
    var len2 = len && p0[0].length;
    for (var i = 0; i < len; i++) {
        if (!out[i]) {
            out[i] = [];
        }
        for (var j = 0; j < len2; j++) {
            out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent);
        }
    }
    return out;
}
function add1DArray(out, p0, p1, sign) {
    var len = p0.length;
    for (var i = 0; i < len; i++) {
        out[i] = p0[i] + p1[i] * sign;
    }
    return out;
}
function add2DArray(out, p0, p1, sign) {
    var len = p0.length;
    var len2 = len && p0[0].length;
    for (var i = 0; i < len; i++) {
        if (!out[i]) {
            out[i] = [];
        }
        for (var j = 0; j < len2; j++) {
            out[i][j] = p0[i][j] + p1[i][j] * sign;
        }
    }
    return out;
}
function fillColorStops(val0, val1) {
    var len0 = val0.length;
    var len1 = val1.length;
    var shorterArr = len0 > len1 ? val1 : val0;
    var shorterLen = Math.min(len0, len1);
    var last = shorterArr[shorterLen - 1] || { color: [0, 0, 0, 0], offset: 0 };
    for (var i = shorterLen; i < Math.max(len0, len1); i++) {
        shorterArr.push({
            offset: last.offset,
            color: last.color.slice()
        });
    }
}
function fillArray(val0, val1, arrDim) {
    var arr0 = val0;
    var arr1 = val1;
    if (!arr0.push || !arr1.push) {
        return;
    }
    var arr0Len = arr0.length;
    var arr1Len = arr1.length;
    if (arr0Len !== arr1Len) {
        var isPreviousLarger = arr0Len > arr1Len;
        if (isPreviousLarger) {
            arr0.length = arr1Len;
        }
        else {
            for (var i = arr0Len; i < arr1Len; i++) {
                arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i]));
            }
        }
    }
    var len2 = arr0[0] && arr0[0].length;
    for (var i = 0; i < arr0.length; i++) {
        if (arrDim === 1) {
            if (isNaN(arr0[i])) {
                arr0[i] = arr1[i];
            }
        }
        else {
            for (var j = 0; j < len2; j++) {
                if (isNaN(arr0[i][j])) {
                    arr0[i][j] = arr1[i][j];
                }
            }
        }
    }
}
function cloneValue(value) {
    if (isArrayLike(value)) {
        var len = value.length;
        if (isArrayLike(value[0])) {
            var ret = [];
            for (var i = 0; i < len; i++) {
                ret.push(arraySlice.call(value[i]));
            }
            return ret;
        }
        return arraySlice.call(value);
    }
    return value;
}
function rgba2String(rgba) {
    rgba[0] = Math.floor(rgba[0]) || 0;
    rgba[1] = Math.floor(rgba[1]) || 0;
    rgba[2] = Math.floor(rgba[2]) || 0;
    rgba[3] = rgba[3] == null ? 1 : rgba[3];
    return 'rgba(' + rgba.join(',') + ')';
}
function guessArrayDim(value) {
    return isArrayLike(value && value[0]) ? 2 : 1;
}
var VALUE_TYPE_NUMBER = 0;
var VALUE_TYPE_1D_ARRAY = 1;
var VALUE_TYPE_2D_ARRAY = 2;
var VALUE_TYPE_COLOR = 3;
var VALUE_TYPE_LINEAR_GRADIENT = 4;
var VALUE_TYPE_RADIAL_GRADIENT = 5;
var VALUE_TYPE_UNKOWN = 6;
function isGradientValueType(valType) {
    return valType === VALUE_TYPE_LINEAR_GRADIENT || valType === VALUE_TYPE_RADIAL_GRADIENT;
}
function isArrayValueType(valType) {
    return valType === VALUE_TYPE_1D_ARRAY || valType === VALUE_TYPE_2D_ARRAY;
}
var tmpRgba = [0, 0, 0, 0];
var Track = (function () {
    function Track(propName) {
        this.keyframes = [];
        this.discrete = false;
        this._invalid = false;
        this._needsSort = false;
        this._lastFr = 0;
        this._lastFrP = 0;
        this.propName = propName;
    }
    Track.prototype.isFinished = function () {
        return this._finished;
    };
    Track.prototype.setFinished = function () {
        this._finished = true;
        if (this._additiveTrack) {
            this._additiveTrack.setFinished();
        }
    };
    Track.prototype.needsAnimate = function () {
        return this.keyframes.length >= 1;
    };
    Track.prototype.getAdditiveTrack = function () {
        return this._additiveTrack;
    };
    Track.prototype.addKeyframe = function (time, rawValue, easing) {
        this._needsSort = true;
        var keyframes = this.keyframes;
        var len = keyframes.length;
        var discrete = false;
        var valType = VALUE_TYPE_UNKOWN;
        var value = rawValue;
        if (isArrayLike(rawValue)) {
            var arrayDim = guessArrayDim(rawValue);
            valType = arrayDim;
            if (arrayDim === 1 && !isNumber(rawValue[0])
                || arrayDim === 2 && !isNumber(rawValue[0][0])) {
                discrete = true;
            }
        }
        else {
            if (isNumber(rawValue) && !eqNaN(rawValue)) {
                valType = VALUE_TYPE_NUMBER;
            }
            else if (isString(rawValue)) {
                if (!isNaN(+rawValue)) {
                    valType = VALUE_TYPE_NUMBER;
                }
                else {
                    var colorArray = parse(rawValue);
                    if (colorArray) {
                        value = colorArray;
                        valType = VALUE_TYPE_COLOR;
                    }
                }
            }
            else if (isGradientObject(rawValue)) {
                var parsedGradient = extend({}, value);
                parsedGradient.colorStops = map$1(rawValue.colorStops, function (colorStop) { return ({
                    offset: colorStop.offset,
                    color: parse(colorStop.color)
                }); });
                if (isLinearGradient(rawValue)) {
                    valType = VALUE_TYPE_LINEAR_GRADIENT;
                }
                else if (isRadialGradient(rawValue)) {
                    valType = VALUE_TYPE_RADIAL_GRADIENT;
                }
                value = parsedGradient;
            }
        }
        if (len === 0) {
            this.valType = valType;
        }
        else if (valType !== this.valType || valType === VALUE_TYPE_UNKOWN) {
            discrete = true;
        }
        this.discrete = this.discrete || discrete;
        var kf = {
            time: time,
            value: value,
            rawValue: rawValue,
            percent: 0
        };
        if (easing) {
            kf.easing = easing;
            kf.easingFunc = isFunction(easing)
                ? easing
                : easingFuncs$1[easing] || createCubicEasingFunc(easing);
        }
        keyframes.push(kf);
        return kf;
    };
    Track.prototype.prepare = function (maxTime, additiveTrack) {
        var kfs = this.keyframes;
        if (this._needsSort) {
            kfs.sort(function (a, b) {
                return a.time - b.time;
            });
        }
        var valType = this.valType;
        var kfsLen = kfs.length;
        var lastKf = kfs[kfsLen - 1];
        var isDiscrete = this.discrete;
        var isArr = isArrayValueType(valType);
        var isGradient = isGradientValueType(valType);
        for (var i = 0; i < kfsLen; i++) {
            var kf = kfs[i];
            var value = kf.value;
            var lastValue = lastKf.value;
            kf.percent = kf.time / maxTime;
            if (!isDiscrete) {
                if (isArr && i !== kfsLen - 1) {
                    fillArray(value, lastValue, valType);
                }
                else if (isGradient) {
                    fillColorStops(value.colorStops, lastValue.colorStops);
                }
            }
        }
        if (!isDiscrete
            && valType !== VALUE_TYPE_RADIAL_GRADIENT
            && additiveTrack
            && this.needsAnimate()
            && additiveTrack.needsAnimate()
            && valType === additiveTrack.valType
            && !additiveTrack._finished) {
            this._additiveTrack = additiveTrack;
            var startValue = kfs[0].value;
            for (var i = 0; i < kfsLen; i++) {
                if (valType === VALUE_TYPE_NUMBER) {
                    kfs[i].additiveValue = kfs[i].value - startValue;
                }
                else if (valType === VALUE_TYPE_COLOR) {
                    kfs[i].additiveValue =
                        add1DArray([], kfs[i].value, startValue, -1);
                }
                else if (isArrayValueType(valType)) {
                    kfs[i].additiveValue = valType === VALUE_TYPE_1D_ARRAY
                        ? add1DArray([], kfs[i].value, startValue, -1)
                        : add2DArray([], kfs[i].value, startValue, -1);
                }
            }
        }
    };
    Track.prototype.step = function (target, percent) {
        if (this._finished) {
            return;
        }
        if (this._additiveTrack && this._additiveTrack._finished) {
            this._additiveTrack = null;
        }
        var isAdditive = this._additiveTrack != null;
        var valueKey = isAdditive ? 'additiveValue' : 'value';
        var valType = this.valType;
        var keyframes = this.keyframes;
        var kfsNum = keyframes.length;
        var propName = this.propName;
        var isValueColor = valType === VALUE_TYPE_COLOR;
        var frameIdx;
        var lastFrame = this._lastFr;
        var mathMin = Math.min;
        var frame;
        var nextFrame;
        if (kfsNum === 1) {
            frame = nextFrame = keyframes[0];
        }
        else {
            if (percent < 0) {
                frameIdx = 0;
            }
            else if (percent < this._lastFrP) {
                var start = mathMin(lastFrame + 1, kfsNum - 1);
                for (frameIdx = start; frameIdx >= 0; frameIdx--) {
                    if (keyframes[frameIdx].percent <= percent) {
                        break;
                    }
                }
                frameIdx = mathMin(frameIdx, kfsNum - 2);
            }
            else {
                for (frameIdx = lastFrame; frameIdx < kfsNum; frameIdx++) {
                    if (keyframes[frameIdx].percent > percent) {
                        break;
                    }
                }
                frameIdx = mathMin(frameIdx - 1, kfsNum - 2);
            }
            nextFrame = keyframes[frameIdx + 1];
            frame = keyframes[frameIdx];
        }
        if (!(frame && nextFrame)) {
            return;
        }
        this._lastFr = frameIdx;
        this._lastFrP = percent;
        var interval = (nextFrame.percent - frame.percent);
        var w = interval === 0 ? 1 : mathMin((percent - frame.percent) / interval, 1);
        if (nextFrame.easingFunc) {
            w = nextFrame.easingFunc(w);
        }
        var targetArr = isAdditive ? this._additiveValue
            : (isValueColor ? tmpRgba : target[propName]);
        if ((isArrayValueType(valType) || isValueColor) && !targetArr) {
            targetArr = this._additiveValue = [];
        }
        if (this.discrete) {
            target[propName] = w < 1 ? frame.rawValue : nextFrame.rawValue;
        }
        else if (isArrayValueType(valType)) {
            valType === VALUE_TYPE_1D_ARRAY
                ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w)
                : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
        }
        else if (isGradientValueType(valType)) {
            var val = frame[valueKey];
            var nextVal_1 = nextFrame[valueKey];
            var isLinearGradient_1 = valType === VALUE_TYPE_LINEAR_GRADIENT;
            target[propName] = {
                type: isLinearGradient_1 ? 'linear' : 'radial',
                x: interpolateNumber(val.x, nextVal_1.x, w),
                y: interpolateNumber(val.y, nextVal_1.y, w),
                colorStops: map$1(val.colorStops, function (colorStop, idx) {
                    var nextColorStop = nextVal_1.colorStops[idx];
                    return {
                        offset: interpolateNumber(colorStop.offset, nextColorStop.offset, w),
                        color: rgba2String(interpolate1DArray([], colorStop.color, nextColorStop.color, w))
                    };
                }),
                global: nextVal_1.global
            };
            if (isLinearGradient_1) {
                target[propName].x2 = interpolateNumber(val.x2, nextVal_1.x2, w);
                target[propName].y2 = interpolateNumber(val.y2, nextVal_1.y2, w);
            }
            else {
                target[propName].r = interpolateNumber(val.r, nextVal_1.r, w);
            }
        }
        else if (isValueColor) {
            interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w);
            if (!isAdditive) {
                target[propName] = rgba2String(targetArr);
            }
        }
        else {
            var value = interpolateNumber(frame[valueKey], nextFrame[valueKey], w);
            if (isAdditive) {
                this._additiveValue = value;
            }
            else {
                target[propName] = value;
            }
        }
        if (isAdditive) {
            this._addToTarget(target);
        }
    };
    Track.prototype._addToTarget = function (target) {
        var valType = this.valType;
        var propName = this.propName;
        var additiveValue = this._additiveValue;
        if (valType === VALUE_TYPE_NUMBER) {
            target[propName] = target[propName] + additiveValue;
        }
        else if (valType === VALUE_TYPE_COLOR) {
            parse(target[propName], tmpRgba);
            add1DArray(tmpRgba, tmpRgba, additiveValue, 1);
            target[propName] = rgba2String(tmpRgba);
        }
        else if (valType === VALUE_TYPE_1D_ARRAY) {
            add1DArray(target[propName], target[propName], additiveValue, 1);
        }
        else if (valType === VALUE_TYPE_2D_ARRAY) {
            add2DArray(target[propName], target[propName], additiveValue, 1);
        }
    };
    return Track;
}());
var Animator = (function () {
    function Animator(target, loop, allowDiscreteAnimation, additiveTo) {
        this._tracks = {};
        this._trackKeys = [];
        this._maxTime = 0;
        this._started = 0;
        this._clip = null;
        this._target = target;
        this._loop = loop;
        if (loop && additiveTo) {
            logError('Can\' use additive animation on looped animation.');
            return;
        }
        this._additiveAnimators = additiveTo;
        this._allowDiscrete = allowDiscreteAnimation;
    }
    Animator.prototype.getMaxTime = function () {
        return this._maxTime;
    };
    Animator.prototype.getDelay = function () {
        return this._delay;
    };
    Animator.prototype.getLoop = function () {
        return this._loop;
    };
    Animator.prototype.getTarget = function () {
        return this._target;
    };
    Animator.prototype.changeTarget = function (target) {
        this._target = target;
    };
    Animator.prototype.when = function (time, props, easing) {
        return this.whenWithKeys(time, props, keys(props), easing);
    };
    Animator.prototype.whenWithKeys = function (time, props, propNames, easing) {
        var tracks = this._tracks;
        for (var i = 0; i < propNames.length; i++) {
            var propName = propNames[i];
            var track = tracks[propName];
            if (!track) {
                track = tracks[propName] = new Track(propName);
                var initialValue = void 0;
                var additiveTrack = this._getAdditiveTrack(propName);
                if (additiveTrack) {
                    var addtiveTrackKfs = additiveTrack.keyframes;
                    var lastFinalKf = addtiveTrackKfs[addtiveTrackKfs.length - 1];
                    initialValue = lastFinalKf && lastFinalKf.value;
                    if (additiveTrack.valType === VALUE_TYPE_COLOR && initialValue) {
                        initialValue = rgba2String(initialValue);
                    }
                }
                else {
                    initialValue = this._target[propName];
                }
                if (initialValue == null) {
                    continue;
                }
                if (time > 0) {
                    track.addKeyframe(0, cloneValue(initialValue), easing);
                }
                this._trackKeys.push(propName);
            }
            track.addKeyframe(time, cloneValue(props[propName]), easing);
        }
        this._maxTime = Math.max(this._maxTime, time);
        return this;
    };
    Animator.prototype.pause = function () {
        this._clip.pause();
        this._paused = true;
    };
    Animator.prototype.resume = function () {
        this._clip.resume();
        this._paused = false;
    };
    Animator.prototype.isPaused = function () {
        return !!this._paused;
    };
    Animator.prototype.duration = function (duration) {
        this._maxTime = duration;
        this._force = true;
        return this;
    };
    Animator.prototype._doneCallback = function () {
        this._setTracksFinished();
        this._clip = null;
        var doneList = this._doneCbs;
        if (doneList) {
            var len = doneList.length;
            for (var i = 0; i < len; i++) {
                doneList[i].call(this);
            }
        }
    };
    Animator.prototype._abortedCallback = function () {
        this._setTracksFinished();
        var animation = this.animation;
        var abortedList = this._abortedCbs;
        if (animation) {
            animation.removeClip(this._clip);
        }
        this._clip = null;
        if (abortedList) {
            for (var i = 0; i < abortedList.length; i++) {
                abortedList[i].call(this);
            }
        }
    };
    Animator.prototype._setTracksFinished = function () {
        var tracks = this._tracks;
        var tracksKeys = this._trackKeys;
        for (var i = 0; i < tracksKeys.length; i++) {
            tracks[tracksKeys[i]].setFinished();
        }
    };
    Animator.prototype._getAdditiveTrack = function (trackName) {
        var additiveTrack;
        var additiveAnimators = this._additiveAnimators;
        if (additiveAnimators) {
            for (var i = 0; i < additiveAnimators.length; i++) {
                var track = additiveAnimators[i].getTrack(trackName);
                if (track) {
                    additiveTrack = track;
                }
            }
        }
        return additiveTrack;
    };
    Animator.prototype.start = function (easing) {
        if (this._started > 0) {
            return;
        }
        this._started = 1;
        var self = this;
        var tracks = [];
        var maxTime = this._maxTime || 0;
        for (var i = 0; i < this._trackKeys.length; i++) {
            var propName = this._trackKeys[i];
            var track = this._tracks[propName];
            var additiveTrack = this._getAdditiveTrack(propName);
            var kfs = track.keyframes;
            var kfsNum = kfs.length;
            track.prepare(maxTime, additiveTrack);
            if (track.needsAnimate()) {
                if (!this._allowDiscrete && track.discrete) {
                    var lastKf = kfs[kfsNum - 1];
                    if (lastKf) {
                        self._target[track.propName] = lastKf.rawValue;
                    }
                    track.setFinished();
                }
                else {
                    tracks.push(track);
                }
            }
        }
        if (tracks.length || this._force) {
            var clip = new Clip$1({
                life: maxTime,
                loop: this._loop,
                delay: this._delay || 0,
                onframe: function (percent) {
                    self._started = 2;
                    var additiveAnimators = self._additiveAnimators;
                    if (additiveAnimators) {
                        var stillHasAdditiveAnimator = false;
                        for (var i = 0; i < additiveAnimators.length; i++) {
                            if (additiveAnimators[i]._clip) {
                                stillHasAdditiveAnimator = true;
                                break;
                            }
                        }
                        if (!stillHasAdditiveAnimator) {
                            self._additiveAnimators = null;
                        }
                    }
                    for (var i = 0; i < tracks.length; i++) {
                        tracks[i].step(self._target, percent);
                    }
                    var onframeList = self._onframeCbs;
                    if (onframeList) {
                        for (var i = 0; i < onframeList.length; i++) {
                            onframeList[i](self._target, percent);
                        }
                    }
                },
                ondestroy: function () {
                    self._doneCallback();
                }
            });
            this._clip = clip;
            if (this.animation) {
                this.animation.addClip(clip);
            }
            if (easing) {
                clip.setEasing(easing);
            }
        }
        else {
            this._doneCallback();
        }
        return this;
    };
    Animator.prototype.stop = function (forwardToLast) {
        if (!this._clip) {
            return;
        }
        var clip = this._clip;
        if (forwardToLast) {
            clip.onframe(1);
        }
        this._abortedCallback();
    };
    Animator.prototype.delay = function (time) {
        this._delay = time;
        return this;
    };
    Animator.prototype.during = function (cb) {
        if (cb) {
            if (!this._onframeCbs) {
                this._onframeCbs = [];
            }
            this._onframeCbs.push(cb);
        }
        return this;
    };
    Animator.prototype.done = function (cb) {
        if (cb) {
            if (!this._doneCbs) {
                this._doneCbs = [];
            }
            this._doneCbs.push(cb);
        }
        return this;
    };
    Animator.prototype.aborted = function (cb) {
        if (cb) {
            if (!this._abortedCbs) {
                this._abortedCbs = [];
            }
            this._abortedCbs.push(cb);
        }
        return this;
    };
    Animator.prototype.getClip = function () {
        return this._clip;
    };
    Animator.prototype.getTrack = function (propName) {
        return this._tracks[propName];
    };
    Animator.prototype.getTracks = function () {
        var _this = this;
        return map$1(this._trackKeys, function (key) { return _this._tracks[key]; });
    };
    Animator.prototype.stopTracks = function (propNames, forwardToLast) {
        if (!propNames.length || !this._clip) {
            return true;
        }
        var tracks = this._tracks;
        var tracksKeys = this._trackKeys;
        for (var i = 0; i < propNames.length; i++) {
            var track = tracks[propNames[i]];
            if (track && !track.isFinished()) {
                if (forwardToLast) {
                    track.step(this._target, 1);
                }
                else if (this._started === 1) {
                    track.step(this._target, 0);
                }
                track.setFinished();
            }
        }
        var allAborted = true;
        for (var i = 0; i < tracksKeys.length; i++) {
            if (!tracks[tracksKeys[i]].isFinished()) {
                allAborted = false;
                break;
            }
        }
        if (allAborted) {
            this._abortedCallback();
        }
        return allAborted;
    };
    Animator.prototype.saveTo = function (target, trackKeys, firstOrLast) {
        if (!target) {
            return;
        }
        trackKeys = trackKeys || this._trackKeys;
        for (var i = 0; i < trackKeys.length; i++) {
            var propName = trackKeys[i];
            var track = this._tracks[propName];
            if (!track || track.isFinished()) {
                continue;
            }
            var kfs = track.keyframes;
            var kf = kfs[firstOrLast ? 0 : kfs.length - 1];
            if (kf) {
                target[propName] = cloneValue(kf.rawValue);
            }
        }
    };
    Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) {
        trackKeys = trackKeys || keys(finalProps);
        for (var i = 0; i < trackKeys.length; i++) {
            var propName = trackKeys[i];
            var track = this._tracks[propName];
            if (!track) {
                continue;
            }
            var kfs = track.keyframes;
            if (kfs.length > 1) {
                var lastKf = kfs.pop();
                track.addKeyframe(lastKf.time, finalProps[propName]);
                track.prepare(this._maxTime, track.getAdditiveTrack());
            }
        }
    };
    return Animator;
}());
const Animator$1 = Animator;

/* Injected with object hook! */

function getTime() {
    return new Date().getTime();
}
var Animation = (function (_super) {
    __extends(Animation, _super);
    function Animation(opts) {
        var _this = _super.call(this) || this;
        _this._running = false;
        _this._time = 0;
        _this._pausedTime = 0;
        _this._pauseStart = 0;
        _this._paused = false;
        opts = opts || {};
        _this.stage = opts.stage || {};
        return _this;
    }
    Animation.prototype.addClip = function (clip) {
        if (clip.animation) {
            this.removeClip(clip);
        }
        if (!this._head) {
            this._head = this._tail = clip;
        }
        else {
            this._tail.next = clip;
            clip.prev = this._tail;
            clip.next = null;
            this._tail = clip;
        }
        clip.animation = this;
    };
    Animation.prototype.addAnimator = function (animator) {
        animator.animation = this;
        var clip = animator.getClip();
        if (clip) {
            this.addClip(clip);
        }
    };
    Animation.prototype.removeClip = function (clip) {
        if (!clip.animation) {
            return;
        }
        var prev = clip.prev;
        var next = clip.next;
        if (prev) {
            prev.next = next;
        }
        else {
            this._head = next;
        }
        if (next) {
            next.prev = prev;
        }
        else {
            this._tail = prev;
        }
        clip.next = clip.prev = clip.animation = null;
    };
    Animation.prototype.removeAnimator = function (animator) {
        var clip = animator.getClip();
        if (clip) {
            this.removeClip(clip);
        }
        animator.animation = null;
    };
    Animation.prototype.update = function (notTriggerFrameAndStageUpdate) {
        var time = getTime() - this._pausedTime;
        var delta = time - this._time;
        var clip = this._head;
        while (clip) {
            var nextClip = clip.next;
            var finished = clip.step(time, delta);
            if (finished) {
                clip.ondestroy();
                this.removeClip(clip);
                clip = nextClip;
            }
            else {
                clip = nextClip;
            }
        }
        this._time = time;
        if (!notTriggerFrameAndStageUpdate) {
            this.trigger('frame', delta);
            this.stage.update && this.stage.update();
        }
    };
    Animation.prototype._startLoop = function () {
        var self = this;
        this._running = true;
        function step() {
            if (self._running) {
                requestAnimationFrame$2(step);
                !self._paused && self.update();
            }
        }
        requestAnimationFrame$2(step);
    };
    Animation.prototype.start = function () {
        if (this._running) {
            return;
        }
        this._time = getTime();
        this._pausedTime = 0;
        this._startLoop();
    };
    Animation.prototype.stop = function () {
        this._running = false;
    };
    Animation.prototype.pause = function () {
        if (!this._paused) {
            this._pauseStart = getTime();
            this._paused = true;
        }
    };
    Animation.prototype.resume = function () {
        if (this._paused) {
            this._pausedTime += getTime() - this._pauseStart;
            this._paused = false;
        }
    };
    Animation.prototype.clear = function () {
        var clip = this._head;
        while (clip) {
            var nextClip = clip.next;
            clip.prev = clip.next = clip.animation = null;
            clip = nextClip;
        }
        this._head = this._tail = null;
    };
    Animation.prototype.isFinished = function () {
        return this._head == null;
    };
    Animation.prototype.animate = function (target, options) {
        options = options || {};
        this.start();
        var animator = new Animator$1(target, options.loop);
        this.addAnimator(animator);
        return animator;
    };
    return Animation;
}(Eventful$1));
const Animation$1 = Animation;

/* Injected with object hook! */

var TOUCH_CLICK_DELAY = 300;
var globalEventSupported = env$1.domSupported;
var localNativeListenerNames = (function () {
    var mouseHandlerNames = [
        'click', 'dblclick', 'mousewheel', 'wheel', 'mouseout',
        'mouseup', 'mousedown', 'mousemove', 'contextmenu'
    ];
    var touchHandlerNames = [
        'touchstart', 'touchend', 'touchmove'
    ];
    var pointerEventNameMap = {
        pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
    };
    var pointerHandlerNames = map$1(mouseHandlerNames, function (name) {
        var nm = name.replace('mouse', 'pointer');
        return pointerEventNameMap.hasOwnProperty(nm) ? nm : name;
    });
    return {
        mouse: mouseHandlerNames,
        touch: touchHandlerNames,
        pointer: pointerHandlerNames
    };
})();
var globalNativeListenerNames = {
    mouse: ['mousemove', 'mouseup'],
    pointer: ['pointermove', 'pointerup']
};
var wheelEventSupported = false;
function isPointerFromTouch(event) {
    var pointerType = event.pointerType;
    return pointerType === 'pen' || pointerType === 'touch';
}
function setTouchTimer(scope) {
    scope.touching = true;
    if (scope.touchTimer != null) {
        clearTimeout(scope.touchTimer);
        scope.touchTimer = null;
    }
    scope.touchTimer = setTimeout(function () {
        scope.touching = false;
        scope.touchTimer = null;
    }, 700);
}
function markTouch(event) {
    event && (event.zrByTouch = true);
}
function normalizeGlobalEvent(instance, event) {
    return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true);
}
function isLocalEl(instance, el) {
    var elTmp = el;
    var isLocal = false;
    while (elTmp && elTmp.nodeType !== 9
        && !(isLocal = elTmp.domBelongToZr
            || (elTmp !== el && elTmp === instance.painterRoot))) {
        elTmp = elTmp.parentNode;
    }
    return isLocal;
}
var FakeGlobalEvent = (function () {
    function FakeGlobalEvent(instance, event) {
        this.stopPropagation = noop;
        this.stopImmediatePropagation = noop;
        this.preventDefault = noop;
        this.type = event.type;
        this.target = this.currentTarget = instance.dom;
        this.pointerType = event.pointerType;
        this.clientX = event.clientX;
        this.clientY = event.clientY;
    }
    return FakeGlobalEvent;
}());
var localDOMHandlers = {
    mousedown: function (event) {
        event = normalizeEvent(this.dom, event);
        this.__mayPointerCapture = [event.zrX, event.zrY];
        this.trigger('mousedown', event);
    },
    mousemove: function (event) {
        event = normalizeEvent(this.dom, event);
        var downPoint = this.__mayPointerCapture;
        if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) {
            this.__togglePointerCapture(true);
        }
        this.trigger('mousemove', event);
    },
    mouseup: function (event) {
        event = normalizeEvent(this.dom, event);
        this.__togglePointerCapture(false);
        this.trigger('mouseup', event);
    },
    mouseout: function (event) {
        event = normalizeEvent(this.dom, event);
        var element = event.toElement || event.relatedTarget;
        if (!isLocalEl(this, element)) {
            if (this.__pointerCapturing) {
                event.zrEventControl = 'no_globalout';
            }
            this.trigger('mouseout', event);
        }
    },
    wheel: function (event) {
        wheelEventSupported = true;
        event = normalizeEvent(this.dom, event);
        this.trigger('mousewheel', event);
    },
    mousewheel: function (event) {
        if (wheelEventSupported) {
            return;
        }
        event = normalizeEvent(this.dom, event);
        this.trigger('mousewheel', event);
    },
    touchstart: function (event) {
        event = normalizeEvent(this.dom, event);
        markTouch(event);
        this.__lastTouchMoment = new Date();
        this.handler.processGesture(event, 'start');
        localDOMHandlers.mousemove.call(this, event);
        localDOMHandlers.mousedown.call(this, event);
    },
    touchmove: function (event) {
        event = normalizeEvent(this.dom, event);
        markTouch(event);
        this.handler.processGesture(event, 'change');
        localDOMHandlers.mousemove.call(this, event);
    },
    touchend: function (event) {
        event = normalizeEvent(this.dom, event);
        markTouch(event);
        this.handler.processGesture(event, 'end');
        localDOMHandlers.mouseup.call(this, event);
        if (+new Date() - (+this.__lastTouchMoment) < TOUCH_CLICK_DELAY) {
            localDOMHandlers.click.call(this, event);
        }
    },
    pointerdown: function (event) {
        localDOMHandlers.mousedown.call(this, event);
    },
    pointermove: function (event) {
        if (!isPointerFromTouch(event)) {
            localDOMHandlers.mousemove.call(this, event);
        }
    },
    pointerup: function (event) {
        localDOMHandlers.mouseup.call(this, event);
    },
    pointerout: function (event) {
        if (!isPointerFromTouch(event)) {
            localDOMHandlers.mouseout.call(this, event);
        }
    }
};
each$4(['click', 'dblclick', 'contextmenu'], function (name) {
    localDOMHandlers[name] = function (event) {
        event = normalizeEvent(this.dom, event);
        this.trigger(name, event);
    };
});
var globalDOMHandlers = {
    pointermove: function (event) {
        if (!isPointerFromTouch(event)) {
            globalDOMHandlers.mousemove.call(this, event);
        }
    },
    pointerup: function (event) {
        globalDOMHandlers.mouseup.call(this, event);
    },
    mousemove: function (event) {
        this.trigger('mousemove', event);
    },
    mouseup: function (event) {
        var pointerCaptureReleasing = this.__pointerCapturing;
        this.__togglePointerCapture(false);
        this.trigger('mouseup', event);
        if (pointerCaptureReleasing) {
            event.zrEventControl = 'only_globalout';
            this.trigger('mouseout', event);
        }
    }
};
function mountLocalDOMEventListeners(instance, scope) {
    var domHandlers = scope.domHandlers;
    if (env$1.pointerEventsSupported) {
        each$4(localNativeListenerNames.pointer, function (nativeEventName) {
            mountSingleDOMEventListener(scope, nativeEventName, function (event) {
                domHandlers[nativeEventName].call(instance, event);
            });
        });
    }
    else {
        if (env$1.touchEventsSupported) {
            each$4(localNativeListenerNames.touch, function (nativeEventName) {
                mountSingleDOMEventListener(scope, nativeEventName, function (event) {
                    domHandlers[nativeEventName].call(instance, event);
                    setTouchTimer(scope);
                });
            });
        }
        each$4(localNativeListenerNames.mouse, function (nativeEventName) {
            mountSingleDOMEventListener(scope, nativeEventName, function (event) {
                event = getNativeEvent(event);
                if (!scope.touching) {
                    domHandlers[nativeEventName].call(instance, event);
                }
            });
        });
    }
}
function mountGlobalDOMEventListeners(instance, scope) {
    if (env$1.pointerEventsSupported) {
        each$4(globalNativeListenerNames.pointer, mount);
    }
    else if (!env$1.touchEventsSupported) {
        each$4(globalNativeListenerNames.mouse, mount);
    }
    function mount(nativeEventName) {
        function nativeEventListener(event) {
            event = getNativeEvent(event);
            if (!isLocalEl(instance, event.target)) {
                event = normalizeGlobalEvent(instance, event);
                scope.domHandlers[nativeEventName].call(instance, event);
            }
        }
        mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, { capture: true });
    }
}
function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) {
    scope.mounted[nativeEventName] = listener;
    scope.listenerOpts[nativeEventName] = opt;
    addEventListener(scope.domTarget, nativeEventName, listener, opt);
}
function unmountDOMEventListeners(scope) {
    var mounted = scope.mounted;
    for (var nativeEventName in mounted) {
        if (mounted.hasOwnProperty(nativeEventName)) {
            removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]);
        }
    }
    scope.mounted = {};
}
var DOMHandlerScope = (function () {
    function DOMHandlerScope(domTarget, domHandlers) {
        this.mounted = {};
        this.listenerOpts = {};
        this.touching = false;
        this.domTarget = domTarget;
        this.domHandlers = domHandlers;
    }
    return DOMHandlerScope;
}());
var HandlerDomProxy = (function (_super) {
    __extends(HandlerDomProxy, _super);
    function HandlerDomProxy(dom, painterRoot) {
        var _this = _super.call(this) || this;
        _this.__pointerCapturing = false;
        _this.dom = dom;
        _this.painterRoot = painterRoot;
        _this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers);
        if (globalEventSupported) {
            _this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers);
        }
        mountLocalDOMEventListeners(_this, _this._localHandlerScope);
        return _this;
    }
    HandlerDomProxy.prototype.dispose = function () {
        unmountDOMEventListeners(this._localHandlerScope);
        if (globalEventSupported) {
            unmountDOMEventListeners(this._globalHandlerScope);
        }
    };
    HandlerDomProxy.prototype.setCursor = function (cursorStyle) {
        this.dom.style && (this.dom.style.cursor = cursorStyle || 'default');
    };
    HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) {
        this.__mayPointerCapture = null;
        if (globalEventSupported
            && ((+this.__pointerCapturing) ^ (+isPointerCapturing))) {
            this.__pointerCapturing = isPointerCapturing;
            var globalHandlerScope = this._globalHandlerScope;
            isPointerCapturing
                ? mountGlobalDOMEventListeners(this, globalHandlerScope)
                : unmountDOMEventListeners(globalHandlerScope);
        }
    };
    return HandlerDomProxy;
}(Eventful$1));
const HandlerProxy = HandlerDomProxy;

/* Injected with object hook! */

var dpr = 1;
if (env$1.hasGlobalWindow) {
    dpr = Math.max(window.devicePixelRatio
        || (window.screen && window.screen.deviceXDPI / window.screen.logicalXDPI)
        || 1, 1);
}
var devicePixelRatio = dpr;
var DARK_MODE_THRESHOLD = 0.4;
var DARK_LABEL_COLOR = '#333';
var LIGHT_LABEL_COLOR = '#ccc';
var LIGHTER_LABEL_COLOR = '#eee';

/* Injected with object hook! */

var mIdentity = identity;
var EPSILON$1 = 5e-5;
function isNotAroundZero(val) {
    return val > EPSILON$1 || val < -EPSILON$1;
}
var scaleTmp = [];
var tmpTransform = [];
var originTransform = create();
var abs = Math.abs;
var Transformable = (function () {
    function Transformable() {
    }
    Transformable.prototype.getLocalTransform = function (m) {
        return Transformable.getLocalTransform(this, m);
    };
    Transformable.prototype.setPosition = function (arr) {
        this.x = arr[0];
        this.y = arr[1];
    };
    Transformable.prototype.setScale = function (arr) {
        this.scaleX = arr[0];
        this.scaleY = arr[1];
    };
    Transformable.prototype.setSkew = function (arr) {
        this.skewX = arr[0];
        this.skewY = arr[1];
    };
    Transformable.prototype.setOrigin = function (arr) {
        this.originX = arr[0];
        this.originY = arr[1];
    };
    Transformable.prototype.needLocalTransform = function () {
        return isNotAroundZero(this.rotation)
            || isNotAroundZero(this.x)
            || isNotAroundZero(this.y)
            || isNotAroundZero(this.scaleX - 1)
            || isNotAroundZero(this.scaleY - 1)
            || isNotAroundZero(this.skewX)
            || isNotAroundZero(this.skewY);
    };
    Transformable.prototype.updateTransform = function () {
        var parentTransform = this.parent && this.parent.transform;
        var needLocalTransform = this.needLocalTransform();
        var m = this.transform;
        if (!(needLocalTransform || parentTransform)) {
            if (m) {
                mIdentity(m);
                this.invTransform = null;
            }
            return;
        }
        m = m || create();
        if (needLocalTransform) {
            this.getLocalTransform(m);
        }
        else {
            mIdentity(m);
        }
        if (parentTransform) {
            if (needLocalTransform) {
                mul(m, parentTransform, m);
            }
            else {
                copy(m, parentTransform);
            }
        }
        this.transform = m;
        this._resolveGlobalScaleRatio(m);
    };
    Transformable.prototype._resolveGlobalScaleRatio = function (m) {
        var globalScaleRatio = this.globalScaleRatio;
        if (globalScaleRatio != null && globalScaleRatio !== 1) {
            this.getGlobalScale(scaleTmp);
            var relX = scaleTmp[0] < 0 ? -1 : 1;
            var relY = scaleTmp[1] < 0 ? -1 : 1;
            var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0;
            var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0;
            m[0] *= sx;
            m[1] *= sx;
            m[2] *= sy;
            m[3] *= sy;
        }
        this.invTransform = this.invTransform || create();
        invert(this.invTransform, m);
    };
    Transformable.prototype.getComputedTransform = function () {
        var transformNode = this;
        var ancestors = [];
        while (transformNode) {
            ancestors.push(transformNode);
            transformNode = transformNode.parent;
        }
        while (transformNode = ancestors.pop()) {
            transformNode.updateTransform();
        }
        return this.transform;
    };
    Transformable.prototype.setLocalTransform = function (m) {
        if (!m) {
            return;
        }
        var sx = m[0] * m[0] + m[1] * m[1];
        var sy = m[2] * m[2] + m[3] * m[3];
        var rotation = Math.atan2(m[1], m[0]);
        var shearX = Math.PI / 2 + rotation - Math.atan2(m[3], m[2]);
        sy = Math.sqrt(sy) * Math.cos(shearX);
        sx = Math.sqrt(sx);
        this.skewX = shearX;
        this.skewY = 0;
        this.rotation = -rotation;
        this.x = +m[4];
        this.y = +m[5];
        this.scaleX = sx;
        this.scaleY = sy;
        this.originX = 0;
        this.originY = 0;
    };
    Transformable.prototype.decomposeTransform = function () {
        if (!this.transform) {
            return;
        }
        var parent = this.parent;
        var m = this.transform;
        if (parent && parent.transform) {
            mul(tmpTransform, parent.invTransform, m);
            m = tmpTransform;
        }
        var ox = this.originX;
        var oy = this.originY;
        if (ox || oy) {
            originTransform[4] = ox;
            originTransform[5] = oy;
            mul(tmpTransform, m, originTransform);
            tmpTransform[4] -= ox;
            tmpTransform[5] -= oy;
            m = tmpTransform;
        }
        this.setLocalTransform(m);
    };
    Transformable.prototype.getGlobalScale = function (out) {
        var m = this.transform;
        out = out || [];
        if (!m) {
            out[0] = 1;
            out[1] = 1;
            return out;
        }
        out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]);
        out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]);
        if (m[0] < 0) {
            out[0] = -out[0];
        }
        if (m[3] < 0) {
            out[1] = -out[1];
        }
        return out;
    };
    Transformable.prototype.transformCoordToLocal = function (x, y) {
        var v2 = [x, y];
        var invTransform = this.invTransform;
        if (invTransform) {
            applyTransform$1(v2, v2, invTransform);
        }
        return v2;
    };
    Transformable.prototype.transformCoordToGlobal = function (x, y) {
        var v2 = [x, y];
        var transform = this.transform;
        if (transform) {
            applyTransform$1(v2, v2, transform);
        }
        return v2;
    };
    Transformable.prototype.getLineScale = function () {
        var m = this.transform;
        return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10
            ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1]))
            : 1;
    };
    Transformable.prototype.copyTransform = function (source) {
        copyTransform(this, source);
    };
    Transformable.getLocalTransform = function (target, m) {
        m = m || [];
        var ox = target.originX || 0;
        var oy = target.originY || 0;
        var sx = target.scaleX;
        var sy = target.scaleY;
        var ax = target.anchorX;
        var ay = target.anchorY;
        var rotation = target.rotation || 0;
        var x = target.x;
        var y = target.y;
        var skewX = target.skewX ? Math.tan(target.skewX) : 0;
        var skewY = target.skewY ? Math.tan(-target.skewY) : 0;
        if (ox || oy || ax || ay) {
            var dx = ox + ax;
            var dy = oy + ay;
            m[4] = -dx * sx - skewX * dy * sy;
            m[5] = -dy * sy - skewY * dx * sx;
        }
        else {
            m[4] = m[5] = 0;
        }
        m[0] = sx;
        m[3] = sy;
        m[1] = skewY * sx;
        m[2] = skewX * sy;
        rotation && rotate(m, m, rotation);
        m[4] += ox + x;
        m[5] += oy + y;
        return m;
    };
    Transformable.initDefaultProps = (function () {
        var proto = Transformable.prototype;
        proto.scaleX =
            proto.scaleY =
                proto.globalScaleRatio = 1;
        proto.x =
            proto.y =
                proto.originX =
                    proto.originY =
                        proto.skewX =
                            proto.skewY =
                                proto.rotation =
                                    proto.anchorX =
                                        proto.anchorY = 0;
    })();
    return Transformable;
}());
var TRANSFORMABLE_PROPS = [
    'x', 'y', 'originX', 'originY', 'anchorX', 'anchorY', 'rotation', 'scaleX', 'scaleY', 'skewX', 'skewY'
];
function copyTransform(target, source) {
    for (var i = 0; i < TRANSFORMABLE_PROPS.length; i++) {
        var propName = TRANSFORMABLE_PROPS[i];
        target[propName] = source[propName];
    }
}

/* Injected with object hook! */

var textWidthCache = {};
function getWidth(text, font) {
    font = font || DEFAULT_FONT;
    var cacheOfFont = textWidthCache[font];
    if (!cacheOfFont) {
        cacheOfFont = textWidthCache[font] = new LRU$1(500);
    }
    var width = cacheOfFont.get(text);
    if (width == null) {
        width = platformApi.measureText(text, font).width;
        cacheOfFont.put(text, width);
    }
    return width;
}
function innerGetBoundingRect(text, font, textAlign, textBaseline) {
    var width = getWidth(text, font);
    var height = getLineHeight(font);
    var x = adjustTextX(0, width, textAlign);
    var y = adjustTextY(0, height, textBaseline);
    var rect = new BoundingRect$1(x, y, width, height);
    return rect;
}
function getBoundingRect(text, font, textAlign, textBaseline) {
    var textLines = ((text || '') + '').split('\n');
    var len = textLines.length;
    if (len === 1) {
        return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline);
    }
    else {
        var uniondRect = new BoundingRect$1(0, 0, 0, 0);
        for (var i = 0; i < textLines.length; i++) {
            var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline);
            i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect);
        }
        return uniondRect;
    }
}
function adjustTextX(x, width, textAlign) {
    if (textAlign === 'right') {
        x -= width;
    }
    else if (textAlign === 'center') {
        x -= width / 2;
    }
    return x;
}
function adjustTextY(y, height, verticalAlign) {
    if (verticalAlign === 'middle') {
        y -= height / 2;
    }
    else if (verticalAlign === 'bottom') {
        y -= height;
    }
    return y;
}
function getLineHeight(font) {
    return getWidth('国', font);
}
function parsePercent$1(value, maxValue) {
    if (typeof value === 'string') {
        if (value.lastIndexOf('%') >= 0) {
            return parseFloat(value) / 100 * maxValue;
        }
        return parseFloat(value);
    }
    return value;
}
function calculateTextPosition(out, opts, rect) {
    var textPosition = opts.position || 'inside';
    var distance = opts.distance != null ? opts.distance : 5;
    var height = rect.height;
    var width = rect.width;
    var halfHeight = height / 2;
    var x = rect.x;
    var y = rect.y;
    var textAlign = 'left';
    var textVerticalAlign = 'top';
    if (textPosition instanceof Array) {
        x += parsePercent$1(textPosition[0], rect.width);
        y += parsePercent$1(textPosition[1], rect.height);
        textAlign = null;
        textVerticalAlign = null;
    }
    else {
        switch (textPosition) {
            case 'left':
                x -= distance;
                y += halfHeight;
                textAlign = 'right';
                textVerticalAlign = 'middle';
                break;
            case 'right':
                x += distance + width;
                y += halfHeight;
                textVerticalAlign = 'middle';
                break;
            case 'top':
                x += width / 2;
                y -= distance;
                textAlign = 'center';
                textVerticalAlign = 'bottom';
                break;
            case 'bottom':
                x += width / 2;
                y += height + distance;
                textAlign = 'center';
                break;
            case 'inside':
                x += width / 2;
                y += halfHeight;
                textAlign = 'center';
                textVerticalAlign = 'middle';
                break;
            case 'insideLeft':
                x += distance;
                y += halfHeight;
                textVerticalAlign = 'middle';
                break;
            case 'insideRight':
                x += width - distance;
                y += halfHeight;
                textAlign = 'right';
                textVerticalAlign = 'middle';
                break;
            case 'insideTop':
                x += width / 2;
                y += distance;
                textAlign = 'center';
                break;
            case 'insideBottom':
                x += width / 2;
                y += height - distance;
                textAlign = 'center';
                textVerticalAlign = 'bottom';
                break;
            case 'insideTopLeft':
                x += distance;
                y += distance;
                break;
            case 'insideTopRight':
                x += width - distance;
                y += distance;
                textAlign = 'right';
                break;
            case 'insideBottomLeft':
                x += distance;
                y += height - distance;
                textVerticalAlign = 'bottom';
                break;
            case 'insideBottomRight':
                x += width - distance;
                y += height - distance;
                textAlign = 'right';
                textVerticalAlign = 'bottom';
                break;
        }
    }
    out = out || {};
    out.x = x;
    out.y = y;
    out.align = textAlign;
    out.verticalAlign = textVerticalAlign;
    return out;
}

/* Injected with object hook! */

var PRESERVED_NORMAL_STATE = '__zr_normal__';
var PRIMARY_STATES_KEYS$1 = TRANSFORMABLE_PROPS.concat(['ignore']);
var DEFAULT_ANIMATABLE_MAP = reduce(TRANSFORMABLE_PROPS, function (obj, key) {
    obj[key] = true;
    return obj;
}, { ignore: false });
var tmpTextPosCalcRes = {};
var tmpBoundingRect = new BoundingRect$1(0, 0, 0, 0);
var Element$1 = (function () {
    function Element(props) {
        this.id = guid();
        this.animators = [];
        this.currentStates = [];
        this.states = {};
        this._init(props);
    }
    Element.prototype._init = function (props) {
        this.attr(props);
    };
    Element.prototype.drift = function (dx, dy, e) {
        switch (this.draggable) {
            case 'horizontal':
                dy = 0;
                break;
            case 'vertical':
                dx = 0;
                break;
        }
        var m = this.transform;
        if (!m) {
            m = this.transform = [1, 0, 0, 1, 0, 0];
        }
        m[4] += dx;
        m[5] += dy;
        this.decomposeTransform();
        this.markRedraw();
    };
    Element.prototype.beforeUpdate = function () { };
    Element.prototype.afterUpdate = function () { };
    Element.prototype.update = function () {
        this.updateTransform();
        if (this.__dirty) {
            this.updateInnerText();
        }
    };
    Element.prototype.updateInnerText = function (forceUpdate) {
        var textEl = this._textContent;
        if (textEl && (!textEl.ignore || forceUpdate)) {
            if (!this.textConfig) {
                this.textConfig = {};
            }
            var textConfig = this.textConfig;
            var isLocal = textConfig.local;
            var innerTransformable = textEl.innerTransformable;
            var textAlign = void 0;
            var textVerticalAlign = void 0;
            var textStyleChanged = false;
            innerTransformable.parent = isLocal ? this : null;
            var innerOrigin = false;
            innerTransformable.copyTransform(textEl);
            if (textConfig.position != null) {
                var layoutRect = tmpBoundingRect;
                if (textConfig.layoutRect) {
                    layoutRect.copy(textConfig.layoutRect);
                }
                else {
                    layoutRect.copy(this.getBoundingRect());
                }
                if (!isLocal) {
                    layoutRect.applyTransform(this.transform);
                }
                if (this.calculateTextPosition) {
                    this.calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect);
                }
                else {
                    calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect);
                }
                innerTransformable.x = tmpTextPosCalcRes.x;
                innerTransformable.y = tmpTextPosCalcRes.y;
                textAlign = tmpTextPosCalcRes.align;
                textVerticalAlign = tmpTextPosCalcRes.verticalAlign;
                var textOrigin = textConfig.origin;
                if (textOrigin && textConfig.rotation != null) {
                    var relOriginX = void 0;
                    var relOriginY = void 0;
                    if (textOrigin === 'center') {
                        relOriginX = layoutRect.width * 0.5;
                        relOriginY = layoutRect.height * 0.5;
                    }
                    else {
                        relOriginX = parsePercent$1(textOrigin[0], layoutRect.width);
                        relOriginY = parsePercent$1(textOrigin[1], layoutRect.height);
                    }
                    innerOrigin = true;
                    innerTransformable.originX = -innerTransformable.x + relOriginX + (isLocal ? 0 : layoutRect.x);
                    innerTransformable.originY = -innerTransformable.y + relOriginY + (isLocal ? 0 : layoutRect.y);
                }
            }
            if (textConfig.rotation != null) {
                innerTransformable.rotation = textConfig.rotation;
            }
            var textOffset = textConfig.offset;
            if (textOffset) {
                innerTransformable.x += textOffset[0];
                innerTransformable.y += textOffset[1];
                if (!innerOrigin) {
                    innerTransformable.originX = -textOffset[0];
                    innerTransformable.originY = -textOffset[1];
                }
            }
            var isInside = textConfig.inside == null
                ? (typeof textConfig.position === 'string' && textConfig.position.indexOf('inside') >= 0)
                : textConfig.inside;
            var innerTextDefaultStyle = this._innerTextDefaultStyle || (this._innerTextDefaultStyle = {});
            var textFill = void 0;
            var textStroke = void 0;
            var autoStroke = void 0;
            if (isInside && this.canBeInsideText()) {
                textFill = textConfig.insideFill;
                textStroke = textConfig.insideStroke;
                if (textFill == null || textFill === 'auto') {
                    textFill = this.getInsideTextFill();
                }
                if (textStroke == null || textStroke === 'auto') {
                    textStroke = this.getInsideTextStroke(textFill);
                    autoStroke = true;
                }
            }
            else {
                textFill = textConfig.outsideFill;
                textStroke = textConfig.outsideStroke;
                if (textFill == null || textFill === 'auto') {
                    textFill = this.getOutsideFill();
                }
                if (textStroke == null || textStroke === 'auto') {
                    textStroke = this.getOutsideStroke(textFill);
                    autoStroke = true;
                }
            }
            textFill = textFill || '#000';
            if (textFill !== innerTextDefaultStyle.fill
                || textStroke !== innerTextDefaultStyle.stroke
                || autoStroke !== innerTextDefaultStyle.autoStroke
                || textAlign !== innerTextDefaultStyle.align
                || textVerticalAlign !== innerTextDefaultStyle.verticalAlign) {
                textStyleChanged = true;
                innerTextDefaultStyle.fill = textFill;
                innerTextDefaultStyle.stroke = textStroke;
                innerTextDefaultStyle.autoStroke = autoStroke;
                innerTextDefaultStyle.align = textAlign;
                innerTextDefaultStyle.verticalAlign = textVerticalAlign;
                textEl.setDefaultTextStyle(innerTextDefaultStyle);
            }
            textEl.__dirty |= REDRAW_BIT;
            if (textStyleChanged) {
                textEl.dirtyStyle(true);
            }
        }
    };
    Element.prototype.canBeInsideText = function () {
        return true;
    };
    Element.prototype.getInsideTextFill = function () {
        return '#fff';
    };
    Element.prototype.getInsideTextStroke = function (textFill) {
        return '#000';
    };
    Element.prototype.getOutsideFill = function () {
        return this.__zr && this.__zr.isDarkMode() ? LIGHT_LABEL_COLOR : DARK_LABEL_COLOR;
    };
    Element.prototype.getOutsideStroke = function (textFill) {
        var backgroundColor = this.__zr && this.__zr.getBackgroundColor();
        var colorArr = typeof backgroundColor === 'string' && parse(backgroundColor);
        if (!colorArr) {
            colorArr = [255, 255, 255, 1];
        }
        var alpha = colorArr[3];
        var isDark = this.__zr.isDarkMode();
        for (var i = 0; i < 3; i++) {
            colorArr[i] = colorArr[i] * alpha + (isDark ? 0 : 255) * (1 - alpha);
        }
        colorArr[3] = 1;
        return stringify(colorArr, 'rgba');
    };
    Element.prototype.traverse = function (cb, context) { };
    Element.prototype.attrKV = function (key, value) {
        if (key === 'textConfig') {
            this.setTextConfig(value);
        }
        else if (key === 'textContent') {
            this.setTextContent(value);
        }
        else if (key === 'clipPath') {
            this.setClipPath(value);
        }
        else if (key === 'extra') {
            this.extra = this.extra || {};
            extend(this.extra, value);
        }
        else {
            this[key] = value;
        }
    };
    Element.prototype.hide = function () {
        this.ignore = true;
        this.markRedraw();
    };
    Element.prototype.show = function () {
        this.ignore = false;
        this.markRedraw();
    };
    Element.prototype.attr = function (keyOrObj, value) {
        if (typeof keyOrObj === 'string') {
            this.attrKV(keyOrObj, value);
        }
        else if (isObject$2(keyOrObj)) {
            var obj = keyOrObj;
            var keysArr = keys(obj);
            for (var i = 0; i < keysArr.length; i++) {
                var key = keysArr[i];
                this.attrKV(key, keyOrObj[key]);
            }
        }
        this.markRedraw();
        return this;
    };
    Element.prototype.saveCurrentToNormalState = function (toState) {
        this._innerSaveToNormal(toState);
        var normalState = this._normalState;
        for (var i = 0; i < this.animators.length; i++) {
            var animator = this.animators[i];
            var fromStateTransition = animator.__fromStateTransition;
            if (animator.getLoop() || fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) {
                continue;
            }
            var targetName = animator.targetName;
            var target = targetName
                ? normalState[targetName] : normalState;
            animator.saveTo(target);
        }
    };
    Element.prototype._innerSaveToNormal = function (toState) {
        var normalState = this._normalState;
        if (!normalState) {
            normalState = this._normalState = {};
        }
        if (toState.textConfig && !normalState.textConfig) {
            normalState.textConfig = this.textConfig;
        }
        this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS$1);
    };
    Element.prototype._savePrimaryToNormal = function (toState, normalState, primaryKeys) {
        for (var i = 0; i < primaryKeys.length; i++) {
            var key = primaryKeys[i];
            if (toState[key] != null && !(key in normalState)) {
                normalState[key] = this[key];
            }
        }
    };
    Element.prototype.hasState = function () {
        return this.currentStates.length > 0;
    };
    Element.prototype.getState = function (name) {
        return this.states[name];
    };
    Element.prototype.ensureState = function (name) {
        var states = this.states;
        if (!states[name]) {
            states[name] = {};
        }
        return states[name];
    };
    Element.prototype.clearStates = function (noAnimation) {
        this.useState(PRESERVED_NORMAL_STATE, false, noAnimation);
    };
    Element.prototype.useState = function (stateName, keepCurrentStates, noAnimation, forceUseHoverLayer) {
        var toNormalState = stateName === PRESERVED_NORMAL_STATE;
        var hasStates = this.hasState();
        if (!hasStates && toNormalState) {
            return;
        }
        var currentStates = this.currentStates;
        var animationCfg = this.stateTransition;
        if (indexOf(currentStates, stateName) >= 0 && (keepCurrentStates || currentStates.length === 1)) {
            return;
        }
        var state;
        if (this.stateProxy && !toNormalState) {
            state = this.stateProxy(stateName);
        }
        if (!state) {
            state = (this.states && this.states[stateName]);
        }
        if (!state && !toNormalState) {
            logError("State " + stateName + " not exists.");
            return;
        }
        if (!toNormalState) {
            this.saveCurrentToNormalState(state);
        }
        var useHoverLayer = !!((state && state.hoverLayer) || forceUseHoverLayer);
        if (useHoverLayer) {
            this._toggleHoverLayerFlag(true);
        }
        this._applyStateObj(stateName, state, this._normalState, keepCurrentStates, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg);
        var textContent = this._textContent;
        var textGuide = this._textGuide;
        if (textContent) {
            textContent.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer);
        }
        if (textGuide) {
            textGuide.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer);
        }
        if (toNormalState) {
            this.currentStates = [];
            this._normalState = {};
        }
        else {
            if (!keepCurrentStates) {
                this.currentStates = [stateName];
            }
            else {
                this.currentStates.push(stateName);
            }
        }
        this._updateAnimationTargets();
        this.markRedraw();
        if (!useHoverLayer && this.__inHover) {
            this._toggleHoverLayerFlag(false);
            this.__dirty &= ~REDRAW_BIT;
        }
        return state;
    };
    Element.prototype.useStates = function (states, noAnimation, forceUseHoverLayer) {
        if (!states.length) {
            this.clearStates();
        }
        else {
            var stateObjects = [];
            var currentStates = this.currentStates;
            var len = states.length;
            var notChange = len === currentStates.length;
            if (notChange) {
                for (var i = 0; i < len; i++) {
                    if (states[i] !== currentStates[i]) {
                        notChange = false;
                        break;
                    }
                }
            }
            if (notChange) {
                return;
            }
            for (var i = 0; i < len; i++) {
                var stateName = states[i];
                var stateObj = void 0;
                if (this.stateProxy) {
                    stateObj = this.stateProxy(stateName, states);
                }
                if (!stateObj) {
                    stateObj = this.states[stateName];
                }
                if (stateObj) {
                    stateObjects.push(stateObj);
                }
            }
            var lastStateObj = stateObjects[len - 1];
            var useHoverLayer = !!((lastStateObj && lastStateObj.hoverLayer) || forceUseHoverLayer);
            if (useHoverLayer) {
                this._toggleHoverLayerFlag(true);
            }
            var mergedState = this._mergeStates(stateObjects);
            var animationCfg = this.stateTransition;
            this.saveCurrentToNormalState(mergedState);
            this._applyStateObj(states.join(','), mergedState, this._normalState, false, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg);
            var textContent = this._textContent;
            var textGuide = this._textGuide;
            if (textContent) {
                textContent.useStates(states, noAnimation, useHoverLayer);
            }
            if (textGuide) {
                textGuide.useStates(states, noAnimation, useHoverLayer);
            }
            this._updateAnimationTargets();
            this.currentStates = states.slice();
            this.markRedraw();
            if (!useHoverLayer && this.__inHover) {
                this._toggleHoverLayerFlag(false);
                this.__dirty &= ~REDRAW_BIT;
            }
        }
    };
    Element.prototype._updateAnimationTargets = function () {
        for (var i = 0; i < this.animators.length; i++) {
            var animator = this.animators[i];
            if (animator.targetName) {
                animator.changeTarget(this[animator.targetName]);
            }
        }
    };
    Element.prototype.removeState = function (state) {
        var idx = indexOf(this.currentStates, state);
        if (idx >= 0) {
            var currentStates = this.currentStates.slice();
            currentStates.splice(idx, 1);
            this.useStates(currentStates);
        }
    };
    Element.prototype.replaceState = function (oldState, newState, forceAdd) {
        var currentStates = this.currentStates.slice();
        var idx = indexOf(currentStates, oldState);
        var newStateExists = indexOf(currentStates, newState) >= 0;
        if (idx >= 0) {
            if (!newStateExists) {
                currentStates[idx] = newState;
            }
            else {
                currentStates.splice(idx, 1);
            }
        }
        else if (forceAdd && !newStateExists) {
            currentStates.push(newState);
        }
        this.useStates(currentStates);
    };
    Element.prototype.toggleState = function (state, enable) {
        if (enable) {
            this.useState(state, true);
        }
        else {
            this.removeState(state);
        }
    };
    Element.prototype._mergeStates = function (states) {
        var mergedState = {};
        var mergedTextConfig;
        for (var i = 0; i < states.length; i++) {
            var state = states[i];
            extend(mergedState, state);
            if (state.textConfig) {
                mergedTextConfig = mergedTextConfig || {};
                extend(mergedTextConfig, state.textConfig);
            }
        }
        if (mergedTextConfig) {
            mergedState.textConfig = mergedTextConfig;
        }
        return mergedState;
    };
    Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
        var needsRestoreToNormal = !(state && keepCurrentStates);
        if (state && state.textConfig) {
            this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig);
            extend(this.textConfig, state.textConfig);
        }
        else if (needsRestoreToNormal) {
            if (normalState.textConfig) {
                this.textConfig = normalState.textConfig;
            }
        }
        var transitionTarget = {};
        var hasTransition = false;
        for (var i = 0; i < PRIMARY_STATES_KEYS$1.length; i++) {
            var key = PRIMARY_STATES_KEYS$1[i];
            var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key];
            if (state && state[key] != null) {
                if (propNeedsTransition) {
                    hasTransition = true;
                    transitionTarget[key] = state[key];
                }
                else {
                    this[key] = state[key];
                }
            }
            else if (needsRestoreToNormal) {
                if (normalState[key] != null) {
                    if (propNeedsTransition) {
                        hasTransition = true;
                        transitionTarget[key] = normalState[key];
                    }
                    else {
                        this[key] = normalState[key];
                    }
                }
            }
        }
        if (!transition) {
            for (var i = 0; i < this.animators.length; i++) {
                var animator = this.animators[i];
                var targetName = animator.targetName;
                if (!animator.getLoop()) {
                    animator.__changeFinalValue(targetName
                        ? (state || normalState)[targetName]
                        : (state || normalState));
                }
            }
        }
        if (hasTransition) {
            this._transitionState(stateName, transitionTarget, animationCfg);
        }
    };
    Element.prototype._attachComponent = function (componentEl) {
        if (componentEl.__zr && !componentEl.__hostTarget) {
            return;
        }
        if (componentEl === this) {
            return;
        }
        var zr = this.__zr;
        if (zr) {
            componentEl.addSelfToZr(zr);
        }
        componentEl.__zr = zr;
        componentEl.__hostTarget = this;
    };
    Element.prototype._detachComponent = function (componentEl) {
        if (componentEl.__zr) {
            componentEl.removeSelfFromZr(componentEl.__zr);
        }
        componentEl.__zr = null;
        componentEl.__hostTarget = null;
    };
    Element.prototype.getClipPath = function () {
        return this._clipPath;
    };
    Element.prototype.setClipPath = function (clipPath) {
        if (this._clipPath && this._clipPath !== clipPath) {
            this.removeClipPath();
        }
        this._attachComponent(clipPath);
        this._clipPath = clipPath;
        this.markRedraw();
    };
    Element.prototype.removeClipPath = function () {
        var clipPath = this._clipPath;
        if (clipPath) {
            this._detachComponent(clipPath);
            this._clipPath = null;
            this.markRedraw();
        }
    };
    Element.prototype.getTextContent = function () {
        return this._textContent;
    };
    Element.prototype.setTextContent = function (textEl) {
        var previousTextContent = this._textContent;
        if (previousTextContent === textEl) {
            return;
        }
        if (previousTextContent && previousTextContent !== textEl) {
            this.removeTextContent();
        }
        textEl.innerTransformable = new Transformable();
        this._attachComponent(textEl);
        this._textContent = textEl;
        this.markRedraw();
    };
    Element.prototype.setTextConfig = function (cfg) {
        if (!this.textConfig) {
            this.textConfig = {};
        }
        extend(this.textConfig, cfg);
        this.markRedraw();
    };
    Element.prototype.removeTextConfig = function () {
        this.textConfig = null;
        this.markRedraw();
    };
    Element.prototype.removeTextContent = function () {
        var textEl = this._textContent;
        if (textEl) {
            textEl.innerTransformable = null;
            this._detachComponent(textEl);
            this._textContent = null;
            this._innerTextDefaultStyle = null;
            this.markRedraw();
        }
    };
    Element.prototype.getTextGuideLine = function () {
        return this._textGuide;
    };
    Element.prototype.setTextGuideLine = function (guideLine) {
        if (this._textGuide && this._textGuide !== guideLine) {
            this.removeTextGuideLine();
        }
        this._attachComponent(guideLine);
        this._textGuide = guideLine;
        this.markRedraw();
    };
    Element.prototype.removeTextGuideLine = function () {
        var textGuide = this._textGuide;
        if (textGuide) {
            this._detachComponent(textGuide);
            this._textGuide = null;
            this.markRedraw();
        }
    };
    Element.prototype.markRedraw = function () {
        this.__dirty |= REDRAW_BIT;
        var zr = this.__zr;
        if (zr) {
            if (this.__inHover) {
                zr.refreshHover();
            }
            else {
                zr.refresh();
            }
        }
        if (this.__hostTarget) {
            this.__hostTarget.markRedraw();
        }
    };
    Element.prototype.dirty = function () {
        this.markRedraw();
    };
    Element.prototype._toggleHoverLayerFlag = function (inHover) {
        this.__inHover = inHover;
        var textContent = this._textContent;
        var textGuide = this._textGuide;
        if (textContent) {
            textContent.__inHover = inHover;
        }
        if (textGuide) {
            textGuide.__inHover = inHover;
        }
    };
    Element.prototype.addSelfToZr = function (zr) {
        if (this.__zr === zr) {
            return;
        }
        this.__zr = zr;
        var animators = this.animators;
        if (animators) {
            for (var i = 0; i < animators.length; i++) {
                zr.animation.addAnimator(animators[i]);
            }
        }
        if (this._clipPath) {
            this._clipPath.addSelfToZr(zr);
        }
        if (this._textContent) {
            this._textContent.addSelfToZr(zr);
        }
        if (this._textGuide) {
            this._textGuide.addSelfToZr(zr);
        }
    };
    Element.prototype.removeSelfFromZr = function (zr) {
        if (!this.__zr) {
            return;
        }
        this.__zr = null;
        var animators = this.animators;
        if (animators) {
            for (var i = 0; i < animators.length; i++) {
                zr.animation.removeAnimator(animators[i]);
            }
        }
        if (this._clipPath) {
            this._clipPath.removeSelfFromZr(zr);
        }
        if (this._textContent) {
            this._textContent.removeSelfFromZr(zr);
        }
        if (this._textGuide) {
            this._textGuide.removeSelfFromZr(zr);
        }
    };
    Element.prototype.animate = function (key, loop, allowDiscreteAnimation) {
        var target = key ? this[key] : this;
        var animator = new Animator$1(target, loop, allowDiscreteAnimation);
        key && (animator.targetName = key);
        this.addAnimator(animator, key);
        return animator;
    };
    Element.prototype.addAnimator = function (animator, key) {
        var zr = this.__zr;
        var el = this;
        animator.during(function () {
            el.updateDuringAnimation(key);
        }).done(function () {
            var animators = el.animators;
            var idx = indexOf(animators, animator);
            if (idx >= 0) {
                animators.splice(idx, 1);
            }
        });
        this.animators.push(animator);
        if (zr) {
            zr.animation.addAnimator(animator);
        }
        zr && zr.wakeUp();
    };
    Element.prototype.updateDuringAnimation = function (key) {
        this.markRedraw();
    };
    Element.prototype.stopAnimation = function (scope, forwardToLast) {
        var animators = this.animators;
        var len = animators.length;
        var leftAnimators = [];
        for (var i = 0; i < len; i++) {
            var animator = animators[i];
            if (!scope || scope === animator.scope) {
                animator.stop(forwardToLast);
            }
            else {
                leftAnimators.push(animator);
            }
        }
        this.animators = leftAnimators;
        return this;
    };
    Element.prototype.animateTo = function (target, cfg, animationProps) {
        animateTo(this, target, cfg, animationProps);
    };
    Element.prototype.animateFrom = function (target, cfg, animationProps) {
        animateTo(this, target, cfg, animationProps, true);
    };
    Element.prototype._transitionState = function (stateName, target, cfg, animationProps) {
        var animators = animateTo(this, target, cfg, animationProps);
        for (var i = 0; i < animators.length; i++) {
            animators[i].__fromStateTransition = stateName;
        }
    };
    Element.prototype.getBoundingRect = function () {
        return null;
    };
    Element.prototype.getPaintRect = function () {
        return null;
    };
    Element.initDefaultProps = (function () {
        var elProto = Element.prototype;
        elProto.type = 'element';
        elProto.name = '';
        elProto.ignore =
            elProto.silent =
                elProto.isGroup =
                    elProto.draggable =
                        elProto.dragging =
                            elProto.ignoreClip =
                                elProto.__inHover = false;
        elProto.__dirty = REDRAW_BIT;
        function createLegacyProperty(key, privateKey, xKey, yKey) {
            Object.defineProperty(elProto, key, {
                get: function () {
                    if (!this[privateKey]) {
                        var pos = this[privateKey] = [];
                        enhanceArray(this, pos);
                    }
                    return this[privateKey];
                },
                set: function (pos) {
                    this[xKey] = pos[0];
                    this[yKey] = pos[1];
                    this[privateKey] = pos;
                    enhanceArray(this, pos);
                }
            });
            function enhanceArray(self, pos) {
                Object.defineProperty(pos, 0, {
                    get: function () {
                        return self[xKey];
                    },
                    set: function (val) {
                        self[xKey] = val;
                    }
                });
                Object.defineProperty(pos, 1, {
                    get: function () {
                        return self[yKey];
                    },
                    set: function (val) {
                        self[yKey] = val;
                    }
                });
            }
        }
        if (Object.defineProperty) {
            createLegacyProperty('position', '_legacyPos', 'x', 'y');
            createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY');
            createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY');
        }
    })();
    return Element;
}());
mixin(Element$1, Eventful$1);
mixin(Element$1, Transformable);
function animateTo(animatable, target, cfg, animationProps, reverse) {
    cfg = cfg || {};
    var animators = [];
    animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse);
    var finishCount = animators.length;
    var doneHappened = false;
    var cfgDone = cfg.done;
    var cfgAborted = cfg.aborted;
    var doneCb = function () {
        doneHappened = true;
        finishCount--;
        if (finishCount <= 0) {
            doneHappened
                ? (cfgDone && cfgDone())
                : (cfgAborted && cfgAborted());
        }
    };
    var abortedCb = function () {
        finishCount--;
        if (finishCount <= 0) {
            doneHappened
                ? (cfgDone && cfgDone())
                : (cfgAborted && cfgAborted());
        }
    };
    if (!finishCount) {
        cfgDone && cfgDone();
    }
    if (animators.length > 0 && cfg.during) {
        animators[0].during(function (target, percent) {
            cfg.during(percent);
        });
    }
    for (var i = 0; i < animators.length; i++) {
        var animator = animators[i];
        if (doneCb) {
            animator.done(doneCb);
        }
        if (abortedCb) {
            animator.aborted(abortedCb);
        }
        if (cfg.force) {
            animator.duration(cfg.duration);
        }
        animator.start(cfg.easing);
    }
    return animators;
}
function copyArrShallow(source, target, len) {
    for (var i = 0; i < len; i++) {
        source[i] = target[i];
    }
}
function is2DArray(value) {
    return isArrayLike(value[0]);
}
function copyValue(target, source, key) {
    if (isArrayLike(source[key])) {
        if (!isArrayLike(target[key])) {
            target[key] = [];
        }
        if (isTypedArray(source[key])) {
            var len = source[key].length;
            if (target[key].length !== len) {
                target[key] = new (source[key].constructor)(len);
                copyArrShallow(target[key], source[key], len);
            }
        }
        else {
            var sourceArr = source[key];
            var targetArr = target[key];
            var len0 = sourceArr.length;
            if (is2DArray(sourceArr)) {
                var len1 = sourceArr[0].length;
                for (var i = 0; i < len0; i++) {
                    if (!targetArr[i]) {
                        targetArr[i] = Array.prototype.slice.call(sourceArr[i]);
                    }
                    else {
                        copyArrShallow(targetArr[i], sourceArr[i], len1);
                    }
                }
            }
            else {
                copyArrShallow(targetArr, sourceArr, len0);
            }
            targetArr.length = sourceArr.length;
        }
    }
    else {
        target[key] = source[key];
    }
}
function isValueSame(val1, val2) {
    return val1 === val2
        || isArrayLike(val1) && isArrayLike(val2) && is1DArraySame(val1, val2);
}
function is1DArraySame(arr0, arr1) {
    var len = arr0.length;
    if (len !== arr1.length) {
        return false;
    }
    for (var i = 0; i < len; i++) {
        if (arr0[i] !== arr1[i]) {
            return false;
        }
    }
    return true;
}
function animateToShallow(animatable, topKey, animateObj, target, cfg, animationProps, animators, reverse) {
    var targetKeys = keys(target);
    var duration = cfg.duration;
    var delay = cfg.delay;
    var additive = cfg.additive;
    var setToFinal = cfg.setToFinal;
    var animateAll = !isObject$2(animationProps);
    var existsAnimators = animatable.animators;
    var animationKeys = [];
    for (var k = 0; k < targetKeys.length; k++) {
        var innerKey = targetKeys[k];
        var targetVal = target[innerKey];
        if (targetVal != null && animateObj[innerKey] != null
            && (animateAll || animationProps[innerKey])) {
            if (isObject$2(targetVal)
                && !isArrayLike(targetVal)
                && !isGradientObject(targetVal)) {
                if (topKey) {
                    if (!reverse) {
                        animateObj[innerKey] = targetVal;
                        animatable.updateDuringAnimation(topKey);
                    }
                    continue;
                }
                animateToShallow(animatable, innerKey, animateObj[innerKey], targetVal, cfg, animationProps && animationProps[innerKey], animators, reverse);
            }
            else {
                animationKeys.push(innerKey);
            }
        }
        else if (!reverse) {
            animateObj[innerKey] = targetVal;
            animatable.updateDuringAnimation(topKey);
            animationKeys.push(innerKey);
        }
    }
    var keyLen = animationKeys.length;
    if (!additive && keyLen) {
        for (var i = 0; i < existsAnimators.length; i++) {
            var animator = existsAnimators[i];
            if (animator.targetName === topKey) {
                var allAborted = animator.stopTracks(animationKeys);
                if (allAborted) {
                    var idx = indexOf(existsAnimators, animator);
                    existsAnimators.splice(idx, 1);
                }
            }
        }
    }
    if (!cfg.force) {
        animationKeys = filter(animationKeys, function (key) { return !isValueSame(target[key], animateObj[key]); });
        keyLen = animationKeys.length;
    }
    if (keyLen > 0
        || (cfg.force && !animators.length)) {
        var revertedSource = void 0;
        var reversedTarget = void 0;
        var sourceClone = void 0;
        if (reverse) {
            reversedTarget = {};
            if (setToFinal) {
                revertedSource = {};
            }
            for (var i = 0; i < keyLen; i++) {
                var innerKey = animationKeys[i];
                reversedTarget[innerKey] = animateObj[innerKey];
                if (setToFinal) {
                    revertedSource[innerKey] = target[innerKey];
                }
                else {
                    animateObj[innerKey] = target[innerKey];
                }
            }
        }
        else if (setToFinal) {
            sourceClone = {};
            for (var i = 0; i < keyLen; i++) {
                var innerKey = animationKeys[i];
                sourceClone[innerKey] = cloneValue(animateObj[innerKey]);
                copyValue(animateObj, target, innerKey);
            }
        }
        var animator = new Animator$1(animateObj, false, false, additive ? filter(existsAnimators, function (animator) { return animator.targetName === topKey; }) : null);
        animator.targetName = topKey;
        if (cfg.scope) {
            animator.scope = cfg.scope;
        }
        if (setToFinal && revertedSource) {
            animator.whenWithKeys(0, revertedSource, animationKeys);
        }
        if (sourceClone) {
            animator.whenWithKeys(0, sourceClone, animationKeys);
        }
        animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animationKeys).delay(delay || 0);
        animatable.addAnimator(animator, topKey);
        animators.push(animator);
    }
}
const Element$2 = Element$1;

/* Injected with object hook! */

var Group$2 = (function (_super) {
    __extends(Group, _super);
    function Group(opts) {
        var _this = _super.call(this) || this;
        _this.isGroup = true;
        _this._children = [];
        _this.attr(opts);
        return _this;
    }
    Group.prototype.childrenRef = function () {
        return this._children;
    };
    Group.prototype.children = function () {
        return this._children.slice();
    };
    Group.prototype.childAt = function (idx) {
        return this._children[idx];
    };
    Group.prototype.childOfName = function (name) {
        var children = this._children;
        for (var i = 0; i < children.length; i++) {
            if (children[i].name === name) {
                return children[i];
            }
        }
    };
    Group.prototype.childCount = function () {
        return this._children.length;
    };
    Group.prototype.add = function (child) {
        if (child) {
            if (child !== this && child.parent !== this) {
                this._children.push(child);
                this._doAdd(child);
            }
        }
        return this;
    };
    Group.prototype.addBefore = function (child, nextSibling) {
        if (child && child !== this && child.parent !== this
            && nextSibling && nextSibling.parent === this) {
            var children = this._children;
            var idx = children.indexOf(nextSibling);
            if (idx >= 0) {
                children.splice(idx, 0, child);
                this._doAdd(child);
            }
        }
        return this;
    };
    Group.prototype.replace = function (oldChild, newChild) {
        var idx = indexOf(this._children, oldChild);
        if (idx >= 0) {
            this.replaceAt(newChild, idx);
        }
        return this;
    };
    Group.prototype.replaceAt = function (child, index) {
        var children = this._children;
        var old = children[index];
        if (child && child !== this && child.parent !== this && child !== old) {
            children[index] = child;
            old.parent = null;
            var zr = this.__zr;
            if (zr) {
                old.removeSelfFromZr(zr);
            }
            this._doAdd(child);
        }
        return this;
    };
    Group.prototype._doAdd = function (child) {
        if (child.parent) {
            child.parent.remove(child);
        }
        child.parent = this;
        var zr = this.__zr;
        if (zr && zr !== child.__zr) {
            child.addSelfToZr(zr);
        }
        zr && zr.refresh();
    };
    Group.prototype.remove = function (child) {
        var zr = this.__zr;
        var children = this._children;
        var idx = indexOf(children, child);
        if (idx < 0) {
            return this;
        }
        children.splice(idx, 1);
        child.parent = null;
        if (zr) {
            child.removeSelfFromZr(zr);
        }
        zr && zr.refresh();
        return this;
    };
    Group.prototype.removeAll = function () {
        var children = this._children;
        var zr = this.__zr;
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            if (zr) {
                child.removeSelfFromZr(zr);
            }
            child.parent = null;
        }
        children.length = 0;
        return this;
    };
    Group.prototype.eachChild = function (cb, context) {
        var children = this._children;
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            cb.call(context, child, i);
        }
        return this;
    };
    Group.prototype.traverse = function (cb, context) {
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            var stopped = cb.call(context, child);
            if (child.isGroup && !stopped) {
                child.traverse(cb, context);
            }
        }
        return this;
    };
    Group.prototype.addSelfToZr = function (zr) {
        _super.prototype.addSelfToZr.call(this, zr);
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            child.addSelfToZr(zr);
        }
    };
    Group.prototype.removeSelfFromZr = function (zr) {
        _super.prototype.removeSelfFromZr.call(this, zr);
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            child.removeSelfFromZr(zr);
        }
    };
    Group.prototype.getBoundingRect = function (includeChildren) {
        var tmpRect = new BoundingRect$1(0, 0, 0, 0);
        var children = includeChildren || this._children;
        var tmpMat = [];
        var rect = null;
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            if (child.ignore || child.invisible) {
                continue;
            }
            var childRect = child.getBoundingRect();
            var transform = child.getLocalTransform(tmpMat);
            if (transform) {
                BoundingRect$1.applyTransform(tmpRect, childRect, transform);
                rect = rect || tmpRect.clone();
                rect.union(tmpRect);
            }
            else {
                rect = rect || childRect.clone();
                rect.union(childRect);
            }
        }
        return rect || tmpRect;
    };
    return Group;
}(Element$2));
Group$2.prototype.type = 'group';
const Group$3 = Group$2;

/* Injected with object hook! */

/*!
* ZRender, a high performance 2d drawing library.
*
* Copyright (c) 2013, Baidu Inc.
* All rights reserved.
*
* LICENSE
* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
*/
var painterCtors = {};
var instances$1 = {};
function delInstance(id) {
    delete instances$1[id];
}
function isDarkMode(backgroundColor) {
    if (!backgroundColor) {
        return false;
    }
    if (typeof backgroundColor === 'string') {
        return lum(backgroundColor, 1) < DARK_MODE_THRESHOLD;
    }
    else if (backgroundColor.colorStops) {
        var colorStops = backgroundColor.colorStops;
        var totalLum = 0;
        var len = colorStops.length;
        for (var i = 0; i < len; i++) {
            totalLum += lum(colorStops[i].color, 1);
        }
        totalLum /= len;
        return totalLum < DARK_MODE_THRESHOLD;
    }
    return false;
}
var ZRender = (function () {
    function ZRender(id, dom, opts) {
        var _this = this;
        this._sleepAfterStill = 10;
        this._stillFrameAccum = 0;
        this._needsRefresh = true;
        this._needsRefreshHover = true;
        this._darkMode = false;
        opts = opts || {};
        this.dom = dom;
        this.id = id;
        var storage = new Storage$1();
        var rendererType = opts.renderer || 'canvas';
        if (!painterCtors[rendererType]) {
            rendererType = keys(painterCtors)[0];
        }
        opts.useDirtyRect = opts.useDirtyRect == null
            ? false
            : opts.useDirtyRect;
        var painter = new painterCtors[rendererType](dom, storage, opts, id);
        var ssrMode = opts.ssr || painter.ssrOnly;
        this.storage = storage;
        this.painter = painter;
        var handerProxy = (!env$1.node && !env$1.worker && !ssrMode)
            ? new HandlerProxy(painter.getViewportRoot(), painter.root)
            : null;
        var useCoarsePointer = opts.useCoarsePointer;
        var usePointerSize = (useCoarsePointer == null || useCoarsePointer === 'auto')
            ? env$1.touchEventsSupported
            : !!useCoarsePointer;
        var defaultPointerSize = 44;
        var pointerSize;
        if (usePointerSize) {
            pointerSize = retrieve2(opts.pointerSize, defaultPointerSize);
        }
        this.handler = new Handler$1(storage, painter, handerProxy, painter.root, pointerSize);
        this.animation = new Animation$1({
            stage: {
                update: ssrMode ? null : function () { return _this._flush(true); }
            }
        });
        if (!ssrMode) {
            this.animation.start();
        }
    }
    ZRender.prototype.add = function (el) {
        if (!el) {
            return;
        }
        this.storage.addRoot(el);
        el.addSelfToZr(this);
        this.refresh();
    };
    ZRender.prototype.remove = function (el) {
        if (!el) {
            return;
        }
        this.storage.delRoot(el);
        el.removeSelfFromZr(this);
        this.refresh();
    };
    ZRender.prototype.configLayer = function (zLevel, config) {
        if (this.painter.configLayer) {
            this.painter.configLayer(zLevel, config);
        }
        this.refresh();
    };
    ZRender.prototype.setBackgroundColor = function (backgroundColor) {
        if (this.painter.setBackgroundColor) {
            this.painter.setBackgroundColor(backgroundColor);
        }
        this.refresh();
        this._backgroundColor = backgroundColor;
        this._darkMode = isDarkMode(backgroundColor);
    };
    ZRender.prototype.getBackgroundColor = function () {
        return this._backgroundColor;
    };
    ZRender.prototype.setDarkMode = function (darkMode) {
        this._darkMode = darkMode;
    };
    ZRender.prototype.isDarkMode = function () {
        return this._darkMode;
    };
    ZRender.prototype.refreshImmediately = function (fromInside) {
        if (!fromInside) {
            this.animation.update(true);
        }
        this._needsRefresh = false;
        this.painter.refresh();
        this._needsRefresh = false;
    };
    ZRender.prototype.refresh = function () {
        this._needsRefresh = true;
        this.animation.start();
    };
    ZRender.prototype.flush = function () {
        this._flush(false);
    };
    ZRender.prototype._flush = function (fromInside) {
        var triggerRendered;
        var start = getTime();
        if (this._needsRefresh) {
            triggerRendered = true;
            this.refreshImmediately(fromInside);
        }
        if (this._needsRefreshHover) {
            triggerRendered = true;
            this.refreshHoverImmediately();
        }
        var end = getTime();
        if (triggerRendered) {
            this._stillFrameAccum = 0;
            this.trigger('rendered', {
                elapsedTime: end - start
            });
        }
        else if (this._sleepAfterStill > 0) {
            this._stillFrameAccum++;
            if (this._stillFrameAccum > this._sleepAfterStill) {
                this.animation.stop();
            }
        }
    };
    ZRender.prototype.setSleepAfterStill = function (stillFramesCount) {
        this._sleepAfterStill = stillFramesCount;
    };
    ZRender.prototype.wakeUp = function () {
        this.animation.start();
        this._stillFrameAccum = 0;
    };
    ZRender.prototype.refreshHover = function () {
        this._needsRefreshHover = true;
    };
    ZRender.prototype.refreshHoverImmediately = function () {
        this._needsRefreshHover = false;
        if (this.painter.refreshHover && this.painter.getType() === 'canvas') {
            this.painter.refreshHover();
        }
    };
    ZRender.prototype.resize = function (opts) {
        opts = opts || {};
        this.painter.resize(opts.width, opts.height);
        this.handler.resize();
    };
    ZRender.prototype.clearAnimation = function () {
        this.animation.clear();
    };
    ZRender.prototype.getWidth = function () {
        return this.painter.getWidth();
    };
    ZRender.prototype.getHeight = function () {
        return this.painter.getHeight();
    };
    ZRender.prototype.setCursorStyle = function (cursorStyle) {
        this.handler.setCursorStyle(cursorStyle);
    };
    ZRender.prototype.findHover = function (x, y) {
        return this.handler.findHover(x, y);
    };
    ZRender.prototype.on = function (eventName, eventHandler, context) {
        this.handler.on(eventName, eventHandler, context);
        return this;
    };
    ZRender.prototype.off = function (eventName, eventHandler) {
        this.handler.off(eventName, eventHandler);
    };
    ZRender.prototype.trigger = function (eventName, event) {
        this.handler.trigger(eventName, event);
    };
    ZRender.prototype.clear = function () {
        var roots = this.storage.getRoots();
        for (var i = 0; i < roots.length; i++) {
            if (roots[i] instanceof Group$3) {
                roots[i].removeSelfFromZr(this);
            }
        }
        this.storage.delAllRoots();
        this.painter.clear();
    };
    ZRender.prototype.dispose = function () {
        this.animation.stop();
        this.clear();
        this.storage.dispose();
        this.painter.dispose();
        this.handler.dispose();
        this.animation =
            this.storage =
                this.painter =
                    this.handler = null;
        delInstance(this.id);
    };
    return ZRender;
}());
function init$1(dom, opts) {
    var zr = new ZRender(guid(), dom, opts);
    instances$1[zr.id] = zr;
    return zr;
}
function registerPainter(name, Ctor) {
    painterCtors[name] = Ctor;
}

/* Injected with object hook! */

var RADIAN_EPSILON = 1e-4; // Although chrome already enlarge this number to 100 for `toFixed`, but
// we sill follow the spec for compatibility.

var ROUND_SUPPORTED_PRECISION_MAX = 20;

function _trim(str) {
  return str.replace(/^\s+|\s+$/g, '');
}
/**
 * Linear mapping a value from domain to range
 * @param  val
 * @param  domain Domain extent domain[0] can be bigger than domain[1]
 * @param  range  Range extent range[0] can be bigger than range[1]
 * @param  clamp Default to be false
 */


function linearMap(val, domain, range, clamp) {
  var d0 = domain[0];
  var d1 = domain[1];
  var r0 = range[0];
  var r1 = range[1];
  var subDomain = d1 - d0;
  var subRange = r1 - r0;

  if (subDomain === 0) {
    return subRange === 0 ? r0 : (r0 + r1) / 2;
  } // Avoid accuracy problem in edge, such as
  // 146.39 - 62.83 === 83.55999999999999.
  // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError
  // It is a little verbose for efficiency considering this method
  // is a hotspot.


  if (clamp) {
    if (subDomain > 0) {
      if (val <= d0) {
        return r0;
      } else if (val >= d1) {
        return r1;
      }
    } else {
      if (val >= d0) {
        return r0;
      } else if (val <= d1) {
        return r1;
      }
    }
  } else {
    if (val === d0) {
      return r0;
    }

    if (val === d1) {
      return r1;
    }
  }

  return (val - d0) / subDomain * subRange + r0;
}
/**
 * Convert a percent string to absolute number.
 * Returns NaN if percent is not a valid string or number
 */

function parsePercent(percent, all) {
  switch (percent) {
    case 'center':
    case 'middle':
      percent = '50%';
      break;

    case 'left':
    case 'top':
      percent = '0%';
      break;

    case 'right':
    case 'bottom':
      percent = '100%';
      break;
  }

  if (isString(percent)) {
    if (_trim(percent).match(/%$/)) {
      return parseFloat(percent) / 100 * all;
    }

    return parseFloat(percent);
  }

  return percent == null ? NaN : +percent;
}
function round$1(x, precision, returnStr) {
  if (precision == null) {
    precision = 10;
  } // Avoid range error


  precision = Math.min(Math.max(0, precision), ROUND_SUPPORTED_PRECISION_MAX); // PENDING: 1.005.toFixed(2) is '1.00' rather than '1.01'

  x = (+x).toFixed(precision);
  return returnStr ? x : +x;
}
/**
 * Get precision.
 */

function getPrecision(val) {
  val = +val;

  if (isNaN(val)) {
    return 0;
  } // It is much faster than methods converting number to string as follows
  //      let tmp = val.toString();
  //      return tmp.length - 1 - tmp.indexOf('.');
  // especially when precision is low
  // Notice:
  // (1) If the loop count is over about 20, it is slower than `getPrecisionSafe`.
  //     (see https://jsbench.me/2vkpcekkvw/1)
  // (2) If the val is less than for example 1e-15, the result may be incorrect.
  //     (see test/ut/spec/util/number.test.ts `getPrecision_equal_random`)


  if (val > 1e-14) {
    var e = 1;

    for (var i = 0; i < 15; i++, e *= 10) {
      if (Math.round(val * e) / e === val) {
        return i;
      }
    }
  }

  return getPrecisionSafe(val);
}
/**
 * Get precision with slow but safe method
 */

function getPrecisionSafe(val) {
  // toLowerCase for: '3.4E-12'
  var str = val.toString().toLowerCase(); // Consider scientific notation: '3.4e-12' '3.4e+12'

  var eIndex = str.indexOf('e');
  var exp = eIndex > 0 ? +str.slice(eIndex + 1) : 0;
  var significandPartLen = eIndex > 0 ? eIndex : str.length;
  var dotIndex = str.indexOf('.');
  var decimalPartLen = dotIndex < 0 ? 0 : significandPartLen - 1 - dotIndex;
  return Math.max(0, decimalPartLen - exp);
}
/**
 * Minimal dicernible data precisioin according to a single pixel.
 */

function getPixelPrecision(dataExtent, pixelExtent) {
  var log = Math.log;
  var LN10 = Math.LN10;
  var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10);
  var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); // toFixed() digits argument must be between 0 and 20.

  var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20);
  return !isFinite(precision) ? 20 : precision;
}
/**
 * Solve the floating point adding problem like 0.1 + 0.2 === 0.30000000000000004
 * See <http://0.30000000000000004.com/>
 */

function addSafe(val0, val1) {
  var maxPrecision = Math.max(getPrecision(val0), getPrecision(val1)); // const multiplier = Math.pow(10, maxPrecision);
  // return (Math.round(val0 * multiplier) + Math.round(val1 * multiplier)) / multiplier;

  var sum = val0 + val1; // // PENDING: support more?

  return maxPrecision > ROUND_SUPPORTED_PRECISION_MAX ? sum : round$1(sum, maxPrecision);
} // Number.MAX_SAFE_INTEGER, ie do not support.
/**
 * To 0 - 2 * PI, considering negative radian.
 */

function remRadian(radian) {
  var pi2 = Math.PI * 2;
  return (radian % pi2 + pi2) % pi2;
}
/**
 * @param {type} radian
 * @return {boolean}
 */

function isRadianAroundZero(val) {
  return val > -RADIAN_EPSILON && val < RADIAN_EPSILON;
} // eslint-disable-next-line

var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d{1,2})(?::(\d{1,2})(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line

/**
 * @param value valid type: number | string | Date, otherwise return `new Date(NaN)`
 *   These values can be accepted:
 *   + An instance of Date, represent a time in its own time zone.
 *   + Or string in a subset of ISO 8601, only including:
 *     + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06',
 *     + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123',
 *     + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00',
 *     all of which will be treated as local time if time zone is not specified
 *     (see <https://momentjs.com/>).
 *   + Or other string format, including (all of which will be treated as local time):
 *     '2012', '2012-3-1', '2012/3/1', '2012/03/01',
 *     '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123'
 *   + a timestamp, which represent a time in UTC.
 * @return date Never be null/undefined. If invalid, return `new Date(NaN)`.
 */

function parseDate(value) {
  if (value instanceof Date) {
    return value;
  } else if (isString(value)) {
    // Different browsers parse date in different way, so we parse it manually.
    // Some other issues:
    // new Date('1970-01-01') is UTC,
    // new Date('1970/01/01') and new Date('1970-1-01') is local.
    // See issue #3623
    var match = TIME_REG.exec(value);

    if (!match) {
      // return Invalid Date.
      return new Date(NaN);
    } // Use local time when no timezone offset is specified.


    if (!match[8]) {
      // match[n] can only be string or undefined.
      // But take care of '12' + 1 => '121'.
      return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, match[7] ? +match[7].substring(0, 3) : 0);
    } // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time,
    // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment).
    // For example, system timezone is set as "Time Zone: America/Toronto",
    // then these code will get different result:
    // `new Date(1478411999999).getTimezoneOffset();  // get 240`
    // `new Date(1478412000000).getTimezoneOffset();  // get 300`
    // So we should not use `new Date`, but use `Date.UTC`.
    else {
        var hour = +match[4] || 0;

        if (match[8].toUpperCase() !== 'Z') {
          hour -= +match[8].slice(0, 3);
        }

        return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, match[7] ? +match[7].substring(0, 3) : 0));
      }
  } else if (value == null) {
    return new Date(NaN);
  }

  return new Date(Math.round(value));
}
/**
 * Quantity of a number. e.g. 0.1, 1, 10, 100
 *
 * @param val
 * @return
 */

function quantity(val) {
  return Math.pow(10, quantityExponent(val));
}
/**
 * Exponent of the quantity of a number
 * e.g., 1234 equals to 1.234*10^3, so quantityExponent(1234) is 3
 *
 * @param val non-negative value
 * @return
 */

function quantityExponent(val) {
  if (val === 0) {
    return 0;
  }

  var exp = Math.floor(Math.log(val) / Math.LN10);
  /**
   * exp is expected to be the rounded-down result of the base-10 log of val.
   * But due to the precision loss with Math.log(val), we need to restore it
   * using 10^exp to make sure we can get val back from exp. #11249
   */

  if (val / Math.pow(10, exp) >= 10) {
    exp++;
  }

  return exp;
}
/**
 * find a “nice” number approximately equal to x. Round the number if round = true,
 * take ceiling if round = false. The primary observation is that the “nicest”
 * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers.
 *
 * See "Nice Numbers for Graph Labels" of Graphic Gems.
 *
 * @param  val Non-negative value.
 * @param  round
 * @return Niced number
 */

function nice(val, round) {
  var exponent = quantityExponent(val);
  var exp10 = Math.pow(10, exponent);
  var f = val / exp10; // 1 <= f < 10

  var nf;

  if (round) {
    if (f < 1.5) {
      nf = 1;
    } else if (f < 2.5) {
      nf = 2;
    } else if (f < 4) {
      nf = 3;
    } else if (f < 7) {
      nf = 5;
    } else {
      nf = 10;
    }
  } else {
    if (f < 1) {
      nf = 1;
    } else if (f < 2) {
      nf = 2;
    } else if (f < 3) {
      nf = 3;
    } else if (f < 5) {
      nf = 5;
    } else {
      nf = 10;
    }
  }

  val = nf * exp10; // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
  // 20 is the uppper bound of toFixed.

  return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
}
/**
 * [Numeric is defined as]:
 *     `parseFloat(val) == val`
 * For example:
 * numeric:
 *     typeof number except NaN, '-123', '123', '2e3', '-2e3', '011', 'Infinity', Infinity,
 *     and they rounded by white-spaces or line-terminal like ' -123 \n ' (see es spec)
 * not-numeric:
 *     null, undefined, [], {}, true, false, 'NaN', NaN, '123ab',
 *     empty string, string with only white-spaces or line-terminal (see es spec),
 *     0x12, '0x12', '-0x12', 012, '012', '-012',
 *     non-string, ...
 *
 * @test See full test cases in `test/ut/spec/util/number.js`.
 * @return Must be a typeof number. If not numeric, return NaN.
 */

function numericToNumber(val) {
  var valFloat = parseFloat(val);
  return valFloat == val // eslint-disable-line eqeqeq
  && (valFloat !== 0 || !isString(val) || val.indexOf('x') <= 0) // For case ' 0x0 '.
  ? valFloat : NaN;
}
/**
 * Definition of "numeric": see `numericToNumber`.
 */

function isNumeric(val) {
  return !isNaN(numericToNumber(val));
}
/**
 * Use random base to prevent users hard code depending on
 * this auto generated marker id.
 * @return An positive integer.
 */

function getRandomIdBase() {
  return Math.round(Math.random() * 9);
}
/**
 * Get the greatest common divisor.
 *
 * @param {number} a one number
 * @param {number} b the other number
 */

function getGreatestCommonDividor(a, b) {
  if (b === 0) {
    return a;
  }

  return getGreatestCommonDividor(b, a % b);
}
/**
 * Get the least common multiple.
 *
 * @param {number} a one number
 * @param {number} b the other number
 */

function getLeastCommonMultiple(a, b) {
  if (a == null) {
    return b;
  }

  if (b == null) {
    return a;
  }

  return a * b / getGreatestCommonDividor(a, b);
}
/* Injected with object hook! */

/**
 * @throws Error
 */

function throwError(msg) {
  throw new Error(msg);
}
/* Injected with object hook! */

/**
 * Make the name displayable. But we should
 * make sure it is not duplicated with user
 * specified name, so use '\0';
 */


var DUMMY_COMPONENT_NAME_PREFIX = 'series\0';
var INTERNAL_COMPONENT_ID_PREFIX = '\0_ec_\0';
/**
 * If value is not array, then translate it to array.
 * @param  {*} value
 * @return {Array} [value] or value
 */

function normalizeToArray(value) {
  return value instanceof Array ? value : value == null ? [] : [value];
}
/**
 * Sync default option between normal and emphasis like `position` and `show`
 * In case some one will write code like
 *     label: {
 *          show: false,
 *          position: 'outside',
 *          fontSize: 18
 *     },
 *     emphasis: {
 *          label: { show: true }
 *     }
 */

function defaultEmphasis(opt, key, subOpts) {
  // Caution: performance sensitive.
  if (opt) {
    opt[key] = opt[key] || {};
    opt.emphasis = opt.emphasis || {};
    opt.emphasis[key] = opt.emphasis[key] || {}; // Default emphasis option from normal

    for (var i = 0, len = subOpts.length; i < len; i++) {
      var subOptName = subOpts[i];

      if (!opt.emphasis[key].hasOwnProperty(subOptName) && opt[key].hasOwnProperty(subOptName)) {
        opt.emphasis[key][subOptName] = opt[key][subOptName];
      }
    }
  }
}
var TEXT_STYLE_OPTIONS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth', 'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY', 'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding']; // modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([
//     'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter',
//     'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',
//     // FIXME: deprecated, check and remove it.
//     'textStyle'
// ]);

/**
 * The method does not ensure performance.
 * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
 * This helper method retrieves value from data.
 */

function getDataItemValue(dataItem) {
  return isObject$2(dataItem) && !isArray(dataItem) && !(dataItem instanceof Date) ? dataItem.value : dataItem;
}
/**
 * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
 * This helper method determine if dataItem has extra option besides value
 */

function isDataItemOption(dataItem) {
  return isObject$2(dataItem) && !(dataItem instanceof Array); // // markLine data can be array
  // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));
}
/**
 * Mapping to existings for merge.
 *
 * Mode "normalMege":
 *     The mapping result (merge result) will keep the order of the existing
 *     component, rather than the order of new option. Because we should ensure
 *     some specified index reference (like xAxisIndex) keep work.
 *     And in most cases, "merge option" is used to update partial option but not
 *     be expected to change the order.
 *
 * Mode "replaceMege":
 *     (1) Only the id mapped components will be merged.
 *     (2) Other existing components (except internal components) will be removed.
 *     (3) Other new options will be used to create new component.
 *     (4) The index of the existing components will not be modified.
 *     That means their might be "hole" after the removal.
 *     The new components are created first at those available index.
 *
 * Mode "replaceAll":
 *     This mode try to support that reproduce an echarts instance from another
 *     echarts instance (via `getOption`) in some simple cases.
 *     In this scenario, the `result` index are exactly the consistent with the `newCmptOptions`,
 *     which ensures the component index referring (like `xAxisIndex: ?`) corrent. That is,
 *     the "hole" in `newCmptOptions` will also be kept.
 *     On the contrary, other modes try best to eliminate holes.
 *     PENDING: This is an experimental mode yet.
 *
 * @return See the comment of <MappingResult>.
 */

function mappingToExists(existings, newCmptOptions, mode) {
  var isNormalMergeMode = mode === 'normalMerge';
  var isReplaceMergeMode = mode === 'replaceMerge';
  var isReplaceAllMode = mode === 'replaceAll';
  existings = existings || [];
  newCmptOptions = (newCmptOptions || []).slice();
  var existingIdIdxMap = createHashMap(); // Validate id and name on user input option.

  each$4(newCmptOptions, function (cmptOption, index) {
    if (!isObject$2(cmptOption)) {
      newCmptOptions[index] = null;
      return;
    }
  });
  var result = prepareResult(existings, existingIdIdxMap, mode);

  if (isNormalMergeMode || isReplaceMergeMode) {
    mappingById(result, existings, existingIdIdxMap, newCmptOptions);
  }

  if (isNormalMergeMode) {
    mappingByName(result, newCmptOptions);
  }

  if (isNormalMergeMode || isReplaceMergeMode) {
    mappingByIndex(result, newCmptOptions, isReplaceMergeMode);
  } else if (isReplaceAllMode) {
    mappingInReplaceAllMode(result, newCmptOptions);
  }

  makeIdAndName(result); // The array `result` MUST NOT contain elided items, otherwise the
  // forEach will omit those items and result in incorrect result.

  return result;
}

function prepareResult(existings, existingIdIdxMap, mode) {
  var result = [];

  if (mode === 'replaceAll') {
    return result;
  } // Do not use native `map` to in case that the array `existings`
  // contains elided items, which will be omitted.


  for (var index = 0; index < existings.length; index++) {
    var existing = existings[index]; // Because of replaceMerge, `existing` may be null/undefined.

    if (existing && existing.id != null) {
      existingIdIdxMap.set(existing.id, index);
    } // For non-internal-componnets:
    //     Mode "normalMerge": all existings kept.
    //     Mode "replaceMerge": all existing removed unless mapped by id.
    // For internal-components:
    //     go with "replaceMerge" approach in both mode.


    result.push({
      existing: mode === 'replaceMerge' || isComponentIdInternal(existing) ? null : existing,
      newOption: null,
      keyInfo: null,
      brandNew: null
    });
  }

  return result;
}

function mappingById(result, existings, existingIdIdxMap, newCmptOptions) {
  // Mapping by id if specified.
  each$4(newCmptOptions, function (cmptOption, index) {
    if (!cmptOption || cmptOption.id == null) {
      return;
    }

    var optionId = makeComparableKey(cmptOption.id);
    var existingIdx = existingIdIdxMap.get(optionId);

    if (existingIdx != null) {
      var resultItem = result[existingIdx];
      assert(!resultItem.newOption, 'Duplicated option on id "' + optionId + '".');
      resultItem.newOption = cmptOption; // In both mode, if id matched, new option will be merged to
      // the existings rather than creating new component model.

      resultItem.existing = existings[existingIdx];
      newCmptOptions[index] = null;
    }
  });
}

function mappingByName(result, newCmptOptions) {
  // Mapping by name if specified.
  each$4(newCmptOptions, function (cmptOption, index) {
    if (!cmptOption || cmptOption.name == null) {
      return;
    }

    for (var i = 0; i < result.length; i++) {
      var existing = result[i].existing;

      if (!result[i].newOption // Consider name: two map to one.
      // Can not match when both ids existing but different.
      && existing && (existing.id == null || cmptOption.id == null) && !isComponentIdInternal(cmptOption) && !isComponentIdInternal(existing) && keyExistAndEqual('name', existing, cmptOption)) {
        result[i].newOption = cmptOption;
        newCmptOptions[index] = null;
        return;
      }
    }
  });
}

function mappingByIndex(result, newCmptOptions, brandNew) {
  each$4(newCmptOptions, function (cmptOption) {
    if (!cmptOption) {
      return;
    } // Find the first place that not mapped by id and not internal component (consider the "hole").


    var resultItem;
    var nextIdx = 0;

    while ( // Be `!resultItem` only when `nextIdx >= result.length`.
    (resultItem = result[nextIdx]) && ( // (1) Existing models that already have id should be able to mapped to. Because
    // after mapping performed, model will always be assigned with an id if user not given.
    // After that all models have id.
    // (2) If new option has id, it can only set to a hole or append to the last. It should
    // not be merged to the existings with different id. Because id should not be overwritten.
    // (3) Name can be overwritten, because axis use name as 'show label text'.
    resultItem.newOption || isComponentIdInternal(resultItem.existing) || // In mode "replaceMerge", here no not-mapped-non-internal-existing.
    resultItem.existing && cmptOption.id != null && !keyExistAndEqual('id', cmptOption, resultItem.existing))) {
      nextIdx++;
    }

    if (resultItem) {
      resultItem.newOption = cmptOption;
      resultItem.brandNew = brandNew;
    } else {
      result.push({
        newOption: cmptOption,
        brandNew: brandNew,
        existing: null,
        keyInfo: null
      });
    }

    nextIdx++;
  });
}

function mappingInReplaceAllMode(result, newCmptOptions) {
  each$4(newCmptOptions, function (cmptOption) {
    // The feature "reproduce" requires "hole" will also reproduced
    // in case that component index referring are broken.
    result.push({
      newOption: cmptOption,
      brandNew: true,
      existing: null,
      keyInfo: null
    });
  });
}
/**
 * Make id and name for mapping result (result of mappingToExists)
 * into `keyInfo` field.
 */


function makeIdAndName(mapResult) {
  // We use this id to hash component models and view instances
  // in echarts. id can be specified by user, or auto generated.
  // The id generation rule ensures new view instance are able
  // to mapped to old instance when setOption are called in
  // no-merge mode. So we generate model id by name and plus
  // type in view id.
  // name can be duplicated among components, which is convenient
  // to specify multi components (like series) by one name.
  // Ensure that each id is distinct.
  var idMap = createHashMap();
  each$4(mapResult, function (item) {
    var existing = item.existing;
    existing && idMap.set(existing.id, item);
  });
  each$4(mapResult, function (item) {
    var opt = item.newOption; // Force ensure id not duplicated.

    assert(!opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, 'id duplicates: ' + (opt && opt.id));
    opt && opt.id != null && idMap.set(opt.id, item);
    !item.keyInfo && (item.keyInfo = {});
  }); // Make name and id.

  each$4(mapResult, function (item, index) {
    var existing = item.existing;
    var opt = item.newOption;
    var keyInfo = item.keyInfo;

    if (!isObject$2(opt)) {
      return;
    } // Name can be overwritten. Consider case: axis.name = '20km'.
    // But id generated by name will not be changed, which affect
    // only in that case: setOption with 'not merge mode' and view
    // instance will be recreated, which can be accepted.


    keyInfo.name = opt.name != null ? makeComparableKey(opt.name) : existing ? existing.name // Avoid that different series has the same name,
    // because name may be used like in color pallet.
    : DUMMY_COMPONENT_NAME_PREFIX + index;

    if (existing) {
      keyInfo.id = makeComparableKey(existing.id);
    } else if (opt.id != null) {
      keyInfo.id = makeComparableKey(opt.id);
    } else {
      // Consider this situatoin:
      //  optionA: [{name: 'a'}, {name: 'a'}, {..}]
      //  optionB [{..}, {name: 'a'}, {name: 'a'}]
      // Series with the same name between optionA and optionB
      // should be mapped.
      var idNum = 0;

      do {
        keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++;
      } while (idMap.get(keyInfo.id));
    }

    idMap.set(keyInfo.id, item);
  });
}

function keyExistAndEqual(attr, obj1, obj2) {
  var key1 = convertOptionIdName(obj1[attr], null);
  var key2 = convertOptionIdName(obj2[attr], null); // See `MappingExistingItem`. `id` and `name` trade string equals to number.

  return key1 != null && key2 != null && key1 === key2;
}
/**
 * @return return null if not exist.
 */


function makeComparableKey(val) {

  return convertOptionIdName(val, '');
}

function convertOptionIdName(idOrName, defaultValue) {
  if (idOrName == null) {
    return defaultValue;
  }

  return isString(idOrName) ? idOrName : isNumber(idOrName) || isStringSafe(idOrName) ? idOrName + '' : defaultValue;
}

function isNameSpecified(componentModel) {
  var name = componentModel.name; // Is specified when `indexOf` get -1 or > 0.

  return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX));
}
/**
 * @public
 * @param {Object} cmptOption
 * @return {boolean}
 */

function isComponentIdInternal(cmptOption) {
  return cmptOption && cmptOption.id != null && makeComparableKey(cmptOption.id).indexOf(INTERNAL_COMPONENT_ID_PREFIX) === 0;
}
function setComponentTypeToKeyInfo(mappingResult, mainType, componentModelCtor) {
  // Set mainType and complete subType.
  each$4(mappingResult, function (item) {
    var newOption = item.newOption;

    if (isObject$2(newOption)) {
      item.keyInfo.mainType = mainType;
      item.keyInfo.subType = determineSubType(mainType, newOption, item.existing, componentModelCtor);
    }
  });
}

function determineSubType(mainType, newCmptOption, existComponent, componentModelCtor) {
  var subType = newCmptOption.type ? newCmptOption.type : existComponent ? existComponent.subType // Use determineSubType only when there is no existComponent.
  : componentModelCtor.determineSubType(mainType, newCmptOption); // tooltip, markline, markpoint may always has no subType

  return subType;
}
/**
 * @param payload Contains dataIndex (means rawIndex) / dataIndexInside / name
 *                         each of which can be Array or primary type.
 * @return dataIndex If not found, return undefined/null.
 */

function queryDataIndex(data, payload) {
  if (payload.dataIndexInside != null) {
    return payload.dataIndexInside;
  } else if (payload.dataIndex != null) {
    return isArray(payload.dataIndex) ? map$1(payload.dataIndex, function (value) {
      return data.indexOfRawIndex(value);
    }) : data.indexOfRawIndex(payload.dataIndex);
  } else if (payload.name != null) {
    return isArray(payload.name) ? map$1(payload.name, function (value) {
      return data.indexOfName(value);
    }) : data.indexOfName(payload.name);
  }
}
/**
 * Enable property storage to any host object.
 * Notice: Serialization is not supported.
 *
 * For example:
 * let inner = zrUitl.makeInner();
 *
 * function some1(hostObj) {
 *      inner(hostObj).someProperty = 1212;
 *      ...
 * }
 * function some2() {
 *      let fields = inner(this);
 *      fields.someProperty1 = 1212;
 *      fields.someProperty2 = 'xx';
 *      ...
 * }
 *
 * @return {Function}
 */

function makeInner() {
  var key = '__ec_inner_' + innerUniqueIndex++;
  return function (hostObj) {
    return hostObj[key] || (hostObj[key] = {});
  };
}
var innerUniqueIndex = getRandomIdBase();
/**
 * The same behavior as `component.getReferringComponents`.
 */

function parseFinder(ecModel, finderInput, opt) {
  var _a = preParseFinder(finderInput, opt),
      mainTypeSpecified = _a.mainTypeSpecified,
      queryOptionMap = _a.queryOptionMap,
      others = _a.others;

  var result = others;
  var defaultMainType = opt ? opt.defaultMainType : null;

  if (!mainTypeSpecified && defaultMainType) {
    queryOptionMap.set(defaultMainType, {});
  }

  queryOptionMap.each(function (queryOption, mainType) {
    var queryResult = queryReferringComponents(ecModel, mainType, queryOption, {
      useDefault: defaultMainType === mainType,
      enableAll: opt && opt.enableAll != null ? opt.enableAll : true,
      enableNone: opt && opt.enableNone != null ? opt.enableNone : true
    });
    result[mainType + 'Models'] = queryResult.models;
    result[mainType + 'Model'] = queryResult.models[0];
  });
  return result;
}
function preParseFinder(finderInput, opt) {
  var finder;

  if (isString(finderInput)) {
    var obj = {};
    obj[finderInput + 'Index'] = 0;
    finder = obj;
  } else {
    finder = finderInput;
  }

  var queryOptionMap = createHashMap();
  var others = {};
  var mainTypeSpecified = false;
  each$4(finder, function (value, key) {
    // Exclude 'dataIndex' and other illgal keys.
    if (key === 'dataIndex' || key === 'dataIndexInside') {
      others[key] = value;
      return;
    }

    var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || [];
    var mainType = parsedKey[1];
    var queryType = (parsedKey[2] || '').toLowerCase();

    if (!mainType || !queryType || opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0) {
      return;
    }

    mainTypeSpecified = mainTypeSpecified || !!mainType;
    var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {});
    queryOption[queryType] = value;
  });
  return {
    mainTypeSpecified: mainTypeSpecified,
    queryOptionMap: queryOptionMap,
    others: others
  };
}
var SINGLE_REFERRING = {
  useDefault: true,
  enableAll: false,
  enableNone: false
};
function queryReferringComponents(ecModel, mainType, userOption, opt) {
  opt = opt || SINGLE_REFERRING;
  var indexOption = userOption.index;
  var idOption = userOption.id;
  var nameOption = userOption.name;
  var result = {
    models: null,
    specified: indexOption != null || idOption != null || nameOption != null
  };

  if (!result.specified) {
    // Use the first as default if `useDefault`.
    var firstCmpt = void 0;
    result.models = opt.useDefault && (firstCmpt = ecModel.getComponent(mainType)) ? [firstCmpt] : [];
    return result;
  }

  if (indexOption === 'none' || indexOption === false) {
    assert(opt.enableNone, '`"none"` or `false` is not a valid value on index option.');
    result.models = [];
    return result;
  } // `queryComponents` will return all components if
  // both all of index/id/name are null/undefined.


  if (indexOption === 'all') {
    assert(opt.enableAll, '`"all"` is not a valid value on index option.');
    indexOption = idOption = nameOption = null;
  }

  result.models = ecModel.queryComponents({
    mainType: mainType,
    index: indexOption,
    id: idOption,
    name: nameOption
  });
  return result;
}
function setAttribute(dom, key, value) {
  dom.setAttribute ? dom.setAttribute(key, value) : dom[key] = value;
}
function getAttribute(dom, key) {
  return dom.getAttribute ? dom.getAttribute(key) : dom[key];
}
function getTooltipRenderMode(renderModeOption) {
  if (renderModeOption === 'auto') {
    // Using html when `document` exists, use richText otherwise
    return env$1.domSupported ? 'html' : 'richText';
  } else {
    return renderModeOption || 'html';
  }
}
/* Injected with object hook! */

var TYPE_DELIMITER = '.';
var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';
var IS_EXTENDED_CLASS = '___EC__EXTENDED_CLASS___';
/**
 * Notice, parseClassType('') should returns {main: '', sub: ''}
 * @public
 */

function parseClassType(componentType) {
  var ret = {
    main: '',
    sub: ''
  };

  if (componentType) {
    var typeArr = componentType.split(TYPE_DELIMITER);
    ret.main = typeArr[0] || '';
    ret.sub = typeArr[1] || '';
  }

  return ret;
}
/**
 * @public
 */

function checkClassType(componentType) {
  assert(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), 'componentType "' + componentType + '" illegal');
}

function isExtendedClass(clz) {
  return !!(clz && clz[IS_EXTENDED_CLASS]);
}
/**
 * Implements `ExtendableConstructor` for `rootClz`.
 *
 * @usage
 * ```ts
 * class Xxx {}
 * type XxxConstructor = typeof Xxx & ExtendableConstructor
 * enableClassExtend(Xxx as XxxConstructor);
 * ```
 */

function enableClassExtend(rootClz, mandatoryMethods) {
  rootClz.$constructor = rootClz; // FIXME: not necessary?

  rootClz.extend = function (proto) {

    var superClass = this;
    var ExtendedClass;

    if (isESClass(superClass)) {
      ExtendedClass =
      /** @class */
      function (_super) {
        __extends(class_1, _super);

        function class_1() {
          return _super.apply(this, arguments) || this;
        }

        return class_1;
      }(superClass);
    } else {
      // For backward compat, we both support ts class inheritance and this
      // "extend" approach.
      // The constructor should keep the same behavior as ts class inheritance:
      // If this constructor/$constructor is not declared, auto invoke the super
      // constructor.
      // If this constructor/$constructor is declared, it is responsible for
      // calling the super constructor.
      ExtendedClass = function () {
        (proto.$constructor || superClass).apply(this, arguments);
      };

      inherits(ExtendedClass, this);
    }

    extend(ExtendedClass.prototype, proto);
    ExtendedClass[IS_EXTENDED_CLASS] = true;
    ExtendedClass.extend = this.extend;
    ExtendedClass.superCall = superCall;
    ExtendedClass.superApply = superApply;
    ExtendedClass.superClass = superClass;
    return ExtendedClass;
  };
}

function isESClass(fn) {
  return isFunction(fn) && /^class\s/.test(Function.prototype.toString.call(fn));
}
/**
 * A work around to both support ts extend and this extend mechanism.
 * on sub-class.
 * @usage
 * ```ts
 * class Component { ... }
 * classUtil.enableClassExtend(Component);
 * classUtil.enableClassManagement(Component, {registerWhenExtend: true});
 *
 * class Series extends Component { ... }
 * // Without calling `markExtend`, `registerWhenExtend` will not work.
 * Component.markExtend(Series);
 * ```
 */


function mountExtend(SubClz, SupperClz) {
  SubClz.extend = SupperClz.extend;
} // A random offset.

var classBase = Math.round(Math.random() * 10);
/**
 * Implements `CheckableConstructor` for `target`.
 * Can not use instanceof, consider different scope by
 * cross domain or es module import in ec extensions.
 * Mount a method "isInstance()" to Clz.
 *
 * @usage
 * ```ts
 * class Xxx {}
 * type XxxConstructor = typeof Xxx & CheckableConstructor;
 * enableClassCheck(Xxx as XxxConstructor)
 * ```
 */

function enableClassCheck(target) {
  var classAttr = ['__\0is_clz', classBase++].join('_');
  target.prototype[classAttr] = true;

  target.isInstance = function (obj) {
    return !!(obj && obj[classAttr]);
  };
} // superCall should have class info, which can not be fetched from 'this'.
// Consider this case:
// class A has method f,
// class B inherits class A, overrides method f, f call superApply('f'),
// class C inherits class B, does not override method f,
// then when method of class C is called, dead loop occurred.

function superCall(context, methodName) {
  var args = [];

  for (var _i = 2; _i < arguments.length; _i++) {
    args[_i - 2] = arguments[_i];
  }

  return this.superClass.prototype[methodName].apply(context, args);
}

function superApply(context, methodName, args) {
  return this.superClass.prototype[methodName].apply(context, args);
}
/**
 * Implements `ClassManager` for `target`
 *
 * @usage
 * ```ts
 * class Xxx {}
 * type XxxConstructor = typeof Xxx & ClassManager
 * enableClassManagement(Xxx as XxxConstructor);
 * ```
 */


function enableClassManagement(target) {
  /**
   * Component model classes
   * key: componentType,
   * value:
   *     componentClass, when componentType is 'a'
   *     or Object.<subKey, componentClass>, when componentType is 'a.b'
   */
  var storage = {};

  target.registerClass = function (clz) {
    // `type` should not be a "instance member".
    // If using TS class, should better declared as `static type = 'series.pie'`.
    // otherwise users have to mount `type` on prototype manually.
    // For backward compat and enable instance visit type via `this.type`,
    // we still support fetch `type` from prototype.
    var componentFullType = clz.type || clz.prototype.type;

    if (componentFullType) {
      checkClassType(componentFullType); // If only static type declared, we assign it to prototype mandatorily.

      clz.prototype.type = componentFullType;
      var componentTypeInfo = parseClassType(componentFullType);

      if (!componentTypeInfo.sub) {

        storage[componentTypeInfo.main] = clz;
      } else if (componentTypeInfo.sub !== IS_CONTAINER) {
        var container = makeContainer(componentTypeInfo);
        container[componentTypeInfo.sub] = clz;
      }
    }

    return clz;
  };

  target.getClass = function (mainType, subType, throwWhenNotFound) {
    var clz = storage[mainType];

    if (clz && clz[IS_CONTAINER]) {
      clz = subType ? clz[subType] : null;
    }

    if (throwWhenNotFound && !clz) {
      throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.');
    }

    return clz;
  };

  target.getClassesByMainType = function (componentType) {
    var componentTypeInfo = parseClassType(componentType);
    var result = [];
    var obj = storage[componentTypeInfo.main];

    if (obj && obj[IS_CONTAINER]) {
      each$4(obj, function (o, type) {
        type !== IS_CONTAINER && result.push(o);
      });
    } else {
      result.push(obj);
    }

    return result;
  };

  target.hasClass = function (componentType) {
    // Just consider componentType.main.
    var componentTypeInfo = parseClassType(componentType);
    return !!storage[componentTypeInfo.main];
  };
  /**
   * @return Like ['aa', 'bb'], but can not be ['aa.xx']
   */


  target.getAllClassMainTypes = function () {
    var types = [];
    each$4(storage, function (obj, type) {
      types.push(type);
    });
    return types;
  };
  /**
   * If a main type is container and has sub types
   */


  target.hasSubTypes = function (componentType) {
    var componentTypeInfo = parseClassType(componentType);
    var obj = storage[componentTypeInfo.main];
    return obj && obj[IS_CONTAINER];
  };

  function makeContainer(componentTypeInfo) {
    var container = storage[componentTypeInfo.main];

    if (!container || !container[IS_CONTAINER]) {
      container = storage[componentTypeInfo.main] = {};
      container[IS_CONTAINER] = true;
    }

    return container;
  }
} // /**
//  * @param {string|Array.<string>} properties
//  */
// export function setReadOnly(obj, properties) {
// FIXME It seems broken in IE8 simulation of IE11
// if (!zrUtil.isArray(properties)) {
//     properties = properties != null ? [properties] : [];
// }
// zrUtil.each(properties, function (prop) {
//     let value = obj[prop];
//     Object.defineProperty
//         && Object.defineProperty(obj, prop, {
//             value: value, writable: false
//         });
//     zrUtil.isArray(obj[prop])
//         && Object.freeze
//         && Object.freeze(obj[prop]);
// });
// }
/* Injected with object hook! */

function makeStyleMapper(properties, ignoreParent) {
  // Normalize
  for (var i = 0; i < properties.length; i++) {
    if (!properties[i][1]) {
      properties[i][1] = properties[i][0];
    }
  }

  ignoreParent = ignoreParent || false;
  return function (model, excludes, includes) {
    var style = {};

    for (var i = 0; i < properties.length; i++) {
      var propName = properties[i][1];

      if (excludes && indexOf(excludes, propName) >= 0 || includes && indexOf(includes, propName) < 0) {
        continue;
      }

      var val = model.getShallow(propName, ignoreParent);

      if (val != null) {
        style[properties[i][0]] = val;
      }
    } // TODO Text or image?


    return style;
  };
}
/* Injected with object hook! */

var AREA_STYLE_KEY_MAP = [['fill', 'color'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['opacity'], ['shadowColor'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`.
// So do not transfer decal directly.
];
var getAreaStyle = makeStyleMapper(AREA_STYLE_KEY_MAP);

var AreaStyleMixin =
/** @class */
function () {
  function AreaStyleMixin() {}

  AreaStyleMixin.prototype.getAreaStyle = function (excludes, includes) {
    return getAreaStyle(this, excludes, includes);
  };

  return AreaStyleMixin;
}();
/* Injected with object hook! */

var globalImageCache = new LRU$1(50);
function findExistImage(newImageOrSrc) {
    if (typeof newImageOrSrc === 'string') {
        var cachedImgObj = globalImageCache.get(newImageOrSrc);
        return cachedImgObj && cachedImgObj.image;
    }
    else {
        return newImageOrSrc;
    }
}
function createOrUpdateImage(newImageOrSrc, image, hostEl, onload, cbPayload) {
    if (!newImageOrSrc) {
        return image;
    }
    else if (typeof newImageOrSrc === 'string') {
        if ((image && image.__zrImageSrc === newImageOrSrc) || !hostEl) {
            return image;
        }
        var cachedImgObj = globalImageCache.get(newImageOrSrc);
        var pendingWrap = { hostEl: hostEl, cb: onload, cbPayload: cbPayload };
        if (cachedImgObj) {
            image = cachedImgObj.image;
            !isImageReady(image) && cachedImgObj.pending.push(pendingWrap);
        }
        else {
            image = platformApi.loadImage(newImageOrSrc, imageOnLoad, imageOnLoad);
            image.__zrImageSrc = newImageOrSrc;
            globalImageCache.put(newImageOrSrc, image.__cachedImgObj = {
                image: image,
                pending: [pendingWrap]
            });
        }
        return image;
    }
    else {
        return newImageOrSrc;
    }
}
function imageOnLoad() {
    var cachedImgObj = this.__cachedImgObj;
    this.onload = this.onerror = this.__cachedImgObj = null;
    for (var i = 0; i < cachedImgObj.pending.length; i++) {
        var pendingWrap = cachedImgObj.pending[i];
        var cb = pendingWrap.cb;
        cb && cb(this, pendingWrap.cbPayload);
        pendingWrap.hostEl.dirty();
    }
    cachedImgObj.pending.length = 0;
}
function isImageReady(image) {
    return image && image.width && image.height;
}

/* Injected with object hook! */

var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g;
function truncateText(text, containerWidth, font, ellipsis, options) {
    if (!containerWidth) {
        return '';
    }
    var textLines = (text + '').split('\n');
    options = prepareTruncateOptions(containerWidth, font, ellipsis, options);
    for (var i = 0, len = textLines.length; i < len; i++) {
        textLines[i] = truncateSingleLine(textLines[i], options);
    }
    return textLines.join('\n');
}
function prepareTruncateOptions(containerWidth, font, ellipsis, options) {
    options = options || {};
    var preparedOpts = extend({}, options);
    preparedOpts.font = font;
    ellipsis = retrieve2(ellipsis, '...');
    preparedOpts.maxIterations = retrieve2(options.maxIterations, 2);
    var minChar = preparedOpts.minChar = retrieve2(options.minChar, 0);
    preparedOpts.cnCharWidth = getWidth('国', font);
    var ascCharWidth = preparedOpts.ascCharWidth = getWidth('a', font);
    preparedOpts.placeholder = retrieve2(options.placeholder, '');
    var contentWidth = containerWidth = Math.max(0, containerWidth - 1);
    for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) {
        contentWidth -= ascCharWidth;
    }
    var ellipsisWidth = getWidth(ellipsis, font);
    if (ellipsisWidth > contentWidth) {
        ellipsis = '';
        ellipsisWidth = 0;
    }
    contentWidth = containerWidth - ellipsisWidth;
    preparedOpts.ellipsis = ellipsis;
    preparedOpts.ellipsisWidth = ellipsisWidth;
    preparedOpts.contentWidth = contentWidth;
    preparedOpts.containerWidth = containerWidth;
    return preparedOpts;
}
function truncateSingleLine(textLine, options) {
    var containerWidth = options.containerWidth;
    var font = options.font;
    var contentWidth = options.contentWidth;
    if (!containerWidth) {
        return '';
    }
    var lineWidth = getWidth(textLine, font);
    if (lineWidth <= containerWidth) {
        return textLine;
    }
    for (var j = 0;; j++) {
        if (lineWidth <= contentWidth || j >= options.maxIterations) {
            textLine += options.ellipsis;
            break;
        }
        var subLength = j === 0
            ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth)
            : lineWidth > 0
                ? Math.floor(textLine.length * contentWidth / lineWidth)
                : 0;
        textLine = textLine.substr(0, subLength);
        lineWidth = getWidth(textLine, font);
    }
    if (textLine === '') {
        textLine = options.placeholder;
    }
    return textLine;
}
function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) {
    var width = 0;
    var i = 0;
    for (var len = text.length; i < len && width < contentWidth; i++) {
        var charCode = text.charCodeAt(i);
        width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth;
    }
    return i;
}
function parsePlainText(text, style) {
    text != null && (text += '');
    var overflow = style.overflow;
    var padding = style.padding;
    var font = style.font;
    var truncate = overflow === 'truncate';
    var calculatedLineHeight = getLineHeight(font);
    var lineHeight = retrieve2(style.lineHeight, calculatedLineHeight);
    var bgColorDrawn = !!(style.backgroundColor);
    var truncateLineOverflow = style.lineOverflow === 'truncate';
    var width = style.width;
    var lines;
    if (width != null && (overflow === 'break' || overflow === 'breakAll')) {
        lines = text ? wrapText(text, style.font, width, overflow === 'breakAll', 0).lines : [];
    }
    else {
        lines = text ? text.split('\n') : [];
    }
    var contentHeight = lines.length * lineHeight;
    var height = retrieve2(style.height, contentHeight);
    if (contentHeight > height && truncateLineOverflow) {
        var lineCount = Math.floor(height / lineHeight);
        lines = lines.slice(0, lineCount);
    }
    if (text && truncate && width != null) {
        var options = prepareTruncateOptions(width, font, style.ellipsis, {
            minChar: style.truncateMinChar,
            placeholder: style.placeholder
        });
        for (var i = 0; i < lines.length; i++) {
            lines[i] = truncateSingleLine(lines[i], options);
        }
    }
    var outerHeight = height;
    var contentWidth = 0;
    for (var i = 0; i < lines.length; i++) {
        contentWidth = Math.max(getWidth(lines[i], font), contentWidth);
    }
    if (width == null) {
        width = contentWidth;
    }
    var outerWidth = contentWidth;
    if (padding) {
        outerHeight += padding[0] + padding[2];
        outerWidth += padding[1] + padding[3];
        width += padding[1] + padding[3];
    }
    if (bgColorDrawn) {
        outerWidth = width;
    }
    return {
        lines: lines,
        height: height,
        outerWidth: outerWidth,
        outerHeight: outerHeight,
        lineHeight: lineHeight,
        calculatedLineHeight: calculatedLineHeight,
        contentWidth: contentWidth,
        contentHeight: contentHeight,
        width: width
    };
}
var RichTextToken = (function () {
    function RichTextToken() {
    }
    return RichTextToken;
}());
var RichTextLine = (function () {
    function RichTextLine(tokens) {
        this.tokens = [];
        if (tokens) {
            this.tokens = tokens;
        }
    }
    return RichTextLine;
}());
var RichTextContentBlock = (function () {
    function RichTextContentBlock() {
        this.width = 0;
        this.height = 0;
        this.contentWidth = 0;
        this.contentHeight = 0;
        this.outerWidth = 0;
        this.outerHeight = 0;
        this.lines = [];
    }
    return RichTextContentBlock;
}());
function parseRichText(text, style) {
    var contentBlock = new RichTextContentBlock();
    text != null && (text += '');
    if (!text) {
        return contentBlock;
    }
    var topWidth = style.width;
    var topHeight = style.height;
    var overflow = style.overflow;
    var wrapInfo = (overflow === 'break' || overflow === 'breakAll') && topWidth != null
        ? { width: topWidth, accumWidth: 0, breakAll: overflow === 'breakAll' }
        : null;
    var lastIndex = STYLE_REG.lastIndex = 0;
    var result;
    while ((result = STYLE_REG.exec(text)) != null) {
        var matchedIndex = result.index;
        if (matchedIndex > lastIndex) {
            pushTokens(contentBlock, text.substring(lastIndex, matchedIndex), style, wrapInfo);
        }
        pushTokens(contentBlock, result[2], style, wrapInfo, result[1]);
        lastIndex = STYLE_REG.lastIndex;
    }
    if (lastIndex < text.length) {
        pushTokens(contentBlock, text.substring(lastIndex, text.length), style, wrapInfo);
    }
    var pendingList = [];
    var calculatedHeight = 0;
    var calculatedWidth = 0;
    var stlPadding = style.padding;
    var truncate = overflow === 'truncate';
    var truncateLine = style.lineOverflow === 'truncate';
    function finishLine(line, lineWidth, lineHeight) {
        line.width = lineWidth;
        line.lineHeight = lineHeight;
        calculatedHeight += lineHeight;
        calculatedWidth = Math.max(calculatedWidth, lineWidth);
    }
    outer: for (var i = 0; i < contentBlock.lines.length; i++) {
        var line = contentBlock.lines[i];
        var lineHeight = 0;
        var lineWidth = 0;
        for (var j = 0; j < line.tokens.length; j++) {
            var token = line.tokens[j];
            var tokenStyle = token.styleName && style.rich[token.styleName] || {};
            var textPadding = token.textPadding = tokenStyle.padding;
            var paddingH = textPadding ? textPadding[1] + textPadding[3] : 0;
            var font = token.font = tokenStyle.font || style.font;
            token.contentHeight = getLineHeight(font);
            var tokenHeight = retrieve2(tokenStyle.height, token.contentHeight);
            token.innerHeight = tokenHeight;
            textPadding && (tokenHeight += textPadding[0] + textPadding[2]);
            token.height = tokenHeight;
            token.lineHeight = retrieve3(tokenStyle.lineHeight, style.lineHeight, tokenHeight);
            token.align = tokenStyle && tokenStyle.align || style.align;
            token.verticalAlign = tokenStyle && tokenStyle.verticalAlign || 'middle';
            if (truncateLine && topHeight != null && calculatedHeight + token.lineHeight > topHeight) {
                if (j > 0) {
                    line.tokens = line.tokens.slice(0, j);
                    finishLine(line, lineWidth, lineHeight);
                    contentBlock.lines = contentBlock.lines.slice(0, i + 1);
                }
                else {
                    contentBlock.lines = contentBlock.lines.slice(0, i);
                }
                break outer;
            }
            var styleTokenWidth = tokenStyle.width;
            var tokenWidthNotSpecified = styleTokenWidth == null || styleTokenWidth === 'auto';
            if (typeof styleTokenWidth === 'string' && styleTokenWidth.charAt(styleTokenWidth.length - 1) === '%') {
                token.percentWidth = styleTokenWidth;
                pendingList.push(token);
                token.contentWidth = getWidth(token.text, font);
            }
            else {
                if (tokenWidthNotSpecified) {
                    var textBackgroundColor = tokenStyle.backgroundColor;
                    var bgImg = textBackgroundColor && textBackgroundColor.image;
                    if (bgImg) {
                        bgImg = findExistImage(bgImg);
                        if (isImageReady(bgImg)) {
                            token.width = Math.max(token.width, bgImg.width * tokenHeight / bgImg.height);
                        }
                    }
                }
                var remainTruncWidth = truncate && topWidth != null
                    ? topWidth - lineWidth : null;
                if (remainTruncWidth != null && remainTruncWidth < token.width) {
                    if (!tokenWidthNotSpecified || remainTruncWidth < paddingH) {
                        token.text = '';
                        token.width = token.contentWidth = 0;
                    }
                    else {
                        token.text = truncateText(token.text, remainTruncWidth - paddingH, font, style.ellipsis, { minChar: style.truncateMinChar });
                        token.width = token.contentWidth = getWidth(token.text, font);
                    }
                }
                else {
                    token.contentWidth = getWidth(token.text, font);
                }
            }
            token.width += paddingH;
            lineWidth += token.width;
            tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight));
        }
        finishLine(line, lineWidth, lineHeight);
    }
    contentBlock.outerWidth = contentBlock.width = retrieve2(topWidth, calculatedWidth);
    contentBlock.outerHeight = contentBlock.height = retrieve2(topHeight, calculatedHeight);
    contentBlock.contentHeight = calculatedHeight;
    contentBlock.contentWidth = calculatedWidth;
    if (stlPadding) {
        contentBlock.outerWidth += stlPadding[1] + stlPadding[3];
        contentBlock.outerHeight += stlPadding[0] + stlPadding[2];
    }
    for (var i = 0; i < pendingList.length; i++) {
        var token = pendingList[i];
        var percentWidth = token.percentWidth;
        token.width = parseInt(percentWidth, 10) / 100 * contentBlock.width;
    }
    return contentBlock;
}
function pushTokens(block, str, style, wrapInfo, styleName) {
    var isEmptyStr = str === '';
    var tokenStyle = styleName && style.rich[styleName] || {};
    var lines = block.lines;
    var font = tokenStyle.font || style.font;
    var newLine = false;
    var strLines;
    var linesWidths;
    if (wrapInfo) {
        var tokenPadding = tokenStyle.padding;
        var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0;
        if (tokenStyle.width != null && tokenStyle.width !== 'auto') {
            var outerWidth_1 = parsePercent$1(tokenStyle.width, wrapInfo.width) + tokenPaddingH;
            if (lines.length > 0) {
                if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) {
                    strLines = str.split('\n');
                    newLine = true;
                }
            }
            wrapInfo.accumWidth = outerWidth_1;
        }
        else {
            var res = wrapText(str, font, wrapInfo.width, wrapInfo.breakAll, wrapInfo.accumWidth);
            wrapInfo.accumWidth = res.accumWidth + tokenPaddingH;
            linesWidths = res.linesWidths;
            strLines = res.lines;
        }
    }
    else {
        strLines = str.split('\n');
    }
    for (var i = 0; i < strLines.length; i++) {
        var text = strLines[i];
        var token = new RichTextToken();
        token.styleName = styleName;
        token.text = text;
        token.isLineHolder = !text && !isEmptyStr;
        if (typeof tokenStyle.width === 'number') {
            token.width = tokenStyle.width;
        }
        else {
            token.width = linesWidths
                ? linesWidths[i]
                : getWidth(text, font);
        }
        if (!i && !newLine) {
            var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens;
            var tokensLen = tokens.length;
            (tokensLen === 1 && tokens[0].isLineHolder)
                ? (tokens[0] = token)
                : ((text || !tokensLen || isEmptyStr) && tokens.push(token));
        }
        else {
            lines.push(new RichTextLine([token]));
        }
    }
}
function isAlphabeticLetter(ch) {
    var code = ch.charCodeAt(0);
    return code >= 0x20 && code <= 0x24F
        || code >= 0x370 && code <= 0x10FF
        || code >= 0x1200 && code <= 0x13FF
        || code >= 0x1E00 && code <= 0x206F;
}
var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) {
    obj[ch] = true;
    return obj;
}, {});
function isWordBreakChar(ch) {
    if (isAlphabeticLetter(ch)) {
        if (breakCharMap[ch]) {
            return true;
        }
        return false;
    }
    return true;
}
function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) {
    var lines = [];
    var linesWidths = [];
    var line = '';
    var currentWord = '';
    var currentWordWidth = 0;
    var accumWidth = 0;
    for (var i = 0; i < text.length; i++) {
        var ch = text.charAt(i);
        if (ch === '\n') {
            if (currentWord) {
                line += currentWord;
                accumWidth += currentWordWidth;
            }
            lines.push(line);
            linesWidths.push(accumWidth);
            line = '';
            currentWord = '';
            currentWordWidth = 0;
            accumWidth = 0;
            continue;
        }
        var chWidth = getWidth(ch, font);
        var inWord = isBreakAll ? false : !isWordBreakChar(ch);
        if (!lines.length
            ? lastAccumWidth + accumWidth + chWidth > lineWidth
            : accumWidth + chWidth > lineWidth) {
            if (!accumWidth) {
                if (inWord) {
                    lines.push(currentWord);
                    linesWidths.push(currentWordWidth);
                    currentWord = ch;
                    currentWordWidth = chWidth;
                }
                else {
                    lines.push(ch);
                    linesWidths.push(chWidth);
                }
            }
            else if (line || currentWord) {
                if (inWord) {
                    if (!line) {
                        line = currentWord;
                        currentWord = '';
                        currentWordWidth = 0;
                        accumWidth = currentWordWidth;
                    }
                    lines.push(line);
                    linesWidths.push(accumWidth - currentWordWidth);
                    currentWord += ch;
                    currentWordWidth += chWidth;
                    line = '';
                    accumWidth = currentWordWidth;
                }
                else {
                    if (currentWord) {
                        line += currentWord;
                        currentWord = '';
                        currentWordWidth = 0;
                    }
                    lines.push(line);
                    linesWidths.push(accumWidth);
                    line = ch;
                    accumWidth = chWidth;
                }
            }
            continue;
        }
        accumWidth += chWidth;
        if (inWord) {
            currentWord += ch;
            currentWordWidth += chWidth;
        }
        else {
            if (currentWord) {
                line += currentWord;
                currentWord = '';
                currentWordWidth = 0;
            }
            line += ch;
        }
    }
    if (!lines.length && !line) {
        line = text;
        currentWord = '';
        currentWordWidth = 0;
    }
    if (currentWord) {
        line += currentWord;
    }
    if (line) {
        lines.push(line);
        linesWidths.push(accumWidth);
    }
    if (lines.length === 1) {
        accumWidth += lastAccumWidth;
    }
    return {
        accumWidth: accumWidth,
        lines: lines,
        linesWidths: linesWidths
    };
}

/* Injected with object hook! */

var STYLE_MAGIC_KEY = '__zr_style_' + Math.round((Math.random() * 10));
var DEFAULT_COMMON_STYLE = {
    shadowBlur: 0,
    shadowOffsetX: 0,
    shadowOffsetY: 0,
    shadowColor: '#000',
    opacity: 1,
    blend: 'source-over'
};
var DEFAULT_COMMON_ANIMATION_PROPS = {
    style: {
        shadowBlur: true,
        shadowOffsetX: true,
        shadowOffsetY: true,
        shadowColor: true,
        opacity: true
    }
};
DEFAULT_COMMON_STYLE[STYLE_MAGIC_KEY] = true;
var PRIMARY_STATES_KEYS = ['z', 'z2', 'invisible'];
var PRIMARY_STATES_KEYS_IN_HOVER_LAYER = ['invisible'];
var Displayable = (function (_super) {
    __extends(Displayable, _super);
    function Displayable(props) {
        return _super.call(this, props) || this;
    }
    Displayable.prototype._init = function (props) {
        var keysArr = keys(props);
        for (var i = 0; i < keysArr.length; i++) {
            var key = keysArr[i];
            if (key === 'style') {
                this.useStyle(props[key]);
            }
            else {
                _super.prototype.attrKV.call(this, key, props[key]);
            }
        }
        if (!this.style) {
            this.useStyle({});
        }
    };
    Displayable.prototype.beforeBrush = function () { };
    Displayable.prototype.afterBrush = function () { };
    Displayable.prototype.innerBeforeBrush = function () { };
    Displayable.prototype.innerAfterBrush = function () { };
    Displayable.prototype.shouldBePainted = function (viewWidth, viewHeight, considerClipPath, considerAncestors) {
        var m = this.transform;
        if (this.ignore
            || this.invisible
            || this.style.opacity === 0
            || (this.culling
                && isDisplayableCulled(this, viewWidth, viewHeight))
            || (m && !m[0] && !m[3])) {
            return false;
        }
        if (considerClipPath && this.__clipPaths) {
            for (var i = 0; i < this.__clipPaths.length; ++i) {
                if (this.__clipPaths[i].isZeroArea()) {
                    return false;
                }
            }
        }
        if (considerAncestors && this.parent) {
            var parent_1 = this.parent;
            while (parent_1) {
                if (parent_1.ignore) {
                    return false;
                }
                parent_1 = parent_1.parent;
            }
        }
        return true;
    };
    Displayable.prototype.contain = function (x, y) {
        return this.rectContain(x, y);
    };
    Displayable.prototype.traverse = function (cb, context) {
        cb.call(context, this);
    };
    Displayable.prototype.rectContain = function (x, y) {
        var coord = this.transformCoordToLocal(x, y);
        var rect = this.getBoundingRect();
        return rect.contain(coord[0], coord[1]);
    };
    Displayable.prototype.getPaintRect = function () {
        var rect = this._paintRect;
        if (!this._paintRect || this.__dirty) {
            var transform = this.transform;
            var elRect = this.getBoundingRect();
            var style = this.style;
            var shadowSize = style.shadowBlur || 0;
            var shadowOffsetX = style.shadowOffsetX || 0;
            var shadowOffsetY = style.shadowOffsetY || 0;
            rect = this._paintRect || (this._paintRect = new BoundingRect$1(0, 0, 0, 0));
            if (transform) {
                BoundingRect$1.applyTransform(rect, elRect, transform);
            }
            else {
                rect.copy(elRect);
            }
            if (shadowSize || shadowOffsetX || shadowOffsetY) {
                rect.width += shadowSize * 2 + Math.abs(shadowOffsetX);
                rect.height += shadowSize * 2 + Math.abs(shadowOffsetY);
                rect.x = Math.min(rect.x, rect.x + shadowOffsetX - shadowSize);
                rect.y = Math.min(rect.y, rect.y + shadowOffsetY - shadowSize);
            }
            var tolerance = this.dirtyRectTolerance;
            if (!rect.isZero()) {
                rect.x = Math.floor(rect.x - tolerance);
                rect.y = Math.floor(rect.y - tolerance);
                rect.width = Math.ceil(rect.width + 1 + tolerance * 2);
                rect.height = Math.ceil(rect.height + 1 + tolerance * 2);
            }
        }
        return rect;
    };
    Displayable.prototype.setPrevPaintRect = function (paintRect) {
        if (paintRect) {
            this._prevPaintRect = this._prevPaintRect || new BoundingRect$1(0, 0, 0, 0);
            this._prevPaintRect.copy(paintRect);
        }
        else {
            this._prevPaintRect = null;
        }
    };
    Displayable.prototype.getPrevPaintRect = function () {
        return this._prevPaintRect;
    };
    Displayable.prototype.animateStyle = function (loop) {
        return this.animate('style', loop);
    };
    Displayable.prototype.updateDuringAnimation = function (targetKey) {
        if (targetKey === 'style') {
            this.dirtyStyle();
        }
        else {
            this.markRedraw();
        }
    };
    Displayable.prototype.attrKV = function (key, value) {
        if (key !== 'style') {
            _super.prototype.attrKV.call(this, key, value);
        }
        else {
            if (!this.style) {
                this.useStyle(value);
            }
            else {
                this.setStyle(value);
            }
        }
    };
    Displayable.prototype.setStyle = function (keyOrObj, value) {
        if (typeof keyOrObj === 'string') {
            this.style[keyOrObj] = value;
        }
        else {
            extend(this.style, keyOrObj);
        }
        this.dirtyStyle();
        return this;
    };
    Displayable.prototype.dirtyStyle = function (notRedraw) {
        if (!notRedraw) {
            this.markRedraw();
        }
        this.__dirty |= STYLE_CHANGED_BIT;
        if (this._rect) {
            this._rect = null;
        }
    };
    Displayable.prototype.dirty = function () {
        this.dirtyStyle();
    };
    Displayable.prototype.styleChanged = function () {
        return !!(this.__dirty & STYLE_CHANGED_BIT);
    };
    Displayable.prototype.styleUpdated = function () {
        this.__dirty &= ~STYLE_CHANGED_BIT;
    };
    Displayable.prototype.createStyle = function (obj) {
        return createObject(DEFAULT_COMMON_STYLE, obj);
    };
    Displayable.prototype.useStyle = function (obj) {
        if (!obj[STYLE_MAGIC_KEY]) {
            obj = this.createStyle(obj);
        }
        if (this.__inHover) {
            this.__hoverStyle = obj;
        }
        else {
            this.style = obj;
        }
        this.dirtyStyle();
    };
    Displayable.prototype.isStyleObject = function (obj) {
        return obj[STYLE_MAGIC_KEY];
    };
    Displayable.prototype._innerSaveToNormal = function (toState) {
        _super.prototype._innerSaveToNormal.call(this, toState);
        var normalState = this._normalState;
        if (toState.style && !normalState.style) {
            normalState.style = this._mergeStyle(this.createStyle(), this.style);
        }
        this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS);
    };
    Displayable.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
        _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);
        var needsRestoreToNormal = !(state && keepCurrentStates);
        var targetStyle;
        if (state && state.style) {
            if (transition) {
                if (keepCurrentStates) {
                    targetStyle = state.style;
                }
                else {
                    targetStyle = this._mergeStyle(this.createStyle(), normalState.style);
                    this._mergeStyle(targetStyle, state.style);
                }
            }
            else {
                targetStyle = this._mergeStyle(this.createStyle(), keepCurrentStates ? this.style : normalState.style);
                this._mergeStyle(targetStyle, state.style);
            }
        }
        else if (needsRestoreToNormal) {
            targetStyle = normalState.style;
        }
        if (targetStyle) {
            if (transition) {
                var sourceStyle = this.style;
                this.style = this.createStyle(needsRestoreToNormal ? {} : sourceStyle);
                if (needsRestoreToNormal) {
                    var changedKeys = keys(sourceStyle);
                    for (var i = 0; i < changedKeys.length; i++) {
                        var key = changedKeys[i];
                        if (key in targetStyle) {
                            targetStyle[key] = targetStyle[key];
                            this.style[key] = sourceStyle[key];
                        }
                    }
                }
                var targetKeys = keys(targetStyle);
                for (var i = 0; i < targetKeys.length; i++) {
                    var key = targetKeys[i];
                    this.style[key] = this.style[key];
                }
                this._transitionState(stateName, {
                    style: targetStyle
                }, animationCfg, this.getAnimationStyleProps());
            }
            else {
                this.useStyle(targetStyle);
            }
        }
        var statesKeys = this.__inHover ? PRIMARY_STATES_KEYS_IN_HOVER_LAYER : PRIMARY_STATES_KEYS;
        for (var i = 0; i < statesKeys.length; i++) {
            var key = statesKeys[i];
            if (state && state[key] != null) {
                this[key] = state[key];
            }
            else if (needsRestoreToNormal) {
                if (normalState[key] != null) {
                    this[key] = normalState[key];
                }
            }
        }
    };
    Displayable.prototype._mergeStates = function (states) {
        var mergedState = _super.prototype._mergeStates.call(this, states);
        var mergedStyle;
        for (var i = 0; i < states.length; i++) {
            var state = states[i];
            if (state.style) {
                mergedStyle = mergedStyle || {};
                this._mergeStyle(mergedStyle, state.style);
            }
        }
        if (mergedStyle) {
            mergedState.style = mergedStyle;
        }
        return mergedState;
    };
    Displayable.prototype._mergeStyle = function (targetStyle, sourceStyle) {
        extend(targetStyle, sourceStyle);
        return targetStyle;
    };
    Displayable.prototype.getAnimationStyleProps = function () {
        return DEFAULT_COMMON_ANIMATION_PROPS;
    };
    Displayable.initDefaultProps = (function () {
        var dispProto = Displayable.prototype;
        dispProto.type = 'displayable';
        dispProto.invisible = false;
        dispProto.z = 0;
        dispProto.z2 = 0;
        dispProto.zlevel = 0;
        dispProto.culling = false;
        dispProto.cursor = 'pointer';
        dispProto.rectHover = false;
        dispProto.incremental = false;
        dispProto._rect = null;
        dispProto.dirtyRectTolerance = 0;
        dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT;
    })();
    return Displayable;
}(Element$2));
var tmpRect = new BoundingRect$1(0, 0, 0, 0);
var viewRect = new BoundingRect$1(0, 0, 0, 0);
function isDisplayableCulled(el, width, height) {
    tmpRect.copy(el.getBoundingRect());
    if (el.transform) {
        tmpRect.applyTransform(el.transform);
    }
    viewRect.width = width;
    viewRect.height = height;
    return !tmpRect.intersect(viewRect);
}
const Displayable$1 = Displayable;

/* Injected with object hook! */

var mathMin$4 = Math.min;
var mathMax$4 = Math.max;
var mathSin$3 = Math.sin;
var mathCos$3 = Math.cos;
var PI2$5 = Math.PI * 2;
var start = create$1();
var end = create$1();
var extremity = create$1();
function fromLine(x0, y0, x1, y1, min, max) {
    min[0] = mathMin$4(x0, x1);
    min[1] = mathMin$4(y0, y1);
    max[0] = mathMax$4(x0, x1);
    max[1] = mathMax$4(y0, y1);
}
var xDim = [];
var yDim = [];
function fromCubic(x0, y0, x1, y1, x2, y2, x3, y3, min, max) {
    var cubicExtrema$1 = cubicExtrema;
    var cubicAt$1 = cubicAt;
    var n = cubicExtrema$1(x0, x1, x2, x3, xDim);
    min[0] = Infinity;
    min[1] = Infinity;
    max[0] = -Infinity;
    max[1] = -Infinity;
    for (var i = 0; i < n; i++) {
        var x = cubicAt$1(x0, x1, x2, x3, xDim[i]);
        min[0] = mathMin$4(x, min[0]);
        max[0] = mathMax$4(x, max[0]);
    }
    n = cubicExtrema$1(y0, y1, y2, y3, yDim);
    for (var i = 0; i < n; i++) {
        var y = cubicAt$1(y0, y1, y2, y3, yDim[i]);
        min[1] = mathMin$4(y, min[1]);
        max[1] = mathMax$4(y, max[1]);
    }
    min[0] = mathMin$4(x0, min[0]);
    max[0] = mathMax$4(x0, max[0]);
    min[0] = mathMin$4(x3, min[0]);
    max[0] = mathMax$4(x3, max[0]);
    min[1] = mathMin$4(y0, min[1]);
    max[1] = mathMax$4(y0, max[1]);
    min[1] = mathMin$4(y3, min[1]);
    max[1] = mathMax$4(y3, max[1]);
}
function fromQuadratic(x0, y0, x1, y1, x2, y2, min, max) {
    var quadraticExtremum$1 = quadraticExtremum;
    var quadraticAt$1 = quadraticAt;
    var tx = mathMax$4(mathMin$4(quadraticExtremum$1(x0, x1, x2), 1), 0);
    var ty = mathMax$4(mathMin$4(quadraticExtremum$1(y0, y1, y2), 1), 0);
    var x = quadraticAt$1(x0, x1, x2, tx);
    var y = quadraticAt$1(y0, y1, y2, ty);
    min[0] = mathMin$4(x0, x2, x);
    min[1] = mathMin$4(y0, y2, y);
    max[0] = mathMax$4(x0, x2, x);
    max[1] = mathMax$4(y0, y2, y);
}
function fromArc(x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max) {
    var vec2Min = min$1;
    var vec2Max = max$1;
    var diff = Math.abs(startAngle - endAngle);
    if (diff % PI2$5 < 1e-4 && diff > 1e-4) {
        min[0] = x - rx;
        min[1] = y - ry;
        max[0] = x + rx;
        max[1] = y + ry;
        return;
    }
    start[0] = mathCos$3(startAngle) * rx + x;
    start[1] = mathSin$3(startAngle) * ry + y;
    end[0] = mathCos$3(endAngle) * rx + x;
    end[1] = mathSin$3(endAngle) * ry + y;
    vec2Min(min, start, end);
    vec2Max(max, start, end);
    startAngle = startAngle % (PI2$5);
    if (startAngle < 0) {
        startAngle = startAngle + PI2$5;
    }
    endAngle = endAngle % (PI2$5);
    if (endAngle < 0) {
        endAngle = endAngle + PI2$5;
    }
    if (startAngle > endAngle && !anticlockwise) {
        endAngle += PI2$5;
    }
    else if (startAngle < endAngle && anticlockwise) {
        startAngle += PI2$5;
    }
    if (anticlockwise) {
        var tmp = endAngle;
        endAngle = startAngle;
        startAngle = tmp;
    }
    for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
        if (angle > startAngle) {
            extremity[0] = mathCos$3(angle) * rx + x;
            extremity[1] = mathSin$3(angle) * ry + y;
            vec2Min(min, extremity, min);
            vec2Max(max, extremity, max);
        }
    }
}

/* Injected with object hook! */

var CMD$2 = {
    M: 1,
    L: 2,
    C: 3,
    Q: 4,
    A: 5,
    Z: 6,
    R: 7
};
var tmpOutX = [];
var tmpOutY = [];
var min = [];
var max = [];
var min2 = [];
var max2 = [];
var mathMin$3 = Math.min;
var mathMax$3 = Math.max;
var mathCos$2 = Math.cos;
var mathSin$2 = Math.sin;
var mathAbs$1 = Math.abs;
var PI$4 = Math.PI;
var PI2$4 = PI$4 * 2;
var hasTypedArray = typeof Float32Array !== 'undefined';
var tmpAngles = [];
function modPI2(radian) {
    var n = Math.round(radian / PI$4 * 1e8) / 1e8;
    return (n % 2) * PI$4;
}
function normalizeArcAngles(angles, anticlockwise) {
    var newStartAngle = modPI2(angles[0]);
    if (newStartAngle < 0) {
        newStartAngle += PI2$4;
    }
    var delta = newStartAngle - angles[0];
    var newEndAngle = angles[1];
    newEndAngle += delta;
    if (!anticlockwise && newEndAngle - newStartAngle >= PI2$4) {
        newEndAngle = newStartAngle + PI2$4;
    }
    else if (anticlockwise && newStartAngle - newEndAngle >= PI2$4) {
        newEndAngle = newStartAngle - PI2$4;
    }
    else if (!anticlockwise && newStartAngle > newEndAngle) {
        newEndAngle = newStartAngle + (PI2$4 - modPI2(newStartAngle - newEndAngle));
    }
    else if (anticlockwise && newStartAngle < newEndAngle) {
        newEndAngle = newStartAngle - (PI2$4 - modPI2(newEndAngle - newStartAngle));
    }
    angles[0] = newStartAngle;
    angles[1] = newEndAngle;
}
var PathProxy = (function () {
    function PathProxy(notSaveData) {
        this.dpr = 1;
        this._xi = 0;
        this._yi = 0;
        this._x0 = 0;
        this._y0 = 0;
        this._len = 0;
        if (notSaveData) {
            this._saveData = false;
        }
        if (this._saveData) {
            this.data = [];
        }
    }
    PathProxy.prototype.increaseVersion = function () {
        this._version++;
    };
    PathProxy.prototype.getVersion = function () {
        return this._version;
    };
    PathProxy.prototype.setScale = function (sx, sy, segmentIgnoreThreshold) {
        segmentIgnoreThreshold = segmentIgnoreThreshold || 0;
        if (segmentIgnoreThreshold > 0) {
            this._ux = mathAbs$1(segmentIgnoreThreshold / devicePixelRatio / sx) || 0;
            this._uy = mathAbs$1(segmentIgnoreThreshold / devicePixelRatio / sy) || 0;
        }
    };
    PathProxy.prototype.setDPR = function (dpr) {
        this.dpr = dpr;
    };
    PathProxy.prototype.setContext = function (ctx) {
        this._ctx = ctx;
    };
    PathProxy.prototype.getContext = function () {
        return this._ctx;
    };
    PathProxy.prototype.beginPath = function () {
        this._ctx && this._ctx.beginPath();
        this.reset();
        return this;
    };
    PathProxy.prototype.reset = function () {
        if (this._saveData) {
            this._len = 0;
        }
        if (this._pathSegLen) {
            this._pathSegLen = null;
            this._pathLen = 0;
        }
        this._version++;
    };
    PathProxy.prototype.moveTo = function (x, y) {
        this._drawPendingPt();
        this.addData(CMD$2.M, x, y);
        this._ctx && this._ctx.moveTo(x, y);
        this._x0 = x;
        this._y0 = y;
        this._xi = x;
        this._yi = y;
        return this;
    };
    PathProxy.prototype.lineTo = function (x, y) {
        var dx = mathAbs$1(x - this._xi);
        var dy = mathAbs$1(y - this._yi);
        var exceedUnit = dx > this._ux || dy > this._uy;
        this.addData(CMD$2.L, x, y);
        if (this._ctx && exceedUnit) {
            this._ctx.lineTo(x, y);
        }
        if (exceedUnit) {
            this._xi = x;
            this._yi = y;
            this._pendingPtDist = 0;
        }
        else {
            var d2 = dx * dx + dy * dy;
            if (d2 > this._pendingPtDist) {
                this._pendingPtX = x;
                this._pendingPtY = y;
                this._pendingPtDist = d2;
            }
        }
        return this;
    };
    PathProxy.prototype.bezierCurveTo = function (x1, y1, x2, y2, x3, y3) {
        this._drawPendingPt();
        this.addData(CMD$2.C, x1, y1, x2, y2, x3, y3);
        if (this._ctx) {
            this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
        }
        this._xi = x3;
        this._yi = y3;
        return this;
    };
    PathProxy.prototype.quadraticCurveTo = function (x1, y1, x2, y2) {
        this._drawPendingPt();
        this.addData(CMD$2.Q, x1, y1, x2, y2);
        if (this._ctx) {
            this._ctx.quadraticCurveTo(x1, y1, x2, y2);
        }
        this._xi = x2;
        this._yi = y2;
        return this;
    };
    PathProxy.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) {
        this._drawPendingPt();
        tmpAngles[0] = startAngle;
        tmpAngles[1] = endAngle;
        normalizeArcAngles(tmpAngles, anticlockwise);
        startAngle = tmpAngles[0];
        endAngle = tmpAngles[1];
        var delta = endAngle - startAngle;
        this.addData(CMD$2.A, cx, cy, r, r, startAngle, delta, 0, anticlockwise ? 0 : 1);
        this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
        this._xi = mathCos$2(endAngle) * r + cx;
        this._yi = mathSin$2(endAngle) * r + cy;
        return this;
    };
    PathProxy.prototype.arcTo = function (x1, y1, x2, y2, radius) {
        this._drawPendingPt();
        if (this._ctx) {
            this._ctx.arcTo(x1, y1, x2, y2, radius);
        }
        return this;
    };
    PathProxy.prototype.rect = function (x, y, w, h) {
        this._drawPendingPt();
        this._ctx && this._ctx.rect(x, y, w, h);
        this.addData(CMD$2.R, x, y, w, h);
        return this;
    };
    PathProxy.prototype.closePath = function () {
        this._drawPendingPt();
        this.addData(CMD$2.Z);
        var ctx = this._ctx;
        var x0 = this._x0;
        var y0 = this._y0;
        if (ctx) {
            ctx.closePath();
        }
        this._xi = x0;
        this._yi = y0;
        return this;
    };
    PathProxy.prototype.fill = function (ctx) {
        ctx && ctx.fill();
        this.toStatic();
    };
    PathProxy.prototype.stroke = function (ctx) {
        ctx && ctx.stroke();
        this.toStatic();
    };
    PathProxy.prototype.len = function () {
        return this._len;
    };
    PathProxy.prototype.setData = function (data) {
        var len = data.length;
        if (!(this.data && this.data.length === len) && hasTypedArray) {
            this.data = new Float32Array(len);
        }
        for (var i = 0; i < len; i++) {
            this.data[i] = data[i];
        }
        this._len = len;
    };
    PathProxy.prototype.appendPath = function (path) {
        if (!(path instanceof Array)) {
            path = [path];
        }
        var len = path.length;
        var appendSize = 0;
        var offset = this._len;
        for (var i = 0; i < len; i++) {
            appendSize += path[i].len();
        }
        if (hasTypedArray && (this.data instanceof Float32Array)) {
            this.data = new Float32Array(offset + appendSize);
        }
        for (var i = 0; i < len; i++) {
            var appendPathData = path[i].data;
            for (var k = 0; k < appendPathData.length; k++) {
                this.data[offset++] = appendPathData[k];
            }
        }
        this._len = offset;
    };
    PathProxy.prototype.addData = function (cmd, a, b, c, d, e, f, g, h) {
        if (!this._saveData) {
            return;
        }
        var data = this.data;
        if (this._len + arguments.length > data.length) {
            this._expandData();
            data = this.data;
        }
        for (var i = 0; i < arguments.length; i++) {
            data[this._len++] = arguments[i];
        }
    };
    PathProxy.prototype._drawPendingPt = function () {
        if (this._pendingPtDist > 0) {
            this._ctx && this._ctx.lineTo(this._pendingPtX, this._pendingPtY);
            this._pendingPtDist = 0;
        }
    };
    PathProxy.prototype._expandData = function () {
        if (!(this.data instanceof Array)) {
            var newData = [];
            for (var i = 0; i < this._len; i++) {
                newData[i] = this.data[i];
            }
            this.data = newData;
        }
    };
    PathProxy.prototype.toStatic = function () {
        if (!this._saveData) {
            return;
        }
        this._drawPendingPt();
        var data = this.data;
        if (data instanceof Array) {
            data.length = this._len;
            if (hasTypedArray && this._len > 11) {
                this.data = new Float32Array(data);
            }
        }
    };
    PathProxy.prototype.getBoundingRect = function () {
        min[0] = min[1] = min2[0] = min2[1] = Number.MAX_VALUE;
        max[0] = max[1] = max2[0] = max2[1] = -Number.MAX_VALUE;
        var data = this.data;
        var xi = 0;
        var yi = 0;
        var x0 = 0;
        var y0 = 0;
        var i;
        for (i = 0; i < this._len;) {
            var cmd = data[i++];
            var isFirst = i === 1;
            if (isFirst) {
                xi = data[i];
                yi = data[i + 1];
                x0 = xi;
                y0 = yi;
            }
            switch (cmd) {
                case CMD$2.M:
                    xi = x0 = data[i++];
                    yi = y0 = data[i++];
                    min2[0] = x0;
                    min2[1] = y0;
                    max2[0] = x0;
                    max2[1] = y0;
                    break;
                case CMD$2.L:
                    fromLine(xi, yi, data[i], data[i + 1], min2, max2);
                    xi = data[i++];
                    yi = data[i++];
                    break;
                case CMD$2.C:
                    fromCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], min2, max2);
                    xi = data[i++];
                    yi = data[i++];
                    break;
                case CMD$2.Q:
                    fromQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], min2, max2);
                    xi = data[i++];
                    yi = data[i++];
                    break;
                case CMD$2.A:
                    var cx = data[i++];
                    var cy = data[i++];
                    var rx = data[i++];
                    var ry = data[i++];
                    var startAngle = data[i++];
                    var endAngle = data[i++] + startAngle;
                    i += 1;
                    var anticlockwise = !data[i++];
                    if (isFirst) {
                        x0 = mathCos$2(startAngle) * rx + cx;
                        y0 = mathSin$2(startAngle) * ry + cy;
                    }
                    fromArc(cx, cy, rx, ry, startAngle, endAngle, anticlockwise, min2, max2);
                    xi = mathCos$2(endAngle) * rx + cx;
                    yi = mathSin$2(endAngle) * ry + cy;
                    break;
                case CMD$2.R:
                    x0 = xi = data[i++];
                    y0 = yi = data[i++];
                    var width = data[i++];
                    var height = data[i++];
                    fromLine(x0, y0, x0 + width, y0 + height, min2, max2);
                    break;
                case CMD$2.Z:
                    xi = x0;
                    yi = y0;
                    break;
            }
            min$1(min, min, min2);
            max$1(max, max, max2);
        }
        if (i === 0) {
            min[0] = min[1] = max[0] = max[1] = 0;
        }
        return new BoundingRect$1(min[0], min[1], max[0] - min[0], max[1] - min[1]);
    };
    PathProxy.prototype._calculateLength = function () {
        var data = this.data;
        var len = this._len;
        var ux = this._ux;
        var uy = this._uy;
        var xi = 0;
        var yi = 0;
        var x0 = 0;
        var y0 = 0;
        if (!this._pathSegLen) {
            this._pathSegLen = [];
        }
        var pathSegLen = this._pathSegLen;
        var pathTotalLen = 0;
        var segCount = 0;
        for (var i = 0; i < len;) {
            var cmd = data[i++];
            var isFirst = i === 1;
            if (isFirst) {
                xi = data[i];
                yi = data[i + 1];
                x0 = xi;
                y0 = yi;
            }
            var l = -1;
            switch (cmd) {
                case CMD$2.M:
                    xi = x0 = data[i++];
                    yi = y0 = data[i++];
                    break;
                case CMD$2.L: {
                    var x2 = data[i++];
                    var y2 = data[i++];
                    var dx = x2 - xi;
                    var dy = y2 - yi;
                    if (mathAbs$1(dx) > ux || mathAbs$1(dy) > uy || i === len - 1) {
                        l = Math.sqrt(dx * dx + dy * dy);
                        xi = x2;
                        yi = y2;
                    }
                    break;
                }
                case CMD$2.C: {
                    var x1 = data[i++];
                    var y1 = data[i++];
                    var x2 = data[i++];
                    var y2 = data[i++];
                    var x3 = data[i++];
                    var y3 = data[i++];
                    l = cubicLength(xi, yi, x1, y1, x2, y2, x3, y3, 10);
                    xi = x3;
                    yi = y3;
                    break;
                }
                case CMD$2.Q: {
                    var x1 = data[i++];
                    var y1 = data[i++];
                    var x2 = data[i++];
                    var y2 = data[i++];
                    l = quadraticLength(xi, yi, x1, y1, x2, y2, 10);
                    xi = x2;
                    yi = y2;
                    break;
                }
                case CMD$2.A:
                    var cx = data[i++];
                    var cy = data[i++];
                    var rx = data[i++];
                    var ry = data[i++];
                    var startAngle = data[i++];
                    var delta = data[i++];
                    var endAngle = delta + startAngle;
                    i += 1;
                    !data[i++];
                    if (isFirst) {
                        x0 = mathCos$2(startAngle) * rx + cx;
                        y0 = mathSin$2(startAngle) * ry + cy;
                    }
                    l = mathMax$3(rx, ry) * mathMin$3(PI2$4, Math.abs(delta));
                    xi = mathCos$2(endAngle) * rx + cx;
                    yi = mathSin$2(endAngle) * ry + cy;
                    break;
                case CMD$2.R: {
                    x0 = xi = data[i++];
                    y0 = yi = data[i++];
                    var width = data[i++];
                    var height = data[i++];
                    l = width * 2 + height * 2;
                    break;
                }
                case CMD$2.Z: {
                    var dx = x0 - xi;
                    var dy = y0 - yi;
                    l = Math.sqrt(dx * dx + dy * dy);
                    xi = x0;
                    yi = y0;
                    break;
                }
            }
            if (l >= 0) {
                pathSegLen[segCount++] = l;
                pathTotalLen += l;
            }
        }
        this._pathLen = pathTotalLen;
        return pathTotalLen;
    };
    PathProxy.prototype.rebuildPath = function (ctx, percent) {
        var d = this.data;
        var ux = this._ux;
        var uy = this._uy;
        var len = this._len;
        var x0;
        var y0;
        var xi;
        var yi;
        var x;
        var y;
        var drawPart = percent < 1;
        var pathSegLen;
        var pathTotalLen;
        var accumLength = 0;
        var segCount = 0;
        var displayedLength;
        var pendingPtDist = 0;
        var pendingPtX;
        var pendingPtY;
        if (drawPart) {
            if (!this._pathSegLen) {
                this._calculateLength();
            }
            pathSegLen = this._pathSegLen;
            pathTotalLen = this._pathLen;
            displayedLength = percent * pathTotalLen;
            if (!displayedLength) {
                return;
            }
        }
        lo: for (var i = 0; i < len;) {
            var cmd = d[i++];
            var isFirst = i === 1;
            if (isFirst) {
                xi = d[i];
                yi = d[i + 1];
                x0 = xi;
                y0 = yi;
            }
            if (cmd !== CMD$2.L && pendingPtDist > 0) {
                ctx.lineTo(pendingPtX, pendingPtY);
                pendingPtDist = 0;
            }
            switch (cmd) {
                case CMD$2.M:
                    x0 = xi = d[i++];
                    y0 = yi = d[i++];
                    ctx.moveTo(xi, yi);
                    break;
                case CMD$2.L: {
                    x = d[i++];
                    y = d[i++];
                    var dx = mathAbs$1(x - xi);
                    var dy = mathAbs$1(y - yi);
                    if (dx > ux || dy > uy) {
                        if (drawPart) {
                            var l = pathSegLen[segCount++];
                            if (accumLength + l > displayedLength) {
                                var t = (displayedLength - accumLength) / l;
                                ctx.lineTo(xi * (1 - t) + x * t, yi * (1 - t) + y * t);
                                break lo;
                            }
                            accumLength += l;
                        }
                        ctx.lineTo(x, y);
                        xi = x;
                        yi = y;
                        pendingPtDist = 0;
                    }
                    else {
                        var d2 = dx * dx + dy * dy;
                        if (d2 > pendingPtDist) {
                            pendingPtX = x;
                            pendingPtY = y;
                            pendingPtDist = d2;
                        }
                    }
                    break;
                }
                case CMD$2.C: {
                    var x1 = d[i++];
                    var y1 = d[i++];
                    var x2 = d[i++];
                    var y2 = d[i++];
                    var x3 = d[i++];
                    var y3 = d[i++];
                    if (drawPart) {
                        var l = pathSegLen[segCount++];
                        if (accumLength + l > displayedLength) {
                            var t = (displayedLength - accumLength) / l;
                            cubicSubdivide(xi, x1, x2, x3, t, tmpOutX);
                            cubicSubdivide(yi, y1, y2, y3, t, tmpOutY);
                            ctx.bezierCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2], tmpOutX[3], tmpOutY[3]);
                            break lo;
                        }
                        accumLength += l;
                    }
                    ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
                    xi = x3;
                    yi = y3;
                    break;
                }
                case CMD$2.Q: {
                    var x1 = d[i++];
                    var y1 = d[i++];
                    var x2 = d[i++];
                    var y2 = d[i++];
                    if (drawPart) {
                        var l = pathSegLen[segCount++];
                        if (accumLength + l > displayedLength) {
                            var t = (displayedLength - accumLength) / l;
                            quadraticSubdivide(xi, x1, x2, t, tmpOutX);
                            quadraticSubdivide(yi, y1, y2, t, tmpOutY);
                            ctx.quadraticCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2]);
                            break lo;
                        }
                        accumLength += l;
                    }
                    ctx.quadraticCurveTo(x1, y1, x2, y2);
                    xi = x2;
                    yi = y2;
                    break;
                }
                case CMD$2.A:
                    var cx = d[i++];
                    var cy = d[i++];
                    var rx = d[i++];
                    var ry = d[i++];
                    var startAngle = d[i++];
                    var delta = d[i++];
                    var psi = d[i++];
                    var anticlockwise = !d[i++];
                    var r = (rx > ry) ? rx : ry;
                    var isEllipse = mathAbs$1(rx - ry) > 1e-3;
                    var endAngle = startAngle + delta;
                    var breakBuild = false;
                    if (drawPart) {
                        var l = pathSegLen[segCount++];
                        if (accumLength + l > displayedLength) {
                            endAngle = startAngle + delta * (displayedLength - accumLength) / l;
                            breakBuild = true;
                        }
                        accumLength += l;
                    }
                    if (isEllipse && ctx.ellipse) {
                        ctx.ellipse(cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise);
                    }
                    else {
                        ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
                    }
                    if (breakBuild) {
                        break lo;
                    }
                    if (isFirst) {
                        x0 = mathCos$2(startAngle) * rx + cx;
                        y0 = mathSin$2(startAngle) * ry + cy;
                    }
                    xi = mathCos$2(endAngle) * rx + cx;
                    yi = mathSin$2(endAngle) * ry + cy;
                    break;
                case CMD$2.R:
                    x0 = xi = d[i];
                    y0 = yi = d[i + 1];
                    x = d[i++];
                    y = d[i++];
                    var width = d[i++];
                    var height = d[i++];
                    if (drawPart) {
                        var l = pathSegLen[segCount++];
                        if (accumLength + l > displayedLength) {
                            var d_1 = displayedLength - accumLength;
                            ctx.moveTo(x, y);
                            ctx.lineTo(x + mathMin$3(d_1, width), y);
                            d_1 -= width;
                            if (d_1 > 0) {
                                ctx.lineTo(x + width, y + mathMin$3(d_1, height));
                            }
                            d_1 -= height;
                            if (d_1 > 0) {
                                ctx.lineTo(x + mathMax$3(width - d_1, 0), y + height);
                            }
                            d_1 -= width;
                            if (d_1 > 0) {
                                ctx.lineTo(x, y + mathMax$3(height - d_1, 0));
                            }
                            break lo;
                        }
                        accumLength += l;
                    }
                    ctx.rect(x, y, width, height);
                    break;
                case CMD$2.Z:
                    if (drawPart) {
                        var l = pathSegLen[segCount++];
                        if (accumLength + l > displayedLength) {
                            var t = (displayedLength - accumLength) / l;
                            ctx.lineTo(xi * (1 - t) + x0 * t, yi * (1 - t) + y0 * t);
                            break lo;
                        }
                        accumLength += l;
                    }
                    ctx.closePath();
                    xi = x0;
                    yi = y0;
            }
        }
    };
    PathProxy.prototype.clone = function () {
        var newProxy = new PathProxy();
        var data = this.data;
        newProxy.data = data.slice ? data.slice()
            : Array.prototype.slice.call(data);
        newProxy._len = this._len;
        return newProxy;
    };
    PathProxy.CMD = CMD$2;
    PathProxy.initDefaultProps = (function () {
        var proto = PathProxy.prototype;
        proto._saveData = true;
        proto._ux = 0;
        proto._uy = 0;
        proto._pendingPtDist = 0;
        proto._version = 0;
    })();
    return PathProxy;
}());
const PathProxy$1 = PathProxy;

/* Injected with object hook! */

function containStroke$4(x0, y0, x1, y1, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    var _a = 0;
    var _b = x0;
    if ((y > y0 + _l && y > y1 + _l)
        || (y < y0 - _l && y < y1 - _l)
        || (x > x0 + _l && x > x1 + _l)
        || (x < x0 - _l && x < x1 - _l)) {
        return false;
    }
    if (x0 !== x1) {
        _a = (y0 - y1) / (x0 - x1);
        _b = (x0 * y1 - x1 * y0) / (x0 - x1);
    }
    else {
        return Math.abs(x - x0) <= _l / 2;
    }
    var tmp = _a * x - y + _b;
    var _s = tmp * tmp / (_a * _a + 1);
    return _s <= _l / 2 * _l / 2;
}

/* Injected with object hook! */

function containStroke$3(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    if ((y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l)
        || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l)
        || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l)
        || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l)) {
        return false;
    }
    var d = cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, null);
    return d <= _l / 2;
}

/* Injected with object hook! */

function containStroke$2(x0, y0, x1, y1, x2, y2, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    if ((y > y0 + _l && y > y1 + _l && y > y2 + _l)
        || (y < y0 - _l && y < y1 - _l && y < y2 - _l)
        || (x > x0 + _l && x > x1 + _l && x > x2 + _l)
        || (x < x0 - _l && x < x1 - _l && x < x2 - _l)) {
        return false;
    }
    var d = quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, null);
    return d <= _l / 2;
}

/* Injected with object hook! */

var PI2$3 = Math.PI * 2;
function normalizeRadian(angle) {
    angle %= PI2$3;
    if (angle < 0) {
        angle += PI2$3;
    }
    return angle;
}

/* Injected with object hook! */

var PI2$2 = Math.PI * 2;
function containStroke$1(cx, cy, r, startAngle, endAngle, anticlockwise, lineWidth, x, y) {
    if (lineWidth === 0) {
        return false;
    }
    var _l = lineWidth;
    x -= cx;
    y -= cy;
    var d = Math.sqrt(x * x + y * y);
    if ((d - _l > r) || (d + _l < r)) {
        return false;
    }
    if (Math.abs(startAngle - endAngle) % PI2$2 < 1e-4) {
        return true;
    }
    if (anticlockwise) {
        var tmp = startAngle;
        startAngle = normalizeRadian(endAngle);
        endAngle = normalizeRadian(tmp);
    }
    else {
        startAngle = normalizeRadian(startAngle);
        endAngle = normalizeRadian(endAngle);
    }
    if (startAngle > endAngle) {
        endAngle += PI2$2;
    }
    var angle = Math.atan2(y, x);
    if (angle < 0) {
        angle += PI2$2;
    }
    return (angle >= startAngle && angle <= endAngle)
        || (angle + PI2$2 >= startAngle && angle + PI2$2 <= endAngle);
}

/* Injected with object hook! */

function windingLine(x0, y0, x1, y1, x, y) {
    if ((y > y0 && y > y1) || (y < y0 && y < y1)) {
        return 0;
    }
    if (y1 === y0) {
        return 0;
    }
    var t = (y - y0) / (y1 - y0);
    var dir = y1 < y0 ? 1 : -1;
    if (t === 1 || t === 0) {
        dir = y1 < y0 ? 0.5 : -0.5;
    }
    var x_ = t * (x1 - x0) + x0;
    return x_ === x ? Infinity : x_ > x ? dir : 0;
}

/* Injected with object hook! */

var CMD$1 = PathProxy$1.CMD;
var PI2$1 = Math.PI * 2;
var EPSILON = 1e-4;
function isAroundEqual(a, b) {
    return Math.abs(a - b) < EPSILON;
}
var roots = [-1, -1, -1];
var extrema = [-1, -1];
function swapExtrema() {
    var tmp = extrema[0];
    extrema[0] = extrema[1];
    extrema[1] = tmp;
}
function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) {
    if ((y > y0 && y > y1 && y > y2 && y > y3)
        || (y < y0 && y < y1 && y < y2 && y < y3)) {
        return 0;
    }
    var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots);
    if (nRoots === 0) {
        return 0;
    }
    else {
        var w = 0;
        var nExtrema = -1;
        var y0_ = void 0;
        var y1_ = void 0;
        for (var i = 0; i < nRoots; i++) {
            var t = roots[i];
            var unit = (t === 0 || t === 1) ? 0.5 : 1;
            var x_ = cubicAt(x0, x1, x2, x3, t);
            if (x_ < x) {
                continue;
            }
            if (nExtrema < 0) {
                nExtrema = cubicExtrema(y0, y1, y2, y3, extrema);
                if (extrema[1] < extrema[0] && nExtrema > 1) {
                    swapExtrema();
                }
                y0_ = cubicAt(y0, y1, y2, y3, extrema[0]);
                if (nExtrema > 1) {
                    y1_ = cubicAt(y0, y1, y2, y3, extrema[1]);
                }
            }
            if (nExtrema === 2) {
                if (t < extrema[0]) {
                    w += y0_ < y0 ? unit : -unit;
                }
                else if (t < extrema[1]) {
                    w += y1_ < y0_ ? unit : -unit;
                }
                else {
                    w += y3 < y1_ ? unit : -unit;
                }
            }
            else {
                if (t < extrema[0]) {
                    w += y0_ < y0 ? unit : -unit;
                }
                else {
                    w += y3 < y0_ ? unit : -unit;
                }
            }
        }
        return w;
    }
}
function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) {
    if ((y > y0 && y > y1 && y > y2)
        || (y < y0 && y < y1 && y < y2)) {
        return 0;
    }
    var nRoots = quadraticRootAt(y0, y1, y2, y, roots);
    if (nRoots === 0) {
        return 0;
    }
    else {
        var t = quadraticExtremum(y0, y1, y2);
        if (t >= 0 && t <= 1) {
            var w = 0;
            var y_ = quadraticAt(y0, y1, y2, t);
            for (var i = 0; i < nRoots; i++) {
                var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1;
                var x_ = quadraticAt(x0, x1, x2, roots[i]);
                if (x_ < x) {
                    continue;
                }
                if (roots[i] < t) {
                    w += y_ < y0 ? unit : -unit;
                }
                else {
                    w += y2 < y_ ? unit : -unit;
                }
            }
            return w;
        }
        else {
            var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1;
            var x_ = quadraticAt(x0, x1, x2, roots[0]);
            if (x_ < x) {
                return 0;
            }
            return y2 < y0 ? unit : -unit;
        }
    }
}
function windingArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y) {
    y -= cy;
    if (y > r || y < -r) {
        return 0;
    }
    var tmp = Math.sqrt(r * r - y * y);
    roots[0] = -tmp;
    roots[1] = tmp;
    var dTheta = Math.abs(startAngle - endAngle);
    if (dTheta < 1e-4) {
        return 0;
    }
    if (dTheta >= PI2$1 - 1e-4) {
        startAngle = 0;
        endAngle = PI2$1;
        var dir = anticlockwise ? 1 : -1;
        if (x >= roots[0] + cx && x <= roots[1] + cx) {
            return dir;
        }
        else {
            return 0;
        }
    }
    if (startAngle > endAngle) {
        var tmp_1 = startAngle;
        startAngle = endAngle;
        endAngle = tmp_1;
    }
    if (startAngle < 0) {
        startAngle += PI2$1;
        endAngle += PI2$1;
    }
    var w = 0;
    for (var i = 0; i < 2; i++) {
        var x_ = roots[i];
        if (x_ + cx > x) {
            var angle = Math.atan2(y, x_);
            var dir = anticlockwise ? 1 : -1;
            if (angle < 0) {
                angle = PI2$1 + angle;
            }
            if ((angle >= startAngle && angle <= endAngle)
                || (angle + PI2$1 >= startAngle && angle + PI2$1 <= endAngle)) {
                if (angle > Math.PI / 2 && angle < Math.PI * 1.5) {
                    dir = -dir;
                }
                w += dir;
            }
        }
    }
    return w;
}
function containPath(path, lineWidth, isStroke, x, y) {
    var data = path.data;
    var len = path.len();
    var w = 0;
    var xi = 0;
    var yi = 0;
    var x0 = 0;
    var y0 = 0;
    var x1;
    var y1;
    for (var i = 0; i < len;) {
        var cmd = data[i++];
        var isFirst = i === 1;
        if (cmd === CMD$1.M && i > 1) {
            if (!isStroke) {
                w += windingLine(xi, yi, x0, y0, x, y);
            }
        }
        if (isFirst) {
            xi = data[i];
            yi = data[i + 1];
            x0 = xi;
            y0 = yi;
        }
        switch (cmd) {
            case CMD$1.M:
                x0 = data[i++];
                y0 = data[i++];
                xi = x0;
                yi = y0;
                break;
            case CMD$1.L:
                if (isStroke) {
                    if (containStroke$4(xi, yi, data[i], data[i + 1], lineWidth, x, y)) {
                        return true;
                    }
                }
                else {
                    w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0;
                }
                xi = data[i++];
                yi = data[i++];
                break;
            case CMD$1.C:
                if (isStroke) {
                    if (containStroke$3(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) {
                        return true;
                    }
                }
                else {
                    w += windingCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y) || 0;
                }
                xi = data[i++];
                yi = data[i++];
                break;
            case CMD$1.Q:
                if (isStroke) {
                    if (containStroke$2(xi, yi, data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) {
                        return true;
                    }
                }
                else {
                    w += windingQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y) || 0;
                }
                xi = data[i++];
                yi = data[i++];
                break;
            case CMD$1.A:
                var cx = data[i++];
                var cy = data[i++];
                var rx = data[i++];
                var ry = data[i++];
                var theta = data[i++];
                var dTheta = data[i++];
                i += 1;
                var anticlockwise = !!(1 - data[i++]);
                x1 = Math.cos(theta) * rx + cx;
                y1 = Math.sin(theta) * ry + cy;
                if (!isFirst) {
                    w += windingLine(xi, yi, x1, y1, x, y);
                }
                else {
                    x0 = x1;
                    y0 = y1;
                }
                var _x = (x - cx) * ry / rx + cx;
                if (isStroke) {
                    if (containStroke$1(cx, cy, ry, theta, theta + dTheta, anticlockwise, lineWidth, _x, y)) {
                        return true;
                    }
                }
                else {
                    w += windingArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y);
                }
                xi = Math.cos(theta + dTheta) * rx + cx;
                yi = Math.sin(theta + dTheta) * ry + cy;
                break;
            case CMD$1.R:
                x0 = xi = data[i++];
                y0 = yi = data[i++];
                var width = data[i++];
                var height = data[i++];
                x1 = x0 + width;
                y1 = y0 + height;
                if (isStroke) {
                    if (containStroke$4(x0, y0, x1, y0, lineWidth, x, y)
                        || containStroke$4(x1, y0, x1, y1, lineWidth, x, y)
                        || containStroke$4(x1, y1, x0, y1, lineWidth, x, y)
                        || containStroke$4(x0, y1, x0, y0, lineWidth, x, y)) {
                        return true;
                    }
                }
                else {
                    w += windingLine(x1, y0, x1, y1, x, y);
                    w += windingLine(x0, y1, x0, y0, x, y);
                }
                break;
            case CMD$1.Z:
                if (isStroke) {
                    if (containStroke$4(xi, yi, x0, y0, lineWidth, x, y)) {
                        return true;
                    }
                }
                else {
                    w += windingLine(xi, yi, x0, y0, x, y);
                }
                xi = x0;
                yi = y0;
                break;
        }
    }
    if (!isStroke && !isAroundEqual(yi, y0)) {
        w += windingLine(xi, yi, x0, y0, x, y) || 0;
    }
    return w !== 0;
}
function contain$1(pathProxy, x, y) {
    return containPath(pathProxy, 0, false, x, y);
}
function containStroke(pathProxy, lineWidth, x, y) {
    return containPath(pathProxy, lineWidth, true, x, y);
}

/* Injected with object hook! */

var DEFAULT_PATH_STYLE = defaults({
    fill: '#000',
    stroke: null,
    strokePercent: 1,
    fillOpacity: 1,
    strokeOpacity: 1,
    lineDashOffset: 0,
    lineWidth: 1,
    lineCap: 'butt',
    miterLimit: 10,
    strokeNoScale: false,
    strokeFirst: false
}, DEFAULT_COMMON_STYLE);
var DEFAULT_PATH_ANIMATION_PROPS = {
    style: defaults({
        fill: true,
        stroke: true,
        strokePercent: true,
        fillOpacity: true,
        strokeOpacity: true,
        lineDashOffset: true,
        lineWidth: true,
        miterLimit: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
};
var pathCopyParams = TRANSFORMABLE_PROPS.concat(['invisible',
    'culling', 'z', 'z2', 'zlevel', 'parent'
]);
var Path = (function (_super) {
    __extends(Path, _super);
    function Path(opts) {
        return _super.call(this, opts) || this;
    }
    Path.prototype.update = function () {
        var _this = this;
        _super.prototype.update.call(this);
        var style = this.style;
        if (style.decal) {
            var decalEl = this._decalEl = this._decalEl || new Path();
            if (decalEl.buildPath === Path.prototype.buildPath) {
                decalEl.buildPath = function (ctx) {
                    _this.buildPath(ctx, _this.shape);
                };
            }
            decalEl.silent = true;
            var decalElStyle = decalEl.style;
            for (var key in style) {
                if (decalElStyle[key] !== style[key]) {
                    decalElStyle[key] = style[key];
                }
            }
            decalElStyle.fill = style.fill ? style.decal : null;
            decalElStyle.decal = null;
            decalElStyle.shadowColor = null;
            style.strokeFirst && (decalElStyle.stroke = null);
            for (var i = 0; i < pathCopyParams.length; ++i) {
                decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
            }
            decalEl.__dirty |= REDRAW_BIT;
        }
        else if (this._decalEl) {
            this._decalEl = null;
        }
    };
    Path.prototype.getDecalElement = function () {
        return this._decalEl;
    };
    Path.prototype._init = function (props) {
        var keysArr = keys(props);
        this.shape = this.getDefaultShape();
        var defaultStyle = this.getDefaultStyle();
        if (defaultStyle) {
            this.useStyle(defaultStyle);
        }
        for (var i = 0; i < keysArr.length; i++) {
            var key = keysArr[i];
            var value = props[key];
            if (key === 'style') {
                if (!this.style) {
                    this.useStyle(value);
                }
                else {
                    extend(this.style, value);
                }
            }
            else if (key === 'shape') {
                extend(this.shape, value);
            }
            else {
                _super.prototype.attrKV.call(this, key, value);
            }
        }
        if (!this.style) {
            this.useStyle({});
        }
    };
    Path.prototype.getDefaultStyle = function () {
        return null;
    };
    Path.prototype.getDefaultShape = function () {
        return {};
    };
    Path.prototype.canBeInsideText = function () {
        return this.hasFill();
    };
    Path.prototype.getInsideTextFill = function () {
        var pathFill = this.style.fill;
        if (pathFill !== 'none') {
            if (isString(pathFill)) {
                var fillLum = lum(pathFill, 0);
                if (fillLum > 0.5) {
                    return DARK_LABEL_COLOR;
                }
                else if (fillLum > 0.2) {
                    return LIGHTER_LABEL_COLOR;
                }
                return LIGHT_LABEL_COLOR;
            }
            else if (pathFill) {
                return LIGHT_LABEL_COLOR;
            }
        }
        return DARK_LABEL_COLOR;
    };
    Path.prototype.getInsideTextStroke = function (textFill) {
        var pathFill = this.style.fill;
        if (isString(pathFill)) {
            var zr = this.__zr;
            var isDarkMode = !!(zr && zr.isDarkMode());
            var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD;
            if (isDarkMode === isDarkLabel) {
                return pathFill;
            }
        }
    };
    Path.prototype.buildPath = function (ctx, shapeCfg, inBatch) { };
    Path.prototype.pathUpdated = function () {
        this.__dirty &= ~SHAPE_CHANGED_BIT;
    };
    Path.prototype.getUpdatedPathProxy = function (inBatch) {
        !this.path && this.createPathProxy();
        this.path.beginPath();
        this.buildPath(this.path, this.shape, inBatch);
        return this.path;
    };
    Path.prototype.createPathProxy = function () {
        this.path = new PathProxy$1(false);
    };
    Path.prototype.hasStroke = function () {
        var style = this.style;
        var stroke = style.stroke;
        return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
    };
    Path.prototype.hasFill = function () {
        var style = this.style;
        var fill = style.fill;
        return fill != null && fill !== 'none';
    };
    Path.prototype.getBoundingRect = function () {
        var rect = this._rect;
        var style = this.style;
        var needsUpdateRect = !rect;
        if (needsUpdateRect) {
            var firstInvoke = false;
            if (!this.path) {
                firstInvoke = true;
                this.createPathProxy();
            }
            var path = this.path;
            if (firstInvoke || (this.__dirty & SHAPE_CHANGED_BIT)) {
                path.beginPath();
                this.buildPath(path, this.shape, false);
                this.pathUpdated();
            }
            rect = path.getBoundingRect();
        }
        this._rect = rect;
        if (this.hasStroke() && this.path && this.path.len() > 0) {
            var rectStroke = this._rectStroke || (this._rectStroke = rect.clone());
            if (this.__dirty || needsUpdateRect) {
                rectStroke.copy(rect);
                var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
                var w = style.lineWidth;
                if (!this.hasFill()) {
                    var strokeContainThreshold = this.strokeContainThreshold;
                    w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold);
                }
                if (lineScale > 1e-10) {
                    rectStroke.width += w / lineScale;
                    rectStroke.height += w / lineScale;
                    rectStroke.x -= w / lineScale / 2;
                    rectStroke.y -= w / lineScale / 2;
                }
            }
            return rectStroke;
        }
        return rect;
    };
    Path.prototype.contain = function (x, y) {
        var localPos = this.transformCoordToLocal(x, y);
        var rect = this.getBoundingRect();
        var style = this.style;
        x = localPos[0];
        y = localPos[1];
        if (rect.contain(x, y)) {
            var pathProxy = this.path;
            if (this.hasStroke()) {
                var lineWidth = style.lineWidth;
                var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
                if (lineScale > 1e-10) {
                    if (!this.hasFill()) {
                        lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
                    }
                    if (containStroke(pathProxy, lineWidth / lineScale, x, y)) {
                        return true;
                    }
                }
            }
            if (this.hasFill()) {
                return contain$1(pathProxy, x, y);
            }
        }
        return false;
    };
    Path.prototype.dirtyShape = function () {
        this.__dirty |= SHAPE_CHANGED_BIT;
        if (this._rect) {
            this._rect = null;
        }
        if (this._decalEl) {
            this._decalEl.dirtyShape();
        }
        this.markRedraw();
    };
    Path.prototype.dirty = function () {
        this.dirtyStyle();
        this.dirtyShape();
    };
    Path.prototype.animateShape = function (loop) {
        return this.animate('shape', loop);
    };
    Path.prototype.updateDuringAnimation = function (targetKey) {
        if (targetKey === 'style') {
            this.dirtyStyle();
        }
        else if (targetKey === 'shape') {
            this.dirtyShape();
        }
        else {
            this.markRedraw();
        }
    };
    Path.prototype.attrKV = function (key, value) {
        if (key === 'shape') {
            this.setShape(value);
        }
        else {
            _super.prototype.attrKV.call(this, key, value);
        }
    };
    Path.prototype.setShape = function (keyOrObj, value) {
        var shape = this.shape;
        if (!shape) {
            shape = this.shape = {};
        }
        if (typeof keyOrObj === 'string') {
            shape[keyOrObj] = value;
        }
        else {
            extend(shape, keyOrObj);
        }
        this.dirtyShape();
        return this;
    };
    Path.prototype.shapeChanged = function () {
        return !!(this.__dirty & SHAPE_CHANGED_BIT);
    };
    Path.prototype.createStyle = function (obj) {
        return createObject(DEFAULT_PATH_STYLE, obj);
    };
    Path.prototype._innerSaveToNormal = function (toState) {
        _super.prototype._innerSaveToNormal.call(this, toState);
        var normalState = this._normalState;
        if (toState.shape && !normalState.shape) {
            normalState.shape = extend({}, this.shape);
        }
    };
    Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
        _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);
        var needsRestoreToNormal = !(state && keepCurrentStates);
        var targetShape;
        if (state && state.shape) {
            if (transition) {
                if (keepCurrentStates) {
                    targetShape = state.shape;
                }
                else {
                    targetShape = extend({}, normalState.shape);
                    extend(targetShape, state.shape);
                }
            }
            else {
                targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape);
                extend(targetShape, state.shape);
            }
        }
        else if (needsRestoreToNormal) {
            targetShape = normalState.shape;
        }
        if (targetShape) {
            if (transition) {
                this.shape = extend({}, this.shape);
                var targetShapePrimaryProps = {};
                var shapeKeys = keys(targetShape);
                for (var i = 0; i < shapeKeys.length; i++) {
                    var key = shapeKeys[i];
                    if (typeof targetShape[key] === 'object') {
                        this.shape[key] = targetShape[key];
                    }
                    else {
                        targetShapePrimaryProps[key] = targetShape[key];
                    }
                }
                this._transitionState(stateName, {
                    shape: targetShapePrimaryProps
                }, animationCfg);
            }
            else {
                this.shape = targetShape;
                this.dirtyShape();
            }
        }
    };
    Path.prototype._mergeStates = function (states) {
        var mergedState = _super.prototype._mergeStates.call(this, states);
        var mergedShape;
        for (var i = 0; i < states.length; i++) {
            var state = states[i];
            if (state.shape) {
                mergedShape = mergedShape || {};
                this._mergeStyle(mergedShape, state.shape);
            }
        }
        if (mergedShape) {
            mergedState.shape = mergedShape;
        }
        return mergedState;
    };
    Path.prototype.getAnimationStyleProps = function () {
        return DEFAULT_PATH_ANIMATION_PROPS;
    };
    Path.prototype.isZeroArea = function () {
        return false;
    };
    Path.extend = function (defaultProps) {
        var Sub = (function (_super) {
            __extends(Sub, _super);
            function Sub(opts) {
                var _this = _super.call(this, opts) || this;
                defaultProps.init && defaultProps.init.call(_this, opts);
                return _this;
            }
            Sub.prototype.getDefaultStyle = function () {
                return clone$2(defaultProps.style);
            };
            Sub.prototype.getDefaultShape = function () {
                return clone$2(defaultProps.shape);
            };
            return Sub;
        }(Path));
        for (var key in defaultProps) {
            if (typeof defaultProps[key] === 'function') {
                Sub.prototype[key] = defaultProps[key];
            }
        }
        return Sub;
    };
    Path.initDefaultProps = (function () {
        var pathProto = Path.prototype;
        pathProto.type = 'path';
        pathProto.strokeContainThreshold = 5;
        pathProto.segmentIgnoreThreshold = 0;
        pathProto.subPixelOptimize = false;
        pathProto.autoBatch = false;
        pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
    })();
    return Path;
}(Displayable$1));
const Path$1 = Path;

/* Injected with object hook! */

var DEFAULT_TSPAN_STYLE = defaults({
    strokeFirst: true,
    font: DEFAULT_FONT,
    x: 0,
    y: 0,
    textAlign: 'left',
    textBaseline: 'top',
    miterLimit: 2
}, DEFAULT_PATH_STYLE);
var TSpan = (function (_super) {
    __extends(TSpan, _super);
    function TSpan() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TSpan.prototype.hasStroke = function () {
        var style = this.style;
        var stroke = style.stroke;
        return stroke != null && stroke !== 'none' && style.lineWidth > 0;
    };
    TSpan.prototype.hasFill = function () {
        var style = this.style;
        var fill = style.fill;
        return fill != null && fill !== 'none';
    };
    TSpan.prototype.createStyle = function (obj) {
        return createObject(DEFAULT_TSPAN_STYLE, obj);
    };
    TSpan.prototype.setBoundingRect = function (rect) {
        this._rect = rect;
    };
    TSpan.prototype.getBoundingRect = function () {
        var style = this.style;
        if (!this._rect) {
            var text = style.text;
            text != null ? (text += '') : (text = '');
            var rect = getBoundingRect(text, style.font, style.textAlign, style.textBaseline);
            rect.x += style.x || 0;
            rect.y += style.y || 0;
            if (this.hasStroke()) {
                var w = style.lineWidth;
                rect.x -= w / 2;
                rect.y -= w / 2;
                rect.width += w;
                rect.height += w;
            }
            this._rect = rect;
        }
        return this._rect;
    };
    TSpan.initDefaultProps = (function () {
        var tspanProto = TSpan.prototype;
        tspanProto.dirtyRectTolerance = 10;
    })();
    return TSpan;
}(Displayable$1));
TSpan.prototype.type = 'tspan';
const TSpan$1 = TSpan;

/* Injected with object hook! */

var DEFAULT_IMAGE_STYLE = defaults({
    x: 0,
    y: 0
}, DEFAULT_COMMON_STYLE);
var DEFAULT_IMAGE_ANIMATION_PROPS = {
    style: defaults({
        x: true,
        y: true,
        width: true,
        height: true,
        sx: true,
        sy: true,
        sWidth: true,
        sHeight: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
};
function isImageLike(source) {
    return !!(source
        && typeof source !== 'string'
        && source.width && source.height);
}
var ZRImage = (function (_super) {
    __extends(ZRImage, _super);
    function ZRImage() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    ZRImage.prototype.createStyle = function (obj) {
        return createObject(DEFAULT_IMAGE_STYLE, obj);
    };
    ZRImage.prototype._getSize = function (dim) {
        var style = this.style;
        var size = style[dim];
        if (size != null) {
            return size;
        }
        var imageSource = isImageLike(style.image)
            ? style.image : this.__image;
        if (!imageSource) {
            return 0;
        }
        var otherDim = dim === 'width' ? 'height' : 'width';
        var otherDimSize = style[otherDim];
        if (otherDimSize == null) {
            return imageSource[dim];
        }
        else {
            return imageSource[dim] / imageSource[otherDim] * otherDimSize;
        }
    };
    ZRImage.prototype.getWidth = function () {
        return this._getSize('width');
    };
    ZRImage.prototype.getHeight = function () {
        return this._getSize('height');
    };
    ZRImage.prototype.getAnimationStyleProps = function () {
        return DEFAULT_IMAGE_ANIMATION_PROPS;
    };
    ZRImage.prototype.getBoundingRect = function () {
        var style = this.style;
        if (!this._rect) {
            this._rect = new BoundingRect$1(style.x || 0, style.y || 0, this.getWidth(), this.getHeight());
        }
        return this._rect;
    };
    return ZRImage;
}(Displayable$1));
ZRImage.prototype.type = 'image';
const ZRImage$1 = ZRImage;

/* Injected with object hook! */

function buildPath$2(ctx, shape) {
    var x = shape.x;
    var y = shape.y;
    var width = shape.width;
    var height = shape.height;
    var r = shape.r;
    var r1;
    var r2;
    var r3;
    var r4;
    if (width < 0) {
        x = x + width;
        width = -width;
    }
    if (height < 0) {
        y = y + height;
        height = -height;
    }
    if (typeof r === 'number') {
        r1 = r2 = r3 = r4 = r;
    }
    else if (r instanceof Array) {
        if (r.length === 1) {
            r1 = r2 = r3 = r4 = r[0];
        }
        else if (r.length === 2) {
            r1 = r3 = r[0];
            r2 = r4 = r[1];
        }
        else if (r.length === 3) {
            r1 = r[0];
            r2 = r4 = r[1];
            r3 = r[2];
        }
        else {
            r1 = r[0];
            r2 = r[1];
            r3 = r[2];
            r4 = r[3];
        }
    }
    else {
        r1 = r2 = r3 = r4 = 0;
    }
    var total;
    if (r1 + r2 > width) {
        total = r1 + r2;
        r1 *= width / total;
        r2 *= width / total;
    }
    if (r3 + r4 > width) {
        total = r3 + r4;
        r3 *= width / total;
        r4 *= width / total;
    }
    if (r2 + r3 > height) {
        total = r2 + r3;
        r2 *= height / total;
        r3 *= height / total;
    }
    if (r1 + r4 > height) {
        total = r1 + r4;
        r1 *= height / total;
        r4 *= height / total;
    }
    ctx.moveTo(x + r1, y);
    ctx.lineTo(x + width - r2, y);
    r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0);
    ctx.lineTo(x + width, y + height - r3);
    r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2);
    ctx.lineTo(x + r4, y + height);
    r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI);
    ctx.lineTo(x, y + r1);
    r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5);
}

/* Injected with object hook! */

var round = Math.round;
function subPixelOptimizeLine$1(outputShape, inputShape, style) {
    if (!inputShape) {
        return;
    }
    var x1 = inputShape.x1;
    var x2 = inputShape.x2;
    var y1 = inputShape.y1;
    var y2 = inputShape.y2;
    outputShape.x1 = x1;
    outputShape.x2 = x2;
    outputShape.y1 = y1;
    outputShape.y2 = y2;
    var lineWidth = style && style.lineWidth;
    if (!lineWidth) {
        return outputShape;
    }
    if (round(x1 * 2) === round(x2 * 2)) {
        outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true);
    }
    if (round(y1 * 2) === round(y2 * 2)) {
        outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true);
    }
    return outputShape;
}
function subPixelOptimizeRect$1(outputShape, inputShape, style) {
    if (!inputShape) {
        return;
    }
    var originX = inputShape.x;
    var originY = inputShape.y;
    var originWidth = inputShape.width;
    var originHeight = inputShape.height;
    outputShape.x = originX;
    outputShape.y = originY;
    outputShape.width = originWidth;
    outputShape.height = originHeight;
    var lineWidth = style && style.lineWidth;
    if (!lineWidth) {
        return outputShape;
    }
    outputShape.x = subPixelOptimize$1(originX, lineWidth, true);
    outputShape.y = subPixelOptimize$1(originY, lineWidth, true);
    outputShape.width = Math.max(subPixelOptimize$1(originX + originWidth, lineWidth, false) - outputShape.x, originWidth === 0 ? 0 : 1);
    outputShape.height = Math.max(subPixelOptimize$1(originY + originHeight, lineWidth, false) - outputShape.y, originHeight === 0 ? 0 : 1);
    return outputShape;
}
function subPixelOptimize$1(position, lineWidth, positiveOrNegative) {
    if (!lineWidth) {
        return position;
    }
    var doubledPosition = round(position * 2);
    return (doubledPosition + round(lineWidth)) % 2 === 0
        ? doubledPosition / 2
        : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
}

/* Injected with object hook! */

var RectShape = (function () {
    function RectShape() {
        this.x = 0;
        this.y = 0;
        this.width = 0;
        this.height = 0;
    }
    return RectShape;
}());
var subPixelOptimizeOutputShape$1 = {};
var Rect = (function (_super) {
    __extends(Rect, _super);
    function Rect(opts) {
        return _super.call(this, opts) || this;
    }
    Rect.prototype.getDefaultShape = function () {
        return new RectShape();
    };
    Rect.prototype.buildPath = function (ctx, shape) {
        var x;
        var y;
        var width;
        var height;
        if (this.subPixelOptimize) {
            var optimizedShape = subPixelOptimizeRect$1(subPixelOptimizeOutputShape$1, shape, this.style);
            x = optimizedShape.x;
            y = optimizedShape.y;
            width = optimizedShape.width;
            height = optimizedShape.height;
            optimizedShape.r = shape.r;
            shape = optimizedShape;
        }
        else {
            x = shape.x;
            y = shape.y;
            width = shape.width;
            height = shape.height;
        }
        if (!shape.r) {
            ctx.rect(x, y, width, height);
        }
        else {
            buildPath$2(ctx, shape);
        }
    };
    Rect.prototype.isZeroArea = function () {
        return !this.shape.width || !this.shape.height;
    };
    return Rect;
}(Path$1));
Rect.prototype.type = 'rect';
const Rect$1 = Rect;

/* Injected with object hook! */

var DEFAULT_RICH_TEXT_COLOR = {
    fill: '#000'
};
var DEFAULT_STROKE_LINE_WIDTH = 2;
var DEFAULT_TEXT_ANIMATION_PROPS = {
    style: defaults({
        fill: true,
        stroke: true,
        fillOpacity: true,
        strokeOpacity: true,
        lineWidth: true,
        fontSize: true,
        lineHeight: true,
        width: true,
        height: true,
        textShadowColor: true,
        textShadowBlur: true,
        textShadowOffsetX: true,
        textShadowOffsetY: true,
        backgroundColor: true,
        padding: true,
        borderColor: true,
        borderWidth: true,
        borderRadius: true
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
};
var ZRText = (function (_super) {
    __extends(ZRText, _super);
    function ZRText(opts) {
        var _this = _super.call(this) || this;
        _this.type = 'text';
        _this._children = [];
        _this._defaultStyle = DEFAULT_RICH_TEXT_COLOR;
        _this.attr(opts);
        return _this;
    }
    ZRText.prototype.childrenRef = function () {
        return this._children;
    };
    ZRText.prototype.update = function () {
        _super.prototype.update.call(this);
        if (this.styleChanged()) {
            this._updateSubTexts();
        }
        for (var i = 0; i < this._children.length; i++) {
            var child = this._children[i];
            child.zlevel = this.zlevel;
            child.z = this.z;
            child.z2 = this.z2;
            child.culling = this.culling;
            child.cursor = this.cursor;
            child.invisible = this.invisible;
        }
    };
    ZRText.prototype.updateTransform = function () {
        var innerTransformable = this.innerTransformable;
        if (innerTransformable) {
            innerTransformable.updateTransform();
            if (innerTransformable.transform) {
                this.transform = innerTransformable.transform;
            }
        }
        else {
            _super.prototype.updateTransform.call(this);
        }
    };
    ZRText.prototype.getLocalTransform = function (m) {
        var innerTransformable = this.innerTransformable;
        return innerTransformable
            ? innerTransformable.getLocalTransform(m)
            : _super.prototype.getLocalTransform.call(this, m);
    };
    ZRText.prototype.getComputedTransform = function () {
        if (this.__hostTarget) {
            this.__hostTarget.getComputedTransform();
            this.__hostTarget.updateInnerText(true);
        }
        return _super.prototype.getComputedTransform.call(this);
    };
    ZRText.prototype._updateSubTexts = function () {
        this._childCursor = 0;
        normalizeTextStyle(this.style);
        this.style.rich
            ? this._updateRichTexts()
            : this._updatePlainTexts();
        this._children.length = this._childCursor;
        this.styleUpdated();
    };
    ZRText.prototype.addSelfToZr = function (zr) {
        _super.prototype.addSelfToZr.call(this, zr);
        for (var i = 0; i < this._children.length; i++) {
            this._children[i].__zr = zr;
        }
    };
    ZRText.prototype.removeSelfFromZr = function (zr) {
        _super.prototype.removeSelfFromZr.call(this, zr);
        for (var i = 0; i < this._children.length; i++) {
            this._children[i].__zr = null;
        }
    };
    ZRText.prototype.getBoundingRect = function () {
        if (this.styleChanged()) {
            this._updateSubTexts();
        }
        if (!this._rect) {
            var tmpRect = new BoundingRect$1(0, 0, 0, 0);
            var children = this._children;
            var tmpMat = [];
            var rect = null;
            for (var i = 0; i < children.length; i++) {
                var child = children[i];
                var childRect = child.getBoundingRect();
                var transform = child.getLocalTransform(tmpMat);
                if (transform) {
                    tmpRect.copy(childRect);
                    tmpRect.applyTransform(transform);
                    rect = rect || tmpRect.clone();
                    rect.union(tmpRect);
                }
                else {
                    rect = rect || childRect.clone();
                    rect.union(childRect);
                }
            }
            this._rect = rect || tmpRect;
        }
        return this._rect;
    };
    ZRText.prototype.setDefaultTextStyle = function (defaultTextStyle) {
        this._defaultStyle = defaultTextStyle || DEFAULT_RICH_TEXT_COLOR;
    };
    ZRText.prototype.setTextContent = function (textContent) {
    };
    ZRText.prototype._mergeStyle = function (targetStyle, sourceStyle) {
        if (!sourceStyle) {
            return targetStyle;
        }
        var sourceRich = sourceStyle.rich;
        var targetRich = targetStyle.rich || (sourceRich && {});
        extend(targetStyle, sourceStyle);
        if (sourceRich && targetRich) {
            this._mergeRich(targetRich, sourceRich);
            targetStyle.rich = targetRich;
        }
        else if (targetRich) {
            targetStyle.rich = targetRich;
        }
        return targetStyle;
    };
    ZRText.prototype._mergeRich = function (targetRich, sourceRich) {
        var richNames = keys(sourceRich);
        for (var i = 0; i < richNames.length; i++) {
            var richName = richNames[i];
            targetRich[richName] = targetRich[richName] || {};
            extend(targetRich[richName], sourceRich[richName]);
        }
    };
    ZRText.prototype.getAnimationStyleProps = function () {
        return DEFAULT_TEXT_ANIMATION_PROPS;
    };
    ZRText.prototype._getOrCreateChild = function (Ctor) {
        var child = this._children[this._childCursor];
        if (!child || !(child instanceof Ctor)) {
            child = new Ctor();
        }
        this._children[this._childCursor++] = child;
        child.__zr = this.__zr;
        child.parent = this;
        return child;
    };
    ZRText.prototype._updatePlainTexts = function () {
        var style = this.style;
        var textFont = style.font || DEFAULT_FONT;
        var textPadding = style.padding;
        var text = getStyleText(style);
        var contentBlock = parsePlainText(text, style);
        var needDrawBg = needDrawBackground(style);
        var bgColorDrawn = !!(style.backgroundColor);
        var outerHeight = contentBlock.outerHeight;
        var outerWidth = contentBlock.outerWidth;
        var contentWidth = contentBlock.contentWidth;
        var textLines = contentBlock.lines;
        var lineHeight = contentBlock.lineHeight;
        var defaultStyle = this._defaultStyle;
        var baseX = style.x || 0;
        var baseY = style.y || 0;
        var textAlign = style.align || defaultStyle.align || 'left';
        var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top';
        var textX = baseX;
        var textY = adjustTextY(baseY, contentBlock.contentHeight, verticalAlign);
        if (needDrawBg || textPadding) {
            var boxX = adjustTextX(baseX, outerWidth, textAlign);
            var boxY = adjustTextY(baseY, outerHeight, verticalAlign);
            needDrawBg && this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight);
        }
        textY += lineHeight / 2;
        if (textPadding) {
            textX = getTextXForPadding(baseX, textAlign, textPadding);
            if (verticalAlign === 'top') {
                textY += textPadding[0];
            }
            else if (verticalAlign === 'bottom') {
                textY -= textPadding[2];
            }
        }
        var defaultLineWidth = 0;
        var useDefaultFill = false;
        var textFill = getFill('fill' in style
            ? style.fill
            : (useDefaultFill = true, defaultStyle.fill));
        var textStroke = getStroke('stroke' in style
            ? style.stroke
            : (!bgColorDrawn
                && (!defaultStyle.autoStroke || useDefaultFill))
                ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke)
                : null);
        var hasShadow = style.textShadowBlur > 0;
        var fixedBoundingRect = style.width != null
            && (style.overflow === 'truncate' || style.overflow === 'break' || style.overflow === 'breakAll');
        var calculatedLineHeight = contentBlock.calculatedLineHeight;
        for (var i = 0; i < textLines.length; i++) {
            var el = this._getOrCreateChild(TSpan$1);
            var subElStyle = el.createStyle();
            el.useStyle(subElStyle);
            subElStyle.text = textLines[i];
            subElStyle.x = textX;
            subElStyle.y = textY;
            if (textAlign) {
                subElStyle.textAlign = textAlign;
            }
            subElStyle.textBaseline = 'middle';
            subElStyle.opacity = style.opacity;
            subElStyle.strokeFirst = true;
            if (hasShadow) {
                subElStyle.shadowBlur = style.textShadowBlur || 0;
                subElStyle.shadowColor = style.textShadowColor || 'transparent';
                subElStyle.shadowOffsetX = style.textShadowOffsetX || 0;
                subElStyle.shadowOffsetY = style.textShadowOffsetY || 0;
            }
            subElStyle.stroke = textStroke;
            subElStyle.fill = textFill;
            if (textStroke) {
                subElStyle.lineWidth = style.lineWidth || defaultLineWidth;
                subElStyle.lineDash = style.lineDash;
                subElStyle.lineDashOffset = style.lineDashOffset || 0;
            }
            subElStyle.font = textFont;
            setSeparateFont(subElStyle, style);
            textY += lineHeight;
            if (fixedBoundingRect) {
                el.setBoundingRect(new BoundingRect$1(adjustTextX(subElStyle.x, style.width, subElStyle.textAlign), adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline), contentWidth, calculatedLineHeight));
            }
        }
    };
    ZRText.prototype._updateRichTexts = function () {
        var style = this.style;
        var text = getStyleText(style);
        var contentBlock = parseRichText(text, style);
        var contentWidth = contentBlock.width;
        var outerWidth = contentBlock.outerWidth;
        var outerHeight = contentBlock.outerHeight;
        var textPadding = style.padding;
        var baseX = style.x || 0;
        var baseY = style.y || 0;
        var defaultStyle = this._defaultStyle;
        var textAlign = style.align || defaultStyle.align;
        var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign;
        var boxX = adjustTextX(baseX, outerWidth, textAlign);
        var boxY = adjustTextY(baseY, outerHeight, verticalAlign);
        var xLeft = boxX;
        var lineTop = boxY;
        if (textPadding) {
            xLeft += textPadding[3];
            lineTop += textPadding[0];
        }
        var xRight = xLeft + contentWidth;
        if (needDrawBackground(style)) {
            this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight);
        }
        var bgColorDrawn = !!(style.backgroundColor);
        for (var i = 0; i < contentBlock.lines.length; i++) {
            var line = contentBlock.lines[i];
            var tokens = line.tokens;
            var tokenCount = tokens.length;
            var lineHeight = line.lineHeight;
            var remainedWidth = line.width;
            var leftIndex = 0;
            var lineXLeft = xLeft;
            var lineXRight = xRight;
            var rightIndex = tokenCount - 1;
            var token = void 0;
            while (leftIndex < tokenCount
                && (token = tokens[leftIndex], !token.align || token.align === 'left')) {
                this._placeToken(token, style, lineHeight, lineTop, lineXLeft, 'left', bgColorDrawn);
                remainedWidth -= token.width;
                lineXLeft += token.width;
                leftIndex++;
            }
            while (rightIndex >= 0
                && (token = tokens[rightIndex], token.align === 'right')) {
                this._placeToken(token, style, lineHeight, lineTop, lineXRight, 'right', bgColorDrawn);
                remainedWidth -= token.width;
                lineXRight -= token.width;
                rightIndex--;
            }
            lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - remainedWidth) / 2;
            while (leftIndex <= rightIndex) {
                token = tokens[leftIndex];
                this._placeToken(token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center', bgColorDrawn);
                lineXLeft += token.width;
                leftIndex++;
            }
            lineTop += lineHeight;
        }
    };
    ZRText.prototype._placeToken = function (token, style, lineHeight, lineTop, x, textAlign, parentBgColorDrawn) {
        var tokenStyle = style.rich[token.styleName] || {};
        tokenStyle.text = token.text;
        var verticalAlign = token.verticalAlign;
        var y = lineTop + lineHeight / 2;
        if (verticalAlign === 'top') {
            y = lineTop + token.height / 2;
        }
        else if (verticalAlign === 'bottom') {
            y = lineTop + lineHeight - token.height / 2;
        }
        var needDrawBg = !token.isLineHolder && needDrawBackground(tokenStyle);
        needDrawBg && this._renderBackground(tokenStyle, style, textAlign === 'right'
            ? x - token.width
            : textAlign === 'center'
                ? x - token.width / 2
                : x, y - token.height / 2, token.width, token.height);
        var bgColorDrawn = !!tokenStyle.backgroundColor;
        var textPadding = token.textPadding;
        if (textPadding) {
            x = getTextXForPadding(x, textAlign, textPadding);
            y -= token.height / 2 - textPadding[0] - token.innerHeight / 2;
        }
        var el = this._getOrCreateChild(TSpan$1);
        var subElStyle = el.createStyle();
        el.useStyle(subElStyle);
        var defaultStyle = this._defaultStyle;
        var useDefaultFill = false;
        var defaultLineWidth = 0;
        var textFill = getFill('fill' in tokenStyle ? tokenStyle.fill
            : 'fill' in style ? style.fill
                : (useDefaultFill = true, defaultStyle.fill));
        var textStroke = getStroke('stroke' in tokenStyle ? tokenStyle.stroke
            : 'stroke' in style ? style.stroke
                : (!bgColorDrawn
                    && !parentBgColorDrawn
                    && (!defaultStyle.autoStroke || useDefaultFill)) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke)
                    : null);
        var hasShadow = tokenStyle.textShadowBlur > 0
            || style.textShadowBlur > 0;
        subElStyle.text = token.text;
        subElStyle.x = x;
        subElStyle.y = y;
        if (hasShadow) {
            subElStyle.shadowBlur = tokenStyle.textShadowBlur || style.textShadowBlur || 0;
            subElStyle.shadowColor = tokenStyle.textShadowColor || style.textShadowColor || 'transparent';
            subElStyle.shadowOffsetX = tokenStyle.textShadowOffsetX || style.textShadowOffsetX || 0;
            subElStyle.shadowOffsetY = tokenStyle.textShadowOffsetY || style.textShadowOffsetY || 0;
        }
        subElStyle.textAlign = textAlign;
        subElStyle.textBaseline = 'middle';
        subElStyle.font = token.font || DEFAULT_FONT;
        subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1);
        setSeparateFont(subElStyle, tokenStyle);
        if (textStroke) {
            subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth);
            subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash);
            subElStyle.lineDashOffset = style.lineDashOffset || 0;
            subElStyle.stroke = textStroke;
        }
        if (textFill) {
            subElStyle.fill = textFill;
        }
        var textWidth = token.contentWidth;
        var textHeight = token.contentHeight;
        el.setBoundingRect(new BoundingRect$1(adjustTextX(subElStyle.x, textWidth, subElStyle.textAlign), adjustTextY(subElStyle.y, textHeight, subElStyle.textBaseline), textWidth, textHeight));
    };
    ZRText.prototype._renderBackground = function (style, topStyle, x, y, width, height) {
        var textBackgroundColor = style.backgroundColor;
        var textBorderWidth = style.borderWidth;
        var textBorderColor = style.borderColor;
        var isImageBg = textBackgroundColor && textBackgroundColor.image;
        var isPlainOrGradientBg = textBackgroundColor && !isImageBg;
        var textBorderRadius = style.borderRadius;
        var self = this;
        var rectEl;
        var imgEl;
        if (isPlainOrGradientBg || style.lineHeight || (textBorderWidth && textBorderColor)) {
            rectEl = this._getOrCreateChild(Rect$1);
            rectEl.useStyle(rectEl.createStyle());
            rectEl.style.fill = null;
            var rectShape = rectEl.shape;
            rectShape.x = x;
            rectShape.y = y;
            rectShape.width = width;
            rectShape.height = height;
            rectShape.r = textBorderRadius;
            rectEl.dirtyShape();
        }
        if (isPlainOrGradientBg) {
            var rectStyle = rectEl.style;
            rectStyle.fill = textBackgroundColor || null;
            rectStyle.fillOpacity = retrieve2(style.fillOpacity, 1);
        }
        else if (isImageBg) {
            imgEl = this._getOrCreateChild(ZRImage$1);
            imgEl.onload = function () {
                self.dirtyStyle();
            };
            var imgStyle = imgEl.style;
            imgStyle.image = textBackgroundColor.image;
            imgStyle.x = x;
            imgStyle.y = y;
            imgStyle.width = width;
            imgStyle.height = height;
        }
        if (textBorderWidth && textBorderColor) {
            var rectStyle = rectEl.style;
            rectStyle.lineWidth = textBorderWidth;
            rectStyle.stroke = textBorderColor;
            rectStyle.strokeOpacity = retrieve2(style.strokeOpacity, 1);
            rectStyle.lineDash = style.borderDash;
            rectStyle.lineDashOffset = style.borderDashOffset || 0;
            rectEl.strokeContainThreshold = 0;
            if (rectEl.hasFill() && rectEl.hasStroke()) {
                rectStyle.strokeFirst = true;
                rectStyle.lineWidth *= 2;
            }
        }
        var commonStyle = (rectEl || imgEl).style;
        commonStyle.shadowBlur = style.shadowBlur || 0;
        commonStyle.shadowColor = style.shadowColor || 'transparent';
        commonStyle.shadowOffsetX = style.shadowOffsetX || 0;
        commonStyle.shadowOffsetY = style.shadowOffsetY || 0;
        commonStyle.opacity = retrieve3(style.opacity, topStyle.opacity, 1);
    };
    ZRText.makeFont = function (style) {
        var font = '';
        if (hasSeparateFont(style)) {
            font = [
                style.fontStyle,
                style.fontWeight,
                parseFontSize(style.fontSize),
                style.fontFamily || 'sans-serif'
            ].join(' ');
        }
        return font && trim(font) || style.textFont || style.font;
    };
    return ZRText;
}(Displayable$1));
var VALID_TEXT_ALIGN = { left: true, right: 1, center: 1 };
var VALID_TEXT_VERTICAL_ALIGN = { top: 1, bottom: 1, middle: 1 };
var FONT_PARTS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily'];
function parseFontSize(fontSize) {
    if (typeof fontSize === 'string'
        && (fontSize.indexOf('px') !== -1
            || fontSize.indexOf('rem') !== -1
            || fontSize.indexOf('em') !== -1)) {
        return fontSize;
    }
    else if (!isNaN(+fontSize)) {
        return fontSize + 'px';
    }
    else {
        return DEFAULT_FONT_SIZE + 'px';
    }
}
function setSeparateFont(targetStyle, sourceStyle) {
    for (var i = 0; i < FONT_PARTS.length; i++) {
        var fontProp = FONT_PARTS[i];
        var val = sourceStyle[fontProp];
        if (val != null) {
            targetStyle[fontProp] = val;
        }
    }
}
function hasSeparateFont(style) {
    return style.fontSize != null || style.fontFamily || style.fontWeight;
}
function normalizeTextStyle(style) {
    normalizeStyle(style);
    each$4(style.rich, normalizeStyle);
    return style;
}
function normalizeStyle(style) {
    if (style) {
        style.font = ZRText.makeFont(style);
        var textAlign = style.align;
        textAlign === 'middle' && (textAlign = 'center');
        style.align = (textAlign == null || VALID_TEXT_ALIGN[textAlign]) ? textAlign : 'left';
        var verticalAlign = style.verticalAlign;
        verticalAlign === 'center' && (verticalAlign = 'middle');
        style.verticalAlign = (verticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[verticalAlign]) ? verticalAlign : 'top';
        var textPadding = style.padding;
        if (textPadding) {
            style.padding = normalizeCssArray$1(style.padding);
        }
    }
}
function getStroke(stroke, lineWidth) {
    return (stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none')
        ? null
        : (stroke.image || stroke.colorStops)
            ? '#000'
            : stroke;
}
function getFill(fill) {
    return (fill == null || fill === 'none')
        ? null
        : (fill.image || fill.colorStops)
            ? '#000'
            : fill;
}
function getTextXForPadding(x, textAlign, textPadding) {
    return textAlign === 'right'
        ? (x - textPadding[1])
        : textAlign === 'center'
            ? (x + textPadding[3] / 2 - textPadding[1] / 2)
            : (x + textPadding[3]);
}
function getStyleText(style) {
    var text = style.text;
    text != null && (text += '');
    return text;
}
function needDrawBackground(style) {
    return !!(style.backgroundColor
        || style.lineHeight
        || (style.borderWidth && style.borderColor));
}
const ZRText$1 = ZRText;

/* Injected with object hook! */

var getECData = makeInner();
var setCommonECData = function (seriesIndex, dataType, dataIdx, el) {
  if (el) {
    var ecData = getECData(el); // Add data index and series index for indexing the data by element
    // Useful in tooltip

    ecData.dataIndex = dataIdx;
    ecData.dataType = dataType;
    ecData.seriesIndex = seriesIndex; // TODO: not store dataIndex on children.

    if (el.type === 'group') {
      el.traverse(function (child) {
        var childECData = getECData(child);
        childECData.seriesIndex = seriesIndex;
        childECData.dataIndex = dataIdx;
        childECData.dataType = dataType;
      });
    }
  }
};
/* Injected with object hook! */

var _highlightNextDigit = 1;
var _highlightKeyMap = {};
var getSavedStates = makeInner();
var getComponentStates = makeInner();
var HOVER_STATE_NORMAL = 0;
var HOVER_STATE_BLUR = 1;
var HOVER_STATE_EMPHASIS = 2;
var SPECIAL_STATES = ['emphasis', 'blur', 'select'];
var DISPLAY_STATES = ['normal', 'emphasis', 'blur', 'select'];
var Z2_EMPHASIS_LIFT = 10;
var Z2_SELECT_LIFT = 9;
var HIGHLIGHT_ACTION_TYPE = 'highlight';
var DOWNPLAY_ACTION_TYPE = 'downplay';
var SELECT_ACTION_TYPE = 'select';
var UNSELECT_ACTION_TYPE = 'unselect';
var TOGGLE_SELECT_ACTION_TYPE = 'toggleSelect';

function hasFillOrStroke(fillOrStroke) {
  return fillOrStroke != null && fillOrStroke !== 'none';
} // Most lifted color are duplicated.


var liftedColorCache = new LRU$1(100);

function liftColor(color) {
  if (isString(color)) {
    var liftedColor = liftedColorCache.get(color);

    if (!liftedColor) {
      liftedColor = lift(color, -0.1);
      liftedColorCache.put(color, liftedColor);
    }

    return liftedColor;
  } else if (isGradientObject(color)) {
    var ret = extend({}, color);
    ret.colorStops = map$1(color.colorStops, function (stop) {
      return {
        offset: stop.offset,
        color: lift(stop.color, -0.1)
      };
    });
    return ret;
  } // Change nothing.


  return color;
}

function doChangeHoverState(el, stateName, hoverStateEnum) {
  if (el.onHoverStateChange && (el.hoverState || 0) !== hoverStateEnum) {
    el.onHoverStateChange(stateName);
  }

  el.hoverState = hoverStateEnum;
}

function singleEnterEmphasis(el) {
  // Only mark the flag.
  // States will be applied in the echarts.ts in next frame.
  doChangeHoverState(el, 'emphasis', HOVER_STATE_EMPHASIS);
}

function singleLeaveEmphasis(el) {
  // Only mark the flag.
  // States will be applied in the echarts.ts in next frame.
  if (el.hoverState === HOVER_STATE_EMPHASIS) {
    doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL);
  }
}

function singleEnterBlur(el) {
  doChangeHoverState(el, 'blur', HOVER_STATE_BLUR);
}

function singleLeaveBlur(el) {
  if (el.hoverState === HOVER_STATE_BLUR) {
    doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL);
  }
}

function singleEnterSelect(el) {
  el.selected = true;
}

function singleLeaveSelect(el) {
  el.selected = false;
}

function updateElementState(el, updater, commonParam) {
  updater(el, commonParam);
}

function traverseUpdateState(el, updater, commonParam) {
  updateElementState(el, updater, commonParam);
  el.isGroup && el.traverse(function (child) {
    updateElementState(child, updater, commonParam);
  });
}

function getFromStateStyle(el, props, toStateName, defaultValue) {
  var style = el.style;
  var fromState = {};

  for (var i = 0; i < props.length; i++) {
    var propName = props[i];
    var val = style[propName];
    fromState[propName] = val == null ? defaultValue && defaultValue[propName] : val;
  }

  for (var i = 0; i < el.animators.length; i++) {
    var animator = el.animators[i];

    if (animator.__fromStateTransition // Don't consider the animation to emphasis state.
    && animator.__fromStateTransition.indexOf(toStateName) < 0 && animator.targetName === 'style') {
      animator.saveTo(fromState, props);
    }
  }

  return fromState;
}

function createEmphasisDefaultState(el, stateName, targetStates, state) {
  var hasSelect = targetStates && indexOf(targetStates, 'select') >= 0;
  var cloned = false;

  if (el instanceof Path$1) {
    var store = getSavedStates(el);
    var fromFill = hasSelect ? store.selectFill || store.normalFill : store.normalFill;
    var fromStroke = hasSelect ? store.selectStroke || store.normalStroke : store.normalStroke;

    if (hasFillOrStroke(fromFill) || hasFillOrStroke(fromStroke)) {
      state = state || {};
      var emphasisStyle = state.style || {}; // inherit case

      if (emphasisStyle.fill === 'inherit') {
        cloned = true;
        state = extend({}, state);
        emphasisStyle = extend({}, emphasisStyle);
        emphasisStyle.fill = fromFill;
      } // Apply default color lift
      else if (!hasFillOrStroke(emphasisStyle.fill) && hasFillOrStroke(fromFill)) {
          cloned = true; // Not modify the original value.

          state = extend({}, state);
          emphasisStyle = extend({}, emphasisStyle); // Already being applied 'emphasis'. DON'T lift color multiple times.

          emphasisStyle.fill = liftColor(fromFill);
        } // Not highlight stroke if fill has been highlighted.
        else if (!hasFillOrStroke(emphasisStyle.stroke) && hasFillOrStroke(fromStroke)) {
            if (!cloned) {
              state = extend({}, state);
              emphasisStyle = extend({}, emphasisStyle);
            }

            emphasisStyle.stroke = liftColor(fromStroke);
          }

      state.style = emphasisStyle;
    }
  }

  if (state) {
    // TODO Share with textContent?
    if (state.z2 == null) {
      if (!cloned) {
        state = extend({}, state);
      }

      var z2EmphasisLift = el.z2EmphasisLift;
      state.z2 = el.z2 + (z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT);
    }
  }

  return state;
}

function createSelectDefaultState(el, stateName, state) {
  // const hasSelect = indexOf(el.currentStates, stateName) >= 0;
  if (state) {
    // TODO Share with textContent?
    if (state.z2 == null) {
      state = extend({}, state);
      var z2SelectLift = el.z2SelectLift;
      state.z2 = el.z2 + (z2SelectLift != null ? z2SelectLift : Z2_SELECT_LIFT);
    }
  }

  return state;
}

function createBlurDefaultState(el, stateName, state) {
  var hasBlur = indexOf(el.currentStates, stateName) >= 0;
  var currentOpacity = el.style.opacity;
  var fromState = !hasBlur ? getFromStateStyle(el, ['opacity'], stateName, {
    opacity: 1
  }) : null;
  state = state || {};
  var blurStyle = state.style || {};

  if (blurStyle.opacity == null) {
    // clone state
    state = extend({}, state);
    blurStyle = extend({
      // Already being applied 'emphasis'. DON'T mul opacity multiple times.
      opacity: hasBlur ? currentOpacity : fromState.opacity * 0.1
    }, blurStyle);
    state.style = blurStyle;
  }

  return state;
}

function elementStateProxy(stateName, targetStates) {
  var state = this.states[stateName];

  if (this.style) {
    if (stateName === 'emphasis') {
      return createEmphasisDefaultState(this, stateName, targetStates, state);
    } else if (stateName === 'blur') {
      return createBlurDefaultState(this, stateName, state);
    } else if (stateName === 'select') {
      return createSelectDefaultState(this, stateName, state);
    }
  }

  return state;
}
/**
 * Set hover style (namely "emphasis style") of element.
 * @param el Should not be `zrender/graphic/Group`.
 * @param focus 'self' | 'selfInSeries' | 'series'
 */


function setDefaultStateProxy(el) {
  el.stateProxy = elementStateProxy;
  var textContent = el.getTextContent();
  var textGuide = el.getTextGuideLine();

  if (textContent) {
    textContent.stateProxy = elementStateProxy;
  }

  if (textGuide) {
    textGuide.stateProxy = elementStateProxy;
  }
}
function enterEmphasisWhenMouseOver(el, e) {
  !shouldSilent(el, e) // "emphasis" event highlight has higher priority than mouse highlight.
  && !el.__highByOuter && traverseUpdateState(el, singleEnterEmphasis);
}
function leaveEmphasisWhenMouseOut(el, e) {
  !shouldSilent(el, e) // "emphasis" event highlight has higher priority than mouse highlight.
  && !el.__highByOuter && traverseUpdateState(el, singleLeaveEmphasis);
}
function enterEmphasis(el, highlightDigit) {
  el.__highByOuter |= 1 << (highlightDigit || 0);
  traverseUpdateState(el, singleEnterEmphasis);
}
function leaveEmphasis(el, highlightDigit) {
  !(el.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdateState(el, singleLeaveEmphasis);
}
function enterBlur(el) {
  traverseUpdateState(el, singleEnterBlur);
}
function leaveBlur(el) {
  traverseUpdateState(el, singleLeaveBlur);
}
function enterSelect(el) {
  traverseUpdateState(el, singleEnterSelect);
}
function leaveSelect(el) {
  traverseUpdateState(el, singleLeaveSelect);
}

function shouldSilent(el, e) {
  return el.__highDownSilentOnTouch && e.zrByTouch;
}

function allLeaveBlur(api) {
  var model = api.getModel();
  var leaveBlurredSeries = [];
  var allComponentViews = [];
  model.eachComponent(function (componentType, componentModel) {
    var componentStates = getComponentStates(componentModel);
    var isSeries = componentType === 'series';
    var view = isSeries ? api.getViewOfSeriesModel(componentModel) : api.getViewOfComponentModel(componentModel);
    !isSeries && allComponentViews.push(view);

    if (componentStates.isBlured) {
      // Leave blur anyway
      view.group.traverse(function (child) {
        singleLeaveBlur(child);
      });
      isSeries && leaveBlurredSeries.push(componentModel);
    }

    componentStates.isBlured = false;
  });
  each$4(allComponentViews, function (view) {
    if (view && view.toggleBlurSeries) {
      view.toggleBlurSeries(leaveBlurredSeries, false, model);
    }
  });
}
function blurSeries(targetSeriesIndex, focus, blurScope, api) {
  var ecModel = api.getModel();
  blurScope = blurScope || 'coordinateSystem';

  function leaveBlurOfIndices(data, dataIndices) {
    for (var i = 0; i < dataIndices.length; i++) {
      var itemEl = data.getItemGraphicEl(dataIndices[i]);
      itemEl && leaveBlur(itemEl);
    }
  }

  if (targetSeriesIndex == null) {
    return;
  }

  if (!focus || focus === 'none') {
    return;
  }

  var targetSeriesModel = ecModel.getSeriesByIndex(targetSeriesIndex);
  var targetCoordSys = targetSeriesModel.coordinateSystem;

  if (targetCoordSys && targetCoordSys.master) {
    targetCoordSys = targetCoordSys.master;
  }

  var blurredSeries = [];
  ecModel.eachSeries(function (seriesModel) {
    var sameSeries = targetSeriesModel === seriesModel;
    var coordSys = seriesModel.coordinateSystem;

    if (coordSys && coordSys.master) {
      coordSys = coordSys.master;
    }

    var sameCoordSys = coordSys && targetCoordSys ? coordSys === targetCoordSys : sameSeries; // If there is no coordinate system. use sameSeries instead.

    if (!( // Not blur other series if blurScope series
    blurScope === 'series' && !sameSeries // Not blur other coordinate system if blurScope is coordinateSystem
    || blurScope === 'coordinateSystem' && !sameCoordSys // Not blur self series if focus is series.
    || focus === 'series' && sameSeries // TODO blurScope: coordinate system
    )) {
      var view = api.getViewOfSeriesModel(seriesModel);
      view.group.traverse(function (child) {
        // For the elements that have been triggered by other components,
        // and are still required to be highlighted,
        // because the current is directly forced to blur the element,
        // it will cause the focus self to be unable to highlight, so skip the blur of this element.
        if (child.__highByOuter && sameSeries && focus === 'self') {
          return;
        }

        singleEnterBlur(child);
      });

      if (isArrayLike(focus)) {
        leaveBlurOfIndices(seriesModel.getData(), focus);
      } else if (isObject$2(focus)) {
        var dataTypes = keys(focus);

        for (var d = 0; d < dataTypes.length; d++) {
          leaveBlurOfIndices(seriesModel.getData(dataTypes[d]), focus[dataTypes[d]]);
        }
      }

      blurredSeries.push(seriesModel);
      getComponentStates(seriesModel).isBlured = true;
    }
  });
  ecModel.eachComponent(function (componentType, componentModel) {
    if (componentType === 'series') {
      return;
    }

    var view = api.getViewOfComponentModel(componentModel);

    if (view && view.toggleBlurSeries) {
      view.toggleBlurSeries(blurredSeries, true, ecModel);
    }
  });
}
function blurComponent(componentMainType, componentIndex, api) {
  if (componentMainType == null || componentIndex == null) {
    return;
  }

  var componentModel = api.getModel().getComponent(componentMainType, componentIndex);

  if (!componentModel) {
    return;
  }

  getComponentStates(componentModel).isBlured = true;
  var view = api.getViewOfComponentModel(componentModel);

  if (!view || !view.focusBlurEnabled) {
    return;
  }

  view.group.traverse(function (child) {
    singleEnterBlur(child);
  });
}
function blurSeriesFromHighlightPayload(seriesModel, payload, api) {
  var seriesIndex = seriesModel.seriesIndex;
  var data = seriesModel.getData(payload.dataType);

  if (!data) {

    return;
  }

  var dataIndex = queryDataIndex(data, payload); // Pick the first one if there is multiple/none exists.

  dataIndex = (isArray(dataIndex) ? dataIndex[0] : dataIndex) || 0;
  var el = data.getItemGraphicEl(dataIndex);

  if (!el) {
    var count = data.count();
    var current = 0; // If data on dataIndex is NaN.

    while (!el && current < count) {
      el = data.getItemGraphicEl(current++);
    }
  }

  if (el) {
    var ecData = getECData(el);
    blurSeries(seriesIndex, ecData.focus, ecData.blurScope, api);
  } else {
    // If there is no element put on the data. Try getting it from raw option
    // TODO Should put it on seriesModel?
    var focus_1 = seriesModel.get(['emphasis', 'focus']);
    var blurScope = seriesModel.get(['emphasis', 'blurScope']);

    if (focus_1 != null) {
      blurSeries(seriesIndex, focus_1, blurScope, api);
    }
  }
}
function findComponentHighDownDispatchers(componentMainType, componentIndex, name, api) {
  var ret = {
    focusSelf: false,
    dispatchers: null
  };

  if (componentMainType == null || componentMainType === 'series' || componentIndex == null || name == null) {
    return ret;
  }

  var componentModel = api.getModel().getComponent(componentMainType, componentIndex);

  if (!componentModel) {
    return ret;
  }

  var view = api.getViewOfComponentModel(componentModel);

  if (!view || !view.findHighDownDispatchers) {
    return ret;
  }

  var dispatchers = view.findHighDownDispatchers(name); // At presnet, the component (like Geo) only blur inside itself.
  // So we do not use `blurScope` in component.

  var focusSelf;

  for (var i = 0; i < dispatchers.length; i++) {

    if (getECData(dispatchers[i]).focus === 'self') {
      focusSelf = true;
      break;
    }
  }

  return {
    focusSelf: focusSelf,
    dispatchers: dispatchers
  };
}
function handleGlobalMouseOverForHighDown(dispatcher, e, api) {

  var ecData = getECData(dispatcher);

  var _a = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api),
      dispatchers = _a.dispatchers,
      focusSelf = _a.focusSelf; // If `findHighDownDispatchers` is supported on the component,
  // highlight/downplay elements with the same name.


  if (dispatchers) {
    if (focusSelf) {
      blurComponent(ecData.componentMainType, ecData.componentIndex, api);
    }

    each$4(dispatchers, function (dispatcher) {
      return enterEmphasisWhenMouseOver(dispatcher, e);
    });
  } else {
    // Try blur all in the related series. Then emphasis the hoverred.
    // TODO. progressive mode.
    blurSeries(ecData.seriesIndex, ecData.focus, ecData.blurScope, api);

    if (ecData.focus === 'self') {
      blurComponent(ecData.componentMainType, ecData.componentIndex, api);
    } // Other than series, component that not support `findHighDownDispatcher` will
    // also use it. But in this case, highlight/downplay are only supported in
    // mouse hover but not in dispatchAction.


    enterEmphasisWhenMouseOver(dispatcher, e);
  }
}
function handleGlobalMouseOutForHighDown(dispatcher, e, api) {

  allLeaveBlur(api);
  var ecData = getECData(dispatcher);
  var dispatchers = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api).dispatchers;

  if (dispatchers) {
    each$4(dispatchers, function (dispatcher) {
      return leaveEmphasisWhenMouseOut(dispatcher, e);
    });
  } else {
    leaveEmphasisWhenMouseOut(dispatcher, e);
  }
}
function toggleSelectionFromPayload(seriesModel, payload, api) {
  if (!isSelectChangePayload(payload)) {
    return;
  }

  var dataType = payload.dataType;
  var data = seriesModel.getData(dataType);
  var dataIndex = queryDataIndex(data, payload);

  if (!isArray(dataIndex)) {
    dataIndex = [dataIndex];
  }

  seriesModel[payload.type === TOGGLE_SELECT_ACTION_TYPE ? 'toggleSelect' : payload.type === SELECT_ACTION_TYPE ? 'select' : 'unselect'](dataIndex, dataType);
}
function updateSeriesElementSelection(seriesModel) {
  var allData = seriesModel.getAllData();
  each$4(allData, function (_a) {
    var data = _a.data,
        type = _a.type;
    data.eachItemGraphicEl(function (el, idx) {
      seriesModel.isSelected(idx, type) ? enterSelect(el) : leaveSelect(el);
    });
  });
}
function getAllSelectedIndices(ecModel) {
  var ret = [];
  ecModel.eachSeries(function (seriesModel) {
    var allData = seriesModel.getAllData();
    each$4(allData, function (_a) {
      _a.data;
          var type = _a.type;
      var dataIndices = seriesModel.getSelectedDataIndices();

      if (dataIndices.length > 0) {
        var item = {
          dataIndex: dataIndices,
          seriesIndex: seriesModel.seriesIndex
        };

        if (type != null) {
          item.dataType = type;
        }

        ret.push(item);
      }
    });
  });
  return ret;
}
/**
 * Enable the function that mouseover will trigger the emphasis state.
 *
 * NOTE:
 * This function should be used on the element with dataIndex, seriesIndex.
 *
 */

function enableHoverEmphasis(el, focus, blurScope) {
  setAsHighDownDispatcher(el, true);
  traverseUpdateState(el, setDefaultStateProxy);
  enableHoverFocus(el, focus, blurScope);
}
function disableHoverEmphasis(el) {
  setAsHighDownDispatcher(el, false);
}
function toggleHoverEmphasis(el, focus, blurScope, isDisabled) {
  isDisabled ? disableHoverEmphasis(el) : enableHoverEmphasis(el, focus, blurScope);
}
function enableHoverFocus(el, focus, blurScope) {
  var ecData = getECData(el);

  if (focus != null) {
    // TODO dataIndex may be set after this function. This check is not useful.
    // if (ecData.dataIndex == null) {
    //     if (__DEV__) {
    //         console.warn('focus can only been set on element with dataIndex');
    //     }
    // }
    // else {
    ecData.focus = focus;
    ecData.blurScope = blurScope; // }
  } else if (ecData.focus) {
    ecData.focus = null;
  }
}
var OTHER_STATES = ['emphasis', 'blur', 'select'];
var defaultStyleGetterMap = {
  itemStyle: 'getItemStyle',
  lineStyle: 'getLineStyle',
  areaStyle: 'getAreaStyle'
};
/**
 * Set emphasis/blur/selected states of element.
 */

function setStatesStylesFromModel(el, itemModel, styleType, // default itemStyle
getter) {
  styleType = styleType || 'itemStyle';

  for (var i = 0; i < OTHER_STATES.length; i++) {
    var stateName = OTHER_STATES[i];
    var model = itemModel.getModel([stateName, styleType]);
    var state = el.ensureState(stateName); // Let it throw error if getterType is not found.

    state.style = getter ? getter(model) : model[defaultStyleGetterMap[styleType]]();
  }
}
/**
 *
 * Set element as highlight / downplay dispatcher.
 * It will be checked when element received mouseover event or from highlight action.
 * It's in change of all highlight/downplay behavior of it's children.
 *
 * @param el
 * @param el.highDownSilentOnTouch
 *        In touch device, mouseover event will be trigger on touchstart event
 *        (see module:zrender/dom/HandlerProxy). By this mechanism, we can
 *        conveniently use hoverStyle when tap on touch screen without additional
 *        code for compatibility.
 *        But if the chart/component has select feature, which usually also use
 *        hoverStyle, there might be conflict between 'select-highlight' and
 *        'hover-highlight' especially when roam is enabled (see geo for example).
 *        In this case, `highDownSilentOnTouch` should be used to disable
 *        hover-highlight on touch device.
 * @param asDispatcher If `false`, do not set as "highDownDispatcher".
 */

function setAsHighDownDispatcher(el, asDispatcher) {
  var disable = asDispatcher === false;
  var extendedEl = el; // Make `highDownSilentOnTouch` and `onStateChange` only work after
  // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.

  if (el.highDownSilentOnTouch) {
    extendedEl.__highDownSilentOnTouch = el.highDownSilentOnTouch;
  } // Simple optimize, since this method might be
  // called for each elements of a group in some cases.


  if (!disable || extendedEl.__highDownDispatcher) {
    // Emphasis, normal can be triggered manually by API or other components like hover link.
    // el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
    // Also keep previous record.
    extendedEl.__highByOuter = extendedEl.__highByOuter || 0;
    extendedEl.__highDownDispatcher = !disable;
  }
}
function isHighDownDispatcher(el) {
  return !!(el && el.__highDownDispatcher);
}
/**
 * Support highlight/downplay record on each elements.
 * For the case: hover highlight/downplay (legend, visualMap, ...) and
 * user triggered highlight/downplay should not conflict.
 * Only all of the highlightDigit cleared, return to normal.
 * @param {string} highlightKey
 * @return {number} highlightDigit
 */

function getHighlightDigit(highlightKey) {
  var highlightDigit = _highlightKeyMap[highlightKey];

  if (highlightDigit == null && _highlightNextDigit <= 32) {
    highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++;
  }

  return highlightDigit;
}
function isSelectChangePayload(payload) {
  var payloadType = payload.type;
  return payloadType === SELECT_ACTION_TYPE || payloadType === UNSELECT_ACTION_TYPE || payloadType === TOGGLE_SELECT_ACTION_TYPE;
}
function isHighDownPayload(payload) {
  var payloadType = payload.type;
  return payloadType === HIGHLIGHT_ACTION_TYPE || payloadType === DOWNPLAY_ACTION_TYPE;
}
function savePathStates(el) {
  var store = getSavedStates(el);
  store.normalFill = el.style.fill;
  store.normalStroke = el.style.stroke;
  var selectState = el.states.select || {};
  store.selectFill = selectState.style && selectState.style.fill || null;
  store.selectStroke = selectState.style && selectState.style.stroke || null;
}
/* Injected with object hook! */

var CMD = PathProxy$1.CMD;
var points = [[], [], []];
var mathSqrt$2 = Math.sqrt;
var mathAtan2 = Math.atan2;
function transformPath(path, m) {
    if (!m) {
        return;
    }
    var data = path.data;
    var len = path.len();
    var cmd;
    var nPoint;
    var i;
    var j;
    var k;
    var p;
    var M = CMD.M;
    var C = CMD.C;
    var L = CMD.L;
    var R = CMD.R;
    var A = CMD.A;
    var Q = CMD.Q;
    for (i = 0, j = 0; i < len;) {
        cmd = data[i++];
        j = i;
        nPoint = 0;
        switch (cmd) {
            case M:
                nPoint = 1;
                break;
            case L:
                nPoint = 1;
                break;
            case C:
                nPoint = 3;
                break;
            case Q:
                nPoint = 2;
                break;
            case A:
                var x = m[4];
                var y = m[5];
                var sx = mathSqrt$2(m[0] * m[0] + m[1] * m[1]);
                var sy = mathSqrt$2(m[2] * m[2] + m[3] * m[3]);
                var angle = mathAtan2(-m[1] / sy, m[0] / sx);
                data[i] *= sx;
                data[i++] += x;
                data[i] *= sy;
                data[i++] += y;
                data[i++] *= sx;
                data[i++] *= sy;
                data[i++] += angle;
                data[i++] += angle;
                i += 2;
                j = i;
                break;
            case R:
                p[0] = data[i++];
                p[1] = data[i++];
                applyTransform$1(p, p, m);
                data[j++] = p[0];
                data[j++] = p[1];
                p[0] += data[i++];
                p[1] += data[i++];
                applyTransform$1(p, p, m);
                data[j++] = p[0];
                data[j++] = p[1];
        }
        for (k = 0; k < nPoint; k++) {
            var p_1 = points[k];
            p_1[0] = data[i++];
            p_1[1] = data[i++];
            applyTransform$1(p_1, p_1, m);
            data[j++] = p_1[0];
            data[j++] = p_1[1];
        }
    }
    path.increaseVersion();
}

/* Injected with object hook! */

var mathSqrt$1 = Math.sqrt;
var mathSin$1 = Math.sin;
var mathCos$1 = Math.cos;
var PI$3 = Math.PI;
function vMag(v) {
    return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
}
function vRatio(u, v) {
    return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
}
function vAngle(u, v) {
    return (u[0] * v[1] < u[1] * v[0] ? -1 : 1)
        * Math.acos(vRatio(u, v));
}
function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {
    var psi = psiDeg * (PI$3 / 180.0);
    var xp = mathCos$1(psi) * (x1 - x2) / 2.0
        + mathSin$1(psi) * (y1 - y2) / 2.0;
    var yp = -1 * mathSin$1(psi) * (x1 - x2) / 2.0
        + mathCos$1(psi) * (y1 - y2) / 2.0;
    var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
    if (lambda > 1) {
        rx *= mathSqrt$1(lambda);
        ry *= mathSqrt$1(lambda);
    }
    var f = (fa === fs ? -1 : 1)
        * mathSqrt$1((((rx * rx) * (ry * ry))
            - ((rx * rx) * (yp * yp))
            - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp)
            + (ry * ry) * (xp * xp))) || 0;
    var cxp = f * rx * yp / ry;
    var cyp = f * -ry * xp / rx;
    var cx = (x1 + x2) / 2.0
        + mathCos$1(psi) * cxp
        - mathSin$1(psi) * cyp;
    var cy = (y1 + y2) / 2.0
        + mathSin$1(psi) * cxp
        + mathCos$1(psi) * cyp;
    var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]);
    var u = [(xp - cxp) / rx, (yp - cyp) / ry];
    var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
    var dTheta = vAngle(u, v);
    if (vRatio(u, v) <= -1) {
        dTheta = PI$3;
    }
    if (vRatio(u, v) >= 1) {
        dTheta = 0;
    }
    if (dTheta < 0) {
        var n = Math.round(dTheta / PI$3 * 1e6) / 1e6;
        dTheta = PI$3 * 2 + (n % 2) * PI$3;
    }
    path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);
}
var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig;
var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
function createPathProxyFromString(data) {
    var path = new PathProxy$1();
    if (!data) {
        return path;
    }
    var cpx = 0;
    var cpy = 0;
    var subpathX = cpx;
    var subpathY = cpy;
    var prevCmd;
    var CMD = PathProxy$1.CMD;
    var cmdList = data.match(commandReg);
    if (!cmdList) {
        return path;
    }
    for (var l = 0; l < cmdList.length; l++) {
        var cmdText = cmdList[l];
        var cmdStr = cmdText.charAt(0);
        var cmd = void 0;
        var p = cmdText.match(numberReg) || [];
        var pLen = p.length;
        for (var i = 0; i < pLen; i++) {
            p[i] = parseFloat(p[i]);
        }
        var off = 0;
        while (off < pLen) {
            var ctlPtx = void 0;
            var ctlPty = void 0;
            var rx = void 0;
            var ry = void 0;
            var psi = void 0;
            var fa = void 0;
            var fs = void 0;
            var x1 = cpx;
            var y1 = cpy;
            var len = void 0;
            var pathData = void 0;
            switch (cmdStr) {
                case 'l':
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'L':
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'm':
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.M;
                    path.addData(cmd, cpx, cpy);
                    subpathX = cpx;
                    subpathY = cpy;
                    cmdStr = 'l';
                    break;
                case 'M':
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.M;
                    path.addData(cmd, cpx, cpy);
                    subpathX = cpx;
                    subpathY = cpy;
                    cmdStr = 'L';
                    break;
                case 'h':
                    cpx += p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'H':
                    cpx = p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'v':
                    cpy += p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'V':
                    cpy = p[off++];
                    cmd = CMD.L;
                    path.addData(cmd, cpx, cpy);
                    break;
                case 'C':
                    cmd = CMD.C;
                    path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]);
                    cpx = p[off - 2];
                    cpy = p[off - 1];
                    break;
                case 'c':
                    cmd = CMD.C;
                    path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy);
                    cpx += p[off - 2];
                    cpy += p[off - 1];
                    break;
                case 'S':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    len = path.len();
                    pathData = path.data;
                    if (prevCmd === CMD.C) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cmd = CMD.C;
                    x1 = p[off++];
                    y1 = p[off++];
                    cpx = p[off++];
                    cpy = p[off++];
                    path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
                    break;
                case 's':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    len = path.len();
                    pathData = path.data;
                    if (prevCmd === CMD.C) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cmd = CMD.C;
                    x1 = cpx + p[off++];
                    y1 = cpy + p[off++];
                    cpx += p[off++];
                    cpy += p[off++];
                    path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
                    break;
                case 'Q':
                    x1 = p[off++];
                    y1 = p[off++];
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, x1, y1, cpx, cpy);
                    break;
                case 'q':
                    x1 = p[off++] + cpx;
                    y1 = p[off++] + cpy;
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, x1, y1, cpx, cpy);
                    break;
                case 'T':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    len = path.len();
                    pathData = path.data;
                    if (prevCmd === CMD.Q) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
                    break;
                case 't':
                    ctlPtx = cpx;
                    ctlPty = cpy;
                    len = path.len();
                    pathData = path.data;
                    if (prevCmd === CMD.Q) {
                        ctlPtx += cpx - pathData[len - 4];
                        ctlPty += cpy - pathData[len - 3];
                    }
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.Q;
                    path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
                    break;
                case 'A':
                    rx = p[off++];
                    ry = p[off++];
                    psi = p[off++];
                    fa = p[off++];
                    fs = p[off++];
                    x1 = cpx, y1 = cpy;
                    cpx = p[off++];
                    cpy = p[off++];
                    cmd = CMD.A;
                    processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);
                    break;
                case 'a':
                    rx = p[off++];
                    ry = p[off++];
                    psi = p[off++];
                    fa = p[off++];
                    fs = p[off++];
                    x1 = cpx, y1 = cpy;
                    cpx += p[off++];
                    cpy += p[off++];
                    cmd = CMD.A;
                    processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);
                    break;
            }
        }
        if (cmdStr === 'z' || cmdStr === 'Z') {
            cmd = CMD.Z;
            path.addData(cmd);
            cpx = subpathX;
            cpy = subpathY;
        }
        prevCmd = cmd;
    }
    path.toStatic();
    return path;
}
var SVGPath = (function (_super) {
    __extends(SVGPath, _super);
    function SVGPath() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    SVGPath.prototype.applyTransform = function (m) { };
    return SVGPath;
}(Path$1));
function isPathProxy(path) {
    return path.setData != null;
}
function createPathOptions(str, opts) {
    var pathProxy = createPathProxyFromString(str);
    var innerOpts = extend({}, opts);
    innerOpts.buildPath = function (path) {
        if (isPathProxy(path)) {
            path.setData(pathProxy.data);
            var ctx = path.getContext();
            if (ctx) {
                path.rebuildPath(ctx, 1);
            }
        }
        else {
            var ctx = path;
            pathProxy.rebuildPath(ctx, 1);
        }
    };
    innerOpts.applyTransform = function (m) {
        transformPath(pathProxy, m);
        this.dirtyShape();
    };
    return innerOpts;
}
function createFromString(str, opts) {
    return new SVGPath(createPathOptions(str, opts));
}
function extendFromString(str, defaultOpts) {
    var innerOpts = createPathOptions(str, defaultOpts);
    var Sub = (function (_super) {
        __extends(Sub, _super);
        function Sub(opts) {
            var _this = _super.call(this, opts) || this;
            _this.applyTransform = innerOpts.applyTransform;
            _this.buildPath = innerOpts.buildPath;
            return _this;
        }
        return Sub;
    }(SVGPath));
    return Sub;
}
function mergePath$1(pathEls, opts) {
    var pathList = [];
    var len = pathEls.length;
    for (var i = 0; i < len; i++) {
        var pathEl = pathEls[i];
        pathList.push(pathEl.getUpdatedPathProxy(true));
    }
    var pathBundle = new Path$1(opts);
    pathBundle.createPathProxy();
    pathBundle.buildPath = function (path) {
        if (isPathProxy(path)) {
            path.appendPath(pathList);
            var ctx = path.getContext();
            if (ctx) {
                path.rebuildPath(ctx, 1);
            }
        }
    };
    return pathBundle;
}

/* Injected with object hook! */

var CircleShape = (function () {
    function CircleShape() {
        this.cx = 0;
        this.cy = 0;
        this.r = 0;
    }
    return CircleShape;
}());
var Circle = (function (_super) {
    __extends(Circle, _super);
    function Circle(opts) {
        return _super.call(this, opts) || this;
    }
    Circle.prototype.getDefaultShape = function () {
        return new CircleShape();
    };
    Circle.prototype.buildPath = function (ctx, shape) {
        ctx.moveTo(shape.cx + shape.r, shape.cy);
        ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2);
    };
    return Circle;
}(Path$1));
Circle.prototype.type = 'circle';
const Circle$1 = Circle;

/* Injected with object hook! */

var EllipseShape = (function () {
    function EllipseShape() {
        this.cx = 0;
        this.cy = 0;
        this.rx = 0;
        this.ry = 0;
    }
    return EllipseShape;
}());
var Ellipse = (function (_super) {
    __extends(Ellipse, _super);
    function Ellipse(opts) {
        return _super.call(this, opts) || this;
    }
    Ellipse.prototype.getDefaultShape = function () {
        return new EllipseShape();
    };
    Ellipse.prototype.buildPath = function (ctx, shape) {
        var k = 0.5522848;
        var x = shape.cx;
        var y = shape.cy;
        var a = shape.rx;
        var b = shape.ry;
        var ox = a * k;
        var oy = b * k;
        ctx.moveTo(x - a, y);
        ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b);
        ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y);
        ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b);
        ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y);
        ctx.closePath();
    };
    return Ellipse;
}(Path$1));
Ellipse.prototype.type = 'ellipse';
const Ellipse$1 = Ellipse;

/* Injected with object hook! */

var PI$2 = Math.PI;
var PI2 = PI$2 * 2;
var mathSin = Math.sin;
var mathCos = Math.cos;
var mathACos = Math.acos;
var mathATan2 = Math.atan2;
var mathAbs = Math.abs;
var mathSqrt = Math.sqrt;
var mathMax$2 = Math.max;
var mathMin$2 = Math.min;
var e = 1e-4;
function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
    var dx10 = x1 - x0;
    var dy10 = y1 - y0;
    var dx32 = x3 - x2;
    var dy32 = y3 - y2;
    var t = dy32 * dx10 - dx32 * dy10;
    if (t * t < e) {
        return;
    }
    t = (dx32 * (y0 - y2) - dy32 * (x0 - x2)) / t;
    return [x0 + t * dx10, y0 + t * dy10];
}
function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) {
    var x01 = x0 - x1;
    var y01 = y0 - y1;
    var lo = (clockwise ? cr : -cr) / mathSqrt(x01 * x01 + y01 * y01);
    var ox = lo * y01;
    var oy = -lo * x01;
    var x11 = x0 + ox;
    var y11 = y0 + oy;
    var x10 = x1 + ox;
    var y10 = y1 + oy;
    var x00 = (x11 + x10) / 2;
    var y00 = (y11 + y10) / 2;
    var dx = x10 - x11;
    var dy = y10 - y11;
    var d2 = dx * dx + dy * dy;
    var r = radius - cr;
    var s = x11 * y10 - x10 * y11;
    var d = (dy < 0 ? -1 : 1) * mathSqrt(mathMax$2(0, r * r * d2 - s * s));
    var cx0 = (s * dy - dx * d) / d2;
    var cy0 = (-s * dx - dy * d) / d2;
    var cx1 = (s * dy + dx * d) / d2;
    var cy1 = (-s * dx + dy * d) / d2;
    var dx0 = cx0 - x00;
    var dy0 = cy0 - y00;
    var dx1 = cx1 - x00;
    var dy1 = cy1 - y00;
    if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) {
        cx0 = cx1;
        cy0 = cy1;
    }
    return {
        cx: cx0,
        cy: cy0,
        x0: -ox,
        y0: -oy,
        x1: cx0 * (radius / r - 1),
        y1: cy0 * (radius / r - 1)
    };
}
function normalizeCornerRadius(cr) {
    var arr;
    if (isArray(cr)) {
        var len = cr.length;
        if (!len) {
            return cr;
        }
        if (len === 1) {
            arr = [cr[0], cr[0], 0, 0];
        }
        else if (len === 2) {
            arr = [cr[0], cr[0], cr[1], cr[1]];
        }
        else if (len === 3) {
            arr = cr.concat(cr[2]);
        }
        else {
            arr = cr;
        }
    }
    else {
        arr = [cr, cr, cr, cr];
    }
    return arr;
}
function buildPath$1(ctx, shape) {
    var _a;
    var radius = mathMax$2(shape.r, 0);
    var innerRadius = mathMax$2(shape.r0 || 0, 0);
    var hasRadius = radius > 0;
    var hasInnerRadius = innerRadius > 0;
    if (!hasRadius && !hasInnerRadius) {
        return;
    }
    if (!hasRadius) {
        radius = innerRadius;
        innerRadius = 0;
    }
    if (innerRadius > radius) {
        var tmp = radius;
        radius = innerRadius;
        innerRadius = tmp;
    }
    var startAngle = shape.startAngle, endAngle = shape.endAngle;
    if (isNaN(startAngle) || isNaN(endAngle)) {
        return;
    }
    var cx = shape.cx, cy = shape.cy;
    var clockwise = !!shape.clockwise;
    var arc = mathAbs(endAngle - startAngle);
    var mod = arc > PI2 && arc % PI2;
    mod > e && (arc = mod);
    if (!(radius > e)) {
        ctx.moveTo(cx, cy);
    }
    else if (arc > PI2 - e) {
        ctx.moveTo(cx + radius * mathCos(startAngle), cy + radius * mathSin(startAngle));
        ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise);
        if (innerRadius > e) {
            ctx.moveTo(cx + innerRadius * mathCos(endAngle), cy + innerRadius * mathSin(endAngle));
            ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise);
        }
    }
    else {
        var icrStart = void 0;
        var icrEnd = void 0;
        var ocrStart = void 0;
        var ocrEnd = void 0;
        var ocrs = void 0;
        var ocre = void 0;
        var icrs = void 0;
        var icre = void 0;
        var ocrMax = void 0;
        var icrMax = void 0;
        var limitedOcrMax = void 0;
        var limitedIcrMax = void 0;
        var xre = void 0;
        var yre = void 0;
        var xirs = void 0;
        var yirs = void 0;
        var xrs = radius * mathCos(startAngle);
        var yrs = radius * mathSin(startAngle);
        var xire = innerRadius * mathCos(endAngle);
        var yire = innerRadius * mathSin(endAngle);
        var hasArc = arc > e;
        if (hasArc) {
            var cornerRadius = shape.cornerRadius;
            if (cornerRadius) {
                _a = normalizeCornerRadius(cornerRadius), icrStart = _a[0], icrEnd = _a[1], ocrStart = _a[2], ocrEnd = _a[3];
            }
            var halfRd = mathAbs(radius - innerRadius) / 2;
            ocrs = mathMin$2(halfRd, ocrStart);
            ocre = mathMin$2(halfRd, ocrEnd);
            icrs = mathMin$2(halfRd, icrStart);
            icre = mathMin$2(halfRd, icrEnd);
            limitedOcrMax = ocrMax = mathMax$2(ocrs, ocre);
            limitedIcrMax = icrMax = mathMax$2(icrs, icre);
            if (ocrMax > e || icrMax > e) {
                xre = radius * mathCos(endAngle);
                yre = radius * mathSin(endAngle);
                xirs = innerRadius * mathCos(startAngle);
                yirs = innerRadius * mathSin(startAngle);
                if (arc < PI$2) {
                    var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire);
                    if (it_1) {
                        var x0 = xrs - it_1[0];
                        var y0 = yrs - it_1[1];
                        var x1 = xre - it_1[0];
                        var y1 = yre - it_1[1];
                        var a = 1 / mathSin(mathACos((x0 * x1 + y0 * y1) / (mathSqrt(x0 * x0 + y0 * y0) * mathSqrt(x1 * x1 + y1 * y1))) / 2);
                        var b = mathSqrt(it_1[0] * it_1[0] + it_1[1] * it_1[1]);
                        limitedOcrMax = mathMin$2(ocrMax, (radius - b) / (a + 1));
                        limitedIcrMax = mathMin$2(icrMax, (innerRadius - b) / (a - 1));
                    }
                }
            }
        }
        if (!hasArc) {
            ctx.moveTo(cx + xrs, cy + yrs);
        }
        else if (limitedOcrMax > e) {
            var crStart = mathMin$2(ocrStart, limitedOcrMax);
            var crEnd = mathMin$2(ocrEnd, limitedOcrMax);
            var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, crStart, clockwise);
            var ct1 = computeCornerTangents(xre, yre, xire, yire, radius, crEnd, clockwise);
            ctx.moveTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0);
            if (limitedOcrMax < ocrMax && crStart === crEnd) {
                ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedOcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise);
            }
            else {
                crStart > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crStart, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise);
                ctx.arc(cx, cy, radius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), !clockwise);
                crEnd > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crEnd, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise);
            }
        }
        else {
            ctx.moveTo(cx + xrs, cy + yrs);
            ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise);
        }
        if (!(innerRadius > e) || !hasArc) {
            ctx.lineTo(cx + xire, cy + yire);
        }
        else if (limitedIcrMax > e) {
            var crStart = mathMin$2(icrStart, limitedIcrMax);
            var crEnd = mathMin$2(icrEnd, limitedIcrMax);
            var ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -crEnd, clockwise);
            var ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -crStart, clockwise);
            ctx.lineTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0);
            if (limitedIcrMax < icrMax && crStart === crEnd) {
                ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedIcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise);
            }
            else {
                crEnd > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crEnd, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise);
                ctx.arc(cx, cy, innerRadius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), clockwise);
                crStart > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crStart, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise);
            }
        }
        else {
            ctx.lineTo(cx + xire, cy + yire);
            ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise);
        }
    }
    ctx.closePath();
}

/* Injected with object hook! */

var SectorShape = (function () {
    function SectorShape() {
        this.cx = 0;
        this.cy = 0;
        this.r0 = 0;
        this.r = 0;
        this.startAngle = 0;
        this.endAngle = Math.PI * 2;
        this.clockwise = true;
        this.cornerRadius = 0;
    }
    return SectorShape;
}());
var Sector = (function (_super) {
    __extends(Sector, _super);
    function Sector(opts) {
        return _super.call(this, opts) || this;
    }
    Sector.prototype.getDefaultShape = function () {
        return new SectorShape();
    };
    Sector.prototype.buildPath = function (ctx, shape) {
        buildPath$1(ctx, shape);
    };
    Sector.prototype.isZeroArea = function () {
        return this.shape.startAngle === this.shape.endAngle
            || this.shape.r === this.shape.r0;
    };
    return Sector;
}(Path$1));
Sector.prototype.type = 'sector';
const Sector$1 = Sector;

/* Injected with object hook! */

var RingShape = (function () {
    function RingShape() {
        this.cx = 0;
        this.cy = 0;
        this.r = 0;
        this.r0 = 0;
    }
    return RingShape;
}());
var Ring = (function (_super) {
    __extends(Ring, _super);
    function Ring(opts) {
        return _super.call(this, opts) || this;
    }
    Ring.prototype.getDefaultShape = function () {
        return new RingShape();
    };
    Ring.prototype.buildPath = function (ctx, shape) {
        var x = shape.cx;
        var y = shape.cy;
        var PI2 = Math.PI * 2;
        ctx.moveTo(x + shape.r, y);
        ctx.arc(x, y, shape.r, 0, PI2, false);
        ctx.moveTo(x + shape.r0, y);
        ctx.arc(x, y, shape.r0, 0, PI2, true);
    };
    return Ring;
}(Path$1));
Ring.prototype.type = 'ring';
const Ring$1 = Ring;

/* Injected with object hook! */

function smoothBezier(points, smooth, isLoop, constraint) {
    var cps = [];
    var v = [];
    var v1 = [];
    var v2 = [];
    var prevPoint;
    var nextPoint;
    var min;
    var max;
    if (constraint) {
        min = [Infinity, Infinity];
        max = [-Infinity, -Infinity];
        for (var i = 0, len = points.length; i < len; i++) {
            min$1(min, min, points[i]);
            max$1(max, max, points[i]);
        }
        min$1(min, min, constraint[0]);
        max$1(max, max, constraint[1]);
    }
    for (var i = 0, len = points.length; i < len; i++) {
        var point = points[i];
        if (isLoop) {
            prevPoint = points[i ? i - 1 : len - 1];
            nextPoint = points[(i + 1) % len];
        }
        else {
            if (i === 0 || i === len - 1) {
                cps.push(clone$1(points[i]));
                continue;
            }
            else {
                prevPoint = points[i - 1];
                nextPoint = points[i + 1];
            }
        }
        sub(v, nextPoint, prevPoint);
        scale$2(v, v, smooth);
        var d0 = distance(point, prevPoint);
        var d1 = distance(point, nextPoint);
        var sum = d0 + d1;
        if (sum !== 0) {
            d0 /= sum;
            d1 /= sum;
        }
        scale$2(v1, v, -d0);
        scale$2(v2, v, d1);
        var cp0 = add([], point, v1);
        var cp1 = add([], point, v2);
        if (constraint) {
            max$1(cp0, cp0, min);
            min$1(cp0, cp0, max);
            max$1(cp1, cp1, min);
            min$1(cp1, cp1, max);
        }
        cps.push(cp0);
        cps.push(cp1);
    }
    if (isLoop) {
        cps.push(cps.shift());
    }
    return cps;
}

/* Injected with object hook! */

function buildPath(ctx, shape, closePath) {
    var smooth = shape.smooth;
    var points = shape.points;
    if (points && points.length >= 2) {
        if (smooth) {
            var controlPoints = smoothBezier(points, smooth, closePath, shape.smoothConstraint);
            ctx.moveTo(points[0][0], points[0][1]);
            var len = points.length;
            for (var i = 0; i < (closePath ? len : len - 1); i++) {
                var cp1 = controlPoints[i * 2];
                var cp2 = controlPoints[i * 2 + 1];
                var p = points[(i + 1) % len];
                ctx.bezierCurveTo(cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]);
            }
        }
        else {
            ctx.moveTo(points[0][0], points[0][1]);
            for (var i = 1, l = points.length; i < l; i++) {
                ctx.lineTo(points[i][0], points[i][1]);
            }
        }
        closePath && ctx.closePath();
    }
}

/* Injected with object hook! */

var PolygonShape = (function () {
    function PolygonShape() {
        this.points = null;
        this.smooth = 0;
        this.smoothConstraint = null;
    }
    return PolygonShape;
}());
var Polygon = (function (_super) {
    __extends(Polygon, _super);
    function Polygon(opts) {
        return _super.call(this, opts) || this;
    }
    Polygon.prototype.getDefaultShape = function () {
        return new PolygonShape();
    };
    Polygon.prototype.buildPath = function (ctx, shape) {
        buildPath(ctx, shape, true);
    };
    return Polygon;
}(Path$1));
Polygon.prototype.type = 'polygon';
const Polygon$1 = Polygon;

/* Injected with object hook! */

var PolylineShape = (function () {
    function PolylineShape() {
        this.points = null;
        this.percent = 1;
        this.smooth = 0;
        this.smoothConstraint = null;
    }
    return PolylineShape;
}());
var Polyline = (function (_super) {
    __extends(Polyline, _super);
    function Polyline(opts) {
        return _super.call(this, opts) || this;
    }
    Polyline.prototype.getDefaultStyle = function () {
        return {
            stroke: '#000',
            fill: null
        };
    };
    Polyline.prototype.getDefaultShape = function () {
        return new PolylineShape();
    };
    Polyline.prototype.buildPath = function (ctx, shape) {
        buildPath(ctx, shape, false);
    };
    return Polyline;
}(Path$1));
Polyline.prototype.type = 'polyline';
const Polyline$1 = Polyline;

/* Injected with object hook! */

var subPixelOptimizeOutputShape = {};
var LineShape = (function () {
    function LineShape() {
        this.x1 = 0;
        this.y1 = 0;
        this.x2 = 0;
        this.y2 = 0;
        this.percent = 1;
    }
    return LineShape;
}());
var Line = (function (_super) {
    __extends(Line, _super);
    function Line(opts) {
        return _super.call(this, opts) || this;
    }
    Line.prototype.getDefaultStyle = function () {
        return {
            stroke: '#000',
            fill: null
        };
    };
    Line.prototype.getDefaultShape = function () {
        return new LineShape();
    };
    Line.prototype.buildPath = function (ctx, shape) {
        var x1;
        var y1;
        var x2;
        var y2;
        if (this.subPixelOptimize) {
            var optimizedShape = subPixelOptimizeLine$1(subPixelOptimizeOutputShape, shape, this.style);
            x1 = optimizedShape.x1;
            y1 = optimizedShape.y1;
            x2 = optimizedShape.x2;
            y2 = optimizedShape.y2;
        }
        else {
            x1 = shape.x1;
            y1 = shape.y1;
            x2 = shape.x2;
            y2 = shape.y2;
        }
        var percent = shape.percent;
        if (percent === 0) {
            return;
        }
        ctx.moveTo(x1, y1);
        if (percent < 1) {
            x2 = x1 * (1 - percent) + x2 * percent;
            y2 = y1 * (1 - percent) + y2 * percent;
        }
        ctx.lineTo(x2, y2);
    };
    Line.prototype.pointAt = function (p) {
        var shape = this.shape;
        return [
            shape.x1 * (1 - p) + shape.x2 * p,
            shape.y1 * (1 - p) + shape.y2 * p
        ];
    };
    return Line;
}(Path$1));
Line.prototype.type = 'line';
const Line$1 = Line;

/* Injected with object hook! */

var out = [];
var BezierCurveShape = (function () {
    function BezierCurveShape() {
        this.x1 = 0;
        this.y1 = 0;
        this.x2 = 0;
        this.y2 = 0;
        this.cpx1 = 0;
        this.cpy1 = 0;
        this.percent = 1;
    }
    return BezierCurveShape;
}());
function someVectorAt(shape, t, isTangent) {
    var cpx2 = shape.cpx2;
    var cpy2 = shape.cpy2;
    if (cpx2 != null || cpy2 != null) {
        return [
            (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t),
            (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)
        ];
    }
    else {
        return [
            (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t),
            (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)
        ];
    }
}
var BezierCurve = (function (_super) {
    __extends(BezierCurve, _super);
    function BezierCurve(opts) {
        return _super.call(this, opts) || this;
    }
    BezierCurve.prototype.getDefaultStyle = function () {
        return {
            stroke: '#000',
            fill: null
        };
    };
    BezierCurve.prototype.getDefaultShape = function () {
        return new BezierCurveShape();
    };
    BezierCurve.prototype.buildPath = function (ctx, shape) {
        var x1 = shape.x1;
        var y1 = shape.y1;
        var x2 = shape.x2;
        var y2 = shape.y2;
        var cpx1 = shape.cpx1;
        var cpy1 = shape.cpy1;
        var cpx2 = shape.cpx2;
        var cpy2 = shape.cpy2;
        var percent = shape.percent;
        if (percent === 0) {
            return;
        }
        ctx.moveTo(x1, y1);
        if (cpx2 == null || cpy2 == null) {
            if (percent < 1) {
                quadraticSubdivide(x1, cpx1, x2, percent, out);
                cpx1 = out[1];
                x2 = out[2];
                quadraticSubdivide(y1, cpy1, y2, percent, out);
                cpy1 = out[1];
                y2 = out[2];
            }
            ctx.quadraticCurveTo(cpx1, cpy1, x2, y2);
        }
        else {
            if (percent < 1) {
                cubicSubdivide(x1, cpx1, cpx2, x2, percent, out);
                cpx1 = out[1];
                cpx2 = out[2];
                x2 = out[3];
                cubicSubdivide(y1, cpy1, cpy2, y2, percent, out);
                cpy1 = out[1];
                cpy2 = out[2];
                y2 = out[3];
            }
            ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2);
        }
    };
    BezierCurve.prototype.pointAt = function (t) {
        return someVectorAt(this.shape, t, false);
    };
    BezierCurve.prototype.tangentAt = function (t) {
        var p = someVectorAt(this.shape, t, true);
        return normalize$1(p, p);
    };
    return BezierCurve;
}(Path$1));
BezierCurve.prototype.type = 'bezier-curve';
const BezierCurve$1 = BezierCurve;

/* Injected with object hook! */

var ArcShape = (function () {
    function ArcShape() {
        this.cx = 0;
        this.cy = 0;
        this.r = 0;
        this.startAngle = 0;
        this.endAngle = Math.PI * 2;
        this.clockwise = true;
    }
    return ArcShape;
}());
var Arc = (function (_super) {
    __extends(Arc, _super);
    function Arc(opts) {
        return _super.call(this, opts) || this;
    }
    Arc.prototype.getDefaultStyle = function () {
        return {
            stroke: '#000',
            fill: null
        };
    };
    Arc.prototype.getDefaultShape = function () {
        return new ArcShape();
    };
    Arc.prototype.buildPath = function (ctx, shape) {
        var x = shape.cx;
        var y = shape.cy;
        var r = Math.max(shape.r, 0);
        var startAngle = shape.startAngle;
        var endAngle = shape.endAngle;
        var clockwise = shape.clockwise;
        var unitX = Math.cos(startAngle);
        var unitY = Math.sin(startAngle);
        ctx.moveTo(unitX * r + x, unitY * r + y);
        ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
    };
    return Arc;
}(Path$1));
Arc.prototype.type = 'arc';
const Arc$1 = Arc;

/* Injected with object hook! */

var CompoundPath = (function (_super) {
    __extends(CompoundPath, _super);
    function CompoundPath() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.type = 'compound';
        return _this;
    }
    CompoundPath.prototype._updatePathDirty = function () {
        var paths = this.shape.paths;
        var dirtyPath = this.shapeChanged();
        for (var i = 0; i < paths.length; i++) {
            dirtyPath = dirtyPath || paths[i].shapeChanged();
        }
        if (dirtyPath) {
            this.dirtyShape();
        }
    };
    CompoundPath.prototype.beforeBrush = function () {
        this._updatePathDirty();
        var paths = this.shape.paths || [];
        var scale = this.getGlobalScale();
        for (var i = 0; i < paths.length; i++) {
            if (!paths[i].path) {
                paths[i].createPathProxy();
            }
            paths[i].path.setScale(scale[0], scale[1], paths[i].segmentIgnoreThreshold);
        }
    };
    CompoundPath.prototype.buildPath = function (ctx, shape) {
        var paths = shape.paths || [];
        for (var i = 0; i < paths.length; i++) {
            paths[i].buildPath(ctx, paths[i].shape, true);
        }
    };
    CompoundPath.prototype.afterBrush = function () {
        var paths = this.shape.paths || [];
        for (var i = 0; i < paths.length; i++) {
            paths[i].pathUpdated();
        }
    };
    CompoundPath.prototype.getBoundingRect = function () {
        this._updatePathDirty.call(this);
        return Path$1.prototype.getBoundingRect.call(this);
    };
    return CompoundPath;
}(Path$1));
const CompoundPath$1 = CompoundPath;

/* Injected with object hook! */

var Gradient = (function () {
    function Gradient(colorStops) {
        this.colorStops = colorStops || [];
    }
    Gradient.prototype.addColorStop = function (offset, color) {
        this.colorStops.push({
            offset: offset,
            color: color
        });
    };
    return Gradient;
}());
const Gradient$1 = Gradient;

/* Injected with object hook! */

var LinearGradient = (function (_super) {
    __extends(LinearGradient, _super);
    function LinearGradient(x, y, x2, y2, colorStops, globalCoord) {
        var _this = _super.call(this, colorStops) || this;
        _this.x = x == null ? 0 : x;
        _this.y = y == null ? 0 : y;
        _this.x2 = x2 == null ? 1 : x2;
        _this.y2 = y2 == null ? 0 : y2;
        _this.type = 'linear';
        _this.global = globalCoord || false;
        return _this;
    }
    return LinearGradient;
}(Gradient$1));
const LinearGradient$1 = LinearGradient;

/* Injected with object hook! */

var RadialGradient = (function (_super) {
    __extends(RadialGradient, _super);
    function RadialGradient(x, y, r, colorStops, globalCoord) {
        var _this = _super.call(this, colorStops) || this;
        _this.x = x == null ? 0.5 : x;
        _this.y = y == null ? 0.5 : y;
        _this.r = r == null ? 0.5 : r;
        _this.type = 'radial';
        _this.global = globalCoord || false;
        return _this;
    }
    return RadialGradient;
}(Gradient$1));
const RadialGradient$1 = RadialGradient;

/* Injected with object hook! */

var extent = [0, 0];
var extent2 = [0, 0];
var minTv = new Point$1();
var maxTv = new Point$1();
var OrientedBoundingRect = (function () {
    function OrientedBoundingRect(rect, transform) {
        this._corners = [];
        this._axes = [];
        this._origin = [0, 0];
        for (var i = 0; i < 4; i++) {
            this._corners[i] = new Point$1();
        }
        for (var i = 0; i < 2; i++) {
            this._axes[i] = new Point$1();
        }
        if (rect) {
            this.fromBoundingRect(rect, transform);
        }
    }
    OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) {
        var corners = this._corners;
        var axes = this._axes;
        var x = rect.x;
        var y = rect.y;
        var x2 = x + rect.width;
        var y2 = y + rect.height;
        corners[0].set(x, y);
        corners[1].set(x2, y);
        corners[2].set(x2, y2);
        corners[3].set(x, y2);
        if (transform) {
            for (var i = 0; i < 4; i++) {
                corners[i].transform(transform);
            }
        }
        Point$1.sub(axes[0], corners[1], corners[0]);
        Point$1.sub(axes[1], corners[3], corners[0]);
        axes[0].normalize();
        axes[1].normalize();
        for (var i = 0; i < 2; i++) {
            this._origin[i] = axes[i].dot(corners[0]);
        }
    };
    OrientedBoundingRect.prototype.intersect = function (other, mtv) {
        var overlapped = true;
        var noMtv = !mtv;
        minTv.set(Infinity, Infinity);
        maxTv.set(0, 0);
        if (!this._intersectCheckOneSide(this, other, minTv, maxTv, noMtv, 1)) {
            overlapped = false;
            if (noMtv) {
                return overlapped;
            }
        }
        if (!this._intersectCheckOneSide(other, this, minTv, maxTv, noMtv, -1)) {
            overlapped = false;
            if (noMtv) {
                return overlapped;
            }
        }
        if (!noMtv) {
            Point$1.copy(mtv, overlapped ? minTv : maxTv);
        }
        return overlapped;
    };
    OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, minTv, maxTv, noMtv, inverse) {
        var overlapped = true;
        for (var i = 0; i < 2; i++) {
            var axis = this._axes[i];
            this._getProjMinMaxOnAxis(i, self._corners, extent);
            this._getProjMinMaxOnAxis(i, other._corners, extent2);
            if (extent[1] < extent2[0] || extent[0] > extent2[1]) {
                overlapped = false;
                if (noMtv) {
                    return overlapped;
                }
                var dist0 = Math.abs(extent2[0] - extent[1]);
                var dist1 = Math.abs(extent[0] - extent2[1]);
                if (Math.min(dist0, dist1) > maxTv.len()) {
                    if (dist0 < dist1) {
                        Point$1.scale(maxTv, axis, -dist0 * inverse);
                    }
                    else {
                        Point$1.scale(maxTv, axis, dist1 * inverse);
                    }
                }
            }
            else if (minTv) {
                var dist0 = Math.abs(extent2[0] - extent[1]);
                var dist1 = Math.abs(extent[0] - extent2[1]);
                if (Math.min(dist0, dist1) < minTv.len()) {
                    if (dist0 < dist1) {
                        Point$1.scale(minTv, axis, dist0 * inverse);
                    }
                    else {
                        Point$1.scale(minTv, axis, -dist1 * inverse);
                    }
                }
            }
        }
        return overlapped;
    };
    OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) {
        var axis = this._axes[dim];
        var origin = this._origin;
        var proj = corners[0].dot(axis) + origin[dim];
        var min = proj;
        var max = proj;
        for (var i = 1; i < corners.length; i++) {
            var proj_1 = corners[i].dot(axis) + origin[dim];
            min = Math.min(proj_1, min);
            max = Math.max(proj_1, max);
        }
        out[0] = min;
        out[1] = max;
    };
    return OrientedBoundingRect;
}());
const OrientedBoundingRect$1 = OrientedBoundingRect;

/* Injected with object hook! */

var m = [];
var IncrementalDisplayable = (function (_super) {
    __extends(IncrementalDisplayable, _super);
    function IncrementalDisplayable() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.notClear = true;
        _this.incremental = true;
        _this._displayables = [];
        _this._temporaryDisplayables = [];
        _this._cursor = 0;
        return _this;
    }
    IncrementalDisplayable.prototype.traverse = function (cb, context) {
        cb.call(context, this);
    };
    IncrementalDisplayable.prototype.useStyle = function () {
        this.style = {};
    };
    IncrementalDisplayable.prototype.getCursor = function () {
        return this._cursor;
    };
    IncrementalDisplayable.prototype.innerAfterBrush = function () {
        this._cursor = this._displayables.length;
    };
    IncrementalDisplayable.prototype.clearDisplaybles = function () {
        this._displayables = [];
        this._temporaryDisplayables = [];
        this._cursor = 0;
        this.markRedraw();
        this.notClear = false;
    };
    IncrementalDisplayable.prototype.clearTemporalDisplayables = function () {
        this._temporaryDisplayables = [];
    };
    IncrementalDisplayable.prototype.addDisplayable = function (displayable, notPersistent) {
        if (notPersistent) {
            this._temporaryDisplayables.push(displayable);
        }
        else {
            this._displayables.push(displayable);
        }
        this.markRedraw();
    };
    IncrementalDisplayable.prototype.addDisplayables = function (displayables, notPersistent) {
        notPersistent = notPersistent || false;
        for (var i = 0; i < displayables.length; i++) {
            this.addDisplayable(displayables[i], notPersistent);
        }
    };
    IncrementalDisplayable.prototype.getDisplayables = function () {
        return this._displayables;
    };
    IncrementalDisplayable.prototype.getTemporalDisplayables = function () {
        return this._temporaryDisplayables;
    };
    IncrementalDisplayable.prototype.eachPendingDisplayable = function (cb) {
        for (var i = this._cursor; i < this._displayables.length; i++) {
            cb && cb(this._displayables[i]);
        }
        for (var i = 0; i < this._temporaryDisplayables.length; i++) {
            cb && cb(this._temporaryDisplayables[i]);
        }
    };
    IncrementalDisplayable.prototype.update = function () {
        this.updateTransform();
        for (var i = this._cursor; i < this._displayables.length; i++) {
            var displayable = this._displayables[i];
            displayable.parent = this;
            displayable.update();
            displayable.parent = null;
        }
        for (var i = 0; i < this._temporaryDisplayables.length; i++) {
            var displayable = this._temporaryDisplayables[i];
            displayable.parent = this;
            displayable.update();
            displayable.parent = null;
        }
    };
    IncrementalDisplayable.prototype.getBoundingRect = function () {
        if (!this._rect) {
            var rect = new BoundingRect$1(Infinity, Infinity, -Infinity, -Infinity);
            for (var i = 0; i < this._displayables.length; i++) {
                var displayable = this._displayables[i];
                var childRect = displayable.getBoundingRect().clone();
                if (displayable.needLocalTransform()) {
                    childRect.applyTransform(displayable.getLocalTransform(m));
                }
                rect.union(childRect);
            }
            this._rect = rect;
        }
        return this._rect;
    };
    IncrementalDisplayable.prototype.contain = function (x, y) {
        var localPos = this.transformCoordToLocal(x, y);
        var rect = this.getBoundingRect();
        if (rect.contain(localPos[0], localPos[1])) {
            for (var i = 0; i < this._displayables.length; i++) {
                var displayable = this._displayables[i];
                if (displayable.contain(x, y)) {
                    return true;
                }
            }
        }
        return false;
    };
    return IncrementalDisplayable;
}(Displayable$1));
const IncrementalDisplayable$1 = IncrementalDisplayable;

/* Injected with object hook! */

var transitionStore = makeInner();
/**
 * Return null if animation is disabled.
 */

function getAnimationConfig(animationType, animatableModel, dataIndex, // Extra opts can override the option in animatable model.
extraOpts, // TODO It's only for pictorial bar now.
extraDelayParams) {
  var animationPayload; // Check if there is global animation configuration from dataZoom/resize can override the config in option.
  // If animation is enabled. Will use this animation config in payload.
  // If animation is disabled. Just ignore it.

  if (animatableModel && animatableModel.ecModel) {
    var updatePayload = animatableModel.ecModel.getUpdatePayload();
    animationPayload = updatePayload && updatePayload.animation;
  }

  var animationEnabled = animatableModel && animatableModel.isAnimationEnabled();
  var isUpdate = animationType === 'update';

  if (animationEnabled) {
    var duration = void 0;
    var easing = void 0;
    var delay = void 0;

    if (extraOpts) {
      duration = retrieve2(extraOpts.duration, 200);
      easing = retrieve2(extraOpts.easing, 'cubicOut');
      delay = 0;
    } else {
      duration = animatableModel.getShallow(isUpdate ? 'animationDurationUpdate' : 'animationDuration');
      easing = animatableModel.getShallow(isUpdate ? 'animationEasingUpdate' : 'animationEasing');
      delay = animatableModel.getShallow(isUpdate ? 'animationDelayUpdate' : 'animationDelay');
    } // animation from payload has highest priority.


    if (animationPayload) {
      animationPayload.duration != null && (duration = animationPayload.duration);
      animationPayload.easing != null && (easing = animationPayload.easing);
      animationPayload.delay != null && (delay = animationPayload.delay);
    }

    if (isFunction(delay)) {
      delay = delay(dataIndex, extraDelayParams);
    }

    if (isFunction(duration)) {
      duration = duration(dataIndex);
    }

    var config = {
      duration: duration || 0,
      delay: delay,
      easing: easing
    };
    return config;
  } else {
    return null;
  }
}

function animateOrSetProps(animationType, el, props, animatableModel, dataIndex, cb, during) {
  var isFrom = false;
  var removeOpt;

  if (isFunction(dataIndex)) {
    during = cb;
    cb = dataIndex;
    dataIndex = null;
  } else if (isObject$2(dataIndex)) {
    cb = dataIndex.cb;
    during = dataIndex.during;
    isFrom = dataIndex.isFrom;
    removeOpt = dataIndex.removeOpt;
    dataIndex = dataIndex.dataIndex;
  }

  var isRemove = animationType === 'leave';

  if (!isRemove) {
    // Must stop the remove animation.
    el.stopAnimation('leave');
  }

  var animationConfig = getAnimationConfig(animationType, animatableModel, dataIndex, isRemove ? removeOpt || {} : null, animatableModel && animatableModel.getAnimationDelayParams ? animatableModel.getAnimationDelayParams(el, dataIndex) : null);

  if (animationConfig && animationConfig.duration > 0) {
    var duration = animationConfig.duration;
    var animationDelay = animationConfig.delay;
    var animationEasing = animationConfig.easing;
    var animateConfig = {
      duration: duration,
      delay: animationDelay || 0,
      easing: animationEasing,
      done: cb,
      force: !!cb || !!during,
      // Set to final state in update/init animation.
      // So the post processing based on the path shape can be done correctly.
      setToFinal: !isRemove,
      scope: animationType,
      during: during
    };
    isFrom ? el.animateFrom(props, animateConfig) : el.animateTo(props, animateConfig);
  } else {
    el.stopAnimation(); // If `isFrom`, the props is the "from" props.

    !isFrom && el.attr(props); // Call during at least once.

    during && during(1);
    cb && cb();
  }
}
/**
 * Update graphic element properties with or without animation according to the
 * configuration in series.
 *
 * Caution: this method will stop previous animation.
 * So do not use this method to one element twice before
 * animation starts, unless you know what you are doing.
 * @example
 *     graphic.updateProps(el, {
 *         position: [100, 100]
 *     }, seriesModel, dataIndex, function () { console.log('Animation done!'); });
 *     // Or
 *     graphic.updateProps(el, {
 *         position: [100, 100]
 *     }, seriesModel, function () { console.log('Animation done!'); });
 */


function updateProps$1(el, props, // TODO: TYPE AnimatableModel
animatableModel, dataIndex, cb, during) {
  animateOrSetProps('update', el, props, animatableModel, dataIndex, cb, during);
}
/**
 * Init graphic element properties with or without animation according to the
 * configuration in series.
 *
 * Caution: this method will stop previous animation.
 * So do not use this method to one element twice before
 * animation starts, unless you know what you are doing.
 */

function initProps(el, props, animatableModel, dataIndex, cb, during) {
  animateOrSetProps('enter', el, props, animatableModel, dataIndex, cb, during);
}
/**
 * If element is removed.
 * It can determine if element is having remove animation.
 */

function isElementRemoved(el) {
  if (!el.__zr) {
    return true;
  }

  for (var i = 0; i < el.animators.length; i++) {
    var animator = el.animators[i];

    if (animator.scope === 'leave') {
      return true;
    }
  }

  return false;
}
/**
 * Remove graphic element
 */

function removeElement(el, props, animatableModel, dataIndex, cb, during) {
  // Don't do remove animation twice.
  if (isElementRemoved(el)) {
    return;
  }

  animateOrSetProps('leave', el, props, animatableModel, dataIndex, cb, during);
}

function fadeOutDisplayable(el, animatableModel, dataIndex, done) {
  el.removeTextContent();
  el.removeTextGuideLine();
  removeElement(el, {
    style: {
      opacity: 0
    }
  }, animatableModel, dataIndex, done);
}

function removeElementWithFadeOut(el, animatableModel, dataIndex) {
  function doRemove() {
    el.parent && el.parent.remove(el);
  } // Hide label and labelLine first
  // TODO Also use fade out animation?


  if (!el.isGroup) {
    fadeOutDisplayable(el, animatableModel, dataIndex, doRemove);
  } else {
    el.traverse(function (disp) {
      if (!disp.isGroup) {
        // Can invoke doRemove multiple times.
        fadeOutDisplayable(disp, animatableModel, dataIndex, doRemove);
      }
    });
  }
}
/**
 * Save old style for style transition in universalTransition module.
 * It's used when element will be reused in each render.
 * For chart like map, heatmap, which will always create new element.
 * We don't need to save this because universalTransition can get old style from the old element
 */

function saveOldStyle(el) {
  transitionStore(el).oldStyle = el.style;
}
/* Injected with object hook! */

var mathMax$1 = Math.max;
var mathMin$1 = Math.min;
var _customShapeMap = {};
/**
 * Extend shape with parameters
 */

function extendShape(opts) {
  return Path$1.extend(opts);
}
var extendPathFromString = extendFromString;
/**
 * Extend path
 */

function extendPath(pathData, opts) {
  return extendPathFromString(pathData, opts);
}
/**
 * Register a user defined shape.
 * The shape class can be fetched by `getShapeClass`
 * This method will overwrite the registered shapes, including
 * the registered built-in shapes, if using the same `name`.
 * The shape can be used in `custom series` and
 * `graphic component` by declaring `{type: name}`.
 *
 * @param name
 * @param ShapeClass Can be generated by `extendShape`.
 */

function registerShape(name, ShapeClass) {
  _customShapeMap[name] = ShapeClass;
}
/**
 * Find shape class registered by `registerShape`. Usually used in
 * fetching user defined shape.
 *
 * [Caution]:
 * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared
 * to use user registered shapes.
 * Because the built-in shape (see `getBuiltInShape`) will be registered by
 * `registerShape` by default. That enables users to get both built-in
 * shapes as well as the shapes belonging to themsleves. But users can overwrite
 * the built-in shapes by using names like 'circle', 'rect' via calling
 * `registerShape`. So the echarts inner featrues should not fetch shapes from here
 * in case that it is overwritten by users, except that some features, like
 * `custom series`, `graphic component`, do it deliberately.
 *
 * (2) In the features like `custom series`, `graphic component`, the user input
 * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic
 * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names
 * are reserved names, that is, if some user registers a shape named `'image'`,
 * the shape will not be used. If we intending to add some more reserved names
 * in feature, that might bring break changes (disable some existing user shape
 * names). But that case probably rarely happens. So we don't make more mechanism
 * to resolve this issue here.
 *
 * @param name
 * @return The shape class. If not found, return nothing.
 */

function getShapeClass(name) {
  if (_customShapeMap.hasOwnProperty(name)) {
    return _customShapeMap[name];
  }
}
/**
 * Create a path element from path data string
 * @param pathData
 * @param opts
 * @param rect
 * @param layout 'center' or 'cover' default to be cover
 */

function makePath(pathData, opts, rect, layout) {
  var path = createFromString(pathData, opts);

  if (rect) {
    if (layout === 'center') {
      rect = centerGraphic(rect, path.getBoundingRect());
    }

    resizePath(path, rect);
  }

  return path;
}
/**
 * Create a image element from image url
 * @param imageUrl image url
 * @param opts options
 * @param rect constrain rect
 * @param layout 'center' or 'cover'. Default to be 'cover'
 */

function makeImage(imageUrl, rect, layout) {
  var zrImg = new ZRImage$1({
    style: {
      image: imageUrl,
      x: rect.x,
      y: rect.y,
      width: rect.width,
      height: rect.height
    },
    onload: function (img) {
      if (layout === 'center') {
        var boundingRect = {
          width: img.width,
          height: img.height
        };
        zrImg.setStyle(centerGraphic(rect, boundingRect));
      }
    }
  });
  return zrImg;
}
/**
 * Get position of centered element in bounding box.
 *
 * @param  rect         element local bounding box
 * @param  boundingRect constraint bounding box
 * @return element position containing x, y, width, and height
 */

function centerGraphic(rect, boundingRect) {
  // Set rect to center, keep width / height ratio.
  var aspect = boundingRect.width / boundingRect.height;
  var width = rect.height * aspect;
  var height;

  if (width <= rect.width) {
    height = rect.height;
  } else {
    width = rect.width;
    height = width / aspect;
  }

  var cx = rect.x + rect.width / 2;
  var cy = rect.y + rect.height / 2;
  return {
    x: cx - width / 2,
    y: cy - height / 2,
    width: width,
    height: height
  };
}

var mergePath = mergePath$1;
/**
 * Resize a path to fit the rect
 * @param path
 * @param rect
 */

function resizePath(path, rect) {
  if (!path.applyTransform) {
    return;
  }

  var pathRect = path.getBoundingRect();
  var m = pathRect.calculateTransform(rect);
  path.applyTransform(m);
}
/**
 * Sub pixel optimize line for canvas
 */

function subPixelOptimizeLine(shape, lineWidth) {
  subPixelOptimizeLine$1(shape, shape, {
    lineWidth: lineWidth
  });
  return shape;
}
/**
 * Sub pixel optimize rect for canvas
 */

function subPixelOptimizeRect(param) {
  subPixelOptimizeRect$1(param.shape, param.shape, param.style);
  return param;
}
/**
 * Sub pixel optimize for canvas
 *
 * @param position Coordinate, such as x, y
 * @param lineWidth Should be nonnegative integer.
 * @param positiveOrNegative Default false (negative).
 * @return Optimized position.
 */

var subPixelOptimize = subPixelOptimize$1;
/**
 * Get transform matrix of target (param target),
 * in coordinate of its ancestor (param ancestor)
 *
 * @param target
 * @param [ancestor]
 */

function getTransform(target, ancestor) {
  var mat = identity([]);

  while (target && target !== ancestor) {
    mul(mat, target.getLocalTransform(), mat);
    target = target.parent;
  }

  return mat;
}
/**
 * Apply transform to an vertex.
 * @param target [x, y]
 * @param transform Can be:
 *      + Transform matrix: like [1, 0, 0, 1, 0, 0]
 *      + {position, rotation, scale}, the same as `zrender/Transformable`.
 * @param invert Whether use invert matrix.
 * @return [x, y]
 */

function applyTransform(target, transform, invert$1) {
  if (transform && !isArrayLike(transform)) {
    transform = Transformable.getLocalTransform(transform);
  }

  if (invert$1) {
    transform = invert([], transform);
  }

  return applyTransform$1([], target, transform);
}
/**
 * @param direction 'left' 'right' 'top' 'bottom'
 * @param transform Transform matrix: like [1, 0, 0, 1, 0, 0]
 * @param invert Whether use invert matrix.
 * @return Transformed direction. 'left' 'right' 'top' 'bottom'
 */

function transformDirection(direction, transform, invert) {
  // Pick a base, ensure that transform result will not be (0, 0).
  var hBase = transform[4] === 0 || transform[5] === 0 || transform[0] === 0 ? 1 : Math.abs(2 * transform[4] / transform[0]);
  var vBase = transform[4] === 0 || transform[5] === 0 || transform[2] === 0 ? 1 : Math.abs(2 * transform[4] / transform[2]);
  var vertex = [direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0];
  vertex = applyTransform(vertex, transform, invert);
  return Math.abs(vertex[0]) > Math.abs(vertex[1]) ? vertex[0] > 0 ? 'right' : 'left' : vertex[1] > 0 ? 'bottom' : 'top';
}

function isNotGroup(el) {
  return !el.isGroup;
}

function isPath(el) {
  return el.shape != null;
}
/**
 * Apply group transition animation from g1 to g2.
 * If no animatableModel, no animation.
 */


function groupTransition(g1, g2, animatableModel) {
  if (!g1 || !g2) {
    return;
  }

  function getElMap(g) {
    var elMap = {};
    g.traverse(function (el) {
      if (isNotGroup(el) && el.anid) {
        elMap[el.anid] = el;
      }
    });
    return elMap;
  }

  function getAnimatableProps(el) {
    var obj = {
      x: el.x,
      y: el.y,
      rotation: el.rotation
    };

    if (isPath(el)) {
      obj.shape = extend({}, el.shape);
    }

    return obj;
  }

  var elMap1 = getElMap(g1);
  g2.traverse(function (el) {
    if (isNotGroup(el) && el.anid) {
      var oldEl = elMap1[el.anid];

      if (oldEl) {
        var newProp = getAnimatableProps(el);
        el.attr(getAnimatableProps(oldEl));
        updateProps$1(el, newProp, animatableModel, getECData(el).dataIndex);
      }
    }
  });
}
function clipPointsByRect(points, rect) {
  // FIXME: This way might be incorrect when graphic clipped by a corner
  // and when element has a border.
  return map$1(points, function (point) {
    var x = point[0];
    x = mathMax$1(x, rect.x);
    x = mathMin$1(x, rect.x + rect.width);
    var y = point[1];
    y = mathMax$1(y, rect.y);
    y = mathMin$1(y, rect.y + rect.height);
    return [x, y];
  });
}
/**
 * Return a new clipped rect. If rect size are negative, return undefined.
 */

function clipRectByRect(targetRect, rect) {
  var x = mathMax$1(targetRect.x, rect.x);
  var x2 = mathMin$1(targetRect.x + targetRect.width, rect.x + rect.width);
  var y = mathMax$1(targetRect.y, rect.y);
  var y2 = mathMin$1(targetRect.y + targetRect.height, rect.y + rect.height); // If the total rect is cliped, nothing, including the border,
  // should be painted. So return undefined.

  if (x2 >= x && y2 >= y) {
    return {
      x: x,
      y: y,
      width: x2 - x,
      height: y2 - y
    };
  }
}
function createIcon(iconStr, // Support 'image://' or 'path://' or direct svg path.
opt, rect) {
  var innerOpts = extend({
    rectHover: true
  }, opt);
  var style = innerOpts.style = {
    strokeNoScale: true
  };
  rect = rect || {
    x: -1,
    y: -1,
    width: 2,
    height: 2
  };

  if (iconStr) {
    return iconStr.indexOf('image://') === 0 ? (style.image = iconStr.slice(8), defaults(style, rect), new ZRImage$1(innerOpts)) : makePath(iconStr.replace('path://', ''), innerOpts, rect, 'center');
  }
}
/**
 * Return `true` if the given line (line `a`) and the given polygon
 * are intersect.
 * Note that we do not count colinear as intersect here because no
 * requirement for that. We could do that if required in future.
 */

function linePolygonIntersect(a1x, a1y, a2x, a2y, points) {
  for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) {
    var p = points[i];

    if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) {
      return true;
    }

    p2 = p;
  }
}
/**
 * Return `true` if the given two lines (line `a` and line `b`)
 * are intersect.
 * Note that we do not count colinear as intersect here because no
 * requirement for that. We could do that if required in future.
 */

function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) {
  // let `vec_m` to be `vec_a2 - vec_a1` and `vec_n` to be `vec_b2 - vec_b1`.
  var mx = a2x - a1x;
  var my = a2y - a1y;
  var nx = b2x - b1x;
  var ny = b2y - b1y; // `vec_m` and `vec_n` are parallel iff
  //     existing `k` such that `vec_m = k · vec_n`, equivalent to `vec_m X vec_n = 0`.

  var nmCrossProduct = crossProduct2d(nx, ny, mx, my);

  if (nearZero(nmCrossProduct)) {
    return false;
  } // `vec_m` and `vec_n` are intersect iff
  //     existing `p` and `q` in [0, 1] such that `vec_a1 + p * vec_m = vec_b1 + q * vec_n`,
  //     such that `q = ((vec_a1 - vec_b1) X vec_m) / (vec_n X vec_m)`
  //           and `p = ((vec_a1 - vec_b1) X vec_n) / (vec_n X vec_m)`.


  var b1a1x = a1x - b1x;
  var b1a1y = a1y - b1y;
  var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct;

  if (q < 0 || q > 1) {
    return false;
  }

  var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct;

  if (p < 0 || p > 1) {
    return false;
  }

  return true;
}
/**
 * Cross product of 2-dimension vector.
 */

function crossProduct2d(x1, y1, x2, y2) {
  return x1 * y2 - x2 * y1;
}

function nearZero(val) {
  return val <= 1e-6 && val >= -1e-6;
}

function setTooltipConfig(opt) {
  var itemTooltipOption = opt.itemTooltipOption;
  var componentModel = opt.componentModel;
  var itemName = opt.itemName;
  var itemTooltipOptionObj = isString(itemTooltipOption) ? {
    formatter: itemTooltipOption
  } : itemTooltipOption;
  var mainType = componentModel.mainType;
  var componentIndex = componentModel.componentIndex;
  var formatterParams = {
    componentType: mainType,
    name: itemName,
    $vars: ['name']
  };
  formatterParams[mainType + 'Index'] = componentIndex;
  var formatterParamsExtra = opt.formatterParamsExtra;

  if (formatterParamsExtra) {
    each$4(keys(formatterParamsExtra), function (key) {
      if (!hasOwn(formatterParams, key)) {
        formatterParams[key] = formatterParamsExtra[key];
        formatterParams.$vars.push(key);
      }
    });
  }

  var ecData = getECData(opt.el);
  ecData.componentMainType = mainType;
  ecData.componentIndex = componentIndex;
  ecData.tooltipConfig = {
    name: itemName,
    option: defaults({
      content: itemName,
      formatterParams: formatterParams
    }, itemTooltipOptionObj)
  };
}

function traverseElement(el, cb) {
  var stopped; // TODO
  // Polyfill for fixing zrender group traverse don't visit it's root issue.

  if (el.isGroup) {
    stopped = cb(el);
  }

  if (!stopped) {
    el.traverse(cb);
  }
}

function traverseElements(els, cb) {
  if (els) {
    if (isArray(els)) {
      for (var i = 0; i < els.length; i++) {
        traverseElement(els[i], cb);
      }
    } else {
      traverseElement(els, cb);
    }
  }
} // Register built-in shapes. These shapes might be overwritten
// by users, although we do not recommend that.

registerShape('circle', Circle$1);
registerShape('ellipse', Ellipse$1);
registerShape('sector', Sector$1);
registerShape('ring', Ring$1);
registerShape('polygon', Polygon$1);
registerShape('polyline', Polyline$1);
registerShape('rect', Rect$1);
registerShape('line', Line$1);
registerShape('bezierCurve', BezierCurve$1);
registerShape('arc', Arc$1);
/* Injected with object hook! */

const graphic = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
    __proto__: null,
    Arc: Arc$1,
    BezierCurve: BezierCurve$1,
    BoundingRect: BoundingRect$1,
    Circle: Circle$1,
    CompoundPath: CompoundPath$1,
    Ellipse: Ellipse$1,
    Group: Group$3,
    Image: ZRImage$1,
    IncrementalDisplayable: IncrementalDisplayable$1,
    Line: Line$1,
    LinearGradient: LinearGradient$1,
    OrientedBoundingRect: OrientedBoundingRect$1,
    Path: Path$1,
    Point: Point$1,
    Polygon: Polygon$1,
    Polyline: Polyline$1,
    RadialGradient: RadialGradient$1,
    Rect: Rect$1,
    Ring: Ring$1,
    Sector: Sector$1,
    Text: ZRText$1,
    applyTransform,
    clipPointsByRect,
    clipRectByRect,
    createIcon,
    extendPath,
    extendShape,
    getShapeClass,
    getTransform,
    groupTransition,
    initProps,
    isElementRemoved,
    lineLineIntersect,
    linePolygonIntersect,
    makeImage,
    makePath,
    mergePath,
    registerShape,
    removeElement,
    removeElementWithFadeOut,
    resizePath,
    setTooltipConfig,
    subPixelOptimize,
    subPixelOptimizeLine,
    subPixelOptimizeRect,
    transformDirection,
    traverseElements,
    updateProps: updateProps$1
}, Symbol.toStringTag, { value: 'Module' }));

var EMPTY_OBJ = {};
function setLabelText(label, labelTexts) {
  for (var i = 0; i < SPECIAL_STATES.length; i++) {
    var stateName = SPECIAL_STATES[i];
    var text = labelTexts[stateName];
    var state = label.ensureState(stateName);
    state.style = state.style || {};
    state.style.text = text;
  }

  var oldStates = label.currentStates.slice();
  label.clearStates(true);
  label.setStyle({
    text: labelTexts.normal
  });
  label.useStates(oldStates, true);
}

function getLabelText(opt, stateModels, interpolatedValue) {
  var labelFetcher = opt.labelFetcher;
  var labelDataIndex = opt.labelDataIndex;
  var labelDimIndex = opt.labelDimIndex;
  var normalModel = stateModels.normal;
  var baseText;

  if (labelFetcher) {
    baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, normalModel && normalModel.get('formatter'), interpolatedValue != null ? {
      interpolatedValue: interpolatedValue
    } : null);
  }

  if (baseText == null) {
    baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt, interpolatedValue) : opt.defaultText;
  }

  var statesText = {
    normal: baseText
  };

  for (var i = 0; i < SPECIAL_STATES.length; i++) {
    var stateName = SPECIAL_STATES[i];
    var stateModel = stateModels[stateName];
    statesText[stateName] = retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, stateName, null, labelDimIndex, stateModel && stateModel.get('formatter')) : null, baseText);
  }

  return statesText;
}

function setLabelStyle(targetEl, labelStatesModels, opt, stateSpecified // TODO specified position?
) {
  opt = opt || EMPTY_OBJ;
  var isSetOnText = targetEl instanceof ZRText$1;
  var needsCreateText = false;

  for (var i = 0; i < DISPLAY_STATES.length; i++) {
    var stateModel = labelStatesModels[DISPLAY_STATES[i]];

    if (stateModel && stateModel.getShallow('show')) {
      needsCreateText = true;
      break;
    }
  }

  var textContent = isSetOnText ? targetEl : targetEl.getTextContent();

  if (needsCreateText) {
    if (!isSetOnText) {
      // Reuse the previous
      if (!textContent) {
        textContent = new ZRText$1();
        targetEl.setTextContent(textContent);
      } // Use same state proxy


      if (targetEl.stateProxy) {
        textContent.stateProxy = targetEl.stateProxy;
      }
    }

    var labelStatesTexts = getLabelText(opt, labelStatesModels);
    var normalModel = labelStatesModels.normal;
    var showNormal = !!normalModel.getShallow('show');
    var normalStyle = createTextStyle(normalModel, stateSpecified && stateSpecified.normal, opt, false, !isSetOnText);
    normalStyle.text = labelStatesTexts.normal;

    if (!isSetOnText) {
      // Always create new
      targetEl.setTextConfig(createTextConfig(normalModel, opt, false));
    }

    for (var i = 0; i < SPECIAL_STATES.length; i++) {
      var stateName = SPECIAL_STATES[i];
      var stateModel = labelStatesModels[stateName];

      if (stateModel) {
        var stateObj = textContent.ensureState(stateName);
        var stateShow = !!retrieve2(stateModel.getShallow('show'), showNormal);

        if (stateShow !== showNormal) {
          stateObj.ignore = !stateShow;
        }

        stateObj.style = createTextStyle(stateModel, stateSpecified && stateSpecified[stateName], opt, true, !isSetOnText);
        stateObj.style.text = labelStatesTexts[stateName];

        if (!isSetOnText) {
          var targetElEmphasisState = targetEl.ensureState(stateName);
          targetElEmphasisState.textConfig = createTextConfig(stateModel, opt, true);
        }
      }
    } // PENDING: if there is many requirements that emphasis position
    // need to be different from normal position, we might consider
    // auto silent is those cases.


    textContent.silent = !!normalModel.getShallow('silent'); // Keep x and y

    if (textContent.style.x != null) {
      normalStyle.x = textContent.style.x;
    }

    if (textContent.style.y != null) {
      normalStyle.y = textContent.style.y;
    }

    textContent.ignore = !showNormal; // Always create new style.

    textContent.useStyle(normalStyle);
    textContent.dirty();

    if (opt.enableTextSetter) {
      labelInner(textContent).setLabelText = function (interpolatedValue) {
        var labelStatesTexts = getLabelText(opt, labelStatesModels, interpolatedValue);
        setLabelText(textContent, labelStatesTexts);
      };
    }
  } else if (textContent) {
    // Not display rich text.
    textContent.ignore = true;
  }

  targetEl.dirty();
}
function getLabelStatesModels(itemModel, labelName) {
  labelName = labelName || 'label';
  var statesModels = {
    normal: itemModel.getModel(labelName)
  };

  for (var i = 0; i < SPECIAL_STATES.length; i++) {
    var stateName = SPECIAL_STATES[i];
    statesModels[stateName] = itemModel.getModel([stateName, labelName]);
  }

  return statesModels;
}
/**
 * Set basic textStyle properties.
 */

function createTextStyle(textStyleModel, specifiedTextStyle, // Fixed style in the code. Can't be set by model.
opt, isNotNormal, isAttached // If text is attached on an element. If so, auto color will handling in zrender.
) {
  var textStyle = {};
  setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached);
  specifiedTextStyle && extend(textStyle, specifiedTextStyle); // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);

  return textStyle;
}
function createTextConfig(textStyleModel, opt, isNotNormal) {
  opt = opt || {};
  var textConfig = {};
  var labelPosition;
  var labelRotate = textStyleModel.getShallow('rotate');
  var labelDistance = retrieve2(textStyleModel.getShallow('distance'), isNotNormal ? null : 5);
  var labelOffset = textStyleModel.getShallow('offset');
  labelPosition = textStyleModel.getShallow('position') || (isNotNormal ? null : 'inside'); // 'outside' is not a valid zr textPostion value, but used
  // in bar series, and magric type should be considered.

  labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top');

  if (labelPosition != null) {
    textConfig.position = labelPosition;
  }

  if (labelOffset != null) {
    textConfig.offset = labelOffset;
  }

  if (labelRotate != null) {
    labelRotate *= Math.PI / 180;
    textConfig.rotation = labelRotate;
  }

  if (labelDistance != null) {
    textConfig.distance = labelDistance;
  } // fill and auto is determined by the color of path fill if it's not specified by developers.


  textConfig.outsideFill = textStyleModel.get('color') === 'inherit' ? opt.inheritColor || null : 'auto';
  return textConfig;
}
/**
 * The uniform entry of set text style, that is, retrieve style definitions
 * from `model` and set to `textStyle` object.
 *
 * Never in merge mode, but in overwrite mode, that is, all of the text style
 * properties will be set. (Consider the states of normal and emphasis and
 * default value can be adopted, merge would make the logic too complicated
 * to manage.)
 */

function setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached) {
  // Consider there will be abnormal when merge hover style to normal style if given default value.
  opt = opt || EMPTY_OBJ;
  var ecModel = textStyleModel.ecModel;
  var globalTextStyle = ecModel && ecModel.option.textStyle; // Consider case:
  // {
  //     data: [{
  //         value: 12,
  //         label: {
  //             rich: {
  //                 // no 'a' here but using parent 'a'.
  //             }
  //         }
  //     }],
  //     rich: {
  //         a: { ... }
  //     }
  // }

  var richItemNames = getRichItemNames(textStyleModel);
  var richResult;

  if (richItemNames) {
    richResult = {};

    for (var name_1 in richItemNames) {
      if (richItemNames.hasOwnProperty(name_1)) {
        // Cascade is supported in rich.
        var richTextStyle = textStyleModel.getModel(['rich', name_1]); // In rich, never `disableBox`.
        // FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`,
        // the default color `'blue'` will not be adopted if no color declared in `rich`.
        // That might confuses users. So probably we should put `textStyleModel` as the
        // root ancestor of the `richTextStyle`. But that would be a break change.

        setTokenTextStyle(richResult[name_1] = {}, richTextStyle, globalTextStyle, opt, isNotNormal, isAttached, false, true);
      }
    }
  }

  if (richResult) {
    textStyle.rich = richResult;
  }

  var overflow = textStyleModel.get('overflow');

  if (overflow) {
    textStyle.overflow = overflow;
  }

  var margin = textStyleModel.get('minMargin');

  if (margin != null) {
    textStyle.margin = margin;
  }

  setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, true, false);
} // Consider case:
// {
//     data: [{
//         value: 12,
//         label: {
//             rich: {
//                 // no 'a' here but using parent 'a'.
//             }
//         }
//     }],
//     rich: {
//         a: { ... }
//     }
// }
// TODO TextStyleModel


function getRichItemNames(textStyleModel) {
  // Use object to remove duplicated names.
  var richItemNameMap;

  while (textStyleModel && textStyleModel !== textStyleModel.ecModel) {
    var rich = (textStyleModel.option || EMPTY_OBJ).rich;

    if (rich) {
      richItemNameMap = richItemNameMap || {};
      var richKeys = keys(rich);

      for (var i = 0; i < richKeys.length; i++) {
        var richKey = richKeys[i];
        richItemNameMap[richKey] = 1;
      }
    }

    textStyleModel = textStyleModel.parentModel;
  }

  return richItemNameMap;
}

var TEXT_PROPS_WITH_GLOBAL = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'];
var TEXT_PROPS_SELF = ['align', 'lineHeight', 'width', 'height', 'tag', 'verticalAlign', 'ellipsis'];
var TEXT_PROPS_BOX = ['padding', 'borderWidth', 'borderRadius', 'borderDashOffset', 'backgroundColor', 'borderColor', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'];

function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, isBlock, inRich) {
  // In merge mode, default value should not be given.
  globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ;
  var inheritColor = opt && opt.inheritColor;
  var fillColor = textStyleModel.getShallow('color');
  var strokeColor = textStyleModel.getShallow('textBorderColor');
  var opacity = retrieve2(textStyleModel.getShallow('opacity'), globalTextStyle.opacity);

  if (fillColor === 'inherit' || fillColor === 'auto') {

    if (inheritColor) {
      fillColor = inheritColor;
    } else {
      fillColor = null;
    }
  }

  if (strokeColor === 'inherit' || strokeColor === 'auto') {

    if (inheritColor) {
      strokeColor = inheritColor;
    } else {
      strokeColor = null;
    }
  }

  if (!isAttached) {
    // Only use default global textStyle.color if text is individual.
    // Otherwise it will use the strategy of attached text color because text may be on a path.
    fillColor = fillColor || globalTextStyle.color;
    strokeColor = strokeColor || globalTextStyle.textBorderColor;
  }

  if (fillColor != null) {
    textStyle.fill = fillColor;
  }

  if (strokeColor != null) {
    textStyle.stroke = strokeColor;
  }

  var textBorderWidth = retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth);

  if (textBorderWidth != null) {
    textStyle.lineWidth = textBorderWidth;
  }

  var textBorderType = retrieve2(textStyleModel.getShallow('textBorderType'), globalTextStyle.textBorderType);

  if (textBorderType != null) {
    textStyle.lineDash = textBorderType;
  }

  var textBorderDashOffset = retrieve2(textStyleModel.getShallow('textBorderDashOffset'), globalTextStyle.textBorderDashOffset);

  if (textBorderDashOffset != null) {
    textStyle.lineDashOffset = textBorderDashOffset;
  }

  if (!isNotNormal && opacity == null && !inRich) {
    opacity = opt && opt.defaultOpacity;
  }

  if (opacity != null) {
    textStyle.opacity = opacity;
  } // TODO


  if (!isNotNormal && !isAttached) {
    // Set default finally.
    if (textStyle.fill == null && opt.inheritColor) {
      textStyle.fill = opt.inheritColor;
    }
  } // Do not use `getFont` here, because merge should be supported, where
  // part of these properties may be changed in emphasis style, and the
  // others should remain their original value got from normal style.


  for (var i = 0; i < TEXT_PROPS_WITH_GLOBAL.length; i++) {
    var key = TEXT_PROPS_WITH_GLOBAL[i];
    var val = retrieve2(textStyleModel.getShallow(key), globalTextStyle[key]);

    if (val != null) {
      textStyle[key] = val;
    }
  }

  for (var i = 0; i < TEXT_PROPS_SELF.length; i++) {
    var key = TEXT_PROPS_SELF[i];
    var val = textStyleModel.getShallow(key);

    if (val != null) {
      textStyle[key] = val;
    }
  }

  if (textStyle.verticalAlign == null) {
    var baseline = textStyleModel.getShallow('baseline');

    if (baseline != null) {
      textStyle.verticalAlign = baseline;
    }
  }

  if (!isBlock || !opt.disableBox) {
    for (var i = 0; i < TEXT_PROPS_BOX.length; i++) {
      var key = TEXT_PROPS_BOX[i];
      var val = textStyleModel.getShallow(key);

      if (val != null) {
        textStyle[key] = val;
      }
    }

    var borderType = textStyleModel.getShallow('borderType');

    if (borderType != null) {
      textStyle.borderDash = borderType;
    }

    if ((textStyle.backgroundColor === 'auto' || textStyle.backgroundColor === 'inherit') && inheritColor) {

      textStyle.backgroundColor = inheritColor;
    }

    if ((textStyle.borderColor === 'auto' || textStyle.borderColor === 'inherit') && inheritColor) {

      textStyle.borderColor = inheritColor;
    }
  }
}

function getFont(opt, ecModel) {
  var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
  return trim([// FIXME in node-canvas fontWeight is before fontStyle
  opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' '));
}
var labelInner = makeInner();
function setLabelValueAnimation(label, labelStatesModels, value, getDefaultText) {
  if (!label) {
    return;
  }

  var obj = labelInner(label);
  obj.prevValue = obj.value;
  obj.value = value;
  var normalLabelModel = labelStatesModels.normal;
  obj.valueAnimation = normalLabelModel.get('valueAnimation');

  if (obj.valueAnimation) {
    obj.precision = normalLabelModel.get('precision');
    obj.defaultInterpolatedText = getDefaultText;
    obj.statesModels = labelStatesModels;
  }
}
/* Injected with object hook! */

var PATH_COLOR = ['textStyle', 'color'];
var textStyleParams = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'padding', 'lineHeight', 'rich', 'width', 'height', 'overflow']; // TODO Performance improvement?

var tmpText = new ZRText$1();

var TextStyleMixin =
/** @class */
function () {
  function TextStyleMixin() {}
  /**
   * Get color property or get color from option.textStyle.color
   */
  // TODO Callback


  TextStyleMixin.prototype.getTextColor = function (isEmphasis) {
    var ecModel = this.ecModel;
    return this.getShallow('color') || (!isEmphasis && ecModel ? ecModel.get(PATH_COLOR) : null);
  };
  /**
   * Create font string from fontStyle, fontWeight, fontSize, fontFamily
   * @return {string}
   */


  TextStyleMixin.prototype.getFont = function () {
    return getFont({
      fontStyle: this.getShallow('fontStyle'),
      fontWeight: this.getShallow('fontWeight'),
      fontSize: this.getShallow('fontSize'),
      fontFamily: this.getShallow('fontFamily')
    }, this.ecModel);
  };

  TextStyleMixin.prototype.getTextRect = function (text) {
    var style = {
      text: text,
      verticalAlign: this.getShallow('verticalAlign') || this.getShallow('baseline')
    };

    for (var i = 0; i < textStyleParams.length; i++) {
      style[textStyleParams[i]] = this.getShallow(textStyleParams[i]);
    }

    tmpText.useStyle(style);
    tmpText.update();
    return tmpText.getBoundingRect();
  };

  return TextStyleMixin;
}();
const TextStyleMixin$1 = TextStyleMixin;
/* Injected with object hook! */

var LINE_STYLE_KEY_MAP = [['lineWidth', 'width'], ['stroke', 'color'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'type'], ['lineDashOffset', 'dashOffset'], ['lineCap', 'cap'], ['lineJoin', 'join'], ['miterLimit'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`.
// So do not transfer decal directly.
];
var getLineStyle = makeStyleMapper(LINE_STYLE_KEY_MAP);

var LineStyleMixin =
/** @class */
function () {
  function LineStyleMixin() {}

  LineStyleMixin.prototype.getLineStyle = function (excludes) {
    return getLineStyle(this, excludes);
  };

  return LineStyleMixin;
}();
/* Injected with object hook! */

var ITEM_STYLE_KEY_MAP = [['fill', 'color'], ['stroke', 'borderColor'], ['lineWidth', 'borderWidth'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'borderType'], ['lineDashOffset', 'borderDashOffset'], ['lineCap', 'borderCap'], ['lineJoin', 'borderJoin'], ['miterLimit', 'borderMiterLimit'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`.
// So do not transfer decal directly.
];
var getItemStyle = makeStyleMapper(ITEM_STYLE_KEY_MAP);

var ItemStyleMixin =
/** @class */
function () {
  function ItemStyleMixin() {}

  ItemStyleMixin.prototype.getItemStyle = function (excludes, includes) {
    return getItemStyle(this, excludes, includes);
  };

  return ItemStyleMixin;
}();
/* Injected with object hook! */

var Model =
/** @class */
function () {
  function Model(option, parentModel, ecModel) {
    this.parentModel = parentModel;
    this.ecModel = ecModel;
    this.option = option; // Simple optimization
    // if (this.init) {
    //     if (arguments.length <= 4) {
    //         this.init(option, parentModel, ecModel, extraOpt);
    //     }
    //     else {
    //         this.init.apply(this, arguments);
    //     }
    // }
  }

  Model.prototype.init = function (option, parentModel, ecModel) {
  };
  /**
   * Merge the input option to me.
   */


  Model.prototype.mergeOption = function (option, ecModel) {
    merge(this.option, option, true);
  }; // `path` can be 'a.b.c', so the return value type have to be `ModelOption`
  // TODO: TYPE strict key check?
  // get(path: string | string[], ignoreParent?: boolean): ModelOption;


  Model.prototype.get = function (path, ignoreParent) {
    if (path == null) {
      return this.option;
    }

    return this._doGet(this.parsePath(path), !ignoreParent && this.parentModel);
  };

  Model.prototype.getShallow = function (key, ignoreParent) {
    var option = this.option;
    var val = option == null ? option : option[key];

    if (val == null && !ignoreParent) {
      var parentModel = this.parentModel;

      if (parentModel) {
        // FIXME:TS do not know how to make it works
        val = parentModel.getShallow(key);
      }
    }

    return val;
  }; // `path` can be 'a.b.c', so the return value type have to be `Model<ModelOption>`
  // getModel(path: string | string[], parentModel?: Model): Model;
  // TODO 'a.b.c' is deprecated


  Model.prototype.getModel = function (path, parentModel) {
    var hasPath = path != null;
    var pathFinal = hasPath ? this.parsePath(path) : null;
    var obj = hasPath ? this._doGet(pathFinal) : this.option;
    parentModel = parentModel || this.parentModel && this.parentModel.getModel(this.resolveParentPath(pathFinal));
    return new Model(obj, parentModel, this.ecModel);
  };
  /**
   * If model has option
   */


  Model.prototype.isEmpty = function () {
    return this.option == null;
  };

  Model.prototype.restoreData = function () {}; // Pending


  Model.prototype.clone = function () {
    var Ctor = this.constructor;
    return new Ctor(clone$2(this.option));
  }; // setReadOnly(properties): void {
  // clazzUtil.setReadOnly(this, properties);
  // }
  // If path is null/undefined, return null/undefined.


  Model.prototype.parsePath = function (path) {
    if (typeof path === 'string') {
      return path.split('.');
    }

    return path;
  }; // Resolve path for parent. Perhaps useful when parent use a different property.
  // Default to be a identity resolver.
  // Can be modified to a different resolver.


  Model.prototype.resolveParentPath = function (path) {
    return path;
  }; // FIXME:TS check whether put this method here


  Model.prototype.isAnimationEnabled = function () {
    if (!env$1.node && this.option) {
      if (this.option.animation != null) {
        return !!this.option.animation;
      } else if (this.parentModel) {
        return this.parentModel.isAnimationEnabled();
      }
    }
  };

  Model.prototype._doGet = function (pathArr, parentModel) {
    var obj = this.option;

    if (!pathArr) {
      return obj;
    }

    for (var i = 0; i < pathArr.length; i++) {
      // Ignore empty
      if (!pathArr[i]) {
        continue;
      } // obj could be number/string/... (like 0)


      obj = obj && typeof obj === 'object' ? obj[pathArr[i]] : null;

      if (obj == null) {
        break;
      }
    }

    if (obj == null && parentModel) {
      obj = parentModel._doGet(this.resolveParentPath(pathArr), parentModel.parentModel);
    }

    return obj;
  };

  return Model;
}();

enableClassExtend(Model);
enableClassCheck(Model);
mixin(Model, LineStyleMixin);
mixin(Model, ItemStyleMixin);
mixin(Model, AreaStyleMixin);
mixin(Model, TextStyleMixin$1);
const Model$1 = Model;
/* Injected with object hook! */

var base = Math.round(Math.random() * 10);
/**
 * @public
 * @param {string} type
 * @return {string}
 */

function getUID(type) {
  // Considering the case of crossing js context,
  // use Math.random to make id as unique as possible.
  return [type || '', base++].join('_');
}
/**
 * Implements `SubTypeDefaulterManager` for `target`.
 */

function enableSubTypeDefaulter(target) {
  var subTypeDefaulters = {};

  target.registerSubTypeDefaulter = function (componentType, defaulter) {
    var componentTypeInfo = parseClassType(componentType);
    subTypeDefaulters[componentTypeInfo.main] = defaulter;
  };

  target.determineSubType = function (componentType, option) {
    var type = option.type;

    if (!type) {
      var componentTypeMain = parseClassType(componentType).main;

      if (target.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) {
        type = subTypeDefaulters[componentTypeMain](option);
      }
    }

    return type;
  };
}
/**
 * Implements `TopologicalTravelable<any>` for `entity`.
 *
 * Topological travel on Activity Network (Activity On Vertices).
 * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].
 * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.
 * If there is circular dependencey, Error will be thrown.
 */

function enableTopologicalTravel(entity, dependencyGetter) {
  /**
   * @param targetNameList Target Component type list.
   *                       Can be ['aa', 'bb', 'aa.xx']
   * @param fullNameList By which we can build dependency graph.
   * @param callback Params: componentType, dependencies.
   * @param context Scope of callback.
   */
  entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) {
    if (!targetNameList.length) {
      return;
    }

    var result = makeDepndencyGraph(fullNameList);
    var graph = result.graph;
    var noEntryList = result.noEntryList;
    var targetNameSet = {};
    each$4(targetNameList, function (name) {
      targetNameSet[name] = true;
    });

    while (noEntryList.length) {
      var currComponentType = noEntryList.pop();
      var currVertex = graph[currComponentType];
      var isInTargetNameSet = !!targetNameSet[currComponentType];

      if (isInTargetNameSet) {
        callback.call(context, currComponentType, currVertex.originalDeps.slice());
        delete targetNameSet[currComponentType];
      }

      each$4(currVertex.successor, isInTargetNameSet ? removeEdgeAndAdd : removeEdge);
    }

    each$4(targetNameSet, function () {
      var errMsg = '';

      throw new Error(errMsg);
    });

    function removeEdge(succComponentType) {
      graph[succComponentType].entryCount--;

      if (graph[succComponentType].entryCount === 0) {
        noEntryList.push(succComponentType);
      }
    } // Consider this case: legend depends on series, and we call
    // chart.setOption({series: [...]}), where only series is in option.
    // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will
    // not be called, but only sereis.mergeOption is called. Thus legend
    // have no chance to update its local record about series (like which
    // name of series is available in legend).


    function removeEdgeAndAdd(succComponentType) {
      targetNameSet[succComponentType] = true;
      removeEdge(succComponentType);
    }
  };

  function makeDepndencyGraph(fullNameList) {
    var graph = {};
    var noEntryList = [];
    each$4(fullNameList, function (name) {
      var thisItem = createDependencyGraphItem(graph, name);
      var originalDeps = thisItem.originalDeps = dependencyGetter(name);
      var availableDeps = getAvailableDependencies(originalDeps, fullNameList);
      thisItem.entryCount = availableDeps.length;

      if (thisItem.entryCount === 0) {
        noEntryList.push(name);
      }

      each$4(availableDeps, function (dependentName) {
        if (indexOf(thisItem.predecessor, dependentName) < 0) {
          thisItem.predecessor.push(dependentName);
        }

        var thatItem = createDependencyGraphItem(graph, dependentName);

        if (indexOf(thatItem.successor, dependentName) < 0) {
          thatItem.successor.push(name);
        }
      });
    });
    return {
      graph: graph,
      noEntryList: noEntryList
    };
  }

  function createDependencyGraphItem(graph, name) {
    if (!graph[name]) {
      graph[name] = {
        predecessor: [],
        successor: []
      };
    }

    return graph[name];
  }

  function getAvailableDependencies(originalDeps, fullNameList) {
    var availableDeps = [];
    each$4(originalDeps, function (dep) {
      indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep);
    });
    return availableDeps;
  }
}
function inheritDefaultOption(superOption, subOption) {
  // See also `model/Component.ts#getDefaultOption`
  return merge(merge({}, superOption, true), subOption, true);
}
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * Language: English.
 */
const langEN = {
  time: {
    month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    monthAbbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    dayOfWeek: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    dayOfWeekAbbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
  },
  legend: {
    selector: {
      all: 'All',
      inverse: 'Inv'
    }
  },
  toolbox: {
    brush: {
      title: {
        rect: 'Box Select',
        polygon: 'Lasso Select',
        lineX: 'Horizontally Select',
        lineY: 'Vertically Select',
        keep: 'Keep Selections',
        clear: 'Clear Selections'
      }
    },
    dataView: {
      title: 'Data View',
      lang: ['Data View', 'Close', 'Refresh']
    },
    dataZoom: {
      title: {
        zoom: 'Zoom',
        back: 'Zoom Reset'
      }
    },
    magicType: {
      title: {
        line: 'Switch to Line Chart',
        bar: 'Switch to Bar Chart',
        stack: 'Stack',
        tiled: 'Tile'
      }
    },
    restore: {
      title: 'Restore'
    },
    saveAsImage: {
      title: 'Save as Image',
      lang: ['Right Click to Save Image']
    }
  },
  series: {
    typeNames: {
      pie: 'Pie chart',
      bar: 'Bar chart',
      line: 'Line chart',
      scatter: 'Scatter plot',
      effectScatter: 'Ripple scatter plot',
      radar: 'Radar chart',
      tree: 'Tree',
      treemap: 'Treemap',
      boxplot: 'Boxplot',
      candlestick: 'Candlestick',
      k: 'K line chart',
      heatmap: 'Heat map',
      map: 'Map',
      parallel: 'Parallel coordinate map',
      lines: 'Line graph',
      graph: 'Relationship graph',
      sankey: 'Sankey diagram',
      funnel: 'Funnel chart',
      gauge: 'Gauge',
      pictorialBar: 'Pictorial bar',
      themeRiver: 'Theme River Map',
      sunburst: 'Sunburst'
    }
  },
  aria: {
    general: {
      withTitle: 'This is a chart about "{title}"',
      withoutTitle: 'This is a chart'
    },
    series: {
      single: {
        prefix: '',
        withName: ' with type {seriesType} named {seriesName}.',
        withoutName: ' with type {seriesType}.'
      },
      multiple: {
        prefix: '. It consists of {seriesCount} series count.',
        withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.',
        withoutName: ' The {seriesId} series is a {seriesType}.',
        separator: {
          middle: '',
          end: ''
        }
      }
    },
    data: {
      allData: 'The data is as follows: ',
      partialData: 'The first {displayCnt} items are: ',
      withName: 'the data for {name} is {value}',
      withoutName: '{value}',
      separator: {
        middle: ', ',
        end: '. '
      }
    }
  }
};
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
const langZH = {
  time: {
    month: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    monthAbbr: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    dayOfWeek: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    dayOfWeekAbbr: ['日', '一', '二', '三', '四', '五', '六']
  },
  legend: {
    selector: {
      all: '全选',
      inverse: '反选'
    }
  },
  toolbox: {
    brush: {
      title: {
        rect: '矩形选择',
        polygon: '圈选',
        lineX: '横向选择',
        lineY: '纵向选择',
        keep: '保持选择',
        clear: '清除选择'
      }
    },
    dataView: {
      title: '数据视图',
      lang: ['数据视图', '关闭', '刷新']
    },
    dataZoom: {
      title: {
        zoom: '区域缩放',
        back: '区域缩放还原'
      }
    },
    magicType: {
      title: {
        line: '切换为折线图',
        bar: '切换为柱状图',
        stack: '切换为堆叠',
        tiled: '切换为平铺'
      }
    },
    restore: {
      title: '还原'
    },
    saveAsImage: {
      title: '保存为图片',
      lang: ['右键另存为图片']
    }
  },
  series: {
    typeNames: {
      pie: '饼图',
      bar: '柱状图',
      line: '折线图',
      scatter: '散点图',
      effectScatter: '涟漪散点图',
      radar: '雷达图',
      tree: '树图',
      treemap: '矩形树图',
      boxplot: '箱型图',
      candlestick: 'K线图',
      k: 'K线图',
      heatmap: '热力图',
      map: '地图',
      parallel: '平行坐标图',
      lines: '线图',
      graph: '关系图',
      sankey: '桑基图',
      funnel: '漏斗图',
      gauge: '仪表盘图',
      pictorialBar: '象形柱图',
      themeRiver: '主题河流图',
      sunburst: '旭日图'
    }
  },
  aria: {
    general: {
      withTitle: '这是一个关于“{title}”的图表。',
      withoutTitle: '这是一个图表，'
    },
    series: {
      single: {
        prefix: '',
        withName: '图表类型是{seriesType}，表示{seriesName}。',
        withoutName: '图表类型是{seriesType}。'
      },
      multiple: {
        prefix: '它由{seriesCount}个图表系列组成。',
        withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType}，',
        withoutName: '第{seriesId}个系列是一个{seriesType}，',
        separator: {
          middle: '；',
          end: '。'
        }
      }
    },
    data: {
      allData: '其数据是——',
      partialData: '其中，前{displayCnt}项是——',
      withName: '{name}的数据是{value}',
      withoutName: '{value}',
      separator: {
        middle: '，',
        end: ''
      }
    }
  }
};
/* Injected with object hook! */

var LOCALE_ZH = 'ZH';
var LOCALE_EN = 'EN';
var DEFAULT_LOCALE = LOCALE_EN;
var localeStorage = {};
var localeModels = {};
var SYSTEM_LANG = !env$1.domSupported ? DEFAULT_LOCALE : function () {
  var langStr = (
  /* eslint-disable-next-line */
  document.documentElement.lang || navigator.language || navigator.browserLanguage).toUpperCase();
  return langStr.indexOf(LOCALE_ZH) > -1 ? LOCALE_ZH : DEFAULT_LOCALE;
}();
function registerLocale(locale, localeObj) {
  locale = locale.toUpperCase();
  localeModels[locale] = new Model$1(localeObj);
  localeStorage[locale] = localeObj;
} // export function getLocale(locale: string) {
//     return localeStorage[locale];
// }

function createLocaleObject(locale) {
  if (isString(locale)) {
    var localeObj = localeStorage[locale.toUpperCase()] || {};

    if (locale === LOCALE_ZH || locale === LOCALE_EN) {
      return clone$2(localeObj);
    } else {
      return merge(clone$2(localeObj), clone$2(localeStorage[DEFAULT_LOCALE]), false);
    }
  } else {
    return merge(clone$2(locale), clone$2(localeStorage[DEFAULT_LOCALE]), false);
  }
}
function getLocaleModel(lang) {
  return localeModels[lang];
}
function getDefaultLocaleModel() {
  return localeModels[DEFAULT_LOCALE];
} // Default locale

registerLocale(LOCALE_EN, langEN);
registerLocale(LOCALE_ZH, langZH);
/* Injected with object hook! */

var ONE_SECOND = 1000;
var ONE_MINUTE = ONE_SECOND * 60;
var ONE_HOUR = ONE_MINUTE * 60;
var ONE_DAY = ONE_HOUR * 24;
var ONE_YEAR = ONE_DAY * 365;
var defaultLeveledFormatter = {
  year: '{yyyy}',
  month: '{MMM}',
  day: '{d}',
  hour: '{HH}:{mm}',
  minute: '{HH}:{mm}',
  second: '{HH}:{mm}:{ss}',
  millisecond: '{HH}:{mm}:{ss} {SSS}',
  none: '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss} {SSS}'
};
var fullDayFormatter = '{yyyy}-{MM}-{dd}';
var fullLeveledFormatter = {
  year: '{yyyy}',
  month: '{yyyy}-{MM}',
  day: fullDayFormatter,
  hour: fullDayFormatter + ' ' + defaultLeveledFormatter.hour,
  minute: fullDayFormatter + ' ' + defaultLeveledFormatter.minute,
  second: fullDayFormatter + ' ' + defaultLeveledFormatter.second,
  millisecond: defaultLeveledFormatter.none
};
var primaryTimeUnits = ['year', 'month', 'day', 'hour', 'minute', 'second', 'millisecond'];
var timeUnits = ['year', 'half-year', 'quarter', 'month', 'week', 'half-week', 'day', 'half-day', 'quarter-day', 'hour', 'minute', 'second', 'millisecond'];
function pad(str, len) {
  str += '';
  return '0000'.substr(0, len - str.length) + str;
}
function getPrimaryTimeUnit(timeUnit) {
  switch (timeUnit) {
    case 'half-year':
    case 'quarter':
      return 'month';

    case 'week':
    case 'half-week':
      return 'day';

    case 'half-day':
    case 'quarter-day':
      return 'hour';

    default:
      // year, minutes, second, milliseconds
      return timeUnit;
  }
}
function isPrimaryTimeUnit(timeUnit) {
  return timeUnit === getPrimaryTimeUnit(timeUnit);
}
function getDefaultFormatPrecisionOfInterval(timeUnit) {
  switch (timeUnit) {
    case 'year':
    case 'month':
      return 'day';

    case 'millisecond':
      return 'millisecond';

    default:
      // Also for day, hour, minute, second
      return 'second';
  }
}
function format( // Note: The result based on `isUTC` are totally different, which can not be just simply
// substituted by the result without `isUTC`. So we make the param `isUTC` mandatory.
time, template, isUTC, lang) {
  var date = parseDate(time);
  var y = date[fullYearGetterName(isUTC)]();
  var M = date[monthGetterName(isUTC)]() + 1;
  var q = Math.floor((M - 1) / 3) + 1;
  var d = date[dateGetterName(isUTC)]();
  var e = date['get' + (isUTC ? 'UTC' : '') + 'Day']();
  var H = date[hoursGetterName(isUTC)]();
  var h = (H - 1) % 12 + 1;
  var m = date[minutesGetterName(isUTC)]();
  var s = date[secondsGetterName(isUTC)]();
  var S = date[millisecondsGetterName(isUTC)]();
  var localeModel = lang instanceof Model$1 ? lang : getLocaleModel(lang || SYSTEM_LANG) || getDefaultLocaleModel();
  var timeModel = localeModel.getModel('time');
  var month = timeModel.get('month');
  var monthAbbr = timeModel.get('monthAbbr');
  var dayOfWeek = timeModel.get('dayOfWeek');
  var dayOfWeekAbbr = timeModel.get('dayOfWeekAbbr');
  return (template || '').replace(/{yyyy}/g, y + '').replace(/{yy}/g, pad(y % 100 + '', 2)).replace(/{Q}/g, q + '').replace(/{MMMM}/g, month[M - 1]).replace(/{MMM}/g, monthAbbr[M - 1]).replace(/{MM}/g, pad(M, 2)).replace(/{M}/g, M + '').replace(/{dd}/g, pad(d, 2)).replace(/{d}/g, d + '').replace(/{eeee}/g, dayOfWeek[e]).replace(/{ee}/g, dayOfWeekAbbr[e]).replace(/{e}/g, e + '').replace(/{HH}/g, pad(H, 2)).replace(/{H}/g, H + '').replace(/{hh}/g, pad(h + '', 2)).replace(/{h}/g, h + '').replace(/{mm}/g, pad(m, 2)).replace(/{m}/g, m + '').replace(/{ss}/g, pad(s, 2)).replace(/{s}/g, s + '').replace(/{SSS}/g, pad(S, 3)).replace(/{S}/g, S + '');
}
function leveledFormat(tick, idx, formatter, lang, isUTC) {
  var template = null;

  if (isString(formatter)) {
    // Single formatter for all units at all levels
    template = formatter;
  } else if (isFunction(formatter)) {
    // Callback formatter
    template = formatter(tick.value, idx, {
      level: tick.level
    });
  } else {
    var defaults$1 = extend({}, defaultLeveledFormatter);

    if (tick.level > 0) {
      for (var i = 0; i < primaryTimeUnits.length; ++i) {
        defaults$1[primaryTimeUnits[i]] = "{primary|" + defaults$1[primaryTimeUnits[i]] + "}";
      }
    }

    var mergedFormatter = formatter ? formatter.inherit === false ? formatter // Use formatter with bigger units
    : defaults(formatter, defaults$1) : defaults$1;
    var unit = getUnitFromValue(tick.value, isUTC);

    if (mergedFormatter[unit]) {
      template = mergedFormatter[unit];
    } else if (mergedFormatter.inherit) {
      // Unit formatter is not defined and should inherit from bigger units
      var targetId = timeUnits.indexOf(unit);

      for (var i = targetId - 1; i >= 0; --i) {
        if (mergedFormatter[unit]) {
          template = mergedFormatter[unit];
          break;
        }
      }

      template = template || defaults$1.none;
    }

    if (isArray(template)) {
      var levelId = tick.level == null ? 0 : tick.level >= 0 ? tick.level : template.length + tick.level;
      levelId = Math.min(levelId, template.length - 1);
      template = template[levelId];
    }
  }

  return format(new Date(tick.value), template, isUTC, lang);
}
function getUnitFromValue(value, isUTC) {
  var date = parseDate(value);
  var M = date[monthGetterName(isUTC)]() + 1;
  var d = date[dateGetterName(isUTC)]();
  var h = date[hoursGetterName(isUTC)]();
  var m = date[minutesGetterName(isUTC)]();
  var s = date[secondsGetterName(isUTC)]();
  var S = date[millisecondsGetterName(isUTC)]();
  var isSecond = S === 0;
  var isMinute = isSecond && s === 0;
  var isHour = isMinute && m === 0;
  var isDay = isHour && h === 0;
  var isMonth = isDay && d === 1;
  var isYear = isMonth && M === 1;

  if (isYear) {
    return 'year';
  } else if (isMonth) {
    return 'month';
  } else if (isDay) {
    return 'day';
  } else if (isHour) {
    return 'hour';
  } else if (isMinute) {
    return 'minute';
  } else if (isSecond) {
    return 'second';
  } else {
    return 'millisecond';
  }
}
function getUnitValue(value, unit, isUTC) {
  var date = isNumber(value) ? parseDate(value) : value;
  unit = unit || getUnitFromValue(value, isUTC);

  switch (unit) {
    case 'year':
      return date[fullYearGetterName(isUTC)]();

    case 'half-year':
      return date[monthGetterName(isUTC)]() >= 6 ? 1 : 0;

    case 'quarter':
      return Math.floor((date[monthGetterName(isUTC)]() + 1) / 4);

    case 'month':
      return date[monthGetterName(isUTC)]();

    case 'day':
      return date[dateGetterName(isUTC)]();

    case 'half-day':
      return date[hoursGetterName(isUTC)]() / 24;

    case 'hour':
      return date[hoursGetterName(isUTC)]();

    case 'minute':
      return date[minutesGetterName(isUTC)]();

    case 'second':
      return date[secondsGetterName(isUTC)]();

    case 'millisecond':
      return date[millisecondsGetterName(isUTC)]();
  }
}
function fullYearGetterName(isUTC) {
  return isUTC ? 'getUTCFullYear' : 'getFullYear';
}
function monthGetterName(isUTC) {
  return isUTC ? 'getUTCMonth' : 'getMonth';
}
function dateGetterName(isUTC) {
  return isUTC ? 'getUTCDate' : 'getDate';
}
function hoursGetterName(isUTC) {
  return isUTC ? 'getUTCHours' : 'getHours';
}
function minutesGetterName(isUTC) {
  return isUTC ? 'getUTCMinutes' : 'getMinutes';
}
function secondsGetterName(isUTC) {
  return isUTC ? 'getUTCSeconds' : 'getSeconds';
}
function millisecondsGetterName(isUTC) {
  return isUTC ? 'getUTCMilliseconds' : 'getMilliseconds';
}
function fullYearSetterName(isUTC) {
  return isUTC ? 'setUTCFullYear' : 'setFullYear';
}
function monthSetterName(isUTC) {
  return isUTC ? 'setUTCMonth' : 'setMonth';
}
function dateSetterName(isUTC) {
  return isUTC ? 'setUTCDate' : 'setDate';
}
function hoursSetterName(isUTC) {
  return isUTC ? 'setUTCHours' : 'setHours';
}
function minutesSetterName(isUTC) {
  return isUTC ? 'setUTCMinutes' : 'setMinutes';
}
function secondsSetterName(isUTC) {
  return isUTC ? 'setUTCSeconds' : 'setSeconds';
}
function millisecondsSetterName(isUTC) {
  return isUTC ? 'setUTCMilliseconds' : 'setMilliseconds';
}
/* Injected with object hook! */

/**
 * Add a comma each three digit.
 */

function addCommas(x) {
  if (!isNumeric(x)) {
    return isString(x) ? x : '-';
  }

  var parts = (x + '').split('.');
  return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + (parts.length > 1 ? '.' + parts[1] : '');
}
function toCamelCase(str, upperCaseFirst) {
  str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) {
    return group1.toUpperCase();
  });

  if (upperCaseFirst && str) {
    str = str.charAt(0).toUpperCase() + str.slice(1);
  }

  return str;
}
var normalizeCssArray = normalizeCssArray$1;
/**
 * Make value user readable for tooltip and label.
 * "User readable":
 *     Try to not print programmer-specific text like NaN, Infinity, null, undefined.
 *     Avoid to display an empty string, which users can not recognize there is
 *     a value and it might look like a bug.
 */

function makeValueReadable(value, valueType, useUTC) {
  var USER_READABLE_DEFUALT_TIME_PATTERN = '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}';

  function stringToUserReadable(str) {
    return str && trim(str) ? str : '-';
  }

  function isNumberUserReadable(num) {
    return !!(num != null && !isNaN(num) && isFinite(num));
  }

  var isTypeTime = valueType === 'time';
  var isValueDate = value instanceof Date;

  if (isTypeTime || isValueDate) {
    var date = isTypeTime ? parseDate(value) : value;

    if (!isNaN(+date)) {
      return format(date, USER_READABLE_DEFUALT_TIME_PATTERN, useUTC);
    } else if (isValueDate) {
      return '-';
    } // In other cases, continue to try to display the value in the following code.

  }

  if (valueType === 'ordinal') {
    return isStringSafe(value) ? stringToUserReadable(value) : isNumber(value) ? isNumberUserReadable(value) ? value + '' : '-' : '-';
  } // By default.


  var numericResult = numericToNumber(value);
  return isNumberUserReadable(numericResult) ? addCommas(numericResult) : isStringSafe(value) ? stringToUserReadable(value) : typeof value === 'boolean' ? value + '' : '-';
}
var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

var wrapVar = function (varName, seriesIdx) {
  return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
};
/**
 * Template formatter
 * @param {Array.<Object>|Object} paramsList
 */


function formatTpl(tpl, paramsList, encode) {
  if (!isArray(paramsList)) {
    paramsList = [paramsList];
  }

  var seriesLen = paramsList.length;

  if (!seriesLen) {
    return '';
  }

  var $vars = paramsList[0].$vars || [];

  for (var i = 0; i < $vars.length; i++) {
    var alias = TPL_VAR_ALIAS[i];
    tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0));
  }

  for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
    for (var k = 0; k < $vars.length; k++) {
      var val = paramsList[seriesIdx][$vars[k]];
      tpl = tpl.replace(wrapVar(TPL_VAR_ALIAS[k], seriesIdx), encode ? encodeHTML(val) : val);
    }
  }

  return tpl;
}
function getTooltipMarker(inOpt, extraCssText) {
  var opt = isString(inOpt) ? {
    color: inOpt,
    extraCssText: extraCssText
  } : inOpt || {};
  var color = opt.color;
  var type = opt.type;
  extraCssText = opt.extraCssText;
  var renderMode = opt.renderMode || 'html';

  if (!color) {
    return '';
  }

  if (renderMode === 'html') {
    return type === 'subItem' ? '<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;' + 'border-radius:4px;width:4px;height:4px;background-color:' // Only support string
    + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>' : '<span style="display:inline-block;margin-right:4px;' + 'border-radius:10px;width:10px;height:10px;background-color:' + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>';
  } else {
    // Should better not to auto generate style name by auto-increment number here.
    // Because this util is usually called in tooltip formatter, which is probably
    // called repeatedly when mouse move and the auto-increment number increases fast.
    // Users can make their own style name by theirselves, make it unique and readable.
    var markerId = opt.markerId || 'markerX';
    return {
      renderMode: renderMode,
      content: '{' + markerId + '|}  ',
      style: type === 'subItem' ? {
        width: 4,
        height: 4,
        borderRadius: 2,
        backgroundColor: color
      } : {
        width: 10,
        height: 10,
        borderRadius: 5,
        backgroundColor: color
      }
    };
  }
}
/**
 * @return Never be null/undefined.
 */

function convertToColorString(color, defaultColor) {
  defaultColor = defaultColor || 'transparent';
  return isString(color) ? color : isObject$2(color) ? color.colorStops && (color.colorStops[0] || {}).color || defaultColor : defaultColor;
}
/**
 * open new tab
 * @param link url
 * @param target blank or self
 */

function windowOpen(link, target) {
  /* global window */
  if (target === '_blank' || target === 'blank') {
    var blank = window.open();
    blank.opener = null;
    blank.location.href = link;
  } else {
    window.open(link, target);
  }
}
/* Injected with object hook! */

var each$3 = each$4;
/**
 * @public
 */

var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height'];
/**
 * @public
 */

var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']];

function boxLayout(orient, group, gap, maxWidth, maxHeight) {
  var x = 0;
  var y = 0;

  if (maxWidth == null) {
    maxWidth = Infinity;
  }

  if (maxHeight == null) {
    maxHeight = Infinity;
  }

  var currentLineMaxSize = 0;
  group.eachChild(function (child, idx) {
    var rect = child.getBoundingRect();
    var nextChild = group.childAt(idx + 1);
    var nextChildRect = nextChild && nextChild.getBoundingRect();
    var nextX;
    var nextY;

    if (orient === 'horizontal') {
      var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0);
      nextX = x + moveX; // Wrap when width exceeds maxWidth or meet a `newline` group
      // FIXME compare before adding gap?

      if (nextX > maxWidth || child.newline) {
        x = 0;
        nextX = moveX;
        y += currentLineMaxSize + gap;
        currentLineMaxSize = rect.height;
      } else {
        // FIXME: consider rect.y is not `0`?
        currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
      }
    } else {
      var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0);
      nextY = y + moveY; // Wrap when width exceeds maxHeight or meet a `newline` group

      if (nextY > maxHeight || child.newline) {
        x += currentLineMaxSize + gap;
        y = 0;
        nextY = moveY;
        currentLineMaxSize = rect.width;
      } else {
        currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
      }
    }

    if (child.newline) {
      return;
    }

    child.x = x;
    child.y = y;
    child.markRedraw();
    orient === 'horizontal' ? x = nextX + gap : y = nextY + gap;
  });
}
/**
 * VBox or HBox layouting
 * @param {string} orient
 * @param {module:zrender/graphic/Group} group
 * @param {number} gap
 * @param {number} [width=Infinity]
 * @param {number} [height=Infinity]
 */


var box = boxLayout;
/**
 * VBox layouting
 * @param {module:zrender/graphic/Group} group
 * @param {number} gap
 * @param {number} [width=Infinity]
 * @param {number} [height=Infinity]
 */

curry$1(boxLayout, 'vertical');
/**
 * HBox layouting
 * @param {module:zrender/graphic/Group} group
 * @param {number} gap
 * @param {number} [width=Infinity]
 * @param {number} [height=Infinity]
 */

curry$1(boxLayout, 'horizontal');
/**
 * Parse position info.
 */

function getLayoutRect(positionInfo, containerRect, margin) {
  margin = normalizeCssArray(margin || 0);
  var containerWidth = containerRect.width;
  var containerHeight = containerRect.height;
  var left = parsePercent(positionInfo.left, containerWidth);
  var top = parsePercent(positionInfo.top, containerHeight);
  var right = parsePercent(positionInfo.right, containerWidth);
  var bottom = parsePercent(positionInfo.bottom, containerHeight);
  var width = parsePercent(positionInfo.width, containerWidth);
  var height = parsePercent(positionInfo.height, containerHeight);
  var verticalMargin = margin[2] + margin[0];
  var horizontalMargin = margin[1] + margin[3];
  var aspect = positionInfo.aspect; // If width is not specified, calculate width from left and right

  if (isNaN(width)) {
    width = containerWidth - right - horizontalMargin - left;
  }

  if (isNaN(height)) {
    height = containerHeight - bottom - verticalMargin - top;
  }

  if (aspect != null) {
    // If width and height are not given
    // 1. Graph should not exceeds the container
    // 2. Aspect must be keeped
    // 3. Graph should take the space as more as possible
    // FIXME
    // Margin is not considered, because there is no case that both
    // using margin and aspect so far.
    if (isNaN(width) && isNaN(height)) {
      if (aspect > containerWidth / containerHeight) {
        width = containerWidth * 0.8;
      } else {
        height = containerHeight * 0.8;
      }
    } // Calculate width or height with given aspect


    if (isNaN(width)) {
      width = aspect * height;
    }

    if (isNaN(height)) {
      height = width / aspect;
    }
  } // If left is not specified, calculate left from right and width


  if (isNaN(left)) {
    left = containerWidth - right - width - horizontalMargin;
  }

  if (isNaN(top)) {
    top = containerHeight - bottom - height - verticalMargin;
  } // Align left and top


  switch (positionInfo.left || positionInfo.right) {
    case 'center':
      left = containerWidth / 2 - width / 2 - margin[3];
      break;

    case 'right':
      left = containerWidth - width - horizontalMargin;
      break;
  }

  switch (positionInfo.top || positionInfo.bottom) {
    case 'middle':
    case 'center':
      top = containerHeight / 2 - height / 2 - margin[0];
      break;

    case 'bottom':
      top = containerHeight - height - verticalMargin;
      break;
  } // If something is wrong and left, top, width, height are calculated as NaN


  left = left || 0;
  top = top || 0;

  if (isNaN(width)) {
    // Width may be NaN if only one value is given except width
    width = containerWidth - horizontalMargin - left - (right || 0);
  }

  if (isNaN(height)) {
    // Height may be NaN if only one value is given except height
    height = containerHeight - verticalMargin - top - (bottom || 0);
  }

  var rect = new BoundingRect$1(left + margin[3], top + margin[0], width, height);
  rect.margin = margin;
  return rect;
}
function fetchLayoutMode(ins) {
  var layoutMode = ins.layoutMode || ins.constructor.layoutMode;
  return isObject$2(layoutMode) ? layoutMode : layoutMode ? {
    type: layoutMode
  } : null;
}
/**
 * Consider Case:
 * When default option has {left: 0, width: 100}, and we set {right: 0}
 * through setOption or media query, using normal zrUtil.merge will cause
 * {right: 0} does not take effect.
 *
 * @example
 * ComponentModel.extend({
 *     init: function () {
 *         ...
 *         let inputPositionParams = layout.getLayoutParams(option);
 *         this.mergeOption(inputPositionParams);
 *     },
 *     mergeOption: function (newOption) {
 *         newOption && zrUtil.merge(thisOption, newOption, true);
 *         layout.mergeLayoutParam(thisOption, newOption);
 *     }
 * });
 *
 * @param targetOption
 * @param newOption
 * @param opt
 */

function mergeLayoutParam(targetOption, newOption, opt) {
  var ignoreSize = opt && opt.ignoreSize;
  !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]);
  var hResult = merge(HV_NAMES[0], 0);
  var vResult = merge(HV_NAMES[1], 1);
  copy(HV_NAMES[0], targetOption, hResult);
  copy(HV_NAMES[1], targetOption, vResult);

  function merge(names, hvIdx) {
    var newParams = {};
    var newValueCount = 0;
    var merged = {};
    var mergedValueCount = 0;
    var enoughParamNumber = 2;
    each$3(names, function (name) {
      merged[name] = targetOption[name];
    });
    each$3(names, function (name) {
      // Consider case: newOption.width is null, which is
      // set by user for removing width setting.
      hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
      hasValue(newParams, name) && newValueCount++;
      hasValue(merged, name) && mergedValueCount++;
    });

    if (ignoreSize[hvIdx]) {
      // Only one of left/right is premitted to exist.
      if (hasValue(newOption, names[1])) {
        merged[names[2]] = null;
      } else if (hasValue(newOption, names[2])) {
        merged[names[1]] = null;
      }

      return merged;
    } // Case: newOption: {width: ..., right: ...},
    // or targetOption: {right: ...} and newOption: {width: ...},
    // There is no conflict when merged only has params count
    // little than enoughParamNumber.


    if (mergedValueCount === enoughParamNumber || !newValueCount) {
      return merged;
    } // Case: newOption: {width: ..., right: ...},
    // Than we can make sure user only want those two, and ignore
    // all origin params in targetOption.
    else if (newValueCount >= enoughParamNumber) {
        return newParams;
      } else {
        // Chose another param from targetOption by priority.
        for (var i = 0; i < names.length; i++) {
          var name_1 = names[i];

          if (!hasProp(newParams, name_1) && hasProp(targetOption, name_1)) {
            newParams[name_1] = targetOption[name_1];
            break;
          }
        }

        return newParams;
      }
  }

  function hasProp(obj, name) {
    return obj.hasOwnProperty(name);
  }

  function hasValue(obj, name) {
    return obj[name] != null && obj[name] !== 'auto';
  }

  function copy(names, target, source) {
    each$3(names, function (name) {
      target[name] = source[name];
    });
  }
}
/**
 * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
 */

function getLayoutParams(source) {
  return copyLayoutParams({}, source);
}
/**
 * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
 * @param {Object} source
 * @return {Object} Result contains those props.
 */

function copyLayoutParams(target, source) {
  source && target && each$3(LOCATION_PARAMS, function (name) {
    source.hasOwnProperty(name) && (target[name] = source[name]);
  });
  return target;
}
/* Injected with object hook! */

var inner$9 = makeInner();

var ComponentModel =
/** @class */
function (_super) {
  __extends(ComponentModel, _super);

  function ComponentModel(option, parentModel, ecModel) {
    var _this = _super.call(this, option, parentModel, ecModel) || this;

    _this.uid = getUID('ec_cpt_model');
    return _this;
  }

  ComponentModel.prototype.init = function (option, parentModel, ecModel) {
    this.mergeDefaultAndTheme(option, ecModel);
  };

  ComponentModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
    var layoutMode = fetchLayoutMode(this);
    var inputPositionParams = layoutMode ? getLayoutParams(option) : {};
    var themeModel = ecModel.getTheme();
    merge(option, themeModel.get(this.mainType));
    merge(option, this.getDefaultOption());

    if (layoutMode) {
      mergeLayoutParam(option, inputPositionParams, layoutMode);
    }
  };

  ComponentModel.prototype.mergeOption = function (option, ecModel) {
    merge(this.option, option, true);
    var layoutMode = fetchLayoutMode(this);

    if (layoutMode) {
      mergeLayoutParam(this.option, option, layoutMode);
    }
  };
  /**
   * Called immediately after `init` or `mergeOption` of this instance called.
   */


  ComponentModel.prototype.optionUpdated = function (newCptOption, isInit) {};
  /**
   * [How to declare defaultOption]:
   *
   * (A) If using class declaration in typescript (since echarts 5):
   * ```ts
   * import {ComponentOption} from '../model/option.js';
   * export interface XxxOption extends ComponentOption {
   *     aaa: number
   * }
   * export class XxxModel extends Component {
   *     static type = 'xxx';
   *     static defaultOption: XxxOption = {
   *         aaa: 123
   *     }
   * }
   * Component.registerClass(XxxModel);
   * ```
   * ```ts
   * import {inheritDefaultOption} from '../util/component.js';
   * import {XxxModel, XxxOption} from './XxxModel.js';
   * export interface XxxSubOption extends XxxOption {
   *     bbb: number
   * }
   * class XxxSubModel extends XxxModel {
   *     static defaultOption: XxxSubOption = inheritDefaultOption(XxxModel.defaultOption, {
   *         bbb: 456
   *     })
   *     fn() {
   *         let opt = this.getDefaultOption();
   *         // opt is {aaa: 123, bbb: 456}
   *     }
   * }
   * ```
   *
   * (B) If using class extend (previous approach in echarts 3 & 4):
   * ```js
   * let XxxComponent = Component.extend({
   *     defaultOption: {
   *         xx: 123
   *     }
   * })
   * ```
   * ```js
   * let XxxSubComponent = XxxComponent.extend({
   *     defaultOption: {
   *         yy: 456
   *     },
   *     fn: function () {
   *         let opt = this.getDefaultOption();
   *         // opt is {xx: 123, yy: 456}
   *     }
   * })
   * ```
   */


  ComponentModel.prototype.getDefaultOption = function () {
    var ctor = this.constructor; // If using class declaration, it is different to travel super class
    // in legacy env and auto merge defaultOption. So if using class
    // declaration, defaultOption should be merged manually.

    if (!isExtendedClass(ctor)) {
      // When using ts class, defaultOption must be declared as static.
      return ctor.defaultOption;
    } // FIXME: remove this approach?


    var fields = inner$9(this);

    if (!fields.defaultOption) {
      var optList = [];
      var clz = ctor;

      while (clz) {
        var opt = clz.prototype.defaultOption;
        opt && optList.push(opt);
        clz = clz.superClass;
      }

      var defaultOption = {};

      for (var i = optList.length - 1; i >= 0; i--) {
        defaultOption = merge(defaultOption, optList[i], true);
      }

      fields.defaultOption = defaultOption;
    }

    return fields.defaultOption;
  };
  /**
   * Notice: always force to input param `useDefault` in case that forget to consider it.
   * The same behavior as `modelUtil.parseFinder`.
   *
   * @param useDefault In many cases like series refer axis and axis refer grid,
   *        If axis index / axis id not specified, use the first target as default.
   *        In other cases like dataZoom refer axis, if not specified, measn no refer.
   */


  ComponentModel.prototype.getReferringComponents = function (mainType, opt) {
    var indexKey = mainType + 'Index';
    var idKey = mainType + 'Id';
    return queryReferringComponents(this.ecModel, mainType, {
      index: this.get(indexKey, true),
      id: this.get(idKey, true)
    }, opt);
  };

  ComponentModel.prototype.getBoxLayoutParams = function () {
    // Consider itself having box layout configs.
    var boxLayoutModel = this;
    return {
      left: boxLayoutModel.get('left'),
      top: boxLayoutModel.get('top'),
      right: boxLayoutModel.get('right'),
      bottom: boxLayoutModel.get('bottom'),
      width: boxLayoutModel.get('width'),
      height: boxLayoutModel.get('height')
    };
  };
  /**
   * Get key for zlevel.
   * If developers don't configure zlevel. We will assign zlevel to series based on the key.
   * For example, lines with trail effect and progressive series will in an individual zlevel.
   */


  ComponentModel.prototype.getZLevelKey = function () {
    return '';
  };

  ComponentModel.prototype.setZLevel = function (zlevel) {
    this.option.zlevel = zlevel;
  };

  ComponentModel.protoInitialize = function () {
    var proto = ComponentModel.prototype;
    proto.type = 'component';
    proto.id = '';
    proto.name = '';
    proto.mainType = '';
    proto.subType = '';
    proto.componentIndex = 0;
  }();

  return ComponentModel;
}(Model$1);

mountExtend(ComponentModel, Model$1);
enableClassManagement(ComponentModel);
enableSubTypeDefaulter(ComponentModel);
enableTopologicalTravel(ComponentModel, getDependencies);

function getDependencies(componentType) {
  var deps = [];
  each$4(ComponentModel.getClassesByMainType(componentType), function (clz) {
    deps = deps.concat(clz.dependencies || clz.prototype.dependencies || []);
  }); // Ensure main type.

  deps = map$1(deps, function (type) {
    return parseClassType(type).main;
  }); // Hack dataset for convenience.

  if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) {
    deps.unshift('dataset');
  }

  return deps;
}

const ComponentModel$1 = ComponentModel;
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var platform = ''; // Navigator not exists in node

if (typeof navigator !== 'undefined') {
  /* global navigator */
  platform = navigator.platform || '';
}

var decalColor = 'rgba(0, 0, 0, 0.2)';
const globalDefault = {
  darkMode: 'auto',
  // backgroundColor: 'rgba(0,0,0,0)',
  colorBy: 'series',
  color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
  gradientColor: ['#f6efa6', '#d88273', '#bf444c'],
  aria: {
    decal: {
      decals: [{
        color: decalColor,
        dashArrayX: [1, 0],
        dashArrayY: [2, 5],
        symbolSize: 1,
        rotation: Math.PI / 6
      }, {
        color: decalColor,
        symbol: 'circle',
        dashArrayX: [[8, 8], [0, 8, 8, 0]],
        dashArrayY: [6, 0],
        symbolSize: 0.8
      }, {
        color: decalColor,
        dashArrayX: [1, 0],
        dashArrayY: [4, 3],
        rotation: -Math.PI / 4
      }, {
        color: decalColor,
        dashArrayX: [[6, 6], [0, 6, 6, 0]],
        dashArrayY: [6, 0]
      }, {
        color: decalColor,
        dashArrayX: [[1, 0], [1, 6]],
        dashArrayY: [1, 0, 6, 0],
        rotation: Math.PI / 4
      }, {
        color: decalColor,
        symbol: 'triangle',
        dashArrayX: [[9, 9], [0, 9, 9, 0]],
        dashArrayY: [7, 2],
        symbolSize: 0.75
      }]
    }
  },
  // If xAxis and yAxis declared, grid is created by default.
  // grid: {},
  textStyle: {
    // color: '#000',
    // decoration: 'none',
    // PENDING
    fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif',
    // fontFamily: 'Arial, Verdana, sans-serif',
    fontSize: 12,
    fontStyle: 'normal',
    fontWeight: 'normal'
  },
  // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/
  // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
  // Default is source-over
  blendMode: null,
  stateAnimation: {
    duration: 300,
    easing: 'cubicOut'
  },
  animation: 'auto',
  animationDuration: 1000,
  animationDurationUpdate: 500,
  animationEasing: 'cubicInOut',
  animationEasingUpdate: 'cubicInOut',
  animationThreshold: 2000,
  // Configuration for progressive/incremental rendering
  progressiveThreshold: 3000,
  progressive: 400,
  // Threshold of if use single hover layer to optimize.
  // It is recommended that `hoverLayerThreshold` is equivalent to or less than
  // `progressiveThreshold`, otherwise hover will cause restart of progressive,
  // which is unexpected.
  // see example <echarts/test/heatmap-large.html>.
  hoverLayerThreshold: 3000,
  // See: module:echarts/scale/Time
  useUTC: false
};
/* Injected with object hook! */

var VISUAL_DIMENSIONS = createHashMap(['tooltip', 'label', 'itemName', 'itemId', 'itemGroupId', 'seriesName']);
var SOURCE_FORMAT_ORIGINAL = 'original';
var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows';
var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows';
var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns';
var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray';
var SOURCE_FORMAT_UNKNOWN = 'unknown';
var SERIES_LAYOUT_BY_COLUMN = 'column';
var SERIES_LAYOUT_BY_ROW = 'row';
/* Injected with object hook! */

var BE_ORDINAL = {
  Must: 1,
  Might: 2,
  Not: 3 // Other cases

};
var innerGlobalModel = makeInner();
/**
 * MUST be called before mergeOption of all series.
 */

function resetSourceDefaulter(ecModel) {
  // `datasetMap` is used to make default encode.
  innerGlobalModel(ecModel).datasetMap = createHashMap();
}
/**
 * [The strategy of the arrengment of data dimensions for dataset]:
 * "value way": all axes are non-category axes. So series one by one take
 *     several (the number is coordSysDims.length) dimensions from dataset.
 *     The result of data arrengment of data dimensions like:
 *     | ser0_x | ser0_y | ser1_x | ser1_y | ser2_x | ser2_y |
 * "category way": at least one axis is category axis. So the the first data
 *     dimension is always mapped to the first category axis and shared by
 *     all of the series. The other data dimensions are taken by series like
 *     "value way" does.
 *     The result of data arrengment of data dimensions like:
 *     | ser_shared_x | ser0_y | ser1_y | ser2_y |
 *
 * @return encode Never be `null/undefined`.
 */

function makeSeriesEncodeForAxisCoordSys(coordDimensions, seriesModel, source) {
  var encode = {};
  var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); // Currently only make default when using dataset, util more reqirements occur.

  if (!datasetModel || !coordDimensions) {
    return encode;
  }

  var encodeItemName = [];
  var encodeSeriesName = [];
  var ecModel = seriesModel.ecModel;
  var datasetMap = innerGlobalModel(ecModel).datasetMap;
  var key = datasetModel.uid + '_' + source.seriesLayoutBy;
  var baseCategoryDimIndex;
  var categoryWayValueDimStart;
  coordDimensions = coordDimensions.slice();
  each$4(coordDimensions, function (coordDimInfoLoose, coordDimIdx) {
    var coordDimInfo = isObject$2(coordDimInfoLoose) ? coordDimInfoLoose : coordDimensions[coordDimIdx] = {
      name: coordDimInfoLoose
    };

    if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) {
      baseCategoryDimIndex = coordDimIdx;
      categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimInfo);
    }

    encode[coordDimInfo.name] = [];
  });
  var datasetRecord = datasetMap.get(key) || datasetMap.set(key, {
    categoryWayDim: categoryWayValueDimStart,
    valueWayDim: 0
  }); // TODO
  // Auto detect first time axis and do arrangement.

  each$4(coordDimensions, function (coordDimInfo, coordDimIdx) {
    var coordDimName = coordDimInfo.name;
    var count = getDataDimCountOnCoordDim(coordDimInfo); // In value way.

    if (baseCategoryDimIndex == null) {
      var start = datasetRecord.valueWayDim;
      pushDim(encode[coordDimName], start, count);
      pushDim(encodeSeriesName, start, count);
      datasetRecord.valueWayDim += count; // ??? TODO give a better default series name rule?
      // especially when encode x y specified.
      // consider: when multiple series share one dimension
      // category axis, series name should better use
      // the other dimension name. On the other hand, use
      // both dimensions name.
    } // In category way, the first category axis.
    else if (baseCategoryDimIndex === coordDimIdx) {
        pushDim(encode[coordDimName], 0, count);
        pushDim(encodeItemName, 0, count);
      } // In category way, the other axis.
      else {
          var start = datasetRecord.categoryWayDim;
          pushDim(encode[coordDimName], start, count);
          pushDim(encodeSeriesName, start, count);
          datasetRecord.categoryWayDim += count;
        }
  });

  function pushDim(dimIdxArr, idxFrom, idxCount) {
    for (var i = 0; i < idxCount; i++) {
      dimIdxArr.push(idxFrom + i);
    }
  }

  function getDataDimCountOnCoordDim(coordDimInfo) {
    var dimsDef = coordDimInfo.dimsDef;
    return dimsDef ? dimsDef.length : 1;
  }

  encodeItemName.length && (encode.itemName = encodeItemName);
  encodeSeriesName.length && (encode.seriesName = encodeSeriesName);
  return encode;
}
/**
 * @return If return null/undefined, indicate that should not use datasetModel.
 */

function querySeriesUpstreamDatasetModel(seriesModel) {
  // Caution: consider the scenario:
  // A dataset is declared and a series is not expected to use the dataset,
  // and at the beginning `setOption({series: { noData })` (just prepare other
  // option but no data), then `setOption({series: {data: [...]}); In this case,
  // the user should set an empty array to avoid that dataset is used by default.
  var thisData = seriesModel.get('data', true);

  if (!thisData) {
    return queryReferringComponents(seriesModel.ecModel, 'dataset', {
      index: seriesModel.get('datasetIndex', true),
      id: seriesModel.get('datasetId', true)
    }, SINGLE_REFERRING).models[0];
  }
}
/**
 * @return Always return an array event empty.
 */

function queryDatasetUpstreamDatasetModels(datasetModel) {
  // Only these attributes declared, we by defualt reference to `datasetIndex: 0`.
  // Otherwise, no reference.
  if (!datasetModel.get('transform', true) && !datasetModel.get('fromTransformResult', true)) {
    return [];
  }

  return queryReferringComponents(datasetModel.ecModel, 'dataset', {
    index: datasetModel.get('fromDatasetIndex', true),
    id: datasetModel.get('fromDatasetId', true)
  }, SINGLE_REFERRING).models;
}
/**
 * The rule should not be complex, otherwise user might not
 * be able to known where the data is wrong.
 * The code is ugly, but how to make it neat?
 */

function guessOrdinal(source, dimIndex) {
  return doGuessOrdinal(source.data, source.sourceFormat, source.seriesLayoutBy, source.dimensionsDefine, source.startIndex, dimIndex);
} // dimIndex may be overflow source data.
// return {BE_ORDINAL}

function doGuessOrdinal(data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex) {
  var result; // Experience value.

  var maxLoop = 5;

  if (isTypedArray(data)) {
    return BE_ORDINAL.Not;
  } // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine
  // always exists in source.


  var dimName;
  var dimType;

  if (dimensionsDefine) {
    var dimDefItem = dimensionsDefine[dimIndex];

    if (isObject$2(dimDefItem)) {
      dimName = dimDefItem.name;
      dimType = dimDefItem.type;
    } else if (isString(dimDefItem)) {
      dimName = dimDefItem;
    }
  }

  if (dimType != null) {
    return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not;
  }

  if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
    var dataArrayRows = data;

    if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
      var sample = dataArrayRows[dimIndex];

      for (var i = 0; i < (sample || []).length && i < maxLoop; i++) {
        if ((result = detectValue(sample[startIndex + i])) != null) {
          return result;
        }
      }
    } else {
      for (var i = 0; i < dataArrayRows.length && i < maxLoop; i++) {
        var row = dataArrayRows[startIndex + i];

        if (row && (result = detectValue(row[dimIndex])) != null) {
          return result;
        }
      }
    }
  } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
    var dataObjectRows = data;

    if (!dimName) {
      return BE_ORDINAL.Not;
    }

    for (var i = 0; i < dataObjectRows.length && i < maxLoop; i++) {
      var item = dataObjectRows[i];

      if (item && (result = detectValue(item[dimName])) != null) {
        return result;
      }
    }
  } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
    var dataKeyedColumns = data;

    if (!dimName) {
      return BE_ORDINAL.Not;
    }

    var sample = dataKeyedColumns[dimName];

    if (!sample || isTypedArray(sample)) {
      return BE_ORDINAL.Not;
    }

    for (var i = 0; i < sample.length && i < maxLoop; i++) {
      if ((result = detectValue(sample[i])) != null) {
        return result;
      }
    }
  } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
    var dataOriginal = data;

    for (var i = 0; i < dataOriginal.length && i < maxLoop; i++) {
      var item = dataOriginal[i];
      var val = getDataItemValue(item);

      if (!isArray(val)) {
        return BE_ORDINAL.Not;
      }

      if ((result = detectValue(val[dimIndex])) != null) {
        return result;
      }
    }
  }

  function detectValue(val) {
    var beStr = isString(val); // Consider usage convenience, '1', '2' will be treated as "number".
    // `isFinit('')` get `true`.

    if (val != null && isFinite(val) && val !== '') {
      return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not;
    } else if (beStr && val !== '-') {
      return BE_ORDINAL.Must;
    }
  }

  return BE_ORDINAL.Not;
}
/* Injected with object hook! */

var internalOptionCreatorMap = createHashMap();
function concatInternalOptions(ecModel, mainType, newCmptOptionList) {
  var internalOptionCreator = internalOptionCreatorMap.get(mainType);

  if (!internalOptionCreator) {
    return newCmptOptionList;
  }

  var internalOptions = internalOptionCreator(ecModel);

  if (!internalOptions) {
    return newCmptOptionList;
  }

  return newCmptOptionList.concat(internalOptions);
}
/* Injected with object hook! */

var innerColor = makeInner();
makeInner();

var PaletteMixin =
/** @class */
function () {
  function PaletteMixin() {}

  PaletteMixin.prototype.getColorFromPalette = function (name, scope, requestNum) {
    var defaultPalette = normalizeToArray(this.get('color', true));
    var layeredPalette = this.get('colorLayer', true);
    return getFromPalette(this, innerColor, defaultPalette, layeredPalette, name, scope, requestNum);
  };

  PaletteMixin.prototype.clearColorPalette = function () {
    clearPalette(this, innerColor);
  };

  return PaletteMixin;
}();

function getNearestPalette(palettes, requestColorNum) {
  var paletteNum = palettes.length; // TODO palettes must be in order

  for (var i = 0; i < paletteNum; i++) {
    if (palettes[i].length > requestColorNum) {
      return palettes[i];
    }
  }

  return palettes[paletteNum - 1];
}
/**
 * @param name MUST NOT be null/undefined. Otherwise call this function
 *             twise with the same parameters will get different result.
 * @param scope default this.
 * @return Can be null/undefined
 */


function getFromPalette(that, inner, defaultPalette, layeredPalette, name, scope, requestNum) {
  scope = scope || that;
  var scopeFields = inner(scope);
  var paletteIdx = scopeFields.paletteIdx || 0;
  var paletteNameMap = scopeFields.paletteNameMap = scopeFields.paletteNameMap || {}; // Use `hasOwnProperty` to avoid conflict with Object.prototype.

  if (paletteNameMap.hasOwnProperty(name)) {
    return paletteNameMap[name];
  }

  var palette = requestNum == null || !layeredPalette ? defaultPalette : getNearestPalette(layeredPalette, requestNum); // In case can't find in layered color palette.

  palette = palette || defaultPalette;

  if (!palette || !palette.length) {
    return;
  }

  var pickedPaletteItem = palette[paletteIdx];

  if (name) {
    paletteNameMap[name] = pickedPaletteItem;
  }

  scopeFields.paletteIdx = (paletteIdx + 1) % palette.length;
  return pickedPaletteItem;
}

function clearPalette(that, inner) {
  inner(that).paletteIdx = 0;
  inner(that).paletteNameMap = {};
}
/* Injected with object hook! */

// Internal method names:
// -----------------------

var reCreateSeriesIndices;
var assertSeriesInitialized;
var initBase;
var OPTION_INNER_KEY = '\0_ec_inner';
var OPTION_INNER_VALUE = 1;

var GlobalModel =
/** @class */
function (_super) {
  __extends(GlobalModel, _super);

  function GlobalModel() {
    return _super !== null && _super.apply(this, arguments) || this;
  }

  GlobalModel.prototype.init = function (option, parentModel, ecModel, theme, locale, optionManager) {
    theme = theme || {};
    this.option = null; // Mark as not initialized.

    this._theme = new Model$1(theme);
    this._locale = new Model$1(locale);
    this._optionManager = optionManager;
  };

  GlobalModel.prototype.setOption = function (option, opts, optionPreprocessorFuncs) {

    var innerOpt = normalizeSetOptionInput(opts);

    this._optionManager.setOption(option, optionPreprocessorFuncs, innerOpt);

    this._resetOption(null, innerOpt);
  };
  /**
   * @param type null/undefined: reset all.
   *        'recreate': force recreate all.
   *        'timeline': only reset timeline option
   *        'media': only reset media query option
   * @return Whether option changed.
   */


  GlobalModel.prototype.resetOption = function (type, opt) {
    return this._resetOption(type, normalizeSetOptionInput(opt));
  };

  GlobalModel.prototype._resetOption = function (type, opt) {
    var optionChanged = false;
    var optionManager = this._optionManager;

    if (!type || type === 'recreate') {
      var baseOption = optionManager.mountOption(type === 'recreate');

      if (!this.option || type === 'recreate') {
        initBase(this, baseOption);
      } else {
        this.restoreData();

        this._mergeOption(baseOption, opt);
      }

      optionChanged = true;
    }

    if (type === 'timeline' || type === 'media') {
      this.restoreData();
    } // By design, if `setOption(option2)` at the second time, and `option2` is a `ECUnitOption`,
    // it should better not have the same props with `MediaUnit['option']`.
    // Because either `option2` or `MediaUnit['option']` will be always merged to "current option"
    // rather than original "baseOption". If they both override a prop, the result might be
    // unexpected when media state changed after `setOption` called.
    // If we really need to modify a props in each `MediaUnit['option']`, use the full version
    // (`{baseOption, media}`) in `setOption`.
    // For `timeline`, the case is the same.


    if (!type || type === 'recreate' || type === 'timeline') {
      var timelineOption = optionManager.getTimelineOption(this);

      if (timelineOption) {
        optionChanged = true;

        this._mergeOption(timelineOption, opt);
      }
    }

    if (!type || type === 'recreate' || type === 'media') {
      var mediaOptions = optionManager.getMediaOption(this);

      if (mediaOptions.length) {
        each$4(mediaOptions, function (mediaOption) {
          optionChanged = true;

          this._mergeOption(mediaOption, opt);
        }, this);
      }
    }

    return optionChanged;
  };

  GlobalModel.prototype.mergeOption = function (option) {
    this._mergeOption(option, null);
  };

  GlobalModel.prototype._mergeOption = function (newOption, opt) {
    var option = this.option;
    var componentsMap = this._componentsMap;
    var componentsCount = this._componentsCount;
    var newCmptTypes = [];
    var newCmptTypeMap = createHashMap();
    var replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap;
    resetSourceDefaulter(this); // If no component class, merge directly.
    // For example: color, animaiton options, etc.

    each$4(newOption, function (componentOption, mainType) {
      if (componentOption == null) {
        return;
      }

      if (!ComponentModel$1.hasClass(mainType)) {
        // globalSettingTask.dirty();
        option[mainType] = option[mainType] == null ? clone$2(componentOption) : merge(option[mainType], componentOption, true);
      } else if (mainType) {
        newCmptTypes.push(mainType);
        newCmptTypeMap.set(mainType, true);
      }
    });

    if (replaceMergeMainTypeMap) {
      // If there is a mainType `xxx` in `replaceMerge` but not declared in option,
      // we trade it as it is declared in option as `{xxx: []}`. Because:
      // (1) for normal merge, `{xxx: null/undefined}` are the same meaning as `{xxx: []}`.
      // (2) some preprocessor may convert some of `{xxx: null/undefined}` to `{xxx: []}`.
      replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) {
        if (ComponentModel$1.hasClass(mainTypeInReplaceMerge) && !newCmptTypeMap.get(mainTypeInReplaceMerge)) {
          newCmptTypes.push(mainTypeInReplaceMerge);
          newCmptTypeMap.set(mainTypeInReplaceMerge, true);
        }
      });
    }

    ComponentModel$1.topologicalTravel(newCmptTypes, ComponentModel$1.getAllClassMainTypes(), visitComponent, this);

    function visitComponent(mainType) {
      var newCmptOptionList = concatInternalOptions(this, mainType, normalizeToArray(newOption[mainType]));
      var oldCmptList = componentsMap.get(mainType);
      var mergeMode = // `!oldCmptList` means init. See the comment in `mappingToExists`
      !oldCmptList ? 'replaceAll' : replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType) ? 'replaceMerge' : 'normalMerge';
      var mappingResult = mappingToExists(oldCmptList, newCmptOptionList, mergeMode); // Set mainType and complete subType.

      setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel$1); // Empty it before the travel, in order to prevent `this._componentsMap`
      // from being used in the `init`/`mergeOption`/`optionUpdated` of some
      // components, which is probably incorrect logic.

      option[mainType] = null;
      componentsMap.set(mainType, null);
      componentsCount.set(mainType, 0);
      var optionsByMainType = [];
      var cmptsByMainType = [];
      var cmptsCountByMainType = 0;
      var tooltipExists;
      each$4(mappingResult, function (resultItem, index) {
        var componentModel = resultItem.existing;
        var newCmptOption = resultItem.newOption;

        if (!newCmptOption) {
          if (componentModel) {
            // Consider where is no new option and should be merged using {},
            // see removeEdgeAndAdd in topologicalTravel and
            // ComponentModel.getAllClassMainTypes.
            componentModel.mergeOption({}, this);
            componentModel.optionUpdated({}, false);
          } // If no both `resultItem.exist` and `resultItem.option`,
          // either it is in `replaceMerge` and not matched by any id,
          // or it has been removed in previous `replaceMerge` and left a "hole" in this component index.

        } else {
          var isSeriesType = mainType === 'series';
          var ComponentModelClass = ComponentModel$1.getClass(mainType, resultItem.keyInfo.subType, !isSeriesType // Give a more detailed warn later if series don't exists
          );

          if (!ComponentModelClass) {

            return;
          } // TODO Before multiple tooltips get supported, we do this check to avoid unexpected exception.


          if (mainType === 'tooltip') {
            if (tooltipExists) {

              return;
            }

            tooltipExists = true;
          }

          if (componentModel && componentModel.constructor === ComponentModelClass) {
            componentModel.name = resultItem.keyInfo.name; // componentModel.settingTask && componentModel.settingTask.dirty();

            componentModel.mergeOption(newCmptOption, this);
            componentModel.optionUpdated(newCmptOption, false);
          } else {
            // PENDING Global as parent ?
            var extraOpt = extend({
              componentIndex: index
            }, resultItem.keyInfo);
            componentModel = new ComponentModelClass(newCmptOption, this, this, extraOpt); // Assign `keyInfo`

            extend(componentModel, extraOpt);

            if (resultItem.brandNew) {
              componentModel.__requireNewView = true;
            }

            componentModel.init(newCmptOption, this, this); // Call optionUpdated after init.
            // newCmptOption has been used as componentModel.option
            // and may be merged with theme and default, so pass null
            // to avoid confusion.

            componentModel.optionUpdated(null, true);
          }
        }

        if (componentModel) {
          optionsByMainType.push(componentModel.option);
          cmptsByMainType.push(componentModel);
          cmptsCountByMainType++;
        } else {
          // Always do assign to avoid elided item in array.
          optionsByMainType.push(void 0);
          cmptsByMainType.push(void 0);
        }
      }, this);
      option[mainType] = optionsByMainType;
      componentsMap.set(mainType, cmptsByMainType);
      componentsCount.set(mainType, cmptsCountByMainType); // Backup series for filtering.

      if (mainType === 'series') {
        reCreateSeriesIndices(this);
      }
    } // If no series declared, ensure `_seriesIndices` initialized.


    if (!this._seriesIndices) {
      reCreateSeriesIndices(this);
    }
  };
  /**
   * Get option for output (cloned option and inner info removed)
   */


  GlobalModel.prototype.getOption = function () {
    var option = clone$2(this.option);
    each$4(option, function (optInMainType, mainType) {
      if (ComponentModel$1.hasClass(mainType)) {
        var opts = normalizeToArray(optInMainType); // Inner cmpts need to be removed.
        // Inner cmpts might not be at last since ec5.0, but still
        // compatible for users: if inner cmpt at last, splice the returned array.

        var realLen = opts.length;
        var metNonInner = false;

        for (var i = realLen - 1; i >= 0; i--) {
          // Remove options with inner id.
          if (opts[i] && !isComponentIdInternal(opts[i])) {
            metNonInner = true;
          } else {
            opts[i] = null;
            !metNonInner && realLen--;
          }
        }

        opts.length = realLen;
        option[mainType] = opts;
      }
    });
    delete option[OPTION_INNER_KEY];
    return option;
  };

  GlobalModel.prototype.getTheme = function () {
    return this._theme;
  };

  GlobalModel.prototype.getLocaleModel = function () {
    return this._locale;
  };

  GlobalModel.prototype.setUpdatePayload = function (payload) {
    this._payload = payload;
  };

  GlobalModel.prototype.getUpdatePayload = function () {
    return this._payload;
  };
  /**
   * @param idx If not specified, return the first one.
   */


  GlobalModel.prototype.getComponent = function (mainType, idx) {
    var list = this._componentsMap.get(mainType);

    if (list) {
      var cmpt = list[idx || 0];

      if (cmpt) {
        return cmpt;
      } else if (idx == null) {
        for (var i = 0; i < list.length; i++) {
          if (list[i]) {
            return list[i];
          }
        }
      }
    }
  };
  /**
   * @return Never be null/undefined.
   */


  GlobalModel.prototype.queryComponents = function (condition) {
    var mainType = condition.mainType;

    if (!mainType) {
      return [];
    }

    var index = condition.index;
    var id = condition.id;
    var name = condition.name;

    var cmpts = this._componentsMap.get(mainType);

    if (!cmpts || !cmpts.length) {
      return [];
    }

    var result;

    if (index != null) {
      result = [];
      each$4(normalizeToArray(index), function (idx) {
        cmpts[idx] && result.push(cmpts[idx]);
      });
    } else if (id != null) {
      result = queryByIdOrName('id', id, cmpts);
    } else if (name != null) {
      result = queryByIdOrName('name', name, cmpts);
    } else {
      // Return all non-empty components in that mainType
      result = filter(cmpts, function (cmpt) {
        return !!cmpt;
      });
    }

    return filterBySubType(result, condition);
  };
  /**
   * The interface is different from queryComponents,
   * which is convenient for inner usage.
   *
   * @usage
   * let result = findComponents(
   *     {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}
   * );
   * let result = findComponents(
   *     {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}
   * );
   * let result = findComponents(
   *     {mainType: 'series',
   *     filter: function (model, index) {...}}
   * );
   * // result like [component0, componnet1, ...]
   */


  GlobalModel.prototype.findComponents = function (condition) {
    var query = condition.query;
    var mainType = condition.mainType;
    var queryCond = getQueryCond(query);
    var result = queryCond ? this.queryComponents(queryCond) // Retrieve all non-empty components.
    : filter(this._componentsMap.get(mainType), function (cmpt) {
      return !!cmpt;
    });
    return doFilter(filterBySubType(result, condition));

    function getQueryCond(q) {
      var indexAttr = mainType + 'Index';
      var idAttr = mainType + 'Id';
      var nameAttr = mainType + 'Name';
      return q && (q[indexAttr] != null || q[idAttr] != null || q[nameAttr] != null) ? {
        mainType: mainType,
        // subType will be filtered finally.
        index: q[indexAttr],
        id: q[idAttr],
        name: q[nameAttr]
      } : null;
    }

    function doFilter(res) {
      return condition.filter ? filter(res, condition.filter) : res;
    }
  };

  GlobalModel.prototype.eachComponent = function (mainType, cb, context) {
    var componentsMap = this._componentsMap;

    if (isFunction(mainType)) {
      var ctxForAll_1 = cb;
      var cbForAll_1 = mainType;
      componentsMap.each(function (cmpts, componentType) {
        for (var i = 0; cmpts && i < cmpts.length; i++) {
          var cmpt = cmpts[i];
          cmpt && cbForAll_1.call(ctxForAll_1, componentType, cmpt, cmpt.componentIndex);
        }
      });
    } else {
      var cmpts = isString(mainType) ? componentsMap.get(mainType) : isObject$2(mainType) ? this.findComponents(mainType) : null;

      for (var i = 0; cmpts && i < cmpts.length; i++) {
        var cmpt = cmpts[i];
        cmpt && cb.call(context, cmpt, cmpt.componentIndex);
      }
    }
  };
  /**
   * Get series list before filtered by name.
   */


  GlobalModel.prototype.getSeriesByName = function (name) {
    var nameStr = convertOptionIdName(name, null);
    return filter(this._componentsMap.get('series'), function (oneSeries) {
      return !!oneSeries && nameStr != null && oneSeries.name === nameStr;
    });
  };
  /**
   * Get series list before filtered by index.
   */


  GlobalModel.prototype.getSeriesByIndex = function (seriesIndex) {
    return this._componentsMap.get('series')[seriesIndex];
  };
  /**
   * Get series list before filtered by type.
   * FIXME: rename to getRawSeriesByType?
   */


  GlobalModel.prototype.getSeriesByType = function (subType) {
    return filter(this._componentsMap.get('series'), function (oneSeries) {
      return !!oneSeries && oneSeries.subType === subType;
    });
  };
  /**
   * Get all series before filtered.
   */


  GlobalModel.prototype.getSeries = function () {
    return filter(this._componentsMap.get('series'), function (oneSeries) {
      return !!oneSeries;
    });
  };
  /**
   * Count series before filtered.
   */


  GlobalModel.prototype.getSeriesCount = function () {
    return this._componentsCount.get('series');
  };
  /**
   * After filtering, series may be different
   * from raw series.
   */


  GlobalModel.prototype.eachSeries = function (cb, context) {
    assertSeriesInitialized(this);
    each$4(this._seriesIndices, function (rawSeriesIndex) {
      var series = this._componentsMap.get('series')[rawSeriesIndex];

      cb.call(context, series, rawSeriesIndex);
    }, this);
  };
  /**
   * Iterate raw series before filtered.
   *
   * @param {Function} cb
   * @param {*} context
   */


  GlobalModel.prototype.eachRawSeries = function (cb, context) {
    each$4(this._componentsMap.get('series'), function (series) {
      series && cb.call(context, series, series.componentIndex);
    });
  };
  /**
   * After filtering, series may be different.
   * from raw series.
   */


  GlobalModel.prototype.eachSeriesByType = function (subType, cb, context) {
    assertSeriesInitialized(this);
    each$4(this._seriesIndices, function (rawSeriesIndex) {
      var series = this._componentsMap.get('series')[rawSeriesIndex];

      if (series.subType === subType) {
        cb.call(context, series, rawSeriesIndex);
      }
    }, this);
  };
  /**
   * Iterate raw series before filtered of given type.
   */


  GlobalModel.prototype.eachRawSeriesByType = function (subType, cb, context) {
    return each$4(this.getSeriesByType(subType), cb, context);
  };

  GlobalModel.prototype.isSeriesFiltered = function (seriesModel) {
    assertSeriesInitialized(this);
    return this._seriesIndicesMap.get(seriesModel.componentIndex) == null;
  };

  GlobalModel.prototype.getCurrentSeriesIndices = function () {
    return (this._seriesIndices || []).slice();
  };

  GlobalModel.prototype.filterSeries = function (cb, context) {
    assertSeriesInitialized(this);
    var newSeriesIndices = [];
    each$4(this._seriesIndices, function (seriesRawIdx) {
      var series = this._componentsMap.get('series')[seriesRawIdx];

      cb.call(context, series, seriesRawIdx) && newSeriesIndices.push(seriesRawIdx);
    }, this);
    this._seriesIndices = newSeriesIndices;
    this._seriesIndicesMap = createHashMap(newSeriesIndices);
  };

  GlobalModel.prototype.restoreData = function (payload) {
    reCreateSeriesIndices(this);
    var componentsMap = this._componentsMap;
    var componentTypes = [];
    componentsMap.each(function (components, componentType) {
      if (ComponentModel$1.hasClass(componentType)) {
        componentTypes.push(componentType);
      }
    });
    ComponentModel$1.topologicalTravel(componentTypes, ComponentModel$1.getAllClassMainTypes(), function (componentType) {
      each$4(componentsMap.get(componentType), function (component) {
        if (component && (componentType !== 'series' || !isNotTargetSeries(component, payload))) {
          component.restoreData();
        }
      });
    });
  };

  GlobalModel.internalField = function () {
    reCreateSeriesIndices = function (ecModel) {
      var seriesIndices = ecModel._seriesIndices = [];
      each$4(ecModel._componentsMap.get('series'), function (series) {
        // series may have been removed by `replaceMerge`.
        series && seriesIndices.push(series.componentIndex);
      });
      ecModel._seriesIndicesMap = createHashMap(seriesIndices);
    };

    assertSeriesInitialized = function (ecModel) {
    };

    initBase = function (ecModel, baseOption) {
      // Using OPTION_INNER_KEY to mark that this option cannot be used outside,
      // i.e. `chart.setOption(chart.getModel().option);` is forbidden.
      ecModel.option = {};
      ecModel.option[OPTION_INNER_KEY] = OPTION_INNER_VALUE; // Init with series: [], in case of calling findSeries method
      // before series initialized.

      ecModel._componentsMap = createHashMap({
        series: []
      });
      ecModel._componentsCount = createHashMap(); // If user spefied `option.aria`, aria will be enable. This detection should be
      // performed before theme and globalDefault merge.

      var airaOption = baseOption.aria;

      if (isObject$2(airaOption) && airaOption.enabled == null) {
        airaOption.enabled = true;
      }

      mergeTheme(baseOption, ecModel._theme.option); // TODO Needs clone when merging to the unexisted property

      merge(baseOption, globalDefault, false);

      ecModel._mergeOption(baseOption, null);
    };
  }();

  return GlobalModel;
}(Model$1);

function isNotTargetSeries(seriesModel, payload) {
  if (payload) {
    var index = payload.seriesIndex;
    var id = payload.seriesId;
    var name_1 = payload.seriesName;
    return index != null && seriesModel.componentIndex !== index || id != null && seriesModel.id !== id || name_1 != null && seriesModel.name !== name_1;
  }
}

function mergeTheme(option, theme) {
  // PENDING
  // NOT use `colorLayer` in theme if option has `color`
  var notMergeColorLayer = option.color && !option.colorLayer;
  each$4(theme, function (themeItem, name) {
    if (name === 'colorLayer' && notMergeColorLayer) {
      return;
    } // If it is component model mainType, the model handles that merge later.
    // otherwise, merge them here.


    if (!ComponentModel$1.hasClass(name)) {
      if (typeof themeItem === 'object') {
        option[name] = !option[name] ? clone$2(themeItem) : merge(option[name], themeItem, false);
      } else {
        if (option[name] == null) {
          option[name] = themeItem;
        }
      }
    }
  });
}

function queryByIdOrName(attr, idOrName, cmpts) {
  // Here is a break from echarts4: string and number are
  // treated as equal.
  if (isArray(idOrName)) {
    var keyMap_1 = createHashMap();
    each$4(idOrName, function (idOrNameItem) {
      if (idOrNameItem != null) {
        var idName = convertOptionIdName(idOrNameItem, null);
        idName != null && keyMap_1.set(idOrNameItem, true);
      }
    });
    return filter(cmpts, function (cmpt) {
      return cmpt && keyMap_1.get(cmpt[attr]);
    });
  } else {
    var idName_1 = convertOptionIdName(idOrName, null);
    return filter(cmpts, function (cmpt) {
      return cmpt && idName_1 != null && cmpt[attr] === idName_1;
    });
  }
}

function filterBySubType(components, condition) {
  // Using hasOwnProperty for restrict. Consider
  // subType is undefined in user payload.
  return condition.hasOwnProperty('subType') ? filter(components, function (cmpt) {
    return cmpt && cmpt.subType === condition.subType;
  }) : components;
}

function normalizeSetOptionInput(opts) {
  var replaceMergeMainTypeMap = createHashMap();
  opts && each$4(normalizeToArray(opts.replaceMerge), function (mainType) {

    replaceMergeMainTypeMap.set(mainType, true);
  });
  return {
    replaceMergeMainTypeMap: replaceMergeMainTypeMap
  };
}

mixin(GlobalModel, PaletteMixin);
const GlobalModel$1 = GlobalModel;
/* Injected with object hook! */

var availableMethods = ['getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isSSR', 'isDisposed', 'on', 'off', 'getDataURL', 'getConnectedDataURL', // 'getModel',
'getOption', // 'getViewOfComponentModel',
// 'getViewOfSeriesModel',
'getId', 'updateLabelLayout'];

var ExtensionAPI =
/** @class */
function () {
  function ExtensionAPI(ecInstance) {
    each$4(availableMethods, function (methodName) {
      this[methodName] = bind$1(ecInstance[methodName], ecInstance);
    }, this);
  }

  return ExtensionAPI;
}();

const ExtensionAPI$1 = ExtensionAPI;
/* Injected with object hook! */

var coordinateSystemCreators = {};

var CoordinateSystemManager =
/** @class */
function () {
  function CoordinateSystemManager() {
    this._coordinateSystems = [];
  }

  CoordinateSystemManager.prototype.create = function (ecModel, api) {
    var coordinateSystems = [];
    each$4(coordinateSystemCreators, function (creator, type) {
      var list = creator.create(ecModel, api);
      coordinateSystems = coordinateSystems.concat(list || []);
    });
    this._coordinateSystems = coordinateSystems;
  };

  CoordinateSystemManager.prototype.update = function (ecModel, api) {
    each$4(this._coordinateSystems, function (coordSys) {
      coordSys.update && coordSys.update(ecModel, api);
    });
  };

  CoordinateSystemManager.prototype.getCoordinateSystems = function () {
    return this._coordinateSystems.slice();
  };

  CoordinateSystemManager.register = function (type, creator) {
    coordinateSystemCreators[type] = creator;
  };

  CoordinateSystemManager.get = function (type) {
    return coordinateSystemCreators[type];
  };

  return CoordinateSystemManager;
}();

const CoordinateSystem = CoordinateSystemManager;
/* Injected with object hook! */

var QUERY_REG = /^(min|max)?(.+)$/; // Key: mainType
// type FakeComponentsMap = HashMap<(MappingExistingItem & { subType: string })[]>;

/**
 * TERM EXPLANATIONS:
 * See `ECOption` and `ECUnitOption` in `src/util/types.ts`.
 */

var OptionManager =
/** @class */
function () {
  // timeline.notMerge is not supported in ec3. Firstly there is rearly
  // case that notMerge is needed. Secondly supporting 'notMerge' requires
  // rawOption cloned and backuped when timeline changed, which does no
  // good to performance. What's more, that both timeline and setOption
  // method supply 'notMerge' brings complex and some problems.
  // Consider this case:
  // (step1) chart.setOption({timeline: {notMerge: false}, ...}, false);
  // (step2) chart.setOption({timeline: {notMerge: true}, ...}, false);
  function OptionManager(api) {
    this._timelineOptions = [];
    this._mediaList = [];
    /**
     * -1, means default.
     * empty means no media.
     */

    this._currentMediaIndices = [];
    this._api = api;
  }

  OptionManager.prototype.setOption = function (rawOption, optionPreprocessorFuncs, opt) {
    if (rawOption) {
      // That set dat primitive is dangerous if user reuse the data when setOption again.
      each$4(normalizeToArray(rawOption.series), function (series) {
        series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data);
      });
      each$4(normalizeToArray(rawOption.dataset), function (dataset) {
        dataset && dataset.source && isTypedArray(dataset.source) && setAsPrimitive(dataset.source);
      });
    } // Caution: some series modify option data, if do not clone,
    // it should ensure that the repeat modify correctly
    // (create a new object when modify itself).


    rawOption = clone$2(rawOption); // FIXME
    // If some property is set in timeline options or media option but
    // not set in baseOption, a warning should be given.

    var optionBackup = this._optionBackup;
    var newParsedOption = parseRawOption(rawOption, optionPreprocessorFuncs, !optionBackup);
    this._newBaseOption = newParsedOption.baseOption; // For setOption at second time (using merge mode);

    if (optionBackup) {
      // FIXME
      // the restore merge solution is essentially incorrect.
      // the mapping can not be 100% consistent with ecModel, which probably brings
      // potential bug!
      // The first merge is delayed, because in most cases, users do not call `setOption` twice.
      // let fakeCmptsMap = this._fakeCmptsMap;
      // if (!fakeCmptsMap) {
      //     fakeCmptsMap = this._fakeCmptsMap = createHashMap();
      //     mergeToBackupOption(fakeCmptsMap, null, optionBackup.baseOption, null);
      // }
      // mergeToBackupOption(
      //     fakeCmptsMap, optionBackup.baseOption, newParsedOption.baseOption, opt
      // );
      // For simplicity, timeline options and media options do not support merge,
      // that is, if you `setOption` twice and both has timeline options, the latter
      // timeline options will not be merged to the former, but just substitute them.
      if (newParsedOption.timelineOptions.length) {
        optionBackup.timelineOptions = newParsedOption.timelineOptions;
      }

      if (newParsedOption.mediaList.length) {
        optionBackup.mediaList = newParsedOption.mediaList;
      }

      if (newParsedOption.mediaDefault) {
        optionBackup.mediaDefault = newParsedOption.mediaDefault;
      }
    } else {
      this._optionBackup = newParsedOption;
    }
  };

  OptionManager.prototype.mountOption = function (isRecreate) {
    var optionBackup = this._optionBackup;
    this._timelineOptions = optionBackup.timelineOptions;
    this._mediaList = optionBackup.mediaList;
    this._mediaDefault = optionBackup.mediaDefault;
    this._currentMediaIndices = [];
    return clone$2(isRecreate // this._optionBackup.baseOption, which is created at the first `setOption`
    // called, and is merged into every new option by inner method `mergeToBackupOption`
    // each time `setOption` called, can be only used in `isRecreate`, because
    // its reliability is under suspicion. In other cases option merge is
    // performed by `model.mergeOption`.
    ? optionBackup.baseOption : this._newBaseOption);
  };

  OptionManager.prototype.getTimelineOption = function (ecModel) {
    var option;
    var timelineOptions = this._timelineOptions;

    if (timelineOptions.length) {
      // getTimelineOption can only be called after ecModel inited,
      // so we can get currentIndex from timelineModel.
      var timelineModel = ecModel.getComponent('timeline');

      if (timelineModel) {
        option = clone$2( // FIXME:TS as TimelineModel or quivlant interface
        timelineOptions[timelineModel.getCurrentIndex()]);
      }
    }

    return option;
  };

  OptionManager.prototype.getMediaOption = function (ecModel) {
    var ecWidth = this._api.getWidth();

    var ecHeight = this._api.getHeight();

    var mediaList = this._mediaList;
    var mediaDefault = this._mediaDefault;
    var indices = [];
    var result = []; // No media defined.

    if (!mediaList.length && !mediaDefault) {
      return result;
    } // Multi media may be applied, the latter defined media has higher priority.


    for (var i = 0, len = mediaList.length; i < len; i++) {
      if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) {
        indices.push(i);
      }
    } // FIXME
    // Whether mediaDefault should force users to provide? Otherwise
    // the change by media query can not be recorvered.


    if (!indices.length && mediaDefault) {
      indices = [-1];
    }

    if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) {
      result = map$1(indices, function (index) {
        return clone$2(index === -1 ? mediaDefault.option : mediaList[index].option);
      });
    } // Otherwise return nothing.


    this._currentMediaIndices = indices;
    return result;
  };

  return OptionManager;
}();
/**
 * [RAW_OPTION_PATTERNS]
 * (Note: "series: []" represents all other props in `ECUnitOption`)
 *
 * (1) No prop "baseOption" declared:
 * Root option is used as "baseOption" (except prop "options" and "media").
 * ```js
 * option = {
 *     series: [],
 *     timeline: {},
 *     options: [],
 * };
 * option = {
 *     series: [],
 *     media: {},
 * };
 * option = {
 *     series: [],
 *     timeline: {},
 *     options: [],
 *     media: {},
 * }
 * ```
 *
 * (2) Prop "baseOption" declared:
 * If "baseOption" declared, `ECUnitOption` props can only be declared
 * inside "baseOption" except prop "timeline" (compat ec2).
 * ```js
 * option = {
 *     baseOption: {
 *         timeline: {},
 *         series: [],
 *     },
 *     options: []
 * };
 * option = {
 *     baseOption: {
 *         series: [],
 *     },
 *     media: []
 * };
 * option = {
 *     baseOption: {
 *         timeline: {},
 *         series: [],
 *     },
 *     options: []
 *     media: []
 * };
 * option = {
 *     // ec3 compat ec2: allow (only) `timeline` declared
 *     // outside baseOption. Keep this setting for compat.
 *     timeline: {},
 *     baseOption: {
 *         series: [],
 *     },
 *     options: [],
 *     media: []
 * };
 * ```
 */


function parseRawOption( // `rawOption` May be modified
rawOption, optionPreprocessorFuncs, isNew) {
  var mediaList = [];
  var mediaDefault;
  var baseOption;
  var declaredBaseOption = rawOption.baseOption; // Compatible with ec2, [RAW_OPTION_PATTERNS] above.

  var timelineOnRoot = rawOption.timeline;
  var timelineOptionsOnRoot = rawOption.options;
  var mediaOnRoot = rawOption.media;
  var hasMedia = !!rawOption.media;
  var hasTimeline = !!(timelineOptionsOnRoot || timelineOnRoot || declaredBaseOption && declaredBaseOption.timeline);

  if (declaredBaseOption) {
    baseOption = declaredBaseOption; // For merge option.

    if (!baseOption.timeline) {
      baseOption.timeline = timelineOnRoot;
    }
  } // For convenience, enable to use the root option as the `baseOption`:
  // `{ ...normalOptionProps, media: [{ ... }, { ... }] }`
  else {
      if (hasTimeline || hasMedia) {
        rawOption.options = rawOption.media = null;
      }

      baseOption = rawOption;
    }

  if (hasMedia) {
    if (isArray(mediaOnRoot)) {
      each$4(mediaOnRoot, function (singleMedia) {

        if (singleMedia && singleMedia.option) {
          if (singleMedia.query) {
            mediaList.push(singleMedia);
          } else if (!mediaDefault) {
            // Use the first media default.
            mediaDefault = singleMedia;
          }
        }
      });
    }
  }

  doPreprocess(baseOption);
  each$4(timelineOptionsOnRoot, function (option) {
    return doPreprocess(option);
  });
  each$4(mediaList, function (media) {
    return doPreprocess(media.option);
  });

  function doPreprocess(option) {
    each$4(optionPreprocessorFuncs, function (preProcess) {
      preProcess(option, isNew);
    });
  }

  return {
    baseOption: baseOption,
    timelineOptions: timelineOptionsOnRoot || [],
    mediaDefault: mediaDefault,
    mediaList: mediaList
  };
}
/**
 * @see <http://www.w3.org/TR/css3-mediaqueries/#media1>
 * Support: width, height, aspectRatio
 * Can use max or min as prefix.
 */


function applyMediaQuery(query, ecWidth, ecHeight) {
  var realMap = {
    width: ecWidth,
    height: ecHeight,
    aspectratio: ecWidth / ecHeight // lower case for convenience.

  };
  var applicable = true;
  each$4(query, function (value, attr) {
    var matched = attr.match(QUERY_REG);

    if (!matched || !matched[1] || !matched[2]) {
      return;
    }

    var operator = matched[1];
    var realAttr = matched[2].toLowerCase();

    if (!compare(realMap[realAttr], value, operator)) {
      applicable = false;
    }
  });
  return applicable;
}

function compare(real, expect, operator) {
  if (operator === 'min') {
    return real >= expect;
  } else if (operator === 'max') {
    return real <= expect;
  } else {
    // Equals
    return real === expect;
  }
}

function indicesEquals(indices1, indices2) {
  // indices is always order by asc and has only finite number.
  return indices1.join(',') === indices2.join(',');
}
/**
 * Consider case:
 * `chart.setOption(opt1);`
 * Then user do some interaction like dataZoom, dataView changing.
 * `chart.setOption(opt2);`
 * Then user press 'reset button' in toolbox.
 *
 * After doing that all of the interaction effects should be reset, the
 * chart should be the same as the result of invoke
 * `chart.setOption(opt1); chart.setOption(opt2);`.
 *
 * Although it is not able ensure that
 * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to
 * `chart.setOption(merge(opt1, opt2));` exactly,
 * this might be the only simple way to implement that feature.
 *
 * MEMO: We've considered some other approaches:
 * 1. Each model handles its self restoration but not uniform treatment.
 *     (Too complex in logic and error-prone)
 * 2. Use a shadow ecModel. (Performance expensive)
 *
 * FIXME: A possible solution:
 * Add a extra level of model for each component model. The inheritance chain would be:
 * ecModel <- componentModel <- componentActionModel <- dataItemModel
 * And all of the actions can only modify the `componentActionModel` rather than
 * `componentModel`. `setOption` will only modify the `ecModel` and `componentModel`.
 * When "resotre" action triggered, model from `componentActionModel` will be discarded
 * instead of recreating the "ecModel" from the "_optionBackup".
 */
// function mergeToBackupOption(
//     fakeCmptsMap: FakeComponentsMap,
//     // `tarOption` Can be null/undefined, means init
//     tarOption: ECUnitOption,
//     newOption: ECUnitOption,
//     // Can be null/undefined
//     opt: InnerSetOptionOpts
// ): void {
//     newOption = newOption || {} as ECUnitOption;
//     const notInit = !!tarOption;
//     each(newOption, function (newOptsInMainType, mainType) {
//         if (newOptsInMainType == null) {
//             return;
//         }
//         if (!ComponentModel.hasClass(mainType)) {
//             if (tarOption) {
//                 tarOption[mainType] = merge(tarOption[mainType], newOptsInMainType, true);
//             }
//         }
//         else {
//             const oldTarOptsInMainType = notInit ? normalizeToArray(tarOption[mainType]) : null;
//             const oldFakeCmptsInMainType = fakeCmptsMap.get(mainType) || [];
//             const resultTarOptsInMainType = notInit ? (tarOption[mainType] = [] as ComponentOption[]) : null;
//             const resultFakeCmptsInMainType = fakeCmptsMap.set(mainType, []);
//             const mappingResult = mappingToExists(
//                 oldFakeCmptsInMainType,
//                 normalizeToArray(newOptsInMainType),
//                 (opt && opt.replaceMergeMainTypeMap.get(mainType)) ? 'replaceMerge' : 'normalMerge'
//             );
//             setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel as ComponentModelConstructor);
//             each(mappingResult, function (resultItem, index) {
//                 // The same logic as `Global.ts#_mergeOption`.
//                 let fakeCmpt = resultItem.existing;
//                 const newOption = resultItem.newOption;
//                 const keyInfo = resultItem.keyInfo;
//                 let fakeCmptOpt;
//                 if (!newOption) {
//                     fakeCmptOpt = oldTarOptsInMainType[index];
//                 }
//                 else {
//                     if (fakeCmpt && fakeCmpt.subType === keyInfo.subType) {
//                         fakeCmpt.name = keyInfo.name;
//                         if (notInit) {
//                             fakeCmptOpt = merge(oldTarOptsInMainType[index], newOption, true);
//                         }
//                     }
//                     else {
//                         fakeCmpt = extend({}, keyInfo);
//                         if (notInit) {
//                             fakeCmptOpt = clone(newOption);
//                         }
//                     }
//                 }
//                 if (fakeCmpt) {
//                     notInit && resultTarOptsInMainType.push(fakeCmptOpt);
//                     resultFakeCmptsInMainType.push(fakeCmpt);
//                 }
//                 else {
//                     notInit && resultTarOptsInMainType.push(void 0);
//                     resultFakeCmptsInMainType.push(void 0);
//                 }
//             });
//         }
//     });
// }


const OptionManager$1 = OptionManager;
/* Injected with object hook! */

var each$2 = each$4;
var isObject$1 = isObject$2;
var POSSIBLE_STYLES = ['areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', 'chordStyle', 'label', 'labelLine'];

function compatEC2ItemStyle(opt) {
  var itemStyleOpt = opt && opt.itemStyle;

  if (!itemStyleOpt) {
    return;
  }

  for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) {
    var styleName = POSSIBLE_STYLES[i];
    var normalItemStyleOpt = itemStyleOpt.normal;
    var emphasisItemStyleOpt = itemStyleOpt.emphasis;

    if (normalItemStyleOpt && normalItemStyleOpt[styleName]) {

      opt[styleName] = opt[styleName] || {};

      if (!opt[styleName].normal) {
        opt[styleName].normal = normalItemStyleOpt[styleName];
      } else {
        merge(opt[styleName].normal, normalItemStyleOpt[styleName]);
      }

      normalItemStyleOpt[styleName] = null;
    }

    if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) {

      opt[styleName] = opt[styleName] || {};

      if (!opt[styleName].emphasis) {
        opt[styleName].emphasis = emphasisItemStyleOpt[styleName];
      } else {
        merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]);
      }

      emphasisItemStyleOpt[styleName] = null;
    }
  }
}

function convertNormalEmphasis(opt, optType, useExtend) {
  if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) {
    var normalOpt = opt[optType].normal;
    var emphasisOpt = opt[optType].emphasis;

    if (normalOpt) {


      if (useExtend) {
        opt[optType].normal = opt[optType].emphasis = null;
        defaults(opt[optType], normalOpt);
      } else {
        opt[optType] = normalOpt;
      }
    }

    if (emphasisOpt) {

      opt.emphasis = opt.emphasis || {};
      opt.emphasis[optType] = emphasisOpt; // Also compat the case user mix the style and focus together in ec3 style
      // for example: { itemStyle: { normal: {}, emphasis: {focus, shadowBlur} } }

      if (emphasisOpt.focus) {
        opt.emphasis.focus = emphasisOpt.focus;
      }

      if (emphasisOpt.blurScope) {
        opt.emphasis.blurScope = emphasisOpt.blurScope;
      }
    }
  }
}

function removeEC3NormalStatus(opt) {
  convertNormalEmphasis(opt, 'itemStyle');
  convertNormalEmphasis(opt, 'lineStyle');
  convertNormalEmphasis(opt, 'areaStyle');
  convertNormalEmphasis(opt, 'label');
  convertNormalEmphasis(opt, 'labelLine'); // treemap

  convertNormalEmphasis(opt, 'upperLabel'); // graph

  convertNormalEmphasis(opt, 'edgeLabel');
}

function compatTextStyle(opt, propName) {
  // Check whether is not object (string\null\undefined ...)
  var labelOptSingle = isObject$1(opt) && opt[propName];
  var textStyle = isObject$1(labelOptSingle) && labelOptSingle.textStyle;

  if (textStyle) {

    for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) {
      var textPropName = TEXT_STYLE_OPTIONS[i];

      if (textStyle.hasOwnProperty(textPropName)) {
        labelOptSingle[textPropName] = textStyle[textPropName];
      }
    }
  }
}

function compatEC3CommonStyles(opt) {
  if (opt) {
    removeEC3NormalStatus(opt);
    compatTextStyle(opt, 'label');
    opt.emphasis && compatTextStyle(opt.emphasis, 'label');
  }
}

function processSeries(seriesOpt) {
  if (!isObject$1(seriesOpt)) {
    return;
  }

  compatEC2ItemStyle(seriesOpt);
  removeEC3NormalStatus(seriesOpt);
  compatTextStyle(seriesOpt, 'label'); // treemap

  compatTextStyle(seriesOpt, 'upperLabel'); // graph

  compatTextStyle(seriesOpt, 'edgeLabel');

  if (seriesOpt.emphasis) {
    compatTextStyle(seriesOpt.emphasis, 'label'); // treemap

    compatTextStyle(seriesOpt.emphasis, 'upperLabel'); // graph

    compatTextStyle(seriesOpt.emphasis, 'edgeLabel');
  }

  var markPoint = seriesOpt.markPoint;

  if (markPoint) {
    compatEC2ItemStyle(markPoint);
    compatEC3CommonStyles(markPoint);
  }

  var markLine = seriesOpt.markLine;

  if (markLine) {
    compatEC2ItemStyle(markLine);
    compatEC3CommonStyles(markLine);
  }

  var markArea = seriesOpt.markArea;

  if (markArea) {
    compatEC3CommonStyles(markArea);
  }

  var data = seriesOpt.data; // Break with ec3: if `setOption` again, there may be no `type` in option,
  // then the backward compat based on option type will not be performed.

  if (seriesOpt.type === 'graph') {
    data = data || seriesOpt.nodes;
    var edgeData = seriesOpt.links || seriesOpt.edges;

    if (edgeData && !isTypedArray(edgeData)) {
      for (var i = 0; i < edgeData.length; i++) {
        compatEC3CommonStyles(edgeData[i]);
      }
    }

    each$4(seriesOpt.categories, function (opt) {
      removeEC3NormalStatus(opt);
    });
  }

  if (data && !isTypedArray(data)) {
    for (var i = 0; i < data.length; i++) {
      compatEC3CommonStyles(data[i]);
    }
  } // mark point data


  markPoint = seriesOpt.markPoint;

  if (markPoint && markPoint.data) {
    var mpData = markPoint.data;

    for (var i = 0; i < mpData.length; i++) {
      compatEC3CommonStyles(mpData[i]);
    }
  } // mark line data


  markLine = seriesOpt.markLine;

  if (markLine && markLine.data) {
    var mlData = markLine.data;

    for (var i = 0; i < mlData.length; i++) {
      if (isArray(mlData[i])) {
        compatEC3CommonStyles(mlData[i][0]);
        compatEC3CommonStyles(mlData[i][1]);
      } else {
        compatEC3CommonStyles(mlData[i]);
      }
    }
  } // Series


  if (seriesOpt.type === 'gauge') {
    compatTextStyle(seriesOpt, 'axisLabel');
    compatTextStyle(seriesOpt, 'title');
    compatTextStyle(seriesOpt, 'detail');
  } else if (seriesOpt.type === 'treemap') {
    convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle');
    each$4(seriesOpt.levels, function (opt) {
      removeEC3NormalStatus(opt);
    });
  } else if (seriesOpt.type === 'tree') {
    removeEC3NormalStatus(seriesOpt.leaves);
  } // sunburst starts from ec4, so it does not need to compat levels.

}

function toArr(o) {
  return isArray(o) ? o : o ? [o] : [];
}

function toObj(o) {
  return (isArray(o) ? o[0] : o) || {};
}

function globalCompatStyle(option, isTheme) {
  each$2(toArr(option.series), function (seriesOpt) {
    isObject$1(seriesOpt) && processSeries(seriesOpt);
  });
  var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar'];
  isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis');
  each$2(axes, function (axisName) {
    each$2(toArr(option[axisName]), function (axisOpt) {
      if (axisOpt) {
        compatTextStyle(axisOpt, 'axisLabel');
        compatTextStyle(axisOpt.axisPointer, 'label');
      }
    });
  });
  each$2(toArr(option.parallel), function (parallelOpt) {
    var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault;
    compatTextStyle(parallelAxisDefault, 'axisLabel');
    compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label');
  });
  each$2(toArr(option.calendar), function (calendarOpt) {
    convertNormalEmphasis(calendarOpt, 'itemStyle');
    compatTextStyle(calendarOpt, 'dayLabel');
    compatTextStyle(calendarOpt, 'monthLabel');
    compatTextStyle(calendarOpt, 'yearLabel');
  }); // radar.name.textStyle

  each$2(toArr(option.radar), function (radarOpt) {
    compatTextStyle(radarOpt, 'name'); // Use axisName instead of name because component has name property

    if (radarOpt.name && radarOpt.axisName == null) {
      radarOpt.axisName = radarOpt.name;
      delete radarOpt.name;
    }

    if (radarOpt.nameGap != null && radarOpt.axisNameGap == null) {
      radarOpt.axisNameGap = radarOpt.nameGap;
      delete radarOpt.nameGap;
    }
  });
  each$2(toArr(option.geo), function (geoOpt) {
    if (isObject$1(geoOpt)) {
      compatEC3CommonStyles(geoOpt);
      each$2(toArr(geoOpt.regions), function (regionObj) {
        compatEC3CommonStyles(regionObj);
      });
    }
  });
  each$2(toArr(option.timeline), function (timelineOpt) {
    compatEC3CommonStyles(timelineOpt);
    convertNormalEmphasis(timelineOpt, 'label');
    convertNormalEmphasis(timelineOpt, 'itemStyle');
    convertNormalEmphasis(timelineOpt, 'controlStyle', true);
    var data = timelineOpt.data;
    isArray(data) && each$4(data, function (item) {
      if (isObject$2(item)) {
        convertNormalEmphasis(item, 'label');
        convertNormalEmphasis(item, 'itemStyle');
      }
    });
  });
  each$2(toArr(option.toolbox), function (toolboxOpt) {
    convertNormalEmphasis(toolboxOpt, 'iconStyle');
    each$2(toolboxOpt.feature, function (featureOpt) {
      convertNormalEmphasis(featureOpt, 'iconStyle');
    });
  });
  compatTextStyle(toObj(option.axisPointer), 'label');
  compatTextStyle(toObj(option.tooltip).axisPointer, 'label'); // Clean logs
  // storedLogs = {};
}
/* Injected with object hook! */

function get(opt, path) {
  var pathArr = path.split(',');
  var obj = opt;

  for (var i = 0; i < pathArr.length; i++) {
    obj = obj && obj[pathArr[i]];

    if (obj == null) {
      break;
    }
  }

  return obj;
}

function set(opt, path, val, overwrite) {
  var pathArr = path.split(',');
  var obj = opt;
  var key;
  var i = 0;

  for (; i < pathArr.length - 1; i++) {
    key = pathArr[i];

    if (obj[key] == null) {
      obj[key] = {};
    }

    obj = obj[key];
  }

  if (overwrite || obj[pathArr[i]] == null) {
    obj[pathArr[i]] = val;
  }
}

function compatLayoutProperties(option) {
  option && each$4(LAYOUT_PROPERTIES, function (prop) {
    if (prop[0] in option && !(prop[1] in option)) {
      option[prop[1]] = option[prop[0]];
    }
  });
}

var LAYOUT_PROPERTIES = [['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']];
var COMPATITABLE_COMPONENTS = ['grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline'];
var BAR_ITEM_STYLE_MAP = [['borderRadius', 'barBorderRadius'], ['borderColor', 'barBorderColor'], ['borderWidth', 'barBorderWidth']];

function compatBarItemStyle(option) {
  var itemStyle = option && option.itemStyle;

  if (itemStyle) {
    for (var i = 0; i < BAR_ITEM_STYLE_MAP.length; i++) {
      var oldName = BAR_ITEM_STYLE_MAP[i][1];
      var newName = BAR_ITEM_STYLE_MAP[i][0];

      if (itemStyle[oldName] != null) {
        itemStyle[newName] = itemStyle[oldName];
      }
    }
  }
}

function compatPieLabel(option) {
  if (!option) {
    return;
  }

  if (option.alignTo === 'edge' && option.margin != null && option.edgeDistance == null) {

    option.edgeDistance = option.margin;
  }
}

function compatSunburstState(option) {
  if (!option) {
    return;
  }

  if (option.downplay && !option.blur) {
    option.blur = option.downplay;
  }
}

function compatGraphFocus(option) {
  if (!option) {
    return;
  }

  if (option.focusNodeAdjacency != null) {
    option.emphasis = option.emphasis || {};

    if (option.emphasis.focus == null) {

      option.emphasis.focus = 'adjacency';
    }
  }
}

function traverseTree(data, cb) {
  if (data) {
    for (var i = 0; i < data.length; i++) {
      cb(data[i]);
      data[i] && traverseTree(data[i].children, cb);
    }
  }
}

function globalBackwardCompat(option, isTheme) {
  globalCompatStyle(option, isTheme); // Make sure series array for model initialization.

  option.series = normalizeToArray(option.series);
  each$4(option.series, function (seriesOpt) {
    if (!isObject$2(seriesOpt)) {
      return;
    }

    var seriesType = seriesOpt.type;

    if (seriesType === 'line') {
      if (seriesOpt.clipOverflow != null) {
        seriesOpt.clip = seriesOpt.clipOverflow;
      }
    } else if (seriesType === 'pie' || seriesType === 'gauge') {
      if (seriesOpt.clockWise != null) {
        seriesOpt.clockwise = seriesOpt.clockWise;
      }

      compatPieLabel(seriesOpt.label);
      var data = seriesOpt.data;

      if (data && !isTypedArray(data)) {
        for (var i = 0; i < data.length; i++) {
          compatPieLabel(data[i]);
        }
      }

      if (seriesOpt.hoverOffset != null) {
        seriesOpt.emphasis = seriesOpt.emphasis || {};

        if (seriesOpt.emphasis.scaleSize = null) {

          seriesOpt.emphasis.scaleSize = seriesOpt.hoverOffset;
        }
      }
    } else if (seriesType === 'gauge') {
      var pointerColor = get(seriesOpt, 'pointer.color');
      pointerColor != null && set(seriesOpt, 'itemStyle.color', pointerColor);
    } else if (seriesType === 'bar') {
      compatBarItemStyle(seriesOpt);
      compatBarItemStyle(seriesOpt.backgroundStyle);
      compatBarItemStyle(seriesOpt.emphasis);
      var data = seriesOpt.data;

      if (data && !isTypedArray(data)) {
        for (var i = 0; i < data.length; i++) {
          if (typeof data[i] === 'object') {
            compatBarItemStyle(data[i]);
            compatBarItemStyle(data[i] && data[i].emphasis);
          }
        }
      }
    } else if (seriesType === 'sunburst') {
      var highlightPolicy = seriesOpt.highlightPolicy;

      if (highlightPolicy) {
        seriesOpt.emphasis = seriesOpt.emphasis || {};

        if (!seriesOpt.emphasis.focus) {
          seriesOpt.emphasis.focus = highlightPolicy;
        }
      }

      compatSunburstState(seriesOpt);
      traverseTree(seriesOpt.data, compatSunburstState);
    } else if (seriesType === 'graph' || seriesType === 'sankey') {
      compatGraphFocus(seriesOpt); // TODO nodes, edges?
    } else if (seriesType === 'map') {
      if (seriesOpt.mapType && !seriesOpt.map) {

        seriesOpt.map = seriesOpt.mapType;
      }

      if (seriesOpt.mapLocation) {

        defaults(seriesOpt, seriesOpt.mapLocation);
      }
    }

    if (seriesOpt.hoverAnimation != null) {
      seriesOpt.emphasis = seriesOpt.emphasis || {};

      if (seriesOpt.emphasis && seriesOpt.emphasis.scale == null) {

        seriesOpt.emphasis.scale = seriesOpt.hoverAnimation;
      }
    }

    compatLayoutProperties(seriesOpt);
  }); // dataRange has changed to visualMap

  if (option.dataRange) {
    option.visualMap = option.dataRange;
  }

  each$4(COMPATITABLE_COMPONENTS, function (componentName) {
    var options = option[componentName];

    if (options) {
      if (!isArray(options)) {
        options = [options];
      }

      each$4(options, function (option) {
        compatLayoutProperties(option);
      });
    }
  });
}
/* Injected with object hook! */

//     data processing stage is blocked in stream.
//     See <module:echarts/stream/Scheduler#performDataProcessorTasks>
// (2) Only register once when import repeatedly.
//     Should be executed after series is filtered and before stack calculation.

function dataStack(ecModel) {
  var stackInfoMap = createHashMap();
  ecModel.eachSeries(function (seriesModel) {
    var stack = seriesModel.get('stack'); // Compatible: when `stack` is set as '', do not stack.

    if (stack) {
      var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []);
      var data = seriesModel.getData();
      var stackInfo = {
        // Used for calculate axis extent automatically.
        // TODO: Type getCalculationInfo return more specific type?
        stackResultDimension: data.getCalculationInfo('stackResultDimension'),
        stackedOverDimension: data.getCalculationInfo('stackedOverDimension'),
        stackedDimension: data.getCalculationInfo('stackedDimension'),
        stackedByDimension: data.getCalculationInfo('stackedByDimension'),
        isStackedByIndex: data.getCalculationInfo('isStackedByIndex'),
        data: data,
        seriesModel: seriesModel
      }; // If stacked on axis that do not support data stack.

      if (!stackInfo.stackedDimension || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)) {
        return;
      }

      stackInfoList.length && data.setCalculationInfo('stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel);
      stackInfoList.push(stackInfo);
    }
  });
  stackInfoMap.each(calculateStack);
}

function calculateStack(stackInfoList) {
  each$4(stackInfoList, function (targetStackInfo, idxInStack) {
    var resultVal = [];
    var resultNaN = [NaN, NaN];
    var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension];
    var targetData = targetStackInfo.data;
    var isStackedByIndex = targetStackInfo.isStackedByIndex;
    var stackStrategy = targetStackInfo.seriesModel.get('stackStrategy') || 'samesign'; // Should not write on raw data, because stack series model list changes
    // depending on legend selection.

    targetData.modify(dims, function (v0, v1, dataIndex) {
      var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex); // Consider `connectNulls` of line area, if value is NaN, stackedOver
      // should also be NaN, to draw a appropriate belt area.

      if (isNaN(sum)) {
        return resultNaN;
      }

      var byValue;
      var stackedDataRawIndex;

      if (isStackedByIndex) {
        stackedDataRawIndex = targetData.getRawIndex(dataIndex);
      } else {
        byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex);
      } // If stackOver is NaN, chart view will render point on value start.


      var stackedOver = NaN;

      for (var j = idxInStack - 1; j >= 0; j--) {
        var stackInfo = stackInfoList[j]; // Has been optimized by inverted indices on `stackedByDimension`.

        if (!isStackedByIndex) {
          stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue);
        }

        if (stackedDataRawIndex >= 0) {
          var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex); // Considering positive stack, negative stack and empty data

          if (stackStrategy === 'all' // single stack group
          || stackStrategy === 'positive' && val > 0 || stackStrategy === 'negative' && val < 0 || stackStrategy === 'samesign' && sum >= 0 && val > 0 // All positive stack
          || stackStrategy === 'samesign' && sum <= 0 && val < 0 // All negative stack
          ) {
              // The sum has to be very small to be affected by the
              // floating arithmetic problem. An incorrect result will probably
              // cause axis min/max to be filtered incorrectly.
              sum = addSafe(sum, val);
              stackedOver = val;
              break;
            }
        }
      }

      resultVal[0] = sum;
      resultVal[1] = stackedOver;
      return resultVal;
    });
  });
}
/* Injected with object hook! */

var SourceImpl =
/** @class */
function () {
  function SourceImpl(fields) {
    this.data = fields.data || (fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []);
    this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN; // Visit config

    this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN;
    this.startIndex = fields.startIndex || 0;
    this.dimensionsDetectedCount = fields.dimensionsDetectedCount;
    this.metaRawOption = fields.metaRawOption;
    var dimensionsDefine = this.dimensionsDefine = fields.dimensionsDefine;

    if (dimensionsDefine) {
      for (var i = 0; i < dimensionsDefine.length; i++) {
        var dim = dimensionsDefine[i];

        if (dim.type == null) {
          if (guessOrdinal(this, i) === BE_ORDINAL.Must) {
            dim.type = 'ordinal';
          }
        }
      }
    }
  }

  return SourceImpl;
}();

function isSourceInstance(val) {
  return val instanceof SourceImpl;
}
/**
 * Create a source from option.
 * NOTE: Created source is immutable. Don't change any properties in it.
 */

function createSource(sourceData, thisMetaRawOption, // can be null. If not provided, auto detect it from `sourceData`.
sourceFormat) {
  sourceFormat = sourceFormat || detectSourceFormat(sourceData);
  var seriesLayoutBy = thisMetaRawOption.seriesLayoutBy;
  var determined = determineSourceDimensions(sourceData, sourceFormat, seriesLayoutBy, thisMetaRawOption.sourceHeader, thisMetaRawOption.dimensions);
  var source = new SourceImpl({
    data: sourceData,
    sourceFormat: sourceFormat,
    seriesLayoutBy: seriesLayoutBy,
    dimensionsDefine: determined.dimensionsDefine,
    startIndex: determined.startIndex,
    dimensionsDetectedCount: determined.dimensionsDetectedCount,
    metaRawOption: clone$2(thisMetaRawOption)
  });
  return source;
}
/**
 * Wrap original series data for some compatibility cases.
 */

function createSourceFromSeriesDataOption(data) {
  return new SourceImpl({
    data: data,
    sourceFormat: isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL
  });
}
/**
 * Clone source but excludes source data.
 */

function cloneSourceShallow(source) {
  return new SourceImpl({
    data: source.data,
    sourceFormat: source.sourceFormat,
    seriesLayoutBy: source.seriesLayoutBy,
    dimensionsDefine: clone$2(source.dimensionsDefine),
    startIndex: source.startIndex,
    dimensionsDetectedCount: source.dimensionsDetectedCount
  });
}
/**
 * Note: An empty array will be detected as `SOURCE_FORMAT_ARRAY_ROWS`.
 */

function detectSourceFormat(data) {
  var sourceFormat = SOURCE_FORMAT_UNKNOWN;

  if (isTypedArray(data)) {
    sourceFormat = SOURCE_FORMAT_TYPED_ARRAY;
  } else if (isArray(data)) {
    // FIXME Whether tolerate null in top level array?
    if (data.length === 0) {
      sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
    }

    for (var i = 0, len = data.length; i < len; i++) {
      var item = data[i];

      if (item == null) {
        continue;
      } else if (isArray(item)) {
        sourceFormat = SOURCE_FORMAT_ARRAY_ROWS;
        break;
      } else if (isObject$2(item)) {
        sourceFormat = SOURCE_FORMAT_OBJECT_ROWS;
        break;
      }
    }
  } else if (isObject$2(data)) {
    for (var key in data) {
      if (hasOwn(data, key) && isArrayLike(data[key])) {
        sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS;
        break;
      }
    }
  }

  return sourceFormat;
}
/**
 * Determine the source definitions from data standalone dimensions definitions
 * are not specified.
 */

function determineSourceDimensions(data, sourceFormat, seriesLayoutBy, sourceHeader, // standalone raw dimensions definition, like:
// {
//     dimensions: ['aa', 'bb', { name: 'cc', type: 'time' }]
// }
// in `dataset` or `series`
dimensionsDefine) {
  var dimensionsDetectedCount;
  var startIndex; // PENDING: Could data be null/undefined here?
  // currently, if `dataset.source` not specified, error thrown.
  // if `series.data` not specified, nothing rendered without error thrown.
  // Should test these cases.

  if (!data) {
    return {
      dimensionsDefine: normalizeDimensionsOption(dimensionsDefine),
      startIndex: startIndex,
      dimensionsDetectedCount: dimensionsDetectedCount
    };
  }

  if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
    var dataArrayRows = data; // Rule: Most of the first line are string: it is header.
    // Caution: consider a line with 5 string and 1 number,
    // it still can not be sure it is a head, because the
    // 5 string may be 5 values of category columns.

    if (sourceHeader === 'auto' || sourceHeader == null) {
      arrayRowsTravelFirst(function (val) {
        // '-' is regarded as null/undefined.
        if (val != null && val !== '-') {
          if (isString(val)) {
            startIndex == null && (startIndex = 1);
          } else {
            startIndex = 0;
          }
        } // 10 is an experience number, avoid long loop.

      }, seriesLayoutBy, dataArrayRows, 10);
    } else {
      startIndex = isNumber(sourceHeader) ? sourceHeader : sourceHeader ? 1 : 0;
    }

    if (!dimensionsDefine && startIndex === 1) {
      dimensionsDefine = [];
      arrayRowsTravelFirst(function (val, index) {
        dimensionsDefine[index] = val != null ? val + '' : '';
      }, seriesLayoutBy, dataArrayRows, Infinity);
    }

    dimensionsDetectedCount = dimensionsDefine ? dimensionsDefine.length : seriesLayoutBy === SERIES_LAYOUT_BY_ROW ? dataArrayRows.length : dataArrayRows[0] ? dataArrayRows[0].length : null;
  } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
    if (!dimensionsDefine) {
      dimensionsDefine = objectRowsCollectDimensions(data);
    }
  } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
    if (!dimensionsDefine) {
      dimensionsDefine = [];
      each$4(data, function (colArr, key) {
        dimensionsDefine.push(key);
      });
    }
  } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
    var value0 = getDataItemValue(data[0]);
    dimensionsDetectedCount = isArray(value0) && value0.length || 1;
  } else ;

  return {
    startIndex: startIndex,
    dimensionsDefine: normalizeDimensionsOption(dimensionsDefine),
    dimensionsDetectedCount: dimensionsDetectedCount
  };
}

function objectRowsCollectDimensions(data) {
  var firstIndex = 0;
  var obj;

  while (firstIndex < data.length && !(obj = data[firstIndex++])) {} // jshint ignore: line


  if (obj) {
    return keys(obj);
  }
} // Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'],
// which is reasonable. But dimension name is duplicated.
// Returns undefined or an array contains only object without null/undefined or string.


function normalizeDimensionsOption(dimensionsDefine) {
  if (!dimensionsDefine) {
    // The meaning of null/undefined is different from empty array.
    return;
  }

  var nameMap = createHashMap();
  return map$1(dimensionsDefine, function (rawItem, index) {
    rawItem = isObject$2(rawItem) ? rawItem : {
      name: rawItem
    }; // Other fields will be discarded.

    var item = {
      name: rawItem.name,
      displayName: rawItem.displayName,
      type: rawItem.type
    }; // User can set null in dimensions.
    // We don't auto specify name, otherwise a given name may
    // cause it to be referred unexpectedly.

    if (item.name == null) {
      return item;
    } // Also consider number form like 2012.


    item.name += ''; // User may also specify displayName.
    // displayName will always exists except user not
    // specified or dim name is not specified or detected.
    // (A auto generated dim name will not be used as
    // displayName).

    if (item.displayName == null) {
      item.displayName = item.name;
    }

    var exist = nameMap.get(item.name);

    if (!exist) {
      nameMap.set(item.name, {
        count: 1
      });
    } else {
      item.name += '-' + exist.count++;
    }

    return item;
  });
}

function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) {
  if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) {
    for (var i = 0; i < data.length && i < maxLoop; i++) {
      cb(data[i] ? data[i][0] : null, i);
    }
  } else {
    var value0 = data[0] || [];

    for (var i = 0; i < value0.length && i < maxLoop; i++) {
      cb(value0[i], i);
    }
  }
}

function shouldRetrieveDataByName(source) {
  var sourceFormat = source.sourceFormat;
  return sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS;
}
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var _a, _b, _c; // TODO
var providerMethods;
var mountMethods;
/**
 * If normal array used, mutable chunk size is supported.
 * If typed array used, chunk size must be fixed.
 */

var DefaultDataProvider =
/** @class */
function () {
  function DefaultDataProvider(sourceParam, dimSize) {
    // let source: Source;
    var source = !isSourceInstance(sourceParam) ? createSourceFromSeriesDataOption(sourceParam) : sourceParam; // declare source is Source;

    this._source = source;
    var data = this._data = source.data; // Typed array. TODO IE10+?

    if (source.sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {

      this._offset = 0;
      this._dimSize = dimSize;
      this._data = data;
    }

    mountMethods(this, data, source);
  }

  DefaultDataProvider.prototype.getSource = function () {
    return this._source;
  };

  DefaultDataProvider.prototype.count = function () {
    return 0;
  };

  DefaultDataProvider.prototype.getItem = function (idx, out) {
    return;
  };

  DefaultDataProvider.prototype.appendData = function (newData) {};

  DefaultDataProvider.prototype.clean = function () {};

  DefaultDataProvider.protoInitialize = function () {
    // PENDING: To avoid potential incompat (e.g., prototype
    // is visited somewhere), still init them on prototype.
    var proto = DefaultDataProvider.prototype;
    proto.pure = false;
    proto.persistent = true;
  }();

  DefaultDataProvider.internalField = function () {
    var _a;

    mountMethods = function (provider, data, source) {
      var sourceFormat = source.sourceFormat;
      var seriesLayoutBy = source.seriesLayoutBy;
      var startIndex = source.startIndex;
      var dimsDef = source.dimensionsDefine;
      var methods = providerMethods[getMethodMapKey(sourceFormat, seriesLayoutBy)];

      extend(provider, methods);

      if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
        provider.getItem = getItemForTypedArray;
        provider.count = countForTypedArray;
        provider.fillStorage = fillStorageForTypedArray;
      } else {
        var rawItemGetter = getRawSourceItemGetter(sourceFormat, seriesLayoutBy);
        provider.getItem = bind$1(rawItemGetter, null, data, startIndex, dimsDef);
        var rawCounter = getRawSourceDataCounter(sourceFormat, seriesLayoutBy);
        provider.count = bind$1(rawCounter, null, data, startIndex, dimsDef);
      }
    };

    var getItemForTypedArray = function (idx, out) {
      idx = idx - this._offset;
      out = out || [];
      var data = this._data;
      var dimSize = this._dimSize;
      var offset = dimSize * idx;

      for (var i = 0; i < dimSize; i++) {
        out[i] = data[offset + i];
      }

      return out;
    };

    var fillStorageForTypedArray = function (start, end, storage, extent) {
      var data = this._data;
      var dimSize = this._dimSize;

      for (var dim = 0; dim < dimSize; dim++) {
        var dimExtent = extent[dim];
        var min = dimExtent[0] == null ? Infinity : dimExtent[0];
        var max = dimExtent[1] == null ? -Infinity : dimExtent[1];
        var count = end - start;
        var arr = storage[dim];

        for (var i = 0; i < count; i++) {
          // appendData with TypedArray will always do replace in provider.
          var val = data[i * dimSize + dim];
          arr[start + i] = val;
          val < min && (min = val);
          val > max && (max = val);
        }

        dimExtent[0] = min;
        dimExtent[1] = max;
      }
    };

    var countForTypedArray = function () {
      return this._data ? this._data.length / this._dimSize : 0;
    };

    providerMethods = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = {
      pure: true,
      appendData: appendDataSimply
    }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = {
      pure: true,
      appendData: function () {
        throw new Error('Do not support appendData when set seriesLayoutBy: "row".');
      }
    }, _a[SOURCE_FORMAT_OBJECT_ROWS] = {
      pure: true,
      appendData: appendDataSimply
    }, _a[SOURCE_FORMAT_KEYED_COLUMNS] = {
      pure: true,
      appendData: function (newData) {
        var data = this._data;
        each$4(newData, function (newCol, key) {
          var oldCol = data[key] || (data[key] = []);

          for (var i = 0; i < (newCol || []).length; i++) {
            oldCol.push(newCol[i]);
          }
        });
      }
    }, _a[SOURCE_FORMAT_ORIGINAL] = {
      appendData: appendDataSimply
    }, _a[SOURCE_FORMAT_TYPED_ARRAY] = {
      persistent: false,
      pure: true,
      appendData: function (newData) {

        this._data = newData;
      },
      // Clean self if data is already used.
      clean: function () {
        // PENDING
        this._offset += this.count();
        this._data = null;
      }
    }, _a);

    function appendDataSimply(newData) {
      for (var i = 0; i < newData.length; i++) {
        this._data.push(newData[i]);
      }
    }
  }();

  return DefaultDataProvider;
}();

var getItemSimply = function (rawData, startIndex, dimsDef, idx) {
  return rawData[idx];
};

var rawSourceItemGetterMap = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef, idx) {
  return rawData[idx + startIndex];
}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef, idx, out) {
  idx += startIndex;
  var item = out || [];
  var data = rawData;

  for (var i = 0; i < data.length; i++) {
    var row = data[i];
    item[i] = row ? row[idx] : null;
  }

  return item;
}, _a[SOURCE_FORMAT_OBJECT_ROWS] = getItemSimply, _a[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef, idx, out) {
  var item = out || [];

  for (var i = 0; i < dimsDef.length; i++) {
    var dimName = dimsDef[i].name;

    var col = rawData[dimName];
    item[i] = col ? col[idx] : null;
  }

  return item;
}, _a[SOURCE_FORMAT_ORIGINAL] = getItemSimply, _a);
function getRawSourceItemGetter(sourceFormat, seriesLayoutBy) {
  var method = rawSourceItemGetterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)];

  return method;
}

var countSimply = function (rawData, startIndex, dimsDef) {
  return rawData.length;
};

var rawSourceDataCounterMap = (_b = {}, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef) {
  return Math.max(0, rawData.length - startIndex);
}, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef) {
  var row = rawData[0];
  return row ? Math.max(0, row.length - startIndex) : 0;
}, _b[SOURCE_FORMAT_OBJECT_ROWS] = countSimply, _b[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef) {
  var dimName = dimsDef[0].name;

  var col = rawData[dimName];
  return col ? col.length : 0;
}, _b[SOURCE_FORMAT_ORIGINAL] = countSimply, _b);
function getRawSourceDataCounter(sourceFormat, seriesLayoutBy) {
  var method = rawSourceDataCounterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)];

  return method;
}

var getRawValueSimply = function (dataItem, dimIndex, property) {
  return dataItem[dimIndex];
};

var rawSourceValueGetterMap = (_c = {}, _c[SOURCE_FORMAT_ARRAY_ROWS] = getRawValueSimply, _c[SOURCE_FORMAT_OBJECT_ROWS] = function (dataItem, dimIndex, property) {
  return dataItem[property];
}, _c[SOURCE_FORMAT_KEYED_COLUMNS] = getRawValueSimply, _c[SOURCE_FORMAT_ORIGINAL] = function (dataItem, dimIndex, property) {
  // FIXME: In some case (markpoint in geo (geo-map.html)),
  // dataItem is {coord: [...]}
  var value = getDataItemValue(dataItem);
  return !(value instanceof Array) ? value : value[dimIndex];
}, _c[SOURCE_FORMAT_TYPED_ARRAY] = getRawValueSimply, _c);
function getRawSourceValueGetter(sourceFormat) {
  var method = rawSourceValueGetterMap[sourceFormat];

  return method;
}

function getMethodMapKey(sourceFormat, seriesLayoutBy) {
  return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS ? sourceFormat + '_' + seriesLayoutBy : sourceFormat;
} // ??? FIXME can these logic be more neat: getRawValue, getRawDataItem,
// Consider persistent.
// Caution: why use raw value to display on label or tooltip?
// A reason is to avoid format. For example time value we do not know
// how to format is expected. More over, if stack is used, calculated
// value may be 0.91000000001, which have brings trouble to display.
// TODO: consider how to treat null/undefined/NaN when display?


function retrieveRawValue(data, dataIndex, // If dimIndex is null/undefined, return OptionDataItem.
// Otherwise, return OptionDataValue.
dim) {
  if (!data) {
    return;
  } // Consider data may be not persistent.


  var dataItem = data.getRawDataItem(dataIndex);

  if (dataItem == null) {
    return;
  }

  var store = data.getStore();
  var sourceFormat = store.getSource().sourceFormat;

  if (dim != null) {
    var dimIndex = data.getDimensionIndex(dim);
    var property = store.getDimensionProperty(dimIndex);
    return getRawSourceValueGetter(sourceFormat)(dataItem, dimIndex, property);
  } else {
    var result = dataItem;

    if (sourceFormat === SOURCE_FORMAT_ORIGINAL) {
      result = getDataItemValue(dataItem);
    }

    return result;
  }
}
/* Injected with object hook! */

var DIMENSION_LABEL_REG = /\{@(.+?)\}/g;

var DataFormatMixin =
/** @class */
function () {
  function DataFormatMixin() {}
  /**
   * Get params for formatter
   */


  DataFormatMixin.prototype.getDataParams = function (dataIndex, dataType) {
    var data = this.getData(dataType);
    var rawValue = this.getRawValue(dataIndex, dataType);
    var rawDataIndex = data.getRawIndex(dataIndex);
    var name = data.getName(dataIndex);
    var itemOpt = data.getRawDataItem(dataIndex);
    var style = data.getItemVisual(dataIndex, 'style');
    var color = style && style[data.getItemVisual(dataIndex, 'drawType') || 'fill'];
    var borderColor = style && style.stroke;
    var mainType = this.mainType;
    var isSeries = mainType === 'series';
    var userOutput = data.userOutput && data.userOutput.get();
    return {
      componentType: mainType,
      componentSubType: this.subType,
      componentIndex: this.componentIndex,
      seriesType: isSeries ? this.subType : null,
      seriesIndex: this.seriesIndex,
      seriesId: isSeries ? this.id : null,
      seriesName: isSeries ? this.name : null,
      name: name,
      dataIndex: rawDataIndex,
      data: itemOpt,
      dataType: dataType,
      value: rawValue,
      color: color,
      borderColor: borderColor,
      dimensionNames: userOutput ? userOutput.fullDimensions : null,
      encode: userOutput ? userOutput.encode : null,
      // Param name list for mapping `a`, `b`, `c`, `d`, `e`
      $vars: ['seriesName', 'name', 'value']
    };
  };
  /**
   * Format label
   * @param dataIndex
   * @param status 'normal' by default
   * @param dataType
   * @param labelDimIndex Only used in some chart that
   *        use formatter in different dimensions, like radar.
   * @param formatter Formatter given outside.
   * @return return null/undefined if no formatter
   */


  DataFormatMixin.prototype.getFormattedLabel = function (dataIndex, status, dataType, labelDimIndex, formatter, extendParams) {
    status = status || 'normal';
    var data = this.getData(dataType);
    var params = this.getDataParams(dataIndex, dataType);

    if (extendParams) {
      params.value = extendParams.interpolatedValue;
    }

    if (labelDimIndex != null && isArray(params.value)) {
      params.value = params.value[labelDimIndex];
    }

    if (!formatter) {
      var itemModel = data.getItemModel(dataIndex); // @ts-ignore

      formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : [status, 'label', 'formatter']);
    }

    if (isFunction(formatter)) {
      params.status = status;
      params.dimensionIndex = labelDimIndex;
      return formatter(params);
    } else if (isString(formatter)) {
      var str = formatTpl(formatter, params); // Support 'aaa{@[3]}bbb{@product}ccc'.
      // Do not support '}' in dim name util have to.

      return str.replace(DIMENSION_LABEL_REG, function (origin, dimStr) {
        var len = dimStr.length;
        var dimLoose = dimStr;

        if (dimLoose.charAt(0) === '[' && dimLoose.charAt(len - 1) === ']') {
          dimLoose = +dimLoose.slice(1, len - 1); // Also support: '[]' => 0
        }

        var val = retrieveRawValue(data, dataIndex, dimLoose);

        if (extendParams && isArray(extendParams.interpolatedValue)) {
          var dimIndex = data.getDimensionIndex(dimLoose);

          if (dimIndex >= 0) {
            val = extendParams.interpolatedValue[dimIndex];
          }
        }

        return val != null ? val + '' : '';
      });
    }
  };
  /**
   * Get raw value in option
   */


  DataFormatMixin.prototype.getRawValue = function (idx, dataType) {
    return retrieveRawValue(this.getData(dataType), idx);
  };
  /**
   * Should be implemented.
   * @param {number} dataIndex
   * @param {boolean} [multipleSeries=false]
   * @param {string} [dataType]
   */


  DataFormatMixin.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
    // Empty function
    return;
  };

  return DataFormatMixin;
}();
// but guess little chance has been used outside. Do we need to backward
// compat it?
// type TooltipFormatResultLegacyObject = {
//     // `html` means the markup language text, either in 'html' or 'richText'.
//     // The name `html` is not appropriate because in 'richText' it is not a HTML
//     // string. But still support it for backward compatibility.
//     html: string;
//     markers: Dictionary<ColorString>;
// };

/**
 * For backward compat, normalize the return from `formatTooltip`.
 */

function normalizeTooltipFormatResult(result) {
  var markupText; // let markers: Dictionary<ColorString>;

  var markupFragment;

  if (isObject$2(result)) {
    if (result.type) {
      markupFragment = result;
    } // else {
    //     markupText = (result as TooltipFormatResultLegacyObject).html;
    //     markers = (result as TooltipFormatResultLegacyObject).markers;
    //     if (markersExisting) {
    //         markers = zrUtil.merge(markersExisting, markers);
    //     }
    // }

  } else {
    markupText = result;
  }

  return {
    text: markupText,
    // markers: markers || markersExisting,
    frag: markupFragment
  };
}
/* Injected with object hook! */

/**
 * @param {Object} define
 * @return See the return of `createTask`.
 */

function createTask(define) {
  return new Task(define);
}

var Task =
/** @class */
function () {
  function Task(define) {
    define = define || {};
    this._reset = define.reset;
    this._plan = define.plan;
    this._count = define.count;
    this._onDirty = define.onDirty;
    this._dirty = true;
  }
  /**
   * @param step Specified step.
   * @param skip Skip customer perform call.
   * @param modBy Sampling window size.
   * @param modDataCount Sampling count.
   * @return whether unfinished.
   */


  Task.prototype.perform = function (performArgs) {
    var upTask = this._upstream;
    var skip = performArgs && performArgs.skip; // TODO some refactor.
    // Pull data. Must pull data each time, because context.data
    // may be updated by Series.setData.

    if (this._dirty && upTask) {
      var context = this.context;
      context.data = context.outputData = upTask.context.outputData;
    }

    if (this.__pipeline) {
      this.__pipeline.currentTask = this;
    }

    var planResult;

    if (this._plan && !skip) {
      planResult = this._plan(this.context);
    } // Support sharding by mod, which changes the render sequence and makes the rendered graphic
    // elements uniformed distributed when progress, especially when moving or zooming.


    var lastModBy = normalizeModBy(this._modBy);
    var lastModDataCount = this._modDataCount || 0;
    var modBy = normalizeModBy(performArgs && performArgs.modBy);
    var modDataCount = performArgs && performArgs.modDataCount || 0;

    if (lastModBy !== modBy || lastModDataCount !== modDataCount) {
      planResult = 'reset';
    }

    function normalizeModBy(val) {
      !(val >= 1) && (val = 1); // jshint ignore:line

      return val;
    }

    var forceFirstProgress;

    if (this._dirty || planResult === 'reset') {
      this._dirty = false;
      forceFirstProgress = this._doReset(skip);
    }

    this._modBy = modBy;
    this._modDataCount = modDataCount;
    var step = performArgs && performArgs.step;

    if (upTask) {

      this._dueEnd = upTask._outputDueEnd;
    } // DataTask or overallTask
    else {

        this._dueEnd = this._count ? this._count(this.context) : Infinity;
      } // Note: Stubs, that its host overall task let it has progress, has progress.
    // If no progress, pass index from upstream to downstream each time plan called.


    if (this._progress) {
      var start = this._dueIndex;
      var end = Math.min(step != null ? this._dueIndex + step : Infinity, this._dueEnd);

      if (!skip && (forceFirstProgress || start < end)) {
        var progress = this._progress;

        if (isArray(progress)) {
          for (var i = 0; i < progress.length; i++) {
            this._doProgress(progress[i], start, end, modBy, modDataCount);
          }
        } else {
          this._doProgress(progress, start, end, modBy, modDataCount);
        }
      }

      this._dueIndex = end; // If no `outputDueEnd`, assume that output data and
      // input data is the same, so use `dueIndex` as `outputDueEnd`.

      var outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : end;

      this._outputDueEnd = outputDueEnd;
    } else {
      // (1) Some overall task has no progress.
      // (2) Stubs, that its host overall task do not let it has progress, has no progress.
      // This should always be performed so it can be passed to downstream.
      this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : this._dueEnd;
    }

    return this.unfinished();
  };

  Task.prototype.dirty = function () {
    this._dirty = true;
    this._onDirty && this._onDirty(this.context);
  };

  Task.prototype._doProgress = function (progress, start, end, modBy, modDataCount) {
    iterator.reset(start, end, modBy, modDataCount);
    this._callingProgress = progress;

    this._callingProgress({
      start: start,
      end: end,
      count: end - start,
      next: iterator.next
    }, this.context);
  };

  Task.prototype._doReset = function (skip) {
    this._dueIndex = this._outputDueEnd = this._dueEnd = 0;
    this._settedOutputEnd = null;
    var progress;
    var forceFirstProgress;

    if (!skip && this._reset) {
      progress = this._reset(this.context);

      if (progress && progress.progress) {
        forceFirstProgress = progress.forceFirstProgress;
        progress = progress.progress;
      } // To simplify no progress checking, array must has item.


      if (isArray(progress) && !progress.length) {
        progress = null;
      }
    }

    this._progress = progress;
    this._modBy = this._modDataCount = null;
    var downstream = this._downstream;
    downstream && downstream.dirty();
    return forceFirstProgress;
  };

  Task.prototype.unfinished = function () {
    return this._progress && this._dueIndex < this._dueEnd;
  };
  /**
   * @param downTask The downstream task.
   * @return The downstream task.
   */


  Task.prototype.pipe = function (downTask) {


    if (this._downstream !== downTask || this._dirty) {
      this._downstream = downTask;
      downTask._upstream = this;
      downTask.dirty();
    }
  };

  Task.prototype.dispose = function () {
    if (this._disposed) {
      return;
    }

    this._upstream && (this._upstream._downstream = null);
    this._downstream && (this._downstream._upstream = null);
    this._dirty = false;
    this._disposed = true;
  };

  Task.prototype.getUpstream = function () {
    return this._upstream;
  };

  Task.prototype.getDownstream = function () {
    return this._downstream;
  };

  Task.prototype.setOutputEnd = function (end) {
    // This only happens in dataTask, dataZoom, map, currently.
    // where dataZoom do not set end each time, but only set
    // when reset. So we should record the set end, in case
    // that the stub of dataZoom perform again and earse the
    // set end by upstream.
    this._outputDueEnd = this._settedOutputEnd = end;
  };

  return Task;
}();

var iterator = function () {
  var end;
  var current;
  var modBy;
  var modDataCount;
  var winCount;
  var it = {
    reset: function (s, e, sStep, sCount) {
      current = s;
      end = e;
      modBy = sStep;
      modDataCount = sCount;
      winCount = Math.ceil(modDataCount / modBy);
      it.next = modBy > 1 && modDataCount > 0 ? modNext : sequentialNext;
    }
  };
  return it;

  function sequentialNext() {
    return current < end ? current++ : null;
  }

  function modNext() {
    var dataIndex = current % winCount * modBy + Math.ceil(current / winCount);
    var result = current >= end ? null : dataIndex < modDataCount ? dataIndex // If modDataCount is smaller than data.count() (consider `appendData` case),
    // Use normal linear rendering mode.
    : current;
    current++;
    return result;
  }
}(); // -----------------------------------------------------------------------------
// For stream debug (Should be commented out after used!)
// @usage: printTask(this, 'begin');
// @usage: printTask(this, null, {someExtraProp});
// @usage: Use `__idxInPipeline` as conditional breakpiont.
//
// window.printTask = function (task: any, prefix: string, extra: { [key: string]: unknown }): void {
//     window.ecTaskUID == null && (window.ecTaskUID = 0);
//     task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`);
//     task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`);
//     let props = [];
//     if (task.__pipeline) {
//         let val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`;
//         props.push({text: '__idxInPipeline/total', value: val});
//     } else {
//         let stubCount = 0;
//         task.agentStubMap.each(() => stubCount++);
//         props.push({text: 'idx', value: `overall (stubs: ${stubCount})`});
//     }
//     props.push({text: 'uid', value: task.uidDebug});
//     if (task.__pipeline) {
//         props.push({text: 'pipelineId', value: task.__pipeline.id});
//         task.agent && props.push(
//             {text: 'stubFor', value: task.agent.uidDebug}
//         );
//     }
//     props.push(
//         {text: 'dirty', value: task._dirty},
//         {text: 'dueIndex', value: task._dueIndex},
//         {text: 'dueEnd', value: task._dueEnd},
//         {text: 'outputDueEnd', value: task._outputDueEnd}
//     );
//     if (extra) {
//         Object.keys(extra).forEach(key => {
//             props.push({text: key, value: extra[key]});
//         });
//     }
//     let args = ['color: blue'];
//     let msg = `%c[${prefix || 'T'}] %c` + props.map(item => (
//         args.push('color: green', 'color: red'),
//         `${item.text}: %c${item.value}`
//     )).join('%c, ');
//     console.log.apply(console, [msg].concat(args));
//     // console.log(this);
// };
// window.printPipeline = function (task: any, prefix: string) {
//     const pipeline = task.__pipeline;
//     let currTask = pipeline.head;
//     while (currTask) {
//         window.printTask(currTask, prefix);
//         currTask = currTask._downstream;
//     }
// };
// window.showChain = function (chainHeadTask) {
//     var chain = [];
//     var task = chainHeadTask;
//     while (task) {
//         chain.push({
//             task: task,
//             up: task._upstream,
//             down: task._downstream,
//             idxInPipeline: task.__idxInPipeline
//         });
//         task = task._downstream;
//     }
//     return chain;
// };
// window.findTaskInChain = function (task, chainHeadTask) {
//     let chain = window.showChain(chainHeadTask);
//     let result = [];
//     for (let i = 0; i < chain.length; i++) {
//         let chainItem = chain[i];
//         if (chainItem.task === task) {
//             result.push(i);
//         }
//     }
//     return result;
// };
// window.printChainAEachInChainB = function (chainHeadTaskA, chainHeadTaskB) {
//     let chainA = window.showChain(chainHeadTaskA);
//     for (let i = 0; i < chainA.length; i++) {
//         console.log('chainAIdx:', i, 'inChainB:', window.findTaskInChain(chainA[i].task, chainHeadTaskB));
//     }
// };
/* Injected with object hook! */

/**
 * Convert raw the value in to inner value in List.
 *
 * [Performance sensitive]
 *
 * [Caution]: this is the key logic of user value parser.
 * For backward compatibility, do not modify it until you have to!
 */

function parseDataValue(value, // For high performance, do not omit the second param.
opt) {
  // Performance sensitive.
  var dimType = opt && opt.type;

  if (dimType === 'ordinal') {
    // If given value is a category string
    return value;
  }

  if (dimType === 'time' // spead up when using timestamp
  && !isNumber(value) && value != null && value !== '-') {
    value = +parseDate(value);
  } // dimType defaults 'number'.
  // If dimType is not ordinal and value is null or undefined or NaN or '-',
  // parse to NaN.
  // number-like string (like ' 123 ') can be converted to a number.
  // where null/undefined or other string will be converted to NaN.


  return value == null || value === '' ? NaN // If string (like '-'), using '+' parse to NaN
  // If object, also parse to NaN
  : +value;
}
createHashMap({
  'number': function (val) {
    // Do not use `numericToNumber` here. We have `numericToNumber` by default.
    // Here the number parser can have loose rule:
    // enable to cut suffix: "120px" => 120, "14%" => 14.
    return parseFloat(val);
  },
  'time': function (val) {
    // return timestamp.
    return +parseDate(val);
  },
  'trim': function (val) {
    return isString(val) ? trim(val) : val;
  }
});

var SortOrderComparator =
/** @class */
function () {
  /**
   * @param order by default: 'asc'
   * @param incomparable by default: Always on the tail.
   *        That is, if 'asc' => 'max', if 'desc' => 'min'
   *        See the definition of "incomparable" in [SORT_COMPARISON_RULE].
   */
  function SortOrderComparator(order, incomparable) {
    var isDesc = order === 'desc';
    this._resultLT = isDesc ? 1 : -1;

    if (incomparable == null) {
      incomparable = isDesc ? 'min' : 'max';
    }

    this._incomparable = incomparable === 'min' ? -Infinity : Infinity;
  } // See [SORT_COMPARISON_RULE].
  // Performance sensitive.


  SortOrderComparator.prototype.evaluate = function (lval, rval) {
    // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat.
    var lvalFloat = isNumber(lval) ? lval : numericToNumber(lval);
    var rvalFloat = isNumber(rval) ? rval : numericToNumber(rval);
    var lvalNotNumeric = isNaN(lvalFloat);
    var rvalNotNumeric = isNaN(rvalFloat);

    if (lvalNotNumeric) {
      lvalFloat = this._incomparable;
    }

    if (rvalNotNumeric) {
      rvalFloat = this._incomparable;
    }

    if (lvalNotNumeric && rvalNotNumeric) {
      var lvalIsStr = isString(lval);
      var rvalIsStr = isString(rval);

      if (lvalIsStr) {
        lvalFloat = rvalIsStr ? lval : 0;
      }

      if (rvalIsStr) {
        rvalFloat = lvalIsStr ? rval : 0;
      }
    }

    return lvalFloat < rvalFloat ? this._resultLT : lvalFloat > rvalFloat ? -this._resultLT : 0;
  };

  return SortOrderComparator;
}();
/* Injected with object hook! */

/**
 * TODO: disable writable.
 * This structure will be exposed to users.
 */

var ExternalSource =
/** @class */
function () {
  function ExternalSource() {}

  ExternalSource.prototype.getRawData = function () {
    // Only built-in transform available.
    throw new Error('not supported');
  };

  ExternalSource.prototype.getRawDataItem = function (dataIndex) {
    // Only built-in transform available.
    throw new Error('not supported');
  };

  ExternalSource.prototype.cloneRawData = function () {
    return;
  };
  /**
   * @return If dimension not found, return null/undefined.
   */


  ExternalSource.prototype.getDimensionInfo = function (dim) {
    return;
  };
  /**
   * dimensions defined if and only if either:
   * (a) dataset.dimensions are declared.
   * (b) dataset data include dimensions definitions in data (detected or via specified `sourceHeader`).
   * If dimensions are defined, `dimensionInfoAll` is corresponding to
   * the defined dimensions.
   * Otherwise, `dimensionInfoAll` is determined by data columns.
   * @return Always return an array (even empty array).
   */


  ExternalSource.prototype.cloneAllDimensionInfo = function () {
    return;
  };

  ExternalSource.prototype.count = function () {
    return;
  };
  /**
   * Only support by dimension index.
   * No need to support by dimension name in transform function,
   * because transform function is not case-specific, no need to use name literally.
   */


  ExternalSource.prototype.retrieveValue = function (dataIndex, dimIndex) {
    return;
  };

  ExternalSource.prototype.retrieveValueFromItem = function (dataItem, dimIndex) {
    return;
  };

  ExternalSource.prototype.convertValue = function (rawVal, dimInfo) {
    return parseDataValue(rawVal, dimInfo);
  };

  return ExternalSource;
}();

function createExternalSource(internalSource, externalTransform) {
  var extSource = new ExternalSource();
  var data = internalSource.data;
  var sourceFormat = extSource.sourceFormat = internalSource.sourceFormat;
  var sourceHeaderCount = internalSource.startIndex;
  var errMsg = '';

  if (internalSource.seriesLayoutBy !== SERIES_LAYOUT_BY_COLUMN) {

    throwError(errMsg);
  } // [MEMO]
  // Create a new dimensions structure for exposing.
  // Do not expose all dimension info to users directly.
  // Because the dimension is probably auto detected from data and not might reliable.
  // Should not lead the transformers to think that is reliable and return it.
  // See [DIMENSION_INHERIT_RULE] in `sourceManager.ts`.


  var dimensions = [];
  var dimsByName = {};
  var dimsDef = internalSource.dimensionsDefine;

  if (dimsDef) {
    each$4(dimsDef, function (dimDef, idx) {
      var name = dimDef.name;
      var dimDefExt = {
        index: idx,
        name: name,
        displayName: dimDef.displayName
      };
      dimensions.push(dimDefExt); // Users probably do not specify dimension name. For simplicity, data transform
      // does not generate dimension name.

      if (name != null) {
        // Dimension name should not be duplicated.
        // For simplicity, data transform forbids name duplication, do not generate
        // new name like module `completeDimensions.ts` did, but just tell users.
        var errMsg_1 = '';

        if (hasOwn(dimsByName, name)) {

          throwError(errMsg_1);
        }

        dimsByName[name] = dimDefExt;
      }
    });
  } // If dimension definitions are not defined and can not be detected.
  // e.g., pure data `[[11, 22], ...]`.
  else {
      for (var i = 0; i < internalSource.dimensionsDetectedCount || 0; i++) {
        // Do not generete name or anything others. The consequence process in
        // `transform` or `series` probably have there own name generation strategry.
        dimensions.push({
          index: i
        });
      }
    } // Implement public methods:


  var rawItemGetter = getRawSourceItemGetter(sourceFormat, SERIES_LAYOUT_BY_COLUMN);

  if (externalTransform.__isBuiltIn) {
    extSource.getRawDataItem = function (dataIndex) {
      return rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex);
    };

    extSource.getRawData = bind$1(getRawData, null, internalSource);
  }

  extSource.cloneRawData = bind$1(cloneRawData, null, internalSource);
  var rawCounter = getRawSourceDataCounter(sourceFormat, SERIES_LAYOUT_BY_COLUMN);
  extSource.count = bind$1(rawCounter, null, data, sourceHeaderCount, dimensions);
  var rawValueGetter = getRawSourceValueGetter(sourceFormat);

  extSource.retrieveValue = function (dataIndex, dimIndex) {
    var rawItem = rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex);
    return retrieveValueFromItem(rawItem, dimIndex);
  };

  var retrieveValueFromItem = extSource.retrieveValueFromItem = function (dataItem, dimIndex) {
    if (dataItem == null) {
      return;
    }

    var dimDef = dimensions[dimIndex]; // When `dimIndex` is `null`, `rawValueGetter` return the whole item.

    if (dimDef) {
      return rawValueGetter(dataItem, dimIndex, dimDef.name);
    }
  };

  extSource.getDimensionInfo = bind$1(getDimensionInfo, null, dimensions, dimsByName);
  extSource.cloneAllDimensionInfo = bind$1(cloneAllDimensionInfo, null, dimensions);
  return extSource;
}

function getRawData(upstream) {
  var sourceFormat = upstream.sourceFormat;

  if (!isSupportedSourceFormat(sourceFormat)) {
    var errMsg = '';

    throwError(errMsg);
  }

  return upstream.data;
}

function cloneRawData(upstream) {
  var sourceFormat = upstream.sourceFormat;
  var data = upstream.data;

  if (!isSupportedSourceFormat(sourceFormat)) {
    var errMsg = '';

    throwError(errMsg);
  }

  if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
    var result = [];

    for (var i = 0, len = data.length; i < len; i++) {
      // Not strictly clone for performance
      result.push(data[i].slice());
    }

    return result;
  } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
    var result = [];

    for (var i = 0, len = data.length; i < len; i++) {
      // Not strictly clone for performance
      result.push(extend({}, data[i]));
    }

    return result;
  }
}

function getDimensionInfo(dimensions, dimsByName, dim) {
  if (dim == null) {
    return;
  } // Keep the same logic as `List::getDimension` did.


  if (isNumber(dim) // If being a number-like string but not being defined a dimension name.
  || !isNaN(dim) && !hasOwn(dimsByName, dim)) {
    return dimensions[dim];
  } else if (hasOwn(dimsByName, dim)) {
    return dimsByName[dim];
  }
}

function cloneAllDimensionInfo(dimensions) {
  return clone$2(dimensions);
}

var externalTransformMap = createHashMap();
function registerExternalTransform(externalTransform) {
  externalTransform = clone$2(externalTransform);
  var type = externalTransform.type;
  var errMsg = '';

  if (!type) {

    throwError(errMsg);
  }

  var typeParsed = type.split(':');

  if (typeParsed.length !== 2) {

    throwError(errMsg);
  } // Namespace 'echarts:xxx' is official namespace, where the transforms should
  // be called directly via 'xxx' rather than 'echarts:xxx'.


  var isBuiltIn = false;

  if (typeParsed[0] === 'echarts') {
    type = typeParsed[1];
    isBuiltIn = true;
  }

  externalTransform.__isBuiltIn = isBuiltIn;
  externalTransformMap.set(type, externalTransform);
}
function applyDataTransform(rawTransOption, sourceList, infoForPrint) {
  var pipedTransOption = normalizeToArray(rawTransOption);
  var pipeLen = pipedTransOption.length;
  var errMsg = '';

  if (!pipeLen) {

    throwError(errMsg);
  }

  for (var i = 0, len = pipeLen; i < len; i++) {
    var transOption = pipedTransOption[i];
    sourceList = applySingleDataTransform(transOption, sourceList); // piped transform only support single input, except the fist one.
    // piped transform only support single output, except the last one.

    if (i !== len - 1) {
      sourceList.length = Math.max(sourceList.length, 1);
    }
  }

  return sourceList;
}

function applySingleDataTransform(transOption, upSourceList, infoForPrint, // If `pipeIndex` is null/undefined, no piped transform.
pipeIndex) {
  var errMsg = '';

  if (!upSourceList.length) {

    throwError(errMsg);
  }

  if (!isObject$2(transOption)) {

    throwError(errMsg);
  }

  var transType = transOption.type;
  var externalTransform = externalTransformMap.get(transType);

  if (!externalTransform) {

    throwError(errMsg);
  } // Prepare source


  var extUpSourceList = map$1(upSourceList, function (upSource) {
    return createExternalSource(upSource, externalTransform);
  });
  var resultList = normalizeToArray(externalTransform.transform({
    upstream: extUpSourceList[0],
    upstreamList: extUpSourceList,
    config: clone$2(transOption.config)
  }));

  return map$1(resultList, function (result, resultIndex) {
    var errMsg = '';

    if (!isObject$2(result)) {

      throwError(errMsg);
    }

    if (!result.data) {

      throwError(errMsg);
    }

    var sourceFormat = detectSourceFormat(result.data);

    if (!isSupportedSourceFormat(sourceFormat)) {

      throwError(errMsg);
    }

    var resultMetaRawOption;
    var firstUpSource = upSourceList[0];
    /**
     * Intuitively, the end users known the content of the original `dataset.source`,
     * calucating the transform result in mind.
     * Suppose the original `dataset.source` is:
     * ```js
     * [
     *     ['product', '2012', '2013', '2014', '2015'],
     *     ['AAA', 41.1, 30.4, 65.1, 53.3],
     *     ['BBB', 86.5, 92.1, 85.7, 83.1],
     *     ['CCC', 24.1, 67.2, 79.5, 86.4]
     * ]
     * ```
     * The dimension info have to be detected from the source data.
     * Some of the transformers (like filter, sort) will follow the dimension info
     * of upstream, while others use new dimensions (like aggregate).
     * Transformer can output a field `dimensions` to define the its own output dimensions.
     * We also allow transformers to ignore the output `dimensions` field, and
     * inherit the upstream dimensions definition. It can reduce the burden of handling
     * dimensions in transformers.
     *
     * See also [DIMENSION_INHERIT_RULE] in `sourceManager.ts`.
     */

    if (firstUpSource && resultIndex === 0 // If transformer returns `dimensions`, it means that the transformer has different
    // dimensions definitions. We do not inherit anything from upstream.
    && !result.dimensions) {
      var startIndex = firstUpSource.startIndex; // We copy the header of upstream to the result, because:
      // (1) The returned data always does not contain header line and can not be used
      // as dimension-detection. In this case we can not use "detected dimensions" of
      // upstream directly, because it might be detected based on different `seriesLayoutBy`.
      // (2) We should support that the series read the upstream source in `seriesLayoutBy: 'row'`.
      // So the original detected header should be add to the result, otherwise they can not be read.

      if (startIndex) {
        result.data = firstUpSource.data.slice(0, startIndex).concat(result.data);
      }

      resultMetaRawOption = {
        seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN,
        sourceHeader: startIndex,
        dimensions: firstUpSource.metaRawOption.dimensions
      };
    } else {
      resultMetaRawOption = {
        seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN,
        sourceHeader: 0,
        dimensions: result.dimensions
      };
    }

    return createSource(result.data, resultMetaRawOption, null);
  });
}

function isSupportedSourceFormat(sourceFormat) {
  return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS || sourceFormat === SOURCE_FORMAT_OBJECT_ROWS;
}
/* Injected with object hook! */

var UNDEFINED = 'undefined';
/* global Float64Array, Int32Array, Uint32Array, Uint16Array */
// Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is
// different from the Ctor of typed array.

var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array;
var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array;
var CtorInt32Array$1 = typeof Int32Array === UNDEFINED ? Array : Int32Array;
var CtorFloat64Array = typeof Float64Array === UNDEFINED ? Array : Float64Array;
/**
 * Multi dimensional data store
 */

var dataCtors = {
  'float': CtorFloat64Array,
  'int': CtorInt32Array$1,
  // Ordinal data type can be string or int
  'ordinal': Array,
  'number': Array,
  'time': CtorFloat64Array
};
var defaultDimValueGetters;

function getIndicesCtor(rawCount) {
  // The possible max value in this._indicies is always this._rawCount despite of filtering.
  return rawCount > 65535 ? CtorUint32Array : CtorUint16Array;
}

function getInitialExtent() {
  return [Infinity, -Infinity];
}

function cloneChunk(originalChunk) {
  var Ctor = originalChunk.constructor; // Only shallow clone is enough when Array.

  return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk);
}

function prepareStore(store, dimIdx, dimType, end, append) {
  var DataCtor = dataCtors[dimType || 'float'];

  if (append) {
    var oldStore = store[dimIdx];
    var oldLen = oldStore && oldStore.length;

    if (!(oldLen === end)) {
      var newStore = new DataCtor(end); // The cost of the copy is probably inconsiderable
      // within the initial chunkSize.

      for (var j = 0; j < oldLen; j++) {
        newStore[j] = oldStore[j];
      }

      store[dimIdx] = newStore;
    }
  } else {
    store[dimIdx] = new DataCtor(end);
  }
}
/**
 * Basically, DataStore API keep immutable.
 */

var DataStore =
/** @class */
function () {
  function DataStore() {
    this._chunks = []; // It will not be calculated until needed.

    this._rawExtent = [];
    this._extent = [];
    this._count = 0;
    this._rawCount = 0;
    this._calcDimNameToIdx = createHashMap();
  }
  /**
   * Initialize from data
   */


  DataStore.prototype.initData = function (provider, inputDimensions, dimValueGetter) {

    this._provider = provider; // Clear

    this._chunks = [];
    this._indices = null;
    this.getRawIndex = this._getRawIdxIdentity;
    var source = provider.getSource();
    var defaultGetter = this.defaultDimValueGetter = defaultDimValueGetters[source.sourceFormat]; // Default dim value getter

    this._dimValueGetter = dimValueGetter || defaultGetter; // Reset raw extent.

    this._rawExtent = [];
    shouldRetrieveDataByName(source);
    this._dimensions = map$1(inputDimensions, function (dim) {

      return {
        // Only pick these two props. Not leak other properties like orderMeta.
        type: dim.type,
        property: dim.property
      };
    });

    this._initDataFromProvider(0, provider.count());
  };

  DataStore.prototype.getProvider = function () {
    return this._provider;
  };
  /**
   * Caution: even when a `source` instance owned by a series, the created data store
   * may still be shared by different sereis (the source hash does not use all `source`
   * props, see `sourceManager`). In this case, the `source` props that are not used in
   * hash (like `source.dimensionDefine`) probably only belongs to a certain series and
   * thus should not be fetch here.
   */


  DataStore.prototype.getSource = function () {
    return this._provider.getSource();
  };
  /**
   * @caution Only used in dataStack.
   */


  DataStore.prototype.ensureCalculationDimension = function (dimName, type) {
    var calcDimNameToIdx = this._calcDimNameToIdx;
    var dimensions = this._dimensions;
    var calcDimIdx = calcDimNameToIdx.get(dimName);

    if (calcDimIdx != null) {
      if (dimensions[calcDimIdx].type === type) {
        return calcDimIdx;
      }
    } else {
      calcDimIdx = dimensions.length;
    }

    dimensions[calcDimIdx] = {
      type: type
    };
    calcDimNameToIdx.set(dimName, calcDimIdx);
    this._chunks[calcDimIdx] = new dataCtors[type || 'float'](this._rawCount);
    this._rawExtent[calcDimIdx] = getInitialExtent();
    return calcDimIdx;
  };

  DataStore.prototype.collectOrdinalMeta = function (dimIdx, ordinalMeta) {
    var chunk = this._chunks[dimIdx];
    var dim = this._dimensions[dimIdx];
    var rawExtents = this._rawExtent;
    var offset = dim.ordinalOffset || 0;
    var len = chunk.length;

    if (offset === 0) {
      // We need to reset the rawExtent if collect is from start.
      // Because this dimension may be guessed as number and calcuating a wrong extent.
      rawExtents[dimIdx] = getInitialExtent();
    }

    var dimRawExtent = rawExtents[dimIdx]; // Parse from previous data offset. len may be changed after appendData

    for (var i = offset; i < len; i++) {
      var val = chunk[i] = ordinalMeta.parseAndCollect(chunk[i]);

      if (!isNaN(val)) {
        dimRawExtent[0] = Math.min(val, dimRawExtent[0]);
        dimRawExtent[1] = Math.max(val, dimRawExtent[1]);
      }
    }

    dim.ordinalMeta = ordinalMeta;
    dim.ordinalOffset = len;
    dim.type = 'ordinal'; // Force to be ordinal
  };

  DataStore.prototype.getOrdinalMeta = function (dimIdx) {
    var dimInfo = this._dimensions[dimIdx];
    var ordinalMeta = dimInfo.ordinalMeta;
    return ordinalMeta;
  };

  DataStore.prototype.getDimensionProperty = function (dimIndex) {
    var item = this._dimensions[dimIndex];
    return item && item.property;
  };
  /**
   * Caution: Can be only called on raw data (before `this._indices` created).
   */


  DataStore.prototype.appendData = function (data) {

    var provider = this._provider;
    var start = this.count();
    provider.appendData(data);
    var end = provider.count();

    if (!provider.persistent) {
      end += start;
    }

    if (start < end) {
      this._initDataFromProvider(start, end, true);
    }

    return [start, end];
  };

  DataStore.prototype.appendValues = function (values, minFillLen) {
    var chunks = this._chunks;
    var dimensions = this._dimensions;
    var dimLen = dimensions.length;
    var rawExtent = this._rawExtent;
    var start = this.count();
    var end = start + Math.max(values.length, minFillLen || 0);

    for (var i = 0; i < dimLen; i++) {
      var dim = dimensions[i];
      prepareStore(chunks, i, dim.type, end, true);
    }

    var emptyDataItem = [];

    for (var idx = start; idx < end; idx++) {
      var sourceIdx = idx - start; // Store the data by dimensions

      for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) {
        var dim = dimensions[dimIdx];
        var val = defaultDimValueGetters.arrayRows.call(this, values[sourceIdx] || emptyDataItem, dim.property, sourceIdx, dimIdx);
        chunks[dimIdx][idx] = val;
        var dimRawExtent = rawExtent[dimIdx];
        val < dimRawExtent[0] && (dimRawExtent[0] = val);
        val > dimRawExtent[1] && (dimRawExtent[1] = val);
      }
    }

    this._rawCount = this._count = end;
    return {
      start: start,
      end: end
    };
  };

  DataStore.prototype._initDataFromProvider = function (start, end, append) {
    var provider = this._provider;
    var chunks = this._chunks;
    var dimensions = this._dimensions;
    var dimLen = dimensions.length;
    var rawExtent = this._rawExtent;
    var dimNames = map$1(dimensions, function (dim) {
      return dim.property;
    });

    for (var i = 0; i < dimLen; i++) {
      var dim = dimensions[i];

      if (!rawExtent[i]) {
        rawExtent[i] = getInitialExtent();
      }

      prepareStore(chunks, i, dim.type, end, append);
    }

    if (provider.fillStorage) {
      provider.fillStorage(start, end, chunks, rawExtent);
    } else {
      var dataItem = [];

      for (var idx = start; idx < end; idx++) {
        // NOTICE: Try not to write things into dataItem
        dataItem = provider.getItem(idx, dataItem); // Each data item is value
        // [1, 2]
        // 2
        // Bar chart, line chart which uses category axis
        // only gives the 'y' value. 'x' value is the indices of category
        // Use a tempValue to normalize the value to be a (x, y) value
        // Store the data by dimensions

        for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) {
          var dimStorage = chunks[dimIdx]; // PENDING NULL is empty or zero

          var val = this._dimValueGetter(dataItem, dimNames[dimIdx], idx, dimIdx);

          dimStorage[idx] = val;
          var dimRawExtent = rawExtent[dimIdx];
          val < dimRawExtent[0] && (dimRawExtent[0] = val);
          val > dimRawExtent[1] && (dimRawExtent[1] = val);
        }
      }
    }

    if (!provider.persistent && provider.clean) {
      // Clean unused data if data source is typed array.
      provider.clean();
    }

    this._rawCount = this._count = end; // Reset data extent

    this._extent = [];
  };

  DataStore.prototype.count = function () {
    return this._count;
  };
  /**
   * Get value. Return NaN if idx is out of range.
   */


  DataStore.prototype.get = function (dim, idx) {
    if (!(idx >= 0 && idx < this._count)) {
      return NaN;
    }

    var dimStore = this._chunks[dim];
    return dimStore ? dimStore[this.getRawIndex(idx)] : NaN;
  };

  DataStore.prototype.getValues = function (dimensions, idx) {
    var values = [];
    var dimArr = [];

    if (idx == null) {
      idx = dimensions; // TODO get all from store?

      dimensions = []; // All dimensions

      for (var i = 0; i < this._dimensions.length; i++) {
        dimArr.push(i);
      }
    } else {
      dimArr = dimensions;
    }

    for (var i = 0, len = dimArr.length; i < len; i++) {
      values.push(this.get(dimArr[i], idx));
    }

    return values;
  };
  /**
   * @param dim concrete dim
   */


  DataStore.prototype.getByRawIndex = function (dim, rawIdx) {
    if (!(rawIdx >= 0 && rawIdx < this._rawCount)) {
      return NaN;
    }

    var dimStore = this._chunks[dim];
    return dimStore ? dimStore[rawIdx] : NaN;
  };
  /**
   * Get sum of data in one dimension
   */


  DataStore.prototype.getSum = function (dim) {
    var dimData = this._chunks[dim];
    var sum = 0;

    if (dimData) {
      for (var i = 0, len = this.count(); i < len; i++) {
        var value = this.get(dim, i);

        if (!isNaN(value)) {
          sum += value;
        }
      }
    }

    return sum;
  };
  /**
   * Get median of data in one dimension
   */


  DataStore.prototype.getMedian = function (dim) {
    var dimDataArray = []; // map all data of one dimension

    this.each([dim], function (val) {
      if (!isNaN(val)) {
        dimDataArray.push(val);
      }
    }); // TODO
    // Use quick select?

    var sortedDimDataArray = dimDataArray.sort(function (a, b) {
      return a - b;
    });
    var len = this.count(); // calculate median

    return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2;
  };
  /**
   * Retrieve the index with given raw data index.
   */


  DataStore.prototype.indexOfRawIndex = function (rawIndex) {
    if (rawIndex >= this._rawCount || rawIndex < 0) {
      return -1;
    }

    if (!this._indices) {
      return rawIndex;
    } // Indices are ascending


    var indices = this._indices; // If rawIndex === dataIndex

    var rawDataIndex = indices[rawIndex];

    if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) {
      return rawIndex;
    }

    var left = 0;
    var right = this._count - 1;

    while (left <= right) {
      var mid = (left + right) / 2 | 0;

      if (indices[mid] < rawIndex) {
        left = mid + 1;
      } else if (indices[mid] > rawIndex) {
        right = mid - 1;
      } else {
        return mid;
      }
    }

    return -1;
  };
  /**
   * Retrieve the index of nearest value.
   * @param dim
   * @param value
   * @param [maxDistance=Infinity]
   * @return If and only if multiple indices have
   *         the same value, they are put to the result.
   */


  DataStore.prototype.indicesOfNearest = function (dim, value, maxDistance) {
    var chunks = this._chunks;
    var dimData = chunks[dim];
    var nearestIndices = [];

    if (!dimData) {
      return nearestIndices;
    }

    if (maxDistance == null) {
      maxDistance = Infinity;
    }

    var minDist = Infinity;
    var minDiff = -1;
    var nearestIndicesLen = 0; // Check the test case of `test/ut/spec/data/SeriesData.js`.

    for (var i = 0, len = this.count(); i < len; i++) {
      var dataIndex = this.getRawIndex(i);
      var diff = value - dimData[dataIndex];
      var dist = Math.abs(diff);

      if (dist <= maxDistance) {
        // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,
        // we'd better not push both of them to `nearestIndices`, otherwise it is easy to
        // get more than one item in `nearestIndices` (more specifically, in `tooltip`).
        // So we choose the one that `diff >= 0` in this case.
        // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them
        // should be push to `nearestIndices`.
        if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) {
          minDist = dist;
          minDiff = diff;
          nearestIndicesLen = 0;
        }

        if (diff === minDiff) {
          nearestIndices[nearestIndicesLen++] = i;
        }
      }
    }

    nearestIndices.length = nearestIndicesLen;
    return nearestIndices;
  };

  DataStore.prototype.getIndices = function () {
    var newIndices;
    var indices = this._indices;

    if (indices) {
      var Ctor = indices.constructor;
      var thisCount = this._count; // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.

      if (Ctor === Array) {
        newIndices = new Ctor(thisCount);

        for (var i = 0; i < thisCount; i++) {
          newIndices[i] = indices[i];
        }
      } else {
        newIndices = new Ctor(indices.buffer, 0, thisCount);
      }
    } else {
      var Ctor = getIndicesCtor(this._rawCount);
      newIndices = new Ctor(this.count());

      for (var i = 0; i < newIndices.length; i++) {
        newIndices[i] = i;
      }
    }

    return newIndices;
  };
  /**
   * Data filter.
   */


  DataStore.prototype.filter = function (dims, cb) {
    if (!this._count) {
      return this;
    }

    var newStore = this.clone();
    var count = newStore.count();
    var Ctor = getIndicesCtor(newStore._rawCount);
    var newIndices = new Ctor(count);
    var value = [];
    var dimSize = dims.length;
    var offset = 0;
    var dim0 = dims[0];
    var chunks = newStore._chunks;

    for (var i = 0; i < count; i++) {
      var keep = void 0;
      var rawIdx = newStore.getRawIndex(i); // Simple optimization

      if (dimSize === 0) {
        keep = cb(i);
      } else if (dimSize === 1) {
        var val = chunks[dim0][rawIdx];
        keep = cb(val, i);
      } else {
        var k = 0;

        for (; k < dimSize; k++) {
          value[k] = chunks[dims[k]][rawIdx];
        }

        value[k] = i;
        keep = cb.apply(null, value);
      }

      if (keep) {
        newIndices[offset++] = rawIdx;
      }
    } // Set indices after filtered.


    if (offset < count) {
      newStore._indices = newIndices;
    }

    newStore._count = offset; // Reset data extent

    newStore._extent = [];

    newStore._updateGetRawIdx();

    return newStore;
  };
  /**
   * Select data in range. (For optimization of filter)
   * (Manually inline code, support 5 million data filtering in data zoom.)
   */


  DataStore.prototype.selectRange = function (range) {
    var newStore = this.clone();
    var len = newStore._count;

    if (!len) {
      return this;
    }

    var dims = keys(range);
    var dimSize = dims.length;

    if (!dimSize) {
      return this;
    }

    var originalCount = newStore.count();
    var Ctor = getIndicesCtor(newStore._rawCount);
    var newIndices = new Ctor(originalCount);
    var offset = 0;
    var dim0 = dims[0];
    var min = range[dim0][0];
    var max = range[dim0][1];
    var storeArr = newStore._chunks;
    var quickFinished = false;

    if (!newStore._indices) {
      // Extreme optimization for common case. About 2x faster in chrome.
      var idx = 0;

      if (dimSize === 1) {
        var dimStorage = storeArr[dims[0]];

        for (var i = 0; i < len; i++) {
          var val = dimStorage[i]; // NaN will not be filtered. Consider the case, in line chart, empty
          // value indicates the line should be broken. But for the case like
          // scatter plot, a data item with empty value will not be rendered,
          // but the axis extent may be effected if some other dim of the data
          // item has value. Fortunately it is not a significant negative effect.

          if (val >= min && val <= max || isNaN(val)) {
            newIndices[offset++] = idx;
          }

          idx++;
        }

        quickFinished = true;
      } else if (dimSize === 2) {
        var dimStorage = storeArr[dims[0]];
        var dimStorage2 = storeArr[dims[1]];
        var min2 = range[dims[1]][0];
        var max2 = range[dims[1]][1];

        for (var i = 0; i < len; i++) {
          var val = dimStorage[i];
          var val2 = dimStorage2[i]; // Do not filter NaN, see comment above.

          if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) {
            newIndices[offset++] = idx;
          }

          idx++;
        }

        quickFinished = true;
      }
    }

    if (!quickFinished) {
      if (dimSize === 1) {
        for (var i = 0; i < originalCount; i++) {
          var rawIndex = newStore.getRawIndex(i);
          var val = storeArr[dims[0]][rawIndex]; // Do not filter NaN, see comment above.

          if (val >= min && val <= max || isNaN(val)) {
            newIndices[offset++] = rawIndex;
          }
        }
      } else {
        for (var i = 0; i < originalCount; i++) {
          var keep = true;
          var rawIndex = newStore.getRawIndex(i);

          for (var k = 0; k < dimSize; k++) {
            var dimk = dims[k];
            var val = storeArr[dimk][rawIndex]; // Do not filter NaN, see comment above.

            if (val < range[dimk][0] || val > range[dimk][1]) {
              keep = false;
            }
          }

          if (keep) {
            newIndices[offset++] = newStore.getRawIndex(i);
          }
        }
      }
    } // Set indices after filtered.


    if (offset < originalCount) {
      newStore._indices = newIndices;
    }

    newStore._count = offset; // Reset data extent

    newStore._extent = [];

    newStore._updateGetRawIdx();

    return newStore;
  }; // /**
  //  * Data mapping to a plain array
  //  */
  // mapArray(dims: DimensionIndex[], cb: MapArrayCb): any[] {
  //     const result: any[] = [];
  //     this.each(dims, function () {
  //         result.push(cb && (cb as MapArrayCb).apply(null, arguments));
  //     });
  //     return result;
  // }

  /**
   * Data mapping to a new List with given dimensions
   */


  DataStore.prototype.map = function (dims, cb) {
    // TODO only clone picked chunks.
    var target = this.clone(dims);

    this._updateDims(target, dims, cb);

    return target;
  };
  /**
   * @caution Danger!! Only used in dataStack.
   */


  DataStore.prototype.modify = function (dims, cb) {
    this._updateDims(this, dims, cb);
  };

  DataStore.prototype._updateDims = function (target, dims, cb) {
    var targetChunks = target._chunks;
    var tmpRetValue = [];
    var dimSize = dims.length;
    var dataCount = target.count();
    var values = [];
    var rawExtent = target._rawExtent;

    for (var i = 0; i < dims.length; i++) {
      rawExtent[dims[i]] = getInitialExtent();
    }

    for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) {
      var rawIndex = target.getRawIndex(dataIndex);

      for (var k = 0; k < dimSize; k++) {
        values[k] = targetChunks[dims[k]][rawIndex];
      }

      values[dimSize] = dataIndex;
      var retValue = cb && cb.apply(null, values);

      if (retValue != null) {
        // a number or string (in oridinal dimension)?
        if (typeof retValue !== 'object') {
          tmpRetValue[0] = retValue;
          retValue = tmpRetValue;
        }

        for (var i = 0; i < retValue.length; i++) {
          var dim = dims[i];
          var val = retValue[i];
          var rawExtentOnDim = rawExtent[dim];
          var dimStore = targetChunks[dim];

          if (dimStore) {
            dimStore[rawIndex] = val;
          }

          if (val < rawExtentOnDim[0]) {
            rawExtentOnDim[0] = val;
          }

          if (val > rawExtentOnDim[1]) {
            rawExtentOnDim[1] = val;
          }
        }
      }
    }
  };
  /**
   * Large data down sampling using largest-triangle-three-buckets
   * @param {string} valueDimension
   * @param {number} targetCount
   */


  DataStore.prototype.lttbDownSample = function (valueDimension, rate) {
    var target = this.clone([valueDimension], true);
    var targetStorage = target._chunks;
    var dimStore = targetStorage[valueDimension];
    var len = this.count();
    var sampledIndex = 0;
    var frameSize = Math.floor(1 / rate);
    var currentRawIndex = this.getRawIndex(0);
    var maxArea;
    var area;
    var nextRawIndex;
    var newIndices = new (getIndicesCtor(this._rawCount))(Math.min((Math.ceil(len / frameSize) + 2) * 2, len)); // First frame use the first data.

    newIndices[sampledIndex++] = currentRawIndex;

    for (var i = 1; i < len - 1; i += frameSize) {
      var nextFrameStart = Math.min(i + frameSize, len - 1);
      var nextFrameEnd = Math.min(i + frameSize * 2, len);
      var avgX = (nextFrameEnd + nextFrameStart) / 2;
      var avgY = 0;

      for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) {
        var rawIndex = this.getRawIndex(idx);
        var y = dimStore[rawIndex];

        if (isNaN(y)) {
          continue;
        }

        avgY += y;
      }

      avgY /= nextFrameEnd - nextFrameStart;
      var frameStart = i;
      var frameEnd = Math.min(i + frameSize, len);
      var pointAX = i - 1;
      var pointAY = dimStore[currentRawIndex];
      maxArea = -1;
      nextRawIndex = frameStart;
      var firstNaNIndex = -1;
      var countNaN = 0; // Find a point from current frame that construct a triangle with largest area with previous selected point
      // And the average of next frame.

      for (var idx = frameStart; idx < frameEnd; idx++) {
        var rawIndex = this.getRawIndex(idx);
        var y = dimStore[rawIndex];

        if (isNaN(y)) {
          countNaN++;

          if (firstNaNIndex < 0) {
            firstNaNIndex = rawIndex;
          }

          continue;
        } // Calculate triangle area over three buckets


        area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY));

        if (area > maxArea) {
          maxArea = area;
          nextRawIndex = rawIndex; // Next a is this b
        }
      }

      if (countNaN > 0 && countNaN < frameEnd - frameStart) {
        // Append first NaN point in every bucket.
        // It is necessary to ensure the correct order of indices.
        newIndices[sampledIndex++] = Math.min(firstNaNIndex, nextRawIndex);
        nextRawIndex = Math.max(firstNaNIndex, nextRawIndex);
      }

      newIndices[sampledIndex++] = nextRawIndex;
      currentRawIndex = nextRawIndex; // This a is the next a (chosen b)
    } // First frame use the last data.


    newIndices[sampledIndex++] = this.getRawIndex(len - 1);
    target._count = sampledIndex;
    target._indices = newIndices;
    target.getRawIndex = this._getRawIdx;
    return target;
  };
  /**
   * Large data down sampling on given dimension
   * @param sampleIndex Sample index for name and id
   */


  DataStore.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) {
    var target = this.clone([dimension], true);
    var targetStorage = target._chunks;
    var frameValues = [];
    var frameSize = Math.floor(1 / rate);
    var dimStore = targetStorage[dimension];
    var len = this.count();
    var rawExtentOnDim = target._rawExtent[dimension] = getInitialExtent();
    var newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize));
    var offset = 0;

    for (var i = 0; i < len; i += frameSize) {
      // Last frame
      if (frameSize > len - i) {
        frameSize = len - i;
        frameValues.length = frameSize;
      }

      for (var k = 0; k < frameSize; k++) {
        var dataIdx = this.getRawIndex(i + k);
        frameValues[k] = dimStore[dataIdx];
      }

      var value = sampleValue(frameValues);
      var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)); // Only write value on the filtered data

      dimStore[sampleFrameIdx] = value;

      if (value < rawExtentOnDim[0]) {
        rawExtentOnDim[0] = value;
      }

      if (value > rawExtentOnDim[1]) {
        rawExtentOnDim[1] = value;
      }

      newIndices[offset++] = sampleFrameIdx;
    }

    target._count = offset;
    target._indices = newIndices;

    target._updateGetRawIdx();

    return target;
  };
  /**
   * Data iteration
   * @param ctx default this
   * @example
   *  list.each('x', function (x, idx) {});
   *  list.each(['x', 'y'], function (x, y, idx) {});
   *  list.each(function (idx) {})
   */


  DataStore.prototype.each = function (dims, cb) {
    if (!this._count) {
      return;
    }

    var dimSize = dims.length;
    var chunks = this._chunks;

    for (var i = 0, len = this.count(); i < len; i++) {
      var rawIdx = this.getRawIndex(i); // Simple optimization

      switch (dimSize) {
        case 0:
          cb(i);
          break;

        case 1:
          cb(chunks[dims[0]][rawIdx], i);
          break;

        case 2:
          cb(chunks[dims[0]][rawIdx], chunks[dims[1]][rawIdx], i);
          break;

        default:
          var k = 0;
          var value = [];

          for (; k < dimSize; k++) {
            value[k] = chunks[dims[k]][rawIdx];
          } // Index


          value[k] = i;
          cb.apply(null, value);
      }
    }
  };
  /**
   * Get extent of data in one dimension
   */


  DataStore.prototype.getDataExtent = function (dim) {
    // Make sure use concrete dim as cache name.
    var dimData = this._chunks[dim];
    var initialExtent = getInitialExtent();

    if (!dimData) {
      return initialExtent;
    } // Make more strict checkings to ensure hitting cache.


    var currEnd = this.count(); // Consider the most cases when using data zoom, `getDataExtent`
    // happened before filtering. We cache raw extent, which is not
    // necessary to be cleared and recalculated when restore data.

    var useRaw = !this._indices;
    var dimExtent;

    if (useRaw) {
      return this._rawExtent[dim].slice();
    }

    dimExtent = this._extent[dim];

    if (dimExtent) {
      return dimExtent.slice();
    }

    dimExtent = initialExtent;
    var min = dimExtent[0];
    var max = dimExtent[1];

    for (var i = 0; i < currEnd; i++) {
      var rawIdx = this.getRawIndex(i);
      var value = dimData[rawIdx];
      value < min && (min = value);
      value > max && (max = value);
    }

    dimExtent = [min, max];
    this._extent[dim] = dimExtent;
    return dimExtent;
  };
  /**
   * Get raw data item
   */


  DataStore.prototype.getRawDataItem = function (idx) {
    var rawIdx = this.getRawIndex(idx);

    if (!this._provider.persistent) {
      var val = [];
      var chunks = this._chunks;

      for (var i = 0; i < chunks.length; i++) {
        val.push(chunks[i][rawIdx]);
      }

      return val;
    } else {
      return this._provider.getItem(rawIdx);
    }
  };
  /**
   * Clone shallow.
   *
   * @param clonedDims Determine which dims to clone. Will share the data if not specified.
   */


  DataStore.prototype.clone = function (clonedDims, ignoreIndices) {
    var target = new DataStore();
    var chunks = this._chunks;
    var clonedDimsMap = clonedDims && reduce(clonedDims, function (obj, dimIdx) {
      obj[dimIdx] = true;
      return obj;
    }, {});

    if (clonedDimsMap) {
      for (var i = 0; i < chunks.length; i++) {
        // Not clone if dim is not picked.
        target._chunks[i] = !clonedDimsMap[i] ? chunks[i] : cloneChunk(chunks[i]);
      }
    } else {
      target._chunks = chunks;
    }

    this._copyCommonProps(target);

    if (!ignoreIndices) {
      target._indices = this._cloneIndices();
    }

    target._updateGetRawIdx();

    return target;
  };

  DataStore.prototype._copyCommonProps = function (target) {
    target._count = this._count;
    target._rawCount = this._rawCount;
    target._provider = this._provider;
    target._dimensions = this._dimensions;
    target._extent = clone$2(this._extent);
    target._rawExtent = clone$2(this._rawExtent);
  };

  DataStore.prototype._cloneIndices = function () {
    if (this._indices) {
      var Ctor = this._indices.constructor;
      var indices = void 0;

      if (Ctor === Array) {
        var thisCount = this._indices.length;
        indices = new Ctor(thisCount);

        for (var i = 0; i < thisCount; i++) {
          indices[i] = this._indices[i];
        }
      } else {
        indices = new Ctor(this._indices);
      }

      return indices;
    }

    return null;
  };

  DataStore.prototype._getRawIdxIdentity = function (idx) {
    return idx;
  };

  DataStore.prototype._getRawIdx = function (idx) {
    if (idx < this._count && idx >= 0) {
      return this._indices[idx];
    }

    return -1;
  };

  DataStore.prototype._updateGetRawIdx = function () {
    this.getRawIndex = this._indices ? this._getRawIdx : this._getRawIdxIdentity;
  };

  DataStore.internalField = function () {
    function getDimValueSimply(dataItem, property, dataIndex, dimIndex) {
      return parseDataValue(dataItem[dimIndex], this._dimensions[dimIndex]);
    }

    defaultDimValueGetters = {
      arrayRows: getDimValueSimply,
      objectRows: function (dataItem, property, dataIndex, dimIndex) {
        return parseDataValue(dataItem[property], this._dimensions[dimIndex]);
      },
      keyedColumns: getDimValueSimply,
      original: function (dataItem, property, dataIndex, dimIndex) {
        // Performance sensitive, do not use modelUtil.getDataItemValue.
        // If dataItem is an plain object with no value field, the let `value`
        // will be assigned with the object, but it will be tread correctly
        // in the `convertValue`.
        var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value);
        return parseDataValue(value instanceof Array ? value[dimIndex] // If value is a single number or something else not array.
        : value, this._dimensions[dimIndex]);
      },
      typedArray: function (dataItem, property, dataIndex, dimIndex) {
        return dataItem[dimIndex];
      }
    };
  }();

  return DataStore;
}();
/* Injected with object hook! */

/**
 * [REQUIREMENT_MEMO]:
 * (0) `metaRawOption` means `dimensions`/`sourceHeader`/`seriesLayoutBy` in raw option.
 * (1) Keep support the feature: `metaRawOption` can be specified both on `series` and
 * `root-dataset`. Them on `series` has higher priority.
 * (2) Do not support to set `metaRawOption` on a `non-root-dataset`, because it might
 * confuse users: whether those props indicate how to visit the upstream source or visit
 * the transform result source, and some transforms has nothing to do with these props,
 * and some transforms might have multiple upstream.
 * (3) Transforms should specify `metaRawOption` in each output, just like they can be
 * declared in `root-dataset`.
 * (4) At present only support visit source in `SERIES_LAYOUT_BY_COLUMN` in transforms.
 * That is for reducing complexity in transforms.
 * PENDING: Whether to provide transposition transform?
 *
 * [IMPLEMENTAION_MEMO]:
 * "sourceVisitConfig" are calculated from `metaRawOption` and `data`.
 * They will not be calculated until `source` is about to be visited (to prevent from
 * duplicate calcuation). `source` is visited only in series and input to transforms.
 *
 * [DIMENSION_INHERIT_RULE]:
 * By default the dimensions are inherited from ancestors, unless a transform return
 * a new dimensions definition.
 * Consider the case:
 * ```js
 * dataset: [{
 *     source: [ ['Product', 'Sales', 'Prise'], ['Cookies', 321, 44.21], ...]
 * }, {
 *     transform: { type: 'filter', ... }
 * }]
 * dataset: [{
 *     dimension: ['Product', 'Sales', 'Prise'],
 *     source: [ ['Cookies', 321, 44.21], ...]
 * }, {
 *     transform: { type: 'filter', ... }
 * }]
 * ```
 * The two types of option should have the same behavior after transform.
 *
 *
 * [SCENARIO]:
 * (1) Provide source data directly:
 * ```js
 * series: {
 *     encode: {...},
 *     dimensions: [...]
 *     seriesLayoutBy: 'row',
 *     data: [[...]]
 * }
 * ```
 * (2) Series refer to dataset.
 * ```js
 * series: [{
 *     encode: {...}
 *     // Ignore datasetIndex means `datasetIndex: 0`
 *     // and the dimensions defination in dataset is used
 * }, {
 *     encode: {...},
 *     seriesLayoutBy: 'column',
 *     datasetIndex: 1
 * }]
 * ```
 * (3) dataset transform
 * ```js
 * dataset: [{
 *     source: [...]
 * }, {
 *     source: [...]
 * }, {
 *     // By default from 0.
 *     transform: { type: 'filter', config: {...} }
 * }, {
 *     // Piped.
 *     transform: [
 *         { type: 'filter', config: {...} },
 *         { type: 'sort', config: {...} }
 *     ]
 * }, {
 *     id: 'regressionData',
 *     fromDatasetIndex: 1,
 *     // Third-party transform
 *     transform: { type: 'ecStat:regression', config: {...} }
 * }, {
 *     // retrieve the extra result.
 *     id: 'regressionFormula',
 *     fromDatasetId: 'regressionData',
 *     fromTransformResult: 1
 * }]
 * ```
 */

var SourceManager =
/** @class */
function () {
  function SourceManager(sourceHost) {
    // Cached source. Do not repeat calculating if not dirty.
    this._sourceList = [];
    this._storeList = []; // version sign of each upstream source manager.

    this._upstreamSignList = [];
    this._versionSignBase = 0;
    this._dirty = true;
    this._sourceHost = sourceHost;
  }
  /**
   * Mark dirty.
   */


  SourceManager.prototype.dirty = function () {
    this._setLocalSource([], []);

    this._storeList = [];
    this._dirty = true;
  };

  SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) {
    this._sourceList = sourceList;
    this._upstreamSignList = upstreamSignList;
    this._versionSignBase++;

    if (this._versionSignBase > 9e10) {
      this._versionSignBase = 0;
    }
  };
  /**
   * For detecting whether the upstream source is dirty, so that
   * the local cached source (in `_sourceList`) should be discarded.
   */


  SourceManager.prototype._getVersionSign = function () {
    return this._sourceHost.uid + '_' + this._versionSignBase;
  };
  /**
   * Always return a source instance. Otherwise throw error.
   */


  SourceManager.prototype.prepareSource = function () {
    // For the case that call `setOption` multiple time but no data changed,
    // cache the result source to prevent from repeating transform.
    if (this._isDirty()) {
      this._createSource();

      this._dirty = false;
    }
  };

  SourceManager.prototype._createSource = function () {
    this._setLocalSource([], []);

    var sourceHost = this._sourceHost;

    var upSourceMgrList = this._getUpstreamSourceManagers();

    var hasUpstream = !!upSourceMgrList.length;
    var resultSourceList;
    var upstreamSignList;

    if (isSeries(sourceHost)) {
      var seriesModel = sourceHost;
      var data = void 0;
      var sourceFormat = void 0;
      var upSource = void 0; // Has upstream dataset

      if (hasUpstream) {
        var upSourceMgr = upSourceMgrList[0];
        upSourceMgr.prepareSource();
        upSource = upSourceMgr.getSource();
        data = upSource.data;
        sourceFormat = upSource.sourceFormat;
        upstreamSignList = [upSourceMgr._getVersionSign()];
      } // Series data is from own.
      else {
          data = seriesModel.get('data', true);
          sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL;
          upstreamSignList = [];
        } // See [REQUIREMENT_MEMO], merge settings on series and parent dataset if it is root.


      var newMetaRawOption = this._getSourceMetaRawOption() || {};
      var upMetaRawOption = upSource && upSource.metaRawOption || {};
      var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, upMetaRawOption.seriesLayoutBy) || null;
      var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upMetaRawOption.sourceHeader); // Note here we should not use `upSource.dimensionsDefine`. Consider the case:
      // `upSource.dimensionsDefine` is detected by `seriesLayoutBy: 'column'`,
      // but series need `seriesLayoutBy: 'row'`.

      var dimensions = retrieve2(newMetaRawOption.dimensions, upMetaRawOption.dimensions); // We share source with dataset as much as possible
      // to avoid extra memory cost of high dimensional data.

      var needsCreateSource = seriesLayoutBy !== upMetaRawOption.seriesLayoutBy || !!sourceHeader !== !!upMetaRawOption.sourceHeader || dimensions;
      resultSourceList = needsCreateSource ? [createSource(data, {
        seriesLayoutBy: seriesLayoutBy,
        sourceHeader: sourceHeader,
        dimensions: dimensions
      }, sourceFormat)] : [];
    } else {
      var datasetModel = sourceHost; // Has upstream dataset.

      if (hasUpstream) {
        var result = this._applyTransform(upSourceMgrList);

        resultSourceList = result.sourceList;
        upstreamSignList = result.upstreamSignList;
      } // Is root dataset.
      else {
          var sourceData = datasetModel.get('source', true);
          resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null)];
          upstreamSignList = [];
        }
    }

    this._setLocalSource(resultSourceList, upstreamSignList);
  };

  SourceManager.prototype._applyTransform = function (upMgrList) {
    var datasetModel = this._sourceHost;
    var transformOption = datasetModel.get('transform', true);
    var fromTransformResult = datasetModel.get('fromTransformResult', true);

    if (fromTransformResult != null) {
      var errMsg = '';

      if (upMgrList.length !== 1) {

        doThrow(errMsg);
      }
    }

    var sourceList;
    var upSourceList = [];
    var upstreamSignList = [];
    each$4(upMgrList, function (upMgr) {
      upMgr.prepareSource();
      var upSource = upMgr.getSource(fromTransformResult || 0);
      var errMsg = '';

      if (fromTransformResult != null && !upSource) {

        doThrow(errMsg);
      }

      upSourceList.push(upSource);
      upstreamSignList.push(upMgr._getVersionSign());
    });

    if (transformOption) {
      sourceList = applyDataTransform(transformOption, upSourceList, {
        datasetIndex: datasetModel.componentIndex
      });
    } else if (fromTransformResult != null) {
      sourceList = [cloneSourceShallow(upSourceList[0])];
    }

    return {
      sourceList: sourceList,
      upstreamSignList: upstreamSignList
    };
  };

  SourceManager.prototype._isDirty = function () {
    if (this._dirty) {
      return true;
    } // All sourceList is from the some upstream.


    var upSourceMgrList = this._getUpstreamSourceManagers();

    for (var i = 0; i < upSourceMgrList.length; i++) {
      var upSrcMgr = upSourceMgrList[i];

      if ( // Consider the case that there is ancestor diry, call it recursively.
      // The performance is probably not an issue because usually the chain is not long.
      upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) {
        return true;
      }
    }
  };
  /**
   * @param sourceIndex By default 0, means "main source".
   *                    In most cases there is only one source.
   */


  SourceManager.prototype.getSource = function (sourceIndex) {
    sourceIndex = sourceIndex || 0;
    var source = this._sourceList[sourceIndex];

    if (!source) {
      // Series may share source instance with dataset.
      var upSourceMgrList = this._getUpstreamSourceManagers();

      return upSourceMgrList[0] && upSourceMgrList[0].getSource(sourceIndex);
    }

    return source;
  };
  /**
   *
   * Get a data store which can be shared across series.
   * Only available for series.
   *
   * @param seriesDimRequest Dimensions that are generated in series.
   *        Should have been sorted by `storeDimIndex` asc.
   */


  SourceManager.prototype.getSharedDataStore = function (seriesDimRequest) {

    var schema = seriesDimRequest.makeStoreSchema();
    return this._innerGetDataStore(schema.dimensions, seriesDimRequest.source, schema.hash);
  };

  SourceManager.prototype._innerGetDataStore = function (storeDims, seriesSource, sourceReadKey) {
    // TODO Can use other sourceIndex?
    var sourceIndex = 0;
    var storeList = this._storeList;
    var cachedStoreMap = storeList[sourceIndex];

    if (!cachedStoreMap) {
      cachedStoreMap = storeList[sourceIndex] = {};
    }

    var cachedStore = cachedStoreMap[sourceReadKey];

    if (!cachedStore) {
      var upSourceMgr = this._getUpstreamSourceManagers()[0];

      if (isSeries(this._sourceHost) && upSourceMgr) {
        cachedStore = upSourceMgr._innerGetDataStore(storeDims, seriesSource, sourceReadKey);
      } else {
        cachedStore = new DataStore(); // Always create store from source of series.

        cachedStore.initData(new DefaultDataProvider(seriesSource, storeDims.length), storeDims);
      }

      cachedStoreMap[sourceReadKey] = cachedStore;
    }

    return cachedStore;
  };
  /**
   * PENDING: Is it fast enough?
   * If no upstream, return empty array.
   */


  SourceManager.prototype._getUpstreamSourceManagers = function () {
    // Always get the relationship from the raw option.
    // Do not cache the link of the dependency graph, so that
    // there is no need to update them when change happens.
    var sourceHost = this._sourceHost;

    if (isSeries(sourceHost)) {
      var datasetModel = querySeriesUpstreamDatasetModel(sourceHost);
      return !datasetModel ? [] : [datasetModel.getSourceManager()];
    } else {
      return map$1(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) {
        return datasetModel.getSourceManager();
      });
    }
  };

  SourceManager.prototype._getSourceMetaRawOption = function () {
    var sourceHost = this._sourceHost;
    var seriesLayoutBy;
    var sourceHeader;
    var dimensions;

    if (isSeries(sourceHost)) {
      seriesLayoutBy = sourceHost.get('seriesLayoutBy', true);
      sourceHeader = sourceHost.get('sourceHeader', true);
      dimensions = sourceHost.get('dimensions', true);
    } // See [REQUIREMENT_MEMO], `non-root-dataset` do not support them.
    else if (!this._getUpstreamSourceManagers().length) {
        var model = sourceHost;
        seriesLayoutBy = model.get('seriesLayoutBy', true);
        sourceHeader = model.get('sourceHeader', true);
        dimensions = model.get('dimensions', true);
      }

    return {
      seriesLayoutBy: seriesLayoutBy,
      sourceHeader: sourceHeader,
      dimensions: dimensions
    };
  };

  return SourceManager;
}();

function isSeries(sourceHost) {
  // Avoid circular dependency with Series.ts
  return sourceHost.mainType === 'series';
}

function doThrow(errMsg) {
  throw new Error(errMsg);
}
/* Injected with object hook! */

var TOOLTIP_LINE_HEIGHT_CSS = 'line-height:1'; // TODO: more textStyle option

function getTooltipTextStyle(textStyle, renderMode) {
  var nameFontColor = textStyle.color || '#6e7079';
  var nameFontSize = textStyle.fontSize || 12;
  var nameFontWeight = textStyle.fontWeight || '400';
  var valueFontColor = textStyle.color || '#464646';
  var valueFontSize = textStyle.fontSize || 14;
  var valueFontWeight = textStyle.fontWeight || '900';

  if (renderMode === 'html') {
    // `textStyle` is probably from user input, should be encoded to reduce security risk.
    return {
      // eslint-disable-next-line max-len
      nameStyle: "font-size:" + encodeHTML(nameFontSize + '') + "px;color:" + encodeHTML(nameFontColor) + ";font-weight:" + encodeHTML(nameFontWeight + ''),
      // eslint-disable-next-line max-len
      valueStyle: "font-size:" + encodeHTML(valueFontSize + '') + "px;color:" + encodeHTML(valueFontColor) + ";font-weight:" + encodeHTML(valueFontWeight + '')
    };
  } else {
    return {
      nameStyle: {
        fontSize: nameFontSize,
        fill: nameFontColor,
        fontWeight: nameFontWeight
      },
      valueStyle: {
        fontSize: valueFontSize,
        fill: valueFontColor,
        fontWeight: valueFontWeight
      }
    };
  }
} // See `TooltipMarkupLayoutIntent['innerGapLevel']`.
// (value from UI design)


var HTML_GAPS = [0, 10, 20, 30];
var RICH_TEXT_GAPS = ['', '\n', '\n\n', '\n\n\n']; // eslint-disable-next-line max-len

function createTooltipMarkup(type, option) {
  option.type = type;
  return option;
}

function isSectionFragment(frag) {
  return frag.type === 'section';
}

function getBuilder(frag) {
  return isSectionFragment(frag) ? buildSection : buildNameValue;
}

function getBlockGapLevel(frag) {
  if (isSectionFragment(frag)) {
    var gapLevel_1 = 0;
    var subBlockLen = frag.blocks.length;
    var hasInnerGap_1 = subBlockLen > 1 || subBlockLen > 0 && !frag.noHeader;
    each$4(frag.blocks, function (subBlock) {
      var subGapLevel = getBlockGapLevel(subBlock); // If the some of the sub-blocks have some gaps (like 10px) inside, this block
      // should use a larger gap (like 20px) to distinguish those sub-blocks.

      if (subGapLevel >= gapLevel_1) {
        gapLevel_1 = subGapLevel + +(hasInnerGap_1 && ( // 0 always can not be readable gap level.
        !subGapLevel // If no header, always keep the sub gap level. Otherwise
        // look weird in case `multipleSeries`.
        || isSectionFragment(subBlock) && !subBlock.noHeader));
      }
    });
    return gapLevel_1;
  }

  return 0;
}

function buildSection(ctx, fragment, topMarginForOuterGap, toolTipTextStyle) {
  var noHeader = fragment.noHeader;
  var gaps = getGap(getBlockGapLevel(fragment));
  var subMarkupTextList = [];
  var subBlocks = fragment.blocks || [];
  assert(!subBlocks || isArray(subBlocks));
  subBlocks = subBlocks || [];
  var orderMode = ctx.orderMode;

  if (fragment.sortBlocks && orderMode) {
    subBlocks = subBlocks.slice();
    var orderMap = {
      valueAsc: 'asc',
      valueDesc: 'desc'
    };

    if (hasOwn(orderMap, orderMode)) {
      var comparator_1 = new SortOrderComparator(orderMap[orderMode], null);
      subBlocks.sort(function (a, b) {
        return comparator_1.evaluate(a.sortParam, b.sortParam);
      });
    } // FIXME 'seriesDesc' necessary?
    else if (orderMode === 'seriesDesc') {
        subBlocks.reverse();
      }
  }

  each$4(subBlocks, function (subBlock, idx) {
    var valueFormatter = fragment.valueFormatter;
    var subMarkupText = getBuilder(subBlock)( // Inherit valueFormatter
    valueFormatter ? extend(extend({}, ctx), {
      valueFormatter: valueFormatter
    }) : ctx, subBlock, idx > 0 ? gaps.html : 0, toolTipTextStyle);
    subMarkupText != null && subMarkupTextList.push(subMarkupText);
  });
  var subMarkupText = ctx.renderMode === 'richText' ? subMarkupTextList.join(gaps.richText) : wrapBlockHTML(subMarkupTextList.join(''), noHeader ? topMarginForOuterGap : gaps.html);

  if (noHeader) {
    return subMarkupText;
  }

  var displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC);
  var nameStyle = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode).nameStyle;

  if (ctx.renderMode === 'richText') {
    return wrapInlineNameRichText(ctx, displayableHeader, nameStyle) + gaps.richText + subMarkupText;
  } else {
    return wrapBlockHTML("<div style=\"" + nameStyle + ";" + TOOLTIP_LINE_HEIGHT_CSS + ";\">" + encodeHTML(displayableHeader) + '</div>' + subMarkupText, topMarginForOuterGap);
  }
}

function buildNameValue(ctx, fragment, topMarginForOuterGap, toolTipTextStyle) {
  var renderMode = ctx.renderMode;
  var noName = fragment.noName;
  var noValue = fragment.noValue;
  var noMarker = !fragment.markerType;
  var name = fragment.name;
  var useUTC = ctx.useUTC;

  var valueFormatter = fragment.valueFormatter || ctx.valueFormatter || function (value) {
    value = isArray(value) ? value : [value];
    return map$1(value, function (val, idx) {
      return makeValueReadable(val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC);
    });
  };

  if (noName && noValue) {
    return;
  }

  var markerStr = noMarker ? '' : ctx.markupStyleCreator.makeTooltipMarker(fragment.markerType, fragment.markerColor || '#333', renderMode);
  var readableName = noName ? '' : makeValueReadable(name, 'ordinal', useUTC);
  var valueTypeOption = fragment.valueType;
  var readableValueList = noValue ? [] : valueFormatter(fragment.value);
  var valueAlignRight = !noMarker || !noName; // It little weird if only value next to marker but far from marker.

  var valueCloseToMarker = !noMarker && noName;

  var _a = getTooltipTextStyle(toolTipTextStyle, renderMode),
      nameStyle = _a.nameStyle,
      valueStyle = _a.valueStyle;

  return renderMode === 'richText' ? (noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle)) // Value has commas inside, so use ' ' as delimiter for multiple values.
  + (noValue ? '' : wrapInlineValueRichText(ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)) : wrapBlockHTML((noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle)) + (noValue ? '' : wrapInlineValueHTML(readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)), topMarginForOuterGap);
}
/**
 * @return markupText. null/undefined means no content.
 */


function buildTooltipMarkup(fragment, markupStyleCreator, renderMode, orderMode, useUTC, toolTipTextStyle) {
  if (!fragment) {
    return;
  }

  var builder = getBuilder(fragment);
  var ctx = {
    useUTC: useUTC,
    renderMode: renderMode,
    orderMode: orderMode,
    markupStyleCreator: markupStyleCreator,
    valueFormatter: fragment.valueFormatter
  };
  return builder(ctx, fragment, 0, toolTipTextStyle);
}

function getGap(gapLevel) {
  return {
    html: HTML_GAPS[gapLevel],
    richText: RICH_TEXT_GAPS[gapLevel]
  };
}

function wrapBlockHTML(encodedContent, topGap) {
  var clearfix = '<div style="clear:both"></div>';
  var marginCSS = "margin: " + topGap + "px 0 0";
  return "<div style=\"" + marginCSS + ";" + TOOLTIP_LINE_HEIGHT_CSS + ";\">" + encodedContent + clearfix + '</div>';
}

function wrapInlineNameHTML(name, leftHasMarker, style) {
  var marginCss = leftHasMarker ? 'margin-left:2px' : '';
  return "<span style=\"" + style + ";" + marginCss + "\">" + encodeHTML(name) + '</span>';
}

function wrapInlineValueHTML(valueList, alignRight, valueCloseToMarker, style) {
  // Do not too close to marker, considering there are multiple values separated by spaces.
  var paddingStr = valueCloseToMarker ? '10px' : '20px';
  var alignCSS = alignRight ? "float:right;margin-left:" + paddingStr : '';
  valueList = isArray(valueList) ? valueList : [valueList];
  return "<span style=\"" + alignCSS + ";" + style + "\">" // Value has commas inside, so use '  ' as delimiter for multiple values.
  + map$1(valueList, function (value) {
    return encodeHTML(value);
  }).join('&nbsp;&nbsp;') + '</span>';
}

function wrapInlineNameRichText(ctx, name, style) {
  return ctx.markupStyleCreator.wrapRichTextStyle(name, style);
}

function wrapInlineValueRichText(ctx, values, alignRight, valueCloseToMarker, style) {
  var styles = [style];
  var paddingLeft = valueCloseToMarker ? 10 : 20;
  alignRight && styles.push({
    padding: [0, 0, 0, paddingLeft],
    align: 'right'
  }); // Value has commas inside, so use '  ' as delimiter for multiple values.

  return ctx.markupStyleCreator.wrapRichTextStyle(isArray(values) ? values.join('  ') : values, styles);
}

function retrieveVisualColorForTooltipMarker(series, dataIndex) {
  var style = series.getData().getItemVisual(dataIndex, 'style');
  var color = style[series.visualDrawType];
  return convertToColorString(color);
}
function getPaddingFromTooltipModel(model, renderMode) {
  var padding = model.get('padding');
  return padding != null ? padding // We give slightly different to look pretty.
  : renderMode === 'richText' ? [8, 10] : 10;
}
/**
 * The major feature is generate styles for `renderMode: 'richText'`.
 * But it also serves `renderMode: 'html'` to provide
 * "renderMode-independent" API.
 */

var TooltipMarkupStyleCreator =
/** @class */
function () {
  function TooltipMarkupStyleCreator() {
    this.richTextStyles = {}; // Notice that "generate a style name" usually happens repeatedly when mouse is moving and
    // a tooltip is displayed. So we put the `_nextStyleNameId` as a member of each creator
    // rather than static shared by all creators (which will cause it increase to fast).

    this._nextStyleNameId = getRandomIdBase();
  }

  TooltipMarkupStyleCreator.prototype._generateStyleName = function () {
    return '__EC_aUTo_' + this._nextStyleNameId++;
  };

  TooltipMarkupStyleCreator.prototype.makeTooltipMarker = function (markerType, colorStr, renderMode) {
    var markerId = renderMode === 'richText' ? this._generateStyleName() : null;
    var marker = getTooltipMarker({
      color: colorStr,
      type: markerType,
      renderMode: renderMode,
      markerId: markerId
    });

    if (isString(marker)) {
      return marker;
    } else {

      this.richTextStyles[markerId] = marker.style;
      return marker.content;
    }
  };
  /**
   * @usage
   * ```ts
   * const styledText = markupStyleCreator.wrapRichTextStyle([
   *     // The styles will be auto merged.
   *     {
   *         fontSize: 12,
   *         color: 'blue'
   *     },
   *     {
   *         padding: 20
   *     }
   * ]);
   * ```
   */


  TooltipMarkupStyleCreator.prototype.wrapRichTextStyle = function (text, styles) {
    var finalStl = {};

    if (isArray(styles)) {
      each$4(styles, function (stl) {
        return extend(finalStl, stl);
      });
    } else {
      extend(finalStl, styles);
    }

    var styleName = this._generateStyleName();

    this.richTextStyles[styleName] = finalStl;
    return "{" + styleName + "|" + text + "}";
  };

  return TooltipMarkupStyleCreator;
}();
/* Injected with object hook! */

function defaultSeriesFormatTooltip(opt) {
  var series = opt.series;
  var dataIndex = opt.dataIndex;
  var multipleSeries = opt.multipleSeries;
  var data = series.getData();
  var tooltipDims = data.mapDimensionsAll('defaultedTooltip');
  var tooltipDimLen = tooltipDims.length;
  var value = series.getRawValue(dataIndex);
  var isValueArr = isArray(value);
  var markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex); // Complicated rule for pretty tooltip.

  var inlineValue;
  var inlineValueType;
  var subBlocks;
  var sortParam;

  if (tooltipDimLen > 1 || isValueArr && !tooltipDimLen) {
    var formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor);
    inlineValue = formatArrResult.inlineValues;
    inlineValueType = formatArrResult.inlineValueTypes;
    subBlocks = formatArrResult.blocks; // Only support tooltip sort by the first inline value. It's enough in most cases.

    sortParam = formatArrResult.inlineValues[0];
  } else if (tooltipDimLen) {
    var dimInfo = data.getDimensionInfo(tooltipDims[0]);
    sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]);
    inlineValueType = dimInfo.type;
  } else {
    sortParam = inlineValue = isValueArr ? value[0] : value;
  } // Do not show generated series name. It might not be readable.


  var seriesNameSpecified = isNameSpecified(series);
  var seriesName = seriesNameSpecified && series.name || '';
  var itemName = data.getName(dataIndex);
  var inlineName = multipleSeries ? seriesName : itemName;
  return createTooltipMarkup('section', {
    header: seriesName,
    // When series name is not specified, do not show a header line with only '-'.
    // This case always happens in tooltip.trigger: 'item'.
    noHeader: multipleSeries || !seriesNameSpecified,
    sortParam: sortParam,
    blocks: [createTooltipMarkup('nameValue', {
      markerType: 'item',
      markerColor: markerColor,
      // Do not mix display seriesName and itemName in one tooltip,
      // which might confuses users.
      name: inlineName,
      // name dimension might be auto assigned, where the name might
      // be not readable. So we check trim here.
      noName: !trim(inlineName),
      value: inlineValue,
      valueType: inlineValueType
    })].concat(subBlocks || [])
  });
}

function formatTooltipArrayValue(value, series, dataIndex, tooltipDims, colorStr) {
  // check: category-no-encode-has-axis-data in dataset.html
  var data = series.getData();
  var isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) {
    var dimItem = data.getDimensionInfo(idx);
    return isValueMultipleLine = isValueMultipleLine || dimItem && dimItem.tooltip !== false && dimItem.displayName != null;
  }, false);
  var inlineValues = [];
  var inlineValueTypes = [];
  var blocks = [];
  tooltipDims.length ? each$4(tooltipDims, function (dim) {
    setEachItem(retrieveRawValue(data, dataIndex, dim), dim);
  }) // By default, all dims is used on tooltip.
  : each$4(value, setEachItem);

  function setEachItem(val, dim) {
    var dimInfo = data.getDimensionInfo(dim); // If `dimInfo.tooltip` is not set, show tooltip.

    if (!dimInfo || dimInfo.otherDims.tooltip === false) {
      return;
    }

    if (isValueMultipleLine) {
      blocks.push(createTooltipMarkup('nameValue', {
        markerType: 'subItem',
        markerColor: colorStr,
        name: dimInfo.displayName,
        value: val,
        valueType: dimInfo.type
      }));
    } else {
      inlineValues.push(val);
      inlineValueTypes.push(dimInfo.type);
    }
  }

  return {
    inlineValues: inlineValues,
    inlineValueTypes: inlineValueTypes,
    blocks: blocks
  };
}
/* Injected with object hook! */

var inner$8 = makeInner();

function getSelectionKey(data, dataIndex) {
  return data.getName(dataIndex) || data.getId(dataIndex);
}

var SERIES_UNIVERSAL_TRANSITION_PROP = '__universalTransitionEnabled';

var SeriesModel =
/** @class */
function (_super) {
  __extends(SeriesModel, _super);

  function SeriesModel() {
    // [Caution]: Because this class or desecendants can be used as `XXX.extend(subProto)`,
    // the class members must not be initialized in constructor or declaration place.
    // Otherwise there is bad case:
    //   class A {xxx = 1;}
    //   enableClassExtend(A);
    //   class B extends A {}
    //   var C = B.extend({xxx: 5});
    //   var c = new C();
    //   console.log(c.xxx); // expect 5 but always 1.
    var _this = _super !== null && _super.apply(this, arguments) || this; // ---------------------------------------
    // Props about data selection
    // ---------------------------------------


    _this._selectedDataIndicesMap = {};
    return _this;
  }

  SeriesModel.prototype.init = function (option, parentModel, ecModel) {
    this.seriesIndex = this.componentIndex;
    this.dataTask = createTask({
      count: dataTaskCount,
      reset: dataTaskReset
    });
    this.dataTask.context = {
      model: this
    };
    this.mergeDefaultAndTheme(option, ecModel);
    var sourceManager = inner$8(this).sourceManager = new SourceManager(this);
    sourceManager.prepareSource();
    var data = this.getInitialData(option, ecModel);
    wrapData(data, this);
    this.dataTask.context.data = data;

    inner$8(this).dataBeforeProcessed = data; // If we reverse the order (make data firstly, and then make
    // dataBeforeProcessed by cloneShallow), cloneShallow will
    // cause data.graph.data !== data when using
    // module:echarts/data/Graph or module:echarts/data/Tree.
    // See module:echarts/data/helper/linkSeriesData
    // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model
    // init or merge stage, because the data can be restored. So we do not `restoreData`
    // and `setData` here, which forbids calling `seriesModel.getData()` in this stage.
    // Call `seriesModel.getRawData()` instead.
    // this.restoreData();

    autoSeriesName(this);

    this._initSelectedMapFromData(data);
  };
  /**
   * Util for merge default and theme to option
   */


  SeriesModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
    var layoutMode = fetchLayoutMode(this);
    var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; // Backward compat: using subType on theme.
    // But if name duplicate between series subType
    // (for example: parallel) add component mainType,
    // add suffix 'Series'.

    var themeSubType = this.subType;

    if (ComponentModel$1.hasClass(themeSubType)) {
      themeSubType += 'Series';
    }

    merge(option, ecModel.getTheme().get(this.subType));
    merge(option, this.getDefaultOption()); // Default label emphasis `show`

    defaultEmphasis(option, 'label', ['show']);
    this.fillDataTextStyle(option.data);

    if (layoutMode) {
      mergeLayoutParam(option, inputPositionParams, layoutMode);
    }
  };

  SeriesModel.prototype.mergeOption = function (newSeriesOption, ecModel) {
    // this.settingTask.dirty();
    newSeriesOption = merge(this.option, newSeriesOption, true);
    this.fillDataTextStyle(newSeriesOption.data);
    var layoutMode = fetchLayoutMode(this);

    if (layoutMode) {
      mergeLayoutParam(this.option, newSeriesOption, layoutMode);
    }

    var sourceManager = inner$8(this).sourceManager;
    sourceManager.dirty();
    sourceManager.prepareSource();
    var data = this.getInitialData(newSeriesOption, ecModel);
    wrapData(data, this);
    this.dataTask.dirty();
    this.dataTask.context.data = data;
    inner$8(this).dataBeforeProcessed = data;
    autoSeriesName(this);

    this._initSelectedMapFromData(data);
  };

  SeriesModel.prototype.fillDataTextStyle = function (data) {
    // Default data label emphasis `show`
    // FIXME Tree structure data ?
    // FIXME Performance ?
    if (data && !isTypedArray(data)) {
      var props = ['show'];

      for (var i = 0; i < data.length; i++) {
        if (data[i] && data[i].label) {
          defaultEmphasis(data[i], 'label', props);
        }
      }
    }
  };
  /**
   * Init a data structure from data related option in series
   * Must be overridden.
   */


  SeriesModel.prototype.getInitialData = function (option, ecModel) {
    return;
  };
  /**
   * Append data to list
   */


  SeriesModel.prototype.appendData = function (params) {
    // FIXME ???
    // (1) If data from dataset, forbidden append.
    // (2) support append data of dataset.
    var data = this.getRawData();
    data.appendData(params.data);
  };
  /**
   * Consider some method like `filter`, `map` need make new data,
   * We should make sure that `seriesModel.getData()` get correct
   * data in the stream procedure. So we fetch data from upstream
   * each time `task.perform` called.
   */


  SeriesModel.prototype.getData = function (dataType) {
    var task = getCurrentTask(this);

    if (task) {
      var data = task.context.data;
      return dataType == null ? data : data.getLinkedData(dataType);
    } else {
      // When series is not alive (that may happen when click toolbox
      // restore or setOption with not merge mode), series data may
      // be still need to judge animation or something when graphic
      // elements want to know whether fade out.
      return inner$8(this).data;
    }
  };

  SeriesModel.prototype.getAllData = function () {
    var mainData = this.getData();
    return mainData && mainData.getLinkedDataAll ? mainData.getLinkedDataAll() : [{
      data: mainData
    }];
  };

  SeriesModel.prototype.setData = function (data) {
    var task = getCurrentTask(this);

    if (task) {
      var context = task.context; // Consider case: filter, data sample.
      // FIXME:TS never used, so comment it
      // if (context.data !== data && task.modifyOutputEnd) {
      //     task.setOutputEnd(data.count());
      // }

      context.outputData = data; // Caution: setData should update context.data,
      // Because getData may be called multiply in a
      // single stage and expect to get the data just
      // set. (For example, AxisProxy, x y both call
      // getData and setDate sequentially).
      // So the context.data should be fetched from
      // upstream each time when a stage starts to be
      // performed.

      if (task !== this.dataTask) {
        context.data = data;
      }
    }

    inner$8(this).data = data;
  };

  SeriesModel.prototype.getEncode = function () {
    var encode = this.get('encode', true);

    if (encode) {
      return createHashMap(encode);
    }
  };

  SeriesModel.prototype.getSourceManager = function () {
    return inner$8(this).sourceManager;
  };

  SeriesModel.prototype.getSource = function () {
    return this.getSourceManager().getSource();
  };
  /**
   * Get data before processed
   */


  SeriesModel.prototype.getRawData = function () {
    return inner$8(this).dataBeforeProcessed;
  };

  SeriesModel.prototype.getColorBy = function () {
    var colorBy = this.get('colorBy');
    return colorBy || 'series';
  };

  SeriesModel.prototype.isColorBySeries = function () {
    return this.getColorBy() === 'series';
  };
  /**
   * Get base axis if has coordinate system and has axis.
   * By default use coordSys.getBaseAxis();
   * Can be overridden for some chart.
   * @return {type} description
   */


  SeriesModel.prototype.getBaseAxis = function () {
    var coordSys = this.coordinateSystem; // @ts-ignore

    return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
  };
  /**
   * Default tooltip formatter
   *
   * @param dataIndex
   * @param multipleSeries
   * @param dataType
   * @param renderMode valid values: 'html'(by default) and 'richText'.
   *        'html' is used for rendering tooltip in extra DOM form, and the result
   *        string is used as DOM HTML content.
   *        'richText' is used for rendering tooltip in rich text form, for those where
   *        DOM operation is not supported.
   * @return formatted tooltip with `html` and `markers`
   *        Notice: The override method can also return string
   */


  SeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
    return defaultSeriesFormatTooltip({
      series: this,
      dataIndex: dataIndex,
      multipleSeries: multipleSeries
    });
  };

  SeriesModel.prototype.isAnimationEnabled = function () {
    var ecModel = this.ecModel; // Disable animation if using echarts in node but not give ssr flag.
    // In ssr mode, renderToString will generate svg with css animation.

    if (env$1.node && !(ecModel && ecModel.ssr)) {
      return false;
    }

    var animationEnabled = this.getShallow('animation');

    if (animationEnabled) {
      if (this.getData().count() > this.getShallow('animationThreshold')) {
        animationEnabled = false;
      }
    }

    return !!animationEnabled;
  };

  SeriesModel.prototype.restoreData = function () {
    this.dataTask.dirty();
  };

  SeriesModel.prototype.getColorFromPalette = function (name, scope, requestColorNum) {
    var ecModel = this.ecModel; // PENDING

    var color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum);

    if (!color) {
      color = ecModel.getColorFromPalette(name, scope, requestColorNum);
    }

    return color;
  };
  /**
   * Use `data.mapDimensionsAll(coordDim)` instead.
   * @deprecated
   */


  SeriesModel.prototype.coordDimToDataDim = function (coordDim) {
    return this.getRawData().mapDimensionsAll(coordDim);
  };
  /**
   * Get progressive rendering count each step
   */


  SeriesModel.prototype.getProgressive = function () {
    return this.get('progressive');
  };
  /**
   * Get progressive rendering count each step
   */


  SeriesModel.prototype.getProgressiveThreshold = function () {
    return this.get('progressiveThreshold');
  }; // PENGING If selectedMode is null ?


  SeriesModel.prototype.select = function (innerDataIndices, dataType) {
    this._innerSelect(this.getData(dataType), innerDataIndices);
  };

  SeriesModel.prototype.unselect = function (innerDataIndices, dataType) {
    var selectedMap = this.option.selectedMap;

    if (!selectedMap) {
      return;
    }

    var selectedMode = this.option.selectedMode;
    var data = this.getData(dataType);

    if (selectedMode === 'series' || selectedMap === 'all') {
      this.option.selectedMap = {};
      this._selectedDataIndicesMap = {};
      return;
    }

    for (var i = 0; i < innerDataIndices.length; i++) {
      var dataIndex = innerDataIndices[i];
      var nameOrId = getSelectionKey(data, dataIndex);
      selectedMap[nameOrId] = false;
      this._selectedDataIndicesMap[nameOrId] = -1;
    }
  };

  SeriesModel.prototype.toggleSelect = function (innerDataIndices, dataType) {
    var tmpArr = [];

    for (var i = 0; i < innerDataIndices.length; i++) {
      tmpArr[0] = innerDataIndices[i];
      this.isSelected(innerDataIndices[i], dataType) ? this.unselect(tmpArr, dataType) : this.select(tmpArr, dataType);
    }
  };

  SeriesModel.prototype.getSelectedDataIndices = function () {
    if (this.option.selectedMap === 'all') {
      return [].slice.call(this.getData().getIndices());
    }

    var selectedDataIndicesMap = this._selectedDataIndicesMap;
    var nameOrIds = keys(selectedDataIndicesMap);
    var dataIndices = [];

    for (var i = 0; i < nameOrIds.length; i++) {
      var dataIndex = selectedDataIndicesMap[nameOrIds[i]];

      if (dataIndex >= 0) {
        dataIndices.push(dataIndex);
      }
    }

    return dataIndices;
  };

  SeriesModel.prototype.isSelected = function (dataIndex, dataType) {
    var selectedMap = this.option.selectedMap;

    if (!selectedMap) {
      return false;
    }

    var data = this.getData(dataType);
    return (selectedMap === 'all' || selectedMap[getSelectionKey(data, dataIndex)]) && !data.getItemModel(dataIndex).get(['select', 'disabled']);
  };

  SeriesModel.prototype.isUniversalTransitionEnabled = function () {
    if (this[SERIES_UNIVERSAL_TRANSITION_PROP]) {
      return true;
    }

    var universalTransitionOpt = this.option.universalTransition; // Quick reject

    if (!universalTransitionOpt) {
      return false;
    }

    if (universalTransitionOpt === true) {
      return true;
    } // Can be simply 'universalTransition: true'


    return universalTransitionOpt && universalTransitionOpt.enabled;
  };

  SeriesModel.prototype._innerSelect = function (data, innerDataIndices) {
    var _a, _b;

    var option = this.option;
    var selectedMode = option.selectedMode;
    var len = innerDataIndices.length;

    if (!selectedMode || !len) {
      return;
    }

    if (selectedMode === 'series') {
      option.selectedMap = 'all';
    } else if (selectedMode === 'multiple') {
      if (!isObject$2(option.selectedMap)) {
        option.selectedMap = {};
      }

      var selectedMap = option.selectedMap;

      for (var i = 0; i < len; i++) {
        var dataIndex = innerDataIndices[i]; // TODO different types of data share same object.

        var nameOrId = getSelectionKey(data, dataIndex);
        selectedMap[nameOrId] = true;
        this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex);
      }
    } else if (selectedMode === 'single' || selectedMode === true) {
      var lastDataIndex = innerDataIndices[len - 1];
      var nameOrId = getSelectionKey(data, lastDataIndex);
      option.selectedMap = (_a = {}, _a[nameOrId] = true, _a);
      this._selectedDataIndicesMap = (_b = {}, _b[nameOrId] = data.getRawIndex(lastDataIndex), _b);
    }
  };

  SeriesModel.prototype._initSelectedMapFromData = function (data) {
    // Ignore select info in data if selectedMap exists.
    // NOTE It's only for legacy usage. edge data is not supported.
    if (this.option.selectedMap) {
      return;
    }

    var dataIndices = [];

    if (data.hasItemOption) {
      data.each(function (idx) {
        var rawItem = data.getRawDataItem(idx);

        if (rawItem && rawItem.selected) {
          dataIndices.push(idx);
        }
      });
    }

    if (dataIndices.length > 0) {
      this._innerSelect(data, dataIndices);
    }
  }; // /**
  //  * @see {module:echarts/stream/Scheduler}
  //  */
  // abstract pipeTask: null


  SeriesModel.registerClass = function (clz) {
    return ComponentModel$1.registerClass(clz);
  };

  SeriesModel.protoInitialize = function () {
    var proto = SeriesModel.prototype;
    proto.type = 'series.__base__';
    proto.seriesIndex = 0;
    proto.ignoreStyleOnData = false;
    proto.hasSymbolVisual = false;
    proto.defaultSymbol = 'circle'; // Make sure the values can be accessed!

    proto.visualStyleAccessPath = 'itemStyle';
    proto.visualDrawType = 'fill';
  }();

  return SeriesModel;
}(ComponentModel$1);

mixin(SeriesModel, DataFormatMixin);
mixin(SeriesModel, PaletteMixin);
mountExtend(SeriesModel, ComponentModel$1);
/**
 * MUST be called after `prepareSource` called
 * Here we need to make auto series, especially for auto legend. But we
 * do not modify series.name in option to avoid side effects.
 */

function autoSeriesName(seriesModel) {
  // User specified name has higher priority, otherwise it may cause
  // series can not be queried unexpectedly.
  var name = seriesModel.name;

  if (!isNameSpecified(seriesModel)) {
    seriesModel.name = getSeriesAutoName(seriesModel) || name;
  }
}

function getSeriesAutoName(seriesModel) {
  var data = seriesModel.getRawData();
  var dataDims = data.mapDimensionsAll('seriesName');
  var nameArr = [];
  each$4(dataDims, function (dataDim) {
    var dimInfo = data.getDimensionInfo(dataDim);
    dimInfo.displayName && nameArr.push(dimInfo.displayName);
  });
  return nameArr.join(' ');
}

function dataTaskCount(context) {
  return context.model.getRawData().count();
}

function dataTaskReset(context) {
  var seriesModel = context.model;
  seriesModel.setData(seriesModel.getRawData().cloneShallow());
  return dataTaskProgress;
}

function dataTaskProgress(param, context) {
  // Avoid repeat cloneShallow when data just created in reset.
  if (context.outputData && param.end > context.outputData.count()) {
    context.model.getRawData().cloneShallow(context.outputData);
  }
} // TODO refactor


function wrapData(data, seriesModel) {
  each$4(concatArray(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) {
    data.wrapMethod(methodName, curry$1(onDataChange, seriesModel));
  });
}

function onDataChange(seriesModel, newList) {
  var task = getCurrentTask(seriesModel);

  if (task) {
    // Consider case: filter, selectRange
    task.setOutputEnd((newList || this).count());
  }

  return newList;
}

function getCurrentTask(seriesModel) {
  var scheduler = (seriesModel.ecModel || {}).scheduler;
  var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid);

  if (pipeline) {
    // When pipline finished, the currrentTask keep the last
    // task (renderTask).
    var task = pipeline.currentTask;

    if (task) {
      var agentStubMap = task.agentStubMap;

      if (agentStubMap) {
        task = agentStubMap.get(seriesModel.uid);
      }
    }

    return task;
  }
}

const SeriesModel$1 = SeriesModel;
/* Injected with object hook! */

var ComponentView =
/** @class */
function () {
  function ComponentView() {
    this.group = new Group$3();
    this.uid = getUID('viewComponent');
  }

  ComponentView.prototype.init = function (ecModel, api) {};

  ComponentView.prototype.render = function (model, ecModel, api, payload) {};

  ComponentView.prototype.dispose = function (ecModel, api) {};

  ComponentView.prototype.updateView = function (model, ecModel, api, payload) {// Do nothing;
  };

  ComponentView.prototype.updateLayout = function (model, ecModel, api, payload) {// Do nothing;
  };

  ComponentView.prototype.updateVisual = function (model, ecModel, api, payload) {// Do nothing;
  };
  /**
   * Hook for toggle blur target series.
   * Can be used in marker for blur or leave blur the markers
   */


  ComponentView.prototype.toggleBlurSeries = function (seriesModels, isBlur, ecModel) {// Do nothing;
  };
  /**
   * Traverse the new rendered elements.
   *
   * It will traverse the new added element in progressive rendering.
   * And traverse all in normal rendering.
   */


  ComponentView.prototype.eachRendered = function (cb) {
    var group = this.group;

    if (group) {
      group.traverse(cb);
    }
  };

  return ComponentView;
}();
enableClassExtend(ComponentView);
enableClassManagement(ComponentView);
const ComponentView$1 = ComponentView;
/* Injected with object hook! */

/**
 * @return {string} If large mode changed, return string 'reset';
 */

function createRenderPlanner() {
  var inner = makeInner();
  return function (seriesModel) {
    var fields = inner(seriesModel);
    var pipelineContext = seriesModel.pipelineContext;
    var originalLarge = !!fields.large;
    var originalProgressive = !!fields.progressiveRender; // FIXME: if the planner works on a filtered series, `pipelineContext` does not
    // exists. See #11611 . Probably we need to modify this structure, see the comment
    // on `performRawSeries` in `Schedular.js`.

    var large = fields.large = !!(pipelineContext && pipelineContext.large);
    var progressive = fields.progressiveRender = !!(pipelineContext && pipelineContext.progressiveRender);
    return !!(originalLarge !== large || originalProgressive !== progressive) && 'reset';
  };
}
/* Injected with object hook! */

var inner$7 = makeInner();
var renderPlanner = createRenderPlanner();

var ChartView =
/** @class */
function () {
  function ChartView() {
    this.group = new Group$3();
    this.uid = getUID('viewChart');
    this.renderTask = createTask({
      plan: renderTaskPlan,
      reset: renderTaskReset
    });
    this.renderTask.context = {
      view: this
    };
  }

  ChartView.prototype.init = function (ecModel, api) {};

  ChartView.prototype.render = function (seriesModel, ecModel, api, payload) {
  };
  /**
   * Highlight series or specified data item.
   */


  ChartView.prototype.highlight = function (seriesModel, ecModel, api, payload) {
    var data = seriesModel.getData(payload && payload.dataType);

    if (!data) {

      return;
    }

    toggleHighlight(data, payload, 'emphasis');
  };
  /**
   * Downplay series or specified data item.
   */


  ChartView.prototype.downplay = function (seriesModel, ecModel, api, payload) {
    var data = seriesModel.getData(payload && payload.dataType);

    if (!data) {

      return;
    }

    toggleHighlight(data, payload, 'normal');
  };
  /**
   * Remove self.
   */


  ChartView.prototype.remove = function (ecModel, api) {
    this.group.removeAll();
  };
  /**
   * Dispose self.
   */


  ChartView.prototype.dispose = function (ecModel, api) {};

  ChartView.prototype.updateView = function (seriesModel, ecModel, api, payload) {
    this.render(seriesModel, ecModel, api, payload);
  }; // FIXME never used?


  ChartView.prototype.updateLayout = function (seriesModel, ecModel, api, payload) {
    this.render(seriesModel, ecModel, api, payload);
  }; // FIXME never used?


  ChartView.prototype.updateVisual = function (seriesModel, ecModel, api, payload) {
    this.render(seriesModel, ecModel, api, payload);
  };
  /**
   * Traverse the new rendered elements.
   *
   * It will traverse the new added element in progressive rendering.
   * And traverse all in normal rendering.
   */


  ChartView.prototype.eachRendered = function (cb) {
    traverseElements(this.group, cb);
  };

  ChartView.markUpdateMethod = function (payload, methodName) {
    inner$7(payload).updateMethod = methodName;
  };

  ChartView.protoInitialize = function () {
    var proto = ChartView.prototype;
    proto.type = 'chart';
  }();

  return ChartView;
}();
/**
 * Set state of single element
 */

function elSetState(el, state, highlightDigit) {
  if (el && isHighDownDispatcher(el)) {
    (state === 'emphasis' ? enterEmphasis : leaveEmphasis)(el, highlightDigit);
  }
}

function toggleHighlight(data, payload, state) {
  var dataIndex = queryDataIndex(data, payload);
  var highlightDigit = payload && payload.highlightKey != null ? getHighlightDigit(payload.highlightKey) : null;

  if (dataIndex != null) {
    each$4(normalizeToArray(dataIndex), function (dataIdx) {
      elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit);
    });
  } else {
    data.eachItemGraphicEl(function (el) {
      elSetState(el, state, highlightDigit);
    });
  }
}

enableClassExtend(ChartView);
enableClassManagement(ChartView);

function renderTaskPlan(context) {
  return renderPlanner(context.model);
}

function renderTaskReset(context) {
  var seriesModel = context.model;
  var ecModel = context.ecModel;
  var api = context.api;
  var payload = context.payload; // FIXME: remove updateView updateVisual

  var progressiveRender = seriesModel.pipelineContext.progressiveRender;
  var view = context.view;
  var updateMethod = payload && inner$7(payload).updateMethod;
  var methodName = progressiveRender ? 'incrementalPrepareRender' : updateMethod && view[updateMethod] ? updateMethod // `appendData` is also supported when data amount
  // is less than progressive threshold.
  : 'render';

  if (methodName !== 'render') {
    view[methodName](seriesModel, ecModel, api, payload);
  }

  return progressMethodMap[methodName];
}

var progressMethodMap = {
  incrementalPrepareRender: {
    progress: function (params, context) {
      context.view.incrementalRender(params, context.model, context.ecModel, context.api, context.payload);
    }
  },
  render: {
    // Put view.render in `progress` to support appendData. But in this case
    // view.render should not be called in reset, otherwise it will be called
    // twise. Use `forceFirstProgress` to make sure that view.render is called
    // in any cases.
    forceFirstProgress: true,
    progress: function (params, context) {
      context.view.render(context.model, context.ecModel, context.api, context.payload);
    }
  }
};
const ChartView$1 = ChartView;
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var ORIGIN_METHOD = '\0__throttleOriginMethod';
var RATE = '\0__throttleRate';
var THROTTLE_TYPE = '\0__throttleType';
/**
 * @public
 * @param {(Function)} fn
 * @param {number} [delay=0] Unit: ms.
 * @param {boolean} [debounce=false]
 *        true: If call interval less than `delay`, only the last call works.
 *        false: If call interval less than `delay, call works on fixed rate.
 * @return {(Function)} throttled fn.
 */

function throttle(fn, delay, debounce) {
  var currCall;
  var lastCall = 0;
  var lastExec = 0;
  var timer = null;
  var diff;
  var scope;
  var args;
  var debounceNextCall;
  delay = delay || 0;

  function exec() {
    lastExec = new Date().getTime();
    timer = null;
    fn.apply(scope, args || []);
  }

  var cb = function () {
    var cbArgs = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      cbArgs[_i] = arguments[_i];
    }

    currCall = new Date().getTime();
    scope = this;
    args = cbArgs;
    var thisDelay = debounceNextCall || delay;
    var thisDebounce = debounceNextCall || debounce;
    debounceNextCall = null;
    diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay;
    clearTimeout(timer); // Here we should make sure that: the `exec` SHOULD NOT be called later
    // than a new call of `cb`, that is, preserving the command order. Consider
    // calculating "scale rate" when roaming as an example. When a call of `cb`
    // happens, either the `exec` is called dierectly, or the call is delayed.
    // But the delayed call should never be later than next call of `cb`. Under
    // this assurance, we can simply update view state each time `dispatchAction`
    // triggered by user roaming, but not need to add extra code to avoid the
    // state being "rolled-back".

    if (thisDebounce) {
      timer = setTimeout(exec, thisDelay);
    } else {
      if (diff >= 0) {
        exec();
      } else {
        timer = setTimeout(exec, -diff);
      }
    }

    lastCall = currCall;
  };
  /**
   * Clear throttle.
   * @public
   */


  cb.clear = function () {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
  };
  /**
   * Enable debounce once.
   */


  cb.debounceNextCall = function (debounceDelay) {
    debounceNextCall = debounceDelay;
  };

  return cb;
}
/**
 * Create throttle method or update throttle rate.
 *
 * @example
 * ComponentView.prototype.render = function () {
 *     ...
 *     throttle.createOrUpdate(
 *         this,
 *         '_dispatchAction',
 *         this.model.get('throttle'),
 *         'fixRate'
 *     );
 * };
 * ComponentView.prototype.remove = function () {
 *     throttle.clear(this, '_dispatchAction');
 * };
 * ComponentView.prototype.dispose = function () {
 *     throttle.clear(this, '_dispatchAction');
 * };
 *
 */

function createOrUpdate(obj, fnAttr, rate, throttleType) {
  var fn = obj[fnAttr];

  if (!fn) {
    return;
  }

  var originFn = fn[ORIGIN_METHOD] || fn;
  var lastThrottleType = fn[THROTTLE_TYPE];
  var lastRate = fn[RATE];

  if (lastRate !== rate || lastThrottleType !== throttleType) {
    if (rate == null || !throttleType) {
      return obj[fnAttr] = originFn;
    }

    fn = obj[fnAttr] = throttle(originFn, rate, throttleType === 'debounce');
    fn[ORIGIN_METHOD] = originFn;
    fn[THROTTLE_TYPE] = throttleType;
    fn[RATE] = rate;
  }

  return fn;
}
/**
 * Clear throttle. Example see throttle.createOrUpdate.
 */

function clear(obj, fnAttr) {
  var fn = obj[fnAttr];

  if (fn && fn[ORIGIN_METHOD]) {
    // Clear throttle
    fn.clear && fn.clear();
    obj[fnAttr] = fn[ORIGIN_METHOD];
  }
}
/* Injected with object hook! */

var inner$6 = makeInner();
var defaultStyleMappers = {
  itemStyle: makeStyleMapper(ITEM_STYLE_KEY_MAP, true),
  lineStyle: makeStyleMapper(LINE_STYLE_KEY_MAP, true)
};
var defaultColorKey = {
  lineStyle: 'stroke',
  itemStyle: 'fill'
};

function getStyleMapper(seriesModel, stylePath) {
  var styleMapper = seriesModel.visualStyleMapper || defaultStyleMappers[stylePath];

  if (!styleMapper) {
    console.warn("Unknown style type '" + stylePath + "'.");
    return defaultStyleMappers.itemStyle;
  }

  return styleMapper;
}

function getDefaultColorKey(seriesModel, stylePath) {
  // return defaultColorKey[stylePath] ||
  var colorKey = seriesModel.visualDrawType || defaultColorKey[stylePath];

  if (!colorKey) {
    console.warn("Unknown style type '" + stylePath + "'.");
    return 'fill';
  }

  return colorKey;
}

var seriesStyleTask = {
  createOnAllSeries: true,
  performRawSeries: true,
  reset: function (seriesModel, ecModel) {
    var data = seriesModel.getData();
    var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle

    var styleModel = seriesModel.getModel(stylePath);
    var getStyle = getStyleMapper(seriesModel, stylePath);
    var globalStyle = getStyle(styleModel);
    var decalOption = styleModel.getShallow('decal');

    if (decalOption) {
      data.setVisual('decal', decalOption);
      decalOption.dirty = true;
    } // TODO


    var colorKey = getDefaultColorKey(seriesModel, stylePath);
    var color = globalStyle[colorKey]; // TODO style callback

    var colorCallback = isFunction(color) ? color : null;
    var hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto'; // Get from color palette by default.

    if (!globalStyle[colorKey] || colorCallback || hasAutoColor) {
      // Note: If some series has color specified (e.g., by itemStyle.color), we DO NOT
      // make it effect palette. Because some scenarios users need to make some series
      // transparent or as background, which should better not effect the palette.
      var colorPalette = seriesModel.getColorFromPalette( // TODO series count changed.
      seriesModel.name, null, ecModel.getSeriesCount());

      if (!globalStyle[colorKey]) {
        globalStyle[colorKey] = colorPalette;
        data.setVisual('colorFromPalette', true);
      }

      globalStyle.fill = globalStyle.fill === 'auto' || isFunction(globalStyle.fill) ? colorPalette : globalStyle.fill;
      globalStyle.stroke = globalStyle.stroke === 'auto' || isFunction(globalStyle.stroke) ? colorPalette : globalStyle.stroke;
    }

    data.setVisual('style', globalStyle);
    data.setVisual('drawType', colorKey); // Only visible series has each data be visual encoded

    if (!ecModel.isSeriesFiltered(seriesModel) && colorCallback) {
      data.setVisual('colorFromPalette', false);
      return {
        dataEach: function (data, idx) {
          var dataParams = seriesModel.getDataParams(idx);
          var itemStyle = extend({}, globalStyle);
          itemStyle[colorKey] = colorCallback(dataParams);
          data.setItemVisual(idx, 'style', itemStyle);
        }
      };
    }
  }
};
var sharedModel = new Model$1();
var dataStyleTask = {
  createOnAllSeries: true,
  performRawSeries: true,
  reset: function (seriesModel, ecModel) {
    if (seriesModel.ignoreStyleOnData || ecModel.isSeriesFiltered(seriesModel)) {
      return;
    }

    var data = seriesModel.getData();
    var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle

    var getStyle = getStyleMapper(seriesModel, stylePath);
    var colorKey = data.getVisual('drawType');
    return {
      dataEach: data.hasItemOption ? function (data, idx) {
        // Not use getItemModel for performance considuration
        var rawItem = data.getRawDataItem(idx);

        if (rawItem && rawItem[stylePath]) {
          sharedModel.option = rawItem[stylePath];
          var style = getStyle(sharedModel);
          var existsStyle = data.ensureUniqueItemVisual(idx, 'style');
          extend(existsStyle, style);

          if (sharedModel.option.decal) {
            data.setItemVisual(idx, 'decal', sharedModel.option.decal);
            sharedModel.option.decal.dirty = true;
          }

          if (colorKey in style) {
            data.setItemVisual(idx, 'colorFromPalette', false);
          }
        }
      } : null
    };
  }
}; // Pick color from palette for the data which has not been set with color yet.
// Note: do not support stream rendering. No such cases yet.

var dataColorPaletteTask = {
  performRawSeries: true,
  overallReset: function (ecModel) {
    // Each type of series uses one scope.
    // Pie and funnel are using different scopes.
    var paletteScopeGroupByType = createHashMap();
    ecModel.eachSeries(function (seriesModel) {
      var colorBy = seriesModel.getColorBy();

      if (seriesModel.isColorBySeries()) {
        return;
      }

      var key = seriesModel.type + '-' + colorBy;
      var colorScope = paletteScopeGroupByType.get(key);

      if (!colorScope) {
        colorScope = {};
        paletteScopeGroupByType.set(key, colorScope);
      }

      inner$6(seriesModel).scope = colorScope;
    });
    ecModel.eachSeries(function (seriesModel) {
      if (seriesModel.isColorBySeries() || ecModel.isSeriesFiltered(seriesModel)) {
        return;
      }

      var dataAll = seriesModel.getRawData();
      var idxMap = {};
      var data = seriesModel.getData();
      var colorScope = inner$6(seriesModel).scope;
      var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle';
      var colorKey = getDefaultColorKey(seriesModel, stylePath);
      data.each(function (idx) {
        var rawIdx = data.getRawIndex(idx);
        idxMap[rawIdx] = idx;
      }); // Iterate on data before filtered. To make sure color from palette can be
      // Consistent when toggling legend.

      dataAll.each(function (rawIdx) {
        var idx = idxMap[rawIdx];
        var fromPalette = data.getItemVisual(idx, 'colorFromPalette'); // Get color from palette for each data only when the color is inherited from series color, which is
        // also picked from color palette. So following situation is not in the case:
        // 1. series.itemStyle.color is set
        // 2. color is encoded by visualMap

        if (fromPalette) {
          var itemStyle = data.ensureUniqueItemVisual(idx, 'style');
          var name_1 = dataAll.getName(rawIdx) || rawIdx + '';
          var dataCount = dataAll.count();
          itemStyle[colorKey] = seriesModel.getColorFromPalette(name_1, colorScope, dataCount);
        }
      });
    });
  }
};
/* Injected with object hook! */

var PI$1 = Math.PI;
/**
 * @param {module:echarts/ExtensionAPI} api
 * @param {Object} [opts]
 * @param {string} [opts.text]
 * @param {string} [opts.color]
 * @param {string} [opts.textColor]
 * @return {module:zrender/Element}
 */

function defaultLoading(api, opts) {
  opts = opts || {};
  defaults(opts, {
    text: 'loading',
    textColor: '#000',
    fontSize: 12,
    fontWeight: 'normal',
    fontStyle: 'normal',
    fontFamily: 'sans-serif',
    maskColor: 'rgba(255, 255, 255, 0.8)',
    showSpinner: true,
    color: '#5470c6',
    spinnerRadius: 10,
    lineWidth: 5,
    zlevel: 0
  });
  var group = new Group$3();
  var mask = new Rect$1({
    style: {
      fill: opts.maskColor
    },
    zlevel: opts.zlevel,
    z: 10000
  });
  group.add(mask);
  var textContent = new ZRText$1({
    style: {
      text: opts.text,
      fill: opts.textColor,
      fontSize: opts.fontSize,
      fontWeight: opts.fontWeight,
      fontStyle: opts.fontStyle,
      fontFamily: opts.fontFamily
    },
    zlevel: opts.zlevel,
    z: 10001
  });
  var labelRect = new Rect$1({
    style: {
      fill: 'none'
    },
    textContent: textContent,
    textConfig: {
      position: 'right',
      distance: 10
    },
    zlevel: opts.zlevel,
    z: 10001
  });
  group.add(labelRect);
  var arc;

  if (opts.showSpinner) {
    arc = new Arc$1({
      shape: {
        startAngle: -PI$1 / 2,
        endAngle: -PI$1 / 2 + 0.1,
        r: opts.spinnerRadius
      },
      style: {
        stroke: opts.color,
        lineCap: 'round',
        lineWidth: opts.lineWidth
      },
      zlevel: opts.zlevel,
      z: 10001
    });
    arc.animateShape(true).when(1000, {
      endAngle: PI$1 * 3 / 2
    }).start('circularInOut');
    arc.animateShape(true).when(1000, {
      startAngle: PI$1 * 3 / 2
    }).delay(300).start('circularInOut');
    group.add(arc);
  } // Inject resize


  group.resize = function () {
    var textWidth = textContent.getBoundingRect().width;
    var r = opts.showSpinner ? opts.spinnerRadius : 0; // cx = (containerWidth - arcDiameter - textDistance - textWidth) / 2
    // textDistance needs to be calculated when both animation and text exist

    var cx = (api.getWidth() - r * 2 - (opts.showSpinner && textWidth ? 10 : 0) - textWidth) / 2 - (opts.showSpinner && textWidth ? 0 : 5 + textWidth / 2) // only show the text
    + (opts.showSpinner ? 0 : textWidth / 2) // only show the spinner
    + (textWidth ? 0 : r);
    var cy = api.getHeight() / 2;
    opts.showSpinner && arc.setShape({
      cx: cx,
      cy: cy
    });
    labelRect.setShape({
      x: cx - r,
      y: cy - r,
      width: r * 2,
      height: r * 2
    });
    mask.setShape({
      x: 0,
      y: 0,
      width: api.getWidth(),
      height: api.getHeight()
    });
  };

  group.resize();
  return group;
}
/* Injected with object hook! */

var Scheduler =
/** @class */
function () {
  function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) {
    // key: handlerUID
    this._stageTaskMap = createHashMap();
    this.ecInstance = ecInstance;
    this.api = api; // Fix current processors in case that in some rear cases that
    // processors might be registered after echarts instance created.
    // Register processors incrementally for a echarts instance is
    // not supported by this stream architecture.

    dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice();
    visualHandlers = this._visualHandlers = visualHandlers.slice();
    this._allHandlers = dataProcessorHandlers.concat(visualHandlers);
  }

  Scheduler.prototype.restoreData = function (ecModel, payload) {
    // TODO: Only restore needed series and components, but not all components.
    // Currently `restoreData` of all of the series and component will be called.
    // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
    // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
    // and some components like coordinate system, axes, dataZoom, visualMap only
    // need their target series refresh.
    // (1) If we are implementing this feature some day, we should consider these cases:
    // if a data processor depends on a component (e.g., dataZoomProcessor depends
    // on the settings of `dataZoom`), it should be re-performed if the component
    // is modified by `setOption`.
    // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,
    // it should be re-performed when the result array of `getTargetSeries` changed.
    // We use `dependencies` to cover these issues.
    // (3) How to update target series when coordinate system related components modified.
    // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty,
    // and this case all of the tasks will be set as dirty.
    ecModel.restoreData(payload); // Theoretically an overall task not only depends on each of its target series, but also
    // depends on all of the series.
    // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks
    // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure
    // that the overall task is set as dirty and to be performed, otherwise it probably cause
    // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it
    // probably cause state chaos (consider `dataZoomProcessor`).

    this._stageTaskMap.each(function (taskRecord) {
      var overallTask = taskRecord.overallTask;
      overallTask && overallTask.dirty();
    });
  }; // If seriesModel provided, incremental threshold is check by series data.


  Scheduler.prototype.getPerformArgs = function (task, isBlock) {
    // For overall task
    if (!task.__pipeline) {
      return;
    }

    var pipeline = this._pipelineMap.get(task.__pipeline.id);

    var pCtx = pipeline.context;
    var incremental = !isBlock && pipeline.progressiveEnabled && (!pCtx || pCtx.progressiveRender) && task.__idxInPipeline > pipeline.blockIndex;
    var step = incremental ? pipeline.step : null;
    var modDataCount = pCtx && pCtx.modDataCount;
    var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null;
    return {
      step: step,
      modBy: modBy,
      modDataCount: modDataCount
    };
  };

  Scheduler.prototype.getPipeline = function (pipelineId) {
    return this._pipelineMap.get(pipelineId);
  };
  /**
   * Current, progressive rendering starts from visual and layout.
   * Always detect render mode in the same stage, avoiding that incorrect
   * detection caused by data filtering.
   * Caution:
   * `updateStreamModes` use `seriesModel.getData()`.
   */


  Scheduler.prototype.updateStreamModes = function (seriesModel, view) {
    var pipeline = this._pipelineMap.get(seriesModel.uid);

    var data = seriesModel.getData();
    var dataLen = data.count(); // `progressiveRender` means that can render progressively in each
    // animation frame. Note that some types of series do not provide
    // `view.incrementalPrepareRender` but support `chart.appendData`. We
    // use the term `incremental` but not `progressive` to describe the
    // case that `chart.appendData`.

    var progressiveRender = pipeline.progressiveEnabled && view.incrementalPrepareRender && dataLen >= pipeline.threshold;
    var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold'); // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint.
    // see `test/candlestick-large3.html`

    var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null;
    seriesModel.pipelineContext = pipeline.context = {
      progressiveRender: progressiveRender,
      modDataCount: modDataCount,
      large: large
    };
  };

  Scheduler.prototype.restorePipelines = function (ecModel) {
    var scheduler = this;
    var pipelineMap = scheduler._pipelineMap = createHashMap();
    ecModel.eachSeries(function (seriesModel) {
      var progressive = seriesModel.getProgressive();
      var pipelineId = seriesModel.uid;
      pipelineMap.set(pipelineId, {
        id: pipelineId,
        head: null,
        tail: null,
        threshold: seriesModel.getProgressiveThreshold(),
        progressiveEnabled: progressive && !(seriesModel.preventIncremental && seriesModel.preventIncremental()),
        blockIndex: -1,
        step: Math.round(progressive || 700),
        count: 0
      });

      scheduler._pipe(seriesModel, seriesModel.dataTask);
    });
  };

  Scheduler.prototype.prepareStageTasks = function () {
    var stageTaskMap = this._stageTaskMap;
    var ecModel = this.api.getModel();
    var api = this.api;
    each$4(this._allHandlers, function (handler) {
      var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {});
      var errMsg = '';

      assert(!(handler.reset && handler.overallReset), errMsg);
      handler.reset && this._createSeriesStageTask(handler, record, ecModel, api);
      handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api);
    }, this);
  };

  Scheduler.prototype.prepareView = function (view, model, ecModel, api) {
    var renderTask = view.renderTask;
    var context = renderTask.context;
    context.model = model;
    context.ecModel = ecModel;
    context.api = api;
    renderTask.__block = !view.incrementalPrepareRender;

    this._pipe(model, renderTask);
  };

  Scheduler.prototype.performDataProcessorTasks = function (ecModel, payload) {
    // If we do not use `block` here, it should be considered when to update modes.
    this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, {
      block: true
    });
  };

  Scheduler.prototype.performVisualTasks = function (ecModel, payload, opt) {
    this._performStageTasks(this._visualHandlers, ecModel, payload, opt);
  };

  Scheduler.prototype._performStageTasks = function (stageHandlers, ecModel, payload, opt) {
    opt = opt || {};
    var unfinished = false;
    var scheduler = this;
    each$4(stageHandlers, function (stageHandler, idx) {
      if (opt.visualType && opt.visualType !== stageHandler.visualType) {
        return;
      }

      var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid);

      var seriesTaskMap = stageHandlerRecord.seriesTaskMap;
      var overallTask = stageHandlerRecord.overallTask;

      if (overallTask) {
        var overallNeedDirty_1;
        var agentStubMap = overallTask.agentStubMap;
        agentStubMap.each(function (stub) {
          if (needSetDirty(opt, stub)) {
            stub.dirty();
            overallNeedDirty_1 = true;
          }
        });
        overallNeedDirty_1 && overallTask.dirty();
        scheduler.updatePayload(overallTask, payload);
        var performArgs_1 = scheduler.getPerformArgs(overallTask, opt.block); // Execute stubs firstly, which may set the overall task dirty,
        // then execute the overall task. And stub will call seriesModel.setData,
        // which ensures that in the overallTask seriesModel.getData() will not
        // return incorrect data.

        agentStubMap.each(function (stub) {
          stub.perform(performArgs_1);
        });

        if (overallTask.perform(performArgs_1)) {
          unfinished = true;
        }
      } else if (seriesTaskMap) {
        seriesTaskMap.each(function (task, pipelineId) {
          if (needSetDirty(opt, task)) {
            task.dirty();
          }

          var performArgs = scheduler.getPerformArgs(task, opt.block); // FIXME
          // if intending to declare `performRawSeries` in handlers, only
          // stream-independent (specifically, data item independent) operations can be
          // performed. Because if a series is filtered, most of the tasks will not
          // be performed. A stream-dependent operation probably cause wrong biz logic.
          // Perhaps we should not provide a separate callback for this case instead
          // of providing the config `performRawSeries`. The stream-dependent operations
          // and stream-independent operations should better not be mixed.

          performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model);
          scheduler.updatePayload(task, payload);

          if (task.perform(performArgs)) {
            unfinished = true;
          }
        });
      }
    });

    function needSetDirty(opt, task) {
      return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id));
    }

    this.unfinished = unfinished || this.unfinished;
  };

  Scheduler.prototype.performSeriesTasks = function (ecModel) {
    var unfinished;
    ecModel.eachSeries(function (seriesModel) {
      // Progress to the end for dataInit and dataRestore.
      unfinished = seriesModel.dataTask.perform() || unfinished;
    });
    this.unfinished = unfinished || this.unfinished;
  };

  Scheduler.prototype.plan = function () {
    // Travel pipelines, check block.
    this._pipelineMap.each(function (pipeline) {
      var task = pipeline.tail;

      do {
        if (task.__block) {
          pipeline.blockIndex = task.__idxInPipeline;
          break;
        }

        task = task.getUpstream();
      } while (task);
    });
  };

  Scheduler.prototype.updatePayload = function (task, payload) {
    payload !== 'remain' && (task.context.payload = payload);
  };

  Scheduler.prototype._createSeriesStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) {
    var scheduler = this;
    var oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap; // The count of stages are totally about only several dozen, so
    // do not need to reuse the map.

    var newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap();
    var seriesType = stageHandler.seriesType;
    var getTargetSeries = stageHandler.getTargetSeries; // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily,
    // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`,
    // it works but it may cause other irrelevant charts blocked.

    if (stageHandler.createOnAllSeries) {
      ecModel.eachRawSeries(create);
    } else if (seriesType) {
      ecModel.eachRawSeriesByType(seriesType, create);
    } else if (getTargetSeries) {
      getTargetSeries(ecModel, api).each(create);
    }

    function create(seriesModel) {
      var pipelineId = seriesModel.uid; // Init tasks for each seriesModel only once.
      // Reuse original task instance.

      var task = newSeriesTaskMap.set(pipelineId, oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId) || createTask({
        plan: seriesTaskPlan,
        reset: seriesTaskReset,
        count: seriesTaskCount
      }));
      task.context = {
        model: seriesModel,
        ecModel: ecModel,
        api: api,
        // PENDING: `useClearVisual` not used?
        useClearVisual: stageHandler.isVisual && !stageHandler.isLayout,
        plan: stageHandler.plan,
        reset: stageHandler.reset,
        scheduler: scheduler
      };

      scheduler._pipe(seriesModel, task);
    }
  };

  Scheduler.prototype._createOverallStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) {
    var scheduler = this;
    var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask // For overall task, the function only be called on reset stage.
    || createTask({
      reset: overallTaskReset
    });
    overallTask.context = {
      ecModel: ecModel,
      api: api,
      overallReset: stageHandler.overallReset,
      scheduler: scheduler
    };
    var oldAgentStubMap = overallTask.agentStubMap; // The count of stages are totally about only several dozen, so
    // do not need to reuse the map.

    var newAgentStubMap = overallTask.agentStubMap = createHashMap();
    var seriesType = stageHandler.seriesType;
    var getTargetSeries = stageHandler.getTargetSeries;
    var overallProgress = true;
    var shouldOverallTaskDirty = false; // FIXME:TS never used, so comment it
    // let modifyOutputEnd = stageHandler.modifyOutputEnd;
    // An overall task with seriesType detected or has `getTargetSeries`, we add
    // stub in each pipelines, it will set the overall task dirty when the pipeline
    // progress. Moreover, to avoid call the overall task each frame (too frequent),
    // we set the pipeline block.

    var errMsg = '';

    assert(!stageHandler.createOnAllSeries, errMsg);

    if (seriesType) {
      ecModel.eachRawSeriesByType(seriesType, createStub);
    } else if (getTargetSeries) {
      getTargetSeries(ecModel, api).each(createStub);
    } // Otherwise, (usually it is legacy case), the overall task will only be
    // executed when upstream is dirty. Otherwise the progressive rendering of all
    // pipelines will be disabled unexpectedly. But it still needs stubs to receive
    // dirty info from upstream.
    else {
        overallProgress = false;
        each$4(ecModel.getSeries(), createStub);
      }

    function createStub(seriesModel) {
      var pipelineId = seriesModel.uid;
      var stub = newAgentStubMap.set(pipelineId, oldAgentStubMap && oldAgentStubMap.get(pipelineId) || ( // When the result of `getTargetSeries` changed, the overallTask
      // should be set as dirty and re-performed.
      shouldOverallTaskDirty = true, createTask({
        reset: stubReset,
        onDirty: stubOnDirty
      })));
      stub.context = {
        model: seriesModel,
        overallProgress: overallProgress // FIXME:TS never used, so comment it
        // modifyOutputEnd: modifyOutputEnd

      };
      stub.agent = overallTask;
      stub.__block = overallProgress;

      scheduler._pipe(seriesModel, stub);
    }

    if (shouldOverallTaskDirty) {
      overallTask.dirty();
    }
  };

  Scheduler.prototype._pipe = function (seriesModel, task) {
    var pipelineId = seriesModel.uid;

    var pipeline = this._pipelineMap.get(pipelineId);

    !pipeline.head && (pipeline.head = task);
    pipeline.tail && pipeline.tail.pipe(task);
    pipeline.tail = task;
    task.__idxInPipeline = pipeline.count++;
    task.__pipeline = pipeline;
  };

  Scheduler.wrapStageHandler = function (stageHandler, visualType) {
    if (isFunction(stageHandler)) {
      stageHandler = {
        overallReset: stageHandler,
        seriesType: detectSeriseType(stageHandler)
      };
    }

    stageHandler.uid = getUID('stageHandler');
    visualType && (stageHandler.visualType = visualType);
    return stageHandler;
  };
  return Scheduler;
}();

function overallTaskReset(context) {
  context.overallReset(context.ecModel, context.api, context.payload);
}

function stubReset(context) {
  return context.overallProgress && stubProgress;
}

function stubProgress() {
  this.agent.dirty();
  this.getDownstream().dirty();
}

function stubOnDirty() {
  this.agent && this.agent.dirty();
}

function seriesTaskPlan(context) {
  return context.plan ? context.plan(context.model, context.ecModel, context.api, context.payload) : null;
}

function seriesTaskReset(context) {
  if (context.useClearVisual) {
    context.data.clearAllVisual();
  }

  var resetDefines = context.resetDefines = normalizeToArray(context.reset(context.model, context.ecModel, context.api, context.payload));
  return resetDefines.length > 1 ? map$1(resetDefines, function (v, idx) {
    return makeSeriesTaskProgress(idx);
  }) : singleSeriesTaskProgress;
}

var singleSeriesTaskProgress = makeSeriesTaskProgress(0);

function makeSeriesTaskProgress(resetDefineIdx) {
  return function (params, context) {
    var data = context.data;
    var resetDefine = context.resetDefines[resetDefineIdx];

    if (resetDefine && resetDefine.dataEach) {
      for (var i = params.start; i < params.end; i++) {
        resetDefine.dataEach(data, i);
      }
    } else if (resetDefine && resetDefine.progress) {
      resetDefine.progress(params, data);
    }
  };
}

function seriesTaskCount(context) {
  return context.data.count();
}
/**
 * Only some legacy stage handlers (usually in echarts extensions) are pure function.
 * To ensure that they can work normally, they should work in block mode, that is,
 * they should not be started util the previous tasks finished. So they cause the
 * progressive rendering disabled. We try to detect the series type, to narrow down
 * the block range to only the series type they concern, but not all series.
 */


function detectSeriseType(legacyFunc) {
  seriesType = null;

  try {
    // Assume there is no async when calling `eachSeriesByType`.
    legacyFunc(ecModelMock, apiMock);
  } catch (e) {}

  return seriesType;
}

var ecModelMock = {};
var apiMock = {};
var seriesType;
mockMethods(ecModelMock, GlobalModel$1);
mockMethods(apiMock, ExtensionAPI$1);

ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) {
  seriesType = type;
};

ecModelMock.eachComponent = function (cond) {
  if (cond.mainType === 'series' && cond.subType) {
    seriesType = cond.subType;
  }
};

function mockMethods(target, Clz) {
  /* eslint-disable */
  for (var name_1 in Clz.prototype) {
    // Do not use hasOwnProperty
    target[name_1] = noop;
  }
  /* eslint-enable */

}

const Scheduler$1 = Scheduler;
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var colorAll = ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'];
const lightTheme = {
  color: colorAll,
  colorLayer: [['#37A2DA', '#ffd85c', '#fd7b5f'], ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], colorAll]
};
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var contrastColor = '#B9B8CE';
var backgroundColor = '#100C2A';

var axisCommon = function () {
  return {
    axisLine: {
      lineStyle: {
        color: contrastColor
      }
    },
    splitLine: {
      lineStyle: {
        color: '#484753'
      }
    },
    splitArea: {
      areaStyle: {
        color: ['rgba(255,255,255,0.02)', 'rgba(255,255,255,0.05)']
      }
    },
    minorSplitLine: {
      lineStyle: {
        color: '#20203B'
      }
    }
  };
};

var colorPalette = ['#4992ff', '#7cffb2', '#fddd60', '#ff6e76', '#58d9f9', '#05c091', '#ff8a45', '#8d48e3', '#dd79ff'];
var theme = {
  darkMode: true,
  color: colorPalette,
  backgroundColor: backgroundColor,
  axisPointer: {
    lineStyle: {
      color: '#817f91'
    },
    crossStyle: {
      color: '#817f91'
    },
    label: {
      // TODO Contrast of label backgorundColor
      color: '#fff'
    }
  },
  legend: {
    textStyle: {
      color: contrastColor
    }
  },
  textStyle: {
    color: contrastColor
  },
  title: {
    textStyle: {
      color: '#EEF1FA'
    },
    subtextStyle: {
      color: '#B9B8CE'
    }
  },
  toolbox: {
    iconStyle: {
      borderColor: contrastColor
    }
  },
  dataZoom: {
    borderColor: '#71708A',
    textStyle: {
      color: contrastColor
    },
    brushStyle: {
      color: 'rgba(135,163,206,0.3)'
    },
    handleStyle: {
      color: '#353450',
      borderColor: '#C5CBE3'
    },
    moveHandleStyle: {
      color: '#B0B6C3',
      opacity: 0.3
    },
    fillerColor: 'rgba(135,163,206,0.2)',
    emphasis: {
      handleStyle: {
        borderColor: '#91B7F2',
        color: '#4D587D'
      },
      moveHandleStyle: {
        color: '#636D9A',
        opacity: 0.7
      }
    },
    dataBackground: {
      lineStyle: {
        color: '#71708A',
        width: 1
      },
      areaStyle: {
        color: '#71708A'
      }
    },
    selectedDataBackground: {
      lineStyle: {
        color: '#87A3CE'
      },
      areaStyle: {
        color: '#87A3CE'
      }
    }
  },
  visualMap: {
    textStyle: {
      color: contrastColor
    }
  },
  timeline: {
    lineStyle: {
      color: contrastColor
    },
    label: {
      color: contrastColor
    },
    controlStyle: {
      color: contrastColor,
      borderColor: contrastColor
    }
  },
  calendar: {
    itemStyle: {
      color: backgroundColor
    },
    dayLabel: {
      color: contrastColor
    },
    monthLabel: {
      color: contrastColor
    },
    yearLabel: {
      color: contrastColor
    }
  },
  timeAxis: axisCommon(),
  logAxis: axisCommon(),
  valueAxis: axisCommon(),
  categoryAxis: axisCommon(),
  line: {
    symbol: 'circle'
  },
  graph: {
    color: colorPalette
  },
  gauge: {
    title: {
      color: contrastColor
    },
    axisLine: {
      lineStyle: {
        color: [[1, 'rgba(207,212,219,0.2)']]
      }
    },
    axisLabel: {
      color: contrastColor
    },
    detail: {
      color: '#EEF1FA'
    }
  },
  candlestick: {
    itemStyle: {
      color: '#f64e56',
      color0: '#54ea92',
      borderColor: '#f64e56',
      borderColor0: '#54ea92' // borderColor: '#ca2824',
      // borderColor0: '#09a443'

    }
  }
};
theme.categoryAxis.splitLine.show = false;
const darkTheme = theme;
/* Injected with object hook! */

/**
 * Usage of query:
 * `chart.on('click', query, handler);`
 * The `query` can be:
 * + The component type query string, only `mainType` or `mainType.subType`,
 *   like: 'xAxis', 'series', 'xAxis.category' or 'series.line'.
 * + The component query object, like:
 *   `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`,
 *   `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`.
 * + The data query object, like:
 *   `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`.
 * + The other query object (cmponent customized query), like:
 *   `{element: 'some'}` (only available in custom series).
 *
 * Caveat: If a prop in the `query` object is `null/undefined`, it is the
 * same as there is no such prop in the `query` object.
 */

var ECEventProcessor =
/** @class */
function () {
  function ECEventProcessor() {}

  ECEventProcessor.prototype.normalizeQuery = function (query) {
    var cptQuery = {};
    var dataQuery = {};
    var otherQuery = {}; // `query` is `mainType` or `mainType.subType` of component.

    if (isString(query)) {
      var condCptType = parseClassType(query); // `.main` and `.sub` may be ''.

      cptQuery.mainType = condCptType.main || null;
      cptQuery.subType = condCptType.sub || null;
    } // `query` is an object, convert to {mainType, index, name, id}.
    else {
        // `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved,
        // can not be used in `compomentModel.filterForExposedEvent`.
        var suffixes_1 = ['Index', 'Name', 'Id'];
        var dataKeys_1 = {
          name: 1,
          dataIndex: 1,
          dataType: 1
        };
        each$4(query, function (val, key) {
          var reserved = false;

          for (var i = 0; i < suffixes_1.length; i++) {
            var propSuffix = suffixes_1[i];
            var suffixPos = key.lastIndexOf(propSuffix);

            if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) {
              var mainType = key.slice(0, suffixPos); // Consider `dataIndex`.

              if (mainType !== 'data') {
                cptQuery.mainType = mainType;
                cptQuery[propSuffix.toLowerCase()] = val;
                reserved = true;
              }
            }
          }

          if (dataKeys_1.hasOwnProperty(key)) {
            dataQuery[key] = val;
            reserved = true;
          }

          if (!reserved) {
            otherQuery[key] = val;
          }
        });
      }

    return {
      cptQuery: cptQuery,
      dataQuery: dataQuery,
      otherQuery: otherQuery
    };
  };

  ECEventProcessor.prototype.filter = function (eventType, query) {
    // They should be assigned before each trigger call.
    var eventInfo = this.eventInfo;

    if (!eventInfo) {
      return true;
    }

    var targetEl = eventInfo.targetEl;
    var packedEvent = eventInfo.packedEvent;
    var model = eventInfo.model;
    var view = eventInfo.view; // For event like 'globalout'.

    if (!model || !view) {
      return true;
    }

    var cptQuery = query.cptQuery;
    var dataQuery = query.dataQuery;
    return check(cptQuery, model, 'mainType') && check(cptQuery, model, 'subType') && check(cptQuery, model, 'index', 'componentIndex') && check(cptQuery, model, 'name') && check(cptQuery, model, 'id') && check(dataQuery, packedEvent, 'name') && check(dataQuery, packedEvent, 'dataIndex') && check(dataQuery, packedEvent, 'dataType') && (!view.filterForExposedEvent || view.filterForExposedEvent(eventType, query.otherQuery, targetEl, packedEvent));

    function check(query, host, prop, propOnHost) {
      return query[prop] == null || host[propOnHost || prop] === query[prop];
    }
  };

  ECEventProcessor.prototype.afterTrigger = function () {
    // Make sure the eventInfo won't be used in next trigger.
    this.eventInfo = null;
  };

  return ECEventProcessor;
}();
/* Injected with object hook! */

var SYMBOL_PROPS_WITH_CB = ['symbol', 'symbolSize', 'symbolRotate', 'symbolOffset'];
var SYMBOL_PROPS = SYMBOL_PROPS_WITH_CB.concat(['symbolKeepAspect']); // Encoding visual for all series include which is filtered for legend drawing

var seriesSymbolTask = {
  createOnAllSeries: true,
  // For legend.
  performRawSeries: true,
  reset: function (seriesModel, ecModel) {
    var data = seriesModel.getData();

    if (seriesModel.legendIcon) {
      data.setVisual('legendIcon', seriesModel.legendIcon);
    }

    if (!seriesModel.hasSymbolVisual) {
      return;
    }

    var symbolOptions = {};
    var symbolOptionsCb = {};
    var hasCallback = false;

    for (var i = 0; i < SYMBOL_PROPS_WITH_CB.length; i++) {
      var symbolPropName = SYMBOL_PROPS_WITH_CB[i];
      var val = seriesModel.get(symbolPropName);

      if (isFunction(val)) {
        hasCallback = true;
        symbolOptionsCb[symbolPropName] = val;
      } else {
        symbolOptions[symbolPropName] = val;
      }
    }

    symbolOptions.symbol = symbolOptions.symbol || seriesModel.defaultSymbol;
    data.setVisual(extend({
      legendIcon: seriesModel.legendIcon || symbolOptions.symbol,
      symbolKeepAspect: seriesModel.get('symbolKeepAspect')
    }, symbolOptions)); // Only visible series has each data be visual encoded

    if (ecModel.isSeriesFiltered(seriesModel)) {
      return;
    }

    var symbolPropsCb = keys(symbolOptionsCb);

    function dataEach(data, idx) {
      var rawValue = seriesModel.getRawValue(idx);
      var params = seriesModel.getDataParams(idx);

      for (var i = 0; i < symbolPropsCb.length; i++) {
        var symbolPropName = symbolPropsCb[i];
        data.setItemVisual(idx, symbolPropName, symbolOptionsCb[symbolPropName](rawValue, params));
      }
    }

    return {
      dataEach: hasCallback ? dataEach : null
    };
  }
};
var dataSymbolTask = {
  createOnAllSeries: true,
  // For legend.
  performRawSeries: true,
  reset: function (seriesModel, ecModel) {
    if (!seriesModel.hasSymbolVisual) {
      return;
    } // Only visible series has each data be visual encoded


    if (ecModel.isSeriesFiltered(seriesModel)) {
      return;
    }

    var data = seriesModel.getData();

    function dataEach(data, idx) {
      var itemModel = data.getItemModel(idx);

      for (var i = 0; i < SYMBOL_PROPS.length; i++) {
        var symbolPropName = SYMBOL_PROPS[i];
        var val = itemModel.getShallow(symbolPropName, true);

        if (val != null) {
          data.setItemVisual(idx, symbolPropName, val);
        }
      }
    }

    return {
      dataEach: data.hasItemOption ? dataEach : null
    };
  }
};
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function getItemVisualFromData(data, dataIndex, key) {
  switch (key) {
    case 'color':
      var style = data.getItemVisual(dataIndex, 'style');
      return style[data.getVisual('drawType')];

    case 'opacity':
      return data.getItemVisual(dataIndex, 'style').opacity;

    case 'symbol':
    case 'symbolSize':
    case 'liftZ':
      return data.getItemVisual(dataIndex, key);

  }
}
function getVisualFromData(data, key) {
  switch (key) {
    case 'color':
      var style = data.getVisual('style');
      return style[data.getVisual('drawType')];

    case 'opacity':
      return data.getVisual('style').opacity;

    case 'symbol':
    case 'symbolSize':
    case 'liftZ':
      return data.getVisual(key);

  }
}
/* Injected with object hook! */

function handleSeriesLegacySelectEvents(type, eventPostfix, ecIns, ecModel, payload) {
  var legacyEventName = type + eventPostfix;

  if (!ecIns.isSilent(legacyEventName)) {

    ecModel.eachComponent({
      mainType: 'series',
      subType: 'pie'
    }, function (seriesModel) {
      var seriesIndex = seriesModel.seriesIndex;
      var selectedMap = seriesModel.option.selectedMap;
      var selected = payload.selected;

      for (var i = 0; i < selected.length; i++) {
        if (selected[i].seriesIndex === seriesIndex) {
          var data = seriesModel.getData();
          var dataIndex = queryDataIndex(data, payload.fromActionPayload);
          ecIns.trigger(legacyEventName, {
            type: legacyEventName,
            seriesId: seriesModel.id,
            name: isArray(dataIndex) ? data.getName(dataIndex[0]) : data.getName(dataIndex),
            selected: isString(selectedMap) ? selectedMap : extend({}, selectedMap)
          });
        }
      }
    });
  }
}

function handleLegacySelectEvents(messageCenter, ecIns, api) {
  messageCenter.on('selectchanged', function (params) {
    var ecModel = api.getModel();

    if (params.isFromClick) {
      handleSeriesLegacySelectEvents('map', 'selectchanged', ecIns, ecModel, params);
      handleSeriesLegacySelectEvents('pie', 'selectchanged', ecIns, ecModel, params);
    } else if (params.fromAction === 'select') {
      handleSeriesLegacySelectEvents('map', 'selected', ecIns, ecModel, params);
      handleSeriesLegacySelectEvents('pie', 'selected', ecIns, ecModel, params);
    } else if (params.fromAction === 'unselect') {
      handleSeriesLegacySelectEvents('map', 'unselected', ecIns, ecModel, params);
      handleSeriesLegacySelectEvents('pie', 'unselected', ecIns, ecModel, params);
    }
  });
}
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function findEventDispatcher(target, det, returnFirstMatch) {
  var found;

  while (target) {
    if (det(target)) {
      found = target;

      if (returnFirstMatch) {
        break;
      }
    }

    target = target.__hostTarget || target.parent;
  }

  return found;
}
/* Injected with object hook! */

var wmUniqueIndex = Math.round(Math.random() * 9);
var supportDefineProperty = typeof Object.defineProperty === 'function';
var WeakMap$1 = (function () {
    function WeakMap() {
        this._id = '__ec_inner_' + wmUniqueIndex++;
    }
    WeakMap.prototype.get = function (key) {
        return this._guard(key)[this._id];
    };
    WeakMap.prototype.set = function (key, value) {
        var target = this._guard(key);
        if (supportDefineProperty) {
            Object.defineProperty(target, this._id, {
                value: value,
                enumerable: false,
                configurable: true
            });
        }
        else {
            target[this._id] = value;
        }
        return this;
    };
    WeakMap.prototype["delete"] = function (key) {
        if (this.has(key)) {
            delete this._guard(key)[this._id];
            return true;
        }
        return false;
    };
    WeakMap.prototype.has = function (key) {
        return !!this._guard(key)[this._id];
    };
    WeakMap.prototype._guard = function (key) {
        if (key !== Object(key)) {
            throw TypeError('Value of WeakMap is not a non-null object.');
        }
        return key;
    };
    return WeakMap;
}());
const WeakMap$2 = WeakMap$1;

/* Injected with object hook! */

/**
 * Triangle shape
 * @inner
 */

var Triangle = Path$1.extend({
  type: 'triangle',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx, cy - height);
    path.lineTo(cx + width, cy + height);
    path.lineTo(cx - width, cy + height);
    path.closePath();
  }
});
/**
 * Diamond shape
 * @inner
 */

var Diamond = Path$1.extend({
  type: 'diamond',
  shape: {
    cx: 0,
    cy: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var width = shape.width / 2;
    var height = shape.height / 2;
    path.moveTo(cx, cy - height);
    path.lineTo(cx + width, cy);
    path.lineTo(cx, cy + height);
    path.lineTo(cx - width, cy);
    path.closePath();
  }
});
/**
 * Pin shape
 * @inner
 */

var Pin = Path$1.extend({
  type: 'pin',
  shape: {
    // x, y on the cusp
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (path, shape) {
    var x = shape.x;
    var y = shape.y;
    var w = shape.width / 5 * 3; // Height must be larger than width

    var h = Math.max(w, shape.height);
    var r = w / 2; // Dist on y with tangent point and circle center

    var dy = r * r / (h - r);
    var cy = y - h + r + dy;
    var angle = Math.asin(dy / r); // Dist on x with tangent point and circle center

    var dx = Math.cos(angle) * r;
    var tanX = Math.sin(angle);
    var tanY = Math.cos(angle);
    var cpLen = r * 0.6;
    var cpLen2 = r * 0.7;
    path.moveTo(x - dx, cy + dy);
    path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle);
    path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y);
    path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy);
    path.closePath();
  }
});
/**
 * Arrow shape
 * @inner
 */

var Arrow = Path$1.extend({
  type: 'arrow',
  shape: {
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  buildPath: function (ctx, shape) {
    var height = shape.height;
    var width = shape.width;
    var x = shape.x;
    var y = shape.y;
    var dx = width / 3 * 2;
    ctx.moveTo(x, y);
    ctx.lineTo(x + dx, y + height);
    ctx.lineTo(x, y + height / 4 * 3);
    ctx.lineTo(x - dx, y + height);
    ctx.lineTo(x, y);
    ctx.closePath();
  }
});
/**
 * Map of path constructors
 */
// TODO Use function to build symbol path.

var symbolCtors = {
  line: Line$1,
  rect: Rect$1,
  roundRect: Rect$1,
  square: Rect$1,
  circle: Circle$1,
  diamond: Diamond,
  pin: Pin,
  arrow: Arrow,
  triangle: Triangle
};
var symbolShapeMakers = {
  line: function (x, y, w, h, shape) {
    shape.x1 = x;
    shape.y1 = y + h / 2;
    shape.x2 = x + w;
    shape.y2 = y + h / 2;
  },
  rect: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
  },
  roundRect: function (x, y, w, h, shape) {
    shape.x = x;
    shape.y = y;
    shape.width = w;
    shape.height = h;
    shape.r = Math.min(w, h) / 4;
  },
  square: function (x, y, w, h, shape) {
    var size = Math.min(w, h);
    shape.x = x;
    shape.y = y;
    shape.width = size;
    shape.height = size;
  },
  circle: function (x, y, w, h, shape) {
    // Put circle in the center of square
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.r = Math.min(w, h) / 2;
  },
  diamond: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  pin: function (x, y, w, h, shape) {
    shape.x = x + w / 2;
    shape.y = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  arrow: function (x, y, w, h, shape) {
    shape.x = x + w / 2;
    shape.y = y + h / 2;
    shape.width = w;
    shape.height = h;
  },
  triangle: function (x, y, w, h, shape) {
    shape.cx = x + w / 2;
    shape.cy = y + h / 2;
    shape.width = w;
    shape.height = h;
  }
};
var symbolBuildProxies = {};
each$4(symbolCtors, function (Ctor, name) {
  symbolBuildProxies[name] = new Ctor();
});
var SymbolClz = Path$1.extend({
  type: 'symbol',
  shape: {
    symbolType: '',
    x: 0,
    y: 0,
    width: 0,
    height: 0
  },
  calculateTextPosition: function (out, config, rect) {
    var res = calculateTextPosition(out, config, rect);
    var shape = this.shape;

    if (shape && shape.symbolType === 'pin' && config.position === 'inside') {
      res.y = rect.y + rect.height * 0.4;
    }

    return res;
  },
  buildPath: function (ctx, shape, inBundle) {
    var symbolType = shape.symbolType;

    if (symbolType !== 'none') {
      var proxySymbol = symbolBuildProxies[symbolType];

      if (!proxySymbol) {
        // Default rect
        symbolType = 'rect';
        proxySymbol = symbolBuildProxies[symbolType];
      }

      symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape);
      proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle);
    }
  }
}); // Provide setColor helper method to avoid determine if set the fill or stroke outside

function symbolPathSetColor(color, innerColor) {
  if (this.type !== 'image') {
    var symbolStyle = this.style;

    if (this.__isEmptyBrush) {
      symbolStyle.stroke = color;
      symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView

      symbolStyle.lineWidth = 2;
    } else if (this.shape.symbolType === 'line') {
      symbolStyle.stroke = color;
    } else {
      symbolStyle.fill = color;
    }

    this.markRedraw();
  }
}
/**
 * Create a symbol element with given symbol configuration: shape, x, y, width, height, color
 */


function createSymbol(symbolType, x, y, w, h, color, // whether to keep the ratio of w/h,
keepAspect) {
  // TODO Support image object, DynamicImage.
  var isEmpty = symbolType.indexOf('empty') === 0;

  if (isEmpty) {
    symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
  }

  var symbolPath;

  if (symbolType.indexOf('image://') === 0) {
    symbolPath = makeImage(symbolType.slice(8), new BoundingRect$1(x, y, w, h), keepAspect ? 'center' : 'cover');
  } else if (symbolType.indexOf('path://') === 0) {
    symbolPath = makePath(symbolType.slice(7), {}, new BoundingRect$1(x, y, w, h), keepAspect ? 'center' : 'cover');
  } else {
    symbolPath = new SymbolClz({
      shape: {
        symbolType: symbolType,
        x: x,
        y: y,
        width: w,
        height: h
      }
    });
  }

  symbolPath.__isEmptyBrush = isEmpty; // TODO Should deprecate setColor

  symbolPath.setColor = symbolPathSetColor;

  if (color) {
    symbolPath.setColor(color);
  }

  return symbolPath;
}
function normalizeSymbolOffset(symbolOffset, symbolSize) {
  if (symbolOffset == null) {
    return;
  }

  if (!isArray(symbolOffset)) {
    symbolOffset = [symbolOffset, symbolOffset];
  }

  return [parsePercent(symbolOffset[0], symbolSize[0]) || 0, parsePercent(retrieve2(symbolOffset[1], symbolOffset[0]), symbolSize[1]) || 0];
}
/* Injected with object hook! */

function isSafeNum(num) {
    return isFinite(num);
}
function createLinearGradient(ctx, obj, rect) {
    var x = obj.x == null ? 0 : obj.x;
    var x2 = obj.x2 == null ? 1 : obj.x2;
    var y = obj.y == null ? 0 : obj.y;
    var y2 = obj.y2 == null ? 0 : obj.y2;
    if (!obj.global) {
        x = x * rect.width + rect.x;
        x2 = x2 * rect.width + rect.x;
        y = y * rect.height + rect.y;
        y2 = y2 * rect.height + rect.y;
    }
    x = isSafeNum(x) ? x : 0;
    x2 = isSafeNum(x2) ? x2 : 1;
    y = isSafeNum(y) ? y : 0;
    y2 = isSafeNum(y2) ? y2 : 0;
    var canvasGradient = ctx.createLinearGradient(x, y, x2, y2);
    return canvasGradient;
}
function createRadialGradient(ctx, obj, rect) {
    var width = rect.width;
    var height = rect.height;
    var min = Math.min(width, height);
    var x = obj.x == null ? 0.5 : obj.x;
    var y = obj.y == null ? 0.5 : obj.y;
    var r = obj.r == null ? 0.5 : obj.r;
    if (!obj.global) {
        x = x * width + rect.x;
        y = y * height + rect.y;
        r = r * min;
    }
    x = isSafeNum(x) ? x : 0.5;
    y = isSafeNum(y) ? y : 0.5;
    r = r >= 0 && isSafeNum(r) ? r : 0.5;
    var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r);
    return canvasGradient;
}
function getCanvasGradient(ctx, obj, rect) {
    var canvasGradient = obj.type === 'radial'
        ? createRadialGradient(ctx, obj, rect)
        : createLinearGradient(ctx, obj, rect);
    var colorStops = obj.colorStops;
    for (var i = 0; i < colorStops.length; i++) {
        canvasGradient.addColorStop(colorStops[i].offset, colorStops[i].color);
    }
    return canvasGradient;
}
function isClipPathChanged(clipPaths, prevClipPaths) {
    if (clipPaths === prevClipPaths || (!clipPaths && !prevClipPaths)) {
        return false;
    }
    if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) {
        return true;
    }
    for (var i = 0; i < clipPaths.length; i++) {
        if (clipPaths[i] !== prevClipPaths[i]) {
            return true;
        }
    }
    return false;
}
function parseInt10(val) {
    return parseInt(val, 10);
}
function getSize(root, whIdx, opts) {
    var wh = ['width', 'height'][whIdx];
    var cwh = ['clientWidth', 'clientHeight'][whIdx];
    var plt = ['paddingLeft', 'paddingTop'][whIdx];
    var prb = ['paddingRight', 'paddingBottom'][whIdx];
    if (opts[wh] != null && opts[wh] !== 'auto') {
        return parseFloat(opts[wh]);
    }
    var stl = document.defaultView.getComputedStyle(root);
    return ((root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh]))
        - (parseInt10(stl[plt]) || 0)
        - (parseInt10(stl[prb]) || 0)) | 0;
}

/* Injected with object hook! */

function normalizeLineDash(lineType, lineWidth) {
    if (!lineType || lineType === 'solid' || !(lineWidth > 0)) {
        return null;
    }
    return lineType === 'dashed'
        ? [4 * lineWidth, 2 * lineWidth]
        : lineType === 'dotted'
            ? [lineWidth]
            : isNumber(lineType)
                ? [lineType] : isArray(lineType) ? lineType : null;
}
function getLineDash(el) {
    var style = el.style;
    var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth);
    var lineDashOffset = style.lineDashOffset;
    if (lineDash) {
        var lineScale_1 = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1;
        if (lineScale_1 && lineScale_1 !== 1) {
            lineDash = map$1(lineDash, function (rawVal) {
                return rawVal / lineScale_1;
            });
            lineDashOffset /= lineScale_1;
        }
    }
    return [lineDash, lineDashOffset];
}

/* Injected with object hook! */

var pathProxyForDraw = new PathProxy$1(true);
function styleHasStroke(style) {
    var stroke = style.stroke;
    return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
}
function isValidStrokeFillStyle(strokeOrFill) {
    return typeof strokeOrFill === 'string' && strokeOrFill !== 'none';
}
function styleHasFill(style) {
    var fill = style.fill;
    return fill != null && fill !== 'none';
}
function doFillPath(ctx, style) {
    if (style.fillOpacity != null && style.fillOpacity !== 1) {
        var originalGlobalAlpha = ctx.globalAlpha;
        ctx.globalAlpha = style.fillOpacity * style.opacity;
        ctx.fill();
        ctx.globalAlpha = originalGlobalAlpha;
    }
    else {
        ctx.fill();
    }
}
function doStrokePath(ctx, style) {
    if (style.strokeOpacity != null && style.strokeOpacity !== 1) {
        var originalGlobalAlpha = ctx.globalAlpha;
        ctx.globalAlpha = style.strokeOpacity * style.opacity;
        ctx.stroke();
        ctx.globalAlpha = originalGlobalAlpha;
    }
    else {
        ctx.stroke();
    }
}
function createCanvasPattern(ctx, pattern, el) {
    var image = createOrUpdateImage(pattern.image, pattern.__image, el);
    if (isImageReady(image)) {
        var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat');
        if (typeof DOMMatrix === 'function'
            && canvasPattern
            && canvasPattern.setTransform) {
            var matrix = new DOMMatrix();
            matrix.translateSelf((pattern.x || 0), (pattern.y || 0));
            matrix.rotateSelf(0, 0, (pattern.rotation || 0) * RADIAN_TO_DEGREE);
            matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1));
            canvasPattern.setTransform(matrix);
        }
        return canvasPattern;
    }
}
function brushPath(ctx, el, style, inBatch) {
    var _a;
    var hasStroke = styleHasStroke(style);
    var hasFill = styleHasFill(style);
    var strokePercent = style.strokePercent;
    var strokePart = strokePercent < 1;
    var firstDraw = !el.path;
    if ((!el.silent || strokePart) && firstDraw) {
        el.createPathProxy();
    }
    var path = el.path || pathProxyForDraw;
    var dirtyFlag = el.__dirty;
    if (!inBatch) {
        var fill = style.fill;
        var stroke = style.stroke;
        var hasFillGradient = hasFill && !!fill.colorStops;
        var hasStrokeGradient = hasStroke && !!stroke.colorStops;
        var hasFillPattern = hasFill && !!fill.image;
        var hasStrokePattern = hasStroke && !!stroke.image;
        var fillGradient = void 0;
        var strokeGradient = void 0;
        var fillPattern = void 0;
        var strokePattern = void 0;
        var rect = void 0;
        if (hasFillGradient || hasStrokeGradient) {
            rect = el.getBoundingRect();
        }
        if (hasFillGradient) {
            fillGradient = dirtyFlag
                ? getCanvasGradient(ctx, fill, rect)
                : el.__canvasFillGradient;
            el.__canvasFillGradient = fillGradient;
        }
        if (hasStrokeGradient) {
            strokeGradient = dirtyFlag
                ? getCanvasGradient(ctx, stroke, rect)
                : el.__canvasStrokeGradient;
            el.__canvasStrokeGradient = strokeGradient;
        }
        if (hasFillPattern) {
            fillPattern = (dirtyFlag || !el.__canvasFillPattern)
                ? createCanvasPattern(ctx, fill, el)
                : el.__canvasFillPattern;
            el.__canvasFillPattern = fillPattern;
        }
        if (hasStrokePattern) {
            strokePattern = (dirtyFlag || !el.__canvasStrokePattern)
                ? createCanvasPattern(ctx, stroke, el)
                : el.__canvasStrokePattern;
            el.__canvasStrokePattern = fillPattern;
        }
        if (hasFillGradient) {
            ctx.fillStyle = fillGradient;
        }
        else if (hasFillPattern) {
            if (fillPattern) {
                ctx.fillStyle = fillPattern;
            }
            else {
                hasFill = false;
            }
        }
        if (hasStrokeGradient) {
            ctx.strokeStyle = strokeGradient;
        }
        else if (hasStrokePattern) {
            if (strokePattern) {
                ctx.strokeStyle = strokePattern;
            }
            else {
                hasStroke = false;
            }
        }
    }
    var scale = el.getGlobalScale();
    path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold);
    var lineDash;
    var lineDashOffset;
    if (ctx.setLineDash && style.lineDash) {
        _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1];
    }
    var needsRebuild = true;
    if (firstDraw || (dirtyFlag & SHAPE_CHANGED_BIT)) {
        path.setDPR(ctx.dpr);
        if (strokePart) {
            path.setContext(null);
        }
        else {
            path.setContext(ctx);
            needsRebuild = false;
        }
        path.reset();
        el.buildPath(path, el.shape, inBatch);
        path.toStatic();
        el.pathUpdated();
    }
    if (needsRebuild) {
        path.rebuildPath(ctx, strokePart ? strokePercent : 1);
    }
    if (lineDash) {
        ctx.setLineDash(lineDash);
        ctx.lineDashOffset = lineDashOffset;
    }
    if (!inBatch) {
        if (style.strokeFirst) {
            if (hasStroke) {
                doStrokePath(ctx, style);
            }
            if (hasFill) {
                doFillPath(ctx, style);
            }
        }
        else {
            if (hasFill) {
                doFillPath(ctx, style);
            }
            if (hasStroke) {
                doStrokePath(ctx, style);
            }
        }
    }
    if (lineDash) {
        ctx.setLineDash([]);
    }
}
function brushImage(ctx, el, style) {
    var image = el.__image = createOrUpdateImage(style.image, el.__image, el, el.onload);
    if (!image || !isImageReady(image)) {
        return;
    }
    var x = style.x || 0;
    var y = style.y || 0;
    var width = el.getWidth();
    var height = el.getHeight();
    var aspect = image.width / image.height;
    if (width == null && height != null) {
        width = height * aspect;
    }
    else if (height == null && width != null) {
        height = width / aspect;
    }
    else if (width == null && height == null) {
        width = image.width;
        height = image.height;
    }
    if (style.sWidth && style.sHeight) {
        var sx = style.sx || 0;
        var sy = style.sy || 0;
        ctx.drawImage(image, sx, sy, style.sWidth, style.sHeight, x, y, width, height);
    }
    else if (style.sx && style.sy) {
        var sx = style.sx;
        var sy = style.sy;
        var sWidth = width - sx;
        var sHeight = height - sy;
        ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height);
    }
    else {
        ctx.drawImage(image, x, y, width, height);
    }
}
function brushText(ctx, el, style) {
    var _a;
    var text = style.text;
    text != null && (text += '');
    if (text) {
        ctx.font = style.font || DEFAULT_FONT;
        ctx.textAlign = style.textAlign;
        ctx.textBaseline = style.textBaseline;
        var lineDash = void 0;
        var lineDashOffset = void 0;
        if (ctx.setLineDash && style.lineDash) {
            _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1];
        }
        if (lineDash) {
            ctx.setLineDash(lineDash);
            ctx.lineDashOffset = lineDashOffset;
        }
        if (style.strokeFirst) {
            if (styleHasStroke(style)) {
                ctx.strokeText(text, style.x, style.y);
            }
            if (styleHasFill(style)) {
                ctx.fillText(text, style.x, style.y);
            }
        }
        else {
            if (styleHasFill(style)) {
                ctx.fillText(text, style.x, style.y);
            }
            if (styleHasStroke(style)) {
                ctx.strokeText(text, style.x, style.y);
            }
        }
        if (lineDash) {
            ctx.setLineDash([]);
        }
    }
}
var SHADOW_NUMBER_PROPS = ['shadowBlur', 'shadowOffsetX', 'shadowOffsetY'];
var STROKE_PROPS = [
    ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]
];
function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) {
    var styleChanged = false;
    if (!forceSetAll) {
        prevStyle = prevStyle || {};
        if (style === prevStyle) {
            return false;
        }
    }
    if (forceSetAll || style.opacity !== prevStyle.opacity) {
        flushPathDrawn(ctx, scope);
        styleChanged = true;
        var opacity = Math.max(Math.min(style.opacity, 1), 0);
        ctx.globalAlpha = isNaN(opacity) ? DEFAULT_COMMON_STYLE.opacity : opacity;
    }
    if (forceSetAll || style.blend !== prevStyle.blend) {
        if (!styleChanged) {
            flushPathDrawn(ctx, scope);
            styleChanged = true;
        }
        ctx.globalCompositeOperation = style.blend || DEFAULT_COMMON_STYLE.blend;
    }
    for (var i = 0; i < SHADOW_NUMBER_PROPS.length; i++) {
        var propName = SHADOW_NUMBER_PROPS[i];
        if (forceSetAll || style[propName] !== prevStyle[propName]) {
            if (!styleChanged) {
                flushPathDrawn(ctx, scope);
                styleChanged = true;
            }
            ctx[propName] = ctx.dpr * (style[propName] || 0);
        }
    }
    if (forceSetAll || style.shadowColor !== prevStyle.shadowColor) {
        if (!styleChanged) {
            flushPathDrawn(ctx, scope);
            styleChanged = true;
        }
        ctx.shadowColor = style.shadowColor || DEFAULT_COMMON_STYLE.shadowColor;
    }
    return styleChanged;
}
function bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetAll, scope) {
    var style = getStyle(el, scope.inHover);
    var prevStyle = forceSetAll
        ? null
        : (prevEl && getStyle(prevEl, scope.inHover) || {});
    if (style === prevStyle) {
        return false;
    }
    var styleChanged = bindCommonProps(ctx, style, prevStyle, forceSetAll, scope);
    if (forceSetAll || style.fill !== prevStyle.fill) {
        if (!styleChanged) {
            flushPathDrawn(ctx, scope);
            styleChanged = true;
        }
        isValidStrokeFillStyle(style.fill) && (ctx.fillStyle = style.fill);
    }
    if (forceSetAll || style.stroke !== prevStyle.stroke) {
        if (!styleChanged) {
            flushPathDrawn(ctx, scope);
            styleChanged = true;
        }
        isValidStrokeFillStyle(style.stroke) && (ctx.strokeStyle = style.stroke);
    }
    if (forceSetAll || style.opacity !== prevStyle.opacity) {
        if (!styleChanged) {
            flushPathDrawn(ctx, scope);
            styleChanged = true;
        }
        ctx.globalAlpha = style.opacity == null ? 1 : style.opacity;
    }
    if (el.hasStroke()) {
        var lineWidth = style.lineWidth;
        var newLineWidth = lineWidth / ((style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1);
        if (ctx.lineWidth !== newLineWidth) {
            if (!styleChanged) {
                flushPathDrawn(ctx, scope);
                styleChanged = true;
            }
            ctx.lineWidth = newLineWidth;
        }
    }
    for (var i = 0; i < STROKE_PROPS.length; i++) {
        var prop = STROKE_PROPS[i];
        var propName = prop[0];
        if (forceSetAll || style[propName] !== prevStyle[propName]) {
            if (!styleChanged) {
                flushPathDrawn(ctx, scope);
                styleChanged = true;
            }
            ctx[propName] = style[propName] || prop[1];
        }
    }
    return styleChanged;
}
function bindImageStyle(ctx, el, prevEl, forceSetAll, scope) {
    return bindCommonProps(ctx, getStyle(el, scope.inHover), prevEl && getStyle(prevEl, scope.inHover), forceSetAll, scope);
}
function setContextTransform(ctx, el) {
    var m = el.transform;
    var dpr = ctx.dpr || 1;
    if (m) {
        ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);
    }
    else {
        ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
}
function updateClipStatus(clipPaths, ctx, scope) {
    var allClipped = false;
    for (var i = 0; i < clipPaths.length; i++) {
        var clipPath = clipPaths[i];
        allClipped = allClipped || clipPath.isZeroArea();
        setContextTransform(ctx, clipPath);
        ctx.beginPath();
        clipPath.buildPath(ctx, clipPath.shape);
        ctx.clip();
    }
    scope.allClipped = allClipped;
}
function isTransformChanged(m0, m1) {
    if (m0 && m1) {
        return m0[0] !== m1[0]
            || m0[1] !== m1[1]
            || m0[2] !== m1[2]
            || m0[3] !== m1[3]
            || m0[4] !== m1[4]
            || m0[5] !== m1[5];
    }
    else if (!m0 && !m1) {
        return false;
    }
    return true;
}
var DRAW_TYPE_PATH = 1;
var DRAW_TYPE_IMAGE = 2;
var DRAW_TYPE_TEXT = 3;
var DRAW_TYPE_INCREMENTAL = 4;
function canPathBatch(style) {
    var hasFill = styleHasFill(style);
    var hasStroke = styleHasStroke(style);
    return !(style.lineDash
        || !(+hasFill ^ +hasStroke)
        || (hasFill && typeof style.fill !== 'string')
        || (hasStroke && typeof style.stroke !== 'string')
        || style.strokePercent < 1
        || style.strokeOpacity < 1
        || style.fillOpacity < 1);
}
function flushPathDrawn(ctx, scope) {
    scope.batchFill && ctx.fill();
    scope.batchStroke && ctx.stroke();
    scope.batchFill = '';
    scope.batchStroke = '';
}
function getStyle(el, inHover) {
    return inHover ? (el.__hoverStyle || el.style) : el.style;
}
function brushSingle(ctx, el) {
    brush(ctx, el, { inHover: false, viewWidth: 0, viewHeight: 0 }, true);
}
function brush(ctx, el, scope, isLast) {
    var m = el.transform;
    if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
        el.__dirty &= ~REDRAW_BIT;
        el.__isRendered = false;
        return;
    }
    var clipPaths = el.__clipPaths;
    var prevElClipPaths = scope.prevElClipPaths;
    var forceSetTransform = false;
    var forceSetStyle = false;
    if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) {
        if (prevElClipPaths && prevElClipPaths.length) {
            flushPathDrawn(ctx, scope);
            ctx.restore();
            forceSetStyle = forceSetTransform = true;
            scope.prevElClipPaths = null;
            scope.allClipped = false;
            scope.prevEl = null;
        }
        if (clipPaths && clipPaths.length) {
            flushPathDrawn(ctx, scope);
            ctx.save();
            updateClipStatus(clipPaths, ctx, scope);
            forceSetTransform = true;
        }
        scope.prevElClipPaths = clipPaths;
    }
    if (scope.allClipped) {
        el.__isRendered = false;
        return;
    }
    el.beforeBrush && el.beforeBrush();
    el.innerBeforeBrush();
    var prevEl = scope.prevEl;
    if (!prevEl) {
        forceSetStyle = forceSetTransform = true;
    }
    var canBatchPath = el instanceof Path$1
        && el.autoBatch
        && canPathBatch(el.style);
    if (forceSetTransform || isTransformChanged(m, prevEl.transform)) {
        flushPathDrawn(ctx, scope);
        setContextTransform(ctx, el);
    }
    else if (!canBatchPath) {
        flushPathDrawn(ctx, scope);
    }
    var style = getStyle(el, scope.inHover);
    if (el instanceof Path$1) {
        if (scope.lastDrawType !== DRAW_TYPE_PATH) {
            forceSetStyle = true;
            scope.lastDrawType = DRAW_TYPE_PATH;
        }
        bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope);
        if (!canBatchPath || (!scope.batchFill && !scope.batchStroke)) {
            ctx.beginPath();
        }
        brushPath(ctx, el, style, canBatchPath);
        if (canBatchPath) {
            scope.batchFill = style.fill || '';
            scope.batchStroke = style.stroke || '';
        }
    }
    else {
        if (el instanceof TSpan$1) {
            if (scope.lastDrawType !== DRAW_TYPE_TEXT) {
                forceSetStyle = true;
                scope.lastDrawType = DRAW_TYPE_TEXT;
            }
            bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope);
            brushText(ctx, el, style);
        }
        else if (el instanceof ZRImage$1) {
            if (scope.lastDrawType !== DRAW_TYPE_IMAGE) {
                forceSetStyle = true;
                scope.lastDrawType = DRAW_TYPE_IMAGE;
            }
            bindImageStyle(ctx, el, prevEl, forceSetStyle, scope);
            brushImage(ctx, el, style);
        }
        else if (el.getTemporalDisplayables) {
            if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) {
                forceSetStyle = true;
                scope.lastDrawType = DRAW_TYPE_INCREMENTAL;
            }
            brushIncremental(ctx, el, scope);
        }
    }
    if (canBatchPath && isLast) {
        flushPathDrawn(ctx, scope);
    }
    el.innerAfterBrush();
    el.afterBrush && el.afterBrush();
    scope.prevEl = el;
    el.__dirty = 0;
    el.__isRendered = true;
}
function brushIncremental(ctx, el, scope) {
    var displayables = el.getDisplayables();
    var temporalDisplayables = el.getTemporalDisplayables();
    ctx.save();
    var innerScope = {
        prevElClipPaths: null,
        prevEl: null,
        allClipped: false,
        viewWidth: scope.viewWidth,
        viewHeight: scope.viewHeight,
        inHover: scope.inHover
    };
    var i;
    var len;
    for (i = el.getCursor(), len = displayables.length; i < len; i++) {
        var displayable = displayables[i];
        displayable.beforeBrush && displayable.beforeBrush();
        displayable.innerBeforeBrush();
        brush(ctx, displayable, innerScope, i === len - 1);
        displayable.innerAfterBrush();
        displayable.afterBrush && displayable.afterBrush();
        innerScope.prevEl = displayable;
    }
    for (var i_1 = 0, len_1 = temporalDisplayables.length; i_1 < len_1; i_1++) {
        var displayable = temporalDisplayables[i_1];
        displayable.beforeBrush && displayable.beforeBrush();
        displayable.innerBeforeBrush();
        brush(ctx, displayable, innerScope, i_1 === len_1 - 1);
        displayable.innerAfterBrush();
        displayable.afterBrush && displayable.afterBrush();
        innerScope.prevEl = displayable;
    }
    el.clearTemporalDisplayables();
    el.notClear = true;
    ctx.restore();
}

/* Injected with object hook! */

var decalMap = new WeakMap$2();
var decalCache = new LRU$1(100);
var decalKeys = ['symbol', 'symbolSize', 'symbolKeepAspect', 'color', 'backgroundColor', 'dashArrayX', 'dashArrayY', 'maxTileWidth', 'maxTileHeight'];
/**
 * Create or update pattern image from decal options
 *
 * @param {InnerDecalObject | 'none'} decalObject decal options, 'none' if no decal
 * @return {Pattern} pattern with generated image, null if no decal
 */

function createOrUpdatePatternFromDecal(decalObject, api) {
  if (decalObject === 'none') {
    return null;
  }

  var dpr = api.getDevicePixelRatio();
  var zr = api.getZr();
  var isSVG = zr.painter.type === 'svg';

  if (decalObject.dirty) {
    decalMap["delete"](decalObject);
  }

  var oldPattern = decalMap.get(decalObject);

  if (oldPattern) {
    return oldPattern;
  }

  var decalOpt = defaults(decalObject, {
    symbol: 'rect',
    symbolSize: 1,
    symbolKeepAspect: true,
    color: 'rgba(0, 0, 0, 0.2)',
    backgroundColor: null,
    dashArrayX: 5,
    dashArrayY: 5,
    rotation: 0,
    maxTileWidth: 512,
    maxTileHeight: 512
  });

  if (decalOpt.backgroundColor === 'none') {
    decalOpt.backgroundColor = null;
  }

  var pattern = {
    repeat: 'repeat'
  };
  setPatternnSource(pattern);
  pattern.rotation = decalOpt.rotation;
  pattern.scaleX = pattern.scaleY = isSVG ? 1 : 1 / dpr;
  decalMap.set(decalObject, pattern);
  decalObject.dirty = false;
  return pattern;

  function setPatternnSource(pattern) {
    var keys = [dpr];
    var isValidKey = true;

    for (var i = 0; i < decalKeys.length; ++i) {
      var value = decalOpt[decalKeys[i]];

      if (value != null && !isArray(value) && !isString(value) && !isNumber(value) && typeof value !== 'boolean') {
        isValidKey = false;
        break;
      }

      keys.push(value);
    }

    var cacheKey;

    if (isValidKey) {
      cacheKey = keys.join(',') + (isSVG ? '-svg' : '');
      var cache = decalCache.get(cacheKey);

      if (cache) {
        isSVG ? pattern.svgElement = cache : pattern.image = cache;
      }
    }

    var dashArrayX = normalizeDashArrayX(decalOpt.dashArrayX);
    var dashArrayY = normalizeDashArrayY(decalOpt.dashArrayY);
    var symbolArray = normalizeSymbolArray(decalOpt.symbol);
    var lineBlockLengthsX = getLineBlockLengthX(dashArrayX);
    var lineBlockLengthY = getLineBlockLengthY(dashArrayY);
    var canvas = !isSVG && platformApi.createCanvas();
    var svgRoot = isSVG && {
      tag: 'g',
      attrs: {},
      key: 'dcl',
      children: []
    };
    var pSize = getPatternSize();
    var ctx;

    if (canvas) {
      canvas.width = pSize.width * dpr;
      canvas.height = pSize.height * dpr;
      ctx = canvas.getContext('2d');
    }

    brushDecal();

    if (isValidKey) {
      decalCache.put(cacheKey, canvas || svgRoot);
    }

    pattern.image = canvas;
    pattern.svgElement = svgRoot;
    pattern.svgWidth = pSize.width;
    pattern.svgHeight = pSize.height;
    /**
     * Get minimum length that can make a repeatable pattern.
     *
     * @return {Object} pattern width and height
     */

    function getPatternSize() {
      /**
       * For example, if dash is [[3, 2], [2, 1]] for X, it looks like
       * |---  ---  ---  ---  --- ...
       * |-- -- -- -- -- -- -- -- ...
       * |---  ---  ---  ---  --- ...
       * |-- -- -- -- -- -- -- -- ...
       * So the minimum length of X is 15,
       * which is the least common multiple of `3 + 2` and `2 + 1`
       * |---  ---  ---  |---  --- ...
       * |-- -- -- -- -- |-- -- -- ...
       */
      var width = 1;

      for (var i = 0, xlen = lineBlockLengthsX.length; i < xlen; ++i) {
        width = getLeastCommonMultiple(width, lineBlockLengthsX[i]);
      }

      var symbolRepeats = 1;

      for (var i = 0, xlen = symbolArray.length; i < xlen; ++i) {
        symbolRepeats = getLeastCommonMultiple(symbolRepeats, symbolArray[i].length);
      }

      width *= symbolRepeats;
      var height = lineBlockLengthY * lineBlockLengthsX.length * symbolArray.length;

      return {
        width: Math.max(1, Math.min(width, decalOpt.maxTileWidth)),
        height: Math.max(1, Math.min(height, decalOpt.maxTileHeight))
      };
    }

    function brushDecal() {
      if (ctx) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        if (decalOpt.backgroundColor) {
          ctx.fillStyle = decalOpt.backgroundColor;
          ctx.fillRect(0, 0, canvas.width, canvas.height);
        }
      }

      var ySum = 0;

      for (var i = 0; i < dashArrayY.length; ++i) {
        ySum += dashArrayY[i];
      }

      if (ySum <= 0) {
        // dashArrayY is 0, draw nothing
        return;
      }

      var y = -lineBlockLengthY;
      var yId = 0;
      var yIdTotal = 0;
      var xId0 = 0;

      while (y < pSize.height) {
        if (yId % 2 === 0) {
          var symbolYId = yIdTotal / 2 % symbolArray.length;
          var x = 0;
          var xId1 = 0;
          var xId1Total = 0;

          while (x < pSize.width * 2) {
            var xSum = 0;

            for (var i = 0; i < dashArrayX[xId0].length; ++i) {
              xSum += dashArrayX[xId0][i];
            }

            if (xSum <= 0) {
              // Skip empty line
              break;
            } // E.g., [15, 5, 20, 5] draws only for 15 and 20


            if (xId1 % 2 === 0) {
              var size = (1 - decalOpt.symbolSize) * 0.5;
              var left = x + dashArrayX[xId0][xId1] * size;
              var top_1 = y + dashArrayY[yId] * size;
              var width = dashArrayX[xId0][xId1] * decalOpt.symbolSize;
              var height = dashArrayY[yId] * decalOpt.symbolSize;
              var symbolXId = xId1Total / 2 % symbolArray[symbolYId].length;
              brushSymbol(left, top_1, width, height, symbolArray[symbolYId][symbolXId]);
            }

            x += dashArrayX[xId0][xId1];
            ++xId1Total;
            ++xId1;

            if (xId1 === dashArrayX[xId0].length) {
              xId1 = 0;
            }
          }

          ++xId0;

          if (xId0 === dashArrayX.length) {
            xId0 = 0;
          }
        }

        y += dashArrayY[yId];
        ++yIdTotal;
        ++yId;

        if (yId === dashArrayY.length) {
          yId = 0;
        }
      }

      function brushSymbol(x, y, width, height, symbolType) {
        var scale = isSVG ? 1 : dpr;
        var symbol = createSymbol(symbolType, x * scale, y * scale, width * scale, height * scale, decalOpt.color, decalOpt.symbolKeepAspect);

        if (isSVG) {
          var symbolVNode = zr.painter.renderOneToVNode(symbol);

          if (symbolVNode) {
            svgRoot.children.push(symbolVNode);
          }
        } else {
          // Paint to canvas for all other renderers.
          brushSingle(ctx, symbol);
        }
      }
    }
  }
}
/**
 * Convert symbol array into normalized array
 *
 * @param {string | (string | string[])[]} symbol symbol input
 * @return {string[][]} normolized symbol array
 */

function normalizeSymbolArray(symbol) {
  if (!symbol || symbol.length === 0) {
    return [['rect']];
  }

  if (isString(symbol)) {
    return [[symbol]];
  }

  var isAllString = true;

  for (var i = 0; i < symbol.length; ++i) {
    if (!isString(symbol[i])) {
      isAllString = false;
      break;
    }
  }

  if (isAllString) {
    return normalizeSymbolArray([symbol]);
  }

  var result = [];

  for (var i = 0; i < symbol.length; ++i) {
    if (isString(symbol[i])) {
      result.push([symbol[i]]);
    } else {
      result.push(symbol[i]);
    }
  }

  return result;
}
/**
 * Convert dash input into dashArray
 *
 * @param {DecalDashArrayX} dash dash input
 * @return {number[][]} normolized dash array
 */


function normalizeDashArrayX(dash) {
  if (!dash || dash.length === 0) {
    return [[0, 0]];
  }

  if (isNumber(dash)) {
    var dashValue = Math.ceil(dash);
    return [[dashValue, dashValue]];
  }
  /**
   * [20, 5] should be normalized into [[20, 5]],
   * while [20, [5, 10]] should be normalized into [[20, 20], [5, 10]]
   */


  var isAllNumber = true;

  for (var i = 0; i < dash.length; ++i) {
    if (!isNumber(dash[i])) {
      isAllNumber = false;
      break;
    }
  }

  if (isAllNumber) {
    return normalizeDashArrayX([dash]);
  }

  var result = [];

  for (var i = 0; i < dash.length; ++i) {
    if (isNumber(dash[i])) {
      var dashValue = Math.ceil(dash[i]);
      result.push([dashValue, dashValue]);
    } else {
      var dashValue = map$1(dash[i], function (n) {
        return Math.ceil(n);
      });

      if (dashValue.length % 2 === 1) {
        // [4, 2, 1] means |----  -    -- |----  -    -- |
        // so normalize it to be [4, 2, 1, 4, 2, 1]
        result.push(dashValue.concat(dashValue));
      } else {
        result.push(dashValue);
      }
    }
  }

  return result;
}
/**
 * Convert dash input into dashArray
 *
 * @param {DecalDashArrayY} dash dash input
 * @return {number[]} normolized dash array
 */


function normalizeDashArrayY(dash) {
  if (!dash || typeof dash === 'object' && dash.length === 0) {
    return [0, 0];
  }

  if (isNumber(dash)) {
    var dashValue_1 = Math.ceil(dash);
    return [dashValue_1, dashValue_1];
  }

  var dashValue = map$1(dash, function (n) {
    return Math.ceil(n);
  });
  return dash.length % 2 ? dashValue.concat(dashValue) : dashValue;
}
/**
 * Get block length of each line. A block is the length of dash line and space.
 * For example, a line with [4, 1] has a dash line of 4 and a space of 1 after
 * that, so the block length of this line is 5.
 *
 * @param {number[][]} dash dash array of X or Y
 * @return {number[]} block length of each line
 */


function getLineBlockLengthX(dash) {
  return map$1(dash, function (line) {
    return getLineBlockLengthY(line);
  });
}

function getLineBlockLengthY(dash) {
  var blockLength = 0;

  for (var i = 0; i < dash.length; ++i) {
    blockLength += dash[i];
  }

  if (dash.length % 2 === 1) {
    // [4, 2, 1] means |----  -    -- |----  -    -- |
    // So total length is (4 + 2 + 1) * 2
    return blockLength * 2;
  }

  return blockLength;
}
/* Injected with object hook! */

function decalVisual(ecModel, api) {
  ecModel.eachRawSeries(function (seriesModel) {
    if (ecModel.isSeriesFiltered(seriesModel)) {
      return;
    }

    var data = seriesModel.getData();

    if (data.hasItemVisual()) {
      data.each(function (idx) {
        var decal = data.getItemVisual(idx, 'decal');

        if (decal) {
          var itemStyle = data.ensureUniqueItemVisual(idx, 'style');
          itemStyle.decal = createOrUpdatePatternFromDecal(decal, api);
        }
      });
    }

    var decal = data.getVisual('decal');

    if (decal) {
      var style = data.getVisual('style');
      style.decal = createOrUpdatePatternFromDecal(decal, api);
    }
  });
}
/* Injected with object hook! */

var lifecycle = new Eventful$1();
const lifecycle$1 = lifecycle;
/* Injected with object hook! */

// The implementations will be registered when installing the component.
// Avoid these code being bundled to the core module.

var implsStore = {}; // TODO Type

function registerImpl(name, impl) {

  implsStore[name] = impl;
}
function getImpl(name) {

  return implsStore[name];
}
/* Injected with object hook! */

var TEST_FRAME_REMAIN_TIME = 1;
var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
// So data stack stage should be in front of data processing stage.

var PRIORITY_PROCESSOR_DATASTACK = 900; // "Data filter" will block the stream, so it should be
// put at the beginning of data processing.

var PRIORITY_PROCESSOR_FILTER = 1000;
var PRIORITY_PROCESSOR_DEFAULT = 2000;
var PRIORITY_PROCESSOR_STATISTIC = 5000;
var PRIORITY_VISUAL_LAYOUT = 1000;
var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
var PRIORITY_VISUAL_GLOBAL = 2000;
var PRIORITY_VISUAL_CHART = 3000;
var PRIORITY_VISUAL_COMPONENT = 4000; // Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to
// overwrite the viusal result of component (like `visualMap`)
// using data item specific setting (like itemStyle.xxx on data item)

var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; // Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on
// visual result like `symbolSize`.

var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
var PRIORITY_VISUAL_BRUSH = 5000;
var PRIORITY_VISUAL_ARIA = 6000;
var PRIORITY_VISUAL_DECAL = 7000;
var PRIORITY = {
  PROCESSOR: {
    FILTER: PRIORITY_PROCESSOR_FILTER,
    SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
    STATISTIC: PRIORITY_PROCESSOR_STATISTIC
  },
  VISUAL: {
    LAYOUT: PRIORITY_VISUAL_LAYOUT,
    PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
    GLOBAL: PRIORITY_VISUAL_GLOBAL,
    CHART: PRIORITY_VISUAL_CHART,
    POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
    COMPONENT: PRIORITY_VISUAL_COMPONENT,
    BRUSH: PRIORITY_VISUAL_BRUSH,
    CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
    ARIA: PRIORITY_VISUAL_ARIA,
    DECAL: PRIORITY_VISUAL_DECAL
  }
}; // Main process have three entries: `setOption`, `dispatchAction` and `resize`,
// where they must not be invoked nestedly, except the only case: invoke
// dispatchAction with updateMethod "none" in main process.
// This flag is used to carry out this rule.
// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).

var IN_MAIN_PROCESS_KEY = '__flagInMainProcess';
var PENDING_UPDATE = '__pendingUpdate';
var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus';
var ACTION_REG = /^[a-zA-Z0-9_]+$/;
var CONNECT_STATUS_KEY = '__connectUpdateStatus';
var CONNECT_STATUS_PENDING = 0;
var CONNECT_STATUS_UPDATING = 1;
var CONNECT_STATUS_UPDATED = 2;

function createRegisterEventWithLowercaseECharts(method) {
  return function () {
    var args = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      args[_i] = arguments[_i];
    }

    if (this.isDisposed()) {
      disposedWarning(this.id);
      return;
    }

    return toLowercaseNameAndCallEventful(this, method, args);
  };
}

function createRegisterEventWithLowercaseMessageCenter(method) {
  return function () {
    var args = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      args[_i] = arguments[_i];
    }

    return toLowercaseNameAndCallEventful(this, method, args);
  };
}

function toLowercaseNameAndCallEventful(host, method, args) {
  // `args[0]` is event name. Event name is all lowercase.
  args[0] = args[0] && args[0].toLowerCase();
  return Eventful$1.prototype[method].apply(host, args);
}

var MessageCenter =
/** @class */
function (_super) {
  __extends(MessageCenter, _super);

  function MessageCenter() {
    return _super !== null && _super.apply(this, arguments) || this;
  }

  return MessageCenter;
}(Eventful$1);

var messageCenterProto = MessageCenter.prototype;
messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); // ---------------------------------------
// Internal method names for class ECharts
// ---------------------------------------

var prepare;
var prepareView;
var updateDirectly;
var updateMethods;
var doConvertPixel;
var updateStreamModes;
var doDispatchAction;
var flushPendingActions;
var triggerUpdatedEvent;
var bindRenderedEvent;
var bindMouseEvent;
var render;
var renderComponents;
var renderSeries;
var createExtensionAPI;
var enableConnect;
var markStatusToUpdate;
var applyChangedStates;

var ECharts =
/** @class */
function (_super) {
  __extends(ECharts, _super);

  function ECharts(dom, // Theme name or themeOption.
  theme, opts) {
    var _this = _super.call(this, new ECEventProcessor()) || this;

    _this._chartsViews = [];
    _this._chartsMap = {};
    _this._componentsViews = [];
    _this._componentsMap = {}; // Can't dispatch action during rendering procedure

    _this._pendingActions = [];
    opts = opts || {}; // Get theme by name

    if (isString(theme)) {
      theme = themeStorage[theme];
    }

    _this._dom = dom;
    var defaultRenderer = 'canvas';
    var defaultCoarsePointer = 'auto';
    var defaultUseDirtyRect = false;

    var zr = _this._zr = init$1(dom, {
      renderer: opts.renderer || defaultRenderer,
      devicePixelRatio: opts.devicePixelRatio,
      width: opts.width,
      height: opts.height,
      ssr: opts.ssr,
      useDirtyRect: retrieve2(opts.useDirtyRect, defaultUseDirtyRect),
      useCoarsePointer: retrieve2(opts.useCoarsePointer, defaultCoarsePointer),
      pointerSize: opts.pointerSize
    });
    _this._ssr = opts.ssr; // Expect 60 fps.

    _this._throttledZrFlush = throttle(bind$1(zr.flush, zr), 17);
    theme = clone$2(theme);
    theme && globalBackwardCompat(theme, true);
    _this._theme = theme;
    _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);
    _this._coordSysMgr = new CoordinateSystem();
    var api = _this._api = createExtensionAPI(_this); // Sort on demand

    function prioritySortFunc(a, b) {
      return a.__prio - b.__prio;
    }

    sort(visualFuncs, prioritySortFunc);
    sort(dataProcessorFuncs, prioritySortFunc);
    _this._scheduler = new Scheduler$1(_this, api, dataProcessorFuncs, visualFuncs);
    _this._messageCenter = new MessageCenter(); // Init mouse events

    _this._initEvents(); // In case some people write `window.onresize = chart.resize`


    _this.resize = bind$1(_this.resize, _this);
    zr.animation.on('frame', _this._onframe, _this);
    bindRenderedEvent(zr, _this);
    bindMouseEvent(zr, _this); // ECharts instance can be used as value.

    setAsPrimitive(_this);
    return _this;
  }

  ECharts.prototype._onframe = function () {
    if (this._disposed) {
      return;
    }

    applyChangedStates(this);
    var scheduler = this._scheduler; // Lazy update

    if (this[PENDING_UPDATE]) {
      var silent = this[PENDING_UPDATE].silent;
      this[IN_MAIN_PROCESS_KEY] = true;

      try {
        prepare(this);
        updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams);
      } catch (e) {
        this[IN_MAIN_PROCESS_KEY] = false;
        this[PENDING_UPDATE] = null;
        throw e;
      } // At present, in each frame, zrender performs:
      //   (1) animation step forward.
      //   (2) trigger('frame') (where this `_onframe` is called)
      //   (3) zrender flush (render).
      // If we do nothing here, since we use `setToFinal: true`, the step (3) above
      // will render the final state of the elements before the real animation started.


      this._zr.flush();

      this[IN_MAIN_PROCESS_KEY] = false;
      this[PENDING_UPDATE] = null;
      flushPendingActions.call(this, silent);
      triggerUpdatedEvent.call(this, silent);
    } // Avoid do both lazy update and progress in one frame.
    else if (scheduler.unfinished) {
        // Stream progress.
        var remainTime = TEST_FRAME_REMAIN_TIME;
        var ecModel = this._model;
        var api = this._api;
        scheduler.unfinished = false;

        do {
          var startTime = +new Date();
          scheduler.performSeriesTasks(ecModel); // Currently dataProcessorFuncs do not check threshold.

          scheduler.performDataProcessorTasks(ecModel);
          updateStreamModes(this, ecModel); // Do not update coordinate system here. Because that coord system update in
          // each frame is not a good user experience. So we follow the rule that
          // the extent of the coordinate system is determined in the first frame (the
          // frame is executed immediately after task reset.
          // this._coordSysMgr.update(ecModel, api);
          // console.log('--- ec frame visual ---', remainTime);

          scheduler.performVisualTasks(ecModel);
          renderSeries(this, this._model, api, 'remain', {});
          remainTime -= +new Date() - startTime;
        } while (remainTime > 0 && scheduler.unfinished); // Call flush explicitly for trigger finished event.


        if (!scheduler.unfinished) {
          this._zr.flush();
        } // Else, zr flushing be ensue within the same frame,
        // because zr flushing is after onframe event.

      }
  };

  ECharts.prototype.getDom = function () {
    return this._dom;
  };

  ECharts.prototype.getId = function () {
    return this.id;
  };

  ECharts.prototype.getZr = function () {
    return this._zr;
  };

  ECharts.prototype.isSSR = function () {
    return this._ssr;
  };
  /* eslint-disable-next-line */


  ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) {
    if (this[IN_MAIN_PROCESS_KEY]) {

      return;
    }

    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    var silent;
    var replaceMerge;
    var transitionOpt;

    if (isObject$2(notMerge)) {
      lazyUpdate = notMerge.lazyUpdate;
      silent = notMerge.silent;
      replaceMerge = notMerge.replaceMerge;
      transitionOpt = notMerge.transition;
      notMerge = notMerge.notMerge;
    }

    this[IN_MAIN_PROCESS_KEY] = true;

    if (!this._model || notMerge) {
      var optionManager = new OptionManager$1(this._api);
      var theme = this._theme;
      var ecModel = this._model = new GlobalModel$1();
      ecModel.scheduler = this._scheduler;
      ecModel.ssr = this._ssr;
      ecModel.init(null, null, null, theme, this._locale, optionManager);
    }

    this._model.setOption(option, {
      replaceMerge: replaceMerge
    }, optionPreprocessorFuncs);

    var updateParams = {
      seriesTransition: transitionOpt,
      optionChanged: true
    };

    if (lazyUpdate) {
      this[PENDING_UPDATE] = {
        silent: silent,
        updateParams: updateParams
      };
      this[IN_MAIN_PROCESS_KEY] = false; // `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
      // It should wake it up to make sure zrender start to render at the next frame.

      this.getZr().wakeUp();
    } else {
      try {
        prepare(this);
        updateMethods.update.call(this, null, updateParams);
      } catch (e) {
        this[PENDING_UPDATE] = null;
        this[IN_MAIN_PROCESS_KEY] = false;
        throw e;
      } // Ensure zr refresh sychronously, and then pixel in canvas can be
      // fetched after `setOption`.


      if (!this._ssr) {
        // not use flush when using ssr mode.
        this._zr.flush();
      }

      this[PENDING_UPDATE] = null;
      this[IN_MAIN_PROCESS_KEY] = false;
      flushPendingActions.call(this, silent);
      triggerUpdatedEvent.call(this, silent);
    }
  };
  /**
   * @deprecated
   */


  ECharts.prototype.setTheme = function () {
  }; // We don't want developers to use getModel directly.


  ECharts.prototype.getModel = function () {
    return this._model;
  };

  ECharts.prototype.getOption = function () {
    return this._model && this._model.getOption();
  };

  ECharts.prototype.getWidth = function () {
    return this._zr.getWidth();
  };

  ECharts.prototype.getHeight = function () {
    return this._zr.getHeight();
  };

  ECharts.prototype.getDevicePixelRatio = function () {
    return this._zr.painter.dpr
    /* eslint-disable-next-line */
    || env$1.hasGlobalWindow && window.devicePixelRatio || 1;
  };
  /**
   * Get canvas which has all thing rendered
   * @deprecated Use renderToCanvas instead.
   */


  ECharts.prototype.getRenderedCanvas = function (opts) {

    return this.renderToCanvas(opts);
  };

  ECharts.prototype.renderToCanvas = function (opts) {
    opts = opts || {};
    var painter = this._zr.painter;

    return painter.getRenderedCanvas({
      backgroundColor: opts.backgroundColor || this._model.get('backgroundColor'),
      pixelRatio: opts.pixelRatio || this.getDevicePixelRatio()
    });
  };

  ECharts.prototype.renderToSVGString = function (opts) {
    opts = opts || {};
    var painter = this._zr.painter;

    return painter.renderToString({
      useViewBox: opts.useViewBox
    });
  };
  /**
   * Get svg data url
   */


  ECharts.prototype.getSvgDataURL = function () {
    if (!env$1.svgSupported) {
      return;
    }

    var zr = this._zr;
    var list = zr.storage.getDisplayList(); // Stop animations

    each$4(list, function (el) {
      el.stopAnimation(null, true);
    });
    return zr.painter.toDataURL();
  };

  ECharts.prototype.getDataURL = function (opts) {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    opts = opts || {};
    var excludeComponents = opts.excludeComponents;
    var ecModel = this._model;
    var excludesComponentViews = [];
    var self = this;
    each$4(excludeComponents, function (componentType) {
      ecModel.eachComponent({
        mainType: componentType
      }, function (component) {
        var view = self._componentsMap[component.__viewId];

        if (!view.group.ignore) {
          excludesComponentViews.push(view);
          view.group.ignore = true;
        }
      });
    });
    var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.renderToCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png'));
    each$4(excludesComponentViews, function (view) {
      view.group.ignore = false;
    });
    return url;
  };

  ECharts.prototype.getConnectedDataURL = function (opts) {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    var isSvg = opts.type === 'svg';
    var groupId = this.group;
    var mathMin = Math.min;
    var mathMax = Math.max;
    var MAX_NUMBER = Infinity;

    if (connectedGroups[groupId]) {
      var left_1 = MAX_NUMBER;
      var top_1 = MAX_NUMBER;
      var right_1 = -MAX_NUMBER;
      var bottom_1 = -MAX_NUMBER;
      var canvasList_1 = [];
      var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio();
      each$4(instances, function (chart, id) {
        if (chart.group === groupId) {
          var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.renderToCanvas(clone$2(opts));
          var boundingRect = chart.getDom().getBoundingClientRect();
          left_1 = mathMin(boundingRect.left, left_1);
          top_1 = mathMin(boundingRect.top, top_1);
          right_1 = mathMax(boundingRect.right, right_1);
          bottom_1 = mathMax(boundingRect.bottom, bottom_1);
          canvasList_1.push({
            dom: canvas,
            left: boundingRect.left,
            top: boundingRect.top
          });
        }
      });
      left_1 *= dpr_1;
      top_1 *= dpr_1;
      right_1 *= dpr_1;
      bottom_1 *= dpr_1;
      var width = right_1 - left_1;
      var height = bottom_1 - top_1;
      var targetCanvas = platformApi.createCanvas();
      var zr_1 = init$1(targetCanvas, {
        renderer: isSvg ? 'svg' : 'canvas'
      });
      zr_1.resize({
        width: width,
        height: height
      });

      if (isSvg) {
        var content_1 = '';
        each$4(canvasList_1, function (item) {
          var x = item.left - left_1;
          var y = item.top - top_1;
          content_1 += '<g transform="translate(' + x + ',' + y + ')">' + item.dom + '</g>';
        });
        zr_1.painter.getSvgRoot().innerHTML = content_1;

        if (opts.connectedBackgroundColor) {
          zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor);
        }

        zr_1.refreshImmediately();
        return zr_1.painter.toDataURL();
      } else {
        // Background between the charts
        if (opts.connectedBackgroundColor) {
          zr_1.add(new Rect$1({
            shape: {
              x: 0,
              y: 0,
              width: width,
              height: height
            },
            style: {
              fill: opts.connectedBackgroundColor
            }
          }));
        }

        each$4(canvasList_1, function (item) {
          var img = new ZRImage$1({
            style: {
              x: item.left * dpr_1 - left_1,
              y: item.top * dpr_1 - top_1,
              image: item.dom
            }
          });
          zr_1.add(img);
        });
        zr_1.refreshImmediately();
        return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
      }
    } else {
      return this.getDataURL(opts);
    }
  };

  ECharts.prototype.convertToPixel = function (finder, value) {
    return doConvertPixel(this, 'convertToPixel', finder, value);
  };

  ECharts.prototype.convertFromPixel = function (finder, value) {
    return doConvertPixel(this, 'convertFromPixel', finder, value);
  };
  /**
   * Is the specified coordinate systems or components contain the given pixel point.
   * @param {Array|number} value
   * @return {boolean} result
   */


  ECharts.prototype.containPixel = function (finder, value) {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    var ecModel = this._model;
    var result;
    var findResult = parseFinder(ecModel, finder);
    each$4(findResult, function (models, key) {
      key.indexOf('Models') >= 0 && each$4(models, function (model) {
        var coordSys = model.coordinateSystem;

        if (coordSys && coordSys.containPoint) {
          result = result || !!coordSys.containPoint(value);
        } else if (key === 'seriesModels') {
          var view = this._chartsMap[model.__viewId];

          if (view && view.containPoint) {
            result = result || view.containPoint(value, model);
          }
        } else ;
      }, this);
    }, this);
    return !!result;
  };
  /**
   * Get visual from series or data.
   * @param finder
   *        If string, e.g., 'series', means {seriesIndex: 0}.
   *        If Object, could contain some of these properties below:
   *        {
   *            seriesIndex / seriesId / seriesName,
   *            dataIndex / dataIndexInside
   *        }
   *        If dataIndex is not specified, series visual will be fetched,
   *        but not data item visual.
   *        If all of seriesIndex, seriesId, seriesName are not specified,
   *        visual will be fetched from first series.
   * @param visualType 'color', 'symbol', 'symbolSize'
   */


  ECharts.prototype.getVisual = function (finder, visualType) {
    var ecModel = this._model;
    var parsedFinder = parseFinder(ecModel, finder, {
      defaultMainType: 'series'
    });
    var seriesModel = parsedFinder.seriesModel;

    var data = seriesModel.getData();
    var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null;
    return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType);
  };
  /**
   * Get view of corresponding component model
   */


  ECharts.prototype.getViewOfComponentModel = function (componentModel) {
    return this._componentsMap[componentModel.__viewId];
  };
  /**
   * Get view of corresponding series model
   */


  ECharts.prototype.getViewOfSeriesModel = function (seriesModel) {
    return this._chartsMap[seriesModel.__viewId];
  };

  ECharts.prototype._initEvents = function () {
    var _this = this;

    each$4(MOUSE_EVENT_NAMES, function (eveName) {
      var handler = function (e) {
        var ecModel = _this.getModel();

        var el = e.target;
        var params;
        var isGlobalOut = eveName === 'globalout'; // no e.target when 'globalout'.

        if (isGlobalOut) {
          params = {};
        } else {
          el && findEventDispatcher(el, function (parent) {
            var ecData = getECData(parent);

            if (ecData && ecData.dataIndex != null) {
              var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
              params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType, el) || {};
              return true;
            } // If element has custom eventData of components
            else if (ecData.eventData) {
                params = extend({}, ecData.eventData);
                return true;
              }
          }, true);
        } // Contract: if params prepared in mouse event,
        // these properties must be specified:
        // {
        //    componentType: string (component main type)
        //    componentIndex: number
        // }
        // Otherwise event query can not work.


        if (params) {
          var componentType = params.componentType;
          var componentIndex = params.componentIndex; // Special handling for historic reason: when trigger by
          // markLine/markPoint/markArea, the componentType is
          // 'markLine'/'markPoint'/'markArea', but we should better
          // enable them to be queried by seriesIndex, since their
          // option is set in each series.

          if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') {
            componentType = 'series';
            componentIndex = params.seriesIndex;
          }

          var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex);
          var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId];

          params.event = e;
          params.type = eveName;
          _this._$eventProcessor.eventInfo = {
            targetEl: el,
            packedEvent: params,
            model: model,
            view: view
          };

          _this.trigger(eveName, params);
        }
      }; // Consider that some component (like tooltip, brush, ...)
      // register zr event handler, but user event handler might
      // do anything, such as call `setOption` or `dispatchAction`,
      // which probably update any of the content and probably
      // cause problem if it is called previous other inner handlers.


      handler.zrEventfulCallAtLast = true;

      _this._zr.on(eveName, handler, _this);
    });
    each$4(eventActionMap, function (actionType, eventType) {
      _this._messageCenter.on(eventType, function (event) {
        this.trigger(eventType, event);
      }, _this);
    }); // Extra events
    // TODO register?

    each$4(['selectchanged'], function (eventType) {
      _this._messageCenter.on(eventType, function (event) {
        this.trigger(eventType, event);
      }, _this);
    });
    handleLegacySelectEvents(this._messageCenter, this, this._api);
  };

  ECharts.prototype.isDisposed = function () {
    return this._disposed;
  };

  ECharts.prototype.clear = function () {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    this.setOption({
      series: []
    }, true);
  };

  ECharts.prototype.dispose = function () {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    this._disposed = true;
    var dom = this.getDom();

    if (dom) {
      setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
    }

    var chart = this;
    var api = chart._api;
    var ecModel = chart._model;
    each$4(chart._componentsViews, function (component) {
      component.dispose(ecModel, api);
    });
    each$4(chart._chartsViews, function (chart) {
      chart.dispose(ecModel, api);
    }); // Dispose after all views disposed

    chart._zr.dispose(); // Set properties to null.
    // To reduce the memory cost in case the top code still holds this instance unexpectedly.


    chart._dom = chart._model = chart._chartsMap = chart._componentsMap = chart._chartsViews = chart._componentsViews = chart._scheduler = chart._api = chart._zr = chart._throttledZrFlush = chart._theme = chart._coordSysMgr = chart._messageCenter = null;
    delete instances[chart.id];
  };
  /**
   * Resize the chart
   */


  ECharts.prototype.resize = function (opts) {
    if (this[IN_MAIN_PROCESS_KEY]) {

      return;
    }

    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    this._zr.resize(opts);

    var ecModel = this._model; // Resize loading effect

    this._loadingFX && this._loadingFX.resize();

    if (!ecModel) {
      return;
    }

    var needPrepare = ecModel.resetOption('media');
    var silent = opts && opts.silent; // There is some real cases that:
    // chart.setOption(option, { lazyUpdate: true });
    // chart.resize();

    if (this[PENDING_UPDATE]) {
      if (silent == null) {
        silent = this[PENDING_UPDATE].silent;
      }

      needPrepare = true;
      this[PENDING_UPDATE] = null;
    }

    this[IN_MAIN_PROCESS_KEY] = true;

    try {
      needPrepare && prepare(this);
      updateMethods.update.call(this, {
        type: 'resize',
        animation: extend({
          // Disable animation
          duration: 0
        }, opts && opts.animation)
      });
    } catch (e) {
      this[IN_MAIN_PROCESS_KEY] = false;
      throw e;
    }

    this[IN_MAIN_PROCESS_KEY] = false;
    flushPendingActions.call(this, silent);
    triggerUpdatedEvent.call(this, silent);
  };

  ECharts.prototype.showLoading = function (name, cfg) {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    if (isObject$2(name)) {
      cfg = name;
      name = '';
    }

    name = name || 'default';
    this.hideLoading();

    if (!loadingEffects[name]) {

      return;
    }

    var el = loadingEffects[name](this._api, cfg);
    var zr = this._zr;
    this._loadingFX = el;
    zr.add(el);
  };
  /**
   * Hide loading effect
   */


  ECharts.prototype.hideLoading = function () {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    this._loadingFX && this._zr.remove(this._loadingFX);
    this._loadingFX = null;
  };

  ECharts.prototype.makeActionFromEvent = function (eventObj) {
    var payload = extend({}, eventObj);
    payload.type = eventActionMap[eventObj.type];
    return payload;
  };
  /**
   * @param opt If pass boolean, means opt.silent
   * @param opt.silent Default `false`. Whether trigger events.
   * @param opt.flush Default `undefined`.
   *        true: Flush immediately, and then pixel in canvas can be fetched
   *            immediately. Caution: it might affect performance.
   *        false: Not flush.
   *        undefined: Auto decide whether perform flush.
   */


  ECharts.prototype.dispatchAction = function (payload, opt) {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    if (!isObject$2(opt)) {
      opt = {
        silent: !!opt
      };
    }

    if (!actions[payload.type]) {
      return;
    } // Avoid dispatch action before setOption. Especially in `connect`.


    if (!this._model) {
      return;
    } // May dispatchAction in rendering procedure


    if (this[IN_MAIN_PROCESS_KEY]) {
      this._pendingActions.push(payload);

      return;
    }

    var silent = opt.silent;
    doDispatchAction.call(this, payload, silent);
    var flush = opt.flush;

    if (flush) {
      this._zr.flush();
    } else if (flush !== false && env$1.browser.weChat) {
      // In WeChat embedded browser, `requestAnimationFrame` and `setInterval`
      // hang when sliding page (on touch event), which cause that zr does not
      // refresh until user interaction finished, which is not expected.
      // But `dispatchAction` may be called too frequently when pan on touch
      // screen, which impacts performance if do not throttle them.
      this._throttledZrFlush();
    }

    flushPendingActions.call(this, silent);
    triggerUpdatedEvent.call(this, silent);
  };

  ECharts.prototype.updateLabelLayout = function () {
    lifecycle$1.trigger('series:layoutlabels', this._model, this._api, {
      // Not adding series labels.
      // TODO
      updatedSeries: []
    });
  };

  ECharts.prototype.appendData = function (params) {
    if (this._disposed) {
      disposedWarning(this.id);
      return;
    }

    var seriesIndex = params.seriesIndex;
    var ecModel = this.getModel();
    var seriesModel = ecModel.getSeriesByIndex(seriesIndex);

    seriesModel.appendData(params); // Note: `appendData` does not support that update extent of coordinate
    // system, util some scenario require that. In the expected usage of
    // `appendData`, the initial extent of coordinate system should better
    // be fixed by axis `min`/`max` setting or initial data, otherwise if
    // the extent changed while `appendData`, the location of the painted
    // graphic elements have to be changed, which make the usage of
    // `appendData` meaningless.

    this._scheduler.unfinished = true;
    this.getZr().wakeUp();
  }; // A work around for no `internal` modifier in ts yet but
  // need to strictly hide private methods to JS users.


  ECharts.internalField = function () {
    prepare = function (ecIns) {
      var scheduler = ecIns._scheduler;
      scheduler.restorePipelines(ecIns._model);
      scheduler.prepareStageTasks();
      prepareView(ecIns, true);
      prepareView(ecIns, false);
      scheduler.plan();
    };
    /**
     * Prepare view instances of charts and components
     */


    prepareView = function (ecIns, isComponent) {
      var ecModel = ecIns._model;
      var scheduler = ecIns._scheduler;
      var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
      var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
      var zr = ecIns._zr;
      var api = ecIns._api;

      for (var i = 0; i < viewList.length; i++) {
        viewList[i].__alive = false;
      }

      isComponent ? ecModel.eachComponent(function (componentType, model) {
        componentType !== 'series' && doPrepare(model);
      }) : ecModel.eachSeries(doPrepare);

      function doPrepare(model) {
        // By default view will be reused if possible for the case that `setOption` with "notMerge"
        // mode and need to enable transition animation. (Usually, when they have the same id, or
        // especially no id but have the same type & name & index. See the `model.id` generation
        // rule in `makeIdAndName` and `viewId` generation rule here).
        // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that
        // the new model has nothing to do with the old model.
        var requireNewView = model.__requireNewView; // This command should not work twice.

        model.__requireNewView = false; // Consider: id same and type changed.

        var viewId = '_ec_' + model.id + '_' + model.type;
        var view = !requireNewView && viewMap[viewId];

        if (!view) {
          var classType = parseClassType(model.type);
          var Clazz = isComponent ? ComponentView$1.getClass(classType.main, classType.sub) : // FIXME:TS
          // (ChartView as ChartViewConstructor).getClass('series', classType.sub)
          // For backward compat, still support a chart type declared as only subType
          // like "liquidfill", but recommend "series.liquidfill"
          // But need a base class to make a type series.
          ChartView$1.getClass(classType.sub);

          view = new Clazz();
          view.init(ecModel, api);
          viewMap[viewId] = view;
          viewList.push(view);
          zr.add(view.group);
        }

        model.__viewId = view.__id = viewId;
        view.__alive = true;
        view.__model = model;
        view.group.__ecComponentInfo = {
          mainType: model.mainType,
          index: model.componentIndex
        };
        !isComponent && scheduler.prepareView(view, model, ecModel, api);
      }

      for (var i = 0; i < viewList.length;) {
        var view = viewList[i];

        if (!view.__alive) {
          !isComponent && view.renderTask.dispose();
          zr.remove(view.group);
          view.dispose(ecModel, api);
          viewList.splice(i, 1);

          if (viewMap[view.__id] === view) {
            delete viewMap[view.__id];
          }

          view.__id = view.group.__ecComponentInfo = null;
        } else {
          i++;
        }
      }
    };

    updateDirectly = function (ecIns, method, payload, mainType, subType) {
      var ecModel = ecIns._model;
      ecModel.setUpdatePayload(payload); // broadcast

      if (!mainType) {
        // FIXME
        // Chart will not be update directly here, except set dirty.
        // But there is no such scenario now.
        each$4([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView);
        return;
      }

      var query = {};
      query[mainType + 'Id'] = payload[mainType + 'Id'];
      query[mainType + 'Index'] = payload[mainType + 'Index'];
      query[mainType + 'Name'] = payload[mainType + 'Name'];
      var condition = {
        mainType: mainType,
        query: query
      };
      subType && (condition.subType = subType); // subType may be '' by parseClassType;

      var excludeSeriesId = payload.excludeSeriesId;
      var excludeSeriesIdMap;

      if (excludeSeriesId != null) {
        excludeSeriesIdMap = createHashMap();
        each$4(normalizeToArray(excludeSeriesId), function (id) {
          var modelId = convertOptionIdName(id, null);

          if (modelId != null) {
            excludeSeriesIdMap.set(modelId, true);
          }
        });
      } // If dispatchAction before setOption, do nothing.


      ecModel && ecModel.eachComponent(condition, function (model) {
        var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) != null;

        if (isExcluded) {
          return;
        }

        if (isHighDownPayload(payload)) {
          if (model instanceof SeriesModel$1) {
            if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur && !model.get(['emphasis', 'disabled'])) {
              blurSeriesFromHighlightPayload(model, payload, ecIns._api);
            }
          } else {
            var _a = findComponentHighDownDispatchers(model.mainType, model.componentIndex, payload.name, ecIns._api),
                focusSelf = _a.focusSelf,
                dispatchers = _a.dispatchers;

            if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) {
              blurComponent(model.mainType, model.componentIndex, ecIns._api);
            } // PENDING:
            // Whether to put this "enter emphasis" code in `ComponentView`,
            // which will be the same as `ChartView` but might be not necessary
            // and will be far from this logic.


            if (dispatchers) {
              each$4(dispatchers, function (dispatcher) {
                payload.type === HIGHLIGHT_ACTION_TYPE ? enterEmphasis(dispatcher) : leaveEmphasis(dispatcher);
              });
            }
          }
        } else if (isSelectChangePayload(payload)) {
          // TODO geo
          if (model instanceof SeriesModel$1) {
            toggleSelectionFromPayload(model, payload, ecIns._api);
            updateSeriesElementSelection(model);
            markStatusToUpdate(ecIns);
          }
        }
      }, ecIns);
      ecModel && ecModel.eachComponent(condition, function (model) {
        var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) != null;

        if (isExcluded) {
          return;
        }
        callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]);
      }, ecIns);

      function callView(view) {
        view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload);
      }
    };

    updateMethods = {
      prepareAndUpdate: function (payload) {
        prepare(this);
        updateMethods.update.call(this, payload, {
          // Needs to mark option changed if newOption is given.
          // It's from MagicType.
          // TODO If use a separate flag optionChanged in payload?
          optionChanged: payload.newOption != null
        });
      },
      update: function (payload, updateParams) {
        var ecModel = this._model;
        var api = this._api;
        var zr = this._zr;
        var coordSysMgr = this._coordSysMgr;
        var scheduler = this._scheduler; // update before setOption

        if (!ecModel) {
          return;
        }

        ecModel.setUpdatePayload(payload);
        scheduler.restoreData(ecModel, payload);
        scheduler.performSeriesTasks(ecModel); // TODO
        // Save total ecModel here for undo/redo (after restoring data and before processing data).
        // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
        // Create new coordinate system each update
        // In LineView may save the old coordinate system and use it to get the original point.

        coordSysMgr.create(ecModel, api);
        scheduler.performDataProcessorTasks(ecModel, payload); // Current stream render is not supported in data process. So we can update
        // stream modes after data processing, where the filtered data is used to
        // determine whether to use progressive rendering.

        updateStreamModes(this, ecModel); // We update stream modes before coordinate system updated, then the modes info
        // can be fetched when coord sys updating (consider the barGrid extent fix). But
        // the drawback is the full coord info can not be fetched. Fortunately this full
        // coord is not required in stream mode updater currently.

        coordSysMgr.update(ecModel, api);
        clearColorPalette(ecModel);
        scheduler.performVisualTasks(ecModel, payload);
        render(this, ecModel, api, payload, updateParams); // Set background

        var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
        var darkMode = ecModel.get('darkMode');
        zr.setBackgroundColor(backgroundColor); // Force set dark mode.

        if (darkMode != null && darkMode !== 'auto') {
          zr.setDarkMode(darkMode);
        }

        lifecycle$1.trigger('afterupdate', ecModel, api);
      },
      updateTransform: function (payload) {
        var _this = this;

        var ecModel = this._model;
        var api = this._api; // update before setOption

        if (!ecModel) {
          return;
        }

        ecModel.setUpdatePayload(payload); // ChartView.markUpdateMethod(payload, 'updateTransform');

        var componentDirtyList = [];
        ecModel.eachComponent(function (componentType, componentModel) {
          if (componentType === 'series') {
            return;
          }

          var componentView = _this.getViewOfComponentModel(componentModel);

          if (componentView && componentView.__alive) {
            if (componentView.updateTransform) {
              var result = componentView.updateTransform(componentModel, ecModel, api, payload);
              result && result.update && componentDirtyList.push(componentView);
            } else {
              componentDirtyList.push(componentView);
            }
          }
        });
        var seriesDirtyMap = createHashMap();
        ecModel.eachSeries(function (seriesModel) {
          var chartView = _this._chartsMap[seriesModel.__viewId];

          if (chartView.updateTransform) {
            var result = chartView.updateTransform(seriesModel, ecModel, api, payload);
            result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
          } else {
            seriesDirtyMap.set(seriesModel.uid, 1);
          }
        });
        clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
        // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);

        this._scheduler.performVisualTasks(ecModel, payload, {
          setDirty: true,
          dirtyMap: seriesDirtyMap
        }); // Currently, not call render of components. Geo render cost a lot.
        // renderComponents(ecIns, ecModel, api, payload, componentDirtyList);


        renderSeries(this, ecModel, api, payload, {}, seriesDirtyMap);
        lifecycle$1.trigger('afterupdate', ecModel, api);
      },
      updateView: function (payload) {
        var ecModel = this._model; // update before setOption

        if (!ecModel) {
          return;
        }

        ecModel.setUpdatePayload(payload);
        ChartView$1.markUpdateMethod(payload, 'updateView');
        clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.

        this._scheduler.performVisualTasks(ecModel, payload, {
          setDirty: true
        });

        render(this, ecModel, this._api, payload, {});
        lifecycle$1.trigger('afterupdate', ecModel, this._api);
      },
      updateVisual: function (payload) {
        // updateMethods.update.call(this, payload);
        var _this = this;

        var ecModel = this._model; // update before setOption

        if (!ecModel) {
          return;
        }

        ecModel.setUpdatePayload(payload); // clear all visual

        ecModel.eachSeries(function (seriesModel) {
          seriesModel.getData().clearAllVisual();
        }); // Perform visual

        ChartView$1.markUpdateMethod(payload, 'updateVisual');
        clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.

        this._scheduler.performVisualTasks(ecModel, payload, {
          visualType: 'visual',
          setDirty: true
        });

        ecModel.eachComponent(function (componentType, componentModel) {
          if (componentType !== 'series') {
            var componentView = _this.getViewOfComponentModel(componentModel);

            componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload);
          }
        });
        ecModel.eachSeries(function (seriesModel) {
          var chartView = _this._chartsMap[seriesModel.__viewId];
          chartView.updateVisual(seriesModel, ecModel, _this._api, payload);
        });
        lifecycle$1.trigger('afterupdate', ecModel, this._api);
      },
      updateLayout: function (payload) {
        updateMethods.update.call(this, payload);
      }
    };

    doConvertPixel = function (ecIns, methodName, finder, value) {
      if (ecIns._disposed) {
        disposedWarning(ecIns.id);
        return;
      }

      var ecModel = ecIns._model;

      var coordSysList = ecIns._coordSysMgr.getCoordinateSystems();

      var result;
      var parsedFinder = parseFinder(ecModel, finder);

      for (var i = 0; i < coordSysList.length; i++) {
        var coordSys = coordSysList[i];

        if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) {
          return result;
        }
      }
    };

    updateStreamModes = function (ecIns, ecModel) {
      var chartsMap = ecIns._chartsMap;
      var scheduler = ecIns._scheduler;
      ecModel.eachSeries(function (seriesModel) {
        scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
      });
    };

    doDispatchAction = function (payload, silent) {
      var _this = this;

      var ecModel = this.getModel();
      var payloadType = payload.type;
      var escapeConnect = payload.escapeConnect;
      var actionWrap = actions[payloadType];
      var actionInfo = actionWrap.actionInfo;
      var cptTypeTmp = (actionInfo.update || 'update').split(':');
      var updateMethod = cptTypeTmp.pop();
      var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);
      this[IN_MAIN_PROCESS_KEY] = true;
      var payloads = [payload];
      var batched = false; // Batch action

      if (payload.batch) {
        batched = true;
        payloads = map$1(payload.batch, function (item) {
          item = defaults(extend({}, item), payload);
          item.batch = null;
          return item;
        });
      }

      var eventObjBatch = [];
      var eventObj;
      var isSelectChange = isSelectChangePayload(payload);
      var isHighDown = isHighDownPayload(payload); // Only leave blur once if there are multiple batches.

      if (isHighDown) {
        allLeaveBlur(this._api);
      }

      each$4(payloads, function (batchItem) {
        // Action can specify the event by return it.
        eventObj = actionWrap.action(batchItem, _this._model, _this._api); // Emit event outside

        eventObj = eventObj || extend({}, batchItem); // Convert type to eventType

        eventObj.type = actionInfo.event || eventObj.type;
        eventObjBatch.push(eventObj); // light update does not perform data process, layout and visual.

        if (isHighDown) {
          var _a = preParseFinder(payload),
              queryOptionMap = _a.queryOptionMap,
              mainTypeSpecified = _a.mainTypeSpecified;

          var componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series';
          updateDirectly(_this, updateMethod, batchItem, componentMainType);
          markStatusToUpdate(_this);
        } else if (isSelectChange) {
          // At present `dispatchAction({ type: 'select', ... })` is not supported on components.
          // geo still use 'geoselect'.
          updateDirectly(_this, updateMethod, batchItem, 'series');
          markStatusToUpdate(_this);
        } else if (cptType) {
          updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub);
        }
      });

      if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) {
        try {
          // Still dirty
          if (this[PENDING_UPDATE]) {
            prepare(this);
            updateMethods.update.call(this, payload);
            this[PENDING_UPDATE] = null;
          } else {
            updateMethods[updateMethod].call(this, payload);
          }
        } catch (e) {
          this[IN_MAIN_PROCESS_KEY] = false;
          throw e;
        }
      } // Follow the rule of action batch


      if (batched) {
        eventObj = {
          type: actionInfo.event || payloadType,
          escapeConnect: escapeConnect,
          batch: eventObjBatch
        };
      } else {
        eventObj = eventObjBatch[0];
      }

      this[IN_MAIN_PROCESS_KEY] = false;

      if (!silent) {
        var messageCenter = this._messageCenter;
        messageCenter.trigger(eventObj.type, eventObj); // Extra triggered 'selectchanged' event

        if (isSelectChange) {
          var newObj = {
            type: 'selectchanged',
            escapeConnect: escapeConnect,
            selected: getAllSelectedIndices(ecModel),
            isFromClick: payload.isFromClick || false,
            fromAction: payload.type,
            fromActionPayload: payload
          };
          messageCenter.trigger(newObj.type, newObj);
        }
      }
    };

    flushPendingActions = function (silent) {
      var pendingActions = this._pendingActions;

      while (pendingActions.length) {
        var payload = pendingActions.shift();
        doDispatchAction.call(this, payload, silent);
      }
    };

    triggerUpdatedEvent = function (silent) {
      !silent && this.trigger('updated');
    };
    /**
     * Event `rendered` is triggered when zr
     * rendered. It is useful for realtime
     * snapshot (reflect animation).
     *
     * Event `finished` is triggered when:
     * (1) zrender rendering finished.
     * (2) initial animation finished.
     * (3) progressive rendering finished.
     * (4) no pending action.
     * (5) no delayed setOption needs to be processed.
     */


    bindRenderedEvent = function (zr, ecIns) {
      zr.on('rendered', function (params) {
        ecIns.trigger('rendered', params); // The `finished` event should not be triggered repeatedly,
        // so it should only be triggered when rendering indeed happens
        // in zrender. (Consider the case that dipatchAction is keep
        // triggering when mouse move).

        if ( // Although zr is dirty if initial animation is not finished
        // and this checking is called on frame, we also check
        // animation finished for robustness.
        zr.animation.isFinished() && !ecIns[PENDING_UPDATE] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) {
          ecIns.trigger('finished');
        }
      });
    };

    bindMouseEvent = function (zr, ecIns) {
      zr.on('mouseover', function (e) {
        var el = e.target;
        var dispatcher = findEventDispatcher(el, isHighDownDispatcher);

        if (dispatcher) {
          handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api);
          markStatusToUpdate(ecIns);
        }
      }).on('mouseout', function (e) {
        var el = e.target;
        var dispatcher = findEventDispatcher(el, isHighDownDispatcher);

        if (dispatcher) {
          handleGlobalMouseOutForHighDown(dispatcher, e, ecIns._api);
          markStatusToUpdate(ecIns);
        }
      }).on('click', function (e) {
        var el = e.target;
        var dispatcher = findEventDispatcher(el, function (target) {
          return getECData(target).dataIndex != null;
        }, true);

        if (dispatcher) {
          var actionType = dispatcher.selected ? 'unselect' : 'select';
          var ecData = getECData(dispatcher);

          ecIns._api.dispatchAction({
            type: actionType,
            dataType: ecData.dataType,
            dataIndexInside: ecData.dataIndex,
            seriesIndex: ecData.seriesIndex,
            isFromClick: true
          });
        }
      });
    };

    function clearColorPalette(ecModel) {
      ecModel.clearColorPalette();
      ecModel.eachSeries(function (seriesModel) {
        seriesModel.clearColorPalette();
      });
    }

    function allocateZlevels(ecModel) {
      var componentZLevels = [];
      var seriesZLevels = [];
      var hasSeperateZLevel = false;
      ecModel.eachComponent(function (componentType, componentModel) {
        var zlevel = componentModel.get('zlevel') || 0;
        var z = componentModel.get('z') || 0;
        var zlevelKey = componentModel.getZLevelKey();
        hasSeperateZLevel = hasSeperateZLevel || !!zlevelKey;
        (componentType === 'series' ? seriesZLevels : componentZLevels).push({
          zlevel: zlevel,
          z: z,
          idx: componentModel.componentIndex,
          type: componentType,
          key: zlevelKey
        });
      });

      if (hasSeperateZLevel) {
        // Series after component
        var zLevels = componentZLevels.concat(seriesZLevels);
        var lastSeriesZLevel_1;
        var lastSeriesKey_1;
        sort(zLevels, function (a, b) {
          if (a.zlevel === b.zlevel) {
            return a.z - b.z;
          }

          return a.zlevel - b.zlevel;
        });
        each$4(zLevels, function (item) {
          var componentModel = ecModel.getComponent(item.type, item.idx);
          var zlevel = item.zlevel;
          var key = item.key;

          if (lastSeriesZLevel_1 != null) {
            zlevel = Math.max(lastSeriesZLevel_1, zlevel);
          }

          if (key) {
            if (zlevel === lastSeriesZLevel_1 && key !== lastSeriesKey_1) {
              zlevel++;
            }

            lastSeriesKey_1 = key;
          } else if (lastSeriesKey_1) {
            if (zlevel === lastSeriesZLevel_1) {
              zlevel++;
            }

            lastSeriesKey_1 = '';
          }

          lastSeriesZLevel_1 = zlevel;
          componentModel.setZLevel(zlevel);
        });
      }
    }

    render = function (ecIns, ecModel, api, payload, updateParams) {
      allocateZlevels(ecModel);
      renderComponents(ecIns, ecModel, api, payload, updateParams);
      each$4(ecIns._chartsViews, function (chart) {
        chart.__alive = false;
      });
      renderSeries(ecIns, ecModel, api, payload, updateParams); // Remove groups of unrendered charts

      each$4(ecIns._chartsViews, function (chart) {
        if (!chart.__alive) {
          chart.remove(ecModel, api);
        }
      });
    };

    renderComponents = function (ecIns, ecModel, api, payload, updateParams, dirtyList) {
      each$4(dirtyList || ecIns._componentsViews, function (componentView) {
        var componentModel = componentView.__model;
        clearStates(componentModel, componentView);
        componentView.render(componentModel, ecModel, api, payload);
        updateZ(componentModel, componentView);
        updateStates(componentModel, componentView);
      });
    };
    /**
     * Render each chart and component
     */


    renderSeries = function (ecIns, ecModel, api, payload, updateParams, dirtyMap) {
      // Render all charts
      var scheduler = ecIns._scheduler;
      updateParams = extend(updateParams || {}, {
        updatedSeries: ecModel.getSeries()
      }); // TODO progressive?

      lifecycle$1.trigger('series:beforeupdate', ecModel, api, updateParams);
      var unfinished = false;
      ecModel.eachSeries(function (seriesModel) {
        var chartView = ecIns._chartsMap[seriesModel.__viewId];
        chartView.__alive = true;
        var renderTask = chartView.renderTask;
        scheduler.updatePayload(renderTask, payload); // TODO states on marker.

        clearStates(seriesModel, chartView);

        if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
          renderTask.dirty();
        }

        if (renderTask.perform(scheduler.getPerformArgs(renderTask))) {
          unfinished = true;
        }

        chartView.group.silent = !!seriesModel.get('silent'); // Should not call markRedraw on group, because it will disable zrender
        // incremental render (always render from the __startIndex each frame)
        // chartView.group.markRedraw();

        updateBlend(seriesModel, chartView);
        updateSeriesElementSelection(seriesModel);
      });
      scheduler.unfinished = unfinished || scheduler.unfinished;
      lifecycle$1.trigger('series:layoutlabels', ecModel, api, updateParams); // transition after label is layouted.

      lifecycle$1.trigger('series:transition', ecModel, api, updateParams);
      ecModel.eachSeries(function (seriesModel) {
        var chartView = ecIns._chartsMap[seriesModel.__viewId]; // Update Z after labels updated. Before applying states.

        updateZ(seriesModel, chartView); // NOTE: Update states after label is updated.
        // label should be in normal status when layouting.

        updateStates(seriesModel, chartView);
      }); // If use hover layer

      updateHoverLayerStatus(ecIns, ecModel);
      lifecycle$1.trigger('series:afterupdate', ecModel, api, updateParams);
    };

    markStatusToUpdate = function (ecIns) {
      ecIns[STATUS_NEEDS_UPDATE_KEY] = true; // Wake up zrender if it's sleep. Let it update states in the next frame.

      ecIns.getZr().wakeUp();
    };

    applyChangedStates = function (ecIns) {
      if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) {
        return;
      }

      ecIns.getZr().storage.traverse(function (el) {
        // Not applied on removed elements, it may still in fading.
        if (isElementRemoved(el)) {
          return;
        }

        applyElementStates(el);
      });
      ecIns[STATUS_NEEDS_UPDATE_KEY] = false;
    };

    function applyElementStates(el) {
      var newStates = [];
      var oldStates = el.currentStates; // Keep other states.

      for (var i = 0; i < oldStates.length; i++) {
        var stateName = oldStates[i];

        if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) {
          newStates.push(stateName);
        }
      } // Only use states when it's exists.


      if (el.selected && el.states.select) {
        newStates.push('select');
      }

      if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) {
        newStates.push('emphasis');
      } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) {
        newStates.push('blur');
      }

      el.useStates(newStates);
    }

    function updateHoverLayerStatus(ecIns, ecModel) {
      var zr = ecIns._zr;
      var storage = zr.storage;
      var elCount = 0;
      storage.traverse(function (el) {
        if (!el.isGroup) {
          elCount++;
        }
      });

      if (elCount > ecModel.get('hoverLayerThreshold') && !env$1.node && !env$1.worker) {
        ecModel.eachSeries(function (seriesModel) {
          if (seriesModel.preventUsingHoverLayer) {
            return;
          }

          var chartView = ecIns._chartsMap[seriesModel.__viewId];

          if (chartView.__alive) {
            chartView.eachRendered(function (el) {
              if (el.states.emphasis) {
                el.states.emphasis.hoverLayer = true;
              }
            });
          }
        });
      }
    }
    /**
     * Update chart and blend.
     */

    function updateBlend(seriesModel, chartView) {
      var blendMode = seriesModel.get('blendMode') || null;
      chartView.eachRendered(function (el) {
        // FIXME marker and other components
        if (!el.isGroup) {
          // DON'T mark the element dirty. In case element is incremental and don't want to rerender.
          el.style.blend = blendMode;
        }
      });
    }

    function updateZ(model, view) {
      if (model.preventAutoZ) {
        return;
      }

      var z = model.get('z') || 0;
      var zlevel = model.get('zlevel') || 0; // Set z and zlevel

      view.eachRendered(function (el) {
        doUpdateZ(el, z, zlevel, -Infinity); // Don't traverse the children because it has been traversed in _updateZ.

        return true;
      });
    }

    function doUpdateZ(el, z, zlevel, maxZ2) {
      // Group may also have textContent
      var label = el.getTextContent();
      var labelLine = el.getTextGuideLine();
      var isGroup = el.isGroup;

      if (isGroup) {
        // set z & zlevel of children elements of Group
        var children = el.childrenRef();

        for (var i = 0; i < children.length; i++) {
          maxZ2 = Math.max(doUpdateZ(children[i], z, zlevel, maxZ2), maxZ2);
        }
      } else {
        // not Group
        el.z = z;
        el.zlevel = zlevel;
        maxZ2 = Math.max(el.z2, maxZ2);
      } // always set z and zlevel if label/labelLine exists


      if (label) {
        label.z = z;
        label.zlevel = zlevel; // lift z2 of text content
        // TODO if el.emphasis.z2 is spcefied, what about textContent.

        isFinite(maxZ2) && (label.z2 = maxZ2 + 2);
      }

      if (labelLine) {
        var textGuideLineConfig = el.textGuideLineConfig;
        labelLine.z = z;
        labelLine.zlevel = zlevel;
        isFinite(maxZ2) && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1));
      }

      return maxZ2;
    } // Clear states without animation.
    // TODO States on component.


    function clearStates(model, view) {
      view.eachRendered(function (el) {
        // Not applied on removed elements, it may still in fading.
        if (isElementRemoved(el)) {
          return;
        }

        var textContent = el.getTextContent();
        var textGuide = el.getTextGuideLine();

        if (el.stateTransition) {
          el.stateTransition = null;
        }

        if (textContent && textContent.stateTransition) {
          textContent.stateTransition = null;
        }

        if (textGuide && textGuide.stateTransition) {
          textGuide.stateTransition = null;
        } // TODO If el is incremental.


        if (el.hasState()) {
          el.prevStates = el.currentStates;
          el.clearStates();
        } else if (el.prevStates) {
          el.prevStates = null;
        }
      });
    }

    function updateStates(model, view) {
      var stateAnimationModel = model.getModel('stateAnimation');
      var enableAnimation = model.isAnimationEnabled();
      var duration = stateAnimationModel.get('duration');
      var stateTransition = duration > 0 ? {
        duration: duration,
        delay: stateAnimationModel.get('delay'),
        easing: stateAnimationModel.get('easing') // additive: stateAnimationModel.get('additive')

      } : null;
      view.eachRendered(function (el) {
        if (el.states && el.states.emphasis) {
          // Not applied on removed elements, it may still in fading.
          if (isElementRemoved(el)) {
            return;
          }

          if (el instanceof Path$1) {
            savePathStates(el);
          } // Only updated on changed element. In case element is incremental and don't want to rerender.
          // TODO, a more proper way?


          if (el.__dirty) {
            var prevStates = el.prevStates; // Restore states without animation

            if (prevStates) {
              el.useStates(prevStates);
            }
          } // Update state transition and enable animation again.


          if (enableAnimation) {
            el.stateTransition = stateTransition;
            var textContent = el.getTextContent();
            var textGuide = el.getTextGuideLine(); // TODO Is it necessary to animate label?

            if (textContent) {
              textContent.stateTransition = stateTransition;
            }

            if (textGuide) {
              textGuide.stateTransition = stateTransition;
            }
          } // Use highlighted and selected flag to toggle states.


          if (el.__dirty) {
            applyElementStates(el);
          }
        }
      });
    }

    createExtensionAPI = function (ecIns) {
      return new (
      /** @class */
      function (_super) {
        __extends(class_1, _super);

        function class_1() {
          return _super !== null && _super.apply(this, arguments) || this;
        }

        class_1.prototype.getCoordinateSystems = function () {
          return ecIns._coordSysMgr.getCoordinateSystems();
        };

        class_1.prototype.getComponentByElement = function (el) {
          while (el) {
            var modelInfo = el.__ecComponentInfo;

            if (modelInfo != null) {
              return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index);
            }

            el = el.parent;
          }
        };

        class_1.prototype.enterEmphasis = function (el, highlightDigit) {
          enterEmphasis(el, highlightDigit);
          markStatusToUpdate(ecIns);
        };

        class_1.prototype.leaveEmphasis = function (el, highlightDigit) {
          leaveEmphasis(el, highlightDigit);
          markStatusToUpdate(ecIns);
        };

        class_1.prototype.enterBlur = function (el) {
          enterBlur(el);
          markStatusToUpdate(ecIns);
        };

        class_1.prototype.leaveBlur = function (el) {
          leaveBlur(el);
          markStatusToUpdate(ecIns);
        };

        class_1.prototype.enterSelect = function (el) {
          enterSelect(el);
          markStatusToUpdate(ecIns);
        };

        class_1.prototype.leaveSelect = function (el) {
          leaveSelect(el);
          markStatusToUpdate(ecIns);
        };

        class_1.prototype.getModel = function () {
          return ecIns.getModel();
        };

        class_1.prototype.getViewOfComponentModel = function (componentModel) {
          return ecIns.getViewOfComponentModel(componentModel);
        };

        class_1.prototype.getViewOfSeriesModel = function (seriesModel) {
          return ecIns.getViewOfSeriesModel(seriesModel);
        };

        return class_1;
      }(ExtensionAPI$1))(ecIns);
    };

    enableConnect = function (chart) {
      function updateConnectedChartsStatus(charts, status) {
        for (var i = 0; i < charts.length; i++) {
          var otherChart = charts[i];
          otherChart[CONNECT_STATUS_KEY] = status;
        }
      }

      each$4(eventActionMap, function (actionType, eventType) {
        chart._messageCenter.on(eventType, function (event) {
          if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) {
            if (event && event.escapeConnect) {
              return;
            }

            var action_1 = chart.makeActionFromEvent(event);
            var otherCharts_1 = [];
            each$4(instances, function (otherChart) {
              if (otherChart !== chart && otherChart.group === chart.group) {
                otherCharts_1.push(otherChart);
              }
            });
            updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING);
            each$4(otherCharts_1, function (otherChart) {
              if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) {
                otherChart.dispatchAction(action_1);
              }
            });
            updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED);
          }
        });
      });
    };
  }();

  return ECharts;
}(Eventful$1);

var echartsProto = ECharts.prototype;
echartsProto.on = createRegisterEventWithLowercaseECharts('on');
echartsProto.off = createRegisterEventWithLowercaseECharts('off');
/**
 * @deprecated
 */
// @ts-ignore

echartsProto.one = function (eventName, cb, ctx) {
  var self = this;

  function wrapped() {
    var args2 = [];

    for (var _i = 0; _i < arguments.length; _i++) {
      args2[_i] = arguments[_i];
    }

    cb && cb.apply && cb.apply(this, args2); // @ts-ignore

    self.off(eventName, wrapped);
  }

  this.on.call(this, eventName, wrapped, ctx);
};

var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu'];

function disposedWarning(id) {
}

var actions = {};
/**
 * Map eventType to actionType
 */

var eventActionMap = {};
var dataProcessorFuncs = [];
var optionPreprocessorFuncs = [];
var visualFuncs = [];
var themeStorage = {};
var loadingEffects = {};
var instances = {};
var connectedGroups = {};
var idBase = +new Date() - 0;
var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
/**
 * @param opts.devicePixelRatio Use window.devicePixelRatio by default
 * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart.
 * @param opts.width Use clientWidth of the input `dom` by default.
 *        Can be 'auto' (the same as null/undefined)
 * @param opts.height Use clientHeight of the input `dom` by default.
 *        Can be 'auto' (the same as null/undefined)
 * @param opts.locale Specify the locale.
 * @param opts.useDirtyRect Enable dirty rectangle rendering or not.
 */

function init(dom, theme, opts) {
  var isClient = !(opts && opts.ssr);

  if (isClient) {

    var existInstance = getInstanceByDom(dom);

    if (existInstance) {

      return existInstance;
    }
  }

  var chart = new ECharts(dom, theme, opts);
  chart.id = 'ec_' + idBase++;
  instances[chart.id] = chart;
  isClient && setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
  enableConnect(chart);
  lifecycle$1.trigger('afterinit', chart);
  return chart;
}
function getInstanceByDom(dom) {
  return instances[getAttribute(dom, DOM_ATTRIBUTE_KEY)];
}
/**
 * Register theme
 */

function registerTheme(name, theme) {
  themeStorage[name] = theme;
}
/**
 * Register option preprocessor
 */

function registerPreprocessor(preprocessorFunc) {
  if (indexOf(optionPreprocessorFuncs, preprocessorFunc) < 0) {
    optionPreprocessorFuncs.push(preprocessorFunc);
  }
}
function registerProcessor(priority, processor) {
  normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT);
}
/**
 * Register postIniter
 * @param {Function} postInitFunc
 */

function registerPostInit(postInitFunc) {
  registerUpdateLifecycle('afterinit', postInitFunc);
}
/**
 * Register postUpdater
 * @param {Function} postUpdateFunc
 */

function registerPostUpdate(postUpdateFunc) {
  registerUpdateLifecycle('afterupdate', postUpdateFunc);
}
function registerUpdateLifecycle(name, cb) {
  lifecycle$1.on(name, cb);
}
function registerAction(actionInfo, eventName, action) {
  if (isFunction(eventName)) {
    action = eventName;
    eventName = '';
  }

  var actionType = isObject$2(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = {
    event: eventName
  }][0]; // Event name is all lowercase

  actionInfo.event = (actionInfo.event || actionType).toLowerCase();
  eventName = actionInfo.event;

  if (eventActionMap[eventName]) {
    // Already registered.
    return;
  } // Validate action type and event name.


  assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));

  if (!actions[actionType]) {
    actions[actionType] = {
      action: action,
      actionInfo: actionInfo
    };
  }

  eventActionMap[eventName] = actionType;
}
function registerCoordinateSystem(type, coordSysCreator) {
  CoordinateSystem.register(type, coordSysCreator);
}

function registerLayout(priority, layoutTask) {
  normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout');
}

function registerVisual(priority, visualTask) {
  normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');
}
var registeredTasks = [];

function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) {
  if (isFunction(priority) || isObject$2(priority)) {
    fn = priority;
    priority = defaultPriority;
  }


  if (indexOf(registeredTasks, fn) >= 0) {
    return;
  }

  registeredTasks.push(fn);
  var stageHandler = Scheduler$1.wrapStageHandler(fn, visualType);
  stageHandler.__prio = priority;
  stageHandler.__raw = fn;
  targetList.push(stageHandler);
}

function registerLoading(name, loadingFx) {
  loadingEffects[name] = loadingFx;
}
/**
 * The parameters and usage: see `geoSourceManager.registerMap`.
 * Compatible with previous `echarts.registerMap`.
 */

function registerMap(mapName, geoJson, specialAreas) {
  var registerMap = getImpl('registerMap');
  registerMap && registerMap(mapName, geoJson, specialAreas);
}
var registerTransform = registerExternalTransform;
/**
 * Globa dispatchAction to a specified chart instance.
 */
// export function dispatchAction(payload: { chartId: string } & Payload, opt?: Parameters<ECharts['dispatchAction']>[1]) {
//     if (!payload || !payload.chartId) {
//         // Must have chartId to find chart
//         return;
//     }
//     const chart = instances[payload.chartId];
//     if (chart) {
//         chart.dispatchAction(payload, opt);
//     }
// }
// Builtin global visual

registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask);
registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask);
registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask);
registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask);
registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask);
registerVisual(PRIORITY_VISUAL_DECAL, decalVisual);
registerPreprocessor(globalBackwardCompat);
registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack);
registerLoading('default', defaultLoading); // Default actions

registerAction({
  type: HIGHLIGHT_ACTION_TYPE,
  event: HIGHLIGHT_ACTION_TYPE,
  update: HIGHLIGHT_ACTION_TYPE
}, noop);
registerAction({
  type: DOWNPLAY_ACTION_TYPE,
  event: DOWNPLAY_ACTION_TYPE,
  update: DOWNPLAY_ACTION_TYPE
}, noop);
registerAction({
  type: SELECT_ACTION_TYPE,
  event: SELECT_ACTION_TYPE,
  update: SELECT_ACTION_TYPE
}, noop);
registerAction({
  type: UNSELECT_ACTION_TYPE,
  event: UNSELECT_ACTION_TYPE,
  update: UNSELECT_ACTION_TYPE
}, noop);
registerAction({
  type: TOGGLE_SELECT_ACTION_TYPE,
  event: TOGGLE_SELECT_ACTION_TYPE,
  update: TOGGLE_SELECT_ACTION_TYPE
}, noop); // Default theme

registerTheme('light', lightTheme);
registerTheme('dark', darkTheme); // For backward compatibility, where the namespace `dataTool` will
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function dataIndexMapValueLength(valNumOrArrLengthMoreThan2) {
  return valNumOrArrLengthMoreThan2 == null ? 0 : valNumOrArrLengthMoreThan2.length || 1;
}

function defaultKeyGetter(item) {
  return item;
}

var DataDiffer =
/** @class */
function () {
  /**
   * @param context Can be visited by this.context in callback.
   */
  function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context, // By default: 'oneToOne'.
  diffMode) {
    this._old = oldArr;
    this._new = newArr;
    this._oldKeyGetter = oldKeyGetter || defaultKeyGetter;
    this._newKeyGetter = newKeyGetter || defaultKeyGetter; // Visible in callback via `this.context`;

    this.context = context;
    this._diffModeMultiple = diffMode === 'multiple';
  }
  /**
   * Callback function when add a data
   */


  DataDiffer.prototype.add = function (func) {
    this._add = func;
    return this;
  };
  /**
   * Callback function when update a data
   */


  DataDiffer.prototype.update = function (func) {
    this._update = func;
    return this;
  };
  /**
   * Callback function when update a data and only work in `cbMode: 'byKey'`.
   */


  DataDiffer.prototype.updateManyToOne = function (func) {
    this._updateManyToOne = func;
    return this;
  };
  /**
   * Callback function when update a data and only work in `cbMode: 'byKey'`.
   */


  DataDiffer.prototype.updateOneToMany = function (func) {
    this._updateOneToMany = func;
    return this;
  };
  /**
   * Callback function when update a data and only work in `cbMode: 'byKey'`.
   */


  DataDiffer.prototype.updateManyToMany = function (func) {
    this._updateManyToMany = func;
    return this;
  };
  /**
   * Callback function when remove a data
   */


  DataDiffer.prototype.remove = function (func) {
    this._remove = func;
    return this;
  };

  DataDiffer.prototype.execute = function () {
    this[this._diffModeMultiple ? '_executeMultiple' : '_executeOneToOne']();
  };

  DataDiffer.prototype._executeOneToOne = function () {
    var oldArr = this._old;
    var newArr = this._new;
    var newDataIndexMap = {};
    var oldDataKeyArr = new Array(oldArr.length);
    var newDataKeyArr = new Array(newArr.length);

    this._initIndexMap(oldArr, null, oldDataKeyArr, '_oldKeyGetter');

    this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter');

    for (var i = 0; i < oldArr.length; i++) {
      var oldKey = oldDataKeyArr[i];
      var newIdxMapVal = newDataIndexMap[oldKey];
      var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); // idx can never be empty array here. see 'set null' logic below.

      if (newIdxMapValLen > 1) {
        // Consider there is duplicate key (for example, use dataItem.name as key).
        // We should make sure every item in newArr and oldArr can be visited.
        var newIdx = newIdxMapVal.shift();

        if (newIdxMapVal.length === 1) {
          newDataIndexMap[oldKey] = newIdxMapVal[0];
        }

        this._update && this._update(newIdx, i);
      } else if (newIdxMapValLen === 1) {
        newDataIndexMap[oldKey] = null;
        this._update && this._update(newIdxMapVal, i);
      } else {
        this._remove && this._remove(i);
      }
    }

    this._performRestAdd(newDataKeyArr, newDataIndexMap);
  };
  /**
   * For example, consider the case:
   * oldData: [o0, o1, o2, o3, o4, o5, o6, o7],
   * newData: [n0, n1, n2, n3, n4, n5, n6, n7, n8],
   * Where:
   *     o0, o1, n0 has key 'a' (many to one)
   *     o5, n4, n5, n6 has key 'b' (one to many)
   *     o2, n1 has key 'c' (one to one)
   *     n2, n3 has key 'd' (add)
   *     o3, o4 has key 'e' (remove)
   *     o6, o7, n7, n8 has key 'f' (many to many, treated as add and remove)
   * Then:
   *     (The order of the following directives are not ensured.)
   *     this._updateManyToOne(n0, [o0, o1]);
   *     this._updateOneToMany([n4, n5, n6], o5);
   *     this._update(n1, o2);
   *     this._remove(o3);
   *     this._remove(o4);
   *     this._remove(o6);
   *     this._remove(o7);
   *     this._add(n2);
   *     this._add(n3);
   *     this._add(n7);
   *     this._add(n8);
   */


  DataDiffer.prototype._executeMultiple = function () {
    var oldArr = this._old;
    var newArr = this._new;
    var oldDataIndexMap = {};
    var newDataIndexMap = {};
    var oldDataKeyArr = [];
    var newDataKeyArr = [];

    this._initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter');

    this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter');

    for (var i = 0; i < oldDataKeyArr.length; i++) {
      var oldKey = oldDataKeyArr[i];
      var oldIdxMapVal = oldDataIndexMap[oldKey];
      var newIdxMapVal = newDataIndexMap[oldKey];
      var oldIdxMapValLen = dataIndexMapValueLength(oldIdxMapVal);
      var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal);

      if (oldIdxMapValLen > 1 && newIdxMapValLen === 1) {
        this._updateManyToOne && this._updateManyToOne(newIdxMapVal, oldIdxMapVal);
        newDataIndexMap[oldKey] = null;
      } else if (oldIdxMapValLen === 1 && newIdxMapValLen > 1) {
        this._updateOneToMany && this._updateOneToMany(newIdxMapVal, oldIdxMapVal);
        newDataIndexMap[oldKey] = null;
      } else if (oldIdxMapValLen === 1 && newIdxMapValLen === 1) {
        this._update && this._update(newIdxMapVal, oldIdxMapVal);
        newDataIndexMap[oldKey] = null;
      } else if (oldIdxMapValLen > 1 && newIdxMapValLen > 1) {
        this._updateManyToMany && this._updateManyToMany(newIdxMapVal, oldIdxMapVal);
        newDataIndexMap[oldKey] = null;
      } else if (oldIdxMapValLen > 1) {
        for (var i_1 = 0; i_1 < oldIdxMapValLen; i_1++) {
          this._remove && this._remove(oldIdxMapVal[i_1]);
        }
      } else {
        this._remove && this._remove(oldIdxMapVal);
      }
    }

    this._performRestAdd(newDataKeyArr, newDataIndexMap);
  };

  DataDiffer.prototype._performRestAdd = function (newDataKeyArr, newDataIndexMap) {
    for (var i = 0; i < newDataKeyArr.length; i++) {
      var newKey = newDataKeyArr[i];
      var newIdxMapVal = newDataIndexMap[newKey];
      var idxMapValLen = dataIndexMapValueLength(newIdxMapVal);

      if (idxMapValLen > 1) {
        for (var j = 0; j < idxMapValLen; j++) {
          this._add && this._add(newIdxMapVal[j]);
        }
      } else if (idxMapValLen === 1) {
        this._add && this._add(newIdxMapVal);
      } // Support both `newDataKeyArr` are duplication removed or not removed.


      newDataIndexMap[newKey] = null;
    }
  };

  DataDiffer.prototype._initIndexMap = function (arr, // Can be null.
  map, // In 'byKey', the output `keyArr` is duplication removed.
  // In 'byIndex', the output `keyArr` is not duplication removed and
  //     its indices are accurately corresponding to `arr`.
  keyArr, keyGetterName) {
    var cbModeMultiple = this._diffModeMultiple;

    for (var i = 0; i < arr.length; i++) {
      // Add prefix to avoid conflict with Object.prototype.
      var key = '_ec_' + this[keyGetterName](arr[i], i);

      if (!cbModeMultiple) {
        keyArr[i] = key;
      }

      if (!map) {
        continue;
      }

      var idxMapVal = map[key];
      var idxMapValLen = dataIndexMapValueLength(idxMapVal);

      if (idxMapValLen === 0) {
        // Simple optimize: in most cases, one index has one key,
        // do not need array.
        map[key] = i;

        if (cbModeMultiple) {
          keyArr.push(key);
        }
      } else if (idxMapValLen === 1) {
        map[key] = [idxMapVal, i];
      } else {
        idxMapVal.push(i);
      }
    }
  };

  return DataDiffer;
}();

const DataDiffer$1 = DataDiffer;
/* Injected with object hook! */

var DimensionUserOuput =
/** @class */
function () {
  function DimensionUserOuput(encode, dimRequest) {
    this._encode = encode;
    this._schema = dimRequest;
  }

  DimensionUserOuput.prototype.get = function () {
    return {
      // Do not generate full dimension name until fist used.
      fullDimensions: this._getFullDimensionNames(),
      encode: this._encode
    };
  };
  /**
   * Get all data store dimension names.
   * Theoretically a series data store is defined both by series and used dataset (if any).
   * If some dimensions are omitted for performance reason in `this.dimensions`,
   * the dimension name may not be auto-generated if user does not specify a dimension name.
   * In this case, the dimension name is `null`/`undefined`.
   */


  DimensionUserOuput.prototype._getFullDimensionNames = function () {
    if (!this._cachedDimNames) {
      this._cachedDimNames = this._schema ? this._schema.makeOutputDimensionNames() : [];
    }

    return this._cachedDimNames;
  };

  return DimensionUserOuput;
}();
function summarizeDimensions(data, schema) {
  var summary = {};
  var encode = summary.encode = {};
  var notExtraCoordDimMap = createHashMap();
  var defaultedLabel = [];
  var defaultedTooltip = [];
  var userOutputEncode = {};
  each$4(data.dimensions, function (dimName) {
    var dimItem = data.getDimensionInfo(dimName);
    var coordDim = dimItem.coordDim;

    if (coordDim) {

      var coordDimIndex = dimItem.coordDimIndex;
      getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName;

      if (!dimItem.isExtraCoord) {
        notExtraCoordDimMap.set(coordDim, 1); // Use the last coord dim (and label friendly) as default label,
        // because when dataset is used, it is hard to guess which dimension
        // can be value dimension. If both show x, y on label is not look good,
        // and conventionally y axis is focused more.

        if (mayLabelDimType(dimItem.type)) {
          defaultedLabel[0] = dimName;
        } // User output encode do not contain generated coords.
        // And it only has index. User can use index to retrieve value from the raw item array.


        getOrCreateEncodeArr(userOutputEncode, coordDim)[coordDimIndex] = data.getDimensionIndex(dimItem.name);
      }

      if (dimItem.defaultTooltip) {
        defaultedTooltip.push(dimName);
      }
    }

    VISUAL_DIMENSIONS.each(function (v, otherDim) {
      var encodeArr = getOrCreateEncodeArr(encode, otherDim);
      var dimIndex = dimItem.otherDims[otherDim];

      if (dimIndex != null && dimIndex !== false) {
        encodeArr[dimIndex] = dimItem.name;
      }
    });
  });
  var dataDimsOnCoord = [];
  var encodeFirstDimNotExtra = {};
  notExtraCoordDimMap.each(function (v, coordDim) {
    var dimArr = encode[coordDim];
    encodeFirstDimNotExtra[coordDim] = dimArr[0]; // Not necessary to remove duplicate, because a data
    // dim canot on more than one coordDim.

    dataDimsOnCoord = dataDimsOnCoord.concat(dimArr);
  });
  summary.dataDimsOnCoord = dataDimsOnCoord;
  summary.dataDimIndicesOnCoord = map$1(dataDimsOnCoord, function (dimName) {
    return data.getDimensionInfo(dimName).storeDimIndex;
  });
  summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra;
  var encodeLabel = encode.label; // FIXME `encode.label` is not recommended, because formatter cannot be set
  // in this way. Use label.formatter instead. Maybe remove this approach someday.

  if (encodeLabel && encodeLabel.length) {
    defaultedLabel = encodeLabel.slice();
  }

  var encodeTooltip = encode.tooltip;

  if (encodeTooltip && encodeTooltip.length) {
    defaultedTooltip = encodeTooltip.slice();
  } else if (!defaultedTooltip.length) {
    defaultedTooltip = defaultedLabel.slice();
  }

  encode.defaultedLabel = defaultedLabel;
  encode.defaultedTooltip = defaultedTooltip;
  summary.userOutput = new DimensionUserOuput(userOutputEncode, schema);
  return summary;
}

function getOrCreateEncodeArr(encode, dim) {
  if (!encode.hasOwnProperty(dim)) {
    encode[dim] = [];
  }

  return encode[dim];
} // FIXME:TS should be type `AxisType`


function getDimensionTypeByAxis(axisType) {
  return axisType === 'category' ? 'ordinal' : axisType === 'time' ? 'time' : 'float';
}

function mayLabelDimType(dimType) {
  // In most cases, ordinal and time do not suitable for label.
  // Ordinal info can be displayed on axis. Time is too long.
  return !(dimType === 'ordinal' || dimType === 'time');
} // function findTheLastDimMayLabel(data) {
//     // Get last value dim
//     let dimensions = data.dimensions.slice();
//     let valueType;
//     let valueDim;
//     while (dimensions.length && (
//         valueDim = dimensions.pop(),
//         valueType = data.getDimensionInfo(valueDim).type,
//         valueType === 'ordinal' || valueType === 'time'
//     )) {} // jshint ignore:line
//     return valueDim;
// }
/* Injected with object hook! */

var SeriesDimensionDefine =
/** @class */
function () {
  /**
   * @param opt All of the fields will be shallow copied.
   */
  function SeriesDimensionDefine(opt) {
    /**
     * The format of `otherDims` is:
     * ```js
     * {
     *     tooltip?: number
     *     label?: number
     *     itemName?: number
     *     seriesName?: number
     * }
     * ```
     *
     * A `series.encode` can specified these fields:
     * ```js
     * encode: {
     *     // "3, 1, 5" is the index of data dimension.
     *     tooltip: [3, 1, 5],
     *     label: [0, 3],
     *     ...
     * }
     * ```
     * `otherDims` is the parse result of the `series.encode` above, like:
     * ```js
     * // Suppose the index of this data dimension is `3`.
     * this.otherDims = {
     *     // `3` is at the index `0` of the `encode.tooltip`
     *     tooltip: 0,
     *     // `3` is at the index `1` of the `encode.label`
     *     label: 1
     * };
     * ```
     *
     * This prop should never be `null`/`undefined` after initialized.
     */
    this.otherDims = {};

    if (opt != null) {
      extend(this, opt);
    }
  }

  return SeriesDimensionDefine;
}();
const SeriesDimensionDefine$1 = SeriesDimensionDefine;
/* Injected with object hook! */

var inner$5 = makeInner();
var dimTypeShort = {
  float: 'f',
  int: 'i',
  ordinal: 'o',
  number: 'n',
  time: 't'
};
/**
 * Represents the dimension requirement of a series.
 *
 * NOTICE:
 * When there are too many dimensions in dataset and many series, only the used dimensions
 * (i.e., used by coord sys and declared in `series.encode`) are add to `dimensionDefineList`.
 * But users may query data by other unused dimension names.
 * In this case, users can only query data if and only if they have defined dimension names
 * via ec option, so we provide `getDimensionIndexFromSource`, which only query them from
 * `source` dimensions.
 */

var SeriesDataSchema =
/** @class */
function () {
  function SeriesDataSchema(opt) {
    this.dimensions = opt.dimensions;
    this._dimOmitted = opt.dimensionOmitted;
    this.source = opt.source;
    this._fullDimCount = opt.fullDimensionCount;

    this._updateDimOmitted(opt.dimensionOmitted);
  }

  SeriesDataSchema.prototype.isDimensionOmitted = function () {
    return this._dimOmitted;
  };

  SeriesDataSchema.prototype._updateDimOmitted = function (dimensionOmitted) {
    this._dimOmitted = dimensionOmitted;

    if (!dimensionOmitted) {
      return;
    }

    if (!this._dimNameMap) {
      this._dimNameMap = ensureSourceDimNameMap(this.source);
    }
  };
  /**
   * @caution Can only be used when `dimensionOmitted: true`.
   *
   * Get index by user defined dimension name (i.e., not internal generate name).
   * That is, get index from `dimensionsDefine`.
   * If no `dimensionsDefine`, or no name get, return -1.
   */


  SeriesDataSchema.prototype.getSourceDimensionIndex = function (dimName) {
    return retrieve2(this._dimNameMap.get(dimName), -1);
  };
  /**
   * @caution Can only be used when `dimensionOmitted: true`.
   *
   * Notice: may return `null`/`undefined` if user not specify dimension names.
   */


  SeriesDataSchema.prototype.getSourceDimension = function (dimIndex) {
    var dimensionsDefine = this.source.dimensionsDefine;

    if (dimensionsDefine) {
      return dimensionsDefine[dimIndex];
    }
  };

  SeriesDataSchema.prototype.makeStoreSchema = function () {
    var dimCount = this._fullDimCount;
    var willRetrieveDataByName = shouldRetrieveDataByName(this.source);
    var makeHashStrict = !shouldOmitUnusedDimensions(dimCount); // If source don't have dimensions or series don't omit unsed dimensions.
    // Generate from seriesDimList directly

    var dimHash = '';
    var dims = [];

    for (var fullDimIdx = 0, seriesDimIdx = 0; fullDimIdx < dimCount; fullDimIdx++) {
      var property = void 0;
      var type = void 0;
      var ordinalMeta = void 0;
      var seriesDimDef = this.dimensions[seriesDimIdx]; // The list has been sorted by `storeDimIndex` asc.

      if (seriesDimDef && seriesDimDef.storeDimIndex === fullDimIdx) {
        property = willRetrieveDataByName ? seriesDimDef.name : null;
        type = seriesDimDef.type;
        ordinalMeta = seriesDimDef.ordinalMeta;
        seriesDimIdx++;
      } else {
        var sourceDimDef = this.getSourceDimension(fullDimIdx);

        if (sourceDimDef) {
          property = willRetrieveDataByName ? sourceDimDef.name : null;
          type = sourceDimDef.type;
        }
      }

      dims.push({
        property: property,
        type: type,
        ordinalMeta: ordinalMeta
      }); // If retrieving data by index,
      //   use <index, type, ordinalMeta> to determine whether data can be shared.
      //   (Because in this case there might be no dimension name defined in dataset, but indices always exists).
      //   (Indices are always 0, 1, 2, ..., so we can ignore them to shorten the hash).
      // Otherwise if retrieving data by property name (like `data: [{aa: 123, bb: 765}, ...]`),
      //   use <property, type, ordinalMeta> in hash.

      if (willRetrieveDataByName && property != null // For data stack, we have make sure each series has its own dim on this store.
      // So we do not add property to hash to make sure they can share this store.
      && (!seriesDimDef || !seriesDimDef.isCalculationCoord)) {
        dimHash += makeHashStrict // Use escape character '`' in case that property name contains '$'.
        ? property.replace(/\`/g, '`1').replace(/\$/g, '`2') // For better performance, when there are large dimensions, tolerant this defects that hardly meet.
        : property;
      }

      dimHash += '$';
      dimHash += dimTypeShort[type] || 'f';

      if (ordinalMeta) {
        dimHash += ordinalMeta.uid;
      }

      dimHash += '$';
    } // Source from endpoint(usually series) will be read differently
    // when seriesLayoutBy or startIndex(which is affected by sourceHeader) are different.
    // So we use this three props as key.


    var source = this.source;
    var hash = [source.seriesLayoutBy, source.startIndex, dimHash].join('$$');
    return {
      dimensions: dims,
      hash: hash
    };
  };

  SeriesDataSchema.prototype.makeOutputDimensionNames = function () {
    var result = [];

    for (var fullDimIdx = 0, seriesDimIdx = 0; fullDimIdx < this._fullDimCount; fullDimIdx++) {
      var name_1 = void 0;
      var seriesDimDef = this.dimensions[seriesDimIdx]; // The list has been sorted by `storeDimIndex` asc.

      if (seriesDimDef && seriesDimDef.storeDimIndex === fullDimIdx) {
        if (!seriesDimDef.isCalculationCoord) {
          name_1 = seriesDimDef.name;
        }

        seriesDimIdx++;
      } else {
        var sourceDimDef = this.getSourceDimension(fullDimIdx);

        if (sourceDimDef) {
          name_1 = sourceDimDef.name;
        }
      }

      result.push(name_1);
    }

    return result;
  };

  SeriesDataSchema.prototype.appendCalculationDimension = function (dimDef) {
    this.dimensions.push(dimDef);
    dimDef.isCalculationCoord = true;
    this._fullDimCount++; // If append dimension on a data store, consider the store
    // might be shared by different series, series dimensions not
    // really map to store dimensions.

    this._updateDimOmitted(true);
  };

  return SeriesDataSchema;
}();
function isSeriesDataSchema(schema) {
  return schema instanceof SeriesDataSchema;
}
function createDimNameMap(dimsDef) {
  var dataDimNameMap = createHashMap();

  for (var i = 0; i < (dimsDef || []).length; i++) {
    var dimDefItemRaw = dimsDef[i];
    var userDimName = isObject$2(dimDefItemRaw) ? dimDefItemRaw.name : dimDefItemRaw;

    if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
      dataDimNameMap.set(userDimName, i);
    }
  }

  return dataDimNameMap;
}
function ensureSourceDimNameMap(source) {
  var innerSource = inner$5(source);
  return innerSource.dimNameMap || (innerSource.dimNameMap = createDimNameMap(source.dimensionsDefine));
}
function shouldOmitUnusedDimensions(dimCount) {
  return dimCount > 30;
}
/* Injected with object hook! */

var isObject = isObject$2;
var map = map$1;
var CtorInt32Array = typeof Int32Array === 'undefined' ? Array : Int32Array; // Use prefix to avoid index to be the same as otherIdList[idx],
// which will cause weird update animation.

var ID_PREFIX = 'e\0\0';
var INDEX_NOT_FOUND = -1; // type SeriesDimensionIndex = DimensionIndex;

var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_dimSummary', 'userOutput', '_rawData', '_dimValueGetter', '_nameDimIdx', '_idDimIdx', '_nameRepeatCount'];
var CLONE_PROPERTIES = ['_approximateExtent']; // -----------------------------
// Internal method declarations:
// -----------------------------

var prepareInvertedIndex;
var getId;
var getIdNameFromStore;
var normalizeDimensions;
var transferProperties;
var cloneListForMapAndSample;
var makeIdFromName;

var SeriesData =
/** @class */
function () {
  /**
   * @param dimensionsInput.dimensions
   *        For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
   *        Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
   */
  function SeriesData(dimensionsInput, hostModel) {
    this.type = 'list';
    this._dimOmitted = false;
    this._nameList = [];
    this._idList = []; // Models of data option is stored sparse for optimizing memory cost
    // Never used yet (not used yet).
    // private _optionModels: Model[] = [];
    // Global visual properties after visual coding

    this._visual = {}; // Global layout properties.

    this._layout = {}; // Item visual properties after visual coding

    this._itemVisuals = []; // Item layout properties after layout

    this._itemLayouts = []; // Graphic elements

    this._graphicEls = []; // key: dim, value: extent

    this._approximateExtent = {};
    this._calculationInfo = {}; // Having detected that there is data item is non primitive type
    // (in type `OptionDataItemObject`).
    // Like `data: [ { value: xx, itemStyle: {...} }, ...]`
    // At present it only happen in `SOURCE_FORMAT_ORIGINAL`.

    this.hasItemOption = false; // Methods that create a new list based on this list should be listed here.
    // Notice that those method should `RETURN` the new list.

    this.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'lttbDownSample', 'map']; // Methods that change indices of this list should be listed here.

    this.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
    this.DOWNSAMPLE_METHODS = ['downSample', 'lttbDownSample'];
    var dimensions;
    var assignStoreDimIdx = false;

    if (isSeriesDataSchema(dimensionsInput)) {
      dimensions = dimensionsInput.dimensions;
      this._dimOmitted = dimensionsInput.isDimensionOmitted();
      this._schema = dimensionsInput;
    } else {
      assignStoreDimIdx = true;
      dimensions = dimensionsInput;
    }

    dimensions = dimensions || ['x', 'y'];
    var dimensionInfos = {};
    var dimensionNames = [];
    var invertedIndicesMap = {};
    var needsHasOwn = false;
    var emptyObj = {};

    for (var i = 0; i < dimensions.length; i++) {
      // Use the original dimensions[i], where other flag props may exists.
      var dimInfoInput = dimensions[i];
      var dimensionInfo = isString(dimInfoInput) ? new SeriesDimensionDefine$1({
        name: dimInfoInput
      }) : !(dimInfoInput instanceof SeriesDimensionDefine$1) ? new SeriesDimensionDefine$1(dimInfoInput) : dimInfoInput;
      var dimensionName = dimensionInfo.name;
      dimensionInfo.type = dimensionInfo.type || 'float';

      if (!dimensionInfo.coordDim) {
        dimensionInfo.coordDim = dimensionName;
        dimensionInfo.coordDimIndex = 0;
      }

      var otherDims = dimensionInfo.otherDims = dimensionInfo.otherDims || {};
      dimensionNames.push(dimensionName);
      dimensionInfos[dimensionName] = dimensionInfo;

      if (emptyObj[dimensionName] != null) {
        needsHasOwn = true;
      }

      if (dimensionInfo.createInvertedIndices) {
        invertedIndicesMap[dimensionName] = [];
      }

      if (otherDims.itemName === 0) {
        this._nameDimIdx = i;
      }

      if (otherDims.itemId === 0) {
        this._idDimIdx = i;
      }

      if (assignStoreDimIdx) {
        dimensionInfo.storeDimIndex = i;
      }
    }

    this.dimensions = dimensionNames;
    this._dimInfos = dimensionInfos;

    this._initGetDimensionInfo(needsHasOwn);

    this.hostModel = hostModel;
    this._invertedIndicesMap = invertedIndicesMap;

    if (this._dimOmitted) {
      var dimIdxToName_1 = this._dimIdxToName = createHashMap();
      each$4(dimensionNames, function (dimName) {
        dimIdxToName_1.set(dimensionInfos[dimName].storeDimIndex, dimName);
      });
    }
  }
  /**
   *
   * Get concrete dimension name by dimension name or dimension index.
   * If input a dimension name, do not validate whether the dimension name exits.
   *
   * @caution
   * @param dim Must make sure the dimension is `SeriesDimensionLoose`.
   * Because only those dimensions will have auto-generated dimension names if not
   * have a user-specified name, and other dimensions will get a return of null/undefined.
   *
   * @notice Because of this reason, should better use `getDimensionIndex` instead, for examples:
   * ```js
   * const val = data.getStore().get(data.getDimensionIndex(dim), dataIdx);
   * ```
   *
   * @return Concrete dim name.
   */


  SeriesData.prototype.getDimension = function (dim) {
    var dimIdx = this._recognizeDimIndex(dim);

    if (dimIdx == null) {
      return dim;
    }

    dimIdx = dim;

    if (!this._dimOmitted) {
      return this.dimensions[dimIdx];
    } // Retrieve from series dimension definition because it probably contains
    // generated dimension name (like 'x', 'y').


    var dimName = this._dimIdxToName.get(dimIdx);

    if (dimName != null) {
      return dimName;
    }

    var sourceDimDef = this._schema.getSourceDimension(dimIdx);

    if (sourceDimDef) {
      return sourceDimDef.name;
    }
  };
  /**
   * Get dimension index in data store. Return -1 if not found.
   * Can be used to index value from getRawValue.
   */


  SeriesData.prototype.getDimensionIndex = function (dim) {
    var dimIdx = this._recognizeDimIndex(dim);

    if (dimIdx != null) {
      return dimIdx;
    }

    if (dim == null) {
      return -1;
    }

    var dimInfo = this._getDimInfo(dim);

    return dimInfo ? dimInfo.storeDimIndex : this._dimOmitted ? this._schema.getSourceDimensionIndex(dim) : -1;
  };
  /**
   * The meanings of the input parameter `dim`:
   *
   * + If dim is a number (e.g., `1`), it means the index of the dimension.
   *   For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'.
   * + If dim is a number-like string (e.g., `"1"`):
   *     + If there is the same concrete dim name defined in `series.dimensions` or `dataset.dimensions`,
   *        it means that concrete name.
   *     + If not, it will be converted to a number, which means the index of the dimension.
   *        (why? because of the backward compatibility. We have been tolerating number-like string in
   *        dimension setting, although now it seems that it is not a good idea.)
   *     For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`,
   *     if no dimension name is defined as `"1"`.
   * + If dim is a not-number-like string, it means the concrete dim name.
   *   For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`,
   *   or customized in `dimensions` property of option like `"age"`.
   *
   * @return recognized `DimensionIndex`. Otherwise return null/undefined (means that dim is `DimensionName`).
   */


  SeriesData.prototype._recognizeDimIndex = function (dim) {
    if (isNumber(dim) // If being a number-like string but not being defined as a dimension name.
    || dim != null && !isNaN(dim) && !this._getDimInfo(dim) && (!this._dimOmitted || this._schema.getSourceDimensionIndex(dim) < 0)) {
      return +dim;
    }
  };

  SeriesData.prototype._getStoreDimIndex = function (dim) {
    var dimIdx = this.getDimensionIndex(dim);

    return dimIdx;
  };
  /**
   * Get type and calculation info of particular dimension
   * @param dim
   *        Dimension can be concrete names like x, y, z, lng, lat, angle, radius
   *        Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
   */


  SeriesData.prototype.getDimensionInfo = function (dim) {
    // Do not clone, because there may be categories in dimInfo.
    return this._getDimInfo(this.getDimension(dim));
  };

  SeriesData.prototype._initGetDimensionInfo = function (needsHasOwn) {
    var dimensionInfos = this._dimInfos;
    this._getDimInfo = needsHasOwn ? function (dimName) {
      return dimensionInfos.hasOwnProperty(dimName) ? dimensionInfos[dimName] : undefined;
    } : function (dimName) {
      return dimensionInfos[dimName];
    };
  };
  /**
   * concrete dimension name list on coord.
   */


  SeriesData.prototype.getDimensionsOnCoord = function () {
    return this._dimSummary.dataDimsOnCoord.slice();
  };

  SeriesData.prototype.mapDimension = function (coordDim, idx) {
    var dimensionsSummary = this._dimSummary;

    if (idx == null) {
      return dimensionsSummary.encodeFirstDimNotExtra[coordDim];
    }

    var dims = dimensionsSummary.encode[coordDim];
    return dims ? dims[idx] : null;
  };

  SeriesData.prototype.mapDimensionsAll = function (coordDim) {
    var dimensionsSummary = this._dimSummary;
    var dims = dimensionsSummary.encode[coordDim];
    return (dims || []).slice();
  };

  SeriesData.prototype.getStore = function () {
    return this._store;
  };
  /**
   * Initialize from data
   * @param data source or data or data store.
   * @param nameList The name of a datum is used on data diff and
   *        default label/tooltip.
   *        A name can be specified in encode.itemName,
   *        or dataItem.name (only for series option data),
   *        or provided in nameList from outside.
   */


  SeriesData.prototype.initData = function (data, nameList, dimValueGetter) {
    var _this = this;

    var store;

    if (data instanceof DataStore) {
      store = data;
    }

    if (!store) {
      var dimensions = this.dimensions;
      var provider = isSourceInstance(data) || isArrayLike(data) ? new DefaultDataProvider(data, dimensions.length) : data;
      store = new DataStore();
      var dimensionInfos = map(dimensions, function (dimName) {
        return {
          type: _this._dimInfos[dimName].type,
          property: dimName
        };
      });
      store.initData(provider, dimensionInfos, dimValueGetter);
    }

    this._store = store; // Reset

    this._nameList = (nameList || []).slice();
    this._idList = [];
    this._nameRepeatCount = {};

    this._doInit(0, store.count()); // Cache summary info for fast visit. See "dimensionHelper".
    // Needs to be initialized after store is prepared.


    this._dimSummary = summarizeDimensions(this, this._schema);
    this.userOutput = this._dimSummary.userOutput;
  };
  /**
   * Caution: Can be only called on raw data (before `this._indices` created).
   */


  SeriesData.prototype.appendData = function (data) {
    var range = this._store.appendData(data);

    this._doInit(range[0], range[1]);
  };
  /**
   * Caution: Can be only called on raw data (before `this._indices` created).
   * This method does not modify `rawData` (`dataProvider`), but only
   * add values to store.
   *
   * The final count will be increased by `Math.max(values.length, names.length)`.
   *
   * @param values That is the SourceType: 'arrayRows', like
   *        [
   *            [12, 33, 44],
   *            [NaN, 43, 1],
   *            ['-', 'asdf', 0]
   *        ]
   *        Each item is exactly corresponding to a dimension.
   */


  SeriesData.prototype.appendValues = function (values, names) {
    var _a = this._store.appendValues(values, names.length),
        start = _a.start,
        end = _a.end;

    var shouldMakeIdFromName = this._shouldMakeIdFromName();

    this._updateOrdinalMeta();

    if (names) {
      for (var idx = start; idx < end; idx++) {
        var sourceIdx = idx - start;
        this._nameList[idx] = names[sourceIdx];

        if (shouldMakeIdFromName) {
          makeIdFromName(this, idx);
        }
      }
    }
  };

  SeriesData.prototype._updateOrdinalMeta = function () {
    var store = this._store;
    var dimensions = this.dimensions;

    for (var i = 0; i < dimensions.length; i++) {
      var dimInfo = this._dimInfos[dimensions[i]];

      if (dimInfo.ordinalMeta) {
        store.collectOrdinalMeta(dimInfo.storeDimIndex, dimInfo.ordinalMeta);
      }
    }
  };

  SeriesData.prototype._shouldMakeIdFromName = function () {
    var provider = this._store.getProvider();

    return this._idDimIdx == null && provider.getSource().sourceFormat !== SOURCE_FORMAT_TYPED_ARRAY && !provider.fillStorage;
  };

  SeriesData.prototype._doInit = function (start, end) {
    if (start >= end) {
      return;
    }

    var store = this._store;
    var provider = store.getProvider();

    this._updateOrdinalMeta();

    var nameList = this._nameList;
    var idList = this._idList;
    var sourceFormat = provider.getSource().sourceFormat;
    var isFormatOriginal = sourceFormat === SOURCE_FORMAT_ORIGINAL; // Each data item is value
    // [1, 2]
    // 2
    // Bar chart, line chart which uses category axis
    // only gives the 'y' value. 'x' value is the indices of category
    // Use a tempValue to normalize the value to be a (x, y) value
    // If dataItem is {name: ...} or {id: ...}, it has highest priority.
    // This kind of ids and names are always stored `_nameList` and `_idList`.

    if (isFormatOriginal && !provider.pure) {
      var sharedDataItem = [];

      for (var idx = start; idx < end; idx++) {
        // NOTICE: Try not to write things into dataItem
        var dataItem = provider.getItem(idx, sharedDataItem);

        if (!this.hasItemOption && isDataItemOption(dataItem)) {
          this.hasItemOption = true;
        }

        if (dataItem) {
          var itemName = dataItem.name;

          if (nameList[idx] == null && itemName != null) {
            nameList[idx] = convertOptionIdName(itemName, null);
          }

          var itemId = dataItem.id;

          if (idList[idx] == null && itemId != null) {
            idList[idx] = convertOptionIdName(itemId, null);
          }
        }
      }
    }

    if (this._shouldMakeIdFromName()) {
      for (var idx = start; idx < end; idx++) {
        makeIdFromName(this, idx);
      }
    }

    prepareInvertedIndex(this);
  };
  /**
   * PENDING: In fact currently this function is only used to short-circuit
   * the calling of `scale.unionExtentFromData` when data have been filtered by modules
   * like "dataZoom". `scale.unionExtentFromData` is used to calculate data extent for series on
   * an axis, but if a "axis related data filter module" is used, the extent of the axis have
   * been fixed and no need to calling `scale.unionExtentFromData` actually.
   * But if we add "custom data filter" in future, which is not "axis related", this method may
   * be still needed.
   *
   * Optimize for the scenario that data is filtered by a given extent.
   * Consider that if data amount is more than hundreds of thousand,
   * extent calculation will cost more than 10ms and the cache will
   * be erased because of the filtering.
   */


  SeriesData.prototype.getApproximateExtent = function (dim) {
    return this._approximateExtent[dim] || this._store.getDataExtent(this._getStoreDimIndex(dim));
  };
  /**
   * Calculate extent on a filtered data might be time consuming.
   * Approximate extent is only used for: calculate extent of filtered data outside.
   */


  SeriesData.prototype.setApproximateExtent = function (extent, dim) {
    dim = this.getDimension(dim);
    this._approximateExtent[dim] = extent.slice();
  };

  SeriesData.prototype.getCalculationInfo = function (key) {
    return this._calculationInfo[key];
  };

  SeriesData.prototype.setCalculationInfo = function (key, value) {
    isObject(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value;
  };
  /**
   * @return Never be null/undefined. `number` will be converted to string. Because:
   * In most cases, name is used in display, where returning a string is more convenient.
   * In other cases, name is used in query (see `indexOfName`), where we can keep the
   * rule that name `2` equals to name `'2'`.
   */


  SeriesData.prototype.getName = function (idx) {
    var rawIndex = this.getRawIndex(idx);
    var name = this._nameList[rawIndex];

    if (name == null && this._nameDimIdx != null) {
      name = getIdNameFromStore(this, this._nameDimIdx, rawIndex);
    }

    if (name == null) {
      name = '';
    }

    return name;
  };

  SeriesData.prototype._getCategory = function (dimIdx, idx) {
    var ordinal = this._store.get(dimIdx, idx);

    var ordinalMeta = this._store.getOrdinalMeta(dimIdx);

    if (ordinalMeta) {
      return ordinalMeta.categories[ordinal];
    }

    return ordinal;
  };
  /**
   * @return Never null/undefined. `number` will be converted to string. Because:
   * In all cases having encountered at present, id is used in making diff comparison, which
   * are usually based on hash map. We can keep the rule that the internal id are always string
   * (treat `2` is the same as `'2'`) to make the related logic simple.
   */


  SeriesData.prototype.getId = function (idx) {
    return getId(this, this.getRawIndex(idx));
  };

  SeriesData.prototype.count = function () {
    return this._store.count();
  };
  /**
   * Get value. Return NaN if idx is out of range.
   *
   * @notice Should better to use `data.getStore().get(dimIndex, dataIdx)` instead.
   */


  SeriesData.prototype.get = function (dim, idx) {
    var store = this._store;
    var dimInfo = this._dimInfos[dim];

    if (dimInfo) {
      return store.get(dimInfo.storeDimIndex, idx);
    }
  };
  /**
   * @notice Should better to use `data.getStore().getByRawIndex(dimIndex, dataIdx)` instead.
   */


  SeriesData.prototype.getByRawIndex = function (dim, rawIdx) {
    var store = this._store;
    var dimInfo = this._dimInfos[dim];

    if (dimInfo) {
      return store.getByRawIndex(dimInfo.storeDimIndex, rawIdx);
    }
  };

  SeriesData.prototype.getIndices = function () {
    return this._store.getIndices();
  };

  SeriesData.prototype.getDataExtent = function (dim) {
    return this._store.getDataExtent(this._getStoreDimIndex(dim));
  };

  SeriesData.prototype.getSum = function (dim) {
    return this._store.getSum(this._getStoreDimIndex(dim));
  };

  SeriesData.prototype.getMedian = function (dim) {
    return this._store.getMedian(this._getStoreDimIndex(dim));
  };

  SeriesData.prototype.getValues = function (dimensions, idx) {
    var _this = this;

    var store = this._store;
    return isArray(dimensions) ? store.getValues(map(dimensions, function (dim) {
      return _this._getStoreDimIndex(dim);
    }), idx) : store.getValues(dimensions);
  };
  /**
   * If value is NaN. Including '-'
   * Only check the coord dimensions.
   */


  SeriesData.prototype.hasValue = function (idx) {
    var dataDimIndicesOnCoord = this._dimSummary.dataDimIndicesOnCoord;

    for (var i = 0, len = dataDimIndicesOnCoord.length; i < len; i++) {
      // Ordinal type originally can be string or number.
      // But when an ordinal type is used on coord, it can
      // not be string but only number. So we can also use isNaN.
      if (isNaN(this._store.get(dataDimIndicesOnCoord[i], idx))) {
        return false;
      }
    }

    return true;
  };
  /**
   * Retrieve the index with given name
   */


  SeriesData.prototype.indexOfName = function (name) {
    for (var i = 0, len = this._store.count(); i < len; i++) {
      if (this.getName(i) === name) {
        return i;
      }
    }

    return -1;
  };

  SeriesData.prototype.getRawIndex = function (idx) {
    return this._store.getRawIndex(idx);
  };

  SeriesData.prototype.indexOfRawIndex = function (rawIndex) {
    return this._store.indexOfRawIndex(rawIndex);
  };
  /**
   * Only support the dimension which inverted index created.
   * Do not support other cases until required.
   * @param dim concrete dim
   * @param value ordinal index
   * @return rawIndex
   */


  SeriesData.prototype.rawIndexOf = function (dim, value) {
    var invertedIndices = dim && this._invertedIndicesMap[dim];

    var rawIndex = invertedIndices[value];

    if (rawIndex == null || isNaN(rawIndex)) {
      return INDEX_NOT_FOUND;
    }

    return rawIndex;
  };
  /**
   * Retrieve the index of nearest value
   * @param dim
   * @param value
   * @param [maxDistance=Infinity]
   * @return If and only if multiple indices has
   *         the same value, they are put to the result.
   */


  SeriesData.prototype.indicesOfNearest = function (dim, value, maxDistance) {
    return this._store.indicesOfNearest(this._getStoreDimIndex(dim), value, maxDistance);
  };

  SeriesData.prototype.each = function (dims, cb, ctx) {

    if (isFunction(dims)) {
      ctx = cb;
      cb = dims;
      dims = [];
    } // ctxCompat just for compat echarts3


    var fCtx = ctx || this;
    var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this);

    this._store.each(dimIndices, fCtx ? bind$1(cb, fCtx) : cb);
  };

  SeriesData.prototype.filterSelf = function (dims, cb, ctx) {

    if (isFunction(dims)) {
      ctx = cb;
      cb = dims;
      dims = [];
    } // ctxCompat just for compat echarts3


    var fCtx = ctx || this;
    var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this);
    this._store = this._store.filter(dimIndices, fCtx ? bind$1(cb, fCtx) : cb);
    return this;
  };
  /**
   * Select data in range. (For optimization of filter)
   * (Manually inline code, support 5 million data filtering in data zoom.)
   */


  SeriesData.prototype.selectRange = function (range) {

    var _this = this;

    var innerRange = {};
    var dims = keys(range);
    each$4(dims, function (dim) {
      var dimIdx = _this._getStoreDimIndex(dim);

      innerRange[dimIdx] = range[dim];
    });
    this._store = this._store.selectRange(innerRange);
    return this;
  };
  /* eslint-enable max-len */


  SeriesData.prototype.mapArray = function (dims, cb, ctx) {

    if (isFunction(dims)) {
      ctx = cb;
      cb = dims;
      dims = [];
    } // ctxCompat just for compat echarts3


    ctx = ctx || this;
    var result = [];
    this.each(dims, function () {
      result.push(cb && cb.apply(this, arguments));
    }, ctx);
    return result;
  };

  SeriesData.prototype.map = function (dims, cb, ctx, ctxCompat) {

    var fCtx = ctx || ctxCompat || this;
    var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this);
    var list = cloneListForMapAndSample(this);
    list._store = this._store.map(dimIndices, fCtx ? bind$1(cb, fCtx) : cb);
    return list;
  };

  SeriesData.prototype.modify = function (dims, cb, ctx, ctxCompat) {


    var fCtx = ctx || ctxCompat || this;

    var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this); // If do shallow clone here, if there are too many stacked series,
    // it still cost lots of memory, because `_store.dimensions` are not shared.
    // We should consider there probably be shallow clone happen in each series
    // in consequent filter/map.

    this._store.modify(dimIndices, fCtx ? bind$1(cb, fCtx) : cb);
  };
  /**
   * Large data down sampling on given dimension
   * @param sampleIndex Sample index for name and id
   */


  SeriesData.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) {
    var list = cloneListForMapAndSample(this);
    list._store = this._store.downSample(this._getStoreDimIndex(dimension), rate, sampleValue, sampleIndex);
    return list;
  };
  /**
   * Large data down sampling using largest-triangle-three-buckets
   * @param {string} valueDimension
   * @param {number} targetCount
   */


  SeriesData.prototype.lttbDownSample = function (valueDimension, rate) {
    var list = cloneListForMapAndSample(this);
    list._store = this._store.lttbDownSample(this._getStoreDimIndex(valueDimension), rate);
    return list;
  };

  SeriesData.prototype.getRawDataItem = function (idx) {
    return this._store.getRawDataItem(idx);
  };
  /**
   * Get model of one data item.
   */
  // TODO: Type of data item


  SeriesData.prototype.getItemModel = function (idx) {
    var hostModel = this.hostModel;
    var dataItem = this.getRawDataItem(idx);
    return new Model$1(dataItem, hostModel, hostModel && hostModel.ecModel);
  };
  /**
   * Create a data differ
   */


  SeriesData.prototype.diff = function (otherList) {
    var thisList = this;
    return new DataDiffer$1(otherList ? otherList.getStore().getIndices() : [], this.getStore().getIndices(), function (idx) {
      return getId(otherList, idx);
    }, function (idx) {
      return getId(thisList, idx);
    });
  };
  /**
   * Get visual property.
   */


  SeriesData.prototype.getVisual = function (key) {
    var visual = this._visual;
    return visual && visual[key];
  };

  SeriesData.prototype.setVisual = function (kvObj, val) {
    this._visual = this._visual || {};

    if (isObject(kvObj)) {
      extend(this._visual, kvObj);
    } else {
      this._visual[kvObj] = val;
    }
  };
  /**
   * Get visual property of single data item
   */
  // eslint-disable-next-line


  SeriesData.prototype.getItemVisual = function (idx, key) {
    var itemVisual = this._itemVisuals[idx];
    var val = itemVisual && itemVisual[key];

    if (val == null) {
      // Use global visual property
      return this.getVisual(key);
    }

    return val;
  };
  /**
   * If exists visual property of single data item
   */


  SeriesData.prototype.hasItemVisual = function () {
    return this._itemVisuals.length > 0;
  };
  /**
   * Make sure itemVisual property is unique
   */
  // TODO: use key to save visual to reduce memory.


  SeriesData.prototype.ensureUniqueItemVisual = function (idx, key) {
    var itemVisuals = this._itemVisuals;
    var itemVisual = itemVisuals[idx];

    if (!itemVisual) {
      itemVisual = itemVisuals[idx] = {};
    }

    var val = itemVisual[key];

    if (val == null) {
      val = this.getVisual(key); // TODO Performance?

      if (isArray(val)) {
        val = val.slice();
      } else if (isObject(val)) {
        val = extend({}, val);
      }

      itemVisual[key] = val;
    }

    return val;
  }; // eslint-disable-next-line


  SeriesData.prototype.setItemVisual = function (idx, key, value) {
    var itemVisual = this._itemVisuals[idx] || {};
    this._itemVisuals[idx] = itemVisual;

    if (isObject(key)) {
      extend(itemVisual, key);
    } else {
      itemVisual[key] = value;
    }
  };
  /**
   * Clear itemVisuals and list visual.
   */


  SeriesData.prototype.clearAllVisual = function () {
    this._visual = {};
    this._itemVisuals = [];
  };

  SeriesData.prototype.setLayout = function (key, val) {
    isObject(key) ? extend(this._layout, key) : this._layout[key] = val;
  };
  /**
   * Get layout property.
   */


  SeriesData.prototype.getLayout = function (key) {
    return this._layout[key];
  };
  /**
   * Get layout of single data item
   */


  SeriesData.prototype.getItemLayout = function (idx) {
    return this._itemLayouts[idx];
  };
  /**
   * Set layout of single data item
   */


  SeriesData.prototype.setItemLayout = function (idx, layout, merge) {
    this._itemLayouts[idx] = merge ? extend(this._itemLayouts[idx] || {}, layout) : layout;
  };
  /**
   * Clear all layout of single data item
   */


  SeriesData.prototype.clearItemLayouts = function () {
    this._itemLayouts.length = 0;
  };
  /**
   * Set graphic element relative to data. It can be set as null
   */


  SeriesData.prototype.setItemGraphicEl = function (idx, el) {
    var seriesIndex = this.hostModel && this.hostModel.seriesIndex;
    setCommonECData(seriesIndex, this.dataType, idx, el);
    this._graphicEls[idx] = el;
  };

  SeriesData.prototype.getItemGraphicEl = function (idx) {
    return this._graphicEls[idx];
  };

  SeriesData.prototype.eachItemGraphicEl = function (cb, context) {
    each$4(this._graphicEls, function (el, idx) {
      if (el) {
        cb && cb.call(context, el, idx);
      }
    });
  };
  /**
   * Shallow clone a new list except visual and layout properties, and graph elements.
   * New list only change the indices.
   */


  SeriesData.prototype.cloneShallow = function (list) {
    if (!list) {
      list = new SeriesData(this._schema ? this._schema : map(this.dimensions, this._getDimInfo, this), this.hostModel);
    }

    transferProperties(list, this);
    list._store = this._store;
    return list;
  };
  /**
   * Wrap some method to add more feature
   */


  SeriesData.prototype.wrapMethod = function (methodName, injectFunction) {
    var originalMethod = this[methodName];

    if (!isFunction(originalMethod)) {
      return;
    }

    this.__wrappedMethods = this.__wrappedMethods || [];

    this.__wrappedMethods.push(methodName);

    this[methodName] = function () {
      var res = originalMethod.apply(this, arguments);
      return injectFunction.apply(this, [res].concat(slice(arguments)));
    };
  }; // ----------------------------------------------------------
  // A work around for internal method visiting private member.
  // ----------------------------------------------------------


  SeriesData.internalField = function () {
    prepareInvertedIndex = function (data) {
      var invertedIndicesMap = data._invertedIndicesMap;
      each$4(invertedIndicesMap, function (invertedIndices, dim) {
        var dimInfo = data._dimInfos[dim]; // Currently, only dimensions that has ordinalMeta can create inverted indices.

        var ordinalMeta = dimInfo.ordinalMeta;
        var store = data._store;

        if (ordinalMeta) {
          invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); // The default value of TypedArray is 0. To avoid miss
          // mapping to 0, we should set it as INDEX_NOT_FOUND.

          for (var i = 0; i < invertedIndices.length; i++) {
            invertedIndices[i] = INDEX_NOT_FOUND;
          }

          for (var i = 0; i < store.count(); i++) {
            // Only support the case that all values are distinct.
            invertedIndices[store.get(dimInfo.storeDimIndex, i)] = i;
          }
        }
      });
    };

    getIdNameFromStore = function (data, dimIdx, idx) {
      return convertOptionIdName(data._getCategory(dimIdx, idx), null);
    };
    /**
     * @see the comment of `List['getId']`.
     */


    getId = function (data, rawIndex) {
      var id = data._idList[rawIndex];

      if (id == null && data._idDimIdx != null) {
        id = getIdNameFromStore(data, data._idDimIdx, rawIndex);
      }

      if (id == null) {
        id = ID_PREFIX + rawIndex;
      }

      return id;
    };

    normalizeDimensions = function (dimensions) {
      if (!isArray(dimensions)) {
        dimensions = dimensions != null ? [dimensions] : [];
      }

      return dimensions;
    };
    /**
     * Data in excludeDimensions is copied, otherwise transferred.
     */


    cloneListForMapAndSample = function (original) {
      var list = new SeriesData(original._schema ? original._schema : map(original.dimensions, original._getDimInfo, original), original.hostModel); // FIXME If needs stackedOn, value may already been stacked

      transferProperties(list, original);
      return list;
    };

    transferProperties = function (target, source) {
      each$4(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) {
        if (source.hasOwnProperty(propName)) {
          target[propName] = source[propName];
        }
      });
      target.__wrappedMethods = source.__wrappedMethods;
      each$4(CLONE_PROPERTIES, function (propName) {
        target[propName] = clone$2(source[propName]);
      });
      target._calculationInfo = extend({}, source._calculationInfo);
    };

    makeIdFromName = function (data, idx) {
      var nameList = data._nameList;
      var idList = data._idList;
      var nameDimIdx = data._nameDimIdx;
      var idDimIdx = data._idDimIdx;
      var name = nameList[idx];
      var id = idList[idx];

      if (name == null && nameDimIdx != null) {
        nameList[idx] = name = getIdNameFromStore(data, nameDimIdx, idx);
      }

      if (id == null && idDimIdx != null) {
        idList[idx] = id = getIdNameFromStore(data, idDimIdx, idx);
      }

      if (id == null && name != null) {
        var nameRepeatCount = data._nameRepeatCount;
        var nmCnt = nameRepeatCount[name] = (nameRepeatCount[name] || 0) + 1;
        id = name;

        if (nmCnt > 1) {
          id += '__ec__' + nmCnt;
        }

        idList[idx] = id;
      }
    };
  }();

  return SeriesData;
}();

const SeriesData$1 = SeriesData;
/* Injected with object hook! */

/**
 * This method builds the relationship between:
 * + "what the coord sys or series requires (see `coordDimensions`)",
 * + "what the user defines (in `encode` and `dimensions`, see `opt.dimensionsDefine` and `opt.encodeDefine`)"
 * + "what the data source provids (see `source`)".
 *
 * Some guess strategy will be adapted if user does not define something.
 * If no 'value' dimension specified, the first no-named dimension will be
 * named as 'value'.
 *
 * @return The results are always sorted by `storeDimIndex` asc.
 */

function prepareSeriesDataSchema( // TODO: TYPE completeDimensions type
source, opt) {
  if (!isSourceInstance(source)) {
    source = createSourceFromSeriesDataOption(source);
  }

  opt = opt || {};
  var sysDims = opt.coordDimensions || [];
  var dimsDef = opt.dimensionsDefine || source.dimensionsDefine || [];
  var coordDimNameMap = createHashMap();
  var resultList = [];
  var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimensionsCount); // Try to ignore unused dimensions if sharing a high dimension datastore
  // 30 is an experience value.

  var omitUnusedDimensions = opt.canOmitUnusedDimensions && shouldOmitUnusedDimensions(dimCount);
  var isUsingSourceDimensionsDef = dimsDef === source.dimensionsDefine;
  var dataDimNameMap = isUsingSourceDimensionsDef ? ensureSourceDimNameMap(source) : createDimNameMap(dimsDef);
  var encodeDef = opt.encodeDefine;

  if (!encodeDef && opt.encodeDefaulter) {
    encodeDef = opt.encodeDefaulter(source, dimCount);
  }

  var encodeDefMap = createHashMap(encodeDef);
  var indicesMap = new CtorInt32Array$1(dimCount);

  for (var i = 0; i < indicesMap.length; i++) {
    indicesMap[i] = -1;
  }

  function getResultItem(dimIdx) {
    var idx = indicesMap[dimIdx];

    if (idx < 0) {
      var dimDefItemRaw = dimsDef[dimIdx];
      var dimDefItem = isObject$2(dimDefItemRaw) ? dimDefItemRaw : {
        name: dimDefItemRaw
      };
      var resultItem = new SeriesDimensionDefine$1();
      var userDimName = dimDefItem.name;

      if (userDimName != null && dataDimNameMap.get(userDimName) != null) {
        // Only if `series.dimensions` is defined in option
        // displayName, will be set, and dimension will be displayed vertically in
        // tooltip by default.
        resultItem.name = resultItem.displayName = userDimName;
      }

      dimDefItem.type != null && (resultItem.type = dimDefItem.type);
      dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName);
      var newIdx = resultList.length;
      indicesMap[dimIdx] = newIdx;
      resultItem.storeDimIndex = dimIdx;
      resultList.push(resultItem);
      return resultItem;
    }

    return resultList[idx];
  }

  if (!omitUnusedDimensions) {
    for (var i = 0; i < dimCount; i++) {
      getResultItem(i);
    }
  } // Set `coordDim` and `coordDimIndex` by `encodeDefMap` and normalize `encodeDefMap`.


  encodeDefMap.each(function (dataDimsRaw, coordDim) {
    var dataDims = normalizeToArray(dataDimsRaw).slice(); // Note: It is allowed that `dataDims.length` is `0`, e.g., options is
    // `{encode: {x: -1, y: 1}}`. Should not filter anything in
    // this case.

    if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) {
      encodeDefMap.set(coordDim, false);
      return;
    }

    var validDataDims = encodeDefMap.set(coordDim, []);
    each$4(dataDims, function (resultDimIdxOrName, idx) {
      // The input resultDimIdx can be dim name or index.
      var resultDimIdx = isString(resultDimIdxOrName) ? dataDimNameMap.get(resultDimIdxOrName) : resultDimIdxOrName;

      if (resultDimIdx != null && resultDimIdx < dimCount) {
        validDataDims[idx] = resultDimIdx;
        applyDim(getResultItem(resultDimIdx), coordDim, idx);
      }
    });
  }); // Apply templates and default order from `sysDims`.

  var availDimIdx = 0;
  each$4(sysDims, function (sysDimItemRaw) {
    var coordDim;
    var sysDimItemDimsDef;
    var sysDimItemOtherDims;
    var sysDimItem;

    if (isString(sysDimItemRaw)) {
      coordDim = sysDimItemRaw;
      sysDimItem = {};
    } else {
      sysDimItem = sysDimItemRaw;
      coordDim = sysDimItem.name;
      var ordinalMeta = sysDimItem.ordinalMeta;
      sysDimItem.ordinalMeta = null;
      sysDimItem = extend({}, sysDimItem);
      sysDimItem.ordinalMeta = ordinalMeta; // `coordDimIndex` should not be set directly.

      sysDimItemDimsDef = sysDimItem.dimsDef;
      sysDimItemOtherDims = sysDimItem.otherDims;
      sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null;
    }

    var dataDims = encodeDefMap.get(coordDim); // negative resultDimIdx means no need to mapping.

    if (dataDims === false) {
      return;
    }

    dataDims = normalizeToArray(dataDims); // dimensions provides default dim sequences.

    if (!dataDims.length) {
      for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) {
        while (availDimIdx < dimCount && getResultItem(availDimIdx).coordDim != null) {
          availDimIdx++;
        }

        availDimIdx < dimCount && dataDims.push(availDimIdx++);
      }
    } // Apply templates.


    each$4(dataDims, function (resultDimIdx, coordDimIndex) {
      var resultItem = getResultItem(resultDimIdx); // Coordinate system has a higher priority on dim type than source.

      if (isUsingSourceDimensionsDef && sysDimItem.type != null) {
        resultItem.type = sysDimItem.type;
      }

      applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex);

      if (resultItem.name == null && sysDimItemDimsDef) {
        var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex];
        !isObject$2(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = {
          name: sysDimItemDimsDefItem
        });
        resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name;
        resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip;
      } // FIXME refactor, currently only used in case: {otherDims: {tooltip: false}}


      sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims);
    });
  });

  function applyDim(resultItem, coordDim, coordDimIndex) {
    if (VISUAL_DIMENSIONS.get(coordDim) != null) {
      resultItem.otherDims[coordDim] = coordDimIndex;
    } else {
      resultItem.coordDim = coordDim;
      resultItem.coordDimIndex = coordDimIndex;
      coordDimNameMap.set(coordDim, true);
    }
  } // Make sure the first extra dim is 'value'.


  var generateCoord = opt.generateCoord;
  var generateCoordCount = opt.generateCoordCount;
  var fromZero = generateCoordCount != null;
  generateCoordCount = generateCoord ? generateCoordCount || 1 : 0;
  var extra = generateCoord || 'value';

  function ifNoNameFillWithCoordName(resultItem) {
    if (resultItem.name == null) {
      // Duplication will be removed in the next step.
      resultItem.name = resultItem.coordDim;
    }
  } // Set dim `name` and other `coordDim` and other props.


  if (!omitUnusedDimensions) {
    for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
      var resultItem = getResultItem(resultDimIdx);
      var coordDim = resultItem.coordDim;

      if (coordDim == null) {
        // TODO no need to generate coordDim for isExtraCoord?
        resultItem.coordDim = genCoordDimName(extra, coordDimNameMap, fromZero);
        resultItem.coordDimIndex = 0; // Series specified generateCoord is using out.

        if (!generateCoord || generateCoordCount <= 0) {
          resultItem.isExtraCoord = true;
        }

        generateCoordCount--;
      }

      ifNoNameFillWithCoordName(resultItem);

      if (resultItem.type == null && (guessOrdinal(source, resultDimIdx) === BE_ORDINAL.Must // Consider the case:
      // {
      //    dataset: {source: [
      //        ['2001', 123],
      //        ['2002', 456],
      //        ...
      //        ['The others', 987],
      //    ]},
      //    series: {type: 'pie'}
      // }
      // The first column should better be treated as a "ordinal" although it
      // might not be detected as an "ordinal" by `guessOrdinal`.
      || resultItem.isExtraCoord && (resultItem.otherDims.itemName != null || resultItem.otherDims.seriesName != null))) {
        resultItem.type = 'ordinal';
      }
    }
  } else {
    each$4(resultList, function (resultItem) {
      // PENDING: guessOrdinal or let user specify type: 'ordinal' manually?
      ifNoNameFillWithCoordName(resultItem);
    }); // Sort dimensions: there are some rule that use the last dim as label,
    // and for some latter travel process easier.

    resultList.sort(function (item0, item1) {
      return item0.storeDimIndex - item1.storeDimIndex;
    });
  }

  removeDuplication(resultList);
  return new SeriesDataSchema({
    source: source,
    dimensions: resultList,
    fullDimensionCount: dimCount,
    dimensionOmitted: omitUnusedDimensions
  });
}

function removeDuplication(result) {
  var duplicationMap = createHashMap();

  for (var i = 0; i < result.length; i++) {
    var dim = result[i];
    var dimOriginalName = dim.name;
    var count = duplicationMap.get(dimOriginalName) || 0;

    if (count > 0) {
      // Starts from 0.
      dim.name = dimOriginalName + (count - 1);
    }

    count++;
    duplicationMap.set(dimOriginalName, count);
  }
} // ??? TODO
// Originally detect dimCount by data[0]. Should we
// optimize it to only by sysDims and dimensions and encode.
// So only necessary dims will be initialized.
// But
// (1) custom series should be considered. where other dims
// may be visited.
// (2) sometimes user need to calculate bubble size or use visualMap
// on other dimensions besides coordSys needed.
// So, dims that is not used by system, should be shared in data store?


function getDimCount(source, sysDims, dimsDef, optDimCount) {
  // Note that the result dimCount should not small than columns count
  // of data, otherwise `dataDimNameMap` checking will be incorrect.
  var dimCount = Math.max(source.dimensionsDetectedCount || 1, sysDims.length, dimsDef.length, optDimCount || 0);
  each$4(sysDims, function (sysDimItem) {
    var sysDimItemDimsDef;

    if (isObject$2(sysDimItem) && (sysDimItemDimsDef = sysDimItem.dimsDef)) {
      dimCount = Math.max(dimCount, sysDimItemDimsDef.length);
    }
  });
  return dimCount;
}

function genCoordDimName(name, map, fromZero) {
  if (fromZero || map.hasKey(name)) {
    var i = 0;

    while (map.hasKey(name + i)) {
      i++;
    }

    name += i;
  }

  map.set(name, true);
  return name;
}
/* Injected with object hook! */

/**
 * @class
 * For example:
 * {
 *     coordSysName: 'cartesian2d',
 *     coordSysDims: ['x', 'y', ...],
 *     axisMap: HashMap({
 *         x: xAxisModel,
 *         y: yAxisModel
 *     }),
 *     categoryAxisMap: HashMap({
 *         x: xAxisModel,
 *         y: undefined
 *     }),
 *     // The index of the first category axis in `coordSysDims`.
 *     // `null/undefined` means no category axis exists.
 *     firstCategoryDimIndex: 1,
 *     // To replace user specified encode.
 * }
 */

var CoordSysInfo =
/** @class */
function () {
  function CoordSysInfo(coordSysName) {
    this.coordSysDims = [];
    this.axisMap = createHashMap();
    this.categoryAxisMap = createHashMap();
    this.coordSysName = coordSysName;
  }

  return CoordSysInfo;
}();

function getCoordSysInfoBySeries(seriesModel) {
  var coordSysName = seriesModel.get('coordinateSystem');
  var result = new CoordSysInfo(coordSysName);
  var fetch = fetchers[coordSysName];

  if (fetch) {
    fetch(seriesModel, result, result.axisMap, result.categoryAxisMap);
    return result;
  }
}
var fetchers = {
  cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) {
    var xAxisModel = seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0];
    var yAxisModel = seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0];

    result.coordSysDims = ['x', 'y'];
    axisMap.set('x', xAxisModel);
    axisMap.set('y', yAxisModel);

    if (isCategory(xAxisModel)) {
      categoryAxisMap.set('x', xAxisModel);
      result.firstCategoryDimIndex = 0;
    }

    if (isCategory(yAxisModel)) {
      categoryAxisMap.set('y', yAxisModel);
      result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1);
    }
  },
  singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) {
    var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0];

    result.coordSysDims = ['single'];
    axisMap.set('single', singleAxisModel);

    if (isCategory(singleAxisModel)) {
      categoryAxisMap.set('single', singleAxisModel);
      result.firstCategoryDimIndex = 0;
    }
  },
  polar: function (seriesModel, result, axisMap, categoryAxisMap) {
    var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0];
    var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
    var angleAxisModel = polarModel.findAxisModel('angleAxis');

    result.coordSysDims = ['radius', 'angle'];
    axisMap.set('radius', radiusAxisModel);
    axisMap.set('angle', angleAxisModel);

    if (isCategory(radiusAxisModel)) {
      categoryAxisMap.set('radius', radiusAxisModel);
      result.firstCategoryDimIndex = 0;
    }

    if (isCategory(angleAxisModel)) {
      categoryAxisMap.set('angle', angleAxisModel);
      result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1);
    }
  },
  geo: function (seriesModel, result, axisMap, categoryAxisMap) {
    result.coordSysDims = ['lng', 'lat'];
  },
  parallel: function (seriesModel, result, axisMap, categoryAxisMap) {
    var ecModel = seriesModel.ecModel;
    var parallelModel = ecModel.getComponent('parallel', seriesModel.get('parallelIndex'));
    var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice();
    each$4(parallelModel.parallelAxisIndex, function (axisIndex, index) {
      var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
      var axisDim = coordSysDims[index];
      axisMap.set(axisDim, axisModel);

      if (isCategory(axisModel)) {
        categoryAxisMap.set(axisDim, axisModel);

        if (result.firstCategoryDimIndex == null) {
          result.firstCategoryDimIndex = index;
        }
      }
    });
  }
};

function isCategory(axisModel) {
  return axisModel.get('type') === 'category';
}
/* Injected with object hook! */

/**
 * Note that it is too complicated to support 3d stack by value
 * (have to create two-dimension inverted index), so in 3d case
 * we just support that stacked by index.
 *
 * @param seriesModel
 * @param dimensionsInput The same as the input of <module:echarts/data/SeriesData>.
 *        The input will be modified.
 * @param opt
 * @param opt.stackedCoordDimension Specify a coord dimension if needed.
 * @param opt.byIndex=false
 * @return calculationInfo
 * {
 *     stackedDimension: string
 *     stackedByDimension: string
 *     isStackedByIndex: boolean
 *     stackedOverDimension: string
 *     stackResultDimension: string
 * }
 */

function enableDataStack(seriesModel, dimensionsInput, opt) {
  opt = opt || {};
  var byIndex = opt.byIndex;
  var stackedCoordDimension = opt.stackedCoordDimension;
  var dimensionDefineList;
  var schema;
  var store;

  if (isLegacyDimensionsInput(dimensionsInput)) {
    dimensionDefineList = dimensionsInput;
  } else {
    schema = dimensionsInput.schema;
    dimensionDefineList = schema.dimensions;
    store = dimensionsInput.store;
  } // Compatibal: when `stack` is set as '', do not stack.


  var mayStack = !!(seriesModel && seriesModel.get('stack'));
  var stackedByDimInfo;
  var stackedDimInfo;
  var stackResultDimension;
  var stackedOverDimension;
  each$4(dimensionDefineList, function (dimensionInfo, index) {
    if (isString(dimensionInfo)) {
      dimensionDefineList[index] = dimensionInfo = {
        name: dimensionInfo
      };
    }

    if (mayStack && !dimensionInfo.isExtraCoord) {
      // Find the first ordinal dimension as the stackedByDimInfo.
      if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) {
        stackedByDimInfo = dimensionInfo;
      } // Find the first stackable dimension as the stackedDimInfo.


      if (!stackedDimInfo && dimensionInfo.type !== 'ordinal' && dimensionInfo.type !== 'time' && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim)) {
        stackedDimInfo = dimensionInfo;
      }
    }
  });

  if (stackedDimInfo && !byIndex && !stackedByDimInfo) {
    // Compatible with previous design, value axis (time axis) only stack by index.
    // It may make sense if the user provides elaborately constructed data.
    byIndex = true;
  } // Add stack dimension, they can be both calculated by coordinate system in `unionExtent`.
  // That put stack logic in List is for using conveniently in echarts extensions, but it
  // might not be a good way.


  if (stackedDimInfo) {
    // Use a weird name that not duplicated with other names.
    // Also need to use seriesModel.id as postfix because different
    // series may share same data store. The stack dimension needs to be distinguished.
    stackResultDimension = '__\0ecstackresult_' + seriesModel.id;
    stackedOverDimension = '__\0ecstackedover_' + seriesModel.id; // Create inverted index to fast query index by value.

    if (stackedByDimInfo) {
      stackedByDimInfo.createInvertedIndices = true;
    }

    var stackedDimCoordDim_1 = stackedDimInfo.coordDim;
    var stackedDimType = stackedDimInfo.type;
    var stackedDimCoordIndex_1 = 0;
    each$4(dimensionDefineList, function (dimensionInfo) {
      if (dimensionInfo.coordDim === stackedDimCoordDim_1) {
        stackedDimCoordIndex_1++;
      }
    });
    var stackedOverDimensionDefine = {
      name: stackResultDimension,
      coordDim: stackedDimCoordDim_1,
      coordDimIndex: stackedDimCoordIndex_1,
      type: stackedDimType,
      isExtraCoord: true,
      isCalculationCoord: true,
      storeDimIndex: dimensionDefineList.length
    };
    var stackResultDimensionDefine = {
      name: stackedOverDimension,
      // This dimension contains stack base (generally, 0), so do not set it as
      // `stackedDimCoordDim` to avoid extent calculation, consider log scale.
      coordDim: stackedOverDimension,
      coordDimIndex: stackedDimCoordIndex_1 + 1,
      type: stackedDimType,
      isExtraCoord: true,
      isCalculationCoord: true,
      storeDimIndex: dimensionDefineList.length + 1
    };

    if (schema) {
      if (store) {
        stackedOverDimensionDefine.storeDimIndex = store.ensureCalculationDimension(stackedOverDimension, stackedDimType);
        stackResultDimensionDefine.storeDimIndex = store.ensureCalculationDimension(stackResultDimension, stackedDimType);
      }

      schema.appendCalculationDimension(stackedOverDimensionDefine);
      schema.appendCalculationDimension(stackResultDimensionDefine);
    } else {
      dimensionDefineList.push(stackedOverDimensionDefine);
      dimensionDefineList.push(stackResultDimensionDefine);
    }
  }

  return {
    stackedDimension: stackedDimInfo && stackedDimInfo.name,
    stackedByDimension: stackedByDimInfo && stackedByDimInfo.name,
    isStackedByIndex: byIndex,
    stackedOverDimension: stackedOverDimension,
    stackResultDimension: stackResultDimension
  };
}

function isLegacyDimensionsInput(dimensionsInput) {
  return !isSeriesDataSchema(dimensionsInput.schema);
}

function isDimensionStacked(data, stackedDim) {
  // Each single series only maps to one pair of axis. So we do not need to
  // check stackByDim, whatever stacked by a dimension or stacked by index.
  return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension');
}
function getStackedDimension(data, targetDim) {
  return isDimensionStacked(data, targetDim) ? data.getCalculationInfo('stackResultDimension') : targetDim;
}
/* Injected with object hook! */

function getCoordSysDimDefs(seriesModel, coordSysInfo) {
  var coordSysName = seriesModel.get('coordinateSystem');
  var registeredCoordSys = CoordinateSystem.get(coordSysName);
  var coordSysDimDefs;

  if (coordSysInfo && coordSysInfo.coordSysDims) {
    coordSysDimDefs = map$1(coordSysInfo.coordSysDims, function (dim) {
      var dimInfo = {
        name: dim
      };
      var axisModel = coordSysInfo.axisMap.get(dim);

      if (axisModel) {
        var axisType = axisModel.get('type');
        dimInfo.type = getDimensionTypeByAxis(axisType);
      }

      return dimInfo;
    });
  }

  if (!coordSysDimDefs) {
    // Get dimensions from registered coordinate system
    coordSysDimDefs = registeredCoordSys && (registeredCoordSys.getDimensionsInfo ? registeredCoordSys.getDimensionsInfo() : registeredCoordSys.dimensions.slice()) || ['x', 'y'];
  }

  return coordSysDimDefs;
}

function injectOrdinalMeta(dimInfoList, createInvertedIndices, coordSysInfo) {
  var firstCategoryDimIndex;
  var hasNameEncode;
  coordSysInfo && each$4(dimInfoList, function (dimInfo, dimIndex) {
    var coordDim = dimInfo.coordDim;
    var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim);

    if (categoryAxisModel) {
      if (firstCategoryDimIndex == null) {
        firstCategoryDimIndex = dimIndex;
      }

      dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta();

      if (createInvertedIndices) {
        dimInfo.createInvertedIndices = true;
      }
    }

    if (dimInfo.otherDims.itemName != null) {
      hasNameEncode = true;
    }
  });

  if (!hasNameEncode && firstCategoryDimIndex != null) {
    dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0;
  }

  return firstCategoryDimIndex;
}
/**
 * Caution: there are side effects to `sourceManager` in this method.
 * Should better only be called in `Series['getInitialData']`.
 */


function createSeriesData(sourceRaw, seriesModel, opt) {
  opt = opt || {};
  var sourceManager = seriesModel.getSourceManager();
  var source;
  var isOriginalSource = false;

  if (sourceRaw) {
    isOriginalSource = true;
    source = createSourceFromSeriesDataOption(sourceRaw);
  } else {
    source = sourceManager.getSource(); // Is series.data. not dataset.

    isOriginalSource = source.sourceFormat === SOURCE_FORMAT_ORIGINAL;
  }

  var coordSysInfo = getCoordSysInfoBySeries(seriesModel);
  var coordSysDimDefs = getCoordSysDimDefs(seriesModel, coordSysInfo);
  var useEncodeDefaulter = opt.useEncodeDefaulter;
  var encodeDefaulter = isFunction(useEncodeDefaulter) ? useEncodeDefaulter : useEncodeDefaulter ? curry$1(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel) : null;
  var createDimensionOptions = {
    coordDimensions: coordSysDimDefs,
    generateCoord: opt.generateCoord,
    encodeDefine: seriesModel.getEncode(),
    encodeDefaulter: encodeDefaulter,
    canOmitUnusedDimensions: !isOriginalSource
  };
  var schema = prepareSeriesDataSchema(source, createDimensionOptions);
  var firstCategoryDimIndex = injectOrdinalMeta(schema.dimensions, opt.createInvertedIndices, coordSysInfo);
  var store = !isOriginalSource ? sourceManager.getSharedDataStore(schema) : null;
  var stackCalculationInfo = enableDataStack(seriesModel, {
    schema: schema,
    store: store
  });
  var data = new SeriesData$1(schema, seriesModel);
  data.setCalculationInfo(stackCalculationInfo);
  var dimValueGetter = firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source) ? function (itemOpt, dimName, dataIndex, dimIndex) {
    // Use dataIndex as ordinal value in categoryAxis
    return dimIndex === firstCategoryDimIndex ? dataIndex : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex);
  } : null;
  data.hasItemOption = false;
  data.initData( // Try to reuse the data store in sourceManager if using dataset.
  isOriginalSource ? source : store, null, dimValueGetter);
  return data;
}

function isNeedCompleteOrdinalData(source) {
  if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) {
    var sampleItem = firstDataNotNull(source.data || []);
    return !isArray(getDataItemValue(sampleItem));
  }
}

function firstDataNotNull(arr) {
  var i = 0;

  while (i < arr.length && arr[i] == null) {
    i++;
  }

  return arr[i];
}
/* Injected with object hook! */

var Scale =
/** @class */
function () {
  function Scale(setting) {
    this._setting = setting || {};
    this._extent = [Infinity, -Infinity];
  }

  Scale.prototype.getSetting = function (name) {
    return this._setting[name];
  };
  /**
   * Set extent from data
   */


  Scale.prototype.unionExtent = function (other) {
    var extent = this._extent;
    other[0] < extent[0] && (extent[0] = other[0]);
    other[1] > extent[1] && (extent[1] = other[1]); // not setExtent because in log axis it may transformed to power
    // this.setExtent(extent[0], extent[1]);
  };
  /**
   * Set extent from data
   */


  Scale.prototype.unionExtentFromData = function (data, dim) {
    this.unionExtent(data.getApproximateExtent(dim));
  };
  /**
   * Get extent
   *
   * Extent is always in increase order.
   */


  Scale.prototype.getExtent = function () {
    return this._extent.slice();
  };
  /**
   * Set extent
   */


  Scale.prototype.setExtent = function (start, end) {
    var thisExtent = this._extent;

    if (!isNaN(start)) {
      thisExtent[0] = start;
    }

    if (!isNaN(end)) {
      thisExtent[1] = end;
    }
  };
  /**
   * If value is in extent range
   */


  Scale.prototype.isInExtentRange = function (value) {
    return this._extent[0] <= value && this._extent[1] >= value;
  };
  /**
   * When axis extent depends on data and no data exists,
   * axis ticks should not be drawn, which is named 'blank'.
   */


  Scale.prototype.isBlank = function () {
    return this._isBlank;
  };
  /**
   * When axis extent depends on data and no data exists,
   * axis ticks should not be drawn, which is named 'blank'.
   */


  Scale.prototype.setBlank = function (isBlank) {
    this._isBlank = isBlank;
  };

  return Scale;
}();

enableClassManagement(Scale);
const Scale$1 = Scale;
/* Injected with object hook! */

var uidBase = 0;

var OrdinalMeta =
/** @class */
function () {
  function OrdinalMeta(opt) {
    this.categories = opt.categories || [];
    this._needCollect = opt.needCollect;
    this._deduplication = opt.deduplication;
    this.uid = ++uidBase;
  }

  OrdinalMeta.createByAxisModel = function (axisModel) {
    var option = axisModel.option;
    var data = option.data;
    var categories = data && map$1(data, getName);
    return new OrdinalMeta({
      categories: categories,
      needCollect: !categories,
      // deduplication is default in axis.
      deduplication: option.dedplication !== false
    });
  };

  OrdinalMeta.prototype.getOrdinal = function (category) {
    // @ts-ignore
    return this._getOrCreateMap().get(category);
  };
  /**
   * @return The ordinal. If not found, return NaN.
   */


  OrdinalMeta.prototype.parseAndCollect = function (category) {
    var index;
    var needCollect = this._needCollect; // The value of category dim can be the index of the given category set.
    // This feature is only supported when !needCollect, because we should
    // consider a common case: a value is 2017, which is a number but is
    // expected to be tread as a category. This case usually happen in dataset,
    // where it happent to be no need of the index feature.

    if (!isString(category) && !needCollect) {
      return category;
    } // Optimize for the scenario:
    // category is ['2012-01-01', '2012-01-02', ...], where the input
    // data has been ensured not duplicate and is large data.
    // Notice, if a dataset dimension provide categroies, usually echarts
    // should remove duplication except user tell echarts dont do that
    // (set axis.deduplication = false), because echarts do not know whether
    // the values in the category dimension has duplication (consider the
    // parallel-aqi example)


    if (needCollect && !this._deduplication) {
      index = this.categories.length;
      this.categories[index] = category;
      return index;
    }

    var map = this._getOrCreateMap(); // @ts-ignore


    index = map.get(category);

    if (index == null) {
      if (needCollect) {
        index = this.categories.length;
        this.categories[index] = category; // @ts-ignore

        map.set(category, index);
      } else {
        index = NaN;
      }
    }

    return index;
  }; // Consider big data, do not create map until needed.


  OrdinalMeta.prototype._getOrCreateMap = function () {
    return this._map || (this._map = createHashMap(this.categories));
  };

  return OrdinalMeta;
}();

function getName(obj) {
  if (isObject$2(obj) && obj.value != null) {
    return obj.value;
  } else {
    return obj + '';
  }
}

const OrdinalMeta$1 = OrdinalMeta;
/* Injected with object hook! */

function isIntervalOrLogScale(scale) {
  return scale.type === 'interval' || scale.type === 'log';
}
/**
 * @param extent Both extent[0] and extent[1] should be valid number.
 *               Should be extent[0] < extent[1].
 * @param splitNumber splitNumber should be >= 1.
 */

function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) {
  var result = {};
  var span = extent[1] - extent[0];
  var interval = result.interval = nice(span / splitNumber, true);

  if (minInterval != null && interval < minInterval) {
    interval = result.interval = minInterval;
  }

  if (maxInterval != null && interval > maxInterval) {
    interval = result.interval = maxInterval;
  } // Tow more digital for tick.


  var precision = result.intervalPrecision = getIntervalPrecision(interval); // Niced extent inside original extent

  var niceTickExtent = result.niceTickExtent = [round$1(Math.ceil(extent[0] / interval) * interval, precision), round$1(Math.floor(extent[1] / interval) * interval, precision)];
  fixExtent(niceTickExtent, extent);
  return result;
}
function increaseInterval(interval) {
  var exp10 = Math.pow(10, quantityExponent(interval)); // Increase interval

  var f = interval / exp10;

  if (!f) {
    f = 1;
  } else if (f === 2) {
    f = 3;
  } else if (f === 3) {
    f = 5;
  } else {
    // f is 1 or 5
    f *= 2;
  }

  return round$1(f * exp10);
}
/**
 * @return interval precision
 */

function getIntervalPrecision(interval) {
  // Tow more digital for tick.
  return getPrecision(interval) + 2;
}

function clamp(niceTickExtent, idx, extent) {
  niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]);
} // In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent.


function fixExtent(niceTickExtent, extent) {
  !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]);
  !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]);
  clamp(niceTickExtent, 0, extent);
  clamp(niceTickExtent, 1, extent);

  if (niceTickExtent[0] > niceTickExtent[1]) {
    niceTickExtent[0] = niceTickExtent[1];
  }
}
function contain(val, extent) {
  return val >= extent[0] && val <= extent[1];
}
function normalize(val, extent) {
  if (extent[1] === extent[0]) {
    return 0.5;
  }

  return (val - extent[0]) / (extent[1] - extent[0]);
}
function scale(val, extent) {
  return val * (extent[1] - extent[0]) + extent[0];
}
/* Injected with object hook! */

var OrdinalScale =
/** @class */
function (_super) {
  __extends(OrdinalScale, _super);

  function OrdinalScale(setting) {
    var _this = _super.call(this, setting) || this;

    _this.type = 'ordinal';

    var ordinalMeta = _this.getSetting('ordinalMeta'); // Caution: Should not use instanceof, consider ec-extensions using
    // import approach to get OrdinalMeta class.


    if (!ordinalMeta) {
      ordinalMeta = new OrdinalMeta$1({});
    }

    if (isArray(ordinalMeta)) {
      ordinalMeta = new OrdinalMeta$1({
        categories: map$1(ordinalMeta, function (item) {
          return isObject$2(item) ? item.value : item;
        })
      });
    }

    _this._ordinalMeta = ordinalMeta;
    _this._extent = _this.getSetting('extent') || [0, ordinalMeta.categories.length - 1];
    return _this;
  }

  OrdinalScale.prototype.parse = function (val) {
    // Caution: Math.round(null) will return `0` rather than `NaN`
    if (val == null) {
      return NaN;
    }

    return isString(val) ? this._ordinalMeta.getOrdinal(val) // val might be float.
    : Math.round(val);
  };

  OrdinalScale.prototype.contain = function (rank) {
    rank = this.parse(rank);
    return contain(rank, this._extent) && this._ordinalMeta.categories[rank] != null;
  };
  /**
   * Normalize given rank or name to linear [0, 1]
   * @param val raw ordinal number.
   * @return normalized value in [0, 1].
   */


  OrdinalScale.prototype.normalize = function (val) {
    val = this._getTickNumber(this.parse(val));
    return normalize(val, this._extent);
  };
  /**
   * @param val normalized value in [0, 1].
   * @return raw ordinal number.
   */


  OrdinalScale.prototype.scale = function (val) {
    val = Math.round(scale(val, this._extent));
    return this.getRawOrdinalNumber(val);
  };

  OrdinalScale.prototype.getTicks = function () {
    var ticks = [];
    var extent = this._extent;
    var rank = extent[0];

    while (rank <= extent[1]) {
      ticks.push({
        value: rank
      });
      rank++;
    }

    return ticks;
  };

  OrdinalScale.prototype.getMinorTicks = function (splitNumber) {
    // Not support.
    return;
  };
  /**
   * @see `Ordinal['_ordinalNumbersByTick']`
   */


  OrdinalScale.prototype.setSortInfo = function (info) {
    if (info == null) {
      this._ordinalNumbersByTick = this._ticksByOrdinalNumber = null;
      return;
    }

    var infoOrdinalNumbers = info.ordinalNumbers;
    var ordinalsByTick = this._ordinalNumbersByTick = [];
    var ticksByOrdinal = this._ticksByOrdinalNumber = []; // Unnecessary support negative tick in `realtimeSort`.

    var tickNum = 0;
    var allCategoryLen = this._ordinalMeta.categories.length;

    for (var len = Math.min(allCategoryLen, infoOrdinalNumbers.length); tickNum < len; ++tickNum) {
      var ordinalNumber = infoOrdinalNumbers[tickNum];
      ordinalsByTick[tickNum] = ordinalNumber;
      ticksByOrdinal[ordinalNumber] = tickNum;
    } // Handle that `series.data` only covers part of the `axis.category.data`.


    var unusedOrdinal = 0;

    for (; tickNum < allCategoryLen; ++tickNum) {
      while (ticksByOrdinal[unusedOrdinal] != null) {
        unusedOrdinal++;
      }
      ordinalsByTick.push(unusedOrdinal);
      ticksByOrdinal[unusedOrdinal] = tickNum;
    }
  };

  OrdinalScale.prototype._getTickNumber = function (ordinal) {
    var ticksByOrdinalNumber = this._ticksByOrdinalNumber; // also support ordinal out of range of `ordinalMeta.categories.length`,
    // where ordinal numbers are used as tick value directly.

    return ticksByOrdinalNumber && ordinal >= 0 && ordinal < ticksByOrdinalNumber.length ? ticksByOrdinalNumber[ordinal] : ordinal;
  };
  /**
   * @usage
   * ```js
   * const ordinalNumber = ordinalScale.getRawOrdinalNumber(tickVal);
   *
   * // case0
   * const rawOrdinalValue = axisModel.getCategories()[ordinalNumber];
   * // case1
   * const rawOrdinalValue = this._ordinalMeta.categories[ordinalNumber];
   * // case2
   * const coord = axis.dataToCoord(ordinalNumber);
   * ```
   *
   * @param {OrdinalNumber} tickNumber index of display
   */


  OrdinalScale.prototype.getRawOrdinalNumber = function (tickNumber) {
    var ordinalNumbersByTick = this._ordinalNumbersByTick; // tickNumber may be out of range, e.g., when axis max is larger than `ordinalMeta.categories.length`.,
    // where ordinal numbers are used as tick value directly.

    return ordinalNumbersByTick && tickNumber >= 0 && tickNumber < ordinalNumbersByTick.length ? ordinalNumbersByTick[tickNumber] : tickNumber;
  };
  /**
   * Get item on tick
   */


  OrdinalScale.prototype.getLabel = function (tick) {
    if (!this.isBlank()) {
      var ordinalNumber = this.getRawOrdinalNumber(tick.value);
      var cateogry = this._ordinalMeta.categories[ordinalNumber]; // Note that if no data, ordinalMeta.categories is an empty array.
      // Return empty if it's not exist.

      return cateogry == null ? '' : cateogry + '';
    }
  };

  OrdinalScale.prototype.count = function () {
    return this._extent[1] - this._extent[0] + 1;
  };

  OrdinalScale.prototype.unionExtentFromData = function (data, dim) {
    this.unionExtent(data.getApproximateExtent(dim));
  };
  /**
   * @override
   * If value is in extent range
   */


  OrdinalScale.prototype.isInExtentRange = function (value) {
    value = this._getTickNumber(value);
    return this._extent[0] <= value && this._extent[1] >= value;
  };

  OrdinalScale.prototype.getOrdinalMeta = function () {
    return this._ordinalMeta;
  };

  OrdinalScale.prototype.calcNiceTicks = function () {};

  OrdinalScale.prototype.calcNiceExtent = function () {};

  OrdinalScale.type = 'ordinal';
  return OrdinalScale;
}(Scale$1);

Scale$1.registerClass(OrdinalScale);
const OrdinalScale$1 = OrdinalScale;
/* Injected with object hook! */

var roundNumber = round$1;

var IntervalScale =
/** @class */
function (_super) {
  __extends(IntervalScale, _super);

  function IntervalScale() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = 'interval'; // Step is calculated in adjustExtent.

    _this._interval = 0;
    _this._intervalPrecision = 2;
    return _this;
  }

  IntervalScale.prototype.parse = function (val) {
    return val;
  };

  IntervalScale.prototype.contain = function (val) {
    return contain(val, this._extent);
  };

  IntervalScale.prototype.normalize = function (val) {
    return normalize(val, this._extent);
  };

  IntervalScale.prototype.scale = function (val) {
    return scale(val, this._extent);
  };

  IntervalScale.prototype.setExtent = function (start, end) {
    var thisExtent = this._extent; // start,end may be a Number like '25',so...

    if (!isNaN(start)) {
      thisExtent[0] = parseFloat(start);
    }

    if (!isNaN(end)) {
      thisExtent[1] = parseFloat(end);
    }
  };

  IntervalScale.prototype.unionExtent = function (other) {
    var extent = this._extent;
    other[0] < extent[0] && (extent[0] = other[0]);
    other[1] > extent[1] && (extent[1] = other[1]); // unionExtent may called by it's sub classes

    this.setExtent(extent[0], extent[1]);
  };

  IntervalScale.prototype.getInterval = function () {
    return this._interval;
  };

  IntervalScale.prototype.setInterval = function (interval) {
    this._interval = interval; // Dropped auto calculated niceExtent and use user-set extent.
    // We assume user wants to set both interval, min, max to get a better result.

    this._niceExtent = this._extent.slice();
    this._intervalPrecision = getIntervalPrecision(interval);
  };
  /**
   * @param expandToNicedExtent Whether expand the ticks to niced extent.
   */


  IntervalScale.prototype.getTicks = function (expandToNicedExtent) {
    var interval = this._interval;
    var extent = this._extent;
    var niceTickExtent = this._niceExtent;
    var intervalPrecision = this._intervalPrecision;
    var ticks = []; // If interval is 0, return [];

    if (!interval) {
      return ticks;
    } // Consider this case: using dataZoom toolbox, zoom and zoom.


    var safeLimit = 10000;

    if (extent[0] < niceTickExtent[0]) {
      if (expandToNicedExtent) {
        ticks.push({
          value: roundNumber(niceTickExtent[0] - interval, intervalPrecision)
        });
      } else {
        ticks.push({
          value: extent[0]
        });
      }
    }

    var tick = niceTickExtent[0];

    while (tick <= niceTickExtent[1]) {
      ticks.push({
        value: tick
      }); // Avoid rounding error

      tick = roundNumber(tick + interval, intervalPrecision);

      if (tick === ticks[ticks.length - 1].value) {
        // Consider out of safe float point, e.g.,
        // -3711126.9907707 + 2e-10 === -3711126.9907707
        break;
      }

      if (ticks.length > safeLimit) {
        return [];
      }
    } // Consider this case: the last item of ticks is smaller
    // than niceTickExtent[1] and niceTickExtent[1] === extent[1].


    var lastNiceTick = ticks.length ? ticks[ticks.length - 1].value : niceTickExtent[1];

    if (extent[1] > lastNiceTick) {
      if (expandToNicedExtent) {
        ticks.push({
          value: roundNumber(lastNiceTick + interval, intervalPrecision)
        });
      } else {
        ticks.push({
          value: extent[1]
        });
      }
    }

    return ticks;
  };

  IntervalScale.prototype.getMinorTicks = function (splitNumber) {
    var ticks = this.getTicks(true);
    var minorTicks = [];
    var extent = this.getExtent();

    for (var i = 1; i < ticks.length; i++) {
      var nextTick = ticks[i];
      var prevTick = ticks[i - 1];
      var count = 0;
      var minorTicksGroup = [];
      var interval = nextTick.value - prevTick.value;
      var minorInterval = interval / splitNumber;

      while (count < splitNumber - 1) {
        var minorTick = roundNumber(prevTick.value + (count + 1) * minorInterval); // For the first and last interval. The count may be less than splitNumber.

        if (minorTick > extent[0] && minorTick < extent[1]) {
          minorTicksGroup.push(minorTick);
        }

        count++;
      }

      minorTicks.push(minorTicksGroup);
    }

    return minorTicks;
  };
  /**
   * @param opt.precision If 'auto', use nice presision.
   * @param opt.pad returns 1.50 but not 1.5 if precision is 2.
   */


  IntervalScale.prototype.getLabel = function (data, opt) {
    if (data == null) {
      return '';
    }

    var precision = opt && opt.precision;

    if (precision == null) {
      precision = getPrecision(data.value) || 0;
    } else if (precision === 'auto') {
      // Should be more precise then tick.
      precision = this._intervalPrecision;
    } // (1) If `precision` is set, 12.005 should be display as '12.00500'.
    // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'.


    var dataNum = roundNumber(data.value, precision, true);
    return addCommas(dataNum);
  };
  /**
   * @param splitNumber By default `5`.
   */


  IntervalScale.prototype.calcNiceTicks = function (splitNumber, minInterval, maxInterval) {
    splitNumber = splitNumber || 5;
    var extent = this._extent;
    var span = extent[1] - extent[0];

    if (!isFinite(span)) {
      return;
    } // User may set axis min 0 and data are all negative
    // FIXME If it needs to reverse ?


    if (span < 0) {
      span = -span;
      extent.reverse();
    }

    var result = intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval);
    this._intervalPrecision = result.intervalPrecision;
    this._interval = result.interval;
    this._niceExtent = result.niceTickExtent;
  };

  IntervalScale.prototype.calcNiceExtent = function (opt) {
    var extent = this._extent; // If extent start and end are same, expand them

    if (extent[0] === extent[1]) {
      if (extent[0] !== 0) {
        // Expand extent
        // Note that extents can be both negative. See #13154
        var expandSize = Math.abs(extent[0]); // In the fowllowing case
        //      Axis has been fixed max 100
        //      Plus data are all 100 and axis extent are [100, 100].
        // Extend to the both side will cause expanded max is larger than fixed max.
        // So only expand to the smaller side.

        if (!opt.fixMax) {
          extent[1] += expandSize / 2;
          extent[0] -= expandSize / 2;
        } else {
          extent[0] -= expandSize / 2;
        }
      } else {
        extent[1] = 1;
      }
    }

    var span = extent[1] - extent[0]; // If there are no data and extent are [Infinity, -Infinity]

    if (!isFinite(span)) {
      extent[0] = 0;
      extent[1] = 1;
    }

    this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); // let extent = this._extent;

    var interval = this._interval;

    if (!opt.fixMin) {
      extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval);
    }

    if (!opt.fixMax) {
      extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval);
    }
  };

  IntervalScale.prototype.setNiceExtent = function (min, max) {
    this._niceExtent = [min, max];
  };

  IntervalScale.type = 'interval';
  return IntervalScale;
}(Scale$1);

Scale$1.registerClass(IntervalScale);
const IntervalScale$1 = IntervalScale;
/* Injected with object hook! */

/* global Float32Array */

var supportFloat32Array = typeof Float32Array !== 'undefined';
var Float32ArrayCtor = !supportFloat32Array ? Array : Float32Array;
function createFloat32Array(arg) {
  if (isArray(arg)) {
    // Return self directly if don't support TypedArray.
    return supportFloat32Array ? new Float32Array(arg) : arg;
  } // Else is number


  return new Float32ArrayCtor(arg);
}
/* Injected with object hook! */

var STACK_PREFIX = '__ec_stack_';

function getSeriesStackId(seriesModel) {
  return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex;
}

function getAxisKey(axis) {
  return axis.dim + axis.index;
}
function prepareLayoutBarSeries(seriesType, ecModel) {
  var seriesModels = [];
  ecModel.eachSeriesByType(seriesType, function (seriesModel) {
    // Check series coordinate, do layout for cartesian2d only
    if (isOnCartesian(seriesModel)) {
      seriesModels.push(seriesModel);
    }
  });
  return seriesModels;
}
/**
 * Map from (baseAxis.dim + '_' + baseAxis.index) to min gap of two adjacent
 * values.
 * This works for time axes, value axes, and log axes.
 * For a single time axis, return value is in the form like
 * {'x_0': [1000000]}.
 * The value of 1000000 is in milliseconds.
 */

function getValueAxesMinGaps(barSeries) {
  /**
   * Map from axis.index to values.
   * For a single time axis, axisValues is in the form like
   * {'x_0': [1495555200000, 1495641600000, 1495728000000]}.
   * Items in axisValues[x], e.g. 1495555200000, are time values of all
   * series.
   */
  var axisValues = {};
  each$4(barSeries, function (seriesModel) {
    var cartesian = seriesModel.coordinateSystem;
    var baseAxis = cartesian.getBaseAxis();

    if (baseAxis.type !== 'time' && baseAxis.type !== 'value') {
      return;
    }

    var data = seriesModel.getData();
    var key = baseAxis.dim + '_' + baseAxis.index;
    var dimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim));
    var store = data.getStore();

    for (var i = 0, cnt = store.count(); i < cnt; ++i) {
      var value = store.get(dimIdx, i);

      if (!axisValues[key]) {
        // No previous data for the axis
        axisValues[key] = [value];
      } else {
        // No value in previous series
        axisValues[key].push(value);
      } // Ignore duplicated time values in the same axis

    }
  });
  var axisMinGaps = {};

  for (var key in axisValues) {
    if (axisValues.hasOwnProperty(key)) {
      var valuesInAxis = axisValues[key];

      if (valuesInAxis) {
        // Sort axis values into ascending order to calculate gaps
        valuesInAxis.sort(function (a, b) {
          return a - b;
        });
        var min = null;

        for (var j = 1; j < valuesInAxis.length; ++j) {
          var delta = valuesInAxis[j] - valuesInAxis[j - 1];

          if (delta > 0) {
            // Ignore 0 delta because they are of the same axis value
            min = min === null ? delta : Math.min(min, delta);
          }
        } // Set to null if only have one data


        axisMinGaps[key] = min;
      }
    }
  }

  return axisMinGaps;
}

function makeColumnLayout(barSeries) {
  var axisMinGaps = getValueAxesMinGaps(barSeries);
  var seriesInfoList = [];
  each$4(barSeries, function (seriesModel) {
    var cartesian = seriesModel.coordinateSystem;
    var baseAxis = cartesian.getBaseAxis();
    var axisExtent = baseAxis.getExtent();
    var bandWidth;

    if (baseAxis.type === 'category') {
      bandWidth = baseAxis.getBandWidth();
    } else if (baseAxis.type === 'value' || baseAxis.type === 'time') {
      var key = baseAxis.dim + '_' + baseAxis.index;
      var minGap = axisMinGaps[key];
      var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]);
      var scale = baseAxis.scale.getExtent();
      var scaleSpan = Math.abs(scale[1] - scale[0]);
      bandWidth = minGap ? extentSpan / scaleSpan * minGap : extentSpan; // When there is only one data value
    } else {
      var data = seriesModel.getData();
      bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count();
    }

    var barWidth = parsePercent(seriesModel.get('barWidth'), bandWidth);
    var barMaxWidth = parsePercent(seriesModel.get('barMaxWidth'), bandWidth);
    var barMinWidth = parsePercent( // barMinWidth by default is 0.5 / 1 in cartesian. Because in value axis,
    // the auto-calculated bar width might be less than 0.5 / 1.
    seriesModel.get('barMinWidth') || (isInLargeMode(seriesModel) ? 0.5 : 1), bandWidth);
    var barGap = seriesModel.get('barGap');
    var barCategoryGap = seriesModel.get('barCategoryGap');
    seriesInfoList.push({
      bandWidth: bandWidth,
      barWidth: barWidth,
      barMaxWidth: barMaxWidth,
      barMinWidth: barMinWidth,
      barGap: barGap,
      barCategoryGap: barCategoryGap,
      axisKey: getAxisKey(baseAxis),
      stackId: getSeriesStackId(seriesModel)
    });
  });
  return doCalBarWidthAndOffset(seriesInfoList);
}

function doCalBarWidthAndOffset(seriesInfoList) {
  // Columns info on each category axis. Key is cartesian name
  var columnsMap = {};
  each$4(seriesInfoList, function (seriesInfo, idx) {
    var axisKey = seriesInfo.axisKey;
    var bandWidth = seriesInfo.bandWidth;
    var columnsOnAxis = columnsMap[axisKey] || {
      bandWidth: bandWidth,
      remainedWidth: bandWidth,
      autoWidthCount: 0,
      categoryGap: null,
      gap: '20%',
      stacks: {}
    };
    var stacks = columnsOnAxis.stacks;
    columnsMap[axisKey] = columnsOnAxis;
    var stackId = seriesInfo.stackId;

    if (!stacks[stackId]) {
      columnsOnAxis.autoWidthCount++;
    }

    stacks[stackId] = stacks[stackId] || {
      width: 0,
      maxWidth: 0
    }; // Caution: In a single coordinate system, these barGrid attributes
    // will be shared by series. Consider that they have default values,
    // only the attributes set on the last series will work.
    // Do not change this fact unless there will be a break change.

    var barWidth = seriesInfo.barWidth;

    if (barWidth && !stacks[stackId].width) {
      // See #6312, do not restrict width.
      stacks[stackId].width = barWidth;
      barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
      columnsOnAxis.remainedWidth -= barWidth;
    }

    var barMaxWidth = seriesInfo.barMaxWidth;
    barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
    var barMinWidth = seriesInfo.barMinWidth;
    barMinWidth && (stacks[stackId].minWidth = barMinWidth);
    var barGap = seriesInfo.barGap;
    barGap != null && (columnsOnAxis.gap = barGap);
    var barCategoryGap = seriesInfo.barCategoryGap;
    barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap);
  });
  var result = {};
  each$4(columnsMap, function (columnsOnAxis, coordSysName) {
    result[coordSysName] = {};
    var stacks = columnsOnAxis.stacks;
    var bandWidth = columnsOnAxis.bandWidth;
    var categoryGapPercent = columnsOnAxis.categoryGap;

    if (categoryGapPercent == null) {
      var columnCount = keys(stacks).length; // More columns in one group
      // the spaces between group is smaller. Or the column will be too thin.

      categoryGapPercent = Math.max(35 - columnCount * 4, 15) + '%';
    }

    var categoryGap = parsePercent(categoryGapPercent, bandWidth);
    var barGapPercent = parsePercent(columnsOnAxis.gap, 1);
    var remainedWidth = columnsOnAxis.remainedWidth;
    var autoWidthCount = columnsOnAxis.autoWidthCount;
    var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
    autoWidth = Math.max(autoWidth, 0); // Find if any auto calculated bar exceeded maxBarWidth

    each$4(stacks, function (column) {
      var maxWidth = column.maxWidth;
      var minWidth = column.minWidth;

      if (!column.width) {
        var finalWidth = autoWidth;

        if (maxWidth && maxWidth < finalWidth) {
          finalWidth = Math.min(maxWidth, remainedWidth);
        } // `minWidth` has higher priority. `minWidth` decide that whether the
        // bar is able to be visible. So `minWidth` should not be restricted
        // by `maxWidth` or `remainedWidth` (which is from `bandWidth`). In
        // the extreme cases for `value` axis, bars are allowed to overlap
        // with each other if `minWidth` specified.


        if (minWidth && minWidth > finalWidth) {
          finalWidth = minWidth;
        }

        if (finalWidth !== autoWidth) {
          column.width = finalWidth;
          remainedWidth -= finalWidth + barGapPercent * finalWidth;
          autoWidthCount--;
        }
      } else {
        // `barMinWidth/barMaxWidth` has higher priority than `barWidth`, as
        // CSS does. Because barWidth can be a percent value, where
        // `barMaxWidth` can be used to restrict the final width.
        var finalWidth = column.width;

        if (maxWidth) {
          finalWidth = Math.min(finalWidth, maxWidth);
        } // `minWidth` has higher priority, as described above


        if (minWidth) {
          finalWidth = Math.max(finalWidth, minWidth);
        }

        column.width = finalWidth;
        remainedWidth -= finalWidth + barGapPercent * finalWidth;
        autoWidthCount--;
      }
    }); // Recalculate width again

    autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
    autoWidth = Math.max(autoWidth, 0);
    var widthSum = 0;
    var lastColumn;
    each$4(stacks, function (column, idx) {
      if (!column.width) {
        column.width = autoWidth;
      }

      lastColumn = column;
      widthSum += column.width * (1 + barGapPercent);
    });

    if (lastColumn) {
      widthSum -= lastColumn.width * barGapPercent;
    }

    var offset = -widthSum / 2;
    each$4(stacks, function (column, stackId) {
      result[coordSysName][stackId] = result[coordSysName][stackId] || {
        bandWidth: bandWidth,
        offset: offset,
        width: column.width
      };
      offset += column.width * (1 + barGapPercent);
    });
  });
  return result;
}

function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) {
  if (barWidthAndOffset && axis) {
    var result = barWidthAndOffset[getAxisKey(axis)];

    if (result != null && seriesModel != null) {
      return result[getSeriesStackId(seriesModel)];
    }

    return result;
  }
}
function layout$1(seriesType, ecModel) {
  var seriesModels = prepareLayoutBarSeries(seriesType, ecModel);
  var barWidthAndOffset = makeColumnLayout(seriesModels);
  each$4(seriesModels, function (seriesModel) {
    var data = seriesModel.getData();
    var cartesian = seriesModel.coordinateSystem;
    var baseAxis = cartesian.getBaseAxis();
    var stackId = getSeriesStackId(seriesModel);
    var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId];
    var columnOffset = columnLayoutInfo.offset;
    var columnWidth = columnLayoutInfo.width;
    data.setLayout({
      bandWidth: columnLayoutInfo.bandWidth,
      offset: columnOffset,
      size: columnWidth
    });
  });
} // TODO: Do not support stack in large mode yet.

function createProgressiveLayout(seriesType) {
  return {
    seriesType: seriesType,
    plan: createRenderPlanner(),
    reset: function (seriesModel) {
      if (!isOnCartesian(seriesModel)) {
        return;
      }

      var data = seriesModel.getData();
      var cartesian = seriesModel.coordinateSystem;
      var baseAxis = cartesian.getBaseAxis();
      var valueAxis = cartesian.getOtherAxis(baseAxis);
      var valueDimIdx = data.getDimensionIndex(data.mapDimension(valueAxis.dim));
      var baseDimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim));
      var drawBackground = seriesModel.get('showBackground', true);
      var valueDim = data.mapDimension(valueAxis.dim);
      var stackResultDim = data.getCalculationInfo('stackResultDimension');
      var stacked = isDimensionStacked(data, valueDim) && !!data.getCalculationInfo('stackedOnSeries');
      var isValueAxisH = valueAxis.isHorizontal();
      var valueAxisStart = getValueAxisStart(baseAxis, valueAxis);
      var isLarge = isInLargeMode(seriesModel);
      var barMinHeight = seriesModel.get('barMinHeight') || 0;
      var stackedDimIdx = stackResultDim && data.getDimensionIndex(stackResultDim); // Layout info.

      var columnWidth = data.getLayout('size');
      var columnOffset = data.getLayout('offset');
      return {
        progress: function (params, data) {
          var count = params.count;
          var largePoints = isLarge && createFloat32Array(count * 3);
          var largeBackgroundPoints = isLarge && drawBackground && createFloat32Array(count * 3);
          var largeDataIndices = isLarge && createFloat32Array(count);
          var coordLayout = cartesian.master.getRect();
          var bgSize = isValueAxisH ? coordLayout.width : coordLayout.height;
          var dataIndex;
          var store = data.getStore();
          var idxOffset = 0;

          while ((dataIndex = params.next()) != null) {
            var value = store.get(stacked ? stackedDimIdx : valueDimIdx, dataIndex);
            var baseValue = store.get(baseDimIdx, dataIndex);
            var baseCoord = valueAxisStart;
            var startValue = void 0; // Because of the barMinHeight, we can not use the value in
            // stackResultDimension directly.

            if (stacked) {
              startValue = +value - store.get(valueDimIdx, dataIndex);
            }

            var x = void 0;
            var y = void 0;
            var width = void 0;
            var height = void 0;

            if (isValueAxisH) {
              var coord = cartesian.dataToPoint([value, baseValue]);

              if (stacked) {
                var startCoord = cartesian.dataToPoint([startValue, baseValue]);
                baseCoord = startCoord[0];
              }

              x = baseCoord;
              y = coord[1] + columnOffset;
              width = coord[0] - baseCoord;
              height = columnWidth;

              if (Math.abs(width) < barMinHeight) {
                width = (width < 0 ? -1 : 1) * barMinHeight;
              }
            } else {
              var coord = cartesian.dataToPoint([baseValue, value]);

              if (stacked) {
                var startCoord = cartesian.dataToPoint([baseValue, startValue]);
                baseCoord = startCoord[1];
              }

              x = coord[0] + columnOffset;
              y = baseCoord;
              width = columnWidth;
              height = coord[1] - baseCoord;

              if (Math.abs(height) < barMinHeight) {
                // Include zero to has a positive bar
                height = (height <= 0 ? -1 : 1) * barMinHeight;
              }
            }

            if (!isLarge) {
              data.setItemLayout(dataIndex, {
                x: x,
                y: y,
                width: width,
                height: height
              });
            } else {
              largePoints[idxOffset] = x;
              largePoints[idxOffset + 1] = y;
              largePoints[idxOffset + 2] = isValueAxisH ? width : height;

              if (largeBackgroundPoints) {
                largeBackgroundPoints[idxOffset] = isValueAxisH ? coordLayout.x : x;
                largeBackgroundPoints[idxOffset + 1] = isValueAxisH ? y : coordLayout.y;
                largeBackgroundPoints[idxOffset + 2] = bgSize;
              }

              largeDataIndices[dataIndex] = dataIndex;
            }

            idxOffset += 3;
          }

          if (isLarge) {
            data.setLayout({
              largePoints: largePoints,
              largeDataIndices: largeDataIndices,
              largeBackgroundPoints: largeBackgroundPoints,
              valueAxisHorizontal: isValueAxisH
            });
          }
        }
      };
    }
  };
}

function isOnCartesian(seriesModel) {
  return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d';
}

function isInLargeMode(seriesModel) {
  return seriesModel.pipelineContext && seriesModel.pipelineContext.large;
} // See cases in `test/bar-start.html` and `#7412`, `#8747`.


function getValueAxisStart(baseAxis, valueAxis) {
  return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === 'log' ? 1 : 0));
}
/* Injected with object hook! */

var bisect = function (a, x, lo, hi) {
  while (lo < hi) {
    var mid = lo + hi >>> 1;

    if (a[mid][1] < x) {
      lo = mid + 1;
    } else {
      hi = mid;
    }
  }

  return lo;
};

var TimeScale =
/** @class */
function (_super) {
  __extends(TimeScale, _super);

  function TimeScale(settings) {
    var _this = _super.call(this, settings) || this;

    _this.type = 'time';
    return _this;
  }
  /**
   * Get label is mainly for other components like dataZoom, tooltip.
   */


  TimeScale.prototype.getLabel = function (tick) {
    var useUTC = this.getSetting('useUTC');
    return format(tick.value, fullLeveledFormatter[getDefaultFormatPrecisionOfInterval(getPrimaryTimeUnit(this._minLevelUnit))] || fullLeveledFormatter.second, useUTC, this.getSetting('locale'));
  };

  TimeScale.prototype.getFormattedLabel = function (tick, idx, labelFormatter) {
    var isUTC = this.getSetting('useUTC');
    var lang = this.getSetting('locale');
    return leveledFormat(tick, idx, labelFormatter, lang, isUTC);
  };
  /**
   * @override
   */


  TimeScale.prototype.getTicks = function () {
    var interval = this._interval;
    var extent = this._extent;
    var ticks = []; // If interval is 0, return [];

    if (!interval) {
      return ticks;
    }

    ticks.push({
      value: extent[0],
      level: 0
    });
    var useUTC = this.getSetting('useUTC');
    var innerTicks = getIntervalTicks(this._minLevelUnit, this._approxInterval, useUTC, extent);
    ticks = ticks.concat(innerTicks);
    ticks.push({
      value: extent[1],
      level: 0
    });
    return ticks;
  };

  TimeScale.prototype.calcNiceExtent = function (opt) {
    var extent = this._extent; // If extent start and end are same, expand them

    if (extent[0] === extent[1]) {
      // Expand extent
      extent[0] -= ONE_DAY;
      extent[1] += ONE_DAY;
    } // If there are no data and extent are [Infinity, -Infinity]


    if (extent[1] === -Infinity && extent[0] === Infinity) {
      var d = new Date();
      extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate());
      extent[0] = extent[1] - ONE_DAY;
    }

    this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval);
  };

  TimeScale.prototype.calcNiceTicks = function (approxTickNum, minInterval, maxInterval) {
    approxTickNum = approxTickNum || 10;
    var extent = this._extent;
    var span = extent[1] - extent[0];
    this._approxInterval = span / approxTickNum;

    if (minInterval != null && this._approxInterval < minInterval) {
      this._approxInterval = minInterval;
    }

    if (maxInterval != null && this._approxInterval > maxInterval) {
      this._approxInterval = maxInterval;
    }

    var scaleIntervalsLen = scaleIntervals.length;
    var idx = Math.min(bisect(scaleIntervals, this._approxInterval, 0, scaleIntervalsLen), scaleIntervalsLen - 1); // Interval that can be used to calculate ticks

    this._interval = scaleIntervals[idx][1]; // Min level used when picking ticks from top down.
    // We check one more level to avoid the ticks are to sparse in some case.

    this._minLevelUnit = scaleIntervals[Math.max(idx - 1, 0)][0];
  };

  TimeScale.prototype.parse = function (val) {
    // val might be float.
    return isNumber(val) ? val : +parseDate(val);
  };

  TimeScale.prototype.contain = function (val) {
    return contain(this.parse(val), this._extent);
  };

  TimeScale.prototype.normalize = function (val) {
    return normalize(this.parse(val), this._extent);
  };

  TimeScale.prototype.scale = function (val) {
    return scale(val, this._extent);
  };

  TimeScale.type = 'time';
  return TimeScale;
}(IntervalScale$1);
/**
 * This implementation was originally copied from "d3.js"
 * <https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/time/scale.js>
 * with some modifications made for this program.
 * See the license statement at the head of this file.
 */


var scaleIntervals = [// Format                           interval
['second', ONE_SECOND], ['minute', ONE_MINUTE], ['hour', ONE_HOUR], ['quarter-day', ONE_HOUR * 6], ['half-day', ONE_HOUR * 12], ['day', ONE_DAY * 1.2], ['half-week', ONE_DAY * 3.5], ['week', ONE_DAY * 7], ['month', ONE_DAY * 31], ['quarter', ONE_DAY * 95], ['half-year', ONE_YEAR / 2], ['year', ONE_YEAR] // 1Y
];

function isUnitValueSame(unit, valueA, valueB, isUTC) {
  var dateA = parseDate(valueA);
  var dateB = parseDate(valueB);

  var isSame = function (unit) {
    return getUnitValue(dateA, unit, isUTC) === getUnitValue(dateB, unit, isUTC);
  };

  var isSameYear = function () {
    return isSame('year');
  }; // const isSameHalfYear = () => isSameYear() && isSame('half-year');
  // const isSameQuater = () => isSameYear() && isSame('quarter');


  var isSameMonth = function () {
    return isSameYear() && isSame('month');
  };

  var isSameDay = function () {
    return isSameMonth() && isSame('day');
  }; // const isSameHalfDay = () => isSameDay() && isSame('half-day');


  var isSameHour = function () {
    return isSameDay() && isSame('hour');
  };

  var isSameMinute = function () {
    return isSameHour() && isSame('minute');
  };

  var isSameSecond = function () {
    return isSameMinute() && isSame('second');
  };

  var isSameMilliSecond = function () {
    return isSameSecond() && isSame('millisecond');
  };

  switch (unit) {
    case 'year':
      return isSameYear();

    case 'month':
      return isSameMonth();

    case 'day':
      return isSameDay();

    case 'hour':
      return isSameHour();

    case 'minute':
      return isSameMinute();

    case 'second':
      return isSameSecond();

    case 'millisecond':
      return isSameMilliSecond();
  }
} // const primaryUnitGetters = {
//     year: fullYearGetterName(),
//     month: monthGetterName(),
//     day: dateGetterName(),
//     hour: hoursGetterName(),
//     minute: minutesGetterName(),
//     second: secondsGetterName(),
//     millisecond: millisecondsGetterName()
// };
// const primaryUnitUTCGetters = {
//     year: fullYearGetterName(true),
//     month: monthGetterName(true),
//     day: dateGetterName(true),
//     hour: hoursGetterName(true),
//     minute: minutesGetterName(true),
//     second: secondsGetterName(true),
//     millisecond: millisecondsGetterName(true)
// };
// function moveTick(date: Date, unitName: TimeUnit, step: number, isUTC: boolean) {
//     step = step || 1;
//     switch (getPrimaryTimeUnit(unitName)) {
//         case 'year':
//             date[fullYearSetterName(isUTC)](date[fullYearGetterName(isUTC)]() + step);
//             break;
//         case 'month':
//             date[monthSetterName(isUTC)](date[monthGetterName(isUTC)]() + step);
//             break;
//         case 'day':
//             date[dateSetterName(isUTC)](date[dateGetterName(isUTC)]() + step);
//             break;
//         case 'hour':
//             date[hoursSetterName(isUTC)](date[hoursGetterName(isUTC)]() + step);
//             break;
//         case 'minute':
//             date[minutesSetterName(isUTC)](date[minutesGetterName(isUTC)]() + step);
//             break;
//         case 'second':
//             date[secondsSetterName(isUTC)](date[secondsGetterName(isUTC)]() + step);
//             break;
//         case 'millisecond':
//             date[millisecondsSetterName(isUTC)](date[millisecondsGetterName(isUTC)]() + step);
//             break;
//     }
//     return date.getTime();
// }
// const DATE_INTERVALS = [[8, 7.5], [4, 3.5], [2, 1.5]];
// const MONTH_INTERVALS = [[6, 5.5], [3, 2.5], [2, 1.5]];
// const MINUTES_SECONDS_INTERVALS = [[30, 30], [20, 20], [15, 15], [10, 10], [5, 5], [2, 2]];


function getDateInterval(approxInterval, daysInMonth) {
  approxInterval /= ONE_DAY;
  return approxInterval > 16 ? 16 // Math.floor(daysInMonth / 2) + 1  // In this case we only want one tick between two months.
  : approxInterval > 7.5 ? 7 // TODO week 7 or day 8?
  : approxInterval > 3.5 ? 4 : approxInterval > 1.5 ? 2 : 1;
}

function getMonthInterval(approxInterval) {
  var APPROX_ONE_MONTH = 30 * ONE_DAY;
  approxInterval /= APPROX_ONE_MONTH;
  return approxInterval > 6 ? 6 : approxInterval > 3 ? 3 : approxInterval > 2 ? 2 : 1;
}

function getHourInterval(approxInterval) {
  approxInterval /= ONE_HOUR;
  return approxInterval > 12 ? 12 : approxInterval > 6 ? 6 : approxInterval > 3.5 ? 4 : approxInterval > 2 ? 2 : 1;
}

function getMinutesAndSecondsInterval(approxInterval, isMinutes) {
  approxInterval /= isMinutes ? ONE_MINUTE : ONE_SECOND;
  return approxInterval > 30 ? 30 : approxInterval > 20 ? 20 : approxInterval > 15 ? 15 : approxInterval > 10 ? 10 : approxInterval > 5 ? 5 : approxInterval > 2 ? 2 : 1;
}

function getMillisecondsInterval(approxInterval) {
  return nice(approxInterval, true);
}

function getFirstTimestampOfUnit(date, unitName, isUTC) {
  var outDate = new Date(date);

  switch (getPrimaryTimeUnit(unitName)) {
    case 'year':
    case 'month':
      outDate[monthSetterName(isUTC)](0);

    case 'day':
      outDate[dateSetterName(isUTC)](1);

    case 'hour':
      outDate[hoursSetterName(isUTC)](0);

    case 'minute':
      outDate[minutesSetterName(isUTC)](0);

    case 'second':
      outDate[secondsSetterName(isUTC)](0);
      outDate[millisecondsSetterName(isUTC)](0);
  }

  return outDate.getTime();
}

function getIntervalTicks(bottomUnitName, approxInterval, isUTC, extent) {
  var safeLimit = 10000;
  var unitNames = timeUnits;
  var iter = 0;

  function addTicksInSpan(interval, minTimestamp, maxTimestamp, getMethodName, setMethodName, isDate, out) {
    var date = new Date(minTimestamp);
    var dateTime = minTimestamp;
    var d = date[getMethodName](); // if (isDate) {
    //     d -= 1; // Starts with 0;   PENDING
    // }

    while (dateTime < maxTimestamp && dateTime <= extent[1]) {
      out.push({
        value: dateTime
      });
      d += interval;
      date[setMethodName](d);
      dateTime = date.getTime();
    } // This extra tick is for calcuating ticks of next level. Will not been added to the final result


    out.push({
      value: dateTime,
      notAdd: true
    });
  }

  function addLevelTicks(unitName, lastLevelTicks, levelTicks) {
    var newAddedTicks = [];
    var isFirstLevel = !lastLevelTicks.length;

    if (isUnitValueSame(getPrimaryTimeUnit(unitName), extent[0], extent[1], isUTC)) {
      return;
    }

    if (isFirstLevel) {
      lastLevelTicks = [{
        // TODO Optimize. Not include so may ticks.
        value: getFirstTimestampOfUnit(new Date(extent[0]), unitName, isUTC)
      }, {
        value: extent[1]
      }];
    }

    for (var i = 0; i < lastLevelTicks.length - 1; i++) {
      var startTick = lastLevelTicks[i].value;
      var endTick = lastLevelTicks[i + 1].value;

      if (startTick === endTick) {
        continue;
      }

      var interval = void 0;
      var getterName = void 0;
      var setterName = void 0;
      var isDate = false;

      switch (unitName) {
        case 'year':
          interval = Math.max(1, Math.round(approxInterval / ONE_DAY / 365));
          getterName = fullYearGetterName(isUTC);
          setterName = fullYearSetterName(isUTC);
          break;

        case 'half-year':
        case 'quarter':
        case 'month':
          interval = getMonthInterval(approxInterval);
          getterName = monthGetterName(isUTC);
          setterName = monthSetterName(isUTC);
          break;

        case 'week': // PENDING If week is added. Ignore day.

        case 'half-week':
        case 'day':
          interval = getDateInterval(approxInterval); // Use 32 days and let interval been 16

          getterName = dateGetterName(isUTC);
          setterName = dateSetterName(isUTC);
          isDate = true;
          break;

        case 'half-day':
        case 'quarter-day':
        case 'hour':
          interval = getHourInterval(approxInterval);
          getterName = hoursGetterName(isUTC);
          setterName = hoursSetterName(isUTC);
          break;

        case 'minute':
          interval = getMinutesAndSecondsInterval(approxInterval, true);
          getterName = minutesGetterName(isUTC);
          setterName = minutesSetterName(isUTC);
          break;

        case 'second':
          interval = getMinutesAndSecondsInterval(approxInterval, false);
          getterName = secondsGetterName(isUTC);
          setterName = secondsSetterName(isUTC);
          break;

        case 'millisecond':
          interval = getMillisecondsInterval(approxInterval);
          getterName = millisecondsGetterName(isUTC);
          setterName = millisecondsSetterName(isUTC);
          break;
      }

      addTicksInSpan(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks);

      if (unitName === 'year' && levelTicks.length > 1 && i === 0) {
        // Add nearest years to the left extent.
        levelTicks.unshift({
          value: levelTicks[0].value - interval
        });
      }
    }

    for (var i = 0; i < newAddedTicks.length; i++) {
      levelTicks.push(newAddedTicks[i]);
    } // newAddedTicks.length && console.log(unitName, newAddedTicks);


    return newAddedTicks;
  }

  var levelsTicks = [];
  var currentLevelTicks = [];
  var tickCount = 0;
  var lastLevelTickCount = 0;

  for (var i = 0; i < unitNames.length && iter++ < safeLimit; ++i) {
    var primaryTimeUnit = getPrimaryTimeUnit(unitNames[i]);

    if (!isPrimaryTimeUnit(unitNames[i])) {
      // TODO
      continue;
    }

    addLevelTicks(unitNames[i], levelsTicks[levelsTicks.length - 1] || [], currentLevelTicks);
    var nextPrimaryTimeUnit = unitNames[i + 1] ? getPrimaryTimeUnit(unitNames[i + 1]) : null;

    if (primaryTimeUnit !== nextPrimaryTimeUnit) {
      if (currentLevelTicks.length) {
        lastLevelTickCount = tickCount; // Remove the duplicate so the tick count can be precisely.

        currentLevelTicks.sort(function (a, b) {
          return a.value - b.value;
        });
        var levelTicksRemoveDuplicated = [];

        for (var i_1 = 0; i_1 < currentLevelTicks.length; ++i_1) {
          var tickValue = currentLevelTicks[i_1].value;

          if (i_1 === 0 || currentLevelTicks[i_1 - 1].value !== tickValue) {
            levelTicksRemoveDuplicated.push(currentLevelTicks[i_1]);

            if (tickValue >= extent[0] && tickValue <= extent[1]) {
              tickCount++;
            }
          }
        }

        var targetTickNum = (extent[1] - extent[0]) / approxInterval; // Added too much in this level and not too less in last level

        if (tickCount > targetTickNum * 1.5 && lastLevelTickCount > targetTickNum / 1.5) {
          break;
        } // Only treat primary time unit as one level.


        levelsTicks.push(levelTicksRemoveDuplicated);

        if (tickCount > targetTickNum || bottomUnitName === unitNames[i]) {
          break;
        }
      } // Reset if next unitName is primary


      currentLevelTicks = [];
    }
  }

  var levelsTicksInExtent = filter(map$1(levelsTicks, function (levelTicks) {
    return filter(levelTicks, function (tick) {
      return tick.value >= extent[0] && tick.value <= extent[1] && !tick.notAdd;
    });
  }), function (levelTicks) {
    return levelTicks.length > 0;
  });
  var ticks = [];
  var maxLevel = levelsTicksInExtent.length - 1;

  for (var i = 0; i < levelsTicksInExtent.length; ++i) {
    var levelTicks = levelsTicksInExtent[i];

    for (var k = 0; k < levelTicks.length; ++k) {
      ticks.push({
        value: levelTicks[k].value,
        level: maxLevel - i
      });
    }
  }

  ticks.sort(function (a, b) {
    return a.value - b.value;
  }); // Remove duplicates

  var result = [];

  for (var i = 0; i < ticks.length; ++i) {
    if (i === 0 || ticks[i].value !== ticks[i - 1].value) {
      result.push(ticks[i]);
    }
  }

  return result;
}

Scale$1.registerClass(TimeScale);
const TimeScale$1 = TimeScale;
/* Injected with object hook! */

var scaleProto = Scale$1.prototype; // FIXME:TS refactor: not good to call it directly with `this`?

var intervalScaleProto = IntervalScale$1.prototype;
var roundingErrorFix = round$1;
var mathFloor = Math.floor;
var mathCeil = Math.ceil;
var mathPow = Math.pow;
var mathLog$1 = Math.log;

var LogScale =
/** @class */
function (_super) {
  __extends(LogScale, _super);

  function LogScale() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = 'log';
    _this.base = 10;
    _this._originalScale = new IntervalScale$1(); // FIXME:TS actually used by `IntervalScale`

    _this._interval = 0;
    return _this;
  }
  /**
   * @param Whether expand the ticks to niced extent.
   */


  LogScale.prototype.getTicks = function (expandToNicedExtent) {
    var originalScale = this._originalScale;
    var extent = this._extent;
    var originalExtent = originalScale.getExtent();
    var ticks = intervalScaleProto.getTicks.call(this, expandToNicedExtent);
    return map$1(ticks, function (tick) {
      var val = tick.value;
      var powVal = round$1(mathPow(this.base, val)); // Fix #4158

      powVal = val === extent[0] && this._fixMin ? fixRoundingError(powVal, originalExtent[0]) : powVal;
      powVal = val === extent[1] && this._fixMax ? fixRoundingError(powVal, originalExtent[1]) : powVal;
      return {
        value: powVal
      };
    }, this);
  };

  LogScale.prototype.setExtent = function (start, end) {
    var base = mathLog$1(this.base); // log(-Infinity) is NaN, so safe guard here

    start = mathLog$1(Math.max(0, start)) / base;
    end = mathLog$1(Math.max(0, end)) / base;
    intervalScaleProto.setExtent.call(this, start, end);
  };
  /**
   * @return {number} end
   */


  LogScale.prototype.getExtent = function () {
    var base = this.base;
    var extent = scaleProto.getExtent.call(this);
    extent[0] = mathPow(base, extent[0]);
    extent[1] = mathPow(base, extent[1]); // Fix #4158

    var originalScale = this._originalScale;
    var originalExtent = originalScale.getExtent();
    this._fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0]));
    this._fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1]));
    return extent;
  };

  LogScale.prototype.unionExtent = function (extent) {
    this._originalScale.unionExtent(extent);

    var base = this.base;
    extent[0] = mathLog$1(extent[0]) / mathLog$1(base);
    extent[1] = mathLog$1(extent[1]) / mathLog$1(base);
    scaleProto.unionExtent.call(this, extent);
  };

  LogScale.prototype.unionExtentFromData = function (data, dim) {
    // TODO
    // filter value that <= 0
    this.unionExtent(data.getApproximateExtent(dim));
  };
  /**
   * Update interval and extent of intervals for nice ticks
   * @param approxTickNum default 10 Given approx tick number
   */


  LogScale.prototype.calcNiceTicks = function (approxTickNum) {
    approxTickNum = approxTickNum || 10;
    var extent = this._extent;
    var span = extent[1] - extent[0];

    if (span === Infinity || span <= 0) {
      return;
    }

    var interval = quantity(span);
    var err = approxTickNum / span * interval; // Filter ticks to get closer to the desired count.

    if (err <= 0.5) {
      interval *= 10;
    } // Interval should be integer


    while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) {
      interval *= 10;
    }

    var niceExtent = [round$1(mathCeil(extent[0] / interval) * interval), round$1(mathFloor(extent[1] / interval) * interval)];
    this._interval = interval;
    this._niceExtent = niceExtent;
  };

  LogScale.prototype.calcNiceExtent = function (opt) {
    intervalScaleProto.calcNiceExtent.call(this, opt);
    this._fixMin = opt.fixMin;
    this._fixMax = opt.fixMax;
  };

  LogScale.prototype.parse = function (val) {
    return val;
  };

  LogScale.prototype.contain = function (val) {
    val = mathLog$1(val) / mathLog$1(this.base);
    return contain(val, this._extent);
  };

  LogScale.prototype.normalize = function (val) {
    val = mathLog$1(val) / mathLog$1(this.base);
    return normalize(val, this._extent);
  };

  LogScale.prototype.scale = function (val) {
    val = scale(val, this._extent);
    return mathPow(this.base, val);
  };

  LogScale.type = 'log';
  return LogScale;
}(Scale$1);

var proto = LogScale.prototype;
proto.getMinorTicks = intervalScaleProto.getMinorTicks;
proto.getLabel = intervalScaleProto.getLabel;

function fixRoundingError(val, originalVal) {
  return roundingErrorFix(val, getPrecision(originalVal));
}

Scale$1.registerClass(LogScale);
const LogScale$1 = LogScale;
/* Injected with object hook! */

var ScaleRawExtentInfo =
/** @class */
function () {
  function ScaleRawExtentInfo(scale, model, // Usually: data extent from all series on this axis.
  originalExtent) {
    this._prepareParams(scale, model, originalExtent);
  }
  /**
   * Parameters depending on outside (like model, user callback)
   * are prepared and fixed here.
   */


  ScaleRawExtentInfo.prototype._prepareParams = function (scale, model, // Usually: data extent from all series on this axis.
  dataExtent) {
    if (dataExtent[1] < dataExtent[0]) {
      dataExtent = [NaN, NaN];
    }

    this._dataMin = dataExtent[0];
    this._dataMax = dataExtent[1];
    var isOrdinal = this._isOrdinal = scale.type === 'ordinal';
    this._needCrossZero = scale.type === 'interval' && model.getNeedCrossZero && model.getNeedCrossZero();
    var modelMinRaw = this._modelMinRaw = model.get('min', true);

    if (isFunction(modelMinRaw)) {
      // This callback always provides users the full data extent (before data is filtered).
      this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({
        min: dataExtent[0],
        max: dataExtent[1]
      }));
    } else if (modelMinRaw !== 'dataMin') {
      this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw);
    }

    var modelMaxRaw = this._modelMaxRaw = model.get('max', true);

    if (isFunction(modelMaxRaw)) {
      // This callback always provides users the full data extent (before data is filtered).
      this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({
        min: dataExtent[0],
        max: dataExtent[1]
      }));
    } else if (modelMaxRaw !== 'dataMax') {
      this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw);
    }

    if (isOrdinal) {
      // FIXME: there is a flaw here: if there is no "block" data processor like `dataZoom`,
      // and progressive rendering is using, here the category result might just only contain
      // the processed chunk rather than the entire result.
      this._axisDataLen = model.getCategories().length;
    } else {
      var boundaryGap = model.get('boundaryGap');
      var boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0];

      if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') {

        this._boundaryGapInner = [0, 0];
      } else {
        this._boundaryGapInner = [parsePercent$1(boundaryGapArr[0], 1), parsePercent$1(boundaryGapArr[1], 1)];
      }
    }
  };
  /**
   * Calculate extent by prepared parameters.
   * This method has no external dependency and can be called duplicatedly,
   * getting the same result.
   * If parameters changed, should call this method to recalcuate.
   */


  ScaleRawExtentInfo.prototype.calculate = function () {
    // Notice: When min/max is not set (that is, when there are null/undefined,
    // which is the most common case), these cases should be ensured:
    // (1) For 'ordinal', show all axis.data.
    // (2) For others:
    //      + `boundaryGap` is applied (if min/max set, boundaryGap is
    //      disabled).
    //      + If `needCrossZero`, min/max should be zero, otherwise, min/max should
    //      be the result that originalExtent enlarged by boundaryGap.
    // (3) If no data, it should be ensured that `scale.setBlank` is set.
    var isOrdinal = this._isOrdinal;
    var dataMin = this._dataMin;
    var dataMax = this._dataMax;
    var axisDataLen = this._axisDataLen;
    var boundaryGapInner = this._boundaryGapInner;
    var span = !isOrdinal ? dataMax - dataMin || Math.abs(dataMin) : null; // Currently if a `'value'` axis model min is specified as 'dataMin'/'dataMax',
    // `boundaryGap` will not be used. It's the different from specifying as `null`/`undefined`.

    var min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum;
    var max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum; // If `_modelMinNum`/`_modelMaxNum` is `null`/`undefined`, should not be fixed.

    var minFixed = min != null;
    var maxFixed = max != null;

    if (min == null) {
      min = isOrdinal ? axisDataLen ? 0 : NaN : dataMin - boundaryGapInner[0] * span;
    }

    if (max == null) {
      max = isOrdinal ? axisDataLen ? axisDataLen - 1 : NaN : dataMax + boundaryGapInner[1] * span;
    }

    (min == null || !isFinite(min)) && (min = NaN);
    (max == null || !isFinite(max)) && (max = NaN);
    var isBlank = eqNaN(min) || eqNaN(max) || isOrdinal && !axisDataLen; // If data extent modified, need to recalculated to ensure cross zero.

    if (this._needCrossZero) {
      // Axis is over zero and min is not set
      if (min > 0 && max > 0 && !minFixed) {
        min = 0; // minFixed = true;
      } // Axis is under zero and max is not set


      if (min < 0 && max < 0 && !maxFixed) {
        max = 0; // maxFixed = true;
      } // PENDING:
      // When `needCrossZero` and all data is positive/negative, should it be ensured
      // that the results processed by boundaryGap are positive/negative?
      // If so, here `minFixed`/`maxFixed` need to be set.

    }

    var determinedMin = this._determinedMin;
    var determinedMax = this._determinedMax;

    if (determinedMin != null) {
      min = determinedMin;
      minFixed = true;
    }

    if (determinedMax != null) {
      max = determinedMax;
      maxFixed = true;
    } // Ensure min/max be finite number or NaN here. (not to be null/undefined)
    // `NaN` means min/max axis is blank.


    return {
      min: min,
      max: max,
      minFixed: minFixed,
      maxFixed: maxFixed,
      isBlank: isBlank
    };
  };

  ScaleRawExtentInfo.prototype.modifyDataMinMax = function (minMaxName, val) {

    this[DATA_MIN_MAX_ATTR[minMaxName]] = val;
  };

  ScaleRawExtentInfo.prototype.setDeterminedMinMax = function (minMaxName, val) {
    var attr = DETERMINED_MIN_MAX_ATTR[minMaxName];

    this[attr] = val;
  };

  ScaleRawExtentInfo.prototype.freeze = function () {
    // @ts-ignore
    this.frozen = true;
  };

  return ScaleRawExtentInfo;
}();
var DETERMINED_MIN_MAX_ATTR = {
  min: '_determinedMin',
  max: '_determinedMax'
};
var DATA_MIN_MAX_ATTR = {
  min: '_dataMin',
  max: '_dataMax'
};
/**
 * Get scale min max and related info only depends on model settings.
 * This method can be called after coordinate system created.
 * For example, in data processing stage.
 *
 * Scale extent info probably be required multiple times during a workflow.
 * For example:
 * (1) `dataZoom` depends it to get the axis extent in "100%" state.
 * (2) `processor/extentCalculator` depends it to make sure whether axis extent is specified.
 * (3) `coordSys.update` use it to finally decide the scale extent.
 * But the callback of `min`/`max` should not be called multiple times.
 * The code below should not be implemented repeatedly either.
 * So we cache the result in the scale instance, which will be recreated at the beginning
 * of the workflow (because `scale` instance will be recreated each round of the workflow).
 */

function ensureScaleRawExtentInfo(scale, model, // Usually: data extent from all series on this axis.
originalExtent) {
  // Do not permit to recreate.
  var rawExtentInfo = scale.rawExtentInfo;

  if (rawExtentInfo) {
    return rawExtentInfo;
  }

  rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent); // @ts-ignore

  scale.rawExtentInfo = rawExtentInfo;
  return rawExtentInfo;
}
function parseAxisModelMinMax(scale, minMax) {
  return minMax == null ? null : eqNaN(minMax) ? NaN : scale.parse(minMax);
}
/* Injected with object hook! */

/**
 * Get axis scale extent before niced.
 * Item of returned array can only be number (including Infinity and NaN).
 *
 * Caution:
 * Precondition of calling this method:
 * The scale extent has been initialized using series data extent via
 * `scale.setExtent` or `scale.unionExtentFromData`;
 */

function getScaleExtent(scale, model) {
  var scaleType = scale.type;
  var rawExtentResult = ensureScaleRawExtentInfo(scale, model, scale.getExtent()).calculate();
  scale.setBlank(rawExtentResult.isBlank);
  var min = rawExtentResult.min;
  var max = rawExtentResult.max; // If bars are placed on a base axis of type time or interval account for axis boundary overflow and current axis
  // is base axis
  // FIXME
  // (1) Consider support value axis, where below zero and axis `onZero` should be handled properly.
  // (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent?
  //     Should not depend on series type `bar`?
  // (3) Fix that might overlap when using dataZoom.
  // (4) Consider other chart types using `barGrid`?
  // See #6728, #4862, `test/bar-overflow-time-plot.html`

  var ecModel = model.ecModel;

  if (ecModel && scaleType === 'time'
  /* || scaleType === 'interval' */
  ) {
    var barSeriesModels = prepareLayoutBarSeries('bar', ecModel);
    var isBaseAxisAndHasBarSeries_1 = false;
    each$4(barSeriesModels, function (seriesModel) {
      isBaseAxisAndHasBarSeries_1 = isBaseAxisAndHasBarSeries_1 || seriesModel.getBaseAxis() === model.axis;
    });

    if (isBaseAxisAndHasBarSeries_1) {
      // Calculate placement of bars on axis. TODO should be decoupled
      // with barLayout
      var barWidthAndOffset = makeColumnLayout(barSeriesModels); // Adjust axis min and max to account for overflow

      var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset);
      min = adjustedScale.min;
      max = adjustedScale.max;
    }
  }

  return {
    extent: [min, max],
    // "fix" means "fixed", the value should not be
    // changed in the subsequent steps.
    fixMin: rawExtentResult.minFixed,
    fixMax: rawExtentResult.maxFixed
  };
}

function adjustScaleForOverflow(min, max, model, // Only support cartesian coord yet.
barWidthAndOffset) {
  // Get Axis Length
  var axisExtent = model.axis.getExtent();
  var axisLength = axisExtent[1] - axisExtent[0]; // Get bars on current base axis and calculate min and max overflow

  var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis);

  if (barsOnCurrentAxis === undefined) {
    return {
      min: min,
      max: max
    };
  }

  var minOverflow = Infinity;
  each$4(barsOnCurrentAxis, function (item) {
    minOverflow = Math.min(item.offset, minOverflow);
  });
  var maxOverflow = -Infinity;
  each$4(barsOnCurrentAxis, function (item) {
    maxOverflow = Math.max(item.offset + item.width, maxOverflow);
  });
  minOverflow = Math.abs(minOverflow);
  maxOverflow = Math.abs(maxOverflow);
  var totalOverFlow = minOverflow + maxOverflow; // Calculate required buffer based on old range and overflow

  var oldRange = max - min;
  var oldRangePercentOfNew = 1 - (minOverflow + maxOverflow) / axisLength;
  var overflowBuffer = oldRange / oldRangePercentOfNew - oldRange;
  max += overflowBuffer * (maxOverflow / totalOverFlow);
  min -= overflowBuffer * (minOverflow / totalOverFlow);
  return {
    min: min,
    max: max
  };
} // Precondition of calling this method:
// The scale extent has been initialized using series data extent via
// `scale.setExtent` or `scale.unionExtentFromData`;


function niceScaleExtent(scale, inModel) {
  var model = inModel;
  var extentInfo = getScaleExtent(scale, model);
  var extent = extentInfo.extent;
  var splitNumber = model.get('splitNumber');

  if (scale instanceof LogScale$1) {
    scale.base = model.get('logBase');
  }

  var scaleType = scale.type;
  var interval = model.get('interval');
  var isIntervalOrTime = scaleType === 'interval' || scaleType === 'time';
  scale.setExtent(extent[0], extent[1]);
  scale.calcNiceExtent({
    splitNumber: splitNumber,
    fixMin: extentInfo.fixMin,
    fixMax: extentInfo.fixMax,
    minInterval: isIntervalOrTime ? model.get('minInterval') : null,
    maxInterval: isIntervalOrTime ? model.get('maxInterval') : null
  }); // If some one specified the min, max. And the default calculated interval
  // is not good enough. He can specify the interval. It is often appeared
  // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard
  // to be 60.
  // FIXME

  if (interval != null) {
    scale.setInterval && scale.setInterval(interval);
  }
}
/**
 * @param axisType Default retrieve from model.type
 */

function createScaleByModel(model, axisType) {
  axisType = axisType || model.get('type');

  if (axisType) {
    switch (axisType) {
      // Buildin scale
      case 'category':
        return new OrdinalScale$1({
          ordinalMeta: model.getOrdinalMeta ? model.getOrdinalMeta() : model.getCategories(),
          extent: [Infinity, -Infinity]
        });

      case 'time':
        return new TimeScale$1({
          locale: model.ecModel.getLocaleModel(),
          useUTC: model.ecModel.get('useUTC')
        });

      default:
        // case 'value'/'interval', 'log', or others.
        return new (Scale$1.getClass(axisType) || IntervalScale$1)();
    }
  }
}
/**
 * Check if the axis cross 0
 */

function ifAxisCrossZero(axis) {
  var dataExtent = axis.scale.getExtent();
  var min = dataExtent[0];
  var max = dataExtent[1];
  return !(min > 0 && max > 0 || min < 0 && max < 0);
}
/**
 * @param axis
 * @return Label formatter function.
 *         param: {number} tickValue,
 *         param: {number} idx, the index in all ticks.
 *                         If category axis, this param is not required.
 *         return: {string} label string.
 */

function makeLabelFormatter(axis) {
  var labelFormatter = axis.getLabelModel().get('formatter');
  var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null;

  if (axis.scale.type === 'time') {
    return function (tpl) {
      return function (tick, idx) {
        return axis.scale.getFormattedLabel(tick, idx, tpl);
      };
    }(labelFormatter);
  } else if (isString(labelFormatter)) {
    return function (tpl) {
      return function (tick) {
        // For category axis, get raw value; for numeric axis,
        // get formatted label like '1,333,444'.
        var label = axis.scale.getLabel(tick);
        var text = tpl.replace('{value}', label != null ? label : '');
        return text;
      };
    }(labelFormatter);
  } else if (isFunction(labelFormatter)) {
    return function (cb) {
      return function (tick, idx) {
        // The original intention of `idx` is "the index of the tick in all ticks".
        // But the previous implementation of category axis do not consider the
        // `axisLabel.interval`, which cause that, for example, the `interval` is
        // `1`, then the ticks "name5", "name7", "name9" are displayed, where the
        // corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep
        // the definition here for back compatibility.
        if (categoryTickStart != null) {
          idx = tick.value - categoryTickStart;
        }

        return cb(getAxisRawValue(axis, tick), idx, tick.level != null ? {
          level: tick.level
        } : null);
      };
    }(labelFormatter);
  } else {
    return function (tick) {
      return axis.scale.getLabel(tick);
    };
  }
}
function getAxisRawValue(axis, tick) {
  // In category axis with data zoom, tick is not the original
  // index of axis.data. So tick should not be exposed to user
  // in category axis.
  return axis.type === 'category' ? axis.scale.getLabel(tick) : tick.value;
}
/**
 * @param axis
 * @return Be null/undefined if no labels.
 */

function estimateLabelUnionRect(axis) {
  var axisModel = axis.model;
  var scale = axis.scale;

  if (!axisModel.get(['axisLabel', 'show']) || scale.isBlank()) {
    return;
  }

  var realNumberScaleTicks;
  var tickCount;
  var categoryScaleExtent = scale.getExtent(); // Optimize for large category data, avoid call `getTicks()`.

  if (scale instanceof OrdinalScale$1) {
    tickCount = scale.count();
  } else {
    realNumberScaleTicks = scale.getTicks();
    tickCount = realNumberScaleTicks.length;
  }

  var axisLabelModel = axis.getLabelModel();
  var labelFormatter = makeLabelFormatter(axis);
  var rect;
  var step = 1; // Simple optimization for large amount of labels

  if (tickCount > 40) {
    step = Math.ceil(tickCount / 40);
  }

  for (var i = 0; i < tickCount; i += step) {
    var tick = realNumberScaleTicks ? realNumberScaleTicks[i] : {
      value: categoryScaleExtent[0] + i
    };
    var label = labelFormatter(tick, i);
    var unrotatedSingleRect = axisLabelModel.getTextRect(label);
    var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0);
    rect ? rect.union(singleRect) : rect = singleRect;
  }

  return rect;
}

function rotateTextRect(textRect, rotate) {
  var rotateRadians = rotate * Math.PI / 180;
  var beforeWidth = textRect.width;
  var beforeHeight = textRect.height;
  var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians));
  var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians));
  var rotatedRect = new BoundingRect$1(textRect.x, textRect.y, afterWidth, afterHeight);
  return rotatedRect;
}
/**
 * @param model axisLabelModel or axisTickModel
 * @return {number|String} Can be null|'auto'|number|function
 */


function getOptionCategoryInterval(model) {
  var interval = model.get('interval');
  return interval == null ? 'auto' : interval;
}
/**
 * Set `categoryInterval` as 0 implicitly indicates that
 * show all labels regardless of overlap.
 * @param {Object} axis axisModel.axis
 */

function shouldShowAllLabels(axis) {
  return axis.type === 'category' && getOptionCategoryInterval(axis.getLabelModel()) === 0;
}
function getDataDimensionsOnAxis(data, axisDim) {
  // Remove duplicated dat dimensions caused by `getStackedDimension`.
  var dataDimMap = {}; // Currently `mapDimensionsAll` will contain stack result dimension ('__\0ecstackresult').
  // PENDING: is it reasonable? Do we need to remove the original dim from "coord dim" since
  // there has been stacked result dim?

  each$4(data.mapDimensionsAll(axisDim), function (dataDim) {
    // For example, the extent of the original dimension
    // is [0.1, 0.5], the extent of the `stackResultDimension`
    // is [7, 9], the final extent should NOT include [0.1, 0.5],
    // because there is no graphic corresponding to [0.1, 0.5].
    // See the case in `test/area-stack.html` `main1`, where area line
    // stack needs `yAxis` not start from 0.
    dataDimMap[getStackedDimension(data, dataDim)] = true;
  });
  return keys(dataDimMap);
}
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
var AxisModelCommonMixin =
/** @class */
function () {
  function AxisModelCommonMixin() {}

  AxisModelCommonMixin.prototype.getNeedCrossZero = function () {
    var option = this.option;
    return !option.scale;
  };
  /**
   * Should be implemented by each axis model if necessary.
   * @return coordinate system model
   */


  AxisModelCommonMixin.prototype.getCoordSysModel = function () {
    return;
  };

  return AxisModelCommonMixin;
}();
/* Injected with object hook! */

var extensions = [];
var extensionRegisters = {
  registerPreprocessor: registerPreprocessor,
  registerProcessor: registerProcessor,
  registerPostInit: registerPostInit,
  registerPostUpdate: registerPostUpdate,
  registerUpdateLifecycle: registerUpdateLifecycle,
  registerAction: registerAction,
  registerCoordinateSystem: registerCoordinateSystem,
  registerLayout: registerLayout,
  registerVisual: registerVisual,
  registerTransform: registerTransform,
  registerLoading: registerLoading,
  registerMap: registerMap,
  registerImpl: registerImpl,
  PRIORITY: PRIORITY,
  ComponentModel: ComponentModel$1,
  ComponentView: ComponentView$1,
  SeriesModel: SeriesModel$1,
  ChartView: ChartView$1,
  // TODO Use ComponentModel and SeriesModel instead of Constructor
  registerComponentModel: function (ComponentModelClass) {
    ComponentModel$1.registerClass(ComponentModelClass);
  },
  registerComponentView: function (ComponentViewClass) {
    ComponentView$1.registerClass(ComponentViewClass);
  },
  registerSeriesModel: function (SeriesModelClass) {
    SeriesModel$1.registerClass(SeriesModelClass);
  },
  registerChartView: function (ChartViewClass) {
    ChartView$1.registerClass(ChartViewClass);
  },
  registerSubTypeDefaulter: function (componentType, defaulter) {
    ComponentModel$1.registerSubTypeDefaulter(componentType, defaulter);
  },
  registerPainter: function (painterType, PainterCtor) {
    registerPainter(painterType, PainterCtor);
  }
};
function use(ext) {
  if (isArray(ext)) {
    // use([ChartLine, ChartBar]);
    each$4(ext, function (singleExt) {
      use(singleExt);
    });
    return;
  }

  if (indexOf(extensions, ext) >= 0) {
    return;
  }

  extensions.push(ext);

  if (isFunction(ext)) {
    ext = {
      install: ext
    };
  }

  ext.install(extensionRegisters);
}
/* Injected with object hook! */

var inner$4 = makeInner();
function createAxisLabels(axis) {
  // Only ordinal scale support tick interval
  return axis.type === 'category' ? makeCategoryLabels(axis) : makeRealNumberLabels(axis);
}
/**
 * @param {module:echats/coord/Axis} axis
 * @param {module:echarts/model/Model} tickModel For example, can be axisTick, splitLine, splitArea.
 * @return {Object} {
 *     ticks: Array.<number>
 *     tickCategoryInterval: number
 * }
 */

function createAxisTicks(axis, tickModel) {
  // Only ordinal scale support tick interval
  return axis.type === 'category' ? makeCategoryTicks(axis, tickModel) : {
    ticks: map$1(axis.scale.getTicks(), function (tick) {
      return tick.value;
    })
  };
}

function makeCategoryLabels(axis) {
  var labelModel = axis.getLabelModel();
  var result = makeCategoryLabelsActually(axis, labelModel);
  return !labelModel.get('show') || axis.scale.isBlank() ? {
    labels: [],
    labelCategoryInterval: result.labelCategoryInterval
  } : result;
}

function makeCategoryLabelsActually(axis, labelModel) {
  var labelsCache = getListCache(axis, 'labels');
  var optionLabelInterval = getOptionCategoryInterval(labelModel);
  var result = listCacheGet(labelsCache, optionLabelInterval);

  if (result) {
    return result;
  }

  var labels;
  var numericLabelInterval;

  if (isFunction(optionLabelInterval)) {
    labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval);
  } else {
    numericLabelInterval = optionLabelInterval === 'auto' ? makeAutoCategoryInterval(axis) : optionLabelInterval;
    labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval);
  } // Cache to avoid calling interval function repeatedly.


  return listCacheSet(labelsCache, optionLabelInterval, {
    labels: labels,
    labelCategoryInterval: numericLabelInterval
  });
}

function makeCategoryTicks(axis, tickModel) {
  var ticksCache = getListCache(axis, 'ticks');
  var optionTickInterval = getOptionCategoryInterval(tickModel);
  var result = listCacheGet(ticksCache, optionTickInterval);

  if (result) {
    return result;
  }

  var ticks;
  var tickCategoryInterval; // Optimize for the case that large category data and no label displayed,
  // we should not return all ticks.

  if (!tickModel.get('show') || axis.scale.isBlank()) {
    ticks = [];
  }

  if (isFunction(optionTickInterval)) {
    ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true);
  } // Always use label interval by default despite label show. Consider this
  // scenario, Use multiple grid with the xAxis sync, and only one xAxis shows
  // labels. `splitLine` and `axisTick` should be consistent in this case.
  else if (optionTickInterval === 'auto') {
      var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel());
      tickCategoryInterval = labelsResult.labelCategoryInterval;
      ticks = map$1(labelsResult.labels, function (labelItem) {
        return labelItem.tickValue;
      });
    } else {
      tickCategoryInterval = optionTickInterval;
      ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true);
    } // Cache to avoid calling interval function repeatedly.


  return listCacheSet(ticksCache, optionTickInterval, {
    ticks: ticks,
    tickCategoryInterval: tickCategoryInterval
  });
}

function makeRealNumberLabels(axis) {
  var ticks = axis.scale.getTicks();
  var labelFormatter = makeLabelFormatter(axis);
  return {
    labels: map$1(ticks, function (tick, idx) {
      return {
        level: tick.level,
        formattedLabel: labelFormatter(tick, idx),
        rawLabel: axis.scale.getLabel(tick),
        tickValue: tick.value
      };
    })
  };
}

function getListCache(axis, prop) {
  // Because key can be a function, and cache size always is small, we use array cache.
  return inner$4(axis)[prop] || (inner$4(axis)[prop] = []);
}

function listCacheGet(cache, key) {
  for (var i = 0; i < cache.length; i++) {
    if (cache[i].key === key) {
      return cache[i].value;
    }
  }
}

function listCacheSet(cache, key, value) {
  cache.push({
    key: key,
    value: value
  });
  return value;
}

function makeAutoCategoryInterval(axis) {
  var result = inner$4(axis).autoInterval;
  return result != null ? result : inner$4(axis).autoInterval = axis.calculateCategoryInterval();
}
/**
 * Calculate interval for category axis ticks and labels.
 * To get precise result, at least one of `getRotate` and `isHorizontal`
 * should be implemented in axis.
 */


function calculateCategoryInterval(axis) {
  var params = fetchAutoCategoryIntervalCalculationParams(axis);
  var labelFormatter = makeLabelFormatter(axis);
  var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI;
  var ordinalScale = axis.scale;
  var ordinalExtent = ordinalScale.getExtent(); // Providing this method is for optimization:
  // avoid generating a long array by `getTicks`
  // in large category data case.

  var tickCount = ordinalScale.count();

  if (ordinalExtent[1] - ordinalExtent[0] < 1) {
    return 0;
  }

  var step = 1; // Simple optimization. Empirical value: tick count should less than 40.

  if (tickCount > 40) {
    step = Math.max(1, Math.floor(tickCount / 40));
  }

  var tickValue = ordinalExtent[0];
  var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue);
  var unitW = Math.abs(unitSpan * Math.cos(rotation));
  var unitH = Math.abs(unitSpan * Math.sin(rotation));
  var maxW = 0;
  var maxH = 0; // Caution: Performance sensitive for large category data.
  // Consider dataZoom, we should make appropriate step to avoid O(n) loop.

  for (; tickValue <= ordinalExtent[1]; tickValue += step) {
    var width = 0;
    var height = 0; // Not precise, do not consider align and vertical align
    // and each distance from axis line yet.

    var rect = getBoundingRect(labelFormatter({
      value: tickValue
    }), params.font, 'center', 'top'); // Magic number

    width = rect.width * 1.3;
    height = rect.height * 1.3; // Min size, void long loop.

    maxW = Math.max(maxW, width, 7);
    maxH = Math.max(maxH, height, 7);
  }

  var dw = maxW / unitW;
  var dh = maxH / unitH; // 0/0 is NaN, 1/0 is Infinity.

  isNaN(dw) && (dw = Infinity);
  isNaN(dh) && (dh = Infinity);
  var interval = Math.max(0, Math.floor(Math.min(dw, dh)));
  var cache = inner$4(axis.model);
  var axisExtent = axis.getExtent();
  var lastAutoInterval = cache.lastAutoInterval;
  var lastTickCount = cache.lastTickCount; // Use cache to keep interval stable while moving zoom window,
  // otherwise the calculated interval might jitter when the zoom
  // window size is close to the interval-changing size.
  // For example, if all of the axis labels are `a, b, c, d, e, f, g`.
  // The jitter will cause that sometimes the displayed labels are
  // `a, d, g` (interval: 2) sometimes `a, c, e`(interval: 1).

  if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 // Always choose the bigger one, otherwise the critical
  // point is not the same when zooming in or zooming out.
  && lastAutoInterval > interval // If the axis change is caused by chart resize, the cache should not
  // be used. Otherwise some hidden labels might not be shown again.
  && cache.axisExtent0 === axisExtent[0] && cache.axisExtent1 === axisExtent[1]) {
    interval = lastAutoInterval;
  } // Only update cache if cache not used, otherwise the
  // changing of interval is too insensitive.
  else {
      cache.lastTickCount = tickCount;
      cache.lastAutoInterval = interval;
      cache.axisExtent0 = axisExtent[0];
      cache.axisExtent1 = axisExtent[1];
    }

  return interval;
}

function fetchAutoCategoryIntervalCalculationParams(axis) {
  var labelModel = axis.getLabelModel();
  return {
    axisRotate: axis.getRotate ? axis.getRotate() : axis.isHorizontal && !axis.isHorizontal() ? 90 : 0,
    labelRotate: labelModel.get('rotate') || 0,
    font: labelModel.getFont()
  };
}

function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) {
  var labelFormatter = makeLabelFormatter(axis);
  var ordinalScale = axis.scale;
  var ordinalExtent = ordinalScale.getExtent();
  var labelModel = axis.getLabelModel();
  var result = []; // TODO: axisType: ordinalTime, pick the tick from each month/day/year/...

  var step = Math.max((categoryInterval || 0) + 1, 1);
  var startTick = ordinalExtent[0];
  var tickCount = ordinalScale.count(); // Calculate start tick based on zero if possible to keep label consistent
  // while zooming and moving while interval > 0. Otherwise the selection
  // of displayable ticks and symbols probably keep changing.
  // 3 is empirical value.

  if (startTick !== 0 && step > 1 && tickCount / step > 2) {
    startTick = Math.round(Math.ceil(startTick / step) * step);
  } // (1) Only add min max label here but leave overlap checking
  // to render stage, which also ensure the returned list
  // suitable for splitLine and splitArea rendering.
  // (2) Scales except category always contain min max label so
  // do not need to perform this process.


  var showAllLabel = shouldShowAllLabels(axis);
  var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel;
  var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel;

  if (includeMinLabel && startTick !== ordinalExtent[0]) {
    addItem(ordinalExtent[0]);
  } // Optimize: avoid generating large array by `ordinalScale.getTicks()`.


  var tickValue = startTick;

  for (; tickValue <= ordinalExtent[1]; tickValue += step) {
    addItem(tickValue);
  }

  if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) {
    addItem(ordinalExtent[1]);
  }

  function addItem(tickValue) {
    var tickObj = {
      value: tickValue
    };
    result.push(onlyTick ? tickValue : {
      formattedLabel: labelFormatter(tickObj),
      rawLabel: ordinalScale.getLabel(tickObj),
      tickValue: tickValue
    });
  }

  return result;
}

function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) {
  var ordinalScale = axis.scale;
  var labelFormatter = makeLabelFormatter(axis);
  var result = [];
  each$4(ordinalScale.getTicks(), function (tick) {
    var rawLabel = ordinalScale.getLabel(tick);
    var tickValue = tick.value;

    if (categoryInterval(tick.value, rawLabel)) {
      result.push(onlyTick ? tickValue : {
        formattedLabel: labelFormatter(tick),
        rawLabel: rawLabel,
        tickValue: tickValue
      });
    }
  });
  return result;
}
/* Injected with object hook! */

var NORMALIZED_EXTENT = [0, 1];
/**
 * Base class of Axis.
 */

var Axis =
/** @class */
function () {
  function Axis(dim, scale, extent) {
    this.onBand = false;
    this.inverse = false;
    this.dim = dim;
    this.scale = scale;
    this._extent = extent || [0, 0];
  }
  /**
   * If axis extent contain given coord
   */


  Axis.prototype.contain = function (coord) {
    var extent = this._extent;
    var min = Math.min(extent[0], extent[1]);
    var max = Math.max(extent[0], extent[1]);
    return coord >= min && coord <= max;
  };
  /**
   * If axis extent contain given data
   */


  Axis.prototype.containData = function (data) {
    return this.scale.contain(data);
  };
  /**
   * Get coord extent.
   */


  Axis.prototype.getExtent = function () {
    return this._extent.slice();
  };
  /**
   * Get precision used for formatting
   */


  Axis.prototype.getPixelPrecision = function (dataExtent) {
    return getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent);
  };
  /**
   * Set coord extent
   */


  Axis.prototype.setExtent = function (start, end) {
    var extent = this._extent;
    extent[0] = start;
    extent[1] = end;
  };
  /**
   * Convert data to coord. Data is the rank if it has an ordinal scale
   */


  Axis.prototype.dataToCoord = function (data, clamp) {
    var extent = this._extent;
    var scale = this.scale;
    data = scale.normalize(data);

    if (this.onBand && scale.type === 'ordinal') {
      extent = extent.slice();
      fixExtentWithBands(extent, scale.count());
    }

    return linearMap(data, NORMALIZED_EXTENT, extent, clamp);
  };
  /**
   * Convert coord to data. Data is the rank if it has an ordinal scale
   */


  Axis.prototype.coordToData = function (coord, clamp) {
    var extent = this._extent;
    var scale = this.scale;

    if (this.onBand && scale.type === 'ordinal') {
      extent = extent.slice();
      fixExtentWithBands(extent, scale.count());
    }

    var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp);
    return this.scale.scale(t);
  };
  /**
   * Convert pixel point to data in axis
   */


  Axis.prototype.pointToData = function (point, clamp) {
    // Should be implemented in derived class if necessary.
    return;
  };
  /**
   * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`,
   * `axis.getTicksCoords` considers `onBand`, which is used by
   * `boundaryGap:true` of category axis and splitLine and splitArea.
   * @param opt.tickModel default: axis.model.getModel('axisTick')
   * @param opt.clamp If `true`, the first and the last
   *        tick must be at the axis end points. Otherwise, clip ticks
   *        that outside the axis extent.
   */


  Axis.prototype.getTicksCoords = function (opt) {
    opt = opt || {};
    var tickModel = opt.tickModel || this.getTickModel();
    var result = createAxisTicks(this, tickModel);
    var ticks = result.ticks;
    var ticksCoords = map$1(ticks, function (tickVal) {
      return {
        coord: this.dataToCoord(this.scale.type === 'ordinal' ? this.scale.getRawOrdinalNumber(tickVal) : tickVal),
        tickValue: tickVal
      };
    }, this);
    var alignWithLabel = tickModel.get('alignWithLabel');
    fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp);
    return ticksCoords;
  };

  Axis.prototype.getMinorTicksCoords = function () {
    if (this.scale.type === 'ordinal') {
      // Category axis doesn't support minor ticks
      return [];
    }

    var minorTickModel = this.model.getModel('minorTick');
    var splitNumber = minorTickModel.get('splitNumber'); // Protection.

    if (!(splitNumber > 0 && splitNumber < 100)) {
      splitNumber = 5;
    }

    var minorTicks = this.scale.getMinorTicks(splitNumber);
    var minorTicksCoords = map$1(minorTicks, function (minorTicksGroup) {
      return map$1(minorTicksGroup, function (minorTick) {
        return {
          coord: this.dataToCoord(minorTick),
          tickValue: minorTick
        };
      }, this);
    }, this);
    return minorTicksCoords;
  };

  Axis.prototype.getViewLabels = function () {
    return createAxisLabels(this).labels;
  };

  Axis.prototype.getLabelModel = function () {
    return this.model.getModel('axisLabel');
  };
  /**
   * Notice here we only get the default tick model. For splitLine
   * or splitArea, we should pass the splitLineModel or splitAreaModel
   * manually when calling `getTicksCoords`.
   * In GL, this method may be overridden to:
   * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));`
   */


  Axis.prototype.getTickModel = function () {
    return this.model.getModel('axisTick');
  };
  /**
   * Get width of band
   */


  Axis.prototype.getBandWidth = function () {
    var axisExtent = this._extent;
    var dataExtent = this.scale.getExtent();
    var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); // Fix #2728, avoid NaN when only one data.

    len === 0 && (len = 1);
    var size = Math.abs(axisExtent[1] - axisExtent[0]);
    return Math.abs(size) / len;
  };
  /**
   * Only be called in category axis.
   * Can be overridden, consider other axes like in 3D.
   * @return Auto interval for cateogry axis tick and label
   */


  Axis.prototype.calculateCategoryInterval = function () {
    return calculateCategoryInterval(this);
  };

  return Axis;
}();

function fixExtentWithBands(extent, nTick) {
  var size = extent[1] - extent[0];
  var len = nTick;
  var margin = size / len / 2;
  extent[0] += margin;
  extent[1] -= margin;
} // If axis has labels [1, 2, 3, 4]. Bands on the axis are
// |---1---|---2---|---3---|---4---|.
// So the displayed ticks and splitLine/splitArea should between
// each data item, otherwise cause misleading (e.g., split tow bars
// of a single data item when there are two bar series).
// Also consider if tickCategoryInterval > 0 and onBand, ticks and
// splitLine/spliteArea should layout appropriately corresponding
// to displayed labels. (So we should not use `getBandWidth` in this
// case).


function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) {
  var ticksLen = ticksCoords.length;

  if (!axis.onBand || alignWithLabel || !ticksLen) {
    return;
  }

  var axisExtent = axis.getExtent();
  var last;
  var diffSize;

  if (ticksLen === 1) {
    ticksCoords[0].coord = axisExtent[0];
    last = ticksCoords[1] = {
      coord: axisExtent[1]
    };
  } else {
    var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue;
    var shift_1 = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen;
    each$4(ticksCoords, function (ticksItem) {
      ticksItem.coord -= shift_1 / 2;
    });
    var dataExtent = axis.scale.getExtent();
    diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue;
    last = {
      coord: ticksCoords[ticksLen - 1].coord + shift_1 * diffSize
    };
    ticksCoords.push(last);
  }

  var inverse = axisExtent[0] > axisExtent[1]; // Handling clamp.

  if (littleThan(ticksCoords[0].coord, axisExtent[0])) {
    clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift();
  }

  if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) {
    ticksCoords.unshift({
      coord: axisExtent[0]
    });
  }

  if (littleThan(axisExtent[1], last.coord)) {
    clamp ? last.coord = axisExtent[1] : ticksCoords.pop();
  }

  if (clamp && littleThan(last.coord, axisExtent[1])) {
    ticksCoords.push({
      coord: axisExtent[1]
    });
  }

  function littleThan(a, b) {
    // Avoid rounding error cause calculated tick coord different with extent.
    // It may cause an extra unnecessary tick added.
    a = round$1(a);
    b = round$1(b);
    return inverse ? a > b : a < b;
  }
}

const Axis$1 = Axis;
/* Injected with object hook! */

function prepareLayoutList(input) {
  var list = [];

  for (var i = 0; i < input.length; i++) {
    var rawItem = input[i];

    if (rawItem.defaultAttr.ignore) {
      continue;
    }

    var label = rawItem.label;
    var transform = label.getComputedTransform(); // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el.

    var localRect = label.getBoundingRect();
    var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5;
    var minMargin = label.style.margin || 0;
    var globalRect = localRect.clone();
    globalRect.applyTransform(transform);
    globalRect.x -= minMargin / 2;
    globalRect.y -= minMargin / 2;
    globalRect.width += minMargin;
    globalRect.height += minMargin;
    var obb = isAxisAligned ? new OrientedBoundingRect$1(localRect, transform) : null;
    list.push({
      label: label,
      labelLine: rawItem.labelLine,
      rect: globalRect,
      localRect: localRect,
      obb: obb,
      priority: rawItem.priority,
      defaultAttr: rawItem.defaultAttr,
      layoutOption: rawItem.computedLayoutOption,
      axisAligned: isAxisAligned,
      transform: transform
    });
  }

  return list;
}
function hideOverlap(labelList) {
  var displayedLabels = []; // TODO, render overflow visible first, put in the displayedLabels.

  labelList.sort(function (a, b) {
    return b.priority - a.priority;
  });
  var globalRect = new BoundingRect$1(0, 0, 0, 0);

  function hideEl(el) {
    if (!el.ignore) {
      // Show on emphasis.
      var emphasisState = el.ensureState('emphasis');

      if (emphasisState.ignore == null) {
        emphasisState.ignore = false;
      }
    }

    el.ignore = true;
  }

  for (var i = 0; i < labelList.length; i++) {
    var labelItem = labelList[i];
    var isAxisAligned = labelItem.axisAligned;
    var localRect = labelItem.localRect;
    var transform = labelItem.transform;
    var label = labelItem.label;
    var labelLine = labelItem.labelLine;
    globalRect.copy(labelItem.rect); // Add a threshold because layout may be aligned precisely.

    globalRect.width -= 0.1;
    globalRect.height -= 0.1;
    globalRect.x += 0.05;
    globalRect.y += 0.05;
    var obb = labelItem.obb;
    var overlapped = false;

    for (var j = 0; j < displayedLabels.length; j++) {
      var existsTextCfg = displayedLabels[j]; // Fast rejection.

      if (!globalRect.intersect(existsTextCfg.rect)) {
        continue;
      }

      if (isAxisAligned && existsTextCfg.axisAligned) {
        // Is overlapped
        overlapped = true;
        break;
      }

      if (!existsTextCfg.obb) {
        // If self is not axis aligned. But other is.
        existsTextCfg.obb = new OrientedBoundingRect$1(existsTextCfg.localRect, existsTextCfg.transform);
      }

      if (!obb) {
        // If self is axis aligned. But other is not.
        obb = new OrientedBoundingRect$1(localRect, transform);
      }

      if (obb.intersect(existsTextCfg.obb)) {
        overlapped = true;
        break;
      }
    } // TODO Callback to determine if this overlap should be handled?


    if (overlapped) {
      hideEl(label);
      labelLine && hideEl(labelLine);
    } else {
      label.attr('ignore', labelItem.defaultAttr.ignore);
      labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
      displayedLabels.push(labelItem);
    }
  }
}
/* Injected with object hook! */

function createDom(id, painter, dpr) {
    var newDom = platformApi.createCanvas();
    var width = painter.getWidth();
    var height = painter.getHeight();
    var newDomStyle = newDom.style;
    if (newDomStyle) {
        newDomStyle.position = 'absolute';
        newDomStyle.left = '0';
        newDomStyle.top = '0';
        newDomStyle.width = width + 'px';
        newDomStyle.height = height + 'px';
        newDom.setAttribute('data-zr-dom-id', id);
    }
    newDom.width = width * dpr;
    newDom.height = height * dpr;
    return newDom;
}
var Layer = (function (_super) {
    __extends(Layer, _super);
    function Layer(id, painter, dpr) {
        var _this = _super.call(this) || this;
        _this.motionBlur = false;
        _this.lastFrameAlpha = 0.7;
        _this.dpr = 1;
        _this.virtual = false;
        _this.config = {};
        _this.incremental = false;
        _this.zlevel = 0;
        _this.maxRepaintRectCount = 5;
        _this.__dirty = true;
        _this.__firstTimePaint = true;
        _this.__used = false;
        _this.__drawIndex = 0;
        _this.__startIndex = 0;
        _this.__endIndex = 0;
        _this.__prevStartIndex = null;
        _this.__prevEndIndex = null;
        var dom;
        dpr = dpr || devicePixelRatio;
        if (typeof id === 'string') {
            dom = createDom(id, painter, dpr);
        }
        else if (isObject$2(id)) {
            dom = id;
            id = dom.id;
        }
        _this.id = id;
        _this.dom = dom;
        var domStyle = dom.style;
        if (domStyle) {
            disableUserSelect(dom);
            dom.onselectstart = function () { return false; };
            domStyle.padding = '0';
            domStyle.margin = '0';
            domStyle.borderWidth = '0';
        }
        _this.painter = painter;
        _this.dpr = dpr;
        return _this;
    }
    Layer.prototype.getElementCount = function () {
        return this.__endIndex - this.__startIndex;
    };
    Layer.prototype.afterBrush = function () {
        this.__prevStartIndex = this.__startIndex;
        this.__prevEndIndex = this.__endIndex;
    };
    Layer.prototype.initContext = function () {
        this.ctx = this.dom.getContext('2d');
        this.ctx.dpr = this.dpr;
    };
    Layer.prototype.setUnpainted = function () {
        this.__firstTimePaint = true;
    };
    Layer.prototype.createBackBuffer = function () {
        var dpr = this.dpr;
        this.domBack = createDom('back-' + this.id, this.painter, dpr);
        this.ctxBack = this.domBack.getContext('2d');
        if (dpr !== 1) {
            this.ctxBack.scale(dpr, dpr);
        }
    };
    Layer.prototype.createRepaintRects = function (displayList, prevList, viewWidth, viewHeight) {
        if (this.__firstTimePaint) {
            this.__firstTimePaint = false;
            return null;
        }
        var mergedRepaintRects = [];
        var maxRepaintRectCount = this.maxRepaintRectCount;
        var full = false;
        var pendingRect = new BoundingRect$1(0, 0, 0, 0);
        function addRectToMergePool(rect) {
            if (!rect.isFinite() || rect.isZero()) {
                return;
            }
            if (mergedRepaintRects.length === 0) {
                var boundingRect = new BoundingRect$1(0, 0, 0, 0);
                boundingRect.copy(rect);
                mergedRepaintRects.push(boundingRect);
            }
            else {
                var isMerged = false;
                var minDeltaArea = Infinity;
                var bestRectToMergeIdx = 0;
                for (var i = 0; i < mergedRepaintRects.length; ++i) {
                    var mergedRect = mergedRepaintRects[i];
                    if (mergedRect.intersect(rect)) {
                        var pendingRect_1 = new BoundingRect$1(0, 0, 0, 0);
                        pendingRect_1.copy(mergedRect);
                        pendingRect_1.union(rect);
                        mergedRepaintRects[i] = pendingRect_1;
                        isMerged = true;
                        break;
                    }
                    else if (full) {
                        pendingRect.copy(rect);
                        pendingRect.union(mergedRect);
                        var aArea = rect.width * rect.height;
                        var bArea = mergedRect.width * mergedRect.height;
                        var pendingArea = pendingRect.width * pendingRect.height;
                        var deltaArea = pendingArea - aArea - bArea;
                        if (deltaArea < minDeltaArea) {
                            minDeltaArea = deltaArea;
                            bestRectToMergeIdx = i;
                        }
                    }
                }
                if (full) {
                    mergedRepaintRects[bestRectToMergeIdx].union(rect);
                    isMerged = true;
                }
                if (!isMerged) {
                    var boundingRect = new BoundingRect$1(0, 0, 0, 0);
                    boundingRect.copy(rect);
                    mergedRepaintRects.push(boundingRect);
                }
                if (!full) {
                    full = mergedRepaintRects.length >= maxRepaintRectCount;
                }
            }
        }
        for (var i = this.__startIndex; i < this.__endIndex; ++i) {
            var el = displayList[i];
            if (el) {
                var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
                var prevRect = el.__isRendered && ((el.__dirty & REDRAW_BIT) || !shouldPaint)
                    ? el.getPrevPaintRect()
                    : null;
                if (prevRect) {
                    addRectToMergePool(prevRect);
                }
                var curRect = shouldPaint && ((el.__dirty & REDRAW_BIT) || !el.__isRendered)
                    ? el.getPaintRect()
                    : null;
                if (curRect) {
                    addRectToMergePool(curRect);
                }
            }
        }
        for (var i = this.__prevStartIndex; i < this.__prevEndIndex; ++i) {
            var el = prevList[i];
            var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true);
            if (el && (!shouldPaint || !el.__zr) && el.__isRendered) {
                var prevRect = el.getPrevPaintRect();
                if (prevRect) {
                    addRectToMergePool(prevRect);
                }
            }
        }
        var hasIntersections;
        do {
            hasIntersections = false;
            for (var i = 0; i < mergedRepaintRects.length;) {
                if (mergedRepaintRects[i].isZero()) {
                    mergedRepaintRects.splice(i, 1);
                    continue;
                }
                for (var j = i + 1; j < mergedRepaintRects.length;) {
                    if (mergedRepaintRects[i].intersect(mergedRepaintRects[j])) {
                        hasIntersections = true;
                        mergedRepaintRects[i].union(mergedRepaintRects[j]);
                        mergedRepaintRects.splice(j, 1);
                    }
                    else {
                        j++;
                    }
                }
                i++;
            }
        } while (hasIntersections);
        this._paintRects = mergedRepaintRects;
        return mergedRepaintRects;
    };
    Layer.prototype.debugGetPaintRects = function () {
        return (this._paintRects || []).slice();
    };
    Layer.prototype.resize = function (width, height) {
        var dpr = this.dpr;
        var dom = this.dom;
        var domStyle = dom.style;
        var domBack = this.domBack;
        if (domStyle) {
            domStyle.width = width + 'px';
            domStyle.height = height + 'px';
        }
        dom.width = width * dpr;
        dom.height = height * dpr;
        if (domBack) {
            domBack.width = width * dpr;
            domBack.height = height * dpr;
            if (dpr !== 1) {
                this.ctxBack.scale(dpr, dpr);
            }
        }
    };
    Layer.prototype.clear = function (clearAll, clearColor, repaintRects) {
        var dom = this.dom;
        var ctx = this.ctx;
        var width = dom.width;
        var height = dom.height;
        clearColor = clearColor || this.clearColor;
        var haveMotionBLur = this.motionBlur && !clearAll;
        var lastFrameAlpha = this.lastFrameAlpha;
        var dpr = this.dpr;
        var self = this;
        if (haveMotionBLur) {
            if (!this.domBack) {
                this.createBackBuffer();
            }
            this.ctxBack.globalCompositeOperation = 'copy';
            this.ctxBack.drawImage(dom, 0, 0, width / dpr, height / dpr);
        }
        var domBack = this.domBack;
        function doClear(x, y, width, height) {
            ctx.clearRect(x, y, width, height);
            if (clearColor && clearColor !== 'transparent') {
                var clearColorGradientOrPattern = void 0;
                if (isGradientObject(clearColor)) {
                    var shouldCache = clearColor.global || (clearColor.__width === width
                        && clearColor.__height === height);
                    clearColorGradientOrPattern = shouldCache
                        && clearColor.__canvasGradient
                        || getCanvasGradient(ctx, clearColor, {
                            x: 0,
                            y: 0,
                            width: width,
                            height: height
                        });
                    clearColor.__canvasGradient = clearColorGradientOrPattern;
                    clearColor.__width = width;
                    clearColor.__height = height;
                }
                else if (isImagePatternObject(clearColor)) {
                    clearColor.scaleX = clearColor.scaleX || dpr;
                    clearColor.scaleY = clearColor.scaleY || dpr;
                    clearColorGradientOrPattern = createCanvasPattern(ctx, clearColor, {
                        dirty: function () {
                            self.setUnpainted();
                            self.__painter.refresh();
                        }
                    });
                }
                ctx.save();
                ctx.fillStyle = clearColorGradientOrPattern || clearColor;
                ctx.fillRect(x, y, width, height);
                ctx.restore();
            }
            if (haveMotionBLur) {
                ctx.save();
                ctx.globalAlpha = lastFrameAlpha;
                ctx.drawImage(domBack, x, y, width, height);
                ctx.restore();
            }
        }
        if (!repaintRects || haveMotionBLur) {
            doClear(0, 0, width, height);
        }
        else if (repaintRects.length) {
            each$4(repaintRects, function (rect) {
                doClear(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr);
            });
        }
    };
    return Layer;
}(Eventful$1));
const Layer$1 = Layer;

/* Injected with object hook! */

var HOVER_LAYER_ZLEVEL = 1e5;
var CANVAS_ZLEVEL = 314159;
var EL_AFTER_INCREMENTAL_INC = 0.01;
var INCREMENTAL_INC = 0.001;
function isLayerValid(layer) {
    if (!layer) {
        return false;
    }
    if (layer.__builtin__) {
        return true;
    }
    if (typeof (layer.resize) !== 'function'
        || typeof (layer.refresh) !== 'function') {
        return false;
    }
    return true;
}
function createRoot(width, height) {
    var domRoot = document.createElement('div');
    domRoot.style.cssText = [
        'position:relative',
        'width:' + width + 'px',
        'height:' + height + 'px',
        'padding:0',
        'margin:0',
        'border-width:0'
    ].join(';') + ';';
    return domRoot;
}
var CanvasPainter = (function () {
    function CanvasPainter(root, storage, opts, id) {
        this.type = 'canvas';
        this._zlevelList = [];
        this._prevDisplayList = [];
        this._layers = {};
        this._layerConfig = {};
        this._needsManuallyCompositing = false;
        this.type = 'canvas';
        var singleCanvas = !root.nodeName
            || root.nodeName.toUpperCase() === 'CANVAS';
        this._opts = opts = extend({}, opts || {});
        this.dpr = opts.devicePixelRatio || devicePixelRatio;
        this._singleCanvas = singleCanvas;
        this.root = root;
        var rootStyle = root.style;
        if (rootStyle) {
            disableUserSelect(root);
            root.innerHTML = '';
        }
        this.storage = storage;
        var zlevelList = this._zlevelList;
        this._prevDisplayList = [];
        var layers = this._layers;
        if (!singleCanvas) {
            this._width = getSize(root, 0, opts);
            this._height = getSize(root, 1, opts);
            var domRoot = this._domRoot = createRoot(this._width, this._height);
            root.appendChild(domRoot);
        }
        else {
            var rootCanvas = root;
            var width = rootCanvas.width;
            var height = rootCanvas.height;
            if (opts.width != null) {
                width = opts.width;
            }
            if (opts.height != null) {
                height = opts.height;
            }
            this.dpr = opts.devicePixelRatio || 1;
            rootCanvas.width = width * this.dpr;
            rootCanvas.height = height * this.dpr;
            this._width = width;
            this._height = height;
            var mainLayer = new Layer$1(rootCanvas, this, this.dpr);
            mainLayer.__builtin__ = true;
            mainLayer.initContext();
            layers[CANVAS_ZLEVEL] = mainLayer;
            mainLayer.zlevel = CANVAS_ZLEVEL;
            zlevelList.push(CANVAS_ZLEVEL);
            this._domRoot = root;
        }
    }
    CanvasPainter.prototype.getType = function () {
        return 'canvas';
    };
    CanvasPainter.prototype.isSingleCanvas = function () {
        return this._singleCanvas;
    };
    CanvasPainter.prototype.getViewportRoot = function () {
        return this._domRoot;
    };
    CanvasPainter.prototype.getViewportRootOffset = function () {
        var viewportRoot = this.getViewportRoot();
        if (viewportRoot) {
            return {
                offsetLeft: viewportRoot.offsetLeft || 0,
                offsetTop: viewportRoot.offsetTop || 0
            };
        }
    };
    CanvasPainter.prototype.refresh = function (paintAll) {
        var list = this.storage.getDisplayList(true);
        var prevList = this._prevDisplayList;
        var zlevelList = this._zlevelList;
        this._redrawId = Math.random();
        this._paintList(list, prevList, paintAll, this._redrawId);
        for (var i = 0; i < zlevelList.length; i++) {
            var z = zlevelList[i];
            var layer = this._layers[z];
            if (!layer.__builtin__ && layer.refresh) {
                var clearColor = i === 0 ? this._backgroundColor : null;
                layer.refresh(clearColor);
            }
        }
        if (this._opts.useDirtyRect) {
            this._prevDisplayList = list.slice();
        }
        return this;
    };
    CanvasPainter.prototype.refreshHover = function () {
        this._paintHoverList(this.storage.getDisplayList(false));
    };
    CanvasPainter.prototype._paintHoverList = function (list) {
        var len = list.length;
        var hoverLayer = this._hoverlayer;
        hoverLayer && hoverLayer.clear();
        if (!len) {
            return;
        }
        var scope = {
            inHover: true,
            viewWidth: this._width,
            viewHeight: this._height
        };
        var ctx;
        for (var i = 0; i < len; i++) {
            var el = list[i];
            if (el.__inHover) {
                if (!hoverLayer) {
                    hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL);
                }
                if (!ctx) {
                    ctx = hoverLayer.ctx;
                    ctx.save();
                }
                brush(ctx, el, scope, i === len - 1);
            }
        }
        if (ctx) {
            ctx.restore();
        }
    };
    CanvasPainter.prototype.getHoverLayer = function () {
        return this.getLayer(HOVER_LAYER_ZLEVEL);
    };
    CanvasPainter.prototype.paintOne = function (ctx, el) {
        brushSingle(ctx, el);
    };
    CanvasPainter.prototype._paintList = function (list, prevList, paintAll, redrawId) {
        if (this._redrawId !== redrawId) {
            return;
        }
        paintAll = paintAll || false;
        this._updateLayerStatus(list);
        var _a = this._doPaintList(list, prevList, paintAll), finished = _a.finished, needsRefreshHover = _a.needsRefreshHover;
        if (this._needsManuallyCompositing) {
            this._compositeManually();
        }
        if (needsRefreshHover) {
            this._paintHoverList(list);
        }
        if (!finished) {
            var self_1 = this;
            requestAnimationFrame$2(function () {
                self_1._paintList(list, prevList, paintAll, redrawId);
            });
        }
        else {
            this.eachLayer(function (layer) {
                layer.afterBrush && layer.afterBrush();
            });
        }
    };
    CanvasPainter.prototype._compositeManually = function () {
        var ctx = this.getLayer(CANVAS_ZLEVEL).ctx;
        var width = this._domRoot.width;
        var height = this._domRoot.height;
        ctx.clearRect(0, 0, width, height);
        this.eachBuiltinLayer(function (layer) {
            if (layer.virtual) {
                ctx.drawImage(layer.dom, 0, 0, width, height);
            }
        });
    };
    CanvasPainter.prototype._doPaintList = function (list, prevList, paintAll) {
        var _this = this;
        var layerList = [];
        var useDirtyRect = this._opts.useDirtyRect;
        for (var zi = 0; zi < this._zlevelList.length; zi++) {
            var zlevel = this._zlevelList[zi];
            var layer = this._layers[zlevel];
            if (layer.__builtin__
                && layer !== this._hoverlayer
                && (layer.__dirty || paintAll)) {
                layerList.push(layer);
            }
        }
        var finished = true;
        var needsRefreshHover = false;
        var _loop_1 = function (k) {
            var layer = layerList[k];
            var ctx = layer.ctx;
            var repaintRects = useDirtyRect
                && layer.createRepaintRects(list, prevList, this_1._width, this_1._height);
            var start = paintAll ? layer.__startIndex : layer.__drawIndex;
            var useTimer = !paintAll && layer.incremental && Date.now;
            var startTime = useTimer && Date.now();
            var clearColor = layer.zlevel === this_1._zlevelList[0]
                ? this_1._backgroundColor : null;
            if (layer.__startIndex === layer.__endIndex) {
                layer.clear(false, clearColor, repaintRects);
            }
            else if (start === layer.__startIndex) {
                var firstEl = list[start];
                if (!firstEl.incremental || !firstEl.notClear || paintAll) {
                    layer.clear(false, clearColor, repaintRects);
                }
            }
            if (start === -1) {
                console.error('For some unknown reason. drawIndex is -1');
                start = layer.__startIndex;
            }
            var i;
            var repaint = function (repaintRect) {
                var scope = {
                    inHover: false,
                    allClipped: false,
                    prevEl: null,
                    viewWidth: _this._width,
                    viewHeight: _this._height
                };
                for (i = start; i < layer.__endIndex; i++) {
                    var el = list[i];
                    if (el.__inHover) {
                        needsRefreshHover = true;
                    }
                    _this._doPaintEl(el, layer, useDirtyRect, repaintRect, scope, i === layer.__endIndex - 1);
                    if (useTimer) {
                        var dTime = Date.now() - startTime;
                        if (dTime > 15) {
                            break;
                        }
                    }
                }
                if (scope.prevElClipPaths) {
                    ctx.restore();
                }
            };
            if (repaintRects) {
                if (repaintRects.length === 0) {
                    i = layer.__endIndex;
                }
                else {
                    var dpr = this_1.dpr;
                    for (var r = 0; r < repaintRects.length; ++r) {
                        var rect = repaintRects[r];
                        ctx.save();
                        ctx.beginPath();
                        ctx.rect(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr);
                        ctx.clip();
                        repaint(rect);
                        ctx.restore();
                    }
                }
            }
            else {
                ctx.save();
                repaint();
                ctx.restore();
            }
            layer.__drawIndex = i;
            if (layer.__drawIndex < layer.__endIndex) {
                finished = false;
            }
        };
        var this_1 = this;
        for (var k = 0; k < layerList.length; k++) {
            _loop_1(k);
        }
        if (env$1.wxa) {
            each$4(this._layers, function (layer) {
                if (layer && layer.ctx && layer.ctx.draw) {
                    layer.ctx.draw();
                }
            });
        }
        return {
            finished: finished,
            needsRefreshHover: needsRefreshHover
        };
    };
    CanvasPainter.prototype._doPaintEl = function (el, currentLayer, useDirtyRect, repaintRect, scope, isLast) {
        var ctx = currentLayer.ctx;
        if (useDirtyRect) {
            var paintRect = el.getPaintRect();
            if (!repaintRect || paintRect && paintRect.intersect(repaintRect)) {
                brush(ctx, el, scope, isLast);
                el.setPrevPaintRect(paintRect);
            }
        }
        else {
            brush(ctx, el, scope, isLast);
        }
    };
    CanvasPainter.prototype.getLayer = function (zlevel, virtual) {
        if (this._singleCanvas && !this._needsManuallyCompositing) {
            zlevel = CANVAS_ZLEVEL;
        }
        var layer = this._layers[zlevel];
        if (!layer) {
            layer = new Layer$1('zr_' + zlevel, this, this.dpr);
            layer.zlevel = zlevel;
            layer.__builtin__ = true;
            if (this._layerConfig[zlevel]) {
                merge(layer, this._layerConfig[zlevel], true);
            }
            else if (this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC]) {
                merge(layer, this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC], true);
            }
            if (virtual) {
                layer.virtual = virtual;
            }
            this.insertLayer(zlevel, layer);
            layer.initContext();
        }
        return layer;
    };
    CanvasPainter.prototype.insertLayer = function (zlevel, layer) {
        var layersMap = this._layers;
        var zlevelList = this._zlevelList;
        var len = zlevelList.length;
        var domRoot = this._domRoot;
        var prevLayer = null;
        var i = -1;
        if (layersMap[zlevel]) {
            return;
        }
        if (!isLayerValid(layer)) {
            return;
        }
        if (len > 0 && zlevel > zlevelList[0]) {
            for (i = 0; i < len - 1; i++) {
                if (zlevelList[i] < zlevel
                    && zlevelList[i + 1] > zlevel) {
                    break;
                }
            }
            prevLayer = layersMap[zlevelList[i]];
        }
        zlevelList.splice(i + 1, 0, zlevel);
        layersMap[zlevel] = layer;
        if (!layer.virtual) {
            if (prevLayer) {
                var prevDom = prevLayer.dom;
                if (prevDom.nextSibling) {
                    domRoot.insertBefore(layer.dom, prevDom.nextSibling);
                }
                else {
                    domRoot.appendChild(layer.dom);
                }
            }
            else {
                if (domRoot.firstChild) {
                    domRoot.insertBefore(layer.dom, domRoot.firstChild);
                }
                else {
                    domRoot.appendChild(layer.dom);
                }
            }
        }
        layer.__painter = this;
    };
    CanvasPainter.prototype.eachLayer = function (cb, context) {
        var zlevelList = this._zlevelList;
        for (var i = 0; i < zlevelList.length; i++) {
            var z = zlevelList[i];
            cb.call(context, this._layers[z], z);
        }
    };
    CanvasPainter.prototype.eachBuiltinLayer = function (cb, context) {
        var zlevelList = this._zlevelList;
        for (var i = 0; i < zlevelList.length; i++) {
            var z = zlevelList[i];
            var layer = this._layers[z];
            if (layer.__builtin__) {
                cb.call(context, layer, z);
            }
        }
    };
    CanvasPainter.prototype.eachOtherLayer = function (cb, context) {
        var zlevelList = this._zlevelList;
        for (var i = 0; i < zlevelList.length; i++) {
            var z = zlevelList[i];
            var layer = this._layers[z];
            if (!layer.__builtin__) {
                cb.call(context, layer, z);
            }
        }
    };
    CanvasPainter.prototype.getLayers = function () {
        return this._layers;
    };
    CanvasPainter.prototype._updateLayerStatus = function (list) {
        this.eachBuiltinLayer(function (layer, z) {
            layer.__dirty = layer.__used = false;
        });
        function updatePrevLayer(idx) {
            if (prevLayer) {
                if (prevLayer.__endIndex !== idx) {
                    prevLayer.__dirty = true;
                }
                prevLayer.__endIndex = idx;
            }
        }
        if (this._singleCanvas) {
            for (var i_1 = 1; i_1 < list.length; i_1++) {
                var el = list[i_1];
                if (el.zlevel !== list[i_1 - 1].zlevel || el.incremental) {
                    this._needsManuallyCompositing = true;
                    break;
                }
            }
        }
        var prevLayer = null;
        var incrementalLayerCount = 0;
        var prevZlevel;
        var i;
        for (i = 0; i < list.length; i++) {
            var el = list[i];
            var zlevel = el.zlevel;
            var layer = void 0;
            if (prevZlevel !== zlevel) {
                prevZlevel = zlevel;
                incrementalLayerCount = 0;
            }
            if (el.incremental) {
                layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing);
                layer.incremental = true;
                incrementalLayerCount = 1;
            }
            else {
                layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing);
            }
            if (!layer.__builtin__) {
                logError('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id);
            }
            if (layer !== prevLayer) {
                layer.__used = true;
                if (layer.__startIndex !== i) {
                    layer.__dirty = true;
                }
                layer.__startIndex = i;
                if (!layer.incremental) {
                    layer.__drawIndex = i;
                }
                else {
                    layer.__drawIndex = -1;
                }
                updatePrevLayer(i);
                prevLayer = layer;
            }
            if ((el.__dirty & REDRAW_BIT) && !el.__inHover) {
                layer.__dirty = true;
                if (layer.incremental && layer.__drawIndex < 0) {
                    layer.__drawIndex = i;
                }
            }
        }
        updatePrevLayer(i);
        this.eachBuiltinLayer(function (layer, z) {
            if (!layer.__used && layer.getElementCount() > 0) {
                layer.__dirty = true;
                layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0;
            }
            if (layer.__dirty && layer.__drawIndex < 0) {
                layer.__drawIndex = layer.__startIndex;
            }
        });
    };
    CanvasPainter.prototype.clear = function () {
        this.eachBuiltinLayer(this._clearLayer);
        return this;
    };
    CanvasPainter.prototype._clearLayer = function (layer) {
        layer.clear();
    };
    CanvasPainter.prototype.setBackgroundColor = function (backgroundColor) {
        this._backgroundColor = backgroundColor;
        each$4(this._layers, function (layer) {
            layer.setUnpainted();
        });
    };
    CanvasPainter.prototype.configLayer = function (zlevel, config) {
        if (config) {
            var layerConfig = this._layerConfig;
            if (!layerConfig[zlevel]) {
                layerConfig[zlevel] = config;
            }
            else {
                merge(layerConfig[zlevel], config, true);
            }
            for (var i = 0; i < this._zlevelList.length; i++) {
                var _zlevel = this._zlevelList[i];
                if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) {
                    var layer = this._layers[_zlevel];
                    merge(layer, layerConfig[zlevel], true);
                }
            }
        }
    };
    CanvasPainter.prototype.delLayer = function (zlevel) {
        var layers = this._layers;
        var zlevelList = this._zlevelList;
        var layer = layers[zlevel];
        if (!layer) {
            return;
        }
        layer.dom.parentNode.removeChild(layer.dom);
        delete layers[zlevel];
        zlevelList.splice(indexOf(zlevelList, zlevel), 1);
    };
    CanvasPainter.prototype.resize = function (width, height) {
        if (!this._domRoot.style) {
            if (width == null || height == null) {
                return;
            }
            this._width = width;
            this._height = height;
            this.getLayer(CANVAS_ZLEVEL).resize(width, height);
        }
        else {
            var domRoot = this._domRoot;
            domRoot.style.display = 'none';
            var opts = this._opts;
            var root = this.root;
            width != null && (opts.width = width);
            height != null && (opts.height = height);
            width = getSize(root, 0, opts);
            height = getSize(root, 1, opts);
            domRoot.style.display = '';
            if (this._width !== width || height !== this._height) {
                domRoot.style.width = width + 'px';
                domRoot.style.height = height + 'px';
                for (var id in this._layers) {
                    if (this._layers.hasOwnProperty(id)) {
                        this._layers[id].resize(width, height);
                    }
                }
                this.refresh(true);
            }
            this._width = width;
            this._height = height;
        }
        return this;
    };
    CanvasPainter.prototype.clearLayer = function (zlevel) {
        var layer = this._layers[zlevel];
        if (layer) {
            layer.clear();
        }
    };
    CanvasPainter.prototype.dispose = function () {
        this.root.innerHTML = '';
        this.root =
            this.storage =
                this._domRoot =
                    this._layers = null;
    };
    CanvasPainter.prototype.getRenderedCanvas = function (opts) {
        opts = opts || {};
        if (this._singleCanvas && !this._compositeManually) {
            return this._layers[CANVAS_ZLEVEL].dom;
        }
        var imageLayer = new Layer$1('image', this, opts.pixelRatio || this.dpr);
        imageLayer.initContext();
        imageLayer.clear(false, opts.backgroundColor || this._backgroundColor);
        var ctx = imageLayer.ctx;
        if (opts.pixelRatio <= this.dpr) {
            this.refresh();
            var width_1 = imageLayer.dom.width;
            var height_1 = imageLayer.dom.height;
            this.eachLayer(function (layer) {
                if (layer.__builtin__) {
                    ctx.drawImage(layer.dom, 0, 0, width_1, height_1);
                }
                else if (layer.renderToCanvas) {
                    ctx.save();
                    layer.renderToCanvas(ctx);
                    ctx.restore();
                }
            });
        }
        else {
            var scope = {
                inHover: false,
                viewWidth: this._width,
                viewHeight: this._height
            };
            var displayList = this.storage.getDisplayList(true);
            for (var i = 0, len = displayList.length; i < len; i++) {
                var el = displayList[i];
                brush(ctx, el, scope, i === len - 1);
            }
        }
        return imageLayer.dom;
    };
    CanvasPainter.prototype.getWidth = function () {
        return this._width;
    };
    CanvasPainter.prototype.getHeight = function () {
        return this._height;
    };
    return CanvasPainter;
}());
const CanvasPainter$1 = CanvasPainter;

/* Injected with object hook! */

function install$9(registers) {
  registers.registerPainter('canvas', CanvasPainter$1);
}
/* Injected with object hook! */

/**
 * @return label string. Not null/undefined
 */

function getDefaultLabel(data, dataIndex) {
  var labelDims = data.mapDimensionsAll('defaultedLabel');
  var len = labelDims.length; // Simple optimization (in lots of cases, label dims length is 1)

  if (len === 1) {
    var rawVal = retrieveRawValue(data, dataIndex, labelDims[0]);
    return rawVal != null ? rawVal + '' : null;
  } else if (len) {
    var vals = [];

    for (var i = 0; i < labelDims.length; i++) {
      vals.push(retrieveRawValue(data, dataIndex, labelDims[i]));
    }

    return vals.join(' ');
  }
}
function getDefaultInterpolatedLabel(data, interpolatedValue) {
  var labelDims = data.mapDimensionsAll('defaultedLabel');

  if (!isArray(interpolatedValue)) {
    return interpolatedValue + '';
  }

  var vals = [];

  for (var i = 0; i < labelDims.length; i++) {
    var dimIndex = data.getDimensionIndex(labelDims[i]);

    if (dimIndex >= 0) {
      vals.push(interpolatedValue[dimIndex]);
    }
  }

  return vals.join(' ');
}
/* Injected with object hook! */

function createGridClipPath(cartesian, hasAnimation, seriesModel, done, during) {
  var rect = cartesian.getArea();
  var x = rect.x;
  var y = rect.y;
  var width = rect.width;
  var height = rect.height;
  var lineWidth = seriesModel.get(['lineStyle', 'width']) || 2; // Expand the clip path a bit to avoid the border is clipped and looks thinner

  x -= lineWidth / 2;
  y -= lineWidth / 2;
  width += lineWidth;
  height += lineWidth; // fix: https://github.com/apache/incubator-echarts/issues/11369

  x = Math.floor(x);
  width = Math.round(width);
  var clipPath = new Rect$1({
    shape: {
      x: x,
      y: y,
      width: width,
      height: height
    }
  });

  if (hasAnimation) {
    var baseAxis = cartesian.getBaseAxis();
    var isHorizontal = baseAxis.isHorizontal();
    var isAxisInversed = baseAxis.inverse;

    if (isHorizontal) {
      if (isAxisInversed) {
        clipPath.shape.x += width;
      }

      clipPath.shape.width = 0;
    } else {
      if (!isAxisInversed) {
        clipPath.shape.y += height;
      }

      clipPath.shape.height = 0;
    }

    var duringCb = isFunction(during) ? function (percent) {
      during(percent, clipPath);
    } : null;
    initProps(clipPath, {
      shape: {
        width: width,
        height: height,
        x: x,
        y: y
      }
    }, seriesModel, null, done, duringCb);
  }

  return clipPath;
}

function createPolarClipPath(polar, hasAnimation, seriesModel) {
  var sectorArea = polar.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent.

  var r0 = round$1(sectorArea.r0, 1);
  var r = round$1(sectorArea.r, 1);
  var clipPath = new Sector$1({
    shape: {
      cx: round$1(polar.cx, 1),
      cy: round$1(polar.cy, 1),
      r0: r0,
      r: r,
      startAngle: sectorArea.startAngle,
      endAngle: sectorArea.endAngle,
      clockwise: sectorArea.clockwise
    }
  });

  if (hasAnimation) {
    var isRadial = polar.getBaseAxis().dim === 'angle';

    if (isRadial) {
      clipPath.shape.endAngle = sectorArea.startAngle;
    } else {
      clipPath.shape.r = r0;
    }

    initProps(clipPath, {
      shape: {
        endAngle: sectorArea.endAngle,
        r: r
      }
    }, seriesModel);
  }

  return clipPath;
}

function createClipPath(coordSys, hasAnimation, seriesModel, done, during) {
  if (!coordSys) {
    return null;
  } else if (coordSys.type === 'polar') {
    return createPolarClipPath(coordSys, hasAnimation, seriesModel);
  } else if (coordSys.type === 'cartesian2d') {
    return createGridClipPath(coordSys, hasAnimation, seriesModel, done, during);
  }

  return null;
}
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function isCoordinateSystemType(coordSys, type) {
  return coordSys.type === type;
}
/* Injected with object hook! */

var samplers = {
  average: function (frame) {
    var sum = 0;
    var count = 0;

    for (var i = 0; i < frame.length; i++) {
      if (!isNaN(frame[i])) {
        sum += frame[i];
        count++;
      }
    } // Return NaN if count is 0


    return count === 0 ? NaN : sum / count;
  },
  sum: function (frame) {
    var sum = 0;

    for (var i = 0; i < frame.length; i++) {
      // Ignore NaN
      sum += frame[i] || 0;
    }

    return sum;
  },
  max: function (frame) {
    var max = -Infinity;

    for (var i = 0; i < frame.length; i++) {
      frame[i] > max && (max = frame[i]);
    } // NaN will cause illegal axis extent.


    return isFinite(max) ? max : NaN;
  },
  min: function (frame) {
    var min = Infinity;

    for (var i = 0; i < frame.length; i++) {
      frame[i] < min && (min = frame[i]);
    } // NaN will cause illegal axis extent.


    return isFinite(min) ? min : NaN;
  },
  // TODO
  // Median
  nearest: function (frame) {
    return frame[0];
  }
};

var indexSampler = function (frame) {
  return Math.round(frame.length / 2);
};

function dataSample(seriesType) {
  return {
    seriesType: seriesType,
    // FIXME:TS never used, so comment it
    // modifyOutputEnd: true,
    reset: function (seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var sampling = seriesModel.get('sampling');
      var coordSys = seriesModel.coordinateSystem;
      var count = data.count(); // Only cartesian2d support down sampling. Disable it when there is few data.

      if (count > 10 && coordSys.type === 'cartesian2d' && sampling) {
        var baseAxis = coordSys.getBaseAxis();
        var valueAxis = coordSys.getOtherAxis(baseAxis);
        var extent = baseAxis.getExtent();
        var dpr = api.getDevicePixelRatio(); // Coordinste system has been resized

        var size = Math.abs(extent[1] - extent[0]) * (dpr || 1);
        var rate = Math.round(count / size);

        if (isFinite(rate) && rate > 1) {
          if (sampling === 'lttb') {
            seriesModel.setData(data.lttbDownSample(data.mapDimension(valueAxis.dim), 1 / rate));
          }

          var sampler = void 0;

          if (isString(sampling)) {
            sampler = samplers[sampling];
          } else if (isFunction(sampling)) {
            sampler = sampling;
          }

          if (sampler) {
            // Only support sample the first dim mapped from value axis.
            seriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler));
          }
        }
      }
    }
  };
}
/* Injected with object hook! */

var BaseBarSeriesModel =
/** @class */
function (_super) {
  __extends(BaseBarSeriesModel, _super);

  function BaseBarSeriesModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = BaseBarSeriesModel.type;
    return _this;
  }

  BaseBarSeriesModel.prototype.getInitialData = function (option, ecModel) {
    return createSeriesData(null, this, {
      useEncodeDefaulter: true
    });
  };

  BaseBarSeriesModel.prototype.getMarkerPosition = function (value, dims, startingAtTick) {
    var coordSys = this.coordinateSystem;

    if (coordSys && coordSys.clampData) {
      // PENDING if clamp ?
      var clampData_1 = coordSys.clampData(value);
      var pt_1 = coordSys.dataToPoint(clampData_1);

      if (startingAtTick) {
        each$4(coordSys.getAxes(), function (axis, idx) {
          // If axis type is category, use tick coords instead
          if (axis.type === 'category' && dims != null) {
            var tickCoords = axis.getTicksCoords();
            var targetTickId = clampData_1[idx]; // The index of rightmost tick of markArea is 1 larger than x1/y1 index

            var isEnd = dims[idx] === 'x1' || dims[idx] === 'y1';

            if (isEnd) {
              targetTickId += 1;
            } // The only contains one tick, tickCoords is
            // like [{coord: 0, tickValue: 0}, {coord: 0}]
            // to the length should always be larger than 1


            if (tickCoords.length < 2) {
              return;
            } else if (tickCoords.length === 2) {
              // The left value and right value of the axis are
              // the same. coord is 0 in both items. Use the max
              // value of the axis as the coord
              pt_1[idx] = axis.toGlobalCoord(axis.getExtent()[isEnd ? 1 : 0]);
              return;
            }

            var leftCoord = void 0;
            var coord = void 0;
            var stepTickValue = 1;

            for (var i = 0; i < tickCoords.length; i++) {
              var tickCoord = tickCoords[i].coord; // The last item of tickCoords doesn't contain
              // tickValue

              var tickValue = i === tickCoords.length - 1 ? tickCoords[i - 1].tickValue + stepTickValue : tickCoords[i].tickValue;

              if (tickValue === targetTickId) {
                coord = tickCoord;
                break;
              } else if (tickValue < targetTickId) {
                leftCoord = tickCoord;
              } else if (leftCoord != null && tickValue > targetTickId) {
                coord = (tickCoord + leftCoord) / 2;
                break;
              }

              if (i === 1) {
                // Here we assume the step of category axes is
                // the same
                stepTickValue = tickValue - tickCoords[0].tickValue;
              }
            }

            if (coord == null) {
              if (!leftCoord) {
                // targetTickId is smaller than all tick ids in the
                // visible area, use the leftmost tick coord
                coord = tickCoords[0].coord;
              } else if (leftCoord) {
                // targetTickId is larger than all tick ids in the
                // visible area, use the rightmost tick coord
                coord = tickCoords[tickCoords.length - 1].coord;
              }
            }

            pt_1[idx] = axis.toGlobalCoord(coord);
          }
        });
      } else {
        var data = this.getData();
        var offset = data.getLayout('offset');
        var size = data.getLayout('size');
        var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1;
        pt_1[offsetIndex] += offset + size / 2;
      }

      return pt_1;
    }

    return [NaN, NaN];
  };

  BaseBarSeriesModel.type = 'series.__base_bar__';
  BaseBarSeriesModel.defaultOption = {
    // zlevel: 0,
    z: 2,
    coordinateSystem: 'cartesian2d',
    legendHoverLink: true,
    // stack: null
    // Cartesian coordinate system
    // xAxisIndex: 0,
    // yAxisIndex: 0,
    barMinHeight: 0,
    barMinAngle: 0,
    // cursor: null,
    large: false,
    largeThreshold: 400,
    progressive: 3e3,
    progressiveChunkMode: 'mod'
  };
  return BaseBarSeriesModel;
}(SeriesModel$1);

SeriesModel$1.registerClass(BaseBarSeriesModel);
const BaseBarSeriesModel$1 = BaseBarSeriesModel;
/* Injected with object hook! */

var BarSeriesModel =
/** @class */
function (_super) {
  __extends(BarSeriesModel, _super);

  function BarSeriesModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = BarSeriesModel.type;
    return _this;
  }

  BarSeriesModel.prototype.getInitialData = function () {
    return createSeriesData(null, this, {
      useEncodeDefaulter: true,
      createInvertedIndices: !!this.get('realtimeSort', true) || null
    });
  };
  /**
   * @override
   */


  BarSeriesModel.prototype.getProgressive = function () {
    // Do not support progressive in normal mode.
    return this.get('large') ? this.get('progressive') : false;
  };
  /**
   * @override
   */


  BarSeriesModel.prototype.getProgressiveThreshold = function () {
    // Do not support progressive in normal mode.
    var progressiveThreshold = this.get('progressiveThreshold');
    var largeThreshold = this.get('largeThreshold');

    if (largeThreshold > progressiveThreshold) {
      progressiveThreshold = largeThreshold;
    }

    return progressiveThreshold;
  };

  BarSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) {
    return selectors.rect(data.getItemLayout(dataIndex));
  };

  BarSeriesModel.type = 'series.bar';
  BarSeriesModel.dependencies = ['grid', 'polar'];
  BarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel$1.defaultOption, {
    // If clipped
    // Only available on cartesian2d
    clip: true,
    roundCap: false,
    showBackground: false,
    backgroundStyle: {
      color: 'rgba(180, 180, 180, 0.2)',
      borderColor: null,
      borderWidth: 0,
      borderType: 'solid',
      borderRadius: 0,
      shadowBlur: 0,
      shadowColor: null,
      shadowOffsetX: 0,
      shadowOffsetY: 0,
      opacity: 1
    },
    select: {
      itemStyle: {
        borderColor: '#212121'
      }
    },
    realtimeSort: false
  });
  return BarSeriesModel;
}(BaseBarSeriesModel$1);

const BarSeries = BarSeriesModel;
/* Injected with object hook! */

/**
 * Sausage: similar to sector, but have half circle on both sides
 */

var SausageShape =
/** @class */
function () {
  function SausageShape() {
    this.cx = 0;
    this.cy = 0;
    this.r0 = 0;
    this.r = 0;
    this.startAngle = 0;
    this.endAngle = Math.PI * 2;
    this.clockwise = true;
  }

  return SausageShape;
}();

var SausagePath =
/** @class */
function (_super) {
  __extends(SausagePath, _super);

  function SausagePath(opts) {
    var _this = _super.call(this, opts) || this;

    _this.type = 'sausage';
    return _this;
  }

  SausagePath.prototype.getDefaultShape = function () {
    return new SausageShape();
  };

  SausagePath.prototype.buildPath = function (ctx, shape) {
    var cx = shape.cx;
    var cy = shape.cy;
    var r0 = Math.max(shape.r0 || 0, 0);
    var r = Math.max(shape.r, 0);
    var dr = (r - r0) * 0.5;
    var rCenter = r0 + dr;
    var startAngle = shape.startAngle;
    var endAngle = shape.endAngle;
    var clockwise = shape.clockwise;
    var PI2 = Math.PI * 2;
    var lessThanCircle = clockwise ? endAngle - startAngle < PI2 : startAngle - endAngle < PI2;

    if (!lessThanCircle) {
      // Normalize angles
      startAngle = endAngle - (clockwise ? PI2 : -PI2);
    }

    var unitStartX = Math.cos(startAngle);
    var unitStartY = Math.sin(startAngle);
    var unitEndX = Math.cos(endAngle);
    var unitEndY = Math.sin(endAngle);

    if (lessThanCircle) {
      ctx.moveTo(unitStartX * r0 + cx, unitStartY * r0 + cy);
      ctx.arc(unitStartX * rCenter + cx, unitStartY * rCenter + cy, dr, -Math.PI + startAngle, startAngle, !clockwise);
    } else {
      ctx.moveTo(unitStartX * r + cx, unitStartY * r + cy);
    }

    ctx.arc(cx, cy, r, startAngle, endAngle, !clockwise);
    ctx.arc(unitEndX * rCenter + cx, unitEndY * rCenter + cy, dr, endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise);

    if (r0 !== 0) {
      ctx.arc(cx, cy, r0, endAngle, startAngle, clockwise);
    } // ctx.closePath();

  };

  return SausagePath;
}(Path$1);

const Sausage = SausagePath;
/* Injected with object hook! */

function createSectorCalculateTextPosition(positionMapping, opts) {
  opts = opts || {};
  var isRoundCap = opts.isRoundCap;
  return function (out, opts, boundingRect) {
    var textPosition = opts.position;

    if (!textPosition || textPosition instanceof Array) {
      return calculateTextPosition(out, opts, boundingRect);
    }

    var mappedSectorPosition = positionMapping(textPosition);
    var distance = opts.distance != null ? opts.distance : 5;
    var sector = this.shape;
    var cx = sector.cx;
    var cy = sector.cy;
    var r = sector.r;
    var r0 = sector.r0;
    var middleR = (r + r0) / 2;
    var startAngle = sector.startAngle;
    var endAngle = sector.endAngle;
    var middleAngle = (startAngle + endAngle) / 2;
    var extraDist = isRoundCap ? Math.abs(r - r0) / 2 : 0;
    var mathCos = Math.cos;
    var mathSin = Math.sin; // base position: top-left

    var x = cx + r * mathCos(startAngle);
    var y = cy + r * mathSin(startAngle);
    var textAlign = 'left';
    var textVerticalAlign = 'top';

    switch (mappedSectorPosition) {
      case 'startArc':
        x = cx + (r0 - distance) * mathCos(middleAngle);
        y = cy + (r0 - distance) * mathSin(middleAngle);
        textAlign = 'center';
        textVerticalAlign = 'top';
        break;

      case 'insideStartArc':
        x = cx + (r0 + distance) * mathCos(middleAngle);
        y = cy + (r0 + distance) * mathSin(middleAngle);
        textAlign = 'center';
        textVerticalAlign = 'bottom';
        break;

      case 'startAngle':
        x = cx + middleR * mathCos(startAngle) + adjustAngleDistanceX(startAngle, distance + extraDist, false);
        y = cy + middleR * mathSin(startAngle) + adjustAngleDistanceY(startAngle, distance + extraDist, false);
        textAlign = 'right';
        textVerticalAlign = 'middle';
        break;

      case 'insideStartAngle':
        x = cx + middleR * mathCos(startAngle) + adjustAngleDistanceX(startAngle, -distance + extraDist, false);
        y = cy + middleR * mathSin(startAngle) + adjustAngleDistanceY(startAngle, -distance + extraDist, false);
        textAlign = 'left';
        textVerticalAlign = 'middle';
        break;

      case 'middle':
        x = cx + middleR * mathCos(middleAngle);
        y = cy + middleR * mathSin(middleAngle);
        textAlign = 'center';
        textVerticalAlign = 'middle';
        break;

      case 'endArc':
        x = cx + (r + distance) * mathCos(middleAngle);
        y = cy + (r + distance) * mathSin(middleAngle);
        textAlign = 'center';
        textVerticalAlign = 'bottom';
        break;

      case 'insideEndArc':
        x = cx + (r - distance) * mathCos(middleAngle);
        y = cy + (r - distance) * mathSin(middleAngle);
        textAlign = 'center';
        textVerticalAlign = 'top';
        break;

      case 'endAngle':
        x = cx + middleR * mathCos(endAngle) + adjustAngleDistanceX(endAngle, distance + extraDist, true);
        y = cy + middleR * mathSin(endAngle) + adjustAngleDistanceY(endAngle, distance + extraDist, true);
        textAlign = 'left';
        textVerticalAlign = 'middle';
        break;

      case 'insideEndAngle':
        x = cx + middleR * mathCos(endAngle) + adjustAngleDistanceX(endAngle, -distance + extraDist, true);
        y = cy + middleR * mathSin(endAngle) + adjustAngleDistanceY(endAngle, -distance + extraDist, true);
        textAlign = 'right';
        textVerticalAlign = 'middle';
        break;

      default:
        return calculateTextPosition(out, opts, boundingRect);
    }

    out = out || {};
    out.x = x;
    out.y = y;
    out.align = textAlign;
    out.verticalAlign = textVerticalAlign;
    return out;
  };
}
function setSectorTextRotation(sector, textPosition, positionMapping, rotateType) {
  if (isNumber(rotateType)) {
    // user-set rotation
    sector.setTextConfig({
      rotation: rotateType
    });
    return;
  } else if (isArray(textPosition)) {
    // user-set position, use 0 as auto rotation
    sector.setTextConfig({
      rotation: 0
    });
    return;
  }

  var shape = sector.shape;
  var startAngle = shape.clockwise ? shape.startAngle : shape.endAngle;
  var endAngle = shape.clockwise ? shape.endAngle : shape.startAngle;
  var middleAngle = (startAngle + endAngle) / 2;
  var anchorAngle;
  var mappedSectorPosition = positionMapping(textPosition);

  switch (mappedSectorPosition) {
    case 'startArc':
    case 'insideStartArc':
    case 'middle':
    case 'insideEndArc':
    case 'endArc':
      anchorAngle = middleAngle;
      break;

    case 'startAngle':
    case 'insideStartAngle':
      anchorAngle = startAngle;
      break;

    case 'endAngle':
    case 'insideEndAngle':
      anchorAngle = endAngle;
      break;

    default:
      sector.setTextConfig({
        rotation: 0
      });
      return;
  }

  var rotate = Math.PI * 1.5 - anchorAngle;
  /**
   * TODO: labels with rotate > Math.PI / 2 should be rotate another
   * half round flipped to increase readability. However, only middle
   * position supports this for now, because in other positions, the
   * anchor point is not at the center of the text, so the positions
   * after rotating is not as expected.
   */

  if (mappedSectorPosition === 'middle' && rotate > Math.PI / 2 && rotate < Math.PI * 1.5) {
    rotate -= Math.PI;
  }

  sector.setTextConfig({
    rotation: rotate
  });
}

function adjustAngleDistanceX(angle, distance, isEnd) {
  return distance * Math.sin(angle) * (isEnd ? -1 : 1);
}

function adjustAngleDistanceY(angle, distance, isEnd) {
  return distance * Math.cos(angle) * (isEnd ? 1 : -1);
}
/* Injected with object hook! */

function getSectorCornerRadius(model, shape, zeroIfNull) {
  var cornerRadius = model.get('borderRadius');

  if (cornerRadius == null) {
    return zeroIfNull ? {
      cornerRadius: 0
    } : null;
  }

  if (!isArray(cornerRadius)) {
    cornerRadius = [cornerRadius, cornerRadius, cornerRadius, cornerRadius];
  }

  var dr = Math.abs(shape.r || 0 - shape.r0 || 0);
  return {
    cornerRadius: map$1(cornerRadius, function (cr) {
      return parsePercent$1(cr, dr);
    })
  };
}
/* Injected with object hook! */

var mathMax = Math.max;
var mathMin = Math.min;

function getClipArea(coord, data) {
  var coordSysClipArea = coord.getArea && coord.getArea();

  if (isCoordinateSystemType(coord, 'cartesian2d')) {
    var baseAxis = coord.getBaseAxis(); // When boundaryGap is false or using time axis. bar may exceed the grid.
    // We should not clip this part.
    // See test/bar2.html

    if (baseAxis.type !== 'category' || !baseAxis.onBand) {
      var expandWidth = data.getLayout('bandWidth');

      if (baseAxis.isHorizontal()) {
        coordSysClipArea.x -= expandWidth;
        coordSysClipArea.width += expandWidth * 2;
      } else {
        coordSysClipArea.y -= expandWidth;
        coordSysClipArea.height += expandWidth * 2;
      }
    }
  }

  return coordSysClipArea;
}

var BarView =
/** @class */
function (_super) {
  __extends(BarView, _super);

  function BarView() {
    var _this = _super.call(this) || this;

    _this.type = BarView.type;
    _this._isFirstFrame = true;
    return _this;
  }

  BarView.prototype.render = function (seriesModel, ecModel, api, payload) {
    this._model = seriesModel;

    this._removeOnRenderedListener(api);

    this._updateDrawMode(seriesModel);

    var coordinateSystemType = seriesModel.get('coordinateSystem');

    if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') {
      // Clear previously rendered progressive elements.
      this._progressiveEls = null;
      this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api, payload);
    }
  };

  BarView.prototype.incrementalPrepareRender = function (seriesModel) {
    this._clear();

    this._updateDrawMode(seriesModel); // incremental also need to clip, otherwise might be overlow.
    // But must not set clip in each frame, otherwise all of the children will be marked redraw.


    this._updateLargeClip(seriesModel);
  };

  BarView.prototype.incrementalRender = function (params, seriesModel) {
    // Reset
    this._progressiveEls = []; // Do not support progressive in normal mode.

    this._incrementalRenderLarge(params, seriesModel);
  };

  BarView.prototype.eachRendered = function (cb) {
    traverseElements(this._progressiveEls || this.group, cb);
  };

  BarView.prototype._updateDrawMode = function (seriesModel) {
    var isLargeDraw = seriesModel.pipelineContext.large;

    if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) {
      this._isLargeDraw = isLargeDraw;

      this._clear();
    }
  };

  BarView.prototype._renderNormal = function (seriesModel, ecModel, api, payload) {
    var group = this.group;
    var data = seriesModel.getData();
    var oldData = this._data;
    var coord = seriesModel.coordinateSystem;
    var baseAxis = coord.getBaseAxis();
    var isHorizontalOrRadial;

    if (coord.type === 'cartesian2d') {
      isHorizontalOrRadial = baseAxis.isHorizontal();
    } else if (coord.type === 'polar') {
      isHorizontalOrRadial = baseAxis.dim === 'angle';
    }

    var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;
    var realtimeSortCfg = shouldRealtimeSort(seriesModel, coord);

    if (realtimeSortCfg) {
      this._enableRealtimeSort(realtimeSortCfg, data, api);
    }

    var needsClip = seriesModel.get('clip', true) || realtimeSortCfg;
    var coordSysClipArea = getClipArea(coord, data); // If there is clipPath created in large mode. Remove it.

    group.removeClipPath(); // We don't use clipPath in normal mode because we needs a perfect animation
    // And don't want the label are clipped.

    var roundCap = seriesModel.get('roundCap', true);
    var drawBackground = seriesModel.get('showBackground', true);
    var backgroundModel = seriesModel.getModel('backgroundStyle');
    var barBorderRadius = backgroundModel.get('borderRadius') || 0;
    var bgEls = [];
    var oldBgEls = this._backgroundEls;
    var isInitSort = payload && payload.isInitSort;
    var isChangeOrder = payload && payload.type === 'changeAxisOrder';

    function createBackground(dataIndex) {
      var bgLayout = getLayout[coord.type](data, dataIndex);
      var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
      bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius.

      if (coord.type === 'cartesian2d') {
        bgEl.setShape('r', barBorderRadius);
      } else {
        bgEl.setShape('cornerRadius', barBorderRadius);
      }

      bgEls[dataIndex] = bgEl;
      return bgEl;
    }
    data.diff(oldData).add(function (dataIndex) {
      var itemModel = data.getItemModel(dataIndex);
      var layout = getLayout[coord.type](data, dataIndex, itemModel);

      if (drawBackground) {
        createBackground(dataIndex);
      } // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".


      if (!data.hasValue(dataIndex) || !isValidLayout[coord.type](layout)) {
        return;
      }

      var isClipped = false;

      if (needsClip) {
        // Clip will modify the layout params.
        // And return a boolean to determine if the shape are fully clipped.
        isClipped = clip[coord.type](coordSysClipArea, layout);
      }

      var el = elementCreator[coord.type](seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, false, roundCap);

      if (realtimeSortCfg) {
        /**
         * Force label animation because even if the element is
         * ignored because it's clipped, it may not be clipped after
         * changing order. Then, if not using forceLabelAnimation,
         * the label animation was never started, in which case,
         * the label will be the final value and doesn't have label
         * animation.
         */
        el.forceLabelAnimation = true;
      }

      updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');

      if (isInitSort) {
        el.attr({
          shape: layout
        });
      } else if (realtimeSortCfg) {
        updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, dataIndex, isHorizontalOrRadial, false, false);
      } else {
        initProps(el, {
          shape: layout
        }, seriesModel, dataIndex);
      }

      data.setItemGraphicEl(dataIndex, el);
      group.add(el);
      el.ignore = isClipped;
    }).update(function (newIndex, oldIndex) {
      var itemModel = data.getItemModel(newIndex);
      var layout = getLayout[coord.type](data, newIndex, itemModel);

      if (drawBackground) {
        var bgEl = void 0;

        if (oldBgEls.length === 0) {
          bgEl = createBackground(oldIndex);
        } else {
          bgEl = oldBgEls[oldIndex];
          bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius.

          if (coord.type === 'cartesian2d') {
            bgEl.setShape('r', barBorderRadius);
          } else {
            bgEl.setShape('cornerRadius', barBorderRadius);
          }

          bgEls[newIndex] = bgEl;
        }

        var bgLayout = getLayout[coord.type](data, newIndex);
        var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
        updateProps$1(bgEl, {
          shape: shape
        }, animationModel, newIndex);
      }

      var el = oldData.getItemGraphicEl(oldIndex);

      if (!data.hasValue(newIndex) || !isValidLayout[coord.type](layout)) {
        group.remove(el);
        return;
      }

      var isClipped = false;

      if (needsClip) {
        isClipped = clip[coord.type](coordSysClipArea, layout);

        if (isClipped) {
          group.remove(el);
        }
      }

      if (!el) {
        el = elementCreator[coord.type](seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, !!el, roundCap);
      } else {
        saveOldStyle(el);
      }

      if (realtimeSortCfg) {
        el.forceLabelAnimation = true;
      }

      if (isChangeOrder) {
        var textEl = el.getTextContent();

        if (textEl) {
          var labelInnerStore = labelInner(textEl);

          if (labelInnerStore.prevValue != null) {
            /**
             * Set preValue to be value so that no new label
             * should be started, otherwise, it will take a full
             * `animationDurationUpdate` time to finish the
             * animation, which is not expected.
             */
            labelInnerStore.prevValue = labelInnerStore.value;
          }
        }
      } // Not change anything if only order changed.
      // Especially not change label.
      else {
          updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');
        }

      if (isInitSort) {
        el.attr({
          shape: layout
        });
      } else if (realtimeSortCfg) {
        updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, newIndex, isHorizontalOrRadial, true, isChangeOrder);
      } else {
        updateProps$1(el, {
          shape: layout
        }, seriesModel, newIndex, null);
      }

      data.setItemGraphicEl(newIndex, el);
      el.ignore = isClipped;
      group.add(el);
    }).remove(function (dataIndex) {
      var el = oldData.getItemGraphicEl(dataIndex);
      el && removeElementWithFadeOut(el, seriesModel, dataIndex);
    }).execute();
    var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group$3());
    bgGroup.removeAll();

    for (var i = 0; i < bgEls.length; ++i) {
      bgGroup.add(bgEls[i]);
    }

    group.add(bgGroup);
    this._backgroundEls = bgEls;
    this._data = data;
  };

  BarView.prototype._renderLarge = function (seriesModel, ecModel, api) {
    this._clear();

    createLarge(seriesModel, this.group);

    this._updateLargeClip(seriesModel);
  };

  BarView.prototype._incrementalRenderLarge = function (params, seriesModel) {
    this._removeBackground();

    createLarge(seriesModel, this.group, this._progressiveEls, true);
  };

  BarView.prototype._updateLargeClip = function (seriesModel) {
    // Use clipPath in large mode.
    var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel);
    var group = this.group;

    if (clipPath) {
      group.setClipPath(clipPath);
    } else {
      group.removeClipPath();
    }
  };

  BarView.prototype._enableRealtimeSort = function (realtimeSortCfg, data, api) {
    var _this = this; // If no data in the first frame, wait for data to initSort


    if (!data.count()) {
      return;
    }

    var baseAxis = realtimeSortCfg.baseAxis;

    if (this._isFirstFrame) {
      this._dispatchInitSort(data, realtimeSortCfg, api);

      this._isFirstFrame = false;
    } else {
      var orderMapping_1 = function (idx) {
        var el = data.getItemGraphicEl(idx);
        var shape = el && el.shape;
        return shape && // The result should be consistent with the initial sort by data value.
        // Do not support the case that both positive and negative exist.
        Math.abs(baseAxis.isHorizontal() ? shape.height : shape.width) // If data is NaN, shape.xxx may be NaN, so use || 0 here in case
        || 0;
      };

      this._onRendered = function () {
        _this._updateSortWithinSameData(data, orderMapping_1, baseAxis, api);
      };

      api.getZr().on('rendered', this._onRendered);
    }
  };

  BarView.prototype._dataSort = function (data, baseAxis, orderMapping) {
    var info = [];
    data.each(data.mapDimension(baseAxis.dim), function (ordinalNumber, dataIdx) {
      var mappedValue = orderMapping(dataIdx);
      mappedValue = mappedValue == null ? NaN : mappedValue;
      info.push({
        dataIndex: dataIdx,
        mappedValue: mappedValue,
        ordinalNumber: ordinalNumber
      });
    });
    info.sort(function (a, b) {
      // If NaN, it will be treated as min val.
      return b.mappedValue - a.mappedValue;
    });
    return {
      ordinalNumbers: map$1(info, function (item) {
        return item.ordinalNumber;
      })
    };
  };

  BarView.prototype._isOrderChangedWithinSameData = function (data, orderMapping, baseAxis) {
    var scale = baseAxis.scale;
    var ordinalDataDim = data.mapDimension(baseAxis.dim);
    var lastValue = Number.MAX_VALUE;

    for (var tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum) {
      var rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum));
      var value = rawIdx < 0 // If some tick have no bar, the tick will be treated as min.
      ? Number.MIN_VALUE // PENDING: if dataZoom on baseAxis exits, is it a performance issue?
      : orderMapping(data.indexOfRawIndex(rawIdx));

      if (value > lastValue) {
        return true;
      }

      lastValue = value;
    }

    return false;
  };
  /*
   * Consider the case when A and B changed order, whose representing
   * bars are both out of sight, we don't wish to trigger reorder action
   * as long as the order in the view doesn't change.
   */


  BarView.prototype._isOrderDifferentInView = function (orderInfo, baseAxis) {
    var scale = baseAxis.scale;
    var extent = scale.getExtent();
    var tickNum = Math.max(0, extent[0]);
    var tickMax = Math.min(extent[1], scale.getOrdinalMeta().categories.length - 1);

    for (; tickNum <= tickMax; ++tickNum) {
      if (orderInfo.ordinalNumbers[tickNum] !== scale.getRawOrdinalNumber(tickNum)) {
        return true;
      }
    }
  };

  BarView.prototype._updateSortWithinSameData = function (data, orderMapping, baseAxis, api) {
    if (!this._isOrderChangedWithinSameData(data, orderMapping, baseAxis)) {
      return;
    }

    var sortInfo = this._dataSort(data, baseAxis, orderMapping);

    if (this._isOrderDifferentInView(sortInfo, baseAxis)) {
      this._removeOnRenderedListener(api);

      api.dispatchAction({
        type: 'changeAxisOrder',
        componentType: baseAxis.dim + 'Axis',
        axisId: baseAxis.index,
        sortInfo: sortInfo
      });
    }
  };

  BarView.prototype._dispatchInitSort = function (data, realtimeSortCfg, api) {
    var baseAxis = realtimeSortCfg.baseAxis;

    var sortResult = this._dataSort(data, baseAxis, function (dataIdx) {
      return data.get(data.mapDimension(realtimeSortCfg.otherAxis.dim), dataIdx);
    });

    api.dispatchAction({
      type: 'changeAxisOrder',
      componentType: baseAxis.dim + 'Axis',
      isInitSort: true,
      axisId: baseAxis.index,
      sortInfo: sortResult
    });
  };

  BarView.prototype.remove = function (ecModel, api) {
    this._clear(this._model);

    this._removeOnRenderedListener(api);
  };

  BarView.prototype.dispose = function (ecModel, api) {
    this._removeOnRenderedListener(api);
  };

  BarView.prototype._removeOnRenderedListener = function (api) {
    if (this._onRendered) {
      api.getZr().off('rendered', this._onRendered);
      this._onRendered = null;
    }
  };

  BarView.prototype._clear = function (model) {
    var group = this.group;
    var data = this._data;

    if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) {
      this._removeBackground();

      this._backgroundEls = [];
      data.eachItemGraphicEl(function (el) {
        removeElementWithFadeOut(el, model, getECData(el).dataIndex);
      });
    } else {
      group.removeAll();
    }

    this._data = null;
    this._isFirstFrame = true;
  };

  BarView.prototype._removeBackground = function () {
    this.group.remove(this._backgroundGroup);
    this._backgroundGroup = null;
  };

  BarView.type = 'bar';
  return BarView;
}(ChartView$1);

var clip = {
  cartesian2d: function (coordSysBoundingRect, layout) {
    var signWidth = layout.width < 0 ? -1 : 1;
    var signHeight = layout.height < 0 ? -1 : 1; // Needs positive width and height

    if (signWidth < 0) {
      layout.x += layout.width;
      layout.width = -layout.width;
    }

    if (signHeight < 0) {
      layout.y += layout.height;
      layout.height = -layout.height;
    }

    var coordSysX2 = coordSysBoundingRect.x + coordSysBoundingRect.width;
    var coordSysY2 = coordSysBoundingRect.y + coordSysBoundingRect.height;
    var x = mathMax(layout.x, coordSysBoundingRect.x);
    var x2 = mathMin(layout.x + layout.width, coordSysX2);
    var y = mathMax(layout.y, coordSysBoundingRect.y);
    var y2 = mathMin(layout.y + layout.height, coordSysY2);
    var xClipped = x2 < x;
    var yClipped = y2 < y; // When xClipped or yClipped, the element will be marked as `ignore`.
    // But we should also place the element at the edge of the coord sys bounding rect.
    // Because if data changed and the bar shows again, its transition animation
    // will begin at this place.

    layout.x = xClipped && x > coordSysX2 ? x2 : x;
    layout.y = yClipped && y > coordSysY2 ? y2 : y;
    layout.width = xClipped ? 0 : x2 - x;
    layout.height = yClipped ? 0 : y2 - y; // Reverse back

    if (signWidth < 0) {
      layout.x += layout.width;
      layout.width = -layout.width;
    }

    if (signHeight < 0) {
      layout.y += layout.height;
      layout.height = -layout.height;
    }

    return xClipped || yClipped;
  },
  polar: function (coordSysClipArea, layout) {
    var signR = layout.r0 <= layout.r ? 1 : -1; // Make sure r is larger than r0

    if (signR < 0) {
      var tmp = layout.r;
      layout.r = layout.r0;
      layout.r0 = tmp;
    }

    var r = mathMin(layout.r, coordSysClipArea.r);
    var r0 = mathMax(layout.r0, coordSysClipArea.r0);
    layout.r = r;
    layout.r0 = r0;
    var clipped = r - r0 < 0; // Reverse back

    if (signR < 0) {
      var tmp = layout.r;
      layout.r = layout.r0;
      layout.r0 = tmp;
    }

    return clipped;
  }
};
var elementCreator = {
  cartesian2d: function (seriesModel, data, newIndex, layout, isHorizontal, animationModel, axisModel, isUpdate, roundCap) {
    var rect = new Rect$1({
      shape: extend({}, layout),
      z2: 1
    });
    rect.__dataIndex = newIndex;
    rect.name = 'item';

    if (animationModel) {
      var rectShape = rect.shape;
      var animateProperty = isHorizontal ? 'height' : 'width';
      rectShape[animateProperty] = 0;
    }

    return rect;
  },
  polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) {
    var ShapeClass = !isRadial && roundCap ? Sausage : Sector$1;
    var sector = new ShapeClass({
      shape: layout,
      z2: 1
    });
    sector.name = 'item';
    var positionMap = createPolarPositionMapping(isRadial);
    sector.calculateTextPosition = createSectorCalculateTextPosition(positionMap, {
      isRoundCap: ShapeClass === Sausage
    }); // Animation

    if (animationModel) {
      var sectorShape = sector.shape;
      var animateProperty = isRadial ? 'r' : 'endAngle';
      var animateTarget = {};
      sectorShape[animateProperty] = isRadial ? layout.r0 : layout.startAngle;
      animateTarget[animateProperty] = layout[animateProperty];
      (isUpdate ? updateProps$1 : initProps)(sector, {
        shape: animateTarget // __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue

      }, animationModel);
    }

    return sector;
  }
};

function shouldRealtimeSort(seriesModel, coordSys) {
  var realtimeSortOption = seriesModel.get('realtimeSort', true);
  var baseAxis = coordSys.getBaseAxis();

  if (realtimeSortOption && baseAxis.type === 'category' && coordSys.type === 'cartesian2d') {
    return {
      baseAxis: baseAxis,
      otherAxis: coordSys.getOtherAxis(baseAxis)
    };
  }
}

function updateRealtimeAnimation(realtimeSortCfg, seriesAnimationModel, el, layout, newIndex, isHorizontal, isUpdate, isChangeOrder) {
  var seriesTarget;
  var axisTarget;

  if (isHorizontal) {
    axisTarget = {
      x: layout.x,
      width: layout.width
    };
    seriesTarget = {
      y: layout.y,
      height: layout.height
    };
  } else {
    axisTarget = {
      y: layout.y,
      height: layout.height
    };
    seriesTarget = {
      x: layout.x,
      width: layout.width
    };
  }

  if (!isChangeOrder) {
    // Keep the original growth animation if only axis order changed.
    // Not start a new animation.
    (isUpdate ? updateProps$1 : initProps)(el, {
      shape: seriesTarget
    }, seriesAnimationModel, newIndex, null);
  }

  var axisAnimationModel = seriesAnimationModel ? realtimeSortCfg.baseAxis.model : null;
  (isUpdate ? updateProps$1 : initProps)(el, {
    shape: axisTarget
  }, axisAnimationModel, newIndex);
}

function checkPropertiesNotValid(obj, props) {
  for (var i = 0; i < props.length; i++) {
    if (!isFinite(obj[props[i]])) {
      return true;
    }
  }

  return false;
}

var rectPropties = ['x', 'y', 'width', 'height'];
var polarPropties = ['cx', 'cy', 'r', 'startAngle', 'endAngle'];
var isValidLayout = {
  cartesian2d: function (layout) {
    return !checkPropertiesNotValid(layout, rectPropties);
  },
  polar: function (layout) {
    return !checkPropertiesNotValid(layout, polarPropties);
  }
};
var getLayout = {
  // itemModel is only used to get borderWidth, which is not needed
  // when calculating bar background layout.
  cartesian2d: function (data, dataIndex, itemModel) {
    var layout = data.getItemLayout(dataIndex);
    var fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0; // fix layout with lineWidth

    var signX = layout.width > 0 ? 1 : -1;
    var signY = layout.height > 0 ? 1 : -1;
    return {
      x: layout.x + signX * fixedLineWidth / 2,
      y: layout.y + signY * fixedLineWidth / 2,
      width: layout.width - signX * fixedLineWidth,
      height: layout.height - signY * fixedLineWidth
    };
  },
  polar: function (data, dataIndex, itemModel) {
    var layout = data.getItemLayout(dataIndex);
    return {
      cx: layout.cx,
      cy: layout.cy,
      r0: layout.r0,
      r: layout.r,
      startAngle: layout.startAngle,
      endAngle: layout.endAngle,
      clockwise: layout.clockwise
    };
  }
};

function isZeroOnPolar(layout) {
  return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle;
}

function createPolarPositionMapping(isRadial) {
  return function (isRadial) {
    var arcOrAngle = isRadial ? 'Arc' : 'Angle';
    return function (position) {
      switch (position) {
        case 'start':
        case 'insideStart':
        case 'end':
        case 'insideEnd':
          return position + arcOrAngle;

        default:
          return position;
      }
    };
  }(isRadial);
}

function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, isPolar) {
  var style = data.getItemVisual(dataIndex, 'style');

  if (!isPolar) {
    var borderRadius = itemModel.get(['itemStyle', 'borderRadius']) || 0;
    el.setShape('r', borderRadius);
  } else if (!seriesModel.get('roundCap')) {
    var sectorShape = el.shape;
    var cornerRadius = getSectorCornerRadius(itemModel.getModel('itemStyle'), sectorShape, true);
    extend(sectorShape, cornerRadius);
    el.setShape(sectorShape);
  }

  el.useStyle(style);
  var cursorStyle = itemModel.getShallow('cursor');
  cursorStyle && el.attr('cursor', cursorStyle);
  var labelPositionOutside = isPolar ? isHorizontalOrRadial ? layout.r >= layout.r0 ? 'endArc' : 'startArc' : layout.endAngle >= layout.startAngle ? 'endAngle' : 'startAngle' : isHorizontalOrRadial ? layout.height >= 0 ? 'bottom' : 'top' : layout.width >= 0 ? 'right' : 'left';
  var labelStatesModels = getLabelStatesModels(itemModel);
  setLabelStyle(el, labelStatesModels, {
    labelFetcher: seriesModel,
    labelDataIndex: dataIndex,
    defaultText: getDefaultLabel(seriesModel.getData(), dataIndex),
    inheritColor: style.fill,
    defaultOpacity: style.opacity,
    defaultOutsidePosition: labelPositionOutside
  });
  var label = el.getTextContent();

  if (isPolar && label) {
    var position = itemModel.get(['label', 'position']);
    el.textConfig.inside = position === 'middle' ? true : null;
    setSectorTextRotation(el, position === 'outside' ? labelPositionOutside : position, createPolarPositionMapping(isHorizontalOrRadial), itemModel.get(['label', 'rotate']));
  }

  setLabelValueAnimation(label, labelStatesModels, seriesModel.getRawValue(dataIndex), function (value) {
    return getDefaultInterpolatedLabel(data, value);
  });
  var emphasisModel = itemModel.getModel(['emphasis']);
  toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled'));
  setStatesStylesFromModel(el, itemModel);

  if (isZeroOnPolar(layout)) {
    el.style.fill = 'none';
    el.style.stroke = 'none';
    each$4(el.states, function (state) {
      if (state.style) {
        state.style.fill = state.style.stroke = 'none';
      }
    });
  }
} // In case width or height are too small.


function getLineWidth(itemModel, rawLayout) {
  // Has no border.
  var borderColor = itemModel.get(['itemStyle', 'borderColor']);

  if (!borderColor || borderColor === 'none') {
    return 0;
  }

  var lineWidth = itemModel.get(['itemStyle', 'borderWidth']) || 0; // width or height may be NaN for empty data

  var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
  var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
  return Math.min(lineWidth, width, height);
}

var LagePathShape =
/** @class */
function () {
  function LagePathShape() {}

  return LagePathShape;
}();

var LargePath =
/** @class */
function (_super) {
  __extends(LargePath, _super);

  function LargePath(opts) {
    var _this = _super.call(this, opts) || this;

    _this.type = 'largeBar';
    return _this;
  }

  LargePath.prototype.getDefaultShape = function () {
    return new LagePathShape();
  };

  LargePath.prototype.buildPath = function (ctx, shape) {
    // Drawing lines is more efficient than drawing
    // a whole line or drawing rects.
    var points = shape.points;
    var baseDimIdx = this.baseDimIdx;
    var valueDimIdx = 1 - this.baseDimIdx;
    var startPoint = [];
    var size = [];
    var barWidth = this.barWidth;

    for (var i = 0; i < points.length; i += 3) {
      size[baseDimIdx] = barWidth;
      size[valueDimIdx] = points[i + 2];
      startPoint[baseDimIdx] = points[i + baseDimIdx];
      startPoint[valueDimIdx] = points[i + valueDimIdx];
      ctx.rect(startPoint[0], startPoint[1], size[0], size[1]);
    }
  };

  return LargePath;
}(Path$1);

function createLarge(seriesModel, group, progressiveEls, incremental) {
  // TODO support polar
  var data = seriesModel.getData();
  var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
  var largeDataIndices = data.getLayout('largeDataIndices');
  var barWidth = data.getLayout('size');
  var backgroundModel = seriesModel.getModel('backgroundStyle');
  var bgPoints = data.getLayout('largeBackgroundPoints');

  if (bgPoints) {
    var bgEl = new LargePath({
      shape: {
        points: bgPoints
      },
      incremental: !!incremental,
      silent: true,
      z2: 0
    });
    bgEl.baseDimIdx = baseDimIdx;
    bgEl.largeDataIndices = largeDataIndices;
    bgEl.barWidth = barWidth;
    bgEl.useStyle(backgroundModel.getItemStyle());
    group.add(bgEl);
    progressiveEls && progressiveEls.push(bgEl);
  }

  var el = new LargePath({
    shape: {
      points: data.getLayout('largePoints')
    },
    incremental: !!incremental,
    ignoreCoarsePointer: true,
    z2: 1
  });
  el.baseDimIdx = baseDimIdx;
  el.largeDataIndices = largeDataIndices;
  el.barWidth = barWidth;
  group.add(el);
  el.useStyle(data.getVisual('style')); // Enable tooltip and user mouse/touch event handlers.

  getECData(el).seriesIndex = seriesModel.seriesIndex;

  if (!seriesModel.get('silent')) {
    el.on('mousedown', largePathUpdateDataIndex);
    el.on('mousemove', largePathUpdateDataIndex);
  }

  progressiveEls && progressiveEls.push(el);
} // Use throttle to avoid frequently traverse to find dataIndex.


var largePathUpdateDataIndex = throttle(function (event) {
  var largePath = this;
  var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY);
  getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null;
}, 30, false);

function largePathFindDataIndex(largePath, x, y) {
  var baseDimIdx = largePath.baseDimIdx;
  var valueDimIdx = 1 - baseDimIdx;
  var points = largePath.shape.points;
  var largeDataIndices = largePath.largeDataIndices;
  var startPoint = [];
  var size = [];
  var barWidth = largePath.barWidth;

  for (var i = 0, len = points.length / 3; i < len; i++) {
    var ii = i * 3;
    size[baseDimIdx] = barWidth;
    size[valueDimIdx] = points[ii + 2];
    startPoint[baseDimIdx] = points[ii + baseDimIdx];
    startPoint[valueDimIdx] = points[ii + valueDimIdx];

    if (size[valueDimIdx] < 0) {
      startPoint[valueDimIdx] += size[valueDimIdx];
      size[valueDimIdx] = -size[valueDimIdx];
    }

    if (x >= startPoint[0] && x <= startPoint[0] + size[0] && y >= startPoint[1] && y <= startPoint[1] + size[1]) {
      return largeDataIndices[i];
    }
  }

  return -1;
}

function createBackgroundShape(isHorizontalOrRadial, layout, coord) {
  if (isCoordinateSystemType(coord, 'cartesian2d')) {
    var rectShape = layout;
    var coordLayout = coord.getArea();
    return {
      x: isHorizontalOrRadial ? rectShape.x : coordLayout.x,
      y: isHorizontalOrRadial ? coordLayout.y : rectShape.y,
      width: isHorizontalOrRadial ? rectShape.width : coordLayout.width,
      height: isHorizontalOrRadial ? coordLayout.height : rectShape.height
    };
  } else {
    var coordLayout = coord.getArea();
    var sectorShape = layout;
    return {
      cx: coordLayout.cx,
      cy: coordLayout.cy,
      r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0,
      r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r,
      startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0,
      endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2
    };
  }
}

function createBackgroundEl(coord, isHorizontalOrRadial, layout) {
  var ElementClz = coord.type === 'polar' ? Sector$1 : Rect$1;
  return new ElementClz({
    shape: createBackgroundShape(isHorizontalOrRadial, layout, coord),
    silent: true,
    z2: 0
  });
}

const BarView$1 = BarView;
/* Injected with object hook! */

function install$8(registers) {
  registers.registerChartView(BarView$1);
  registers.registerSeriesModel(BarSeries);
  registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT, curry$1(layout$1, 'bar')); // Do layout after other overall layout, which can prepare some information.

  registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, createProgressiveLayout('bar')); // Down sample after filter

  registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('bar'));
  /**
   * @payload
   * @property {string} [componentType=series]
   * @property {number} [dx]
   * @property {number} [dy]
   * @property {number} [zoom]
   * @property {number} [originX]
   * @property {number} [originY]
   */

  registers.registerAction({
    type: 'changeAxisOrder',
    event: 'changeAxisOrder',
    update: 'update'
  }, function (payload, ecModel) {
    var componentType = payload.componentType || 'series';
    ecModel.eachComponent({
      mainType: componentType,
      query: payload
    }, function (componentModel) {
      if (payload.sortInfo) {
        componentModel.axis.setCategorySortInfo(payload.sortInfo);
      }
    });
  });
}
/* Injected with object hook! */

var GridModel =
/** @class */
function (_super) {
  __extends(GridModel, _super);

  function GridModel() {
    return _super !== null && _super.apply(this, arguments) || this;
  }

  GridModel.type = 'grid';
  GridModel.dependencies = ['xAxis', 'yAxis'];
  GridModel.layoutMode = 'box';
  GridModel.defaultOption = {
    show: false,
    // zlevel: 0,
    z: 0,
    left: '10%',
    top: 60,
    right: '10%',
    bottom: 70,
    // If grid size contain label
    containLabel: false,
    // width: {totalWidth} - left - right,
    // height: {totalHeight} - top - bottom,
    backgroundColor: 'rgba(0,0,0,0)',
    borderWidth: 1,
    borderColor: '#ccc'
  };
  return GridModel;
}(ComponentModel$1);

const GridModel$1 = GridModel;
/* Injected with object hook! */

var CartesianAxisModel =
/** @class */
function (_super) {
  __extends(CartesianAxisModel, _super);

  function CartesianAxisModel() {
    return _super !== null && _super.apply(this, arguments) || this;
  }

  CartesianAxisModel.prototype.getCoordSysModel = function () {
    return this.getReferringComponents('grid', SINGLE_REFERRING).models[0];
  };

  CartesianAxisModel.type = 'cartesian2dAxis';
  return CartesianAxisModel;
}(ComponentModel$1);
mixin(CartesianAxisModel, AxisModelCommonMixin);
/* Injected with object hook! */

var defaultOption = {
  show: true,
  // zlevel: 0,
  z: 0,
  // Inverse the axis.
  inverse: false,
  // Axis name displayed.
  name: '',
  // 'start' | 'middle' | 'end'
  nameLocation: 'end',
  // By degree. By default auto rotate by nameLocation.
  nameRotate: null,
  nameTruncate: {
    maxWidth: null,
    ellipsis: '...',
    placeholder: '.'
  },
  // Use global text style by default.
  nameTextStyle: {},
  // The gap between axisName and axisLine.
  nameGap: 15,
  // Default `false` to support tooltip.
  silent: false,
  // Default `false` to avoid legacy user event listener fail.
  triggerEvent: false,
  tooltip: {
    show: false
  },
  axisPointer: {},
  axisLine: {
    show: true,
    onZero: true,
    onZeroAxisIndex: null,
    lineStyle: {
      color: '#6E7079',
      width: 1,
      type: 'solid'
    },
    // The arrow at both ends the the axis.
    symbol: ['none', 'none'],
    symbolSize: [10, 15]
  },
  axisTick: {
    show: true,
    // Whether axisTick is inside the grid or outside the grid.
    inside: false,
    // The length of axisTick.
    length: 5,
    lineStyle: {
      width: 1
    }
  },
  axisLabel: {
    show: true,
    // Whether axisLabel is inside the grid or outside the grid.
    inside: false,
    rotate: 0,
    // true | false | null/undefined (auto)
    showMinLabel: null,
    // true | false | null/undefined (auto)
    showMaxLabel: null,
    margin: 8,
    // formatter: null,
    fontSize: 12
  },
  splitLine: {
    show: true,
    lineStyle: {
      color: ['#E0E6F1'],
      width: 1,
      type: 'solid'
    }
  },
  splitArea: {
    show: false,
    areaStyle: {
      color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)']
    }
  }
};
var categoryAxis = merge({
  // The gap at both ends of the axis. For categoryAxis, boolean.
  boundaryGap: true,
  // Set false to faster category collection.
  deduplication: null,
  // splitArea: {
  // show: false
  // },
  splitLine: {
    show: false
  },
  axisTick: {
    // If tick is align with label when boundaryGap is true
    alignWithLabel: false,
    interval: 'auto'
  },
  axisLabel: {
    interval: 'auto'
  }
}, defaultOption);
var valueAxis = merge({
  boundaryGap: [0, 0],
  axisLine: {
    // Not shown when other axis is categoryAxis in cartesian
    show: 'auto'
  },
  axisTick: {
    // Not shown when other axis is categoryAxis in cartesian
    show: 'auto'
  },
  // TODO
  // min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60]
  splitNumber: 5,
  minorTick: {
    // Minor tick, not available for cateogry axis.
    show: false,
    // Split number of minor ticks. The value should be in range of (0, 100)
    splitNumber: 5,
    // Length of minor tick
    length: 3,
    // Line style
    lineStyle: {// Default to be same with axisTick
    }
  },
  minorSplitLine: {
    show: false,
    lineStyle: {
      color: '#F4F7FD',
      width: 1
    }
  }
}, defaultOption);
var timeAxis = merge({
  splitNumber: 6,
  axisLabel: {
    // To eliminate labels that are not nice
    showMinLabel: false,
    showMaxLabel: false,
    rich: {
      primary: {
        fontWeight: 'bold'
      }
    }
  },
  splitLine: {
    show: false
  }
}, valueAxis);
var logAxis = defaults({
  logBase: 10
}, valueAxis);
const axisDefault = {
  category: categoryAxis,
  value: valueAxis,
  time: timeAxis,
  log: logAxis
};
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var AXIS_TYPES = {
  value: 1,
  category: 1,
  time: 1,
  log: 1
};
/* Injected with object hook! */

/**
 * Generate sub axis model class
 * @param axisName 'x' 'y' 'radius' 'angle' 'parallel' ...
 */

function axisModelCreator(registers, axisName, BaseAxisModelClass, extraDefaultOption) {
  each$4(AXIS_TYPES, function (v, axisType) {
    var defaultOption = merge(merge({}, axisDefault[axisType], true), extraDefaultOption, true);

    var AxisModel =
    /** @class */
    function (_super) {
      __extends(AxisModel, _super);

      function AxisModel() {
        var _this = _super !== null && _super.apply(this, arguments) || this;

        _this.type = axisName + 'Axis.' + axisType;
        return _this;
      }

      AxisModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
        var layoutMode = fetchLayoutMode(this);
        var inputPositionParams = layoutMode ? getLayoutParams(option) : {};
        var themeModel = ecModel.getTheme();
        merge(option, themeModel.get(axisType + 'Axis'));
        merge(option, this.getDefaultOption());
        option.type = getAxisType(option);

        if (layoutMode) {
          mergeLayoutParam(option, inputPositionParams, layoutMode);
        }
      };

      AxisModel.prototype.optionUpdated = function () {
        var thisOption = this.option;

        if (thisOption.type === 'category') {
          this.__ordinalMeta = OrdinalMeta$1.createByAxisModel(this);
        }
      };
      /**
       * Should not be called before all of 'getInitailData' finished.
       * Because categories are collected during initializing data.
       */


      AxisModel.prototype.getCategories = function (rawData) {
        var option = this.option; // FIXME
        // warning if called before all of 'getInitailData' finished.

        if (option.type === 'category') {
          if (rawData) {
            return option.data;
          }

          return this.__ordinalMeta.categories;
        }
      };

      AxisModel.prototype.getOrdinalMeta = function () {
        return this.__ordinalMeta;
      };

      AxisModel.type = axisName + 'Axis.' + axisType;
      AxisModel.defaultOption = defaultOption;
      return AxisModel;
    }(BaseAxisModelClass);

    registers.registerComponentModel(AxisModel);
  });
  registers.registerSubTypeDefaulter(axisName + 'Axis', getAxisType);
}

function getAxisType(option) {
  // Default axis with data is category axis
  return option.type || (option.data ? 'category' : 'value');
}
/* Injected with object hook! */

var Cartesian =
/** @class */
function () {
  function Cartesian(name) {
    this.type = 'cartesian';
    this._dimList = [];
    this._axes = {};
    this.name = name || '';
  }

  Cartesian.prototype.getAxis = function (dim) {
    return this._axes[dim];
  };

  Cartesian.prototype.getAxes = function () {
    return map$1(this._dimList, function (dim) {
      return this._axes[dim];
    }, this);
  };

  Cartesian.prototype.getAxesByScale = function (scaleType) {
    scaleType = scaleType.toLowerCase();
    return filter(this.getAxes(), function (axis) {
      return axis.scale.type === scaleType;
    });
  };

  Cartesian.prototype.addAxis = function (axis) {
    var dim = axis.dim;
    this._axes[dim] = axis;

    this._dimList.push(dim);
  };

  return Cartesian;
}();
const Cartesian$1 = Cartesian;
/* Injected with object hook! */

var cartesian2DDimensions = ['x', 'y'];

function canCalculateAffineTransform(scale) {
  return scale.type === 'interval' || scale.type === 'time';
}

var Cartesian2D =
/** @class */
function (_super) {
  __extends(Cartesian2D, _super);

  function Cartesian2D() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = 'cartesian2d';
    _this.dimensions = cartesian2DDimensions;
    return _this;
  }
  /**
   * Calculate an affine transform matrix if two axes are time or value.
   * It's mainly for accelartion on the large time series data.
   */


  Cartesian2D.prototype.calcAffineTransform = function () {
    this._transform = this._invTransform = null;
    var xAxisScale = this.getAxis('x').scale;
    var yAxisScale = this.getAxis('y').scale;

    if (!canCalculateAffineTransform(xAxisScale) || !canCalculateAffineTransform(yAxisScale)) {
      return;
    }

    var xScaleExtent = xAxisScale.getExtent();
    var yScaleExtent = yAxisScale.getExtent();
    var start = this.dataToPoint([xScaleExtent[0], yScaleExtent[0]]);
    var end = this.dataToPoint([xScaleExtent[1], yScaleExtent[1]]);
    var xScaleSpan = xScaleExtent[1] - xScaleExtent[0];
    var yScaleSpan = yScaleExtent[1] - yScaleExtent[0];

    if (!xScaleSpan || !yScaleSpan) {
      return;
    } // Accelerate data to point calculation on the special large time series data.


    var scaleX = (end[0] - start[0]) / xScaleSpan;
    var scaleY = (end[1] - start[1]) / yScaleSpan;
    var translateX = start[0] - xScaleExtent[0] * scaleX;
    var translateY = start[1] - yScaleExtent[0] * scaleY;
    var m = this._transform = [scaleX, 0, 0, scaleY, translateX, translateY];
    this._invTransform = invert([], m);
  };
  /**
   * Base axis will be used on stacking.
   */


  Cartesian2D.prototype.getBaseAxis = function () {
    return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAxis('x');
  };

  Cartesian2D.prototype.containPoint = function (point) {
    var axisX = this.getAxis('x');
    var axisY = this.getAxis('y');
    return axisX.contain(axisX.toLocalCoord(point[0])) && axisY.contain(axisY.toLocalCoord(point[1]));
  };

  Cartesian2D.prototype.containData = function (data) {
    return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]);
  };

  Cartesian2D.prototype.containZone = function (data1, data2) {
    var zoneDiag1 = this.dataToPoint(data1);
    var zoneDiag2 = this.dataToPoint(data2);
    var area = this.getArea();
    var zone = new BoundingRect$1(zoneDiag1[0], zoneDiag1[1], zoneDiag2[0] - zoneDiag1[0], zoneDiag2[1] - zoneDiag1[1]);
    return area.intersect(zone);
  };

  Cartesian2D.prototype.dataToPoint = function (data, clamp, out) {
    out = out || [];
    var xVal = data[0];
    var yVal = data[1]; // Fast path

    if (this._transform // It's supported that if data is like `[Inifity, 123]`, where only Y pixel calculated.
    && xVal != null && isFinite(xVal) && yVal != null && isFinite(yVal)) {
      return applyTransform$1(out, data, this._transform);
    }

    var xAxis = this.getAxis('x');
    var yAxis = this.getAxis('y');
    out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(xVal, clamp));
    out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(yVal, clamp));
    return out;
  };

  Cartesian2D.prototype.clampData = function (data, out) {
    var xScale = this.getAxis('x').scale;
    var yScale = this.getAxis('y').scale;
    var xAxisExtent = xScale.getExtent();
    var yAxisExtent = yScale.getExtent();
    var x = xScale.parse(data[0]);
    var y = yScale.parse(data[1]);
    out = out || [];
    out[0] = Math.min(Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), Math.max(xAxisExtent[0], xAxisExtent[1]));
    out[1] = Math.min(Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), Math.max(yAxisExtent[0], yAxisExtent[1]));
    return out;
  };

  Cartesian2D.prototype.pointToData = function (point, clamp) {
    var out = [];

    if (this._invTransform) {
      return applyTransform$1(out, point, this._invTransform);
    }

    var xAxis = this.getAxis('x');
    var yAxis = this.getAxis('y');
    out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0]), clamp);
    out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1]), clamp);
    return out;
  };

  Cartesian2D.prototype.getOtherAxis = function (axis) {
    return this.getAxis(axis.dim === 'x' ? 'y' : 'x');
  };
  /**
   * Get rect area of cartesian.
   * Area will have a contain function to determine if a point is in the coordinate system.
   */


  Cartesian2D.prototype.getArea = function () {
    var xExtent = this.getAxis('x').getGlobalExtent();
    var yExtent = this.getAxis('y').getGlobalExtent();
    var x = Math.min(xExtent[0], xExtent[1]);
    var y = Math.min(yExtent[0], yExtent[1]);
    var width = Math.max(xExtent[0], xExtent[1]) - x;
    var height = Math.max(yExtent[0], yExtent[1]) - y;
    return new BoundingRect$1(x, y, width, height);
  };

  return Cartesian2D;
}(Cartesian$1);
/* Injected with object hook! */

var Axis2D =
/** @class */
function (_super) {
  __extends(Axis2D, _super);

  function Axis2D(dim, scale, coordExtent, axisType, position) {
    var _this = _super.call(this, dim, scale, coordExtent) || this;
    /**
     * Index of axis, can be used as key
     * Injected outside.
     */


    _this.index = 0;
    _this.type = axisType || 'value';
    _this.position = position || 'bottom';
    return _this;
  }

  Axis2D.prototype.isHorizontal = function () {
    var position = this.position;
    return position === 'top' || position === 'bottom';
  };
  /**
   * Each item cooresponds to this.getExtent(), which
   * means globalExtent[0] may greater than globalExtent[1],
   * unless `asc` is input.
   *
   * @param {boolean} [asc]
   * @return {Array.<number>}
   */


  Axis2D.prototype.getGlobalExtent = function (asc) {
    var ret = this.getExtent();
    ret[0] = this.toGlobalCoord(ret[0]);
    ret[1] = this.toGlobalCoord(ret[1]);
    asc && ret[0] > ret[1] && ret.reverse();
    return ret;
  };

  Axis2D.prototype.pointToData = function (point, clamp) {
    return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp);
  };
  /**
   * Set ordinalSortInfo
   * @param info new OrdinalSortInfo
   */


  Axis2D.prototype.setCategorySortInfo = function (info) {
    if (this.type !== 'category') {
      return false;
    }

    this.model.option.categorySortInfo = info;
    this.scale.setSortInfo(info);
  };

  return Axis2D;
}(Axis$1);

const Axis2D$1 = Axis2D;
/* Injected with object hook! */

/**
 * Can only be called after coordinate system creation stage.
 * (Can be called before coordinate system update stage).
 */

function layout(gridModel, axisModel, opt) {
  opt = opt || {};
  var grid = gridModel.coordinateSystem;
  var axis = axisModel.axis;
  var layout = {};
  var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0];
  var rawAxisPosition = axis.position;
  var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition;
  var axisDim = axis.dim;
  var rect = grid.getRect();
  var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];
  var idx = {
    left: 0,
    right: 1,
    top: 0,
    bottom: 1,
    onZero: 2
  };
  var axisOffset = axisModel.get('offset') || 0;
  var posBound = axisDim === 'x' ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset] : [rectBound[0] - axisOffset, rectBound[1] + axisOffset];

  if (otherAxisOnZeroOf) {
    var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0));
    posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]);
  } // Axis position


  layout.position = [axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0], axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3]]; // Axis rotation

  layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1); // Tick and label direction, x y is axisDim

  var dirMap = {
    top: -1,
    bottom: 1,
    left: -1,
    right: 1
  };
  layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition];
  layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0;

  if (axisModel.get(['axisTick', 'inside'])) {
    layout.tickDirection = -layout.tickDirection;
  }

  if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) {
    layout.labelDirection = -layout.labelDirection;
  } // Special label rotation


  var labelRotate = axisModel.get(['axisLabel', 'rotate']);
  layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate; // Over splitLine and splitArea

  layout.z2 = 1;
  return layout;
}
function isCartesian2DSeries(seriesModel) {
  return seriesModel.get('coordinateSystem') === 'cartesian2d';
}
function findAxisModels(seriesModel) {
  var axisModelMap = {
    xAxisModel: null,
    yAxisModel: null
  };
  each$4(axisModelMap, function (v, key) {
    var axisType = key.replace(/Model$/, '');
    var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0];

    axisModelMap[key] = axisModel;
  });
  return axisModelMap;
}
/* Injected with object hook! */

var mathLog = Math.log;
function alignScaleTicks(scale, axisModel, alignToScale) {
  var intervalScaleProto = IntervalScale$1.prototype; // NOTE: There is a precondition for log scale  here:
  // In log scale we store _interval and _extent of exponent value.
  // So if we use the method of InternalScale to set/get these data.
  // It process the exponent value, which is linear and what we want here.

  var alignToTicks = intervalScaleProto.getTicks.call(alignToScale);
  var alignToNicedTicks = intervalScaleProto.getTicks.call(alignToScale, true);
  var alignToSplitNumber = alignToTicks.length - 1;
  var alignToInterval = intervalScaleProto.getInterval.call(alignToScale);
  var scaleExtent = getScaleExtent(scale, axisModel);
  var rawExtent = scaleExtent.extent;
  var isMinFixed = scaleExtent.fixMin;
  var isMaxFixed = scaleExtent.fixMax;

  if (scale.type === 'log') {
    var logBase = mathLog(scale.base);
    rawExtent = [mathLog(rawExtent[0]) / logBase, mathLog(rawExtent[1]) / logBase];
  }

  scale.setExtent(rawExtent[0], rawExtent[1]);
  scale.calcNiceExtent({
    splitNumber: alignToSplitNumber,
    fixMin: isMinFixed,
    fixMax: isMaxFixed
  });
  var extent = intervalScaleProto.getExtent.call(scale); // Need to update the rawExtent.
  // Because value in rawExtent may be not parsed. e.g. 'dataMin', 'dataMax'

  if (isMinFixed) {
    rawExtent[0] = extent[0];
  }

  if (isMaxFixed) {
    rawExtent[1] = extent[1];
  }

  var interval = intervalScaleProto.getInterval.call(scale);
  var min = rawExtent[0];
  var max = rawExtent[1];

  if (isMinFixed && isMaxFixed) {
    // User set min, max, divide to get new interval
    interval = (max - min) / alignToSplitNumber;
  } else if (isMinFixed) {
    max = rawExtent[0] + interval * alignToSplitNumber; // User set min, expand extent on the other side

    while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])) {
      interval = increaseInterval(interval);
      max = rawExtent[0] + interval * alignToSplitNumber;
    }
  } else if (isMaxFixed) {
    // User set max, expand extent on the other side
    min = rawExtent[1] - interval * alignToSplitNumber;

    while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])) {
      interval = increaseInterval(interval);
      min = rawExtent[1] - interval * alignToSplitNumber;
    }
  } else {
    var nicedSplitNumber = scale.getTicks().length - 1;

    if (nicedSplitNumber > alignToSplitNumber) {
      interval = increaseInterval(interval);
    }

    var range = interval * alignToSplitNumber;
    max = Math.ceil(rawExtent[1] / interval) * interval;
    min = round$1(max - range); // Not change the result that crossing zero.

    if (min < 0 && rawExtent[0] >= 0) {
      min = 0;
      max = round$1(range);
    } else if (max > 0 && rawExtent[1] <= 0) {
      max = 0;
      min = -round$1(range);
    }
  } // Adjust min, max based on the extent of alignTo. When min or max is set in alignTo scale


  var t0 = (alignToTicks[0].value - alignToNicedTicks[0].value) / alignToInterval;
  var t1 = (alignToTicks[alignToSplitNumber].value - alignToNicedTicks[alignToSplitNumber].value) / alignToInterval; // NOTE: Must in setExtent -> setInterval -> setNiceExtent order.

  intervalScaleProto.setExtent.call(scale, min + interval * t0, max + interval * t1);
  intervalScaleProto.setInterval.call(scale, interval);

  if (t0 || t1) {
    intervalScaleProto.setNiceExtent.call(scale, min + interval, max - interval);
  }
}
/* Injected with object hook! */

var Grid =
/** @class */
function () {
  function Grid(gridModel, ecModel, api) {
    // FIXME:TS where used (different from registered type 'cartesian2d')?
    this.type = 'grid';
    this._coordsMap = {};
    this._coordsList = [];
    this._axesMap = {};
    this._axesList = [];
    this.axisPointerEnabled = true;
    this.dimensions = cartesian2DDimensions;

    this._initCartesian(gridModel, ecModel, api);

    this.model = gridModel;
  }

  Grid.prototype.getRect = function () {
    return this._rect;
  };

  Grid.prototype.update = function (ecModel, api) {
    var axesMap = this._axesMap;

    this._updateScale(ecModel, this.model);

    function updateAxisTicks(axes) {
      var alignTo; // Axis is added in order of axisIndex.

      var axesIndices = keys(axes);
      var len = axesIndices.length;

      if (!len) {
        return;
      }

      var axisNeedsAlign = []; // Process once and calculate the ticks for those don't use alignTicks.

      for (var i = len - 1; i >= 0; i--) {
        var idx = +axesIndices[i]; // Convert to number.

        var axis = axes[idx];
        var model = axis.model;
        var scale = axis.scale;

        if ( // Only value and log axis without interval support alignTicks.
        isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null) {
          axisNeedsAlign.push(axis);
        } else {
          niceScaleExtent(scale, model);

          if (isIntervalOrLogScale(scale)) {
            // Can only align to interval or log axis.
            alignTo = axis;
          }
        }
      }
      // PENDING. Should we find the axis that both set interval, min, max and align to this one?

      if (axisNeedsAlign.length) {
        if (!alignTo) {
          alignTo = axisNeedsAlign.pop();
          niceScaleExtent(alignTo.scale, alignTo.model);
        }

        each$4(axisNeedsAlign, function (axis) {
          alignScaleTicks(axis.scale, axis.model, alignTo.scale);
        });
      }
    }

    updateAxisTicks(axesMap.x);
    updateAxisTicks(axesMap.y); // Key: axisDim_axisIndex, value: boolean, whether onZero target.

    var onZeroRecords = {};
    each$4(axesMap.x, function (xAxis) {
      fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords);
    });
    each$4(axesMap.y, function (yAxis) {
      fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords);
    }); // Resize again if containLabel is enabled
    // FIXME It may cause getting wrong grid size in data processing stage

    this.resize(this.model, api);
  };
  /**
   * Resize the grid
   */


  Grid.prototype.resize = function (gridModel, api, ignoreContainLabel) {
    var boxLayoutParams = gridModel.getBoxLayoutParams();
    var isContainLabel = !ignoreContainLabel && gridModel.get('containLabel');
    var gridRect = getLayoutRect(boxLayoutParams, {
      width: api.getWidth(),
      height: api.getHeight()
    });
    this._rect = gridRect;
    var axesList = this._axesList;
    adjustAxes(); // Minus label size

    if (isContainLabel) {
      each$4(axesList, function (axis) {
        if (!axis.model.get(['axisLabel', 'inside'])) {
          var labelUnionRect = estimateLabelUnionRect(axis);

          if (labelUnionRect) {
            var dim = axis.isHorizontal() ? 'height' : 'width';
            var margin = axis.model.get(['axisLabel', 'margin']);
            gridRect[dim] -= labelUnionRect[dim] + margin;

            if (axis.position === 'top') {
              gridRect.y += labelUnionRect.height + margin;
            } else if (axis.position === 'left') {
              gridRect.x += labelUnionRect.width + margin;
            }
          }
        }
      });
      adjustAxes();
    }

    each$4(this._coordsList, function (coord) {
      // Calculate affine matrix to accelerate the data to point transform.
      // If all the axes scales are time or value.
      coord.calcAffineTransform();
    });

    function adjustAxes() {
      each$4(axesList, function (axis) {
        var isHorizontal = axis.isHorizontal();
        var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height];
        var idx = axis.inverse ? 1 : 0;
        axis.setExtent(extent[idx], extent[1 - idx]);
        updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y);
      });
    }
  };

  Grid.prototype.getAxis = function (dim, axisIndex) {
    var axesMapOnDim = this._axesMap[dim];

    if (axesMapOnDim != null) {
      return axesMapOnDim[axisIndex || 0];
    }
  };

  Grid.prototype.getAxes = function () {
    return this._axesList.slice();
  };

  Grid.prototype.getCartesian = function (xAxisIndex, yAxisIndex) {
    if (xAxisIndex != null && yAxisIndex != null) {
      var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
      return this._coordsMap[key];
    }

    if (isObject$2(xAxisIndex)) {
      yAxisIndex = xAxisIndex.yAxisIndex;
      xAxisIndex = xAxisIndex.xAxisIndex;
    }

    for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) {
      if (coordList[i].getAxis('x').index === xAxisIndex || coordList[i].getAxis('y').index === yAxisIndex) {
        return coordList[i];
      }
    }
  };

  Grid.prototype.getCartesians = function () {
    return this._coordsList.slice();
  };
  /**
   * @implements
   */


  Grid.prototype.convertToPixel = function (ecModel, finder, value) {
    var target = this._findConvertTarget(finder);

    return target.cartesian ? target.cartesian.dataToPoint(value) : target.axis ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) : null;
  };
  /**
   * @implements
   */


  Grid.prototype.convertFromPixel = function (ecModel, finder, value) {
    var target = this._findConvertTarget(finder);

    return target.cartesian ? target.cartesian.pointToData(value) : target.axis ? target.axis.coordToData(target.axis.toLocalCoord(value)) : null;
  };

  Grid.prototype._findConvertTarget = function (finder) {
    var seriesModel = finder.seriesModel;
    var xAxisModel = finder.xAxisModel || seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0];
    var yAxisModel = finder.yAxisModel || seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0];
    var gridModel = finder.gridModel;
    var coordsList = this._coordsList;
    var cartesian;
    var axis;

    if (seriesModel) {
      cartesian = seriesModel.coordinateSystem;
      indexOf(coordsList, cartesian) < 0 && (cartesian = null);
    } else if (xAxisModel && yAxisModel) {
      cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
    } else if (xAxisModel) {
      axis = this.getAxis('x', xAxisModel.componentIndex);
    } else if (yAxisModel) {
      axis = this.getAxis('y', yAxisModel.componentIndex);
    } // Lowest priority.
    else if (gridModel) {
        var grid = gridModel.coordinateSystem;

        if (grid === this) {
          cartesian = this._coordsList[0];
        }
      }

    return {
      cartesian: cartesian,
      axis: axis
    };
  };
  /**
   * @implements
   */


  Grid.prototype.containPoint = function (point) {
    var coord = this._coordsList[0];

    if (coord) {
      return coord.containPoint(point);
    }
  };
  /**
   * Initialize cartesian coordinate systems
   */


  Grid.prototype._initCartesian = function (gridModel, ecModel, api) {
    var _this = this;

    var grid = this;
    var axisPositionUsed = {
      left: false,
      right: false,
      top: false,
      bottom: false
    };
    var axesMap = {
      x: {},
      y: {}
    };
    var axesCount = {
      x: 0,
      y: 0
    }; // Create axis

    ecModel.eachComponent('xAxis', createAxisCreator('x'), this);
    ecModel.eachComponent('yAxis', createAxisCreator('y'), this);

    if (!axesCount.x || !axesCount.y) {
      // Roll back when there no either x or y axis
      this._axesMap = {};
      this._axesList = [];
      return;
    }

    this._axesMap = axesMap; // Create cartesian2d

    each$4(axesMap.x, function (xAxis, xAxisIndex) {
      each$4(axesMap.y, function (yAxis, yAxisIndex) {
        var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
        var cartesian = new Cartesian2D(key);
        cartesian.master = _this;
        cartesian.model = gridModel;
        _this._coordsMap[key] = cartesian;

        _this._coordsList.push(cartesian);

        cartesian.addAxis(xAxis);
        cartesian.addAxis(yAxis);
      });
    });

    function createAxisCreator(dimName) {
      return function (axisModel, idx) {
        if (!isAxisUsedInTheGrid(axisModel, gridModel)) {
          return;
        }

        var axisPosition = axisModel.get('position');

        if (dimName === 'x') {
          // Fix position
          if (axisPosition !== 'top' && axisPosition !== 'bottom') {
            // Default bottom of X
            axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom';
          }
        } else {
          // Fix position
          if (axisPosition !== 'left' && axisPosition !== 'right') {
            // Default left of Y
            axisPosition = axisPositionUsed.left ? 'right' : 'left';
          }
        }

        axisPositionUsed[axisPosition] = true;
        var axis = new Axis2D$1(dimName, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisPosition);
        var isCategory = axis.type === 'category';
        axis.onBand = isCategory && axisModel.get('boundaryGap');
        axis.inverse = axisModel.get('inverse'); // Inject axis into axisModel

        axisModel.axis = axis; // Inject axisModel into axis

        axis.model = axisModel; // Inject grid info axis

        axis.grid = grid; // Index of axis, can be used as key

        axis.index = idx;

        grid._axesList.push(axis);

        axesMap[dimName][idx] = axis;
        axesCount[dimName]++;
      };
    }
  };
  /**
   * Update cartesian properties from series.
   */


  Grid.prototype._updateScale = function (ecModel, gridModel) {
    // Reset scale
    each$4(this._axesList, function (axis) {
      axis.scale.setExtent(Infinity, -Infinity);

      if (axis.type === 'category') {
        var categorySortInfo = axis.model.get('categorySortInfo');
        axis.scale.setSortInfo(categorySortInfo);
      }
    });
    ecModel.eachSeries(function (seriesModel) {
      if (isCartesian2DSeries(seriesModel)) {
        var axesModelMap = findAxisModels(seriesModel);
        var xAxisModel = axesModelMap.xAxisModel;
        var yAxisModel = axesModelMap.yAxisModel;

        if (!isAxisUsedInTheGrid(xAxisModel, gridModel) || !isAxisUsedInTheGrid(yAxisModel, gridModel)) {
          return;
        }

        var cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
        var data = seriesModel.getData();
        var xAxis = cartesian.getAxis('x');
        var yAxis = cartesian.getAxis('y');
        unionExtent(data, xAxis);
        unionExtent(data, yAxis);
      }
    }, this);

    function unionExtent(data, axis) {
      each$4(getDataDimensionsOnAxis(data, axis.dim), function (dim) {
        axis.scale.unionExtentFromData(data, dim);
      });
    }
  };
  /**
   * @param dim 'x' or 'y' or 'auto' or null/undefined
   */


  Grid.prototype.getTooltipAxes = function (dim) {
    var baseAxes = [];
    var otherAxes = [];
    each$4(this.getCartesians(), function (cartesian) {
      var baseAxis = dim != null && dim !== 'auto' ? cartesian.getAxis(dim) : cartesian.getBaseAxis();
      var otherAxis = cartesian.getOtherAxis(baseAxis);
      indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
      indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
    });
    return {
      baseAxes: baseAxes,
      otherAxes: otherAxes
    };
  };

  Grid.create = function (ecModel, api) {
    var grids = [];
    ecModel.eachComponent('grid', function (gridModel, idx) {
      var grid = new Grid(gridModel, ecModel, api);
      grid.name = 'grid_' + idx; // dataSampling requires axis extent, so resize
      // should be performed in create stage.

      grid.resize(gridModel, api, true);
      gridModel.coordinateSystem = grid;
      grids.push(grid);
    }); // Inject the coordinateSystems into seriesModel

    ecModel.eachSeries(function (seriesModel) {
      if (!isCartesian2DSeries(seriesModel)) {
        return;
      }

      var axesModelMap = findAxisModels(seriesModel);
      var xAxisModel = axesModelMap.xAxisModel;
      var yAxisModel = axesModelMap.yAxisModel;
      var gridModel = xAxisModel.getCoordSysModel();

      var grid = gridModel.coordinateSystem;
      seriesModel.coordinateSystem = grid.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
    });
    return grids;
  }; // For deciding which dimensions to use when creating list data


  Grid.dimensions = cartesian2DDimensions;
  return Grid;
}();
/**
 * Check if the axis is used in the specified grid.
 */


function isAxisUsedInTheGrid(axisModel, gridModel) {
  return axisModel.getCoordSysModel() === gridModel;
}

function fixAxisOnZero(axesMap, otherAxisDim, axis, // Key: see `getOnZeroRecordKey`
onZeroRecords) {
  axis.getAxesOnZeroOf = function () {
    // TODO: onZero of multiple axes.
    return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : [];
  }; // onZero can not be enabled in these two situations:
  // 1. When any other axis is a category axis.
  // 2. When no axis is cross 0 point.


  var otherAxes = axesMap[otherAxisDim];
  var otherAxisOnZeroOf;
  var axisModel = axis.model;
  var onZero = axisModel.get(['axisLine', 'onZero']);
  var onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']);

  if (!onZero) {
    return;
  } // If target axis is specified.


  if (onZeroAxisIndex != null) {
    if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) {
      otherAxisOnZeroOf = otherAxes[onZeroAxisIndex];
    }
  } else {
    // Find the first available other axis.
    for (var idx in otherAxes) {
      if (otherAxes.hasOwnProperty(idx) && canOnZeroToAxis(otherAxes[idx]) // Consider that two Y axes on one value axis,
      // if both onZero, the two Y axes overlap.
      && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]) {
        otherAxisOnZeroOf = otherAxes[idx];
        break;
      }
    }
  }

  if (otherAxisOnZeroOf) {
    onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true;
  }

  function getOnZeroRecordKey(axis) {
    return axis.dim + '_' + axis.index;
  }
}

function canOnZeroToAxis(axis) {
  return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis);
}

function updateAxisTransform(axis, coordBase) {
  var axisExtent = axis.getExtent();
  var axisExtentSum = axisExtent[0] + axisExtent[1]; // Fast transform

  axis.toGlobalCoord = axis.dim === 'x' ? function (coord) {
    return coord + coordBase;
  } : function (coord) {
    return axisExtentSum - coord + coordBase;
  };
  axis.toLocalCoord = axis.dim === 'x' ? function (coord) {
    return coord - coordBase;
  } : function (coord) {
    return axisExtentSum - coord + coordBase;
  };
}

const Grid$1 = Grid;
/* Injected with object hook! */

var PI = Math.PI;
/**
 * A final axis is translated and rotated from a "standard axis".
 * So opt.position and opt.rotation is required.
 *
 * A standard axis is and axis from [0, 0] to [0, axisExtent[1]],
 * for example: (0, 0) ------------> (0, 50)
 *
 * nameDirection or tickDirection or labelDirection is 1 means tick
 * or label is below the standard axis, whereas is -1 means above
 * the standard axis. labelOffset means offset between label and axis,
 * which is useful when 'onZero', where axisLabel is in the grid and
 * label in outside grid.
 *
 * Tips: like always,
 * positive rotation represents anticlockwise, and negative rotation
 * represents clockwise.
 * The direction of position coordinate is the same as the direction
 * of screen coordinate.
 *
 * Do not need to consider axis 'inverse', which is auto processed by
 * axis extent.
 */

var AxisBuilder =
/** @class */
function () {
  function AxisBuilder(axisModel, opt) {
    this.group = new Group$3();
    this.opt = opt;
    this.axisModel = axisModel; // Default value

    defaults(opt, {
      labelOffset: 0,
      nameDirection: 1,
      tickDirection: 1,
      labelDirection: 1,
      silent: true,
      handleAutoShown: function () {
        return true;
      }
    }); // FIXME Not use a separate text group?

    var transformGroup = new Group$3({
      x: opt.position[0],
      y: opt.position[1],
      rotation: opt.rotation
    }); // this.group.add(transformGroup);
    // this._transformGroup = transformGroup;

    transformGroup.updateTransform();
    this._transformGroup = transformGroup;
  }

  AxisBuilder.prototype.hasBuilder = function (name) {
    return !!builders[name];
  };

  AxisBuilder.prototype.add = function (name) {
    builders[name](this.opt, this.axisModel, this.group, this._transformGroup);
  };

  AxisBuilder.prototype.getGroup = function () {
    return this.group;
  };

  AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) {
    var rotationDiff = remRadian(textRotation - axisRotation);
    var textAlign;
    var textVerticalAlign;

    if (isRadianAroundZero(rotationDiff)) {
      // Label is parallel with axis line.
      textVerticalAlign = direction > 0 ? 'top' : 'bottom';
      textAlign = 'center';
    } else if (isRadianAroundZero(rotationDiff - PI)) {
      // Label is inverse parallel with axis line.
      textVerticalAlign = direction > 0 ? 'bottom' : 'top';
      textAlign = 'center';
    } else {
      textVerticalAlign = 'middle';

      if (rotationDiff > 0 && rotationDiff < PI) {
        textAlign = direction > 0 ? 'right' : 'left';
      } else {
        textAlign = direction > 0 ? 'left' : 'right';
      }
    }

    return {
      rotation: rotationDiff,
      textAlign: textAlign,
      textVerticalAlign: textVerticalAlign
    };
  };

  AxisBuilder.makeAxisEventDataBase = function (axisModel) {
    var eventData = {
      componentType: axisModel.mainType,
      componentIndex: axisModel.componentIndex
    };
    eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
    return eventData;
  };

  AxisBuilder.isLabelSilent = function (axisModel) {
    var tooltipOpt = axisModel.get('tooltip');
    return axisModel.get('silent') // Consider mouse cursor, add these restrictions.
    || !(axisModel.get('triggerEvent') || tooltipOpt && tooltipOpt.show);
  };

  return AxisBuilder;
}();
var builders = {
  axisLine: function (opt, axisModel, group, transformGroup) {
    var shown = axisModel.get(['axisLine', 'show']);

    if (shown === 'auto' && opt.handleAutoShown) {
      shown = opt.handleAutoShown('axisLine');
    }

    if (!shown) {
      return;
    }

    var extent = axisModel.axis.getExtent();
    var matrix = transformGroup.transform;
    var pt1 = [extent[0], 0];
    var pt2 = [extent[1], 0];
    var inverse = pt1[0] > pt2[0];

    if (matrix) {
      applyTransform$1(pt1, pt1, matrix);
      applyTransform$1(pt2, pt2, matrix);
    }

    var lineStyle = extend({
      lineCap: 'round'
    }, axisModel.getModel(['axisLine', 'lineStyle']).getLineStyle());
    var line = new Line$1({
      shape: {
        x1: pt1[0],
        y1: pt1[1],
        x2: pt2[0],
        y2: pt2[1]
      },
      style: lineStyle,
      strokeContainThreshold: opt.strokeContainThreshold || 5,
      silent: true,
      z2: 1
    });
    subPixelOptimizeLine(line.shape, line.style.lineWidth);
    line.anid = 'line';
    group.add(line);
    var arrows = axisModel.get(['axisLine', 'symbol']);

    if (arrows != null) {
      var arrowSize = axisModel.get(['axisLine', 'symbolSize']);

      if (isString(arrows)) {
        // Use the same arrow for start and end point
        arrows = [arrows, arrows];
      }

      if (isString(arrowSize) || isNumber(arrowSize)) {
        // Use the same size for width and height
        arrowSize = [arrowSize, arrowSize];
      }

      var arrowOffset = normalizeSymbolOffset(axisModel.get(['axisLine', 'symbolOffset']) || 0, arrowSize);
      var symbolWidth_1 = arrowSize[0];
      var symbolHeight_1 = arrowSize[1];
      each$4([{
        rotate: opt.rotation + Math.PI / 2,
        offset: arrowOffset[0],
        r: 0
      }, {
        rotate: opt.rotation - Math.PI / 2,
        offset: arrowOffset[1],
        r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1]))
      }], function (point, index) {
        if (arrows[index] !== 'none' && arrows[index] != null) {
          var symbol = createSymbol(arrows[index], -symbolWidth_1 / 2, -symbolHeight_1 / 2, symbolWidth_1, symbolHeight_1, lineStyle.stroke, true); // Calculate arrow position with offset

          var r = point.r + point.offset;
          var pt = inverse ? pt2 : pt1;
          symbol.attr({
            rotation: point.rotate,
            x: pt[0] + r * Math.cos(opt.rotation),
            y: pt[1] - r * Math.sin(opt.rotation),
            silent: true,
            z2: 11
          });
          group.add(symbol);
        }
      });
    }
  },
  axisTickLabel: function (opt, axisModel, group, transformGroup) {
    var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt);
    var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt);
    fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
    buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart.
    // See https://github.com/apache/echarts/issues/14266 for more.

    if (axisModel.get(['axisLabel', 'hideOverlap'])) {
      var labelList = prepareLayoutList(map$1(labelEls, function (label) {
        return {
          label: label,
          priority: label.z2,
          defaultAttr: {
            ignore: label.ignore
          }
        };
      }));
      hideOverlap(labelList);
    }
  },
  axisName: function (opt, axisModel, group, transformGroup) {
    var name = retrieve(opt.axisName, axisModel.get('name'));

    if (!name) {
      return;
    }

    var nameLocation = axisModel.get('nameLocation');
    var nameDirection = opt.nameDirection;
    var textStyleModel = axisModel.getModel('nameTextStyle');
    var gap = axisModel.get('nameGap') || 0;
    var extent = axisModel.axis.getExtent();
    var gapSignal = extent[0] > extent[1] ? -1 : 1;
    var pos = [nameLocation === 'start' ? extent[0] - gapSignal * gap : nameLocation === 'end' ? extent[1] + gapSignal * gap : (extent[0] + extent[1]) / 2, // Reuse labelOffset.
    isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0];
    var labelLayout;
    var nameRotation = axisModel.get('nameRotate');

    if (nameRotation != null) {
      nameRotation = nameRotation * PI / 180; // To radian.
    }

    var axisNameAvailableWidth;

    if (isNameLocationCenter(nameLocation)) {
      labelLayout = AxisBuilder.innerTextLayout(opt.rotation, nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis.
      nameDirection);
    } else {
      labelLayout = endTextLayout(opt.rotation, nameLocation, nameRotation || 0, extent);
      axisNameAvailableWidth = opt.axisNameAvailableWidth;

      if (axisNameAvailableWidth != null) {
        axisNameAvailableWidth = Math.abs(axisNameAvailableWidth / Math.sin(labelLayout.rotation));
        !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null);
      }
    }

    var textFont = textStyleModel.getFont();
    var truncateOpt = axisModel.get('nameTruncate', true) || {};
    var ellipsis = truncateOpt.ellipsis;
    var maxWidth = retrieve(opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth);
    var textEl = new ZRText$1({
      x: pos[0],
      y: pos[1],
      rotation: labelLayout.rotation,
      silent: AxisBuilder.isLabelSilent(axisModel),
      style: createTextStyle(textStyleModel, {
        text: name,
        font: textFont,
        overflow: 'truncate',
        width: maxWidth,
        ellipsis: ellipsis,
        fill: textStyleModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']),
        align: textStyleModel.get('align') || labelLayout.textAlign,
        verticalAlign: textStyleModel.get('verticalAlign') || labelLayout.textVerticalAlign
      }),
      z2: 1
    });
    setTooltipConfig({
      el: textEl,
      componentModel: axisModel,
      itemName: name
    });
    textEl.__fullText = name; // Id for animation

    textEl.anid = 'name';

    if (axisModel.get('triggerEvent')) {
      var eventData = AxisBuilder.makeAxisEventDataBase(axisModel);
      eventData.targetType = 'axisName';
      eventData.name = name;
      getECData(textEl).eventData = eventData;
    } // FIXME


    transformGroup.add(textEl);
    textEl.updateTransform();
    group.add(textEl);
    textEl.decomposeTransform();
  }
};

function endTextLayout(rotation, textPosition, textRotate, extent) {
  var rotationDiff = remRadian(textRotate - rotation);
  var textAlign;
  var textVerticalAlign;
  var inverse = extent[0] > extent[1];
  var onLeft = textPosition === 'start' && !inverse || textPosition !== 'start' && inverse;

  if (isRadianAroundZero(rotationDiff - PI / 2)) {
    textVerticalAlign = onLeft ? 'bottom' : 'top';
    textAlign = 'center';
  } else if (isRadianAroundZero(rotationDiff - PI * 1.5)) {
    textVerticalAlign = onLeft ? 'top' : 'bottom';
    textAlign = 'center';
  } else {
    textVerticalAlign = 'middle';

    if (rotationDiff < PI * 1.5 && rotationDiff > PI / 2) {
      textAlign = onLeft ? 'left' : 'right';
    } else {
      textAlign = onLeft ? 'right' : 'left';
    }
  }

  return {
    rotation: rotationDiff,
    textAlign: textAlign,
    textVerticalAlign: textVerticalAlign
  };
}

function fixMinMaxLabelShow(axisModel, labelEls, tickEls) {
  if (shouldShowAllLabels(axisModel.axis)) {
    return;
  } // If min or max are user set, we need to check
  // If the tick on min(max) are overlap on their neighbour tick
  // If they are overlapped, we need to hide the min(max) tick label


  var showMinLabel = axisModel.get(['axisLabel', 'showMinLabel']);
  var showMaxLabel = axisModel.get(['axisLabel', 'showMaxLabel']); // FIXME
  // Have not consider onBand yet, where tick els is more than label els.

  labelEls = labelEls || [];
  tickEls = tickEls || [];
  var firstLabel = labelEls[0];
  var nextLabel = labelEls[1];
  var lastLabel = labelEls[labelEls.length - 1];
  var prevLabel = labelEls[labelEls.length - 2];
  var firstTick = tickEls[0];
  var nextTick = tickEls[1];
  var lastTick = tickEls[tickEls.length - 1];
  var prevTick = tickEls[tickEls.length - 2];

  if (showMinLabel === false) {
    ignoreEl(firstLabel);
    ignoreEl(firstTick);
  } else if (isTwoLabelOverlapped(firstLabel, nextLabel)) {
    if (showMinLabel) {
      ignoreEl(nextLabel);
      ignoreEl(nextTick);
    } else {
      ignoreEl(firstLabel);
      ignoreEl(firstTick);
    }
  }

  if (showMaxLabel === false) {
    ignoreEl(lastLabel);
    ignoreEl(lastTick);
  } else if (isTwoLabelOverlapped(prevLabel, lastLabel)) {
    if (showMaxLabel) {
      ignoreEl(prevLabel);
      ignoreEl(prevTick);
    } else {
      ignoreEl(lastLabel);
      ignoreEl(lastTick);
    }
  }
}

function ignoreEl(el) {
  el && (el.ignore = true);
}

function isTwoLabelOverlapped(current, next) {
  // current and next has the same rotation.
  var firstRect = current && current.getBoundingRect().clone();
  var nextRect = next && next.getBoundingRect().clone();

  if (!firstRect || !nextRect) {
    return;
  } // When checking intersect of two rotated labels, we use mRotationBack
  // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`.


  var mRotationBack = identity([]);
  rotate(mRotationBack, mRotationBack, -current.rotation);
  firstRect.applyTransform(mul([], mRotationBack, current.getLocalTransform()));
  nextRect.applyTransform(mul([], mRotationBack, next.getLocalTransform()));
  return firstRect.intersect(nextRect);
}

function isNameLocationCenter(nameLocation) {
  return nameLocation === 'middle' || nameLocation === 'center';
}

function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, anidPrefix) {
  var tickEls = [];
  var pt1 = [];
  var pt2 = [];

  for (var i = 0; i < ticksCoords.length; i++) {
    var tickCoord = ticksCoords[i].coord;
    pt1[0] = tickCoord;
    pt1[1] = 0;
    pt2[0] = tickCoord;
    pt2[1] = tickEndCoord;

    if (tickTransform) {
      applyTransform$1(pt1, pt1, tickTransform);
      applyTransform$1(pt2, pt2, tickTransform);
    } // Tick line, Not use group transform to have better line draw


    var tickEl = new Line$1({
      shape: {
        x1: pt1[0],
        y1: pt1[1],
        x2: pt2[0],
        y2: pt2[1]
      },
      style: tickLineStyle,
      z2: 2,
      autoBatch: true,
      silent: true
    });
    subPixelOptimizeLine(tickEl.shape, tickEl.style.lineWidth);
    tickEl.anid = anidPrefix + '_' + ticksCoords[i].tickValue;
    tickEls.push(tickEl);
  }

  return tickEls;
}

function buildAxisMajorTicks(group, transformGroup, axisModel, opt) {
  var axis = axisModel.axis;
  var tickModel = axisModel.getModel('axisTick');
  var shown = tickModel.get('show');

  if (shown === 'auto' && opt.handleAutoShown) {
    shown = opt.handleAutoShown('axisTick');
  }

  if (!shown || axis.scale.isBlank()) {
    return;
  }

  var lineStyleModel = tickModel.getModel('lineStyle');
  var tickEndCoord = opt.tickDirection * tickModel.get('length');
  var ticksCoords = axis.getTicksCoords();
  var ticksEls = createTicks(ticksCoords, transformGroup.transform, tickEndCoord, defaults(lineStyleModel.getLineStyle(), {
    stroke: axisModel.get(['axisLine', 'lineStyle', 'color'])
  }), 'ticks');

  for (var i = 0; i < ticksEls.length; i++) {
    group.add(ticksEls[i]);
  }

  return ticksEls;
}

function buildAxisMinorTicks(group, transformGroup, axisModel, tickDirection) {
  var axis = axisModel.axis;
  var minorTickModel = axisModel.getModel('minorTick');

  if (!minorTickModel.get('show') || axis.scale.isBlank()) {
    return;
  }

  var minorTicksCoords = axis.getMinorTicksCoords();

  if (!minorTicksCoords.length) {
    return;
  }

  var lineStyleModel = minorTickModel.getModel('lineStyle');
  var tickEndCoord = tickDirection * minorTickModel.get('length');
  var minorTickLineStyle = defaults(lineStyleModel.getLineStyle(), defaults(axisModel.getModel('axisTick').getLineStyle(), {
    stroke: axisModel.get(['axisLine', 'lineStyle', 'color'])
  }));

  for (var i = 0; i < minorTicksCoords.length; i++) {
    var minorTicksEls = createTicks(minorTicksCoords[i], transformGroup.transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i);

    for (var k = 0; k < minorTicksEls.length; k++) {
      group.add(minorTicksEls[k]);
    }
  }
}

function buildAxisLabel(group, transformGroup, axisModel, opt) {
  var axis = axisModel.axis;
  var show = retrieve(opt.axisLabelShow, axisModel.get(['axisLabel', 'show']));

  if (!show || axis.scale.isBlank()) {
    return;
  }

  var labelModel = axisModel.getModel('axisLabel');
  var labelMargin = labelModel.get('margin');
  var labels = axis.getViewLabels(); // Special label rotate.

  var labelRotation = (retrieve(opt.labelRotate, labelModel.get('rotate')) || 0) * PI / 180;
  var labelLayout = AxisBuilder.innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
  var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true);
  var labelEls = [];
  var silent = AxisBuilder.isLabelSilent(axisModel);
  var triggerEvent = axisModel.get('triggerEvent');
  each$4(labels, function (labelItem, index) {
    var tickValue = axis.scale.type === 'ordinal' ? axis.scale.getRawOrdinalNumber(labelItem.tickValue) : labelItem.tickValue;
    var formattedLabel = labelItem.formattedLabel;
    var rawLabel = labelItem.rawLabel;
    var itemLabelModel = labelModel;

    if (rawCategoryData && rawCategoryData[tickValue]) {
      var rawCategoryItem = rawCategoryData[tickValue];

      if (isObject$2(rawCategoryItem) && rawCategoryItem.textStyle) {
        itemLabelModel = new Model$1(rawCategoryItem.textStyle, labelModel, axisModel.ecModel);
      }
    }

    var textColor = itemLabelModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']);
    var tickCoord = axis.dataToCoord(tickValue);
    var textEl = new ZRText$1({
      x: tickCoord,
      y: opt.labelOffset + opt.labelDirection * labelMargin,
      rotation: labelLayout.rotation,
      silent: silent,
      z2: 10 + (labelItem.level || 0),
      style: createTextStyle(itemLabelModel, {
        text: formattedLabel,
        align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign,
        verticalAlign: itemLabelModel.getShallow('verticalAlign', true) || itemLabelModel.getShallow('baseline', true) || labelLayout.textVerticalAlign,
        fill: isFunction(textColor) ? textColor( // (1) In category axis with data zoom, tick is not the original
        // index of axis.data. So tick should not be exposed to user
        // in category axis.
        // (2) Compatible with previous version, which always use formatted label as
        // input. But in interval scale the formatted label is like '223,445', which
        // maked user replace ','. So we modify it to return original val but remain
        // it as 'string' to avoid error in replacing.
        axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, index) : textColor
      })
    });
    textEl.anid = 'label_' + tickValue; // Pack data for mouse event

    if (triggerEvent) {
      var eventData = AxisBuilder.makeAxisEventDataBase(axisModel);
      eventData.targetType = 'axisLabel';
      eventData.value = rawLabel;
      eventData.tickIndex = index;

      if (axis.type === 'category') {
        eventData.dataIndex = tickValue;
      }

      getECData(textEl).eventData = eventData;
    } // FIXME


    transformGroup.add(textEl);
    textEl.updateTransform();
    labelEls.push(textEl);
    group.add(textEl);
    textEl.decomposeTransform();
  });
  return labelEls;
}

const AxisBuilder$1 = AxisBuilder;
/* Injected with object hook! */

// allAxesInfo should be updated when setOption performed.

function collect(ecModel, api) {
  var result = {
    /**
     * key: makeKey(axis.model)
     * value: {
     *      axis,
     *      coordSys,
     *      axisPointerModel,
     *      triggerTooltip,
     *      triggerEmphasis,
     *      involveSeries,
     *      snap,
     *      seriesModels,
     *      seriesDataCount
     * }
     */
    axesInfo: {},
    seriesInvolved: false,

    /**
     * key: makeKey(coordSys.model)
     * value: Object: key makeKey(axis.model), value: axisInfo
     */
    coordSysAxesInfo: {},
    coordSysMap: {}
  };
  collectAxesInfo(result, ecModel, api); // Check seriesInvolved for performance, in case too many series in some chart.

  result.seriesInvolved && collectSeriesInfo(result, ecModel);
  return result;
}

function collectAxesInfo(result, ecModel, api) {
  var globalTooltipModel = ecModel.getComponent('tooltip');
  var globalAxisPointerModel = ecModel.getComponent('axisPointer'); // links can only be set on global.

  var linksOption = globalAxisPointerModel.get('link', true) || [];
  var linkGroups = []; // Collect axes info.

  each$4(api.getCoordinateSystems(), function (coordSys) {
    // Some coordinate system do not support axes, like geo.
    if (!coordSys.axisPointerEnabled) {
      return;
    }

    var coordSysKey = makeKey(coordSys.model);
    var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {};
    result.coordSysMap[coordSysKey] = coordSys; // Set tooltip (like 'cross') is a convenient way to show axisPointer
    // for user. So we enable setting tooltip on coordSys model.

    var coordSysModel = coordSys.model;
    var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel);
    each$4(coordSys.getAxes(), curry$1(saveTooltipAxisInfo, false, null)); // If axis tooltip used, choose tooltip axis for each coordSys.
    // Notice this case: coordSys is `grid` but not `cartesian2D` here.

    if (coordSys.getTooltipAxes && globalTooltipModel // If tooltip.showContent is set as false, tooltip will not
    // show but axisPointer will show as normal.
    && baseTooltipModel.get('show')) {
      // Compatible with previous logic. But series.tooltip.trigger: 'axis'
      // or series.data[n].tooltip.trigger: 'axis' are not support any more.
      var triggerAxis = baseTooltipModel.get('trigger') === 'axis';
      var cross = baseTooltipModel.get(['axisPointer', 'type']) === 'cross';
      var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get(['axisPointer', 'axis']));

      if (triggerAxis || cross) {
        each$4(tooltipAxes.baseAxes, curry$1(saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis));
      }

      if (cross) {
        each$4(tooltipAxes.otherAxes, curry$1(saveTooltipAxisInfo, 'cross', false));
      }
    } // fromTooltip: true | false | 'cross'
    // triggerTooltip: true | false | null


    function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) {
      var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel);
      var axisPointerShow = axisPointerModel.get('show');

      if (!axisPointerShow || axisPointerShow === 'auto' && !fromTooltip && !isHandleTrigger(axisPointerModel)) {
        return;
      }

      if (triggerTooltip == null) {
        triggerTooltip = axisPointerModel.get('triggerTooltip');
      }

      axisPointerModel = fromTooltip ? makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) : axisPointerModel;
      var snap = axisPointerModel.get('snap');
      var triggerEmphasis = axisPointerModel.get('triggerEmphasis');
      var axisKey = makeKey(axis.model);
      var involveSeries = triggerTooltip || snap || axis.type === 'category'; // If result.axesInfo[key] exist, override it (tooltip has higher priority).

      var axisInfo = result.axesInfo[axisKey] = {
        key: axisKey,
        axis: axis,
        coordSys: coordSys,
        axisPointerModel: axisPointerModel,
        triggerTooltip: triggerTooltip,
        triggerEmphasis: triggerEmphasis,
        involveSeries: involveSeries,
        snap: snap,
        useHandle: isHandleTrigger(axisPointerModel),
        seriesModels: [],
        linkGroup: null
      };
      axesInfoInCoordSys[axisKey] = axisInfo;
      result.seriesInvolved = result.seriesInvolved || involveSeries;
      var groupIndex = getLinkGroupIndex(linksOption, axis);

      if (groupIndex != null) {
        var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {
          axesInfo: {}
        });
        linkGroup.axesInfo[axisKey] = axisInfo;
        linkGroup.mapper = linksOption[groupIndex].mapper;
        axisInfo.linkGroup = linkGroup;
      }
    }
  });
}

function makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) {
  var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer');
  var fields = ['type', 'snap', 'lineStyle', 'shadowStyle', 'label', 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z'];
  var volatileOption = {};
  each$4(fields, function (field) {
    volatileOption[field] = clone$2(tooltipAxisPointerModel.get(field));
  }); // category axis do not auto snap, otherwise some tick that do not
  // has value can not be hovered. value/time/log axis default snap if
  // triggered from tooltip and trigger tooltip.

  volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; // Compatible with previous behavior, tooltip axis does not show label by default.
  // Only these properties can be overridden from tooltip to axisPointer.

  if (tooltipAxisPointerModel.get('type') === 'cross') {
    volatileOption.type = 'line';
  }

  var labelOption = volatileOption.label || (volatileOption.label = {}); // Follow the convention, do not show label when triggered by tooltip by default.

  labelOption.show == null && (labelOption.show = false);

  if (fromTooltip === 'cross') {
    // When 'cross', both axes show labels.
    var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get(['label', 'show']);
    labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true; // If triggerTooltip, this is a base axis, which should better not use cross style
    // (cross style is dashed by default)

    if (!triggerTooltip) {
      var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle');
      crossStyle && defaults(labelOption, crossStyle.textStyle);
    }
  }

  return axis.model.getModel('axisPointer', new Model$1(volatileOption, globalAxisPointerModel, ecModel));
}

function collectSeriesInfo(result, ecModel) {
  // Prepare data for axis trigger
  ecModel.eachSeries(function (seriesModel) {
    // Notice this case: this coordSys is `cartesian2D` but not `grid`.
    var coordSys = seriesModel.coordinateSystem;
    var seriesTooltipTrigger = seriesModel.get(['tooltip', 'trigger'], true);
    var seriesTooltipShow = seriesModel.get(['tooltip', 'show'], true);

    if (!coordSys || seriesTooltipTrigger === 'none' || seriesTooltipTrigger === false || seriesTooltipTrigger === 'item' || seriesTooltipShow === false || seriesModel.get(['axisPointer', 'show'], true) === false) {
      return;
    }

    each$4(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) {
      var axis = axisInfo.axis;

      if (coordSys.getAxis(axis.dim) === axis) {
        axisInfo.seriesModels.push(seriesModel);
        axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0);
        axisInfo.seriesDataCount += seriesModel.getData().count();
      }
    });
  });
}
/**
 * For example:
 * {
 *     axisPointer: {
 *         links: [{
 *             xAxisIndex: [2, 4],
 *             yAxisIndex: 'all'
 *         }, {
 *             xAxisId: ['a5', 'a7'],
 *             xAxisName: 'xxx'
 *         }]
 *     }
 * }
 */


function getLinkGroupIndex(linksOption, axis) {
  var axisModel = axis.model;
  var dim = axis.dim;

  for (var i = 0; i < linksOption.length; i++) {
    var linkOption = linksOption[i] || {};

    if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)) {
      return i;
    }
  }
}

function checkPropInLink(linkPropValue, axisPropValue) {
  return linkPropValue === 'all' || isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0 || linkPropValue === axisPropValue;
}

function fixValue(axisModel) {
  var axisInfo = getAxisInfo(axisModel);

  if (!axisInfo) {
    return;
  }

  var axisPointerModel = axisInfo.axisPointerModel;
  var scale = axisInfo.axis.scale;
  var option = axisPointerModel.option;
  var status = axisPointerModel.get('status');
  var value = axisPointerModel.get('value'); // Parse init value for category and time axis.

  if (value != null) {
    value = scale.parse(value);
  }

  var useHandle = isHandleTrigger(axisPointerModel); // If `handle` used, `axisPointer` will always be displayed, so value
  // and status should be initialized.

  if (status == null) {
    option.status = useHandle ? 'show' : 'hide';
  }

  var extent = scale.getExtent().slice();
  extent[0] > extent[1] && extent.reverse();

  if ( // Pick a value on axis when initializing.
  value == null // If both `handle` and `dataZoom` are used, value may be out of axis extent,
  // where we should re-pick a value to keep `handle` displaying normally.
  || value > extent[1]) {
    // Make handle displayed on the end of the axis when init, which looks better.
    value = extent[1];
  }

  if (value < extent[0]) {
    value = extent[0];
  }

  option.value = value;

  if (useHandle) {
    option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show';
  }
}
function getAxisInfo(axisModel) {
  var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo;
  return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)];
}
function getAxisPointerModel(axisModel) {
  var axisInfo = getAxisInfo(axisModel);
  return axisInfo && axisInfo.axisPointerModel;
}

function isHandleTrigger(axisPointerModel) {
  return !!axisPointerModel.get(['handle', 'show']);
}
/**
 * @param {module:echarts/model/Model} model
 * @return {string} unique key
 */


function makeKey(model) {
  return model.type + '||' + model.id;
}
/* Injected with object hook! */

var axisPointerClazz = {};
/**
 * Base class of AxisView.
 */

var AxisView =
/** @class */
function (_super) {
  __extends(AxisView, _super);

  function AxisView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = AxisView.type;
    return _this;
  }
  /**
   * @override
   */


  AxisView.prototype.render = function (axisModel, ecModel, api, payload) {
    // FIXME
    // This process should proformed after coordinate systems updated
    // (axis scale updated), and should be performed each time update.
    // So put it here temporarily, although it is not appropriate to
    // put a model-writing procedure in `view`.
    this.axisPointerClass && fixValue(axisModel);

    _super.prototype.render.apply(this, arguments);

    this._doUpdateAxisPointerClass(axisModel, api, true);
  };
  /**
   * Action handler.
   */


  AxisView.prototype.updateAxisPointer = function (axisModel, ecModel, api, payload) {
    this._doUpdateAxisPointerClass(axisModel, api, false);
  };
  /**
   * @override
   */


  AxisView.prototype.remove = function (ecModel, api) {
    var axisPointer = this._axisPointer;
    axisPointer && axisPointer.remove(api);
  };
  /**
   * @override
   */


  AxisView.prototype.dispose = function (ecModel, api) {
    this._disposeAxisPointer(api);

    _super.prototype.dispose.apply(this, arguments);
  };

  AxisView.prototype._doUpdateAxisPointerClass = function (axisModel, api, forceRender) {
    var Clazz = AxisView.getAxisPointerClass(this.axisPointerClass);

    if (!Clazz) {
      return;
    }

    var axisPointerModel = getAxisPointerModel(axisModel);
    axisPointerModel ? (this._axisPointer || (this._axisPointer = new Clazz())).render(axisModel, axisPointerModel, api, forceRender) : this._disposeAxisPointer(api);
  };

  AxisView.prototype._disposeAxisPointer = function (api) {
    this._axisPointer && this._axisPointer.dispose(api);
    this._axisPointer = null;
  };

  AxisView.registerAxisPointerClass = function (type, clazz) {

    axisPointerClazz[type] = clazz;
  };

  AxisView.getAxisPointerClass = function (type) {
    return type && axisPointerClazz[type];
  };
  AxisView.type = 'axis';
  return AxisView;
}(ComponentView$1);

const AxisView$1 = AxisView;
/* Injected with object hook! */

var inner$3 = makeInner();
function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) {
  var axis = axisModel.axis;

  if (axis.scale.isBlank()) {
    return;
  } // TODO: TYPE


  var splitAreaModel = axisModel.getModel('splitArea');
  var areaStyleModel = splitAreaModel.getModel('areaStyle');
  var areaColors = areaStyleModel.get('color');
  var gridRect = gridModel.coordinateSystem.getRect();
  var ticksCoords = axis.getTicksCoords({
    tickModel: splitAreaModel,
    clamp: true
  });

  if (!ticksCoords.length) {
    return;
  } // For Making appropriate splitArea animation, the color and anid
  // should be corresponding to previous one if possible.


  var areaColorsLen = areaColors.length;
  var lastSplitAreaColors = inner$3(axisView).splitAreaColors;
  var newSplitAreaColors = createHashMap();
  var colorIndex = 0;

  if (lastSplitAreaColors) {
    for (var i = 0; i < ticksCoords.length; i++) {
      var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue);

      if (cIndex != null) {
        colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen;
        break;
      }
    }
  }

  var prev = axis.toGlobalCoord(ticksCoords[0].coord);
  var areaStyle = areaStyleModel.getAreaStyle();
  areaColors = isArray(areaColors) ? areaColors : [areaColors];

  for (var i = 1; i < ticksCoords.length; i++) {
    var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
    var x = void 0;
    var y = void 0;
    var width = void 0;
    var height = void 0;

    if (axis.isHorizontal()) {
      x = prev;
      y = gridRect.y;
      width = tickCoord - x;
      height = gridRect.height;
      prev = x + width;
    } else {
      x = gridRect.x;
      y = prev;
      width = gridRect.width;
      height = tickCoord - y;
      prev = y + height;
    }

    var tickValue = ticksCoords[i - 1].tickValue;
    tickValue != null && newSplitAreaColors.set(tickValue, colorIndex);
    axisGroup.add(new Rect$1({
      anid: tickValue != null ? 'area_' + tickValue : null,
      shape: {
        x: x,
        y: y,
        width: width,
        height: height
      },
      style: defaults({
        fill: areaColors[colorIndex]
      }, areaStyle),
      autoBatch: true,
      silent: true
    }));
    colorIndex = (colorIndex + 1) % areaColorsLen;
  }

  inner$3(axisView).splitAreaColors = newSplitAreaColors;
}
function rectCoordAxisHandleRemove(axisView) {
  inner$3(axisView).splitAreaColors = null;
}
/* Injected with object hook! */

var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName'];
var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine'];

var CartesianAxisView =
/** @class */
function (_super) {
  __extends(CartesianAxisView, _super);

  function CartesianAxisView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = CartesianAxisView.type;
    _this.axisPointerClass = 'CartesianAxisPointer';
    return _this;
  }
  /**
   * @override
   */


  CartesianAxisView.prototype.render = function (axisModel, ecModel, api, payload) {
    this.group.removeAll();
    var oldAxisGroup = this._axisGroup;
    this._axisGroup = new Group$3();
    this.group.add(this._axisGroup);

    if (!axisModel.get('show')) {
      return;
    }

    var gridModel = axisModel.getCoordSysModel();
    var layout$1 = layout(gridModel, axisModel);
    var axisBuilder = new AxisBuilder$1(axisModel, extend({
      handleAutoShown: function (elementType) {
        var cartesians = gridModel.coordinateSystem.getCartesians();

        for (var i = 0; i < cartesians.length; i++) {
          if (isIntervalOrLogScale(cartesians[i].getOtherAxis(axisModel.axis).scale)) {
            // Still show axis tick or axisLine if other axis is value / log
            return true;
          }
        } // Not show axisTick or axisLine if other axis is category / time


        return false;
      }
    }, layout$1));
    each$4(axisBuilderAttrs, axisBuilder.add, axisBuilder);

    this._axisGroup.add(axisBuilder.getGroup());

    each$4(selfBuilderAttrs, function (name) {
      if (axisModel.get([name, 'show'])) {
        axisElementBuilders[name](this, this._axisGroup, axisModel, gridModel);
      }
    }, this); // THIS is a special case for bar racing chart.
    // Update the axis label from the natural initial layout to
    // sorted layout should has no animation.

    var isInitialSortFromBarRacing = payload && payload.type === 'changeAxisOrder' && payload.isInitSort;

    if (!isInitialSortFromBarRacing) {
      groupTransition(oldAxisGroup, this._axisGroup, axisModel);
    }

    _super.prototype.render.call(this, axisModel, ecModel, api, payload);
  };

  CartesianAxisView.prototype.remove = function () {
    rectCoordAxisHandleRemove(this);
  };

  CartesianAxisView.type = 'cartesianAxis';
  return CartesianAxisView;
}(AxisView$1);

var axisElementBuilders = {
  splitLine: function (axisView, axisGroup, axisModel, gridModel) {
    var axis = axisModel.axis;

    if (axis.scale.isBlank()) {
      return;
    }

    var splitLineModel = axisModel.getModel('splitLine');
    var lineStyleModel = splitLineModel.getModel('lineStyle');
    var lineColors = lineStyleModel.get('color');
    lineColors = isArray(lineColors) ? lineColors : [lineColors];
    var gridRect = gridModel.coordinateSystem.getRect();
    var isHorizontal = axis.isHorizontal();
    var lineCount = 0;
    var ticksCoords = axis.getTicksCoords({
      tickModel: splitLineModel
    });
    var p1 = [];
    var p2 = [];
    var lineStyle = lineStyleModel.getLineStyle();

    for (var i = 0; i < ticksCoords.length; i++) {
      var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);

      if (isHorizontal) {
        p1[0] = tickCoord;
        p1[1] = gridRect.y;
        p2[0] = tickCoord;
        p2[1] = gridRect.y + gridRect.height;
      } else {
        p1[0] = gridRect.x;
        p1[1] = tickCoord;
        p2[0] = gridRect.x + gridRect.width;
        p2[1] = tickCoord;
      }

      var colorIndex = lineCount++ % lineColors.length;
      var tickValue = ticksCoords[i].tickValue;
      var line = new Line$1({
        anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null,
        autoBatch: true,
        shape: {
          x1: p1[0],
          y1: p1[1],
          x2: p2[0],
          y2: p2[1]
        },
        style: defaults({
          stroke: lineColors[colorIndex]
        }, lineStyle),
        silent: true
      });
      subPixelOptimizeLine(line.shape, lineStyle.lineWidth);
      axisGroup.add(line);
    }
  },
  minorSplitLine: function (axisView, axisGroup, axisModel, gridModel) {
    var axis = axisModel.axis;
    var minorSplitLineModel = axisModel.getModel('minorSplitLine');
    var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
    var gridRect = gridModel.coordinateSystem.getRect();
    var isHorizontal = axis.isHorizontal();
    var minorTicksCoords = axis.getMinorTicksCoords();

    if (!minorTicksCoords.length) {
      return;
    }

    var p1 = [];
    var p2 = [];
    var lineStyle = lineStyleModel.getLineStyle();

    for (var i = 0; i < minorTicksCoords.length; i++) {
      for (var k = 0; k < minorTicksCoords[i].length; k++) {
        var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord);

        if (isHorizontal) {
          p1[0] = tickCoord;
          p1[1] = gridRect.y;
          p2[0] = tickCoord;
          p2[1] = gridRect.y + gridRect.height;
        } else {
          p1[0] = gridRect.x;
          p1[1] = tickCoord;
          p2[0] = gridRect.x + gridRect.width;
          p2[1] = tickCoord;
        }

        var line = new Line$1({
          anid: 'minor_line_' + minorTicksCoords[i][k].tickValue,
          autoBatch: true,
          shape: {
            x1: p1[0],
            y1: p1[1],
            x2: p2[0],
            y2: p2[1]
          },
          style: lineStyle,
          silent: true
        });
        subPixelOptimizeLine(line.shape, lineStyle.lineWidth);
        axisGroup.add(line);
      }
    }
  },
  splitArea: function (axisView, axisGroup, axisModel, gridModel) {
    rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel);
  }
};

var CartesianXAxisView =
/** @class */
function (_super) {
  __extends(CartesianXAxisView, _super);

  function CartesianXAxisView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = CartesianXAxisView.type;
    return _this;
  }

  CartesianXAxisView.type = 'xAxis';
  return CartesianXAxisView;
}(CartesianAxisView);

var CartesianYAxisView =
/** @class */
function (_super) {
  __extends(CartesianYAxisView, _super);

  function CartesianYAxisView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = CartesianXAxisView.type;
    return _this;
  }

  CartesianYAxisView.type = 'yAxis';
  return CartesianYAxisView;
}(CartesianAxisView);
/* Injected with object hook! */

var GridView =
/** @class */
function (_super) {
  __extends(GridView, _super);

  function GridView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = 'grid';
    return _this;
  }

  GridView.prototype.render = function (gridModel, ecModel) {
    this.group.removeAll();

    if (gridModel.get('show')) {
      this.group.add(new Rect$1({
        shape: gridModel.coordinateSystem.getRect(),
        style: defaults({
          fill: gridModel.get('backgroundColor')
        }, gridModel.getItemStyle()),
        silent: true,
        z2: -1
      }));
    }
  };

  GridView.type = 'grid';
  return GridView;
}(ComponentView$1);

var extraOption = {
  // gridIndex: 0,
  // gridId: '',
  offset: 0
};
function install$7(registers) {
  registers.registerComponentView(GridView);
  registers.registerComponentModel(GridModel$1);
  registers.registerCoordinateSystem('cartesian2d', Grid$1);
  axisModelCreator(registers, 'x', CartesianAxisModel, extraOption);
  axisModelCreator(registers, 'y', CartesianAxisModel, extraOption);
  registers.registerComponentView(CartesianXAxisView);
  registers.registerComponentView(CartesianYAxisView);
  registers.registerPreprocessor(function (option) {
    // Only create grid when need
    if (option.xAxis && option.yAxis && !option.grid) {
      option.grid = {};
    }
  });
}
/* Injected with object hook! */

var inner$2 = makeInner();
var clone = clone$2;
var bind = bind$1;
/**
 * Base axis pointer class in 2D.
 */

var BaseAxisPointer =
/** @class */
function () {
  function BaseAxisPointer() {
    this._dragging = false;
    /**
     * In px, arbitrary value. Do not set too small,
     * no animation is ok for most cases.
     */

    this.animationThreshold = 15;
  }
  /**
   * @implement
   */


  BaseAxisPointer.prototype.render = function (axisModel, axisPointerModel, api, forceRender) {
    var value = axisPointerModel.get('value');
    var status = axisPointerModel.get('status'); // Bind them to `this`, not in closure, otherwise they will not
    // be replaced when user calling setOption in not merge mode.

    this._axisModel = axisModel;
    this._axisPointerModel = axisPointerModel;
    this._api = api; // Optimize: `render` will be called repeatedly during mouse move.
    // So it is power consuming if performing `render` each time,
    // especially on mobile device.

    if (!forceRender && this._lastValue === value && this._lastStatus === status) {
      return;
    }

    this._lastValue = value;
    this._lastStatus = status;
    var group = this._group;
    var handle = this._handle;

    if (!status || status === 'hide') {
      // Do not clear here, for animation better.
      group && group.hide();
      handle && handle.hide();
      return;
    }

    group && group.show();
    handle && handle.show(); // Otherwise status is 'show'

    var elOption = {};
    this.makeElOption(elOption, value, axisModel, axisPointerModel, api); // Enable change axis pointer type.

    var graphicKey = elOption.graphicKey;

    if (graphicKey !== this._lastGraphicKey) {
      this.clear(api);
    }

    this._lastGraphicKey = graphicKey;
    var moveAnimation = this._moveAnimation = this.determineAnimation(axisModel, axisPointerModel);

    if (!group) {
      group = this._group = new Group$3();
      this.createPointerEl(group, elOption, axisModel, axisPointerModel);
      this.createLabelEl(group, elOption, axisModel, axisPointerModel);
      api.getZr().add(group);
    } else {
      var doUpdateProps = curry$1(updateProps, axisPointerModel, moveAnimation);
      this.updatePointerEl(group, elOption, doUpdateProps);
      this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel);
    }

    updateMandatoryProps(group, axisPointerModel, true);

    this._renderHandle(value);
  };
  /**
   * @implement
   */


  BaseAxisPointer.prototype.remove = function (api) {
    this.clear(api);
  };
  /**
   * @implement
   */


  BaseAxisPointer.prototype.dispose = function (api) {
    this.clear(api);
  };
  /**
   * @protected
   */


  BaseAxisPointer.prototype.determineAnimation = function (axisModel, axisPointerModel) {
    var animation = axisPointerModel.get('animation');
    var axis = axisModel.axis;
    var isCategoryAxis = axis.type === 'category';
    var useSnap = axisPointerModel.get('snap'); // Value axis without snap always do not snap.

    if (!useSnap && !isCategoryAxis) {
      return false;
    }

    if (animation === 'auto' || animation == null) {
      var animationThreshold = this.animationThreshold;

      if (isCategoryAxis && axis.getBandWidth() > animationThreshold) {
        return true;
      } // It is important to auto animation when snap used. Consider if there is
      // a dataZoom, animation will be disabled when too many points exist, while
      // it will be enabled for better visual effect when little points exist.


      if (useSnap) {
        var seriesDataCount = getAxisInfo(axisModel).seriesDataCount;
        var axisExtent = axis.getExtent(); // Approximate band width

        return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold;
      }

      return false;
    }

    return animation === true;
  };
  /**
   * add {pointer, label, graphicKey} to elOption
   * @protected
   */


  BaseAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {// Should be implemenented by sub-class.
  };
  /**
   * @protected
   */


  BaseAxisPointer.prototype.createPointerEl = function (group, elOption, axisModel, axisPointerModel) {
    var pointerOption = elOption.pointer;

    if (pointerOption) {
      var pointerEl = inner$2(group).pointerEl = new graphic[pointerOption.type](clone(elOption.pointer));
      group.add(pointerEl);
    }
  };
  /**
   * @protected
   */


  BaseAxisPointer.prototype.createLabelEl = function (group, elOption, axisModel, axisPointerModel) {
    if (elOption.label) {
      var labelEl = inner$2(group).labelEl = new ZRText$1(clone(elOption.label));
      group.add(labelEl);
      updateLabelShowHide(labelEl, axisPointerModel);
    }
  };
  /**
   * @protected
   */


  BaseAxisPointer.prototype.updatePointerEl = function (group, elOption, updateProps) {
    var pointerEl = inner$2(group).pointerEl;

    if (pointerEl && elOption.pointer) {
      pointerEl.setStyle(elOption.pointer.style);
      updateProps(pointerEl, {
        shape: elOption.pointer.shape
      });
    }
  };
  /**
   * @protected
   */


  BaseAxisPointer.prototype.updateLabelEl = function (group, elOption, updateProps, axisPointerModel) {
    var labelEl = inner$2(group).labelEl;

    if (labelEl) {
      labelEl.setStyle(elOption.label.style);
      updateProps(labelEl, {
        // Consider text length change in vertical axis, animation should
        // be used on shape, otherwise the effect will be weird.
        // TODOTODO
        // shape: elOption.label.shape,
        x: elOption.label.x,
        y: elOption.label.y
      });
      updateLabelShowHide(labelEl, axisPointerModel);
    }
  };
  /**
   * @private
   */


  BaseAxisPointer.prototype._renderHandle = function (value) {
    if (this._dragging || !this.updateHandleTransform) {
      return;
    }

    var axisPointerModel = this._axisPointerModel;

    var zr = this._api.getZr();

    var handle = this._handle;
    var handleModel = axisPointerModel.getModel('handle');
    var status = axisPointerModel.get('status');

    if (!handleModel.get('show') || !status || status === 'hide') {
      handle && zr.remove(handle);
      this._handle = null;
      return;
    }

    var isInit;

    if (!this._handle) {
      isInit = true;
      handle = this._handle = createIcon(handleModel.get('icon'), {
        cursor: 'move',
        draggable: true,
        onmousemove: function (e) {
          // For mobile device, prevent screen slider on the button.
          stop(e.event);
        },
        onmousedown: bind(this._onHandleDragMove, this, 0, 0),
        drift: bind(this._onHandleDragMove, this),
        ondragend: bind(this._onHandleDragEnd, this)
      });
      zr.add(handle);
    }

    updateMandatoryProps(handle, axisPointerModel, false); // update style

    handle.setStyle(handleModel.getItemStyle(null, ['color', 'borderColor', 'borderWidth', 'opacity', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'])); // update position

    var handleSize = handleModel.get('size');

    if (!isArray(handleSize)) {
      handleSize = [handleSize, handleSize];
    }

    handle.scaleX = handleSize[0] / 2;
    handle.scaleY = handleSize[1] / 2;
    createOrUpdate(this, '_doDispatchAxisPointer', handleModel.get('throttle') || 0, 'fixRate');

    this._moveHandleToValue(value, isInit);
  };

  BaseAxisPointer.prototype._moveHandleToValue = function (value, isInit) {
    updateProps(this._axisPointerModel, !isInit && this._moveAnimation, this._handle, getHandleTransProps(this.getHandleTransform(value, this._axisModel, this._axisPointerModel)));
  };

  BaseAxisPointer.prototype._onHandleDragMove = function (dx, dy) {
    var handle = this._handle;

    if (!handle) {
      return;
    }

    this._dragging = true; // Persistent for throttle.

    var trans = this.updateHandleTransform(getHandleTransProps(handle), [dx, dy], this._axisModel, this._axisPointerModel);
    this._payloadInfo = trans;
    handle.stopAnimation();
    handle.attr(getHandleTransProps(trans));
    inner$2(handle).lastProp = null;

    this._doDispatchAxisPointer();
  };
  /**
   * Throttled method.
   */


  BaseAxisPointer.prototype._doDispatchAxisPointer = function () {
    var handle = this._handle;

    if (!handle) {
      return;
    }

    var payloadInfo = this._payloadInfo;
    var axisModel = this._axisModel;

    this._api.dispatchAction({
      type: 'updateAxisPointer',
      x: payloadInfo.cursorPoint[0],
      y: payloadInfo.cursorPoint[1],
      tooltipOption: payloadInfo.tooltipOption,
      axesInfo: [{
        axisDim: axisModel.axis.dim,
        axisIndex: axisModel.componentIndex
      }]
    });
  };

  BaseAxisPointer.prototype._onHandleDragEnd = function () {
    this._dragging = false;
    var handle = this._handle;

    if (!handle) {
      return;
    }

    var value = this._axisPointerModel.get('value'); // Consider snap or categroy axis, handle may be not consistent with
    // axisPointer. So move handle to align the exact value position when
    // drag ended.


    this._moveHandleToValue(value); // For the effect: tooltip will be shown when finger holding on handle
    // button, and will be hidden after finger left handle button.


    this._api.dispatchAction({
      type: 'hideTip'
    });
  };
  /**
   * @private
   */


  BaseAxisPointer.prototype.clear = function (api) {
    this._lastValue = null;
    this._lastStatus = null;
    var zr = api.getZr();
    var group = this._group;
    var handle = this._handle;

    if (zr && group) {
      this._lastGraphicKey = null;
      group && zr.remove(group);
      handle && zr.remove(handle);
      this._group = null;
      this._handle = null;
      this._payloadInfo = null;
    }

    clear(this, '_doDispatchAxisPointer');
  };
  /**
   * @protected
   */


  BaseAxisPointer.prototype.doClear = function () {// Implemented by sub-class if necessary.
  };

  BaseAxisPointer.prototype.buildLabel = function (xy, wh, xDimIndex) {
    xDimIndex = xDimIndex || 0;
    return {
      x: xy[xDimIndex],
      y: xy[1 - xDimIndex],
      width: wh[xDimIndex],
      height: wh[1 - xDimIndex]
    };
  };

  return BaseAxisPointer;
}();

function updateProps(animationModel, moveAnimation, el, props) {
  // Animation optimize.
  if (!propsEqual(inner$2(el).lastProp, props)) {
    inner$2(el).lastProp = props;
    moveAnimation ? updateProps$1(el, props, animationModel) : (el.stopAnimation(), el.attr(props));
  }
}

function propsEqual(lastProps, newProps) {
  if (isObject$2(lastProps) && isObject$2(newProps)) {
    var equals_1 = true;
    each$4(newProps, function (item, key) {
      equals_1 = equals_1 && propsEqual(lastProps[key], item);
    });
    return !!equals_1;
  } else {
    return lastProps === newProps;
  }
}

function updateLabelShowHide(labelEl, axisPointerModel) {
  labelEl[axisPointerModel.get(['label', 'show']) ? 'show' : 'hide']();
}

function getHandleTransProps(trans) {
  return {
    x: trans.x || 0,
    y: trans.y || 0,
    rotation: trans.rotation || 0
  };
}

function updateMandatoryProps(group, axisPointerModel, silent) {
  var z = axisPointerModel.get('z');
  var zlevel = axisPointerModel.get('zlevel');
  group && group.traverse(function (el) {
    if (el.type !== 'group') {
      z != null && (el.z = z);
      zlevel != null && (el.zlevel = zlevel);
      el.silent = silent;
    }
  });
}

const BaseAxisPointer$1 = BaseAxisPointer;
/* Injected with object hook! */

function buildElStyle(axisPointerModel) {
  var axisPointerType = axisPointerModel.get('type');
  var styleModel = axisPointerModel.getModel(axisPointerType + 'Style');
  var style;

  if (axisPointerType === 'line') {
    style = styleModel.getLineStyle();
    style.fill = null;
  } else if (axisPointerType === 'shadow') {
    style = styleModel.getAreaStyle();
    style.stroke = null;
  }

  return style;
}
/**
 * @param {Function} labelPos {align, verticalAlign, position}
 */

function buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos) {
  var value = axisPointerModel.get('value');
  var text = getValueLabel(value, axisModel.axis, axisModel.ecModel, axisPointerModel.get('seriesDataIndices'), {
    precision: axisPointerModel.get(['label', 'precision']),
    formatter: axisPointerModel.get(['label', 'formatter'])
  });
  var labelModel = axisPointerModel.getModel('label');
  var paddings = normalizeCssArray(labelModel.get('padding') || 0);
  var font = labelModel.getFont();
  var textRect = getBoundingRect(text, font);
  var position = labelPos.position;
  var width = textRect.width + paddings[1] + paddings[3];
  var height = textRect.height + paddings[0] + paddings[2]; // Adjust by align.

  var align = labelPos.align;
  align === 'right' && (position[0] -= width);
  align === 'center' && (position[0] -= width / 2);
  var verticalAlign = labelPos.verticalAlign;
  verticalAlign === 'bottom' && (position[1] -= height);
  verticalAlign === 'middle' && (position[1] -= height / 2); // Not overflow ec container

  confineInContainer(position, width, height, api);
  var bgColor = labelModel.get('backgroundColor');

  if (!bgColor || bgColor === 'auto') {
    bgColor = axisModel.get(['axisLine', 'lineStyle', 'color']);
  }

  elOption.label = {
    // shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')},
    x: position[0],
    y: position[1],
    style: createTextStyle(labelModel, {
      text: text,
      font: font,
      fill: labelModel.getTextColor(),
      padding: paddings,
      backgroundColor: bgColor
    }),
    // Label should be over axisPointer.
    z2: 10
  };
} // Do not overflow ec container

function confineInContainer(position, width, height, api) {
  var viewWidth = api.getWidth();
  var viewHeight = api.getHeight();
  position[0] = Math.min(position[0] + width, viewWidth) - width;
  position[1] = Math.min(position[1] + height, viewHeight) - height;
  position[0] = Math.max(position[0], 0);
  position[1] = Math.max(position[1], 0);
}

function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) {
  value = axis.scale.parse(value);
  var text = axis.scale.getLabel({
    value: value
  }, {
    // If `precision` is set, width can be fixed (like '12.00500'), which
    // helps to debounce when when moving label.
    precision: opt.precision
  });
  var formatter = opt.formatter;

  if (formatter) {
    var params_1 = {
      value: getAxisRawValue(axis, {
        value: value
      }),
      axisDimension: axis.dim,
      axisIndex: axis.index,
      seriesData: []
    };
    each$4(seriesDataIndices, function (idxItem) {
      var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
      var dataIndex = idxItem.dataIndexInside;
      var dataParams = series && series.getDataParams(dataIndex);
      dataParams && params_1.seriesData.push(dataParams);
    });

    if (isString(formatter)) {
      text = formatter.replace('{value}', text);
    } else if (isFunction(formatter)) {
      text = formatter(params_1);
    }
  }

  return text;
}
function getTransformedPosition(axis, value, layoutInfo) {
  var transform = create();
  rotate(transform, transform, layoutInfo.rotation);
  translate(transform, transform, layoutInfo.position);
  return applyTransform([axis.dataToCoord(value), (layoutInfo.labelOffset || 0) + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)], transform);
}
function buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api) {
  // @ts-ignore
  var textLayout = AxisBuilder$1.innerTextLayout(layoutInfo.rotation, 0, layoutInfo.labelDirection);
  layoutInfo.labelMargin = axisPointerModel.get(['label', 'margin']);
  buildLabelElOption(elOption, axisModel, axisPointerModel, api, {
    position: getTransformedPosition(axisModel.axis, value, layoutInfo),
    align: textLayout.textAlign,
    verticalAlign: textLayout.textVerticalAlign
  });
}
function makeLineShape(p1, p2, xDimIndex) {
  xDimIndex = xDimIndex || 0;
  return {
    x1: p1[xDimIndex],
    y1: p1[1 - xDimIndex],
    x2: p2[xDimIndex],
    y2: p2[1 - xDimIndex]
  };
}
function makeRectShape(xy, wh, xDimIndex) {
  xDimIndex = xDimIndex || 0;
  return {
    x: xy[xDimIndex],
    y: xy[1 - xDimIndex],
    width: wh[xDimIndex],
    height: wh[1 - xDimIndex]
  };
}
/* Injected with object hook! */

var CartesianAxisPointer =
/** @class */
function (_super) {
  __extends(CartesianAxisPointer, _super);

  function CartesianAxisPointer() {
    return _super !== null && _super.apply(this, arguments) || this;
  }
  /**
   * @override
   */


  CartesianAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {
    var axis = axisModel.axis;
    var grid = axis.grid;
    var axisPointerType = axisPointerModel.get('type');
    var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
    var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true));

    if (axisPointerType && axisPointerType !== 'none') {
      var elStyle = buildElStyle(axisPointerModel);
      var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent);
      pointerOption.style = elStyle;
      elOption.graphicKey = pointerOption.type;
      elOption.pointer = pointerOption;
    }

    var layoutInfo = layout(grid.model, axisModel);
    buildCartesianSingleLabelElOption( // @ts-ignore
    value, elOption, layoutInfo, axisModel, axisPointerModel, api);
  };
  /**
   * @override
   */


  CartesianAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) {
    var layoutInfo = layout(axisModel.axis.grid.model, axisModel, {
      labelInside: false
    }); // @ts-ignore

    layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']);
    var pos = getTransformedPosition(axisModel.axis, value, layoutInfo);
    return {
      x: pos[0],
      y: pos[1],
      rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
    };
  };
  /**
   * @override
   */


  CartesianAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) {
    var axis = axisModel.axis;
    var grid = axis.grid;
    var axisExtent = axis.getGlobalExtent(true);
    var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
    var dimIndex = axis.dim === 'x' ? 0 : 1;
    var currPosition = [transform.x, transform.y];
    currPosition[dimIndex] += delta[dimIndex];
    currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
    currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);
    var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
    var cursorPoint = [cursorOtherValue, cursorOtherValue];
    cursorPoint[dimIndex] = currPosition[dimIndex]; // Make tooltip do not overlap axisPointer and in the middle of the grid.

    var tooltipOptions = [{
      verticalAlign: 'middle'
    }, {
      align: 'center'
    }];
    return {
      x: currPosition[0],
      y: currPosition[1],
      rotation: transform.rotation,
      cursorPoint: cursorPoint,
      tooltipOption: tooltipOptions[dimIndex]
    };
  };

  return CartesianAxisPointer;
}(BaseAxisPointer$1);

function getCartesian(grid, axis) {
  var opt = {};
  opt[axis.dim + 'AxisIndex'] = axis.index;
  return grid.getCartesian(opt);
}

var pointerShapeBuilder = {
  line: function (axis, pixelValue, otherExtent) {
    var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getAxisDimIndex(axis));
    return {
      type: 'Line',
      subPixelOptimize: true,
      shape: targetShape
    };
  },
  shadow: function (axis, pixelValue, otherExtent) {
    var bandWidth = Math.max(1, axis.getBandWidth());
    var span = otherExtent[1] - otherExtent[0];
    return {
      type: 'Rect',
      shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getAxisDimIndex(axis))
    };
  }
};

function getAxisDimIndex(axis) {
  return axis.dim === 'x' ? 0 : 1;
}

const CartesianAxisPointer$1 = CartesianAxisPointer;
/* Injected with object hook! */

var AxisPointerModel =
/** @class */
function (_super) {
  __extends(AxisPointerModel, _super);

  function AxisPointerModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = AxisPointerModel.type;
    return _this;
  }

  AxisPointerModel.type = 'axisPointer';
  AxisPointerModel.defaultOption = {
    // 'auto' means that show when triggered by tooltip or handle.
    show: 'auto',
    // zlevel: 0,
    z: 50,
    type: 'line',
    // axispointer triggered by tootip determine snap automatically,
    // see `modelHelper`.
    snap: false,
    triggerTooltip: true,
    triggerEmphasis: true,
    value: null,
    status: null,
    link: [],
    // Do not set 'auto' here, otherwise global animation: false
    // will not effect at this axispointer.
    animation: null,
    animationDurationUpdate: 200,
    lineStyle: {
      color: '#B9BEC9',
      width: 1,
      type: 'dashed'
    },
    shadowStyle: {
      color: 'rgba(210,219,238,0.2)'
    },
    label: {
      show: true,
      formatter: null,
      precision: 'auto',
      margin: 3,
      color: '#fff',
      padding: [5, 7, 5, 7],
      backgroundColor: 'auto',
      borderColor: null,
      borderWidth: 0,
      borderRadius: 3
    },
    handle: {
      show: false,
      // eslint-disable-next-line
      icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z',
      size: 45,
      // handle margin is from symbol center to axis, which is stable when circular move.
      margin: 50,
      // color: '#1b8bbd'
      // color: '#2f4554'
      color: '#333',
      shadowBlur: 3,
      shadowColor: '#aaa',
      shadowOffsetX: 0,
      shadowOffsetY: 2,
      // For mobile performance
      throttle: 40
    }
  };
  return AxisPointerModel;
}(ComponentModel$1);

const AxisPointerModel$1 = AxisPointerModel;
/* Injected with object hook! */

var inner$1 = makeInner();
var each$1 = each$4;
/**
 * @param {string} key
 * @param {module:echarts/ExtensionAPI} api
 * @param {Function} handler
 *      param: {string} currTrigger
 *      param: {Array.<number>} point
 */

function register(key, api, handler) {
  if (env$1.node) {
    return;
  }

  var zr = api.getZr();
  inner$1(zr).records || (inner$1(zr).records = {});
  initGlobalListeners(zr, api);
  var record = inner$1(zr).records[key] || (inner$1(zr).records[key] = {});
  record.handler = handler;
}

function initGlobalListeners(zr, api) {
  if (inner$1(zr).initialized) {
    return;
  }

  inner$1(zr).initialized = true;
  useHandler('click', curry$1(doEnter, 'click'));
  useHandler('mousemove', curry$1(doEnter, 'mousemove')); // useHandler('mouseout', onLeave);

  useHandler('globalout', onLeave);

  function useHandler(eventType, cb) {
    zr.on(eventType, function (e) {
      var dis = makeDispatchAction$1(api);
      each$1(inner$1(zr).records, function (record) {
        record && cb(record, e, dis.dispatchAction);
      });
      dispatchTooltipFinally(dis.pendings, api);
    });
  }
}

function dispatchTooltipFinally(pendings, api) {
  var showLen = pendings.showTip.length;
  var hideLen = pendings.hideTip.length;
  var actuallyPayload;

  if (showLen) {
    actuallyPayload = pendings.showTip[showLen - 1];
  } else if (hideLen) {
    actuallyPayload = pendings.hideTip[hideLen - 1];
  }

  if (actuallyPayload) {
    actuallyPayload.dispatchAction = null;
    api.dispatchAction(actuallyPayload);
  }
}

function onLeave(record, e, dispatchAction) {
  record.handler('leave', null, dispatchAction);
}

function doEnter(currTrigger, record, e, dispatchAction) {
  record.handler(currTrigger, e, dispatchAction);
}

function makeDispatchAction$1(api) {
  var pendings = {
    showTip: [],
    hideTip: []
  }; // FIXME
  // better approach?
  // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip,
  // which may be conflict, (axisPointer call showTip but tooltip call hideTip);
  // So we have to add "final stage" to merge those dispatched actions.

  var dispatchAction = function (payload) {
    var pendingList = pendings[payload.type];

    if (pendingList) {
      pendingList.push(payload);
    } else {
      payload.dispatchAction = dispatchAction;
      api.dispatchAction(payload);
    }
  };

  return {
    dispatchAction: dispatchAction,
    pendings: pendings
  };
}

function unregister(key, api) {
  if (env$1.node) {
    return;
  }

  var zr = api.getZr();
  var record = (inner$1(zr).records || {})[key];

  if (record) {
    inner$1(zr).records[key] = null;
  }
}
/* Injected with object hook! */

var AxisPointerView =
/** @class */
function (_super) {
  __extends(AxisPointerView, _super);

  function AxisPointerView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = AxisPointerView.type;
    return _this;
  }

  AxisPointerView.prototype.render = function (globalAxisPointerModel, ecModel, api) {
    var globalTooltipModel = ecModel.getComponent('tooltip');
    var triggerOn = globalAxisPointerModel.get('triggerOn') || globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click'; // Register global listener in AxisPointerView to enable
    // AxisPointerView to be independent to Tooltip.

    register('axisPointer', api, function (currTrigger, e, dispatchAction) {
      // If 'none', it is not controlled by mouse totally.
      if (triggerOn !== 'none' && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)) {
        dispatchAction({
          type: 'updateAxisPointer',
          currTrigger: currTrigger,
          x: e && e.offsetX,
          y: e && e.offsetY
        });
      }
    });
  };

  AxisPointerView.prototype.remove = function (ecModel, api) {
    unregister('axisPointer', api);
  };

  AxisPointerView.prototype.dispose = function (ecModel, api) {
    unregister('axisPointer', api);
  };

  AxisPointerView.type = 'axisPointer';
  return AxisPointerView;
}(ComponentView$1);

const AxisPointerView$1 = AxisPointerView;
/* Injected with object hook! */

/**
 * @param finder contains {seriesIndex, dataIndex, dataIndexInside}
 * @param ecModel
 * @return  {point: [x, y], el: ...} point Will not be null.
 */

function findPointFromSeries(finder, ecModel) {
  var point = [];
  var seriesIndex = finder.seriesIndex;
  var seriesModel;

  if (seriesIndex == null || !(seriesModel = ecModel.getSeriesByIndex(seriesIndex))) {
    return {
      point: []
    };
  }

  var data = seriesModel.getData();
  var dataIndex = queryDataIndex(data, finder);

  if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) {
    return {
      point: []
    };
  }

  var el = data.getItemGraphicEl(dataIndex);
  var coordSys = seriesModel.coordinateSystem;

  if (seriesModel.getTooltipPosition) {
    point = seriesModel.getTooltipPosition(dataIndex) || [];
  } else if (coordSys && coordSys.dataToPoint) {
    if (finder.isStacked) {
      var baseAxis = coordSys.getBaseAxis();
      var valueAxis = coordSys.getOtherAxis(baseAxis);
      var valueAxisDim = valueAxis.dim;
      var baseAxisDim = baseAxis.dim;
      var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0;
      var baseDim = data.mapDimension(baseAxisDim);
      var stackedData = [];
      stackedData[baseDataOffset] = data.get(baseDim, dataIndex);
      stackedData[1 - baseDataOffset] = data.get(data.getCalculationInfo('stackResultDimension'), dataIndex);
      point = coordSys.dataToPoint(stackedData) || [];
    } else {
      point = coordSys.dataToPoint(data.getValues(map$1(coordSys.dimensions, function (dim) {
        return data.mapDimension(dim);
      }), dataIndex)) || [];
    }
  } else if (el) {
    // Use graphic bounding rect
    var rect = el.getBoundingRect().clone();
    rect.applyTransform(el.transform);
    point = [rect.x + rect.width / 2, rect.y + rect.height / 2];
  }

  return {
    point: point,
    el: el
  };
}
/* Injected with object hook! */

var inner = makeInner();
/**
 * Basic logic: check all axis, if they do not demand show/highlight,
 * then hide/downplay them.
 *
 * @return content of event obj for echarts.connect.
 */

function axisTrigger(payload, ecModel, api) {
  var currTrigger = payload.currTrigger;
  var point = [payload.x, payload.y];
  var finder = payload;
  var dispatchAction = payload.dispatchAction || bind$1(api.dispatchAction, api);
  var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; // Pending
  // See #6121. But we are not able to reproduce it yet.

  if (!coordSysAxesInfo) {
    return;
  }

  if (illegalPoint(point)) {
    // Used in the default behavior of `connection`: use the sample seriesIndex
    // and dataIndex. And also used in the tooltipView trigger.
    point = findPointFromSeries({
      seriesIndex: finder.seriesIndex,
      // Do not use dataIndexInside from other ec instance.
      // FIXME: auto detect it?
      dataIndex: finder.dataIndex
    }, ecModel).point;
  }

  var isIllegalPoint = illegalPoint(point); // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}).
  // Notice: In this case, it is difficult to get the `point` (which is necessary to show
  // tooltip, so if point is not given, we just use the point found by sample seriesIndex
  // and dataIndex.

  var inputAxesInfo = finder.axesInfo;
  var axesInfo = coordSysAxesInfo.axesInfo;
  var shouldHide = currTrigger === 'leave' || illegalPoint(point);
  var outputPayload = {};
  var showValueMap = {};
  var dataByCoordSys = {
    list: [],
    map: {}
  };
  var updaters = {
    showPointer: curry$1(showPointer, showValueMap),
    showTooltip: curry$1(showTooltip, dataByCoordSys)
  }; // Process for triggered axes.

  each$4(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) {
    // If a point given, it must be contained by the coordinate system.
    var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point);
    each$4(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) {
      var axis = axisInfo.axis;
      var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo); // If no inputAxesInfo, no axis is restricted.

      if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) {
        var val = inputAxisInfo && inputAxisInfo.value;

        if (val == null && !isIllegalPoint) {
          val = axis.pointToData(point);
        }

        val != null && processOnAxis(axisInfo, val, updaters, false, outputPayload);
      }
    });
  }); // Process for linked axes.

  var linkTriggers = {};
  each$4(axesInfo, function (tarAxisInfo, tarKey) {
    var linkGroup = tarAxisInfo.linkGroup; // If axis has been triggered in the previous stage, it should not be triggered by link.

    if (linkGroup && !showValueMap[tarKey]) {
      each$4(linkGroup.axesInfo, function (srcAxisInfo, srcKey) {
        var srcValItem = showValueMap[srcKey]; // If srcValItem exist, source axis is triggered, so link to target axis.

        if (srcAxisInfo !== tarAxisInfo && srcValItem) {
          var val = srcValItem.value;
          linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo))));
          linkTriggers[tarAxisInfo.key] = val;
        }
      });
    }
  });
  each$4(linkTriggers, function (val, tarKey) {
    processOnAxis(axesInfo[tarKey], val, updaters, true, outputPayload);
  });
  updateModelActually(showValueMap, axesInfo, outputPayload);
  dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction);
  dispatchHighDownActually(axesInfo, dispatchAction, api);
  return outputPayload;
}

function processOnAxis(axisInfo, newValue, updaters, noSnap, outputFinder) {
  var axis = axisInfo.axis;

  if (axis.scale.isBlank() || !axis.containData(newValue)) {
    return;
  }

  if (!axisInfo.involveSeries) {
    updaters.showPointer(axisInfo, newValue);
    return;
  } // Heavy calculation. So put it after axis.containData checking.


  var payloadInfo = buildPayloadsBySeries(newValue, axisInfo);
  var payloadBatch = payloadInfo.payloadBatch;
  var snapToValue = payloadInfo.snapToValue; // Fill content of event obj for echarts.connect.
  // By default use the first involved series data as a sample to connect.

  if (payloadBatch[0] && outputFinder.seriesIndex == null) {
    extend(outputFinder, payloadBatch[0]);
  } // If no linkSource input, this process is for collecting link
  // target, where snap should not be accepted.


  if (!noSnap && axisInfo.snap) {
    if (axis.containData(snapToValue) && snapToValue != null) {
      newValue = snapToValue;
    }
  }

  updaters.showPointer(axisInfo, newValue, payloadBatch); // Tooltip should always be snapToValue, otherwise there will be
  // incorrect "axis value ~ series value" mapping displayed in tooltip.

  updaters.showTooltip(axisInfo, payloadInfo, snapToValue);
}

function buildPayloadsBySeries(value, axisInfo) {
  var axis = axisInfo.axis;
  var dim = axis.dim;
  var snapToValue = value;
  var payloadBatch = [];
  var minDist = Number.MAX_VALUE;
  var minDiff = -1;
  each$4(axisInfo.seriesModels, function (series, idx) {
    var dataDim = series.getData().mapDimensionsAll(dim);
    var seriesNestestValue;
    var dataIndices;

    if (series.getAxisTooltipData) {
      var result = series.getAxisTooltipData(dataDim, value, axis);
      dataIndices = result.dataIndices;
      seriesNestestValue = result.nestestValue;
    } else {
      dataIndices = series.getData().indicesOfNearest(dataDim[0], value, // Add a threshold to avoid find the wrong dataIndex
      // when data length is not same.
      // false,
      axis.type === 'category' ? 0.5 : null);

      if (!dataIndices.length) {
        return;
      }

      seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]);
    }

    if (seriesNestestValue == null || !isFinite(seriesNestestValue)) {
      return;
    }

    var diff = value - seriesNestestValue;
    var dist = Math.abs(diff); // Consider category case

    if (dist <= minDist) {
      if (dist < minDist || diff >= 0 && minDiff < 0) {
        minDist = dist;
        minDiff = diff;
        snapToValue = seriesNestestValue;
        payloadBatch.length = 0;
      }

      each$4(dataIndices, function (dataIndex) {
        payloadBatch.push({
          seriesIndex: series.seriesIndex,
          dataIndexInside: dataIndex,
          dataIndex: series.getData().getRawIndex(dataIndex)
        });
      });
    }
  });
  return {
    payloadBatch: payloadBatch,
    snapToValue: snapToValue
  };
}

function showPointer(showValueMap, axisInfo, value, payloadBatch) {
  showValueMap[axisInfo.key] = {
    value: value,
    payloadBatch: payloadBatch
  };
}

function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) {
  var payloadBatch = payloadInfo.payloadBatch;
  var axis = axisInfo.axis;
  var axisModel = axis.model;
  var axisPointerModel = axisInfo.axisPointerModel; // If no data, do not create anything in dataByCoordSys,
  // whose length will be used to judge whether dispatch action.

  if (!axisInfo.triggerTooltip || !payloadBatch.length) {
    return;
  }

  var coordSysModel = axisInfo.coordSys.model;
  var coordSysKey = makeKey(coordSysModel);
  var coordSysItem = dataByCoordSys.map[coordSysKey];

  if (!coordSysItem) {
    coordSysItem = dataByCoordSys.map[coordSysKey] = {
      coordSysId: coordSysModel.id,
      coordSysIndex: coordSysModel.componentIndex,
      coordSysType: coordSysModel.type,
      coordSysMainType: coordSysModel.mainType,
      dataByAxis: []
    };
    dataByCoordSys.list.push(coordSysItem);
  }

  coordSysItem.dataByAxis.push({
    axisDim: axis.dim,
    axisIndex: axisModel.componentIndex,
    axisType: axisModel.type,
    axisId: axisModel.id,
    value: value,
    // Caustion: viewHelper.getValueLabel is actually on "view stage", which
    // depends that all models have been updated. So it should not be performed
    // here. Considering axisPointerModel used here is volatile, which is hard
    // to be retrieve in TooltipView, we prepare parameters here.
    valueLabelOpt: {
      precision: axisPointerModel.get(['label', 'precision']),
      formatter: axisPointerModel.get(['label', 'formatter'])
    },
    seriesDataIndices: payloadBatch.slice()
  });
}

function updateModelActually(showValueMap, axesInfo, outputPayload) {
  var outputAxesInfo = outputPayload.axesInfo = []; // Basic logic: If no 'show' required, 'hide' this axisPointer.

  each$4(axesInfo, function (axisInfo, key) {
    var option = axisInfo.axisPointerModel.option;
    var valItem = showValueMap[key];

    if (valItem) {
      !axisInfo.useHandle && (option.status = 'show');
      option.value = valItem.value; // For label formatter param and highlight.

      option.seriesDataIndices = (valItem.payloadBatch || []).slice();
    } // When always show (e.g., handle used), remain
    // original value and status.
    else {
        // If hide, value still need to be set, consider
        // click legend to toggle axis blank.
        !axisInfo.useHandle && (option.status = 'hide');
      } // If status is 'hide', should be no info in payload.


    option.status === 'show' && outputAxesInfo.push({
      axisDim: axisInfo.axis.dim,
      axisIndex: axisInfo.axis.model.componentIndex,
      value: option.value
    });
  });
}

function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) {
  // Basic logic: If no showTip required, hideTip will be dispatched.
  if (illegalPoint(point) || !dataByCoordSys.list.length) {
    dispatchAction({
      type: 'hideTip'
    });
    return;
  } // In most case only one axis (or event one series is used). It is
  // convenient to fetch payload.seriesIndex and payload.dataIndex
  // directly. So put the first seriesIndex and dataIndex of the first
  // axis on the payload.


  var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {};
  dispatchAction({
    type: 'showTip',
    escapeConnect: true,
    x: point[0],
    y: point[1],
    tooltipOption: payload.tooltipOption,
    position: payload.position,
    dataIndexInside: sampleItem.dataIndexInside,
    dataIndex: sampleItem.dataIndex,
    seriesIndex: sampleItem.seriesIndex,
    dataByCoordSys: dataByCoordSys.list
  });
}

function dispatchHighDownActually(axesInfo, dispatchAction, api) {
  // FIXME
  // highlight status modification should be a stage of main process?
  // (Consider confilct (e.g., legend and axisPointer) and setOption)
  var zr = api.getZr();
  var highDownKey = 'axisPointerLastHighlights';
  var lastHighlights = inner(zr)[highDownKey] || {};
  var newHighlights = inner(zr)[highDownKey] = {}; // Update highlight/downplay status according to axisPointer model.
  // Build hash map and remove duplicate incidentally.

  each$4(axesInfo, function (axisInfo, key) {
    var option = axisInfo.axisPointerModel.option;
    option.status === 'show' && axisInfo.triggerEmphasis && each$4(option.seriesDataIndices, function (batchItem) {
      var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex;
      newHighlights[key] = batchItem;
    });
  }); // Diff.

  var toHighlight = [];
  var toDownplay = [];
  each$4(lastHighlights, function (batchItem, key) {
    !newHighlights[key] && toDownplay.push(batchItem);
  });
  each$4(newHighlights, function (batchItem, key) {
    !lastHighlights[key] && toHighlight.push(batchItem);
  });
  toDownplay.length && api.dispatchAction({
    type: 'downplay',
    escapeConnect: true,
    // Not blur others when highlight in axisPointer.
    notBlur: true,
    batch: toDownplay
  });
  toHighlight.length && api.dispatchAction({
    type: 'highlight',
    escapeConnect: true,
    // Not blur others when highlight in axisPointer.
    notBlur: true,
    batch: toHighlight
  });
}

function findInputAxisInfo(inputAxesInfo, axisInfo) {
  for (var i = 0; i < (inputAxesInfo || []).length; i++) {
    var inputAxisInfo = inputAxesInfo[i];

    if (axisInfo.axis.dim === inputAxisInfo.axisDim && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex) {
      return inputAxisInfo;
    }
  }
}

function makeMapperParam(axisInfo) {
  var axisModel = axisInfo.axis.model;
  var item = {};
  var dim = item.axisDim = axisInfo.axis.dim;
  item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex;
  item.axisName = item[dim + 'AxisName'] = axisModel.name;
  item.axisId = item[dim + 'AxisId'] = axisModel.id;
  return item;
}

function illegalPoint(point) {
  return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]);
}
/* Injected with object hook! */

function install$6(registers) {
  // CartesianAxisPointer is not supposed to be required here. But consider
  // echarts.simple.js and online build tooltip, which only require gridSimple,
  // CartesianAxisPointer should be able to required somewhere.
  AxisView$1.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer$1);
  registers.registerComponentModel(AxisPointerModel$1);
  registers.registerComponentView(AxisPointerView$1);
  registers.registerPreprocessor(function (option) {
    // Always has a global axisPointerModel for default setting.
    if (option) {
      (!option.axisPointer || option.axisPointer.length === 0) && (option.axisPointer = {});
      var link = option.axisPointer.link; // Normalize to array to avoid object mergin. But if link
      // is not set, remain null/undefined, otherwise it will
      // override existent link setting.

      if (link && !isArray(link)) {
        option.axisPointer.link = [link];
      }
    }
  }); // This process should proformed after coordinate systems created
  // and series data processed. So put it on statistic processing stage.

  registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) {
    // Build axisPointerModel, mergin tooltip.axisPointer model for each axis.
    // allAxesInfo should be updated when setOption performed.
    ecModel.getComponent('axisPointer').coordSysAxesInfo = collect(ecModel, api);
  }); // Broadcast to all views.

  registers.registerAction({
    type: 'updateAxisPointer',
    event: 'updateAxisPointer',
    update: ':updateAxisPointer'
  }, axisTrigger);
}
/* Injected with object hook! */

function install$5(registers) {
  use(install$7);
  use(install$6);
}
/* Injected with object hook! */

function makeBackground(rect, componentModel) {
  var padding = normalizeCssArray(componentModel.get('padding'));
  var style = componentModel.getItemStyle(['color', 'opacity']);
  style.fill = componentModel.get('backgroundColor');
  rect = new Rect$1({
    shape: {
      x: rect.x - padding[3],
      y: rect.y - padding[0],
      width: rect.width + padding[1] + padding[3],
      height: rect.height + padding[0] + padding[2],
      r: componentModel.get('borderRadius')
    },
    style: style,
    silent: true,
    z2: -1
  }); // FIXME
  // `subPixelOptimizeRect` may bring some gap between edge of viewpart
  // and background rect when setting like `left: 0`, `top: 0`.
  // graphic.subPixelOptimizeRect(rect);

  return rect;
}
/* Injected with object hook! */

var TooltipModel =
/** @class */
function (_super) {
  __extends(TooltipModel, _super);

  function TooltipModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = TooltipModel.type;
    return _this;
  }

  TooltipModel.type = 'tooltip';
  TooltipModel.dependencies = ['axisPointer'];
  TooltipModel.defaultOption = {
    // zlevel: 0,
    z: 60,
    show: true,
    // tooltip main content
    showContent: true,
    // 'trigger' only works on coordinate system.
    // 'item' | 'axis' | 'none'
    trigger: 'item',
    // 'click' | 'mousemove' | 'none'
    triggerOn: 'mousemove|click',
    alwaysShowContent: false,
    displayMode: 'single',
    renderMode: 'auto',
    // whether restraint content inside viewRect.
    // If renderMode: 'richText', default true.
    // If renderMode: 'html', defaut false (for backward compat).
    confine: null,
    showDelay: 0,
    hideDelay: 100,
    // Animation transition time, unit is second
    transitionDuration: 0.4,
    enterable: false,
    backgroundColor: '#fff',
    // box shadow
    shadowBlur: 10,
    shadowColor: 'rgba(0, 0, 0, .2)',
    shadowOffsetX: 1,
    shadowOffsetY: 2,
    // tooltip border radius, unit is px, default is 4
    borderRadius: 4,
    // tooltip border width, unit is px, default is 0 (no border)
    borderWidth: 1,
    // Tooltip inside padding, default is 5 for all direction
    // Array is allowed to set up, right, bottom, left, same with css
    // The default value: See `tooltip/tooltipMarkup.ts#getPaddingFromTooltipModel`.
    padding: null,
    // Extra css text
    extraCssText: '',
    // axis indicator, trigger by axis
    axisPointer: {
      // default is line
      // legal values: 'line' | 'shadow' | 'cross'
      type: 'line',
      // Valid when type is line, appoint tooltip line locate on which line. Optional
      // legal values: 'x' | 'y' | 'angle' | 'radius' | 'auto'
      // default is 'auto', chose the axis which type is category.
      // for multiply y axis, cartesian coord chose x axis, polar chose angle axis
      axis: 'auto',
      animation: 'auto',
      animationDurationUpdate: 200,
      animationEasingUpdate: 'exponentialOut',
      crossStyle: {
        color: '#999',
        width: 1,
        type: 'dashed',
        // TODO formatter
        textStyle: {}
      } // lineStyle and shadowStyle should not be specified here,
      // otherwise it will always override those styles on option.axisPointer.

    },
    textStyle: {
      color: '#666',
      fontSize: 14
    }
  };
  return TooltipModel;
}(ComponentModel$1);

const TooltipModel$1 = TooltipModel;
/* Injected with object hook! */

/* global document */

function shouldTooltipConfine(tooltipModel) {
  var confineOption = tooltipModel.get('confine');
  return confineOption != null ? !!confineOption // In richText mode, the outside part can not be visible.
  : tooltipModel.get('renderMode') === 'richText';
}

function testStyle(styleProps) {
  if (!env$1.domSupported) {
    return;
  }

  var style = document.documentElement.style;

  for (var i = 0, len = styleProps.length; i < len; i++) {
    if (styleProps[i] in style) {
      return styleProps[i];
    }
  }
}

var TRANSFORM_VENDOR = testStyle(['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
var TRANSITION_VENDOR = testStyle(['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
function toCSSVendorPrefix(styleVendor, styleProp) {
  if (!styleVendor) {
    return styleProp;
  }

  styleProp = toCamelCase(styleProp, true);
  var idx = styleVendor.indexOf(styleProp);
  styleVendor = idx === -1 ? styleProp : "-" + styleVendor.slice(0, idx) + "-" + styleProp;
  return styleVendor.toLowerCase();
}
function getComputedStyle$2(el, style) {
  var stl = el.currentStyle || document.defaultView && document.defaultView.getComputedStyle(el);
  return stl ? style ? stl[style] : stl : null;
}
/* Injected with object hook! */

/* global document, window */

var CSS_TRANSITION_VENDOR = toCSSVendorPrefix(TRANSITION_VENDOR, 'transition');
var CSS_TRANSFORM_VENDOR = toCSSVendorPrefix(TRANSFORM_VENDOR, 'transform'); // eslint-disable-next-line

var gCssText = "position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;" + (env$1.transform3dSupported ? 'will-change:transform;' : '');

function mirrorPos(pos) {
  pos = pos === 'left' ? 'right' : pos === 'right' ? 'left' : pos === 'top' ? 'bottom' : 'top';
  return pos;
}

function assembleArrow(tooltipModel, borderColor, arrowPosition) {
  if (!isString(arrowPosition) || arrowPosition === 'inside') {
    return '';
  }

  var backgroundColor = tooltipModel.get('backgroundColor');
  var borderWidth = tooltipModel.get('borderWidth');
  borderColor = convertToColorString(borderColor);
  var arrowPos = mirrorPos(arrowPosition);
  var arrowSize = Math.max(Math.round(borderWidth) * 1.5, 6);
  var positionStyle = '';
  var transformStyle = CSS_TRANSFORM_VENDOR + ':';
  var rotateDeg;

  if (indexOf(['left', 'right'], arrowPos) > -1) {
    positionStyle += 'top:50%';
    transformStyle += "translateY(-50%) rotate(" + (rotateDeg = arrowPos === 'left' ? -225 : -45) + "deg)";
  } else {
    positionStyle += 'left:50%';
    transformStyle += "translateX(-50%) rotate(" + (rotateDeg = arrowPos === 'top' ? 225 : 45) + "deg)";
  }

  var rotateRadian = rotateDeg * Math.PI / 180;
  var arrowWH = arrowSize + borderWidth;
  var rotatedWH = arrowWH * Math.abs(Math.cos(rotateRadian)) + arrowWH * Math.abs(Math.sin(rotateRadian));
  var arrowOffset = Math.round(((rotatedWH - Math.SQRT2 * borderWidth) / 2 + Math.SQRT2 * borderWidth - (rotatedWH - arrowWH) / 2) * 100) / 100;
  positionStyle += ";" + arrowPos + ":-" + arrowOffset + "px";
  var borderStyle = borderColor + " solid " + borderWidth + "px;";
  var styleCss = ["position:absolute;width:" + arrowSize + "px;height:" + arrowSize + "px;z-index:-1;", positionStyle + ";" + transformStyle + ";", "border-bottom:" + borderStyle, "border-right:" + borderStyle, "background-color:" + backgroundColor + ";"];
  return "<div style=\"" + styleCss.join('') + "\"></div>";
}

function assembleTransition(duration, onlyFade) {
  var transitionCurve = 'cubic-bezier(0.23,1,0.32,1)';
  var transitionOption = " " + duration / 2 + "s " + transitionCurve;
  var transitionText = "opacity" + transitionOption + ",visibility" + transitionOption;

  if (!onlyFade) {
    transitionOption = " " + duration + "s " + transitionCurve;
    transitionText += env$1.transformSupported ? "," + CSS_TRANSFORM_VENDOR + transitionOption : ",left" + transitionOption + ",top" + transitionOption;
  }

  return CSS_TRANSITION_VENDOR + ':' + transitionText;
}

function assembleTransform(x, y, toString) {
  // If using float on style, the final width of the dom might
  // keep changing slightly while mouse move. So `toFixed(0)` them.
  var x0 = x.toFixed(0) + 'px';
  var y0 = y.toFixed(0) + 'px'; // not support transform, use `left` and `top` instead.

  if (!env$1.transformSupported) {
    return toString ? "top:" + y0 + ";left:" + x0 + ";" : [['top', y0], ['left', x0]];
  } // support transform


  var is3d = env$1.transform3dSupported;
  var translate = "translate" + (is3d ? '3d' : '') + "(" + x0 + "," + y0 + (is3d ? ',0' : '') + ")";
  return toString ? 'top:0;left:0;' + CSS_TRANSFORM_VENDOR + ':' + translate + ';' : [['top', 0], ['left', 0], [TRANSFORM_VENDOR, translate]];
}
/**
 * @param {Object} textStyle
 * @return {string}
 * @inner
 */


function assembleFont(textStyleModel) {
  var cssText = [];
  var fontSize = textStyleModel.get('fontSize');
  var color = textStyleModel.getTextColor();
  color && cssText.push('color:' + color);
  cssText.push('font:' + textStyleModel.getFont());
  fontSize // @ts-ignore, leave it to the tooltip refactor.
  && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
  var shadowColor = textStyleModel.get('textShadowColor');
  var shadowBlur = textStyleModel.get('textShadowBlur') || 0;
  var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0;
  var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0;
  shadowColor && shadowBlur && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px ' + shadowBlur + 'px ' + shadowColor);
  each$4(['decoration', 'align'], function (name) {
    var val = textStyleModel.get(name);
    val && cssText.push('text-' + name + ':' + val);
  });
  return cssText.join(';');
}

function assembleCssText(tooltipModel, enableTransition, onlyFade) {
  var cssText = [];
  var transitionDuration = tooltipModel.get('transitionDuration');
  var backgroundColor = tooltipModel.get('backgroundColor');
  var shadowBlur = tooltipModel.get('shadowBlur');
  var shadowColor = tooltipModel.get('shadowColor');
  var shadowOffsetX = tooltipModel.get('shadowOffsetX');
  var shadowOffsetY = tooltipModel.get('shadowOffsetY');
  var textStyleModel = tooltipModel.getModel('textStyle');
  var padding = getPaddingFromTooltipModel(tooltipModel, 'html');
  var boxShadow = shadowOffsetX + "px " + shadowOffsetY + "px " + shadowBlur + "px " + shadowColor;
  cssText.push('box-shadow:' + boxShadow); // Animation transition. Do not animate when transitionDuration is 0.

  enableTransition && transitionDuration && cssText.push(assembleTransition(transitionDuration, onlyFade));

  if (backgroundColor) {
    cssText.push('background-color:' + backgroundColor);
  } // Border style


  each$4(['width', 'color', 'radius'], function (name) {
    var borderName = 'border-' + name;
    var camelCase = toCamelCase(borderName);
    var val = tooltipModel.get(camelCase);
    val != null && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px'));
  }); // Text style

  cssText.push(assembleFont(textStyleModel)); // Padding

  if (padding != null) {
    cssText.push('padding:' + normalizeCssArray(padding).join('px ') + 'px');
  }

  return cssText.join(';') + ';';
} // If not able to make, do not modify the input `out`.


function makeStyleCoord$1(out, zr, appendToBody, zrX, zrY) {
  var zrPainter = zr && zr.painter;

  if (appendToBody) {
    var zrViewportRoot = zrPainter && zrPainter.getViewportRoot();

    if (zrViewportRoot) {
      // Some APPs might use scale on body, so we support CSS transform here.
      transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY);
    }
  } else {
    out[0] = zrX;
    out[1] = zrY; // xy should be based on canvas root. But tooltipContent is
    // the sibling of canvas root. So padding of ec container
    // should be considered here.

    var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset();

    if (viewportRootOffset) {
      out[0] += viewportRootOffset.offsetLeft;
      out[1] += viewportRootOffset.offsetTop;
    }
  }

  out[2] = out[0] / zr.getWidth();
  out[3] = out[1] / zr.getHeight();
}

var TooltipHTMLContent =
/** @class */
function () {
  function TooltipHTMLContent(container, api, opt) {
    this._show = false;
    this._styleCoord = [0, 0, 0, 0];
    this._enterable = true;
    this._alwaysShowContent = false;
    this._firstShow = true;
    this._longHide = true;

    if (env$1.wxa) {
      return null;
    }

    var el = document.createElement('div'); // TODO: TYPE

    el.domBelongToZr = true;
    this.el = el;
    var zr = this._zr = api.getZr();
    var appendToBody = this._appendToBody = opt && opt.appendToBody;
    makeStyleCoord$1(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2);

    if (appendToBody) {
      document.body.appendChild(el);
    } else {
      container.appendChild(el);
    }

    this._container = container; // FIXME
    // Is it needed to trigger zr event manually if
    // the browser do not support `pointer-events: none`.

    var self = this;

    el.onmouseenter = function () {
      // clear the timeout in hideLater and keep showing tooltip
      if (self._enterable) {
        clearTimeout(self._hideTimeout);
        self._show = true;
      }

      self._inContent = true;
    };

    el.onmousemove = function (e) {
      e = e || window.event;

      if (!self._enterable) {
        // `pointer-events: none` is set to tooltip content div
        // if `enterable` is set as `false`, and `el.onmousemove`
        // can not be triggered. But in browser that do not
        // support `pointer-events`, we need to do this:
        // Try trigger zrender event to avoid mouse
        // in and out shape too frequently
        var handler = zr.handler;
        var zrViewportRoot = zr.painter.getViewportRoot();
        normalizeEvent(zrViewportRoot, e, true);
        handler.dispatch('mousemove', e);
      }
    };

    el.onmouseleave = function () {
      // set `_inContent` to `false` before `hideLater`
      self._inContent = false;

      if (self._enterable) {
        if (self._show) {
          self.hideLater(self._hideDelay);
        }
      }
    };
  }
  /**
   * Update when tooltip is rendered
   */


  TooltipHTMLContent.prototype.update = function (tooltipModel) {
    // FIXME
    // Move this logic to ec main?
    var container = this._container;
    var position = getComputedStyle$2(container, 'position');
    var domStyle = container.style;

    if (domStyle.position !== 'absolute' && position !== 'absolute') {
      domStyle.position = 'relative';
    } // move tooltip if chart resized


    var alwaysShowContent = tooltipModel.get('alwaysShowContent');
    alwaysShowContent && this._moveIfResized(); // update alwaysShowContent

    this._alwaysShowContent = alwaysShowContent; // update className

    this.el.className = tooltipModel.get('className') || ''; // Hide the tooltip
    // PENDING
    // this.hide();
  };

  TooltipHTMLContent.prototype.show = function (tooltipModel, nearPointColor) {
    clearTimeout(this._hideTimeout);
    clearTimeout(this._longHideTimeout);
    var el = this.el;
    var style = el.style;
    var styleCoord = this._styleCoord;

    if (!el.innerHTML) {
      style.display = 'none';
    } else {
      style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) // initial transform
      + assembleTransform(styleCoord[0], styleCoord[1], true) + ("border-color:" + convertToColorString(nearPointColor) + ";") + (tooltipModel.get('extraCssText') || '') // If mouse occasionally move over the tooltip, a mouseout event will be
      // triggered by canvas, and cause some unexpectable result like dragging
      // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve
      // it. Although it is not supported by IE8~IE10, fortunately it is a rare
      // scenario.
      + (";pointer-events:" + (this._enterable ? 'auto' : 'none'));
    }

    this._show = true;
    this._firstShow = false;
    this._longHide = false;
  };

  TooltipHTMLContent.prototype.setContent = function (content, markers, tooltipModel, borderColor, arrowPosition) {
    var el = this.el;

    if (content == null) {
      el.innerHTML = '';
      return;
    }

    var arrow = '';

    if (isString(arrowPosition) && tooltipModel.get('trigger') === 'item' && !shouldTooltipConfine(tooltipModel)) {
      arrow = assembleArrow(tooltipModel, borderColor, arrowPosition);
    }

    if (isString(content)) {
      el.innerHTML = content + arrow;
    } else if (content) {
      // Clear previous
      el.innerHTML = '';

      if (!isArray(content)) {
        content = [content];
      }

      for (var i = 0; i < content.length; i++) {
        if (isDom(content[i]) && content[i].parentNode !== el) {
          el.appendChild(content[i]);
        }
      } // no arrow if empty


      if (arrow && el.childNodes.length) {
        // no need to create a new parent element, but it's not supported by IE 10 and older.
        // const arrowEl = document.createRange().createContextualFragment(arrow);
        var arrowEl = document.createElement('div');
        arrowEl.innerHTML = arrow;
        el.appendChild(arrowEl);
      }
    }
  };

  TooltipHTMLContent.prototype.setEnterable = function (enterable) {
    this._enterable = enterable;
  };

  TooltipHTMLContent.prototype.getSize = function () {
    var el = this.el;
    return [el.offsetWidth, el.offsetHeight];
  };

  TooltipHTMLContent.prototype.moveTo = function (zrX, zrY) {
    var styleCoord = this._styleCoord;
    makeStyleCoord$1(styleCoord, this._zr, this._appendToBody, zrX, zrY);

    if (styleCoord[0] != null && styleCoord[1] != null) {
      var style_1 = this.el.style;
      var transforms = assembleTransform(styleCoord[0], styleCoord[1]);
      each$4(transforms, function (transform) {
        style_1[transform[0]] = transform[1];
      });
    }
  };
  /**
   * when `alwaysShowContent` is true,
   * move the tooltip after chart resized
   */


  TooltipHTMLContent.prototype._moveIfResized = function () {
    // The ratio of left to width
    var ratioX = this._styleCoord[2]; // The ratio of top to height

    var ratioY = this._styleCoord[3];
    this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight());
  };

  TooltipHTMLContent.prototype.hide = function () {
    var _this = this;

    var style = this.el.style;
    style.visibility = 'hidden';
    style.opacity = '0';
    env$1.transform3dSupported && (style.willChange = '');
    this._show = false;
    this._longHideTimeout = setTimeout(function () {
      return _this._longHide = true;
    }, 500);
  };

  TooltipHTMLContent.prototype.hideLater = function (time) {
    if (this._show && !(this._inContent && this._enterable) && !this._alwaysShowContent) {
      if (time) {
        this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times

        this._show = false;
        this._hideTimeout = setTimeout(bind$1(this.hide, this), time);
      } else {
        this.hide();
      }
    }
  };

  TooltipHTMLContent.prototype.isShow = function () {
    return this._show;
  };

  TooltipHTMLContent.prototype.dispose = function () {
    this.el.parentNode.removeChild(this.el);
  };

  return TooltipHTMLContent;
}();

const TooltipHTMLContent$1 = TooltipHTMLContent;
/* Injected with object hook! */

var TooltipRichContent =
/** @class */
function () {
  function TooltipRichContent(api) {
    this._show = false;
    this._styleCoord = [0, 0, 0, 0];
    this._alwaysShowContent = false;
    this._enterable = true;
    this._zr = api.getZr();
    makeStyleCoord(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2);
  }
  /**
   * Update when tooltip is rendered
   */


  TooltipRichContent.prototype.update = function (tooltipModel) {
    var alwaysShowContent = tooltipModel.get('alwaysShowContent');
    alwaysShowContent && this._moveIfResized(); // update alwaysShowContent

    this._alwaysShowContent = alwaysShowContent;
  };

  TooltipRichContent.prototype.show = function () {
    if (this._hideTimeout) {
      clearTimeout(this._hideTimeout);
    }

    this.el.show();
    this._show = true;
  };
  /**
   * Set tooltip content
   */


  TooltipRichContent.prototype.setContent = function (content, markupStyleCreator, tooltipModel, borderColor, arrowPosition) {
    var _this = this;

    if (isObject$2(content)) {
      throwError('');
    }

    if (this.el) {
      this._zr.remove(this.el);
    }

    var textStyleModel = tooltipModel.getModel('textStyle');
    this.el = new ZRText$1({
      style: {
        rich: markupStyleCreator.richTextStyles,
        text: content,
        lineHeight: 22,
        borderWidth: 1,
        borderColor: borderColor,
        textShadowColor: textStyleModel.get('textShadowColor'),
        fill: tooltipModel.get(['textStyle', 'color']),
        padding: getPaddingFromTooltipModel(tooltipModel, 'richText'),
        verticalAlign: 'top',
        align: 'left'
      },
      z: tooltipModel.get('z')
    });
    each$4(['backgroundColor', 'borderRadius', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'], function (propName) {
      _this.el.style[propName] = tooltipModel.get(propName);
    });
    each$4(['textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'], function (propName) {
      _this.el.style[propName] = textStyleModel.get(propName) || 0;
    });

    this._zr.add(this.el);

    var self = this;
    this.el.on('mouseover', function () {
      // clear the timeout in hideLater and keep showing tooltip
      if (self._enterable) {
        clearTimeout(self._hideTimeout);
        self._show = true;
      }

      self._inContent = true;
    });
    this.el.on('mouseout', function () {
      if (self._enterable) {
        if (self._show) {
          self.hideLater(self._hideDelay);
        }
      }

      self._inContent = false;
    });
  };

  TooltipRichContent.prototype.setEnterable = function (enterable) {
    this._enterable = enterable;
  };

  TooltipRichContent.prototype.getSize = function () {
    var el = this.el;
    var bounding = this.el.getBoundingRect(); // bounding rect does not include shadow. For renderMode richText,
    // if overflow, it will be cut. So calculate them accurately.

    var shadowOuterSize = calcShadowOuterSize(el.style);
    return [bounding.width + shadowOuterSize.left + shadowOuterSize.right, bounding.height + shadowOuterSize.top + shadowOuterSize.bottom];
  };

  TooltipRichContent.prototype.moveTo = function (x, y) {
    var el = this.el;

    if (el) {
      var styleCoord = this._styleCoord;
      makeStyleCoord(styleCoord, this._zr, x, y);
      x = styleCoord[0];
      y = styleCoord[1];
      var style = el.style;
      var borderWidth = mathMaxWith0(style.borderWidth || 0);
      var shadowOuterSize = calcShadowOuterSize(style); // rich text x, y do not include border.

      el.x = x + borderWidth + shadowOuterSize.left;
      el.y = y + borderWidth + shadowOuterSize.top;
      el.markRedraw();
    }
  };
  /**
   * when `alwaysShowContent` is true,
   * move the tooltip after chart resized
   */


  TooltipRichContent.prototype._moveIfResized = function () {
    // The ratio of left to width
    var ratioX = this._styleCoord[2]; // The ratio of top to height

    var ratioY = this._styleCoord[3];
    this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight());
  };

  TooltipRichContent.prototype.hide = function () {
    if (this.el) {
      this.el.hide();
    }

    this._show = false;
  };

  TooltipRichContent.prototype.hideLater = function (time) {
    if (this._show && !(this._inContent && this._enterable) && !this._alwaysShowContent) {
      if (time) {
        this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times

        this._show = false;
        this._hideTimeout = setTimeout(bind$1(this.hide, this), time);
      } else {
        this.hide();
      }
    }
  };

  TooltipRichContent.prototype.isShow = function () {
    return this._show;
  };

  TooltipRichContent.prototype.dispose = function () {
    this._zr.remove(this.el);
  };

  return TooltipRichContent;
}();

function mathMaxWith0(val) {
  return Math.max(0, val);
}

function calcShadowOuterSize(style) {
  var shadowBlur = mathMaxWith0(style.shadowBlur || 0);
  var shadowOffsetX = mathMaxWith0(style.shadowOffsetX || 0);
  var shadowOffsetY = mathMaxWith0(style.shadowOffsetY || 0);
  return {
    left: mathMaxWith0(shadowBlur - shadowOffsetX),
    right: mathMaxWith0(shadowBlur + shadowOffsetX),
    top: mathMaxWith0(shadowBlur - shadowOffsetY),
    bottom: mathMaxWith0(shadowBlur + shadowOffsetY)
  };
}

function makeStyleCoord(out, zr, zrX, zrY) {
  out[0] = zrX;
  out[1] = zrY;
  out[2] = out[0] / zr.getWidth();
  out[3] = out[1] / zr.getHeight();
}

const TooltipRichContent$1 = TooltipRichContent;
/* Injected with object hook! */

var proxyRect = new Rect$1({
  shape: {
    x: -1,
    y: -1,
    width: 2,
    height: 2
  }
});

var TooltipView =
/** @class */
function (_super) {
  __extends(TooltipView, _super);

  function TooltipView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = TooltipView.type;
    return _this;
  }

  TooltipView.prototype.init = function (ecModel, api) {
    if (env$1.node || !api.getDom()) {
      return;
    }

    var tooltipModel = ecModel.getComponent('tooltip');
    var renderMode = this._renderMode = getTooltipRenderMode(tooltipModel.get('renderMode'));
    this._tooltipContent = renderMode === 'richText' ? new TooltipRichContent$1(api) : new TooltipHTMLContent$1(api.getDom(), api, {
      appendToBody: tooltipModel.get('appendToBody', true)
    });
  };

  TooltipView.prototype.render = function (tooltipModel, ecModel, api) {
    if (env$1.node || !api.getDom()) {
      return;
    } // Reset


    this.group.removeAll();
    this._tooltipModel = tooltipModel;
    this._ecModel = ecModel;
    this._api = api;
    var tooltipContent = this._tooltipContent;
    tooltipContent.update(tooltipModel);
    tooltipContent.setEnterable(tooltipModel.get('enterable'));

    this._initGlobalListener();

    this._keepShow(); // PENDING
    // `mousemove` event will be triggered very frequently when the mouse moves fast,
    // which causes that the `updatePosition` function was also called frequently.
    // In Chrome with devtools open and Firefox, tooltip looks laggy and shakes. See #14695 #16101
    // To avoid frequent triggering,
    // consider throttling it in 50ms when transition is enabled


    if (this._renderMode !== 'richText' && tooltipModel.get('transitionDuration')) {
      createOrUpdate(this, '_updatePosition', 50, 'fixRate');
    } else {
      clear(this, '_updatePosition');
    }
  };

  TooltipView.prototype._initGlobalListener = function () {
    var tooltipModel = this._tooltipModel;
    var triggerOn = tooltipModel.get('triggerOn');
    register('itemTooltip', this._api, bind$1(function (currTrigger, e, dispatchAction) {
      // If 'none', it is not controlled by mouse totally.
      if (triggerOn !== 'none') {
        if (triggerOn.indexOf(currTrigger) >= 0) {
          this._tryShow(e, dispatchAction);
        } else if (currTrigger === 'leave') {
          this._hide(dispatchAction);
        }
      }
    }, this));
  };

  TooltipView.prototype._keepShow = function () {
    var tooltipModel = this._tooltipModel;
    var ecModel = this._ecModel;
    var api = this._api;
    var triggerOn = tooltipModel.get('triggerOn'); // Try to keep the tooltip show when refreshing

    if (this._lastX != null && this._lastY != null // When user is willing to control tooltip totally using API,
    // self.manuallyShowTip({x, y}) might cause tooltip hide,
    // which is not expected.
    && triggerOn !== 'none' && triggerOn !== 'click') {
      var self_1 = this;
      clearTimeout(this._refreshUpdateTimeout);
      this._refreshUpdateTimeout = setTimeout(function () {
        // Show tip next tick after other charts are rendered
        // In case highlight action has wrong result
        // FIXME
        !api.isDisposed() && self_1.manuallyShowTip(tooltipModel, ecModel, api, {
          x: self_1._lastX,
          y: self_1._lastY,
          dataByCoordSys: self_1._lastDataByCoordSys
        });
      });
    }
  };
  /**
   * Show tip manually by
   * dispatchAction({
   *     type: 'showTip',
   *     x: 10,
   *     y: 10
   * });
   * Or
   * dispatchAction({
   *      type: 'showTip',
   *      seriesIndex: 0,
   *      dataIndex or dataIndexInside or name
   * });
   *
   *  TODO Batch
   */


  TooltipView.prototype.manuallyShowTip = function (tooltipModel, ecModel, api, payload) {
    if (payload.from === this.uid || env$1.node || !api.getDom()) {
      return;
    }

    var dispatchAction = makeDispatchAction(payload, api); // Reset ticket

    this._ticket = ''; // When triggered from axisPointer.

    var dataByCoordSys = payload.dataByCoordSys;
    var cmptRef = findComponentReference(payload, ecModel, api);

    if (cmptRef) {
      var rect = cmptRef.el.getBoundingRect().clone();
      rect.applyTransform(cmptRef.el.transform);

      this._tryShow({
        offsetX: rect.x + rect.width / 2,
        offsetY: rect.y + rect.height / 2,
        target: cmptRef.el,
        position: payload.position,
        // When manully trigger, the mouse is not on the el, so we'd better to
        // position tooltip on the bottom of the el and display arrow is possible.
        positionDefault: 'bottom'
      }, dispatchAction);
    } else if (payload.tooltip && payload.x != null && payload.y != null) {
      var el = proxyRect;
      el.x = payload.x;
      el.y = payload.y;
      el.update();
      getECData(el).tooltipConfig = {
        name: null,
        option: payload.tooltip
      }; // Manually show tooltip while view is not using zrender elements.

      this._tryShow({
        offsetX: payload.x,
        offsetY: payload.y,
        target: el
      }, dispatchAction);
    } else if (dataByCoordSys) {
      this._tryShow({
        offsetX: payload.x,
        offsetY: payload.y,
        position: payload.position,
        dataByCoordSys: dataByCoordSys,
        tooltipOption: payload.tooltipOption
      }, dispatchAction);
    } else if (payload.seriesIndex != null) {
      if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) {
        return;
      }

      var pointInfo = findPointFromSeries(payload, ecModel);
      var cx = pointInfo.point[0];
      var cy = pointInfo.point[1];

      if (cx != null && cy != null) {
        this._tryShow({
          offsetX: cx,
          offsetY: cy,
          target: pointInfo.el,
          position: payload.position,
          // When manully trigger, the mouse is not on the el, so we'd better to
          // position tooltip on the bottom of the el and display arrow is possible.
          positionDefault: 'bottom'
        }, dispatchAction);
      }
    } else if (payload.x != null && payload.y != null) {
      // FIXME
      // should wrap dispatchAction like `axisPointer/globalListener` ?
      api.dispatchAction({
        type: 'updateAxisPointer',
        x: payload.x,
        y: payload.y
      });

      this._tryShow({
        offsetX: payload.x,
        offsetY: payload.y,
        position: payload.position,
        target: api.getZr().findHover(payload.x, payload.y).target
      }, dispatchAction);
    }
  };

  TooltipView.prototype.manuallyHideTip = function (tooltipModel, ecModel, api, payload) {
    var tooltipContent = this._tooltipContent;

    if (this._tooltipModel) {
      tooltipContent.hideLater(this._tooltipModel.get('hideDelay'));
    }

    this._lastX = this._lastY = this._lastDataByCoordSys = null;

    if (payload.from !== this.uid) {
      this._hide(makeDispatchAction(payload, api));
    }
  }; // Be compatible with previous design, that is, when tooltip.type is 'axis' and
  // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer
  // and tooltip.


  TooltipView.prototype._manuallyAxisShowTip = function (tooltipModel, ecModel, api, payload) {
    var seriesIndex = payload.seriesIndex;
    var dataIndex = payload.dataIndex; // @ts-ignore

    var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;

    if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) {
      return;
    }

    var seriesModel = ecModel.getSeriesByIndex(seriesIndex);

    if (!seriesModel) {
      return;
    }

    var data = seriesModel.getData();
    var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model], this._tooltipModel);

    if (tooltipCascadedModel.get('trigger') !== 'axis') {
      return;
    }

    api.dispatchAction({
      type: 'updateAxisPointer',
      seriesIndex: seriesIndex,
      dataIndex: dataIndex,
      position: payload.position
    });
    return true;
  };

  TooltipView.prototype._tryShow = function (e, dispatchAction) {
    var el = e.target;
    var tooltipModel = this._tooltipModel;

    if (!tooltipModel) {
      return;
    } // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed


    this._lastX = e.offsetX;
    this._lastY = e.offsetY;
    var dataByCoordSys = e.dataByCoordSys;

    if (dataByCoordSys && dataByCoordSys.length) {
      this._showAxisTooltip(dataByCoordSys, e);
    } else if (el) {
      this._lastDataByCoordSys = null;
      var seriesDispatcher_1;
      var cmptDispatcher_1;
      findEventDispatcher(el, function (target) {
        // Always show item tooltip if mouse is on the element with dataIndex
        if (getECData(target).dataIndex != null) {
          seriesDispatcher_1 = target;
          return true;
        } // Tooltip provided directly. Like legend.


        if (getECData(target).tooltipConfig != null) {
          cmptDispatcher_1 = target;
          return true;
        }
      }, true);

      if (seriesDispatcher_1) {
        this._showSeriesItemTooltip(e, seriesDispatcher_1, dispatchAction);
      } else if (cmptDispatcher_1) {
        this._showComponentItemTooltip(e, cmptDispatcher_1, dispatchAction);
      } else {
        this._hide(dispatchAction);
      }
    } else {
      this._lastDataByCoordSys = null;

      this._hide(dispatchAction);
    }
  };

  TooltipView.prototype._showOrMove = function (tooltipModel, cb) {
    // showDelay is used in this case: tooltip.enterable is set
    // as true. User intent to move mouse into tooltip and click
    // something. `showDelay` makes it easier to enter the content
    // but tooltip do not move immediately.
    var delay = tooltipModel.get('showDelay');
    cb = bind$1(cb, this);
    clearTimeout(this._showTimout);
    delay > 0 ? this._showTimout = setTimeout(cb, delay) : cb();
  };

  TooltipView.prototype._showAxisTooltip = function (dataByCoordSys, e) {
    var ecModel = this._ecModel;
    var globalTooltipModel = this._tooltipModel;
    var point = [e.offsetX, e.offsetY];
    var singleTooltipModel = buildTooltipModel([e.tooltipOption], globalTooltipModel);
    var renderMode = this._renderMode;
    var cbParamsList = [];
    var articleMarkup = createTooltipMarkup('section', {
      blocks: [],
      noHeader: true
    }); // Only for legacy: `Serise['formatTooltip']` returns a string.

    var markupTextArrLegacy = [];
    var markupStyleCreator = new TooltipMarkupStyleCreator();
    each$4(dataByCoordSys, function (itemCoordSys) {
      each$4(itemCoordSys.dataByAxis, function (axisItem) {
        var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex);
        var axisValue = axisItem.value;

        if (!axisModel || axisValue == null) {
          return;
        }

        var axisValueLabel = getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt);
        var axisSectionMarkup = createTooltipMarkup('section', {
          header: axisValueLabel,
          noHeader: !trim(axisValueLabel),
          sortBlocks: true,
          blocks: []
        });
        articleMarkup.blocks.push(axisSectionMarkup);
        each$4(axisItem.seriesDataIndices, function (idxItem) {
          var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
          var dataIndex = idxItem.dataIndexInside;
          var cbParams = series.getDataParams(dataIndex); // Can't find data.

          if (cbParams.dataIndex < 0) {
            return;
          }

          cbParams.axisDim = axisItem.axisDim;
          cbParams.axisIndex = axisItem.axisIndex;
          cbParams.axisType = axisItem.axisType;
          cbParams.axisId = axisItem.axisId;
          cbParams.axisValue = getAxisRawValue(axisModel.axis, {
            value: axisValue
          });
          cbParams.axisValueLabel = axisValueLabel; // Pre-create marker style for makers. Users can assemble richText
          // text in `formatter` callback and use those markers style.

          cbParams.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(cbParams.color), renderMode);
          var seriesTooltipResult = normalizeTooltipFormatResult(series.formatTooltip(dataIndex, true, null));
          var frag = seriesTooltipResult.frag;

          if (frag) {
            var valueFormatter = buildTooltipModel([series], globalTooltipModel).get('valueFormatter');
            axisSectionMarkup.blocks.push(valueFormatter ? extend({
              valueFormatter: valueFormatter
            }, frag) : frag);
          }

          if (seriesTooltipResult.text) {
            markupTextArrLegacy.push(seriesTooltipResult.text);
          }

          cbParamsList.push(cbParams);
        });
      });
    }); // In most cases, the second axis is displays upper on the first one.
    // So we reverse it to look better.

    articleMarkup.blocks.reverse();
    markupTextArrLegacy.reverse();
    var positionExpr = e.position;
    var orderMode = singleTooltipModel.get('order');
    var builtMarkupText = buildTooltipMarkup(articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), singleTooltipModel.get('textStyle'));
    builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText);
    var blockBreak = renderMode === 'richText' ? '\n\n' : '<br/>';
    var allMarkupText = markupTextArrLegacy.join(blockBreak);

    this._showOrMove(singleTooltipModel, function () {
      if (this._updateContentNotChangedOnAxis(dataByCoordSys, cbParamsList)) {
        this._updatePosition(singleTooltipModel, positionExpr, point[0], point[1], this._tooltipContent, cbParamsList);
      } else {
        this._showTooltipContent(singleTooltipModel, allMarkupText, cbParamsList, Math.random() + '', point[0], point[1], positionExpr, null, markupStyleCreator);
      }
    }); // Do not trigger events here, because this branch only be entered
    // from dispatchAction.

  };

  TooltipView.prototype._showSeriesItemTooltip = function (e, dispatcher, dispatchAction) {
    var ecModel = this._ecModel;
    var ecData = getECData(dispatcher); // Use dataModel in element if possible
    // Used when mouseover on a element like markPoint or edge
    // In which case, the data is not main data in series.

    var seriesIndex = ecData.seriesIndex;
    var seriesModel = ecModel.getSeriesByIndex(seriesIndex); // For example, graph link.

    var dataModel = ecData.dataModel || seriesModel;
    var dataIndex = ecData.dataIndex;
    var dataType = ecData.dataType;
    var data = dataModel.getData(dataType);
    var renderMode = this._renderMode;
    var positionDefault = e.positionDefault;
    var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model], this._tooltipModel, positionDefault ? {
      position: positionDefault
    } : null);
    var tooltipTrigger = tooltipModel.get('trigger');

    if (tooltipTrigger != null && tooltipTrigger !== 'item') {
      return;
    }

    var params = dataModel.getDataParams(dataIndex, dataType);
    var markupStyleCreator = new TooltipMarkupStyleCreator(); // Pre-create marker style for makers. Users can assemble richText
    // text in `formatter` callback and use those markers style.

    params.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(params.color), renderMode);
    var seriesTooltipResult = normalizeTooltipFormatResult(dataModel.formatTooltip(dataIndex, false, dataType));
    var orderMode = tooltipModel.get('order');
    var valueFormatter = tooltipModel.get('valueFormatter');
    var frag = seriesTooltipResult.frag;
    var markupText = frag ? buildTooltipMarkup(valueFormatter ? extend({
      valueFormatter: valueFormatter
    }, frag) : frag, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), tooltipModel.get('textStyle')) : seriesTooltipResult.text;
    var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;

    this._showOrMove(tooltipModel, function () {
      this._showTooltipContent(tooltipModel, markupText, params, asyncTicket, e.offsetX, e.offsetY, e.position, e.target, markupStyleCreator);
    }); // FIXME
    // duplicated showtip if manuallyShowTip is called from dispatchAction.


    dispatchAction({
      type: 'showTip',
      dataIndexInside: dataIndex,
      dataIndex: data.getRawIndex(dataIndex),
      seriesIndex: seriesIndex,
      from: this.uid
    });
  };

  TooltipView.prototype._showComponentItemTooltip = function (e, el, dispatchAction) {
    var ecData = getECData(el);
    var tooltipConfig = ecData.tooltipConfig;
    var tooltipOpt = tooltipConfig.option || {};

    if (isString(tooltipOpt)) {
      var content = tooltipOpt;
      tooltipOpt = {
        content: content,
        // Fixed formatter
        formatter: content
      };
    }

    var tooltipModelCascade = [tooltipOpt];

    var cmpt = this._ecModel.getComponent(ecData.componentMainType, ecData.componentIndex);

    if (cmpt) {
      tooltipModelCascade.push(cmpt);
    } // In most cases, component tooltip formatter has different params with series tooltip formatter,
    // so that they cannot share the same formatter. Since the global tooltip formatter is used for series
    // by convention, we do not use it as the default formatter for component.


    tooltipModelCascade.push({
      formatter: tooltipOpt.content
    });
    var positionDefault = e.positionDefault;
    var subTooltipModel = buildTooltipModel(tooltipModelCascade, this._tooltipModel, positionDefault ? {
      position: positionDefault
    } : null);
    var defaultHtml = subTooltipModel.get('content');
    var asyncTicket = Math.random() + ''; // PENDING: this case do not support richText style yet.

    var markupStyleCreator = new TooltipMarkupStyleCreator(); // Do not check whether `trigger` is 'none' here, because `trigger`
    // only works on coordinate system. In fact, we have not found case
    // that requires setting `trigger` nothing on component yet.

    this._showOrMove(subTooltipModel, function () {
      // Use formatterParams from element defined in component
      // Avoid users modify it.
      var formatterParams = clone$2(subTooltipModel.get('formatterParams') || {});

      this._showTooltipContent(subTooltipModel, defaultHtml, formatterParams, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator);
    }); // If not dispatch showTip, tip may be hide triggered by axis.


    dispatchAction({
      type: 'showTip',
      from: this.uid
    });
  };

  TooltipView.prototype._showTooltipContent = function ( // Use Model<TooltipOption> insteadof TooltipModel because this model may be from series or other options.
  // Instead of top level tooltip.
  tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markupStyleCreator) {
    // Reset ticket
    this._ticket = '';

    if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) {
      return;
    }

    var tooltipContent = this._tooltipContent;
    tooltipContent.setEnterable(tooltipModel.get('enterable'));
    var formatter = tooltipModel.get('formatter');
    positionExpr = positionExpr || tooltipModel.get('position');
    var html = defaultHtml;

    var nearPoint = this._getNearestPoint([x, y], params, tooltipModel.get('trigger'), tooltipModel.get('borderColor'));

    var nearPointColor = nearPoint.color;

    if (formatter) {
      if (isString(formatter)) {
        var useUTC = tooltipModel.ecModel.get('useUTC');
        var params0 = isArray(params) ? params[0] : params;
        var isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0;
        html = formatter;

        if (isTimeAxis) {
          html = format(params0.axisValue, html, useUTC);
        }

        html = formatTpl(html, params, true);
      } else if (isFunction(formatter)) {
        var callback = bind$1(function (cbTicket, html) {
          if (cbTicket === this._ticket) {
            tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr);

            this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el);
          }
        }, this);
        this._ticket = asyncTicket;
        html = formatter(params, asyncTicket, callback);
      } else {
        html = formatter;
      }
    }

    tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr);
    tooltipContent.show(tooltipModel, nearPointColor);

    this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el);
  };

  TooltipView.prototype._getNearestPoint = function (point, tooltipDataParams, trigger, borderColor) {
    if (trigger === 'axis' || isArray(tooltipDataParams)) {
      return {
        color: borderColor || (this._renderMode === 'html' ? '#fff' : 'none')
      };
    }

    if (!isArray(tooltipDataParams)) {
      return {
        color: borderColor || tooltipDataParams.color || tooltipDataParams.borderColor
      };
    }
  };

  TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, // Mouse x
  y, // Mouse y
  content, params, el) {
    var viewWidth = this._api.getWidth();

    var viewHeight = this._api.getHeight();

    positionExpr = positionExpr || tooltipModel.get('position');
    var contentSize = content.getSize();
    var align = tooltipModel.get('align');
    var vAlign = tooltipModel.get('verticalAlign');
    var rect = el && el.getBoundingRect().clone();
    el && rect.applyTransform(el.transform);

    if (isFunction(positionExpr)) {
      // Callback of position can be an array or a string specify the position
      positionExpr = positionExpr([x, y], params, content.el, rect, {
        viewSize: [viewWidth, viewHeight],
        contentSize: contentSize.slice()
      });
    }

    if (isArray(positionExpr)) {
      x = parsePercent(positionExpr[0], viewWidth);
      y = parsePercent(positionExpr[1], viewHeight);
    } else if (isObject$2(positionExpr)) {
      var boxLayoutPosition = positionExpr;
      boxLayoutPosition.width = contentSize[0];
      boxLayoutPosition.height = contentSize[1];
      var layoutRect = getLayoutRect(boxLayoutPosition, {
        width: viewWidth,
        height: viewHeight
      });
      x = layoutRect.x;
      y = layoutRect.y;
      align = null; // When positionExpr is left/top/right/bottom,
      // align and verticalAlign will not work.

      vAlign = null;
    } // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element
    else if (isString(positionExpr) && el) {
        var pos = calcTooltipPosition(positionExpr, rect, contentSize, tooltipModel.get('borderWidth'));
        x = pos[0];
        y = pos[1];
      } else {
        var pos = refixTooltipPosition(x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20);
        x = pos[0];
        y = pos[1];
      }

    align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0);
    vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0);

    if (shouldTooltipConfine(tooltipModel)) {
      var pos = confineTooltipPosition(x, y, content, viewWidth, viewHeight);
      x = pos[0];
      y = pos[1];
    }

    content.moveTo(x, y);
  }; // FIXME
  // Should we remove this but leave this to user?


  TooltipView.prototype._updateContentNotChangedOnAxis = function (dataByCoordSys, cbParamsList) {
    var lastCoordSys = this._lastDataByCoordSys;
    var lastCbParamsList = this._cbParamsList;
    var contentNotChanged = !!lastCoordSys && lastCoordSys.length === dataByCoordSys.length;
    contentNotChanged && each$4(lastCoordSys, function (lastItemCoordSys, indexCoordSys) {
      var lastDataByAxis = lastItemCoordSys.dataByAxis || [];
      var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {};
      var thisDataByAxis = thisItemCoordSys.dataByAxis || [];
      contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length;
      contentNotChanged && each$4(lastDataByAxis, function (lastItem, indexAxis) {
        var thisItem = thisDataByAxis[indexAxis] || {};
        var lastIndices = lastItem.seriesDataIndices || [];
        var newIndices = thisItem.seriesDataIndices || [];
        contentNotChanged = contentNotChanged && lastItem.value === thisItem.value && lastItem.axisType === thisItem.axisType && lastItem.axisId === thisItem.axisId && lastIndices.length === newIndices.length;
        contentNotChanged && each$4(lastIndices, function (lastIdxItem, j) {
          var newIdxItem = newIndices[j];
          contentNotChanged = contentNotChanged && lastIdxItem.seriesIndex === newIdxItem.seriesIndex && lastIdxItem.dataIndex === newIdxItem.dataIndex;
        }); // check is cbParams data value changed

        lastCbParamsList && each$4(lastItem.seriesDataIndices, function (idxItem) {
          var seriesIdx = idxItem.seriesIndex;
          var cbParams = cbParamsList[seriesIdx];
          var lastCbParams = lastCbParamsList[seriesIdx];

          if (cbParams && lastCbParams && lastCbParams.data !== cbParams.data) {
            contentNotChanged = false;
          }
        });
      });
    });
    this._lastDataByCoordSys = dataByCoordSys;
    this._cbParamsList = cbParamsList;
    return !!contentNotChanged;
  };

  TooltipView.prototype._hide = function (dispatchAction) {
    // Do not directly hideLater here, because this behavior may be prevented
    // in dispatchAction when showTip is dispatched.
    // FIXME
    // duplicated hideTip if manuallyHideTip is called from dispatchAction.
    this._lastDataByCoordSys = null;
    dispatchAction({
      type: 'hideTip',
      from: this.uid
    });
  };

  TooltipView.prototype.dispose = function (ecModel, api) {
    if (env$1.node || !api.getDom()) {
      return;
    }

    clear(this, '_updatePosition');

    this._tooltipContent.dispose();

    unregister('itemTooltip', api);
  };

  TooltipView.type = 'tooltip';
  return TooltipView;
}(ComponentView$1);
/**
 * From top to bottom. (the last one should be globalTooltipModel);
 */


function buildTooltipModel(modelCascade, globalTooltipModel, defaultTooltipOption) {
  // Last is always tooltip model.
  var ecModel = globalTooltipModel.ecModel;
  var resultModel;

  if (defaultTooltipOption) {
    resultModel = new Model$1(defaultTooltipOption, ecModel, ecModel);
    resultModel = new Model$1(globalTooltipModel.option, resultModel, ecModel);
  } else {
    resultModel = globalTooltipModel;
  }

  for (var i = modelCascade.length - 1; i >= 0; i--) {
    var tooltipOpt = modelCascade[i];

    if (tooltipOpt) {
      if (tooltipOpt instanceof Model$1) {
        tooltipOpt = tooltipOpt.get('tooltip', true);
      } // In each data item tooltip can be simply write:
      // {
      //  value: 10,
      //  tooltip: 'Something you need to know'
      // }


      if (isString(tooltipOpt)) {
        tooltipOpt = {
          formatter: tooltipOpt
        };
      }

      if (tooltipOpt) {
        resultModel = new Model$1(tooltipOpt, resultModel, ecModel);
      }
    }
  }

  return resultModel;
}

function makeDispatchAction(payload, api) {
  return payload.dispatchAction || bind$1(api.dispatchAction, api);
}

function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) {
  var size = content.getSize();
  var width = size[0];
  var height = size[1];

  if (gapH != null) {
    // Add extra 2 pixels for this case:
    // At present the "values" in default tooltip are using CSS `float: right`.
    // When the right edge of the tooltip box is on the right side of the
    // viewport, the `float` layout might push the "values" to the second line.
    if (x + width + gapH + 2 > viewWidth) {
      x -= width + gapH;
    } else {
      x += gapH;
    }
  }

  if (gapV != null) {
    if (y + height + gapV > viewHeight) {
      y -= height + gapV;
    } else {
      y += gapV;
    }
  }

  return [x, y];
}

function confineTooltipPosition(x, y, content, viewWidth, viewHeight) {
  var size = content.getSize();
  var width = size[0];
  var height = size[1];
  x = Math.min(x + width, viewWidth) - width;
  y = Math.min(y + height, viewHeight) - height;
  x = Math.max(x, 0);
  y = Math.max(y, 0);
  return [x, y];
}

function calcTooltipPosition(position, rect, contentSize, borderWidth) {
  var domWidth = contentSize[0];
  var domHeight = contentSize[1];
  var offset = Math.ceil(Math.SQRT2 * borderWidth) + 8;
  var x = 0;
  var y = 0;
  var rectWidth = rect.width;
  var rectHeight = rect.height;

  switch (position) {
    case 'inside':
      x = rect.x + rectWidth / 2 - domWidth / 2;
      y = rect.y + rectHeight / 2 - domHeight / 2;
      break;

    case 'top':
      x = rect.x + rectWidth / 2 - domWidth / 2;
      y = rect.y - domHeight - offset;
      break;

    case 'bottom':
      x = rect.x + rectWidth / 2 - domWidth / 2;
      y = rect.y + rectHeight + offset;
      break;

    case 'left':
      x = rect.x - domWidth - offset;
      y = rect.y + rectHeight / 2 - domHeight / 2;
      break;

    case 'right':
      x = rect.x + rectWidth + offset;
      y = rect.y + rectHeight / 2 - domHeight / 2;
  }

  return [x, y];
}

function isCenterAlign(align) {
  return align === 'center' || align === 'middle';
}
/**
 * Find target component by payload like:
 * ```js
 * { legendId: 'some_id', name: 'xxx' }
 * { toolboxIndex: 1, name: 'xxx' }
 * { geoName: 'some_name', name: 'xxx' }
 * ```
 * PENDING: at present only
 *
 * If not found, return null/undefined.
 */


function findComponentReference(payload, ecModel, api) {
  var queryOptionMap = preParseFinder(payload).queryOptionMap;
  var componentMainType = queryOptionMap.keys()[0];

  if (!componentMainType || componentMainType === 'series') {
    return;
  }

  var queryResult = queryReferringComponents(ecModel, componentMainType, queryOptionMap.get(componentMainType), {
    useDefault: false,
    enableAll: false,
    enableNone: false
  });
  var model = queryResult.models[0];

  if (!model) {
    return;
  }

  var view = api.getViewOfComponentModel(model);
  var el;
  view.group.traverse(function (subEl) {
    var tooltipConfig = getECData(subEl).tooltipConfig;

    if (tooltipConfig && tooltipConfig.name === payload.name) {
      el = subEl;
      return true; // stop
    }
  });

  if (el) {
    return {
      componentMainType: componentMainType,
      componentIndex: model.componentIndex,
      el: el
    };
  }
}

const TooltipView$1 = TooltipView;
/* Injected with object hook! */

function install$4(registers) {
  use(install$6);
  registers.registerComponentModel(TooltipModel$1);
  registers.registerComponentView(TooltipView$1);
  /**
   * @action
   * @property {string} type
   * @property {number} seriesIndex
   * @property {number} dataIndex
   * @property {number} [x]
   * @property {number} [y]
   */

  registers.registerAction({
    type: 'showTip',
    event: 'showTip',
    update: 'tooltip:manuallyShowTip'
  }, noop);
  registers.registerAction({
    type: 'hideTip',
    event: 'hideTip',
    update: 'tooltip:manuallyHideTip'
  }, noop);
}
/* Injected with object hook! */

var TitleModel =
/** @class */
function (_super) {
  __extends(TitleModel, _super);

  function TitleModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = TitleModel.type;
    _this.layoutMode = {
      type: 'box',
      ignoreSize: true
    };
    return _this;
  }

  TitleModel.type = 'title';
  TitleModel.defaultOption = {
    // zlevel: 0,
    z: 6,
    show: true,
    text: '',
    target: 'blank',
    subtext: '',
    subtarget: 'blank',
    left: 0,
    top: 0,
    backgroundColor: 'rgba(0,0,0,0)',
    borderColor: '#ccc',
    borderWidth: 0,
    padding: 5,
    itemGap: 10,
    textStyle: {
      fontSize: 18,
      fontWeight: 'bold',
      color: '#464646'
    },
    subtextStyle: {
      fontSize: 12,
      color: '#6E7079'
    }
  };
  return TitleModel;
}(ComponentModel$1); // View


var TitleView =
/** @class */
function (_super) {
  __extends(TitleView, _super);

  function TitleView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = TitleView.type;
    return _this;
  }

  TitleView.prototype.render = function (titleModel, ecModel, api) {
    this.group.removeAll();

    if (!titleModel.get('show')) {
      return;
    }

    var group = this.group;
    var textStyleModel = titleModel.getModel('textStyle');
    var subtextStyleModel = titleModel.getModel('subtextStyle');
    var textAlign = titleModel.get('textAlign');
    var textVerticalAlign = retrieve2(titleModel.get('textBaseline'), titleModel.get('textVerticalAlign'));
    var textEl = new ZRText$1({
      style: createTextStyle(textStyleModel, {
        text: titleModel.get('text'),
        fill: textStyleModel.getTextColor()
      }, {
        disableBox: true
      }),
      z2: 10
    });
    var textRect = textEl.getBoundingRect();
    var subText = titleModel.get('subtext');
    var subTextEl = new ZRText$1({
      style: createTextStyle(subtextStyleModel, {
        text: subText,
        fill: subtextStyleModel.getTextColor(),
        y: textRect.height + titleModel.get('itemGap'),
        verticalAlign: 'top'
      }, {
        disableBox: true
      }),
      z2: 10
    });
    var link = titleModel.get('link');
    var sublink = titleModel.get('sublink');
    var triggerEvent = titleModel.get('triggerEvent', true);
    textEl.silent = !link && !triggerEvent;
    subTextEl.silent = !sublink && !triggerEvent;

    if (link) {
      textEl.on('click', function () {
        windowOpen(link, '_' + titleModel.get('target'));
      });
    }

    if (sublink) {
      subTextEl.on('click', function () {
        windowOpen(sublink, '_' + titleModel.get('subtarget'));
      });
    }

    getECData(textEl).eventData = getECData(subTextEl).eventData = triggerEvent ? {
      componentType: 'title',
      componentIndex: titleModel.componentIndex
    } : null;
    group.add(textEl);
    subText && group.add(subTextEl); // If no subText, but add subTextEl, there will be an empty line.

    var groupRect = group.getBoundingRect();
    var layoutOption = titleModel.getBoxLayoutParams();
    layoutOption.width = groupRect.width;
    layoutOption.height = groupRect.height;
    var layoutRect = getLayoutRect(layoutOption, {
      width: api.getWidth(),
      height: api.getHeight()
    }, titleModel.get('padding')); // Adjust text align based on position

    if (!textAlign) {
      // Align left if title is on the left. center and right is same
      textAlign = titleModel.get('left') || titleModel.get('right'); // @ts-ignore

      if (textAlign === 'middle') {
        textAlign = 'center';
      } // Adjust layout by text align


      if (textAlign === 'right') {
        layoutRect.x += layoutRect.width;
      } else if (textAlign === 'center') {
        layoutRect.x += layoutRect.width / 2;
      }
    }

    if (!textVerticalAlign) {
      textVerticalAlign = titleModel.get('top') || titleModel.get('bottom'); // @ts-ignore

      if (textVerticalAlign === 'center') {
        textVerticalAlign = 'middle';
      }

      if (textVerticalAlign === 'bottom') {
        layoutRect.y += layoutRect.height;
      } else if (textVerticalAlign === 'middle') {
        layoutRect.y += layoutRect.height / 2;
      }

      textVerticalAlign = textVerticalAlign || 'top';
    }

    group.x = layoutRect.x;
    group.y = layoutRect.y;
    group.markRedraw();
    var alignStyle = {
      align: textAlign,
      verticalAlign: textVerticalAlign
    };
    textEl.setStyle(alignStyle);
    subTextEl.setStyle(alignStyle); // Render background
    // Get groupRect again because textAlign has been changed

    groupRect = group.getBoundingRect();
    var padding = layoutRect.margin;
    var style = titleModel.getItemStyle(['color', 'opacity']);
    style.fill = titleModel.get('backgroundColor');
    var rect = new Rect$1({
      shape: {
        x: groupRect.x - padding[3],
        y: groupRect.y - padding[0],
        width: groupRect.width + padding[1] + padding[3],
        height: groupRect.height + padding[0] + padding[2],
        r: titleModel.get('borderRadius')
      },
      style: style,
      subPixelOptimize: true,
      silent: true
    });
    group.add(rect);
  };

  TitleView.type = 'title';
  return TitleView;
}(ComponentView$1);

function install$3(registers) {
  registers.registerComponentModel(TitleModel);
  registers.registerComponentView(TitleView);
}
/* Injected with object hook! */

var getDefaultSelectorOptions = function (ecModel, type) {
  if (type === 'all') {
    return {
      type: 'all',
      title: ecModel.getLocaleModel().get(['legend', 'selector', 'all'])
    };
  } else if (type === 'inverse') {
    return {
      type: 'inverse',
      title: ecModel.getLocaleModel().get(['legend', 'selector', 'inverse'])
    };
  }
};

var LegendModel =
/** @class */
function (_super) {
  __extends(LegendModel, _super);

  function LegendModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = LegendModel.type;
    _this.layoutMode = {
      type: 'box',
      // legend.width/height are maxWidth/maxHeight actually,
      // whereas real width/height is calculated by its content.
      // (Setting {left: 10, right: 10} does not make sense).
      // So consider the case:
      // `setOption({legend: {left: 10});`
      // then `setOption({legend: {right: 10});`
      // The previous `left` should be cleared by setting `ignoreSize`.
      ignoreSize: true
    };
    return _this;
  }

  LegendModel.prototype.init = function (option, parentModel, ecModel) {
    this.mergeDefaultAndTheme(option, ecModel);
    option.selected = option.selected || {};

    this._updateSelector(option);
  };

  LegendModel.prototype.mergeOption = function (option, ecModel) {
    _super.prototype.mergeOption.call(this, option, ecModel);

    this._updateSelector(option);
  };

  LegendModel.prototype._updateSelector = function (option) {
    var selector = option.selector;
    var ecModel = this.ecModel;

    if (selector === true) {
      selector = option.selector = ['all', 'inverse'];
    }

    if (isArray(selector)) {
      each$4(selector, function (item, index) {
        isString(item) && (item = {
          type: item
        });
        selector[index] = merge(item, getDefaultSelectorOptions(ecModel, item.type));
      });
    }
  };

  LegendModel.prototype.optionUpdated = function () {
    this._updateData(this.ecModel);

    var legendData = this._data; // If selectedMode is single, try to select one

    if (legendData[0] && this.get('selectedMode') === 'single') {
      var hasSelected = false; // If has any selected in option.selected

      for (var i = 0; i < legendData.length; i++) {
        var name_1 = legendData[i].get('name');

        if (this.isSelected(name_1)) {
          // Force to unselect others
          this.select(name_1);
          hasSelected = true;
          break;
        }
      } // Try select the first if selectedMode is single


      !hasSelected && this.select(legendData[0].get('name'));
    }
  };

  LegendModel.prototype._updateData = function (ecModel) {
    var potentialData = [];
    var availableNames = [];
    ecModel.eachRawSeries(function (seriesModel) {
      var seriesName = seriesModel.name;
      availableNames.push(seriesName);
      var isPotential;

      if (seriesModel.legendVisualProvider) {
        var provider = seriesModel.legendVisualProvider;
        var names = provider.getAllNames();

        if (!ecModel.isSeriesFiltered(seriesModel)) {
          availableNames = availableNames.concat(names);
        }

        if (names.length) {
          potentialData = potentialData.concat(names);
        } else {
          isPotential = true;
        }
      } else {
        isPotential = true;
      }

      if (isPotential && isNameSpecified(seriesModel)) {
        potentialData.push(seriesModel.name);
      }
    });
    /**
     * @type {Array.<string>}
     * @private
     */

    this._availableNames = availableNames; // If legend.data is not specified in option, use availableNames as data,
    // which is convenient for user preparing option.

    var rawData = this.get('data') || potentialData;
    var legendNameMap = createHashMap();
    var legendData = map$1(rawData, function (dataItem) {
      // Can be string or number
      if (isString(dataItem) || isNumber(dataItem)) {
        dataItem = {
          name: dataItem
        };
      }

      if (legendNameMap.get(dataItem.name)) {
        // remove legend name duplicate
        return null;
      }

      legendNameMap.set(dataItem.name, true);
      return new Model$1(dataItem, this, this.ecModel);
    }, this);
    /**
     * @type {Array.<module:echarts/model/Model>}
     * @private
     */

    this._data = filter(legendData, function (item) {
      return !!item;
    });
  };

  LegendModel.prototype.getData = function () {
    return this._data;
  };

  LegendModel.prototype.select = function (name) {
    var selected = this.option.selected;
    var selectedMode = this.get('selectedMode');

    if (selectedMode === 'single') {
      var data = this._data;
      each$4(data, function (dataItem) {
        selected[dataItem.get('name')] = false;
      });
    }

    selected[name] = true;
  };

  LegendModel.prototype.unSelect = function (name) {
    if (this.get('selectedMode') !== 'single') {
      this.option.selected[name] = false;
    }
  };

  LegendModel.prototype.toggleSelected = function (name) {
    var selected = this.option.selected; // Default is true

    if (!selected.hasOwnProperty(name)) {
      selected[name] = true;
    }

    this[selected[name] ? 'unSelect' : 'select'](name);
  };

  LegendModel.prototype.allSelect = function () {
    var data = this._data;
    var selected = this.option.selected;
    each$4(data, function (dataItem) {
      selected[dataItem.get('name', true)] = true;
    });
  };

  LegendModel.prototype.inverseSelect = function () {
    var data = this._data;
    var selected = this.option.selected;
    each$4(data, function (dataItem) {
      var name = dataItem.get('name', true); // Initially, default value is true

      if (!selected.hasOwnProperty(name)) {
        selected[name] = true;
      }

      selected[name] = !selected[name];
    });
  };

  LegendModel.prototype.isSelected = function (name) {
    var selected = this.option.selected;
    return !(selected.hasOwnProperty(name) && !selected[name]) && indexOf(this._availableNames, name) >= 0;
  };

  LegendModel.prototype.getOrient = function () {
    return this.get('orient') === 'vertical' ? {
      index: 1,
      name: 'vertical'
    } : {
      index: 0,
      name: 'horizontal'
    };
  };

  LegendModel.type = 'legend.plain';
  LegendModel.dependencies = ['series'];
  LegendModel.defaultOption = {
    // zlevel: 0,
    z: 4,
    show: true,
    orient: 'horizontal',
    left: 'center',
    // right: 'center',
    top: 0,
    // bottom: null,
    align: 'auto',
    backgroundColor: 'rgba(0,0,0,0)',
    borderColor: '#ccc',
    borderRadius: 0,
    borderWidth: 0,
    padding: 5,
    itemGap: 10,
    itemWidth: 25,
    itemHeight: 14,
    symbolRotate: 'inherit',
    symbolKeepAspect: true,
    inactiveColor: '#ccc',
    inactiveBorderColor: '#ccc',
    inactiveBorderWidth: 'auto',
    itemStyle: {
      color: 'inherit',
      opacity: 'inherit',
      borderColor: 'inherit',
      borderWidth: 'auto',
      borderCap: 'inherit',
      borderJoin: 'inherit',
      borderDashOffset: 'inherit',
      borderMiterLimit: 'inherit'
    },
    lineStyle: {
      width: 'auto',
      color: 'inherit',
      inactiveColor: '#ccc',
      inactiveWidth: 2,
      opacity: 'inherit',
      type: 'inherit',
      cap: 'inherit',
      join: 'inherit',
      dashOffset: 'inherit',
      miterLimit: 'inherit'
    },
    textStyle: {
      color: '#333'
    },
    selectedMode: true,
    selector: false,
    selectorLabel: {
      show: true,
      borderRadius: 10,
      padding: [3, 5, 3, 5],
      fontSize: 12,
      fontFamily: 'sans-serif',
      color: '#666',
      borderWidth: 1,
      borderColor: '#666'
    },
    emphasis: {
      selectorLabel: {
        show: true,
        color: '#eee',
        backgroundColor: '#666'
      }
    },
    selectorPosition: 'auto',
    selectorItemGap: 7,
    selectorButtonGap: 10,
    tooltip: {
      show: false
    }
  };
  return LegendModel;
}(ComponentModel$1);

const LegendModel$1 = LegendModel;
/* Injected with object hook! */

var curry = curry$1;
var each = each$4;
var Group$1 = Group$3;

var LegendView =
/** @class */
function (_super) {
  __extends(LegendView, _super);

  function LegendView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = LegendView.type;
    _this.newlineDisabled = false;
    return _this;
  }

  LegendView.prototype.init = function () {
    this.group.add(this._contentGroup = new Group$1());
    this.group.add(this._selectorGroup = new Group$1());
    this._isFirstRender = true;
  };
  /**
   * @protected
   */


  LegendView.prototype.getContentGroup = function () {
    return this._contentGroup;
  };
  /**
   * @protected
   */


  LegendView.prototype.getSelectorGroup = function () {
    return this._selectorGroup;
  };
  /**
   * @override
   */


  LegendView.prototype.render = function (legendModel, ecModel, api) {
    var isFirstRender = this._isFirstRender;
    this._isFirstRender = false;
    this.resetInner();

    if (!legendModel.get('show', true)) {
      return;
    }

    var itemAlign = legendModel.get('align');
    var orient = legendModel.get('orient');

    if (!itemAlign || itemAlign === 'auto') {
      itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left';
    } // selector has been normalized to an array in model


    var selector = legendModel.get('selector', true);
    var selectorPosition = legendModel.get('selectorPosition', true);

    if (selector && (!selectorPosition || selectorPosition === 'auto')) {
      selectorPosition = orient === 'horizontal' ? 'end' : 'start';
    }

    this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); // Perform layout.

    var positionInfo = legendModel.getBoxLayoutParams();
    var viewportSize = {
      width: api.getWidth(),
      height: api.getHeight()
    };
    var padding = legendModel.get('padding');
    var maxSize = getLayoutRect(positionInfo, viewportSize, padding);
    var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition); // Place mainGroup, based on the calculated `mainRect`.

    var layoutRect = getLayoutRect(defaults({
      width: mainRect.width,
      height: mainRect.height
    }, positionInfo), viewportSize, padding);
    this.group.x = layoutRect.x - mainRect.x;
    this.group.y = layoutRect.y - mainRect.y;
    this.group.markRedraw(); // Render background after group is layout.

    this.group.add(this._backgroundEl = makeBackground(mainRect, legendModel));
  };

  LegendView.prototype.resetInner = function () {
    this.getContentGroup().removeAll();
    this._backgroundEl && this.group.remove(this._backgroundEl);
    this.getSelectorGroup().removeAll();
  };

  LegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
    var contentGroup = this.getContentGroup();
    var legendDrawnMap = createHashMap();
    var selectMode = legendModel.get('selectedMode');
    var excludeSeriesId = [];
    ecModel.eachRawSeries(function (seriesModel) {
      !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id);
    });
    each(legendModel.getData(), function (legendItemModel, dataIndex) {
      var name = legendItemModel.get('name'); // Use empty string or \n as a newline string

      if (!this.newlineDisabled && (name === '' || name === '\n')) {
        var g = new Group$1(); // @ts-ignore

        g.newline = true;
        contentGroup.add(g);
        return;
      } // Representitive series.


      var seriesModel = ecModel.getSeriesByName(name)[0];

      if (legendDrawnMap.get(name)) {
        // Have been drawn
        return;
      } // Legend to control series.


      if (seriesModel) {
        var data = seriesModel.getData();
        var lineVisualStyle = data.getVisual('legendLineStyle') || {};
        var legendIcon = data.getVisual('legendIcon');
        /**
         * `data.getVisual('style')` may be the color from the register
         * in series. For example, for line series,
         */

        var style = data.getVisual('style');

        var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, style, legendIcon, selectMode, api);

        itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
        legendDrawnMap.set(name, true);
      } else {
        // Legend to control data. In pie and funnel.
        ecModel.eachRawSeries(function (seriesModel) {
          // In case multiple series has same data name
          if (legendDrawnMap.get(name)) {
            return;
          }

          if (seriesModel.legendVisualProvider) {
            var provider = seriesModel.legendVisualProvider;

            if (!provider.containName(name)) {
              return;
            }

            var idx = provider.indexOfName(name);
            var style = provider.getItemVisual(idx, 'style');
            var legendIcon = provider.getItemVisual(idx, 'legendIcon');
            var colorArr = parse(style.fill); // Color may be set to transparent in visualMap when data is out of range.
            // Do not show nothing.

            if (colorArr && colorArr[3] === 0) {
              colorArr[3] = 0.2; // TODO color is set to 0, 0, 0, 0. Should show correct RGBA

              style = extend(extend({}, style), {
                fill: stringify(colorArr, 'rgba')
              });
            }

            var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, {}, style, legendIcon, selectMode, api); // FIXME: consider different series has items with the same name.


            itemGroup.on('click', curry(dispatchSelectAction, null, name, api, excludeSeriesId)) // Should not specify the series name, consider legend controls
            // more than one pie series.
            .on('mouseover', curry(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, null, name, api, excludeSeriesId));
            legendDrawnMap.set(name, true);
          }
        }, this);
      }
    }, this);

    if (selector) {
      this._createSelector(selector, legendModel, api, orient, selectorPosition);
    }
  };

  LegendView.prototype._createSelector = function (selector, legendModel, api, orient, selectorPosition) {
    var selectorGroup = this.getSelectorGroup();
    each(selector, function createSelectorButton(selectorItem) {
      var type = selectorItem.type;
      var labelText = new ZRText$1({
        style: {
          x: 0,
          y: 0,
          align: 'center',
          verticalAlign: 'middle'
        },
        onclick: function () {
          api.dispatchAction({
            type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect'
          });
        }
      });
      selectorGroup.add(labelText);
      var labelModel = legendModel.getModel('selectorLabel');
      var emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']);
      setLabelStyle(labelText, {
        normal: labelModel,
        emphasis: emphasisLabelModel
      }, {
        defaultText: selectorItem.title
      });
      enableHoverEmphasis(labelText);
    });
  };

  LegendView.prototype._createItem = function (seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, itemVisualStyle, legendIcon, selectMode, api) {
    var drawType = seriesModel.visualDrawType;
    var itemWidth = legendModel.get('itemWidth');
    var itemHeight = legendModel.get('itemHeight');
    var isSelected = legendModel.isSelected(name);
    var iconRotate = legendItemModel.get('symbolRotate');
    var symbolKeepAspect = legendItemModel.get('symbolKeepAspect');
    var legendIconType = legendItemModel.get('icon');
    legendIcon = legendIconType || legendIcon || 'roundRect';
    var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected, api);
    var itemGroup = new Group$1();
    var textStyleModel = legendItemModel.getModel('textStyle');

    if (isFunction(seriesModel.getLegendIcon) && (!legendIconType || legendIconType === 'inherit')) {
      // Series has specific way to define legend icon
      itemGroup.add(seriesModel.getLegendIcon({
        itemWidth: itemWidth,
        itemHeight: itemHeight,
        icon: legendIcon,
        iconRotate: iconRotate,
        itemStyle: style.itemStyle,
        lineStyle: style.lineStyle,
        symbolKeepAspect: symbolKeepAspect
      }));
    } else {
      // Use default legend icon policy for most series
      var rotate = legendIconType === 'inherit' && seriesModel.getData().getVisual('symbol') ? iconRotate === 'inherit' ? seriesModel.getData().getVisual('symbolRotate') : iconRotate : 0; // No rotation for no icon

      itemGroup.add(getDefaultLegendIcon({
        itemWidth: itemWidth,
        itemHeight: itemHeight,
        icon: legendIcon,
        iconRotate: rotate,
        itemStyle: style.itemStyle,
        lineStyle: style.lineStyle,
        symbolKeepAspect: symbolKeepAspect
      }));
    }

    var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
    var textAlign = itemAlign;
    var formatter = legendModel.get('formatter');
    var content = name;

    if (isString(formatter) && formatter) {
      content = formatter.replace('{name}', name != null ? name : '');
    } else if (isFunction(formatter)) {
      content = formatter(name);
    }

    var textColor = isSelected ? textStyleModel.getTextColor() : legendItemModel.get('inactiveColor');
    itemGroup.add(new ZRText$1({
      style: createTextStyle(textStyleModel, {
        text: content,
        x: textX,
        y: itemHeight / 2,
        fill: textColor,
        align: textAlign,
        verticalAlign: 'middle'
      }, {
        inheritColor: textColor
      })
    })); // Add a invisible rect to increase the area of mouse hover

    var hitRect = new Rect$1({
      shape: itemGroup.getBoundingRect(),
      invisible: true
    });
    var tooltipModel = legendItemModel.getModel('tooltip');

    if (tooltipModel.get('show')) {
      setTooltipConfig({
        el: hitRect,
        componentModel: legendModel,
        itemName: name,
        itemTooltipOption: tooltipModel.option
      });
    }

    itemGroup.add(hitRect);
    itemGroup.eachChild(function (child) {
      child.silent = true;
    });
    hitRect.silent = !selectMode;
    this.getContentGroup().add(itemGroup);
    enableHoverEmphasis(itemGroup); // @ts-ignore

    itemGroup.__legendDataIndex = dataIndex;
    return itemGroup;
  };

  LegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
    var contentGroup = this.getContentGroup();
    var selectorGroup = this.getSelectorGroup(); // Place items in contentGroup.

    box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height);
    var contentRect = contentGroup.getBoundingRect();
    var contentPos = [-contentRect.x, -contentRect.y];
    selectorGroup.markRedraw();
    contentGroup.markRedraw();

    if (selector) {
      // Place buttons in selectorGroup
      box( // Buttons in selectorGroup always layout horizontally
      'horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
      var selectorRect = selectorGroup.getBoundingRect();
      var selectorPos = [-selectorRect.x, -selectorRect.y];
      var selectorButtonGap = legendModel.get('selectorButtonGap', true);
      var orientIdx = legendModel.getOrient().index;
      var wh = orientIdx === 0 ? 'width' : 'height';
      var hw = orientIdx === 0 ? 'height' : 'width';
      var yx = orientIdx === 0 ? 'y' : 'x';

      if (selectorPosition === 'end') {
        selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap;
      } else {
        contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap;
      } // Always align selector to content as 'middle'


      selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2;
      selectorGroup.x = selectorPos[0];
      selectorGroup.y = selectorPos[1];
      contentGroup.x = contentPos[0];
      contentGroup.y = contentPos[1];
      var mainRect = {
        x: 0,
        y: 0
      };
      mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh];
      mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]);
      mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]);
      return mainRect;
    } else {
      contentGroup.x = contentPos[0];
      contentGroup.y = contentPos[1];
      return this.group.getBoundingRect();
    }
  };
  /**
   * @protected
   */


  LegendView.prototype.remove = function () {
    this.getContentGroup().removeAll();
    this._isFirstRender = true;
  };

  LegendView.type = 'legend.plain';
  return LegendView;
}(ComponentView$1);

function getLegendStyle(iconType, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected, api) {
  /**
   * Use series style if is inherit;
   * elsewise, use legend style
   */
  function handleCommonProps(style, visualStyle) {
    // If lineStyle.width is 'auto', it is set to be 2 if series has border
    if (style.lineWidth === 'auto') {
      style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0;
    }

    each(style, function (propVal, propName) {
      style[propName] === 'inherit' && (style[propName] = visualStyle[propName]);
    });
  } // itemStyle


  var itemStyleModel = legendItemModel.getModel('itemStyle');
  var itemStyle = itemStyleModel.getItemStyle();
  var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke';
  var decalStyle = itemStyleModel.getShallow('decal');
  itemStyle.decal = !decalStyle || decalStyle === 'inherit' ? itemVisualStyle.decal : createOrUpdatePatternFromDecal(decalStyle, api);

  if (itemStyle.fill === 'inherit') {
    /**
     * Series with visualDrawType as 'stroke' should have
     * series stroke as legend fill
     */
    itemStyle.fill = itemVisualStyle[drawType];
  }

  if (itemStyle.stroke === 'inherit') {
    /**
     * icon type with "emptyXXX" should use fill color
     * in visual style
     */
    itemStyle.stroke = itemVisualStyle[iconBrushType];
  }

  if (itemStyle.opacity === 'inherit') {
    /**
     * Use lineStyle.opacity if drawType is stroke
     */
    itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
  }

  handleCommonProps(itemStyle, itemVisualStyle); // lineStyle

  var legendLineModel = legendItemModel.getModel('lineStyle');
  var lineStyle = legendLineModel.getLineStyle();
  handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color

  itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill);
  itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill);
  lineStyle.stroke === 'auto' && (lineStyle.stroke = itemVisualStyle.fill);

  if (!isSelected) {
    var borderWidth = legendItemModel.get('inactiveBorderWidth');
    /**
     * Since stroke is set to be inactiveBorderColor, it may occur that
     * there is no border in series but border in legend, so we need to
     * use border only when series has border if is set to be auto
     */

    var visualHasBorder = itemStyle[iconBrushType];
    itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth;
    itemStyle.fill = legendItemModel.get('inactiveColor');
    itemStyle.stroke = legendItemModel.get('inactiveBorderColor');
    lineStyle.stroke = legendLineModel.get('inactiveColor');
    lineStyle.lineWidth = legendLineModel.get('inactiveWidth');
  }

  return {
    itemStyle: itemStyle,
    lineStyle: lineStyle
  };
}

function getDefaultLegendIcon(opt) {
  var symboType = opt.icon || 'roundRect';
  var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
  icon.setStyle(opt.itemStyle);
  icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
  icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);

  if (symboType.indexOf('empty') > -1) {
    icon.style.stroke = icon.style.fill;
    icon.style.fill = '#fff';
    icon.style.lineWidth = 2;
  }

  return icon;
}

function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
  // downplay before unselect
  dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
  api.dispatchAction({
    type: 'legendToggleSelect',
    name: seriesName != null ? seriesName : dataName
  }); // highlight after select
  // TODO highlight immediately may cause animation loss.

  dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId);
}

function isUseHoverLayer(api) {
  var list = api.getZr().storage.getDisplayList();
  var emphasisState;
  var i = 0;
  var len = list.length;

  while (i < len && !(emphasisState = list[i].states.emphasis)) {
    i++;
  }

  return emphasisState && emphasisState.hoverLayer;
}

function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
  // If element hover will move to a hoverLayer.
  if (!isUseHoverLayer(api)) {
    api.dispatchAction({
      type: 'highlight',
      seriesName: seriesName,
      name: dataName,
      excludeSeriesId: excludeSeriesId
    });
  }
}

function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) {
  // If element hover will move to a hoverLayer.
  if (!isUseHoverLayer(api)) {
    api.dispatchAction({
      type: 'downplay',
      seriesName: seriesName,
      name: dataName,
      excludeSeriesId: excludeSeriesId
    });
  }
}

const LegendView$1 = LegendView;
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function legendFilter(ecModel) {
  var legendModels = ecModel.findComponents({
    mainType: 'legend'
  });

  if (legendModels && legendModels.length) {
    ecModel.filterSeries(function (series) {
      // If in any legend component the status is not selected.
      // Because in legend series is assumed selected when it is not in the legend data.
      for (var i = 0; i < legendModels.length; i++) {
        if (!legendModels[i].isSelected(series.name)) {
          return false;
        }
      }

      return true;
    });
  }
}
/* Injected with object hook! */

function legendSelectActionHandler(methodName, payload, ecModel) {
  var selectedMap = {};
  var isToggleSelect = methodName === 'toggleSelected';
  var isSelected; // Update all legend components

  ecModel.eachComponent('legend', function (legendModel) {
    if (isToggleSelect && isSelected != null) {
      // Force other legend has same selected status
      // Or the first is toggled to true and other are toggled to false
      // In the case one legend has some item unSelected in option. And if other legend
      // doesn't has the item, they will assume it is selected.
      legendModel[isSelected ? 'select' : 'unSelect'](payload.name);
    } else if (methodName === 'allSelect' || methodName === 'inverseSelect') {
      legendModel[methodName]();
    } else {
      legendModel[methodName](payload.name);
      isSelected = legendModel.isSelected(payload.name);
    }

    var legendData = legendModel.getData();
    each$4(legendData, function (model) {
      var name = model.get('name'); // Wrap element

      if (name === '\n' || name === '') {
        return;
      }

      var isItemSelected = legendModel.isSelected(name);

      if (selectedMap.hasOwnProperty(name)) {
        // Unselected if any legend is unselected
        selectedMap[name] = selectedMap[name] && isItemSelected;
      } else {
        selectedMap[name] = isItemSelected;
      }
    });
  }); // Return the event explicitly

  return methodName === 'allSelect' || methodName === 'inverseSelect' ? {
    selected: selectedMap
  } : {
    name: payload.name,
    selected: selectedMap
  };
}

function installLegendAction(registers) {
  /**
   * @event legendToggleSelect
   * @type {Object}
   * @property {string} type 'legendToggleSelect'
   * @property {string} [from]
   * @property {string} name Series name or data item name
   */
  registers.registerAction('legendToggleSelect', 'legendselectchanged', curry$1(legendSelectActionHandler, 'toggleSelected'));
  registers.registerAction('legendAllSelect', 'legendselectall', curry$1(legendSelectActionHandler, 'allSelect'));
  registers.registerAction('legendInverseSelect', 'legendinverseselect', curry$1(legendSelectActionHandler, 'inverseSelect'));
  /**
   * @event legendSelect
   * @type {Object}
   * @property {string} type 'legendSelect'
   * @property {string} name Series name or data item name
   */

  registers.registerAction('legendSelect', 'legendselected', curry$1(legendSelectActionHandler, 'select'));
  /**
   * @event legendUnSelect
   * @type {Object}
   * @property {string} type 'legendUnSelect'
   * @property {string} name Series name or data item name
   */

  registers.registerAction('legendUnSelect', 'legendunselected', curry$1(legendSelectActionHandler, 'unSelect'));
}
/* Injected with object hook! */

function install$2(registers) {
  registers.registerComponentModel(LegendModel$1);
  registers.registerComponentView(LegendView$1);
  registers.registerProcessor(registers.PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter);
  registers.registerSubTypeDefaulter('legend', function () {
    return 'plain';
  });
  installLegendAction(registers);
}
/* Injected with object hook! */

var ScrollableLegendModel =
/** @class */
function (_super) {
  __extends(ScrollableLegendModel, _super);

  function ScrollableLegendModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = ScrollableLegendModel.type;
    return _this;
  }
  /**
   * @param {number} scrollDataIndex
   */


  ScrollableLegendModel.prototype.setScrollDataIndex = function (scrollDataIndex) {
    this.option.scrollDataIndex = scrollDataIndex;
  };

  ScrollableLegendModel.prototype.init = function (option, parentModel, ecModel) {
    var inputPositionParams = getLayoutParams(option);

    _super.prototype.init.call(this, option, parentModel, ecModel);

    mergeAndNormalizeLayoutParams(this, option, inputPositionParams);
  };
  /**
   * @override
   */


  ScrollableLegendModel.prototype.mergeOption = function (option, ecModel) {
    _super.prototype.mergeOption.call(this, option, ecModel);

    mergeAndNormalizeLayoutParams(this, this.option, option);
  };

  ScrollableLegendModel.type = 'legend.scroll';
  ScrollableLegendModel.defaultOption = inheritDefaultOption(LegendModel$1.defaultOption, {
    scrollDataIndex: 0,
    pageButtonItemGap: 5,
    pageButtonGap: null,
    pageButtonPosition: 'end',
    pageFormatter: '{current}/{total}',
    pageIcons: {
      horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'],
      vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z']
    },
    pageIconColor: '#2f4554',
    pageIconInactiveColor: '#aaa',
    pageIconSize: 15,
    pageTextStyle: {
      color: '#333'
    },
    animationDurationUpdate: 800
  });
  return ScrollableLegendModel;
}(LegendModel$1);

function mergeAndNormalizeLayoutParams(legendModel, target, raw) {
  var orient = legendModel.getOrient();
  var ignoreSize = [1, 1];
  ignoreSize[orient.index] = 0;
  mergeLayoutParam(target, raw, {
    type: 'box',
    ignoreSize: !!ignoreSize
  });
}

const ScrollableLegendModel$1 = ScrollableLegendModel;
/* Injected with object hook! */

var Group = Group$3;
var WH = ['width', 'height'];
var XY = ['x', 'y'];

var ScrollableLegendView =
/** @class */
function (_super) {
  __extends(ScrollableLegendView, _super);

  function ScrollableLegendView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = ScrollableLegendView.type;
    _this.newlineDisabled = true;
    _this._currentIndex = 0;
    return _this;
  }

  ScrollableLegendView.prototype.init = function () {
    _super.prototype.init.call(this);

    this.group.add(this._containerGroup = new Group());

    this._containerGroup.add(this.getContentGroup());

    this.group.add(this._controllerGroup = new Group());
  };
  /**
   * @override
   */


  ScrollableLegendView.prototype.resetInner = function () {
    _super.prototype.resetInner.call(this);

    this._controllerGroup.removeAll();

    this._containerGroup.removeClipPath();

    this._containerGroup.__rectSize = null;
  };
  /**
   * @override
   */


  ScrollableLegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
    var self = this; // Render content items.

    _super.prototype.renderInner.call(this, itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition);

    var controllerGroup = this._controllerGroup; // FIXME: support be 'auto' adapt to size number text length,
    // e.g., '3/12345' should not overlap with the control arrow button.

    var pageIconSize = legendModel.get('pageIconSize', true);
    var pageIconSizeArr = isArray(pageIconSize) ? pageIconSize : [pageIconSize, pageIconSize];
    createPageButton('pagePrev', 0);
    var pageTextStyleModel = legendModel.getModel('pageTextStyle');
    controllerGroup.add(new ZRText$1({
      name: 'pageText',
      style: {
        // Placeholder to calculate a proper layout.
        text: 'xx/xx',
        fill: pageTextStyleModel.getTextColor(),
        font: pageTextStyleModel.getFont(),
        verticalAlign: 'middle',
        align: 'center'
      },
      silent: true
    }));
    createPageButton('pageNext', 1);

    function createPageButton(name, iconIdx) {
      var pageDataIndexName = name + 'DataIndex';
      var icon = createIcon(legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx], {
        // Buttons will be created in each render, so we do not need
        // to worry about avoiding using legendModel kept in scope.
        onclick: bind$1(self._pageGo, self, pageDataIndexName, legendModel, api)
      }, {
        x: -pageIconSizeArr[0] / 2,
        y: -pageIconSizeArr[1] / 2,
        width: pageIconSizeArr[0],
        height: pageIconSizeArr[1]
      });
      icon.name = name;
      controllerGroup.add(icon);
    }
  };
  /**
   * @override
   */


  ScrollableLegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
    var selectorGroup = this.getSelectorGroup();
    var orientIdx = legendModel.getOrient().index;
    var wh = WH[orientIdx];
    var xy = XY[orientIdx];
    var hw = WH[1 - orientIdx];
    var yx = XY[1 - orientIdx];
    selector && box( // Buttons in selectorGroup always layout horizontally
    'horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
    var selectorButtonGap = legendModel.get('selectorButtonGap', true);
    var selectorRect = selectorGroup.getBoundingRect();
    var selectorPos = [-selectorRect.x, -selectorRect.y];
    var processMaxSize = clone$2(maxSize);
    selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap);

    var mainRect = this._layoutContentAndController(legendModel, isFirstRender, processMaxSize, orientIdx, wh, hw, yx, xy);

    if (selector) {
      if (selectorPosition === 'end') {
        selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap;
      } else {
        var offset = selectorRect[wh] + selectorButtonGap;
        selectorPos[orientIdx] -= offset;
        mainRect[xy] -= offset;
      }

      mainRect[wh] += selectorRect[wh] + selectorButtonGap;
      selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2;
      mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]);
      mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]);
      selectorGroup.x = selectorPos[0];
      selectorGroup.y = selectorPos[1];
      selectorGroup.markRedraw();
    }

    return mainRect;
  };

  ScrollableLegendView.prototype._layoutContentAndController = function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx, xy) {
    var contentGroup = this.getContentGroup();
    var containerGroup = this._containerGroup;
    var controllerGroup = this._controllerGroup; // Place items in contentGroup.

    box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), !orientIdx ? null : maxSize.width, orientIdx ? null : maxSize.height);
    box( // Buttons in controller are layout always horizontally.
    'horizontal', controllerGroup, legendModel.get('pageButtonItemGap', true));
    var contentRect = contentGroup.getBoundingRect();
    var controllerRect = controllerGroup.getBoundingRect();
    var showController = this._showController = contentRect[wh] > maxSize[wh]; // In case that the inner elements of contentGroup layout do not based on [0, 0]

    var contentPos = [-contentRect.x, -contentRect.y]; // Remain contentPos when scroll animation perfroming.
    // If first rendering, `contentGroup.position` is [0, 0], which
    // does not make sense and may cause unexepcted animation if adopted.

    if (!isFirstRender) {
      contentPos[orientIdx] = contentGroup[xy];
    } // Layout container group based on 0.


    var containerPos = [0, 0];
    var controllerPos = [-controllerRect.x, -controllerRect.y];
    var pageButtonGap = retrieve2(legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true)); // Place containerGroup and controllerGroup and contentGroup.

    if (showController) {
      var pageButtonPosition = legendModel.get('pageButtonPosition', true); // controller is on the right / bottom.

      if (pageButtonPosition === 'end') {
        controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh];
      } // controller is on the left / top.
      else {
          containerPos[orientIdx] += controllerRect[wh] + pageButtonGap;
        }
    } // Always align controller to content as 'middle'.


    controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2;
    contentGroup.setPosition(contentPos);
    containerGroup.setPosition(containerPos);
    controllerGroup.setPosition(controllerPos); // Calculate `mainRect` and set `clipPath`.
    // mainRect should not be calculated by `this.group.getBoundingRect()`
    // for sake of the overflow.

    var mainRect = {
      x: 0,
      y: 0
    }; // Consider content may be overflow (should be clipped).

    mainRect[wh] = showController ? maxSize[wh] : contentRect[wh];
    mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]); // `containerRect[yx] + containerPos[1 - orientIdx]` is 0.

    mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]);
    containerGroup.__rectSize = maxSize[wh];

    if (showController) {
      var clipShape = {
        x: 0,
        y: 0
      };
      clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0);
      clipShape[hw] = mainRect[hw];
      containerGroup.setClipPath(new Rect$1({
        shape: clipShape
      })); // Consider content may be larger than container, container rect
      // can not be obtained from `containerGroup.getBoundingRect()`.

      containerGroup.__rectSize = clipShape[wh];
    } else {
      // Do not remove or ignore controller. Keep them set as placeholders.
      controllerGroup.eachChild(function (child) {
        child.attr({
          invisible: true,
          silent: true
        });
      });
    } // Content translate animation.


    var pageInfo = this._getPageInfo(legendModel);

    pageInfo.pageIndex != null && updateProps$1(contentGroup, {
      x: pageInfo.contentPosition[0],
      y: pageInfo.contentPosition[1]
    }, // When switch from "show controller" to "not show controller", view should be
    // updated immediately without animation, otherwise causes weird effect.
    showController ? legendModel : null);

    this._updatePageInfoView(legendModel, pageInfo);

    return mainRect;
  };

  ScrollableLegendView.prototype._pageGo = function (to, legendModel, api) {
    var scrollDataIndex = this._getPageInfo(legendModel)[to];

    scrollDataIndex != null && api.dispatchAction({
      type: 'legendScroll',
      scrollDataIndex: scrollDataIndex,
      legendId: legendModel.id
    });
  };

  ScrollableLegendView.prototype._updatePageInfoView = function (legendModel, pageInfo) {
    var controllerGroup = this._controllerGroup;
    each$4(['pagePrev', 'pageNext'], function (name) {
      var key = name + 'DataIndex';
      var canJump = pageInfo[key] != null;
      var icon = controllerGroup.childOfName(name);

      if (icon) {
        icon.setStyle('fill', canJump ? legendModel.get('pageIconColor', true) : legendModel.get('pageIconInactiveColor', true));
        icon.cursor = canJump ? 'pointer' : 'default';
      }
    });
    var pageText = controllerGroup.childOfName('pageText');
    var pageFormatter = legendModel.get('pageFormatter');
    var pageIndex = pageInfo.pageIndex;
    var current = pageIndex != null ? pageIndex + 1 : 0;
    var total = pageInfo.pageCount;
    pageText && pageFormatter && pageText.setStyle('text', isString(pageFormatter) ? pageFormatter.replace('{current}', current == null ? '' : current + '').replace('{total}', total == null ? '' : total + '') : pageFormatter({
      current: current,
      total: total
    }));
  };
  /**
   *  contentPosition: Array.<number>, null when data item not found.
   *  pageIndex: number, null when data item not found.
   *  pageCount: number, always be a number, can be 0.
   *  pagePrevDataIndex: number, null when no previous page.
   *  pageNextDataIndex: number, null when no next page.
   * }
   */


  ScrollableLegendView.prototype._getPageInfo = function (legendModel) {
    var scrollDataIndex = legendModel.get('scrollDataIndex', true);
    var contentGroup = this.getContentGroup();
    var containerRectSize = this._containerGroup.__rectSize;
    var orientIdx = legendModel.getOrient().index;
    var wh = WH[orientIdx];
    var xy = XY[orientIdx];

    var targetItemIndex = this._findTargetItemIndex(scrollDataIndex);

    var children = contentGroup.children();
    var targetItem = children[targetItemIndex];
    var itemCount = children.length;
    var pCount = !itemCount ? 0 : 1;
    var result = {
      contentPosition: [contentGroup.x, contentGroup.y],
      pageCount: pCount,
      pageIndex: pCount - 1,
      pagePrevDataIndex: null,
      pageNextDataIndex: null
    };

    if (!targetItem) {
      return result;
    }

    var targetItemInfo = getItemInfo(targetItem);
    result.contentPosition[orientIdx] = -targetItemInfo.s; // Strategy:
    // (1) Always align based on the left/top most item.
    // (2) It is user-friendly that the last item shown in the
    // current window is shown at the begining of next window.
    // Otherwise if half of the last item is cut by the window,
    // it will have no chance to display entirely.
    // (3) Consider that item size probably be different, we
    // have calculate pageIndex by size rather than item index,
    // and we can not get page index directly by division.
    // (4) The window is to narrow to contain more than
    // one item, we should make sure that the page can be fliped.

    for (var i = targetItemIndex + 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i <= itemCount; ++i) {
      currItemInfo = getItemInfo(children[i]);

      if ( // Half of the last item is out of the window.
      !currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize || // If the current item does not intersect with the window, the new page
      // can be started at the current item or the last item.
      currItemInfo && !intersect(currItemInfo, winStartItemInfo.s)) {
        if (winEndItemInfo.i > winStartItemInfo.i) {
          winStartItemInfo = winEndItemInfo;
        } else {
          // e.g., when page size is smaller than item size.
          winStartItemInfo = currItemInfo;
        }

        if (winStartItemInfo) {
          if (result.pageNextDataIndex == null) {
            result.pageNextDataIndex = winStartItemInfo.i;
          }

          ++result.pageCount;
        }
      }

      winEndItemInfo = currItemInfo;
    }

    for (var i = targetItemIndex - 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i >= -1; --i) {
      currItemInfo = getItemInfo(children[i]);

      if ( // If the the end item does not intersect with the window started
      // from the current item, a page can be settled.
      (!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s)) && // e.g., when page size is smaller than item size.
      winStartItemInfo.i < winEndItemInfo.i) {
        winEndItemInfo = winStartItemInfo;

        if (result.pagePrevDataIndex == null) {
          result.pagePrevDataIndex = winStartItemInfo.i;
        }

        ++result.pageCount;
        ++result.pageIndex;
      }

      winStartItemInfo = currItemInfo;
    }

    return result;

    function getItemInfo(el) {
      if (el) {
        var itemRect = el.getBoundingRect();
        var start = itemRect[xy] + el[xy];
        return {
          s: start,
          e: start + itemRect[wh],
          i: el.__legendDataIndex
        };
      }
    }

    function intersect(itemInfo, winStart) {
      return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize;
    }
  };

  ScrollableLegendView.prototype._findTargetItemIndex = function (targetDataIndex) {
    if (!this._showController) {
      return 0;
    }

    var index;
    var contentGroup = this.getContentGroup();
    var defaultIndex;
    contentGroup.eachChild(function (child, idx) {
      var legendDataIdx = child.__legendDataIndex; // FIXME
      // If the given targetDataIndex (from model) is illegal,
      // we use defaultIndex. But the index on the legend model and
      // action payload is still illegal. That case will not be
      // changed until some scenario requires.

      if (defaultIndex == null && legendDataIdx != null) {
        defaultIndex = idx;
      }

      if (legendDataIdx === targetDataIndex) {
        index = idx;
      }
    });
    return index != null ? index : defaultIndex;
  };

  ScrollableLegendView.type = 'legend.scroll';
  return ScrollableLegendView;
}(LegendView$1);

const ScrollableLegendView$1 = ScrollableLegendView;
/* Injected with object hook! */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
function installScrollableLegendAction(registers) {
  /**
   * @event legendScroll
   * @type {Object}
   * @property {string} type 'legendScroll'
   * @property {string} scrollDataIndex
   */
  registers.registerAction('legendScroll', 'legendscroll', function (payload, ecModel) {
    var scrollDataIndex = payload.scrollDataIndex;
    scrollDataIndex != null && ecModel.eachComponent({
      mainType: 'legend',
      subType: 'scroll',
      query: payload
    }, function (legendModel) {
      legendModel.setScrollDataIndex(scrollDataIndex);
    });
  });
}
/* Injected with object hook! */

function install$1(registers) {
  use(install$2);
  registers.registerComponentModel(ScrollableLegendModel$1);
  registers.registerComponentView(ScrollableLegendView$1);
  installScrollableLegendAction(registers);
}
/* Injected with object hook! */

function install(registers) {
  use(install$2);
  use(install$1);
}
/* Injected with object hook! */

var raf = null;
function requestAnimationFrame (callback) {
  if (!raf) {
    raf = (
      window.requestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      function (callback) {
        return setTimeout(callback, 16)
      }
    ).bind(window);
  }
  return raf(callback)
}

var caf = null;
function cancelAnimationFrame (id) {
  if (!caf) {
    caf = (
      window.cancelAnimationFrame ||
      window.webkitCancelAnimationFrame ||
      window.mozCancelAnimationFrame ||
      function (id) {
        clearTimeout(id);
      }
    ).bind(window);
  }

  caf(id);
}

function createStyles (styleText) {
  var style = document.createElement('style');

  if (style.styleSheet) {
    style.styleSheet.cssText = styleText;
  } else {
    style.appendChild(document.createTextNode(styleText));
  }
  (document.querySelector('head') || document.body).appendChild(style);
  return style
}

function createElement (tagName, props) {
  if ( props === void 0 ) props = {};

  var elem = document.createElement(tagName);
  Object.keys(props).forEach(function (key) {
    elem[key] = props[key];
  });
  return elem
}

function getComputedStyle$1 (elem, prop, pseudo) {
  // for older versions of Firefox, `getComputedStyle` required
  // the second argument and may return `null` for some elements
  // when `display: none`
  var computedStyle = window.getComputedStyle(elem, pseudo || null) || {
    display: 'none'
  };

  return computedStyle[prop]
}

function getRenderInfo (elem) {
  if (!document.documentElement.contains(elem)) {
    return {
      detached: true,
      rendered: false
    }
  }

  var current = elem;
  while (current !== document) {
    if (getComputedStyle$1(current, 'display') === 'none') {
      return {
        detached: false,
        rendered: false
      }
    }
    current = current.parentNode;
  }

  return {
    detached: false,
    rendered: true
  }
}

var css_248z = ".resize-triggers{visibility:hidden;opacity:0;pointer-events:none}.resize-contract-trigger,.resize-contract-trigger:before,.resize-expand-trigger,.resize-triggers{content:\"\";position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden}.resize-contract-trigger,.resize-expand-trigger{background:#eee;overflow:auto}.resize-contract-trigger:before{width:200%;height:200%}";

var total = 0;
var style = null;

function addListener (elem, callback) {
  if (!elem.__resize_mutation_handler__) {
    elem.__resize_mutation_handler__ = handleMutation.bind(elem);
  }

  var listeners = elem.__resize_listeners__;

  if (!listeners) {
    elem.__resize_listeners__ = [];
    if (window.ResizeObserver) {
      var offsetWidth = elem.offsetWidth;
      var offsetHeight = elem.offsetHeight;
      var ro = new ResizeObserver(function () {
        if (!elem.__resize_observer_triggered__) {
          elem.__resize_observer_triggered__ = true;
          if (elem.offsetWidth === offsetWidth && elem.offsetHeight === offsetHeight) {
            return
          }
        }
        runCallbacks(elem);
      });

      // initially display none won't trigger ResizeObserver callback
      var ref = getRenderInfo(elem);
      var detached = ref.detached;
      var rendered = ref.rendered;
      elem.__resize_observer_triggered__ = detached === false && rendered === false;
      elem.__resize_observer__ = ro;
      ro.observe(elem);
    } else if (elem.attachEvent && elem.addEventListener) {
      // targeting IE9/10
      elem.__resize_legacy_resize_handler__ = function handleLegacyResize () {
        runCallbacks(elem);
      };
      elem.attachEvent('onresize', elem.__resize_legacy_resize_handler__);
      document.addEventListener('DOMSubtreeModified', elem.__resize_mutation_handler__);
    } else {
      if (!total) {
        style = createStyles(css_248z);
      }
      initTriggers(elem);

      elem.__resize_rendered__ = getRenderInfo(elem).rendered;
      if (window.MutationObserver) {
        var mo = new MutationObserver(elem.__resize_mutation_handler__);
        mo.observe(document, {
          attributes: true,
          childList: true,
          characterData: true,
          subtree: true
        });
        elem.__resize_mutation_observer__ = mo;
      }
    }
  }

  elem.__resize_listeners__.push(callback);
  total++;
}

function removeListener (elem, callback) {
  var listeners = elem.__resize_listeners__;
  if (!listeners) {
    return
  }

  if (callback) {
    listeners.splice(listeners.indexOf(callback), 1);
  }

  // no listeners exist, or removing all listeners
  if (!listeners.length || !callback) {
    // targeting IE9/10
    if (elem.detachEvent && elem.removeEventListener) {
      elem.detachEvent('onresize', elem.__resize_legacy_resize_handler__);
      document.removeEventListener('DOMSubtreeModified', elem.__resize_mutation_handler__);
      return
    }

    if (elem.__resize_observer__) {
      elem.__resize_observer__.unobserve(elem);
      elem.__resize_observer__.disconnect();
      elem.__resize_observer__ = null;
    } else {
      if (elem.__resize_mutation_observer__) {
        elem.__resize_mutation_observer__.disconnect();
        elem.__resize_mutation_observer__ = null;
      }
      elem.removeEventListener('scroll', handleScroll);
      elem.removeChild(elem.__resize_triggers__.triggers);
      elem.__resize_triggers__ = null;
    }
    elem.__resize_listeners__ = null;
  }

  if (!--total && style) {
    style.parentNode.removeChild(style);
  }
}

function getUpdatedSize (elem) {
  var ref = elem.__resize_last__;
  var width = ref.width;
  var height = ref.height;
  var offsetWidth = elem.offsetWidth;
  var offsetHeight = elem.offsetHeight;
  if (offsetWidth !== width || offsetHeight !== height) {
    return {
      width: offsetWidth,
      height: offsetHeight
    }
  }
  return null
}

function handleMutation () {
  // `this` denotes the scrolling element
  var ref = getRenderInfo(this);
  var rendered = ref.rendered;
  var detached = ref.detached;
  if (rendered !== this.__resize_rendered__) {
    if (!detached && this.__resize_triggers__) {
      resetTriggers(this);
      this.addEventListener('scroll', handleScroll, true);
    }
    this.__resize_rendered__ = rendered;
    runCallbacks(this);
  }
}

function handleScroll () {
  var this$1$1 = this;

  // `this` denotes the scrolling element
  resetTriggers(this);
  if (this.__resize_raf__) {
    cancelAnimationFrame(this.__resize_raf__);
  }
  this.__resize_raf__ = requestAnimationFrame(function () {
    var updated = getUpdatedSize(this$1$1);
    if (updated) {
      this$1$1.__resize_last__ = updated;
      runCallbacks(this$1$1);
    }
  });
}

function runCallbacks (elem) {
  if (!elem || !elem.__resize_listeners__) {
    return
  }
  elem.__resize_listeners__.forEach(function (callback) {
    callback.call(elem, elem);
  });
}

function initTriggers (elem) {
  var position = getComputedStyle$1(elem, 'position');
  if (!position || position === 'static') {
    elem.style.position = 'relative';
  }

  elem.__resize_old_position__ = position;
  elem.__resize_last__ = {};

  var triggers = createElement('div', {
    className: 'resize-triggers'
  });
  var expand = createElement('div', {
    className: 'resize-expand-trigger'
  });
  var expandChild = createElement('div');
  var contract = createElement('div', {
    className: 'resize-contract-trigger'
  });
  expand.appendChild(expandChild);
  triggers.appendChild(expand);
  triggers.appendChild(contract);
  elem.appendChild(triggers);

  elem.__resize_triggers__ = {
    triggers: triggers,
    expand: expand,
    expandChild: expandChild,
    contract: contract
  };

  resetTriggers(elem);
  elem.addEventListener('scroll', handleScroll, true);

  elem.__resize_last__ = {
    width: elem.offsetWidth,
    height: elem.offsetHeight
  };
}

function resetTriggers (elem) {
  var ref = elem.__resize_triggers__;
  var expand = ref.expand;
  var expandChild = ref.expandChild;
  var contract = ref.contract;

  // batch read
  var csw = contract.scrollWidth;
  var csh = contract.scrollHeight;
  var eow = expand.offsetWidth;
  var eoh = expand.offsetHeight;
  var esw = expand.scrollWidth;
  var esh = expand.scrollHeight;

  // batch write
  contract.scrollLeft = csw;
  contract.scrollTop = csh;
  expandChild.style.width = eow + 1 + 'px';
  expandChild.style.height = eoh + 1 + 'px';
  expand.scrollLeft = esw;
  expand.scrollTop = esh;
}

/* Injected with object hook! */

var O=function(){return O=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},O.apply(this,arguments)};"function"==typeof SuppressedError&&SuppressedError;var b=["getWidth","getHeight","getDom","getOption","resize","dispatchAction","convertToPixel","convertFromPixel","containPixel","getDataURL","getConnectedDataURL","appendData","clear","isDisposed","dispose"];function y(e){return t=Object.create(null),b.forEach((function(n){t[n]=function(t){return function(){for(var n=[],r=0;r<arguments.length;r++)n[r]=arguments[r];if(!e.value)throw new Error("ECharts is not initialized yet.");return e.value[t].apply(e.value,n)}}(n);})),t;var t;}var E={autoresize:[Boolean,Object]},_=/^on[^a-z]/,x=function(e){return _.test(e)};function j(e,n){var r=unref(e);return r&&"object"==typeof r&&"value"in r?r.value||n:r||n}var A="ecLoadingOptions";var w={loading:Boolean,loadingOptions:Object},z=null,C="x-vue-echarts";var L=[],T=[];!function(e,t){if(e&&"undefined"!=typeof document){var n,r=!0===t.prepend?"prepend":"append",o=!0===t.singleTag,i="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(o){var a=L.indexOf(i);-1===a&&(a=L.push(i)-1,T[a]={}),n=T[a]&&T[a][r]?T[a][r]:T[a][r]=u();}else n=u();65279===e.charCodeAt(0)&&(e=e.substring(1)),n.styleSheet?n.styleSheet.cssText+=e:n.appendChild(document.createTextNode(e));}function u(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var n=Object.keys(t.attributes),o=0;o<n.length;o++)e.setAttribute(n[o],t.attributes[n[o]]);var a="prepend"===r?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}("x-vue-echarts{display:block;width:100%;height:100%;min-width:0}x-vue-echarts>div{width:100%;height:100%}\n",{});var S=function(){if(null!=z)return z;if("undefined"==typeof HTMLElement||"undefined"==typeof customElements)return z=!1;try{new Function("tag","class EChartsElement extends HTMLElement {\n  __dispose = null;\n\n  disconnectedCallback() {\n    if (this.__dispose) {\n      this.__dispose();\n      this.__dispose = null;\n    }\n  }\n}\n\nif (customElements.get(tag) == null) {\n  customElements.define(tag, EChartsElement);\n}\n")(C);}catch(e){return z=!1}return z=!0}();var D="ecTheme",U="ecInitOptions",k="ecUpdateOptions",B=defineComponent({name:"echarts",props:O(O({option:Object,theme:{type:[Object,String]},initOptions:Object,updateOptions:Object,group:String,manualUpdate:Boolean},E),w),emits:{},inheritAttrs:!1,setup:function(t,i){var a=i.attrs,p=shallowRef(),b=shallowRef(),E=shallowRef(),_=shallowRef(),w=inject(D,null),z=inject(U,null),C=inject(k,null),L=toRefs(t),T=L.autoresize,B=L.manualUpdate,P=L.loading,H=L.loadingOptions,M=computed((function(){return _.value||t.option||null})),R=computed((function(){return t.theme||j(w,{})})),F=computed((function(){return t.initOptions||j(z,{})})),N=computed((function(){return t.updateOptions||j(C,{})})),q=computed((function(){return function(e){var t={};for(var n in e)x(n)||(t[n]=e[n]);return t}(a)})),I=getCurrentInstance().proxy.$listeners;function W(e){if(b.value){var n=E.value=init(b.value,R.value,F.value);t.group&&(n.group=t.group);var r=I;r||(r={},Object.keys(a).filter((function(e){return 0===e.indexOf("on")&&e.length>2})).forEach((function(e){var t=e.charAt(2).toLowerCase()+e.slice(3);"Once"===t.substring(t.length-4)&&(t="~".concat(t.substring(0,t.length-4))),r[t]=a[e];}))),Object.keys(r).forEach((function(e){var t=r[e];if(t){var o=e.toLowerCase();"~"===o.charAt(0)&&(o=o.substring(1),t.__once__=!0);var i=n;if(0===o.indexOf("zr:")&&(i=n.getZr(),o=o.substring(3)),t.__once__){delete t.__once__;var a=t;t=function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];a.apply(void 0,e),i.off(o,t);};}i.on(o,t);}})),T.value?nextTick((function(){n&&!n.isDisposed()&&n.resize(),o();})):o();}function o(){var t=e||M.value;t&&n.setOption(t,N.value);}}function Z(){E.value&&(E.value.dispose(),E.value=void 0);}var $=null;watch(B,(function(n){"function"==typeof $&&($(),$=null),n||($=watch((function(){return t.option}),(function(e,t){e&&(E.value?E.value.setOption(e,O({notMerge:e!==t},N.value)):W());}),{deep:!0}));}),{immediate:!0}),watch([R,F],(function(){Z(),W();}),{deep:!0}),watchEffect((function(){t.group&&E.value&&(E.value.group=t.group);}));var G=y(E);return function(e,t,i){var a=inject(A,{}),u=computed((function(){return O(O({},j(a,{})),null==i?void 0:i.value)}));watchEffect((function(){var n=e.value;n&&(t.value?n.showLoading(u.value):n.hideLoading());}));}(E,P,H),function(t,n,r){var o=null;watch([r,t,n],(function(e,t,n){var r=e[0],i=e[1],a=e[2];if(r&&i&&a){var u=!0===a?{}:a,s=u.throttle,c=void 0===s?100:s,l=u.onResize,f=function(){i.resize(),null==l||l();};o=c?throttle(f,c):f,addListener(r,o);}n((function(){r&&o&&removeListener(r,o);}));}));}(E,T,b),onMounted((function(){W();})),onBeforeUnmount((function(){S&&p.value?p.value.__dispose=Z:Z();})),O({chart:E,root:p,inner:b,setOption:function(e,n){t.manualUpdate&&(_.value=e),E.value?E.value.setOption(e,n||{}):W(e);},nonEventAttrs:q},G)},render:function(){var e=O({},this.nonEventAttrs);return e.ref="root",e.class=e.class?["echarts"].concat(e.class):"echarts",h(C,e,[h("div",{ref:"inner"})])}});

/* Injected with object hook! */

const _hoisted_1$4 = { class: "h-full w-[calc(100vw-100px)] translate-x-0 transform overflow-auto border-none shadow-lg transition-transform duration-300 bg-main" };
const _hoisted_2$3 = { p4: "" };
const _hoisted_3$2 = {
  key: 0,
  flex: "~",
  "h-40": "",
  "w-full": ""
};
const _hoisted_4$2 = /* @__PURE__ */ createBaseVNode("div", {
  ma: "",
  italic: "",
  op50: ""
}, " No middleware metric data ", -1);
const _hoisted_5$2 = [
  _hoisted_4$2
];
const _hoisted_6$2 = {
  key: 1,
  class: "my-auto ml-8 text-sm font-mono"
};
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
  __name: "ServerChart",
  async setup(__props) {
    let __temp, __restore;
    use([
      install$9,
      install$8,
      install$3,
      install$4,
      install,
      install$5
    ]);
    const data = ref(([__temp, __restore] = withAsyncContext(() => rpc.getServerMetrics()), __temp = await __temp, __restore(), __temp));
    function getMiddlewareTotalTime(m) {
      return m[m.length - 1].total;
    }
    const middlewareYData = computed(() => {
      return Object.keys(data.value.middleware || {}).sort((a, b) => getMiddlewareTotalTime(data.value.middleware[a]) - getMiddlewareTotalTime(data.value.middleware[b])).slice(-50);
    });
    const middewareSeries = computed(() => {
      return Array.from(middlewareYData.value.reduce((acc, m) => {
        data.value.middleware[m].forEach(({ name }) => acc.add(name));
        return acc;
      }, /* @__PURE__ */ new Set())).sort((a, b) => a.localeCompare(b)).map((m) => ({
        name: m,
        stack: "time",
        type: "bar",
        barWidth: 12,
        data: middlewareYData.value.map((url) => {
          const middleware = data.value.middleware[url].find(({ name }) => name === m);
          return middleware ? middleware.self : 0;
        })
      }));
    });
    const foregroundColor = computed(() => isDark.value ? "#fff" : "#111");
    const backgroundColor = computed(() => isDark.value ? "#111" : "#fff");
    const borderColor = computed(() => "#8888");
    const baseOption = computed(() => ({
      tooltip: {
        trigger: "axis",
        axisPointer: {
          type: "shadow"
        },
        borderColor: borderColor.value,
        backgroundColor: backgroundColor.value,
        textStyle: {
          color: foregroundColor.value
        }
      },
      legend: {
        top: 10,
        textStyle: {
          color: foregroundColor.value
        }
      },
      grid: {
        left: "4%",
        right: "2%",
        top: 60,
        bottom: "2%",
        containLabel: true
      },
      xAxis: {
        type: "value",
        minInterval: 10,
        splitLine: {
          lineStyle: {
            color: borderColor.value
          }
        },
        axisLine: {
          lineStyle: {
            color: borderColor.value
          }
        }
      },
      yAxis: {
        type: "category",
        axisTick: { show: false },
        axisLine: {
          show: false,
          lineStyle: {
            opacity: 0.5,
            color: borderColor.value
          }
        },
        axisLabel: {
          color: foregroundColor.value,
          fontSize: 12,
          formatter(value) {
            return value.split("/").slice(-3).join("/");
          }
        }
      }
    }));
    const middlewareOption = computed(() => {
      const tooltip = {
        ...baseOption.value.tooltip,
        formatter(params) {
          return [params[0].name, ...params.map(({ marker, seriesName, value }) => `${marker}${seriesName} (${value}ms)`)].join("<br/>");
        }
      };
      const yAxis = { ...baseOption.value.yAxis, data: middlewareYData.value };
      return {
        ...baseOption.value,
        yAxis,
        tooltip,
        series: middewareSeries.value
      };
    });
    const middlewareStyle = computed(() => {
      return {
        height: `${Math.max(middlewareYData.value.length * 28, 200)}px`
      };
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$4, [
        createBaseVNode("div", _hoisted_2$3, [
          !unref(middlewareYData).length ? (openBlock(), createElementBlock("div", _hoisted_3$2, _hoisted_5$2)) : createCommentVNode("", true),
          unref(middlewareYData).length ? (openBlock(), createElementBlock("div", _hoisted_6$2, " Metrics for top50 urls ")) : createCommentVNode("", true),
          unref(middlewareYData).length ? (openBlock(), createBlock(unref(B), {
            key: 2,
            class: "h-200 w-100%",
            style: normalizeStyle$1(unref(middlewareStyle)),
            option: unref(middlewareOption),
            autoresize: ""
          }, null, 8, ["style", "option"])) : createCommentVNode("", true)
        ])
      ]);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$3 = { class: "h-full w-[calc(100vw-100px)] translate-x-0 transform overflow-auto border-none shadow-lg transition-transform duration-300 bg-main" };
const _hoisted_2$2 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-chevron-left": "" }, null, -1);
const _hoisted_3$1 = [
  _hoisted_2$2
];
const _hoisted_4$1 = { class: "my-auto text-sm font-mono" };
const _hoisted_5$1 = /* @__PURE__ */ createBaseVNode("div", null, null, -1);
const _hoisted_6$1 = { p4: "" };
const _hoisted_7$1 = {
  key: 0,
  flex: "~",
  "h-40": "",
  "w-full": ""
};
const _hoisted_8$1 = /* @__PURE__ */ createBaseVNode("div", {
  ma: "",
  italic: "",
  op50: ""
}, " No data for this plugin ", -1);
const _hoisted_9$1 = [
  _hoisted_8$1
];
const _sfc_main$4 = /* @__PURE__ */ defineComponent({
  __name: "PluginChart",
  props: {
    plugin: {},
    hook: {},
    exit: { type: Function }
  },
  setup(__props) {
    const props = __props;
    use([
      install$9,
      install$8,
      install$3,
      install$4,
      install,
      install$5
    ]);
    const sortedSearchResults = computed(() => {
      return searchResults.value.filter(({ plugins }) => {
        const plugin = plugins.find(({ name, ...hooks }) => name === props.plugin && hooks[props.hook]);
        return plugin ? plugin[props.hook] : false;
      }).sort((next, cur) => {
        const nextTime = next.plugins.find(({ name }) => name === props.plugin)[props.hook];
        const curTime = cur.plugins.find(({ name }) => name === props.plugin)[props.hook];
        return nextTime - curTime;
      });
    });
    const yData = computed(() => {
      return sortedSearchResults.value.map(({ id }) => id);
    });
    const seriesData = computed(() => {
      return sortedSearchResults.value.map(({ plugins }) => {
        const hookTime = plugins.find(({ name, ...hooks }) => name === props.plugin && hooks[props.hook])[props.hook];
        return {
          itemStyle: { color: hookTime > 50 ? "rgba(255, 0, 0, 400)" : hookTime > 20 ? "#faee58" : "#91cc75" },
          value: hookTime
        };
      });
    });
    const foregroundColor = computed(() => isDark.value ? "#fff" : "#111");
    const backgroundColor = computed(() => isDark.value ? "#111" : "#fff");
    const borderColor = computed(() => "#8888");
    const option = computed(() => ({
      tooltip: {
        trigger: "axis",
        axisPointer: {
          type: "shadow"
        },
        borderColor: borderColor.value,
        backgroundColor: backgroundColor.value,
        textStyle: {
          color: foregroundColor.value
        },
        formatter(params) {
          const { name, seriesName, value, marker } = params[0];
          return `${name}<br />${marker}${seriesName} (${value}ms)`;
        }
      },
      grid: {
        left: "1%",
        right: "2%",
        top: "3%",
        bottom: "2%",
        containLabel: true
      },
      xAxis: {
        type: "value",
        minInterval: 10,
        splitLine: {
          lineStyle: {
            color: borderColor.value
          }
        },
        axisLine: {
          lineStyle: {
            color: borderColor.value
          }
        }
      },
      yAxis: {
        type: "category",
        axisTick: { show: false },
        axisLine: {
          show: false,
          lineStyle: {
            opacity: 0.5,
            color: borderColor.value
          }
        },
        axisLabel: {
          color: foregroundColor.value,
          fontSize: 12,
          formatter(value) {
            return value.split("/").slice(-3).join("/");
          }
        },
        data: yData.value
      },
      series: [
        {
          name: props.plugin,
          type: "bar",
          barWidth: 12,
          colorBy: "data",
          data: seriesData.value
        }
      ]
    }));
    const chartStyle = computed(() => {
      return {
        height: `${Math.max(sortedSearchResults.value.length * 24, 200)}px`
      };
    });
    return (_ctx, _cache) => {
      const _component_NavBar = _sfc_main$c;
      return openBlock(), createElementBlock("div", _hoisted_1$3, [
        createVNode(_component_NavBar, null, {
          actions: withCtx(() => [
            _hoisted_5$1
          ]),
          default: withCtx(() => [
            createBaseVNode("a", {
              class: "my-auto icon-btn !outline-none",
              onClick: _cache[0] || (_cache[0] = ($event) => props.exit())
            }, _hoisted_3$1),
            createBaseVNode("div", _hoisted_4$1, " Metrics for " + toDisplayString(props.plugin), 1)
          ]),
          _: 1
        }),
        createBaseVNode("div", _hoisted_6$1, [
          !unref(yData).length ? (openBlock(), createElementBlock("div", _hoisted_7$1, _hoisted_9$1)) : createCommentVNode("", true),
          createVNode(unref(B), {
            class: "w-100%",
            style: normalizeStyle$1(unref(chartStyle)),
            option: unref(option),
            autoresize: ""
          }, null, 8, ["style", "option"])
        ])
      ]);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$2 = { class: "flex overflow-hidden border border-main rounded divide-x divide-gray-400 divide-opacity-30" };
const _hoisted_2$1 = ["aria-pressed", "onClick"];
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
  __name: "SegmentControl",
  props: {
    options: {},
    modelValue: {}
  },
  emits: ["update:modelValue"],
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$2, [
        (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.options, (option) => {
          return openBlock(), createElementBlock("button", {
            key: option.value,
            class: normalizeClass(["px-2 py-1 text-sm font-mono", { "bg-active": option.value === _ctx.modelValue }]),
            "aria-pressed": option.value === _ctx.modelValue,
            onClick: ($event) => _ctx.$emit("update:modelValue", option.value)
          }, toDisplayString(option.label), 11, _hoisted_2$1);
        }), 128))
      ]);
    };
  }
});

/* Injected with object hook! */

const _hoisted_1$1 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-arrow-left": "" }, null, -1);
const _hoisted_2 = /* @__PURE__ */ createBaseVNode("div", {
  "my-auto": "",
  "text-sm": "",
  "font-mono": ""
}, " Metrics ", -1);
const _hoisted_3 = /* @__PURE__ */ createBaseVNode("div", { "flex-auto": "" }, null, -1);
const _hoisted_4 = {
  key: 2,
  class: "grid grid-cols-[1fr_max-content_max-content_max-content_max-content_max-content_1fr] mb-4 mt-2 whitespace-nowrap children:border-main children:border-b children:px-4 children:py-2 children:align-middle text-sm font-mono"
};
const _hoisted_5 = /* @__PURE__ */ createBaseVNode("div", null, null, -1);
const _hoisted_6 = { class: "text-xs font-bold" };
const _hoisted_7 = /* @__PURE__ */ createBaseVNode("div", { class: "text-center text-xs font-bold" }, " Type ", -1);
const _hoisted_8 = /* @__PURE__ */ createBaseVNode("div", { class: "text-right text-xs font-bold" }, " Passes ", -1);
const _hoisted_9 = /* @__PURE__ */ createBaseVNode("div", { class: "text-right text-xs font-bold" }, " Average Time ", -1);
const _hoisted_10 = /* @__PURE__ */ createBaseVNode("div", { class: "text-right text-xs font-bold" }, " Total Time ", -1);
const _hoisted_11 = /* @__PURE__ */ createBaseVNode("div", null, null, -1);
const _hoisted_12 = /* @__PURE__ */ createBaseVNode("div", null, null, -1);
const _hoisted_13 = ["onClick"];
const _hoisted_14 = { key: 1 };
const _hoisted_15 = { class: "flex items-center text-center p0!" };
const _hoisted_16 = { class: "text-right" };
const _hoisted_17 = /* @__PURE__ */ createBaseVNode("div", { class: "text-right text-gray:50" }, " - ", -1);
const _hoisted_18 = /* @__PURE__ */ createBaseVNode("div", { class: "text-right text-gray:50" }, " - ", -1);
const _hoisted_19 = /* @__PURE__ */ createBaseVNode("div", { class: "text-right text-gray:50" }, " - ", -1);
const _hoisted_20 = /* @__PURE__ */ createBaseVNode("div", null, null, -1);
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
  __name: "metric",
  async setup(__props) {
    let __temp, __restore;
    const data = ref(([__temp, __restore] = withAsyncContext(() => rpc.getPluginMetrics(inspectSSR.value)), __temp = await __temp, __restore(), __temp));
    const selectedPlugin = ref("");
    const displayHookOptions = ["transform", "resolveId", isStaticMode ? "" : "server"].filter(Boolean).map((h) => ({
      label: {
        transform: "plugin.transform",
        resolveId: "plugin.resolveId",
        server: "server.middleware"
      }[h],
      value: h
    }));
    const plugins = computed(() => {
      if (metricDisplayHook.value === "server")
        return [];
      return data.value.map((info) => {
        if (metricDisplayHook.value === "transform") {
          return {
            name: info.name,
            enforce: info.enforce,
            totalTime: info.transform.totalTime,
            invokeCount: info.transform.invokeCount
          };
        } else {
          return {
            name: info.name,
            enforce: info.enforce,
            totalTime: info.resolveId.totalTime,
            invokeCount: info.resolveId.invokeCount
          };
        }
      }).sort((a, b) => b.invokeCount - a.invokeCount).sort((a, b) => b.totalTime - a.totalTime);
    });
    async function refetch() {
      data.value = await rpc.getPluginMetrics(inspectSSR.value);
    }
    onRefetch.on(async () => {
      await refetch();
    });
    function selectPlugin(plugin) {
      selectedPlugin.value = plugin;
    }
    function clearPlugin() {
      selectedPlugin.value = "";
    }
    watch(metricDisplayHook, clearPlugin);
    getHot().then((hot) => {
      if (hot) {
        hot.on("vite-plugin-inspect:update", () => {
          refetch();
        });
      }
    });
    return (_ctx, _cache) => {
      const _component_RouterLink = resolveComponent("RouterLink");
      const _component_SegmentControl = _sfc_main$3;
      const _component_NavBar = _sfc_main$c;
      const _component_PluginChart = _sfc_main$4;
      const _component_ServerChart = _sfc_main$5;
      const _component_PluginName = _sfc_main$i;
      const _component_Badge = __unplugin_components_5;
      const _component_DurationDisplay = _sfc_main$j;
      const _component_Container = __unplugin_components_7;
      return openBlock(), createElementBlock(Fragment, null, [
        createVNode(_component_NavBar, null, {
          default: withCtx(() => [
            createVNode(_component_RouterLink, {
              class: "my-auto icon-btn !outline-none",
              to: "/"
            }, {
              default: withCtx(() => [
                _hoisted_1$1
              ]),
              _: 1
            }),
            _hoisted_2,
            createVNode(_component_SegmentControl, {
              modelValue: unref(metricDisplayHook),
              "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(metricDisplayHook) ? metricDisplayHook.value = $event : null),
              options: unref(displayHookOptions)
            }, null, 8, ["modelValue", "options"]),
            _hoisted_3
          ]),
          _: 1
        }),
        unref(data) ? (openBlock(), createBlock(_component_Container, {
          key: 0,
          "of-auto": ""
        }, {
          default: withCtx(() => [
            unref(selectedPlugin) && unref(metricDisplayHook) !== "server" ? (openBlock(), createBlock(_component_PluginChart, {
              key: 0,
              plugin: unref(selectedPlugin),
              hook: unref(metricDisplayHook),
              exit: clearPlugin
            }, null, 8, ["plugin", "hook"])) : createCommentVNode("", true),
            unref(metricDisplayHook) === "server" ? (openBlock(), createBlock(_component_ServerChart, { key: 1 })) : (openBlock(), createElementBlock("div", _hoisted_4, [
              _hoisted_5,
              createBaseVNode("div", _hoisted_6, " Name (" + toDisplayString(unref(plugins).length) + ") ", 1),
              _hoisted_7,
              _hoisted_8,
              _hoisted_9,
              _hoisted_10,
              _hoisted_11,
              (openBlock(true), createElementBlock(Fragment, null, renderList(unref(plugins), ({ name, totalTime, invokeCount, enforce }) => {
                return openBlock(), createElementBlock(Fragment, { key: name }, [
                  _hoisted_12,
                  totalTime > 0 ? (openBlock(), createElementBlock("div", {
                    key: 0,
                    class: "cursor-pointer text-lime-600 dark:text-lime-200 hover:underline",
                    onClick: ($event) => selectPlugin(name)
                  }, [
                    createVNode(_component_PluginName, { name }, null, 8, ["name"])
                  ], 8, _hoisted_13)) : (openBlock(), createElementBlock("div", _hoisted_14, [
                    createVNode(_component_PluginName, { name }, null, 8, ["name"])
                  ])),
                  createBaseVNode("div", _hoisted_15, [
                    enforce ? (openBlock(), createBlock(_component_Badge, {
                      key: 0,
                      class: normalizeClass(["m-auto text-xs", [enforce === "post" ? "bg-purple5/10 text-purple5" : "bg-green5/10 text-green5"]])
                    }, {
                      default: withCtx(() => [
                        createTextVNode(toDisplayString(enforce), 1)
                      ]),
                      _: 2
                    }, 1032, ["class"])) : createCommentVNode("", true)
                  ]),
                  invokeCount ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
                    createBaseVNode("div", _hoisted_16, toDisplayString(invokeCount), 1),
                    createVNode(_component_DurationDisplay, {
                      class: "text-right",
                      duration: totalTime / invokeCount
                    }, null, 8, ["duration"]),
                    createVNode(_component_DurationDisplay, {
                      class: "text-right",
                      duration: totalTime
                    }, null, 8, ["duration"])
                  ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
                    _hoisted_17,
                    _hoisted_18,
                    _hoisted_19
                  ], 64)),
                  _hoisted_20
                ], 64);
              }), 128))
            ]))
          ]),
          _: 1
        })) : createCommentVNode("", true)
      ], 64);
    };
  }
});

/* Injected with object hook! */

/* unplugin-vue-components disabled */const _sfc_main$1 = {};

function _sfc_render(_ctx, _cache) {
  return (openBlock(), createElementBlock("div", null, " Not Found "))
}
const __pages_import_3__ = /*#__PURE__*/_export_sfc(_sfc_main$1, [['render',_sfc_render]]);
/* Injected with object hook! */

const routes = [{"name":"index","path":"/","component":_sfc_main$a,"children":[{"name":"index-module","path":"module","component":_sfc_main$6,"props":true},{"name":"index-metric","path":"metric","component":_sfc_main$2,"props":true},{"name":"index-all","path":":all(.*)","component":__pages_import_3__,"props":true}],"props":true}];
/* Injected with object hook! */

const _hoisted_1 = {
  grid: "~ rows-[min-content_1fr]",
  size: "h-screen w-screen",
  text: "gray-700 dark:gray-200"
};
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "App",
  setup(__props) {
    onMounted(() => {
      if (isStaticMode)
        document.title = "Vite Inspect (Production)";
    });
    return (_ctx, _cache) => {
      const _component_RouterView = resolveComponent("RouterView");
      return openBlock(), createElementBlock("main", _hoisted_1, [
        (openBlock(), createBlock(Suspense, null, {
          fallback: withCtx(() => [
            createTextVNode(" Loading... ")
          ]),
          default: withCtx(() => [
            createVNode(_component_RouterView)
          ]),
          _: 1
        }))
      ]);
    };
  }
});

/* Injected with object hook! */

const tailwind = '';
/* Injected with object hook! */

const main = '';
/* Injected with object hook! */

const cm = '';
/* Injected with object hook! */

const __uno = '';
/* Injected with object hook! */

const app = createApp(_sfc_main);
const router = createRouter({
  history: createWebHashHistory(),
  routes
});
app.use(router);
app.mount("#app");

/* Injected with object hook! */

/* Injected with object hook! */
