import { eS as common, eT as charts, P as PropTypes } from './index.esm2.js';
import { jsxs, jsx } from 'react/jsx-runtime';
import { Component } from 'react';
import * as d3$1 from 'd3';
import '@qubejs/core';
import 'react-dom';
import 'react-html-parser';
import 'react-router-dom';

var prefix = "$";

function Map() {}

Map.prototype = map.prototype = {
  constructor: Map,
  has: function(key) {
    return (prefix + key) in this;
  },
  get: function(key) {
    return this[prefix + key];
  },
  set: function(key, value) {
    this[prefix + key] = value;
    return this;
  },
  remove: function(key) {
    var property = prefix + key;
    return property in this && delete this[property];
  },
  clear: function() {
    for (var property in this) if (property[0] === prefix) delete this[property];
  },
  keys: function() {
    var keys = [];
    for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
    return keys;
  },
  values: function() {
    var values = [];
    for (var property in this) if (property[0] === prefix) values.push(this[property]);
    return values;
  },
  entries: function() {
    var entries = [];
    for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
    return entries;
  },
  size: function() {
    var size = 0;
    for (var property in this) if (property[0] === prefix) ++size;
    return size;
  },
  empty: function() {
    for (var property in this) if (property[0] === prefix) return false;
    return true;
  },
  each: function(f) {
    for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
  }
};

function map(object, f) {
  var map = new Map;

  // Copy constructor.
  if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });

  // Index array by numeric index or specified key function.
  else if (Array.isArray(object)) {
    var i = -1,
        n = object.length,
        o;

    if (f == null) while (++i < n) map.set(i, object[i]);
    else while (++i < n) map.set(f(o = object[i], i, object), o);
  }

  // Convert object to map.
  else if (object) for (var key in object) map.set(key, object[key]);

  return map;
}

function Set() {}

var proto = map.prototype;

Set.prototype = {
  constructor: Set,
  has: proto.has,
  add: function(value) {
    value += "";
    this[prefix + value] = value;
    return this;
  },
  remove: proto.remove,
  clear: proto.clear,
  values: proto.keys,
  size: proto.size,
  empty: proto.empty,
  each: proto.each
};

var xhtml = "http://www.w3.org/1999/xhtml";

var namespaces = {
  svg: "http://www.w3.org/2000/svg",
  xhtml: xhtml,
  xlink: "http://www.w3.org/1999/xlink",
  xml: "http://www.w3.org/XML/1998/namespace",
  xmlns: "http://www.w3.org/2000/xmlns/"
};

function namespace(name) {
  var prefix = name += "", i = prefix.indexOf(":");
  if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
  return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
}

function creatorInherit(name) {
  return function() {
    var document = this.ownerDocument,
        uri = this.namespaceURI;
    return uri === xhtml && document.documentElement.namespaceURI === xhtml
        ? document.createElement(name)
        : document.createElementNS(uri, name);
  };
}

function creatorFixed(fullname) {
  return function() {
    return this.ownerDocument.createElementNS(fullname.space, fullname.local);
  };
}

function creator(name) {
  var fullname = namespace(name);
  return (fullname.local
      ? creatorFixed
      : creatorInherit)(fullname);
}

function none() {}

function selector(selector) {
  return selector == null ? none : function() {
    return this.querySelector(selector);
  };
}

function selection_select(select) {
  if (typeof select !== "function") select = selector(select);

  for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
      if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
        if ("__data__" in node) subnode.__data__ = node.__data__;
        subgroup[i] = subnode;
      }
    }
  }

  return new Selection(subgroups, this._parents);
}

function empty() {
  return [];
}

function selectorAll(selector) {
  return selector == null ? empty : function() {
    return this.querySelectorAll(selector);
  };
}

function selection_selectAll(select) {
  if (typeof select !== "function") select = selectorAll(select);

  for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
    for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
      if (node = group[i]) {
        subgroups.push(select.call(node, node.__data__, i, group));
        parents.push(node);
      }
    }
  }

  return new Selection(subgroups, parents);
}

function matcher(selector) {
  return function() {
    return this.matches(selector);
  };
}

function selection_filter(match) {
  if (typeof match !== "function") match = matcher(match);

  for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
    for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
      if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
        subgroup.push(node);
      }
    }
  }

  return new Selection(subgroups, this._parents);
}

function sparse(update) {
  return new Array(update.length);
}

function selection_enter() {
  return new Selection(this._enter || this._groups.map(sparse), this._parents);
}

function EnterNode(parent, datum) {
  this.ownerDocument = parent.ownerDocument;
  this.namespaceURI = parent.namespaceURI;
  this._next = null;
  this._parent = parent;
  this.__data__ = datum;
}

EnterNode.prototype = {
  constructor: EnterNode,
  appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
  insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
  querySelector: function(selector) { return this._parent.querySelector(selector); },
  querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
};

function constant(x) {
  return function() {
    return x;
  };
}

var keyPrefix = "$"; // Protect against keys like “__proto__”.

function bindIndex(parent, group, enter, update, exit, data) {
  var i = 0,
      node,
      groupLength = group.length,
      dataLength = data.length;

  // Put any non-null nodes that fit into update.
  // Put any null nodes into enter.
  // Put any remaining data into enter.
  for (; i < dataLength; ++i) {
    if (node = group[i]) {
      node.__data__ = data[i];
      update[i] = node;
    } else {
      enter[i] = new EnterNode(parent, data[i]);
    }
  }

  // Put any non-null nodes that don’t fit into exit.
  for (; i < groupLength; ++i) {
    if (node = group[i]) {
      exit[i] = node;
    }
  }
}

function bindKey(parent, group, enter, update, exit, data, key) {
  var i,
      node,
      nodeByKeyValue = {},
      groupLength = group.length,
      dataLength = data.length,
      keyValues = new Array(groupLength),
      keyValue;

  // Compute the key for each node.
  // If multiple nodes have the same key, the duplicates are added to exit.
  for (i = 0; i < groupLength; ++i) {
    if (node = group[i]) {
      keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
      if (keyValue in nodeByKeyValue) {
        exit[i] = node;
      } else {
        nodeByKeyValue[keyValue] = node;
      }
    }
  }

  // Compute the key for each datum.
  // If there a node associated with this key, join and add it to update.
  // If there is not (or the key is a duplicate), add it to enter.
  for (i = 0; i < dataLength; ++i) {
    keyValue = keyPrefix + key.call(parent, data[i], i, data);
    if (node = nodeByKeyValue[keyValue]) {
      update[i] = node;
      node.__data__ = data[i];
      nodeByKeyValue[keyValue] = null;
    } else {
      enter[i] = new EnterNode(parent, data[i]);
    }
  }

  // Add any remaining nodes that were not bound to data to exit.
  for (i = 0; i < groupLength; ++i) {
    if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
      exit[i] = node;
    }
  }
}

function selection_data(value, key) {
  if (!value) {
    data = new Array(this.size()), j = -1;
    this.each(function(d) { data[++j] = d; });
    return data;
  }

  var bind = key ? bindKey : bindIndex,
      parents = this._parents,
      groups = this._groups;

  if (typeof value !== "function") value = constant(value);

  for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
    var parent = parents[j],
        group = groups[j],
        groupLength = group.length,
        data = value.call(parent, parent && parent.__data__, j, parents),
        dataLength = data.length,
        enterGroup = enter[j] = new Array(dataLength),
        updateGroup = update[j] = new Array(dataLength),
        exitGroup = exit[j] = new Array(groupLength);

    bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);

    // Now connect the enter nodes to their following update node, such that
    // appendChild can insert the materialized enter node before this node,
    // rather than at the end of the parent node.
    for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
      if (previous = enterGroup[i0]) {
        if (i0 >= i1) i1 = i0 + 1;
        while (!(next = updateGroup[i1]) && ++i1 < dataLength);
        previous._next = next || null;
      }
    }
  }

  update = new Selection(update, parents);
  update._enter = enter;
  update._exit = exit;
  return update;
}

function selection_exit() {
  return new Selection(this._exit || this._groups.map(sparse), this._parents);
}

function selection_join(onenter, onupdate, onexit) {
  var enter = this.enter(), update = this, exit = this.exit();
  enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
  if (onupdate != null) update = onupdate(update);
  if (onexit == null) exit.remove(); else onexit(exit);
  return enter && update ? enter.merge(update).order() : update;
}

function selection_merge(selection) {

  for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
    for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
      if (node = group0[i] || group1[i]) {
        merge[i] = node;
      }
    }
  }

  for (; j < m0; ++j) {
    merges[j] = groups0[j];
  }

  return new Selection(merges, this._parents);
}

function selection_order() {

  for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
    for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
      if (node = group[i]) {
        if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
        next = node;
      }
    }
  }

  return this;
}

function selection_sort(compare) {
  if (!compare) compare = ascending;

  function compareNode(a, b) {
    return a && b ? compare(a.__data__, b.__data__) : !a - !b;
  }

  for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
    for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
      if (node = group[i]) {
        sortgroup[i] = node;
      }
    }
    sortgroup.sort(compareNode);
  }

  return new Selection(sortgroups, this._parents).order();
}

function ascending(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

function selection_call() {
  var callback = arguments[0];
  arguments[0] = this;
  callback.apply(null, arguments);
  return this;
}

function selection_nodes() {
  var nodes = new Array(this.size()), i = -1;
  this.each(function() { nodes[++i] = this; });
  return nodes;
}

function selection_node() {

  for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
    for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
      var node = group[i];
      if (node) return node;
    }
  }

  return null;
}

function selection_size() {
  var size = 0;
  this.each(function() { ++size; });
  return size;
}

function selection_empty() {
  return !this.node();
}

function selection_each(callback) {

  for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
    for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
      if (node = group[i]) callback.call(node, node.__data__, i, group);
    }
  }

  return this;
}

function attrRemove(name) {
  return function() {
    this.removeAttribute(name);
  };
}

function attrRemoveNS(fullname) {
  return function() {
    this.removeAttributeNS(fullname.space, fullname.local);
  };
}

function attrConstant(name, value) {
  return function() {
    this.setAttribute(name, value);
  };
}

function attrConstantNS(fullname, value) {
  return function() {
    this.setAttributeNS(fullname.space, fullname.local, value);
  };
}

function attrFunction(name, value) {
  return function() {
    var v = value.apply(this, arguments);
    if (v == null) this.removeAttribute(name);
    else this.setAttribute(name, v);
  };
}

function attrFunctionNS(fullname, value) {
  return function() {
    var v = value.apply(this, arguments);
    if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
    else this.setAttributeNS(fullname.space, fullname.local, v);
  };
}

function selection_attr(name, value) {
  var fullname = namespace(name);

  if (arguments.length < 2) {
    var node = this.node();
    return fullname.local
        ? node.getAttributeNS(fullname.space, fullname.local)
        : node.getAttribute(fullname);
  }

  return this.each((value == null
      ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
      ? (fullname.local ? attrFunctionNS : attrFunction)
      : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
}

function defaultView(node) {
  return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
      || (node.document && node) // node is a Window
      || node.defaultView; // node is a Document
}

function styleRemove(name) {
  return function() {
    this.style.removeProperty(name);
  };
}

function styleConstant(name, value, priority) {
  return function() {
    this.style.setProperty(name, value, priority);
  };
}

function styleFunction(name, value, priority) {
  return function() {
    var v = value.apply(this, arguments);
    if (v == null) this.style.removeProperty(name);
    else this.style.setProperty(name, v, priority);
  };
}

function selection_style(name, value, priority) {
  return arguments.length > 1
      ? this.each((value == null
            ? styleRemove : typeof value === "function"
            ? styleFunction
            : styleConstant)(name, value, priority == null ? "" : priority))
      : styleValue(this.node(), name);
}

function styleValue(node, name) {
  return node.style.getPropertyValue(name)
      || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
}

function propertyRemove(name) {
  return function() {
    delete this[name];
  };
}

function propertyConstant(name, value) {
  return function() {
    this[name] = value;
  };
}

function propertyFunction(name, value) {
  return function() {
    var v = value.apply(this, arguments);
    if (v == null) delete this[name];
    else this[name] = v;
  };
}

function selection_property(name, value) {
  return arguments.length > 1
      ? this.each((value == null
          ? propertyRemove : typeof value === "function"
          ? propertyFunction
          : propertyConstant)(name, value))
      : this.node()[name];
}

function classArray(string) {
  return string.trim().split(/^|\s+/);
}

function classList(node) {
  return node.classList || new ClassList(node);
}

function ClassList(node) {
  this._node = node;
  this._names = classArray(node.getAttribute("class") || "");
}

ClassList.prototype = {
  add: function(name) {
    var i = this._names.indexOf(name);
    if (i < 0) {
      this._names.push(name);
      this._node.setAttribute("class", this._names.join(" "));
    }
  },
  remove: function(name) {
    var i = this._names.indexOf(name);
    if (i >= 0) {
      this._names.splice(i, 1);
      this._node.setAttribute("class", this._names.join(" "));
    }
  },
  contains: function(name) {
    return this._names.indexOf(name) >= 0;
  }
};

function classedAdd(node, names) {
  var list = classList(node), i = -1, n = names.length;
  while (++i < n) list.add(names[i]);
}

function classedRemove(node, names) {
  var list = classList(node), i = -1, n = names.length;
  while (++i < n) list.remove(names[i]);
}

function classedTrue(names) {
  return function() {
    classedAdd(this, names);
  };
}

function classedFalse(names) {
  return function() {
    classedRemove(this, names);
  };
}

function classedFunction(names, value) {
  return function() {
    (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
  };
}

function selection_classed(name, value) {
  var names = classArray(name + "");

  if (arguments.length < 2) {
    var list = classList(this.node()), i = -1, n = names.length;
    while (++i < n) if (!list.contains(names[i])) return false;
    return true;
  }

  return this.each((typeof value === "function"
      ? classedFunction : value
      ? classedTrue
      : classedFalse)(names, value));
}

function textRemove() {
  this.textContent = "";
}

function textConstant(value) {
  return function() {
    this.textContent = value;
  };
}

function textFunction(value) {
  return function() {
    var v = value.apply(this, arguments);
    this.textContent = v == null ? "" : v;
  };
}

function selection_text(value) {
  return arguments.length
      ? this.each(value == null
          ? textRemove : (typeof value === "function"
          ? textFunction
          : textConstant)(value))
      : this.node().textContent;
}

function htmlRemove() {
  this.innerHTML = "";
}

function htmlConstant(value) {
  return function() {
    this.innerHTML = value;
  };
}

function htmlFunction(value) {
  return function() {
    var v = value.apply(this, arguments);
    this.innerHTML = v == null ? "" : v;
  };
}

function selection_html(value) {
  return arguments.length
      ? this.each(value == null
          ? htmlRemove : (typeof value === "function"
          ? htmlFunction
          : htmlConstant)(value))
      : this.node().innerHTML;
}

function raise() {
  if (this.nextSibling) this.parentNode.appendChild(this);
}

function selection_raise() {
  return this.each(raise);
}

function lower() {
  if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
}

function selection_lower() {
  return this.each(lower);
}

function selection_append(name) {
  var create = typeof name === "function" ? name : creator(name);
  return this.select(function() {
    return this.appendChild(create.apply(this, arguments));
  });
}

function constantNull() {
  return null;
}

function selection_insert(name, before) {
  var create = typeof name === "function" ? name : creator(name),
      select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
  return this.select(function() {
    return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
  });
}

function remove() {
  var parent = this.parentNode;
  if (parent) parent.removeChild(this);
}

function selection_remove() {
  return this.each(remove);
}

function selection_cloneShallow() {
  var clone = this.cloneNode(false), parent = this.parentNode;
  return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
}

function selection_cloneDeep() {
  var clone = this.cloneNode(true), parent = this.parentNode;
  return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
}

function selection_clone(deep) {
  return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
}

function selection_datum(value) {
  return arguments.length
      ? this.property("__data__", value)
      : this.node().__data__;
}

var filterEvents = {};

if (typeof document !== "undefined") {
  var element = document.documentElement;
  if (!("onmouseenter" in element)) {
    filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
  }
}

function filterContextListener(listener, index, group) {
  listener = contextListener(listener, index, group);
  return function(event) {
    var related = event.relatedTarget;
    if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
      listener.call(this, event);
    }
  };
}

function contextListener(listener, index, group) {
  return function(event1) {
    try {
      listener.call(this, this.__data__, index, group);
    } finally {
    }
  };
}

function parseTypenames(typenames) {
  return typenames.trim().split(/^|\s+/).map(function(t) {
    var name = "", i = t.indexOf(".");
    if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
    return {type: t, name: name};
  });
}

function onRemove(typename) {
  return function() {
    var on = this.__on;
    if (!on) return;
    for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
      if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
        this.removeEventListener(o.type, o.listener, o.capture);
      } else {
        on[++i] = o;
      }
    }
    if (++i) on.length = i;
    else delete this.__on;
  };
}

function onAdd(typename, value, capture) {
  var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
  return function(d, i, group) {
    var on = this.__on, o, listener = wrap(value, i, group);
    if (on) for (var j = 0, m = on.length; j < m; ++j) {
      if ((o = on[j]).type === typename.type && o.name === typename.name) {
        this.removeEventListener(o.type, o.listener, o.capture);
        this.addEventListener(o.type, o.listener = listener, o.capture = capture);
        o.value = value;
        return;
      }
    }
    this.addEventListener(typename.type, listener, capture);
    o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
    if (!on) this.__on = [o];
    else on.push(o);
  };
}

function selection_on(typename, value, capture) {
  var typenames = parseTypenames(typename + ""), i, n = typenames.length, t;

  if (arguments.length < 2) {
    var on = this.node().__on;
    if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
      for (i = 0, o = on[j]; i < n; ++i) {
        if ((t = typenames[i]).type === o.type && t.name === o.name) {
          return o.value;
        }
      }
    }
    return;
  }

  on = value ? onAdd : onRemove;
  if (capture == null) capture = false;
  for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
  return this;
}

function dispatchEvent(node, type, params) {
  var window = defaultView(node),
      event = window.CustomEvent;

  if (typeof event === "function") {
    event = new event(type, params);
  } else {
    event = window.document.createEvent("Event");
    if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
    else event.initEvent(type, false, false);
  }

  node.dispatchEvent(event);
}

function dispatchConstant(type, params) {
  return function() {
    return dispatchEvent(this, type, params);
  };
}

function dispatchFunction(type, params) {
  return function() {
    return dispatchEvent(this, type, params.apply(this, arguments));
  };
}

function selection_dispatch(type, params) {
  return this.each((typeof params === "function"
      ? dispatchFunction
      : dispatchConstant)(type, params));
}

var root = [null];

function Selection(groups, parents) {
  this._groups = groups;
  this._parents = parents;
}

function selection() {
  return new Selection([[document.documentElement]], root);
}

Selection.prototype = selection.prototype = {
  constructor: Selection,
  select: selection_select,
  selectAll: selection_selectAll,
  filter: selection_filter,
  data: selection_data,
  enter: selection_enter,
  exit: selection_exit,
  join: selection_join,
  merge: selection_merge,
  order: selection_order,
  sort: selection_sort,
  call: selection_call,
  nodes: selection_nodes,
  node: selection_node,
  size: selection_size,
  empty: selection_empty,
  each: selection_each,
  attr: selection_attr,
  style: selection_style,
  property: selection_property,
  classed: selection_classed,
  text: selection_text,
  html: selection_html,
  raise: selection_raise,
  lower: selection_lower,
  append: selection_append,
  insert: selection_insert,
  remove: selection_remove,
  clone: selection_clone,
  datum: selection_datum,
  on: selection_on,
  dispatch: selection_dispatch
};

function select(selector) {
  return typeof selector === "string"
      ? new Selection([[document.querySelector(selector)]], [document.documentElement])
      : new Selection([[selector]], root);
}

/**
 * d3.tip
 * Copyright (c) 2013-2017 Justin Palmer
 *
 * Tooltips for d3.js SVG visualizations
 */
// Public - constructs a new tooltip
//
// Returns a tip
function d3_tip() {
  var direction   = d3TipDirection,
      offset      = d3TipOffset,
      html        = d3TipHTML,
      rootElement = document.body,
      node        = initNode(),
      svg         = null,
      point       = null,
      target      = null;

  function tip(vis) {
    svg = getSVGNode(vis);
    if (!svg) return
    point = svg.createSVGPoint();
    rootElement.appendChild(node);
  }

  // Public - show the tooltip on the screen
  //
  // Returns a tip
  tip.show = function() {
    var args = Array.prototype.slice.call(arguments);
    if (args[args.length - 1] instanceof SVGElement) target = args.pop();

    var content = html.apply(this, args),
        poffset = offset.apply(this, args),
        dir     = direction.apply(this, args),
        nodel   = getNodeEl(),
        i       = directions.length,
        coords,
        scrollTop  = document.documentElement.scrollTop ||
      rootElement.scrollTop,
        scrollLeft = document.documentElement.scrollLeft ||
      rootElement.scrollLeft;

    nodel.html(content)
      .style('opacity', 1).style('pointer-events', 'all');

    while (i--) nodel.classed(directions[i], false);
    coords = directionCallbacks.get(dir).apply(this);
    nodel.classed(dir, true)
      .style('top', (coords.top + poffset[0]) + scrollTop + 'px')
      .style('left', (coords.left + poffset[1]) + scrollLeft + 'px');

    return tip
  };

  // Public - hide the tooltip
  //
  // Returns a tip
  tip.hide = function() {
    var nodel = getNodeEl();
    nodel.style('opacity', 0).style('pointer-events', 'none');
    return tip
  };

  // Public: Proxy attr calls to the d3 tip container.
  // Sets or gets attribute value.
  //
  // n - name of the attribute
  // v - value of the attribute
  //
  // Returns tip or attribute value
  // eslint-disable-next-line no-unused-vars
  tip.attr = function(n, v) {
    if (arguments.length < 2 && typeof n === 'string') {
      return getNodeEl().attr(n)
    }

    var args =  Array.prototype.slice.call(arguments);
    selection.prototype.attr.apply(getNodeEl(), args);
    return tip
  };

  // Public: Proxy style calls to the d3 tip container.
  // Sets or gets a style value.
  //
  // n - name of the property
  // v - value of the property
  //
  // Returns tip or style property value
  // eslint-disable-next-line no-unused-vars
  tip.style = function(n, v) {
    if (arguments.length < 2 && typeof n === 'string') {
      return getNodeEl().style(n)
    }

    var args = Array.prototype.slice.call(arguments);
    selection.prototype.style.apply(getNodeEl(), args);
    return tip
  };

  // Public: Set or get the direction of the tooltip
  //
  // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
  //     sw(southwest), ne(northeast) or se(southeast)
  //
  // Returns tip or direction
  tip.direction = function(v) {
    if (!arguments.length) return direction
    direction = v == null ? v : functor(v);

    return tip
  };

  // Public: Sets or gets the offset of the tip
  //
  // v - Array of [x, y] offset
  //
  // Returns offset or
  tip.offset = function(v) {
    if (!arguments.length) return offset
    offset = v == null ? v : functor(v);

    return tip
  };

  // Public: sets or gets the html value of the tooltip
  //
  // v - String value of the tip
  //
  // Returns html value or tip
  tip.html = function(v) {
    if (!arguments.length) return html
    html = v == null ? v : functor(v);

    return tip
  };

  // Public: sets or gets the root element anchor of the tooltip
  //
  // v - root element of the tooltip
  //
  // Returns root node of tip
  tip.rootElement = function(v) {
    if (!arguments.length) return rootElement
    rootElement = v == null ? v : functor(v);

    return tip
  };

  // Public: destroys the tooltip and removes it from the DOM
  //
  // Returns a tip
  tip.destroy = function() {
    if (node) {
      getNodeEl().remove();
      node = null;
    }
    return tip
  };

  function d3TipDirection() { return 'n' }
  function d3TipOffset() { return [0, 0] }
  function d3TipHTML() { return ' ' }

  var directionCallbacks = map({
        n:  directionNorth,
        s:  directionSouth,
        e:  directionEast,
        w:  directionWest,
        nw: directionNorthWest,
        ne: directionNorthEast,
        sw: directionSouthWest,
        se: directionSouthEast
      }),
      directions = directionCallbacks.keys();

  function directionNorth() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.n.y - node.offsetHeight,
      left: bbox.n.x - node.offsetWidth / 2
    }
  }

  function directionSouth() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.s.y,
      left: bbox.s.x - node.offsetWidth / 2
    }
  }

  function directionEast() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.e.y - node.offsetHeight / 2,
      left: bbox.e.x
    }
  }

  function directionWest() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.w.y - node.offsetHeight / 2,
      left: bbox.w.x - node.offsetWidth
    }
  }

  function directionNorthWest() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.nw.y - node.offsetHeight,
      left: bbox.nw.x - node.offsetWidth
    }
  }

  function directionNorthEast() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.ne.y - node.offsetHeight,
      left: bbox.ne.x
    }
  }

  function directionSouthWest() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.sw.y,
      left: bbox.sw.x - node.offsetWidth
    }
  }

  function directionSouthEast() {
    var bbox = getScreenBBox(this);
    return {
      top:  bbox.se.y,
      left: bbox.se.x
    }
  }

  function initNode() {
    var div = select(document.createElement('div'));
    div
      .style('position', 'absolute')
      .style('top', 0)
      .style('opacity', 0)
      .style('pointer-events', 'none')
      .style('box-sizing', 'border-box');

    return div.node()
  }

  function getSVGNode(element) {
    var svgNode = element.node();
    if (!svgNode) return null
    if (svgNode.tagName.toLowerCase() === 'svg') return svgNode
    return svgNode.ownerSVGElement
  }

  function getNodeEl() {
    if (node == null) {
      node = initNode();
      // re-add node to DOM
      rootElement.appendChild(node);
    }
    return select(node)
  }

  // Private - gets the screen coordinates of a shape
  //
  // Given a shape on the screen, will return an SVGPoint for the directions
  // n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
  // nw(northwest), sw(southwest).
  //
  //    +-+-+
  //    |   |
  //    +   +
  //    |   |
  //    +-+-+
  //
  // Returns an Object {n, s, e, w, nw, sw, ne, se}
  function getScreenBBox(targetShape) {
    var targetel   = target || targetShape;

    while (targetel.getScreenCTM == null && targetel.parentNode != null) {
      targetel = targetel.parentNode;
    }

    var bbox       = {},
        matrix     = targetel.getScreenCTM(),
        tbbox      = targetel.getBBox(),
        width      = tbbox.width,
        height     = tbbox.height,
        x          = tbbox.x,
        y          = tbbox.y;

    point.x = x;
    point.y = y;
    bbox.nw = point.matrixTransform(matrix);
    point.x += width;
    bbox.ne = point.matrixTransform(matrix);
    point.y += height;
    bbox.se = point.matrixTransform(matrix);
    point.x -= width;
    bbox.sw = point.matrixTransform(matrix);
    point.y -= height / 2;
    bbox.w = point.matrixTransform(matrix);
    point.x += width;
    bbox.e = point.matrixTransform(matrix);
    point.x -= width / 2;
    point.y -= height / 2;
    bbox.n = point.matrixTransform(matrix);
    point.y += height;
    bbox.s = point.matrixTransform(matrix);

    return bbox
  }

  // Private - replace D3JS 3.X d3.functor() function
  function functor(v) {
    return typeof v === 'function' ? v : function() {
      return v
    }
  }

  return tip
}

const colorsMap = {
  default: d3$1.schemeBlues.slice().pop().slice(1),
  expense: d3$1.schemeRdPu.slice().pop().slice(1),
  income: d3$1.schemeGreens.slice().pop().slice(1)
};
class Base {
  constructor(element, {
    d3 = d3$1,
    chart = {},
    chartType
  } = {}, defaults = {}) {
    this.chartType = chartType;
    this.config = Object.assign({
      minWidth: 320,
      minHeight: 200,
      width: 'auto',
      height: 300,
      xValue: 'x',
      yValue: 'y',
      margin: {
        top: 10,
        left: 10,
        right: 10,
        bottom: 10
      }
    }, defaults, chart);
    this.d3 = d3;
    this.d3.tip = d3_tip;
    this.element = element;
  }
  getColorSet(setName) {
    return colorsMap[setName] || colorsMap.default;
  }
  setConfig(config) {
    this.config = Object.assign(Object.assign({}, this.config), config);
  }
  init() {}
  update() {}
  draw() {}
  getValuesFromSeries(data) {
    const {
      series
    } = this.config;
    const allData = data.map(item => {
      return series.map(ser => {
        return item[ser.yValue] || 0;
      });
    });
    let allValues = [];
    if (allData.length > 0) {
      allValues = allData.reduce((a, b) => a.concat(b));
    }
    return allValues;
  }
  getWidth() {
    const element = this.element;
    let {
      width
    } = this.config;
    const {
      height,
      minWidth,
      maxWidth,
      margin
    } = this.config;
    if (width === 'auto') {
      width = element.offsetWidth >= minWidth ? element.offsetWidth : minWidth;
    } else if (element.offsetWidth < width) {
      width = element.offsetWidth;
    }
    const innerWidth = width - margin.left - margin.right;
    const innerHeight = height - margin.top - margin.bottom;
    return {
      width,
      height,
      minWidth,
      maxWidth,
      innerWidth,
      innerHeight,
      margin
    };
  }
  dispose() {
    this.element.innerHTML = '';
  }
}

class ColumnChart extends Base {
  constructor(el, options = {}) {
    super(el, {
      chart: options,
      chartType: 'ColumnChart'
    }, {
      margin: {
        top: 20,
        bottom: 90,
        left: 60,
        right: 20
      }
    });
  }
  getConfig() {}
  init() {}
  resetWidth() {
    const d3 = this.d3;
    d3.select(this.element).select('svg').attr('width', 'auto');
  }
  refresh() {
    this.update();
  }
  update() {
    const d3 = this.d3;
    const element = this.element;
    const {
      colorSet,
      xAxis = {},
      yAxis,
      tooltip = {},
      legend = {}
    } = this.config;
    const {
      labelWidth: legendLabelWidth = 80,
      enable: legendEnabled = true
    } = legend;
    const {
      format,
      ticks = 5
    } = yAxis || {};
    const {
      labelWidth = 44
    } = xAxis;
    const {
      formatter: formatTooltip = d => d[xValue]
    } = tooltip;
    const colorSetDefault = this.getColorSet(colorSet);
    const {
      xValue,
      series = []
    } = this.config;
    const columnSeries = series.filter(t => !t.type || t.type === 'Column');
    const lineSeries = series.filter(t => t.type === 'Line');
    d3.select(element).select('svg').attr('width', 'auto');
    const {
      width,
      height,
      innerWidth,
      innerHeight
    } = this.getWidth();
    d3.select(element).select('svg').attr('width', width).attr('height', height);
    if (!this.data) {
      return;
    }
    const data = this.data;
    const allValues = this.getValuesFromSeries(this.data);
    const x = d3.scaleBand().range([0, innerWidth]).domain(data.map(d => d[xValue])).paddingInner(0.2).paddingOuter(0.1);
    this.x = x;
    let minAll = d3.min(allValues, d => d);
    if (minAll > 0) {
      minAll = 0;
    }
    const y = d3.scaleLinear().domain([minAll * 1.005, (d3.max(allValues, d => d) || 100) * 1.005]).range([innerHeight, 0]);
    this.y = y;
    const g = this.gContainer;
    this.tooltip.html(formatTooltip);
    const xAxisCall = d3.axisBottom(x);
    this.xAxisGroup.call(xAxisCall).selectAll('text').attr('y', '10').attr('x', '-5').attr('text-achor', 'end').attr('transform', 'rotate(0)').style('display', function (d, i) {
      const num = data.length / (innerWidth / (labelWidth + 20));
      const everyItem = Math.ceil(num);
      return i % everyItem ? 'none' : 'initial';
    });
    const yAxisCall = d3.axisLeft(y).ticks(ticks).tickFormat(d => format ? format(d) : d);
    this.yAxisGroup.call(yAxisCall);
    let slice = this.columnArea.selectAll('.group').data(data, d => d[xValue]);
    slice.exit().remove();
    slice = slice.enter().append('g').merge(slice).attr('class', 'group').on('mouseover', this.tooltip.show).on('mouseout', this.tooltip.hide);
    const rects = slice.selectAll('rect').data(d => {
      return columnSeries.map((ser, idx) => {
        return {
          orig: ser,
          x: d[ser.xValue],
          y: d[ser.yValue],
          color: ser.color || colorSetDefault[idx]
        };
      });
    });
    function getX(d, idx) {
      return x(d.x) + x.bandwidth(d.x) / columnSeries.length * idx;
    }
    function getWidth(d) {
      return x.bandwidth(d.x) / columnSeries.length;
    }
    lineSeries.forEach(item => {
      const line = d3.line().x(d => {
        return x(d[item.xValue]) + x.bandwidth(d.x) / columnSeries.length;
      }).y(d => {
        return y(d[item.yValue]);
      });
      g.selectAll(`.${item.name}`).transition(d3.transition().duration(750)).attr('d', line(data));
    });
    rects.exit().remove();
    if (legendEnabled) {
      const legRects = this.legend.selectAll('rect').data(series);
      const totalSeries = series.length;
      legRects.enter().append('rect').merge(legRects).attr('x', function (d, i) {
        return innerWidth - (totalSeries - i) * legendLabelWidth;
      }).attr('y', function (d, i) {
        return height - 70;
      }).attr('width', 10).attr('height', 10).style('fill', function (d) {
        const color = d.color;
        return color;
      });
      const legTexts = this.legend.selectAll('text').data(series);
      legTexts.enter().append('text').merge(legTexts).attr('x', function (d, i) {
        return innerWidth - (totalSeries - i) * legendLabelWidth + 16;
      }).attr('y', function (d, i) {
        return height - 70;
      }).attr('alignment-baseline', 'hanging').text(function (d) {
        const text = d.label || d.name;
        return text;
      });
    }
    rects.enter().append('rect').attr('fill', d => d.color).attr('y', d => y(0)).attr('height', d => 0).attr('width', getWidth).merge(rects).attr('x', getX).transition(d3.transition().duration(750)).attr('width', getWidth).attr('y', d => y(d.y)).attr('height', d => y(0) - y(d.y));
  }
  mousemoveTooltip(e) {}
  draw() {
    const element = this.element;
    const d3 = this.d3;
    const {
      yValue,
      xValue,
      margin,
      yAxisLabel,
      xAxisLabel,
      series = []
    } = this.config;
    const lineSeries = series.filter(item => item.type === 'Line');
    const {
      width,
      height,
      innerWidth,
      innerHeight
    } = this.getWidth();
    const svg = d3.select(element).append('svg').attr('class', 'chart-svg').attr('width', width).attr('height', height);
    const g = svg.append('g').attr('transform', `translate(${margin.left}, ${margin.top})`);
    this.gContainer = g;
    this.xAxisGroup = g.append('g').attr('class', 'x axis').attr('transform', `translate(0, ${innerHeight})`);
    this.yAxisGroup = g.append('g').attr('class', 'y axis');
    this.columnArea = g.append('g').attr('class', 'column');
    this.lineArea = g.append('g').attr('class', 'line');
    lineSeries.forEach(item => {
      this.lineArea.append('path').attr('class', item.name).attr('fill', 'none').attr('stroke', item.color).attr('stroke-width', '3px');
    });
    this.legend = g.append('g').attr('class', 'sq-chart-legend');
    this.tooltip = d3.tip().attr('class', 'sq-chart-tooltip');
    g.call(this.tooltip);
    if (!this.data) {
      return;
    }
    this.update();
  }
  dispose() {
    this.tooltip && this.tooltip.destroy();
    this.element.innerHTML = '';
  }
}

window.d3 = d3$1;
// const d3 = window.d3;
class PieChart extends Base {
  constructor(el, options = {}) {
    super(el, {
      chart: options,
      chartType: 'PieChart'
    }, {});
  }
  getConfig() {}
  dispose() {
    this.element.innerHTML = '';
  }
  update() {
    if (!this.data) {
      return;
    }
    const data = this.data;
    var {
      xValue,
      yValue,
      colorSet,
      margin
    } = this.config;
    this.svg.attr('width', 'auto');
    const {
      width,
      height
    } = this.getWidth();
    this.svg.attr('width', width).attr('height', height);
    const pie = d3$1.pie().padAngle(0.005).sort(null).value(d => {
      return d[yValue];
    });
    const arcs = pie(data);
    this.totalSum = d3$1.sum(data, function (d) {
      return d[yValue];
    });
    const catKeys = data.map(d => d[xValue]);
    const color2 = d3$1.scaleOrdinal().domain(catKeys).range(this.getColorSet(colorSet));
    this.rootGroup.attr('transform', `translate(${margin.left}, ${margin.top})`).selectAll('path').data(arcs).join('path').attr('fill', d => color2(d.data[xValue])).on('mouseenter', this.onMouseEnter.bind(this)).on('mouseleave', this.onMouseLeave.bind(this))
    // .attr('d', this.arc)
    .transition().duration(500).attrTween('d', d => {
      var i = d3$1.interpolate(d.startAngle + 0.1, d.endAngle);
      return t => {
        d.endAngle = i(t);
        return this.arc(d);
      };
    });
  }
  draw() {
    const element = this.element;
    const d3 = this.d3;
    var {
      margin
    } = this.config;
    var {
      innerWidth,
      innerHeight
    } = this.getWidth();
    const radius = Math.min(innerWidth, innerHeight) / 2;
    this.arc = d3.arc().innerRadius(radius * 0.4).outerRadius(radius * 0.9);
    this.svg = d3.select(element).append('svg').attr('viewBox', [-innerWidth / 2, -innerHeight / 2, innerWidth, innerHeight]);
    this.textPie = this.svg.append('g').attr('class', 'percentage').attr('transform', `translate(${margin.left}, ${margin.top})`).append('text');
    this.textPie.attr('class', 'sq-chart__pie-text').attr('font-family', "'Work sans', sans-serif").attr('font-size', 24).attr('font-weight', 900).attr('text-anchor', 'middle').style('opacity', '0').text('0%');
    const g = this.svg.append('g');
    this.rootGroup = g;
    this.legendGroup = g.append('g').attr('class', 'sq-chart__legend').attr('transform', `translate(${innerWidth / 2 - 20}, ${50})`);
    this.tooltip = d3.create('div').attr('class', 'sq-chart-tooltip').html(`
    <div class="sq-chart-tooltip__data">
      
    </div>
  `);
    element.appendChild(this.tooltip.node());
    if (!this.data) {
      return;
    }
    this.update();
  }
  onMouseEnter(e, d) {
    const {
      tooltip: tooltipConfig = {},
      xValue,
      yValue,
      margin
    } = this.config;
    const {
      formatter
    } = tooltipConfig;
    var {
      innerWidth,
      innerHeight
    } = this.getWidth();
    const tooltip = this.tooltip;
    const x = this.arc.centroid(d)[0] + innerWidth / 2;
    const y = this.arc.centroid(d)[1] + innerHeight / 2;
    tooltip.style('opacity', 1);
    tooltip.style('transform', `translate(calc( -50% + ${x + margin.left}px), calc(-100% + ${y + margin.top}px))`);
    const data = formatter && formatter(e, d) || d.data[xValue];
    tooltip.select('.sq-chart-tooltip__data').html(data);
    this.textPie.text(d3$1.format('.0%')(d.data[yValue] / this.totalSum)).style('opacity', 1);
  }
  onMouseLeave() {
    const tooltip = this.tooltip;
    tooltip.style('opacity', 0);
    this.textPie.style('opacity', 0);
  }
}

class LineChart extends Base {
  constructor(el, options = {}) {
    super(el, {
      chart: options,
      chartType: 'LineChart'
    }, {
      margin: {
        top: 20,
        bottom: 90,
        left: 60,
        right: 20
      }
    });
  }
  getConfig() {}
  init() {}
  refresh() {
    this.update();
  }
  hideAllFocus() {
    this.config;
    this.focus.main.style('display', 'none');
    const tooltip = d3.select(this.element).select('.sq-chart-d-tooltip');
    tooltip.style('opacity', '0');
  }
  showAllFocus() {
    const {
      series
    } = this.config;
    this.focus.main.style('display', null);
    series.forEach(ser => {});
  }
  update() {
    const d3 = this.d3;
    const vis = this;
    this.element;
    var {
      xValue,
      margin,
      series = [],
      colorSet,
      yAxis = {},
      xAxis = {},
      tooltip = {},
      legendLabelWidth = 100
    } = this.config;
    const {
      type: xAxisDataType
    } = xAxis;
    const {
      format: yAxisFormatter
    } = yAxis;
    const {
      formatter: tooltipFormatter = v => v
    } = tooltip;
    var {
      width,
      height,
      innerWidth,
      innerHeight
    } = this.getWidth();
    vis.t = d3.transition().duration(1000);
    vis.x = d3.scaleUtc().range([0, innerWidth]);
    vis.y = d3.scaleLinear().range([innerHeight, 0]);
    vis.data = vis.data.map(item => {
      return Object.assign({}, item, {
        [xValue]: xAxisDataType === 'date' && !(item[xValue] instanceof Date) ? new Date(item[xValue]) : item[xValue]
      });
    });
    let allValues = this.getValuesFromSeries(vis.data);
    vis.x.domain(d3.extent(vis.data, d => d[xValue]));
    vis.y.domain([d3.min(allValues, d => d) / 1.005, d3.max(allValues, d => d) * 1.005]);
    vis.svg.attr('class', 'chart-svg').attr('width', width).attr('height', height);
    vis.g.attr('transform', `translate(${margin.left}, ${margin.top})`);
    vis.xAxis.attr('transform', `translate(0, ${innerHeight})`);
    // update axes
    vis.xAxisCall.scale(vis.x);
    vis.xAxis.transition(vis.t).call(vis.xAxisCall);
    vis.yAxisCall.scale(vis.y);
    vis.yAxis.transition(vis.t).call(vis.yAxisCall.tickFormat(yAxisFormatter));

    // clear old tooltips
    vis.g.select('.focus').remove();
    vis.g.select('.overlay').remove();

    /******************************** Tooltip Code ********************************/
    vis.focus = {};
    vis.focus.main = vis.g.append('g').attr('class', `focus`).style('display', 'none');
    vis.focus.main.append('line').attr('class', 'x-hover-line hover-line').attr('y1', 0).attr('y2', innerHeight);
    series.forEach(ser => {
      vis.focus[ser.name] = vis.focus.main.append('g').attr('class', `circle-data ${ser.name}`);
      vis.focus[ser.name].append('circle').attr('r', 7.5).attr('class', `sq-line-chart-circle`).style('stroke', ser.color);
      vis.focus[ser.name].append('text').attr('x', 15).attr('dy', '.31em').attr('class', `sq-line-chart-t-text`);
    });
    vis.g.append('rect').attr('class', 'sq-chart-overlay').attr('width', innerWidth).attr('height', innerHeight).on('mouseover', () => this.showAllFocus()).on('mouseout', () => this.hideAllFocus()).on('mousemove', mousemove);
    function mousemove(e) {
      const x0 = vis.x.invert(d3.pointer(e)[0]);
      const i = vis.bisectDate(vis.data, x0, 1);
      const d0 = vis.data[i > 0 ? i - 1 : 0];
      const d1 = vis.data[i >= vis.data.length ? vis.data.length - 1 : i];
      const d = x0 - d0[xValue] > d1[xValue] - x0 ? d1 : d0;
      vis.focus.main.attr('transform', `translate(${vis.x(d[xValue])},0 )`);
      vis.focus.main.select('.x-hover-line').attr('y2', innerHeight);
      const tooltip = d3.select(vis.element).select('.sq-chart-d-tooltip');
      tooltip.html(tooltipFormatter(e, d, series));
      tooltip.style('left', `${vis.x(d[xValue])}px`);
      tooltip.style('opacity', `1`);
      tooltip.style('top', `0px`);
      series.forEach(ser => {
        vis.focus[ser.name].select('circle').attr('cy', vis.y(d[ser.yValue]));
        vis.focus[ser.name].select('text').attr('y', vis.y(d[ser.yValue]));
        vis.focus[ser.name].select('text').html(tooltipFormatter(d[ser.yValue], d));
      });
    }

    /******************************** Legend Code ********************************/
    const legRects = this.legend.selectAll('rect').data(series);
    const totalSeries = series.length;
    legRects.enter().append('rect').merge(legRects).attr('x', function (d, i) {
      return innerWidth - (totalSeries - i) * legendLabelWidth;
    }).attr('y', function (d, i) {
      return height - 70;
    }).attr('width', 10).attr('height', 10).style('fill', function (d) {
      var color = d.color;
      return color;
    });
    const legTexts = this.legend.selectAll('text').data(series);
    legTexts.enter().append('text').merge(legTexts).attr('x', function (d, i) {
      return innerWidth - (totalSeries - i) * legendLabelWidth + 16;
    }).attr('y', function (d, i) {
      return height - 70;
    }).attr('alignment-baseline', 'hanging').text(function (d) {
      var text = d.label || d.name;
      return text;
    });
    /******************************** End Legend Code ********************************/

    // Path generator
    // Update our line path
    series.forEach(ser => {
      vis.line = d3.line()
      // .curve(d3.curveLinear)
      .x(d => {
        return !common.isNullOrUndefined(d[xValue]) ? vis.x(d[xValue]) : null;
      }).y(d => {
        return !common.isNullOrUndefined(d[ser.yValue]) ? vis.y(d[ser.yValue]) : null;
      });
      vis.g.select(`.line.${ser.name}`).attr('stroke', ser.color).attr('d', vis.line(vis.data));
    });
  }
  draw() {
    const vis = this;
    const element = this.element;
    const d3 = this.d3;
    var {
      xValue,
      margin,
      yAxisLabel,
      xAxisLabel,
      series = []
    } = this.config;
    this.getWidth();
    const svg = d3.select(element).append('svg');
    const g = svg.append('g');
    this.svg = svg;
    this.legend = g.append('g').attr('class', 'sq-chart-legend');
    vis.g = g;
    vis.parseTime = d3.timeParse('%d/%m/%Y');
    vis.formatTime = d3.timeFormat('%d/%m/%Y');
    // for tooltip
    vis.bisectDate = d3.bisector(d => d[xValue]).left;
    series.forEach(ser => {
      const {
        strokeWidth = '3px'
      } = ser;
      vis.g.append('path').attr('class', `line ${ser.name}`).attr('fill', 'none').attr('stroke', 'grey').attr('stroke-width', strokeWidth);
    });
    this.legend = g.append('g').attr('class', 'sq-chart-legend');
    this.tooltipEl = d3.select(element).append('div').attr('class', 'sq-chart-d-tooltip');
    // axis generators
    vis.xAxisCall = d3.axisBottom();
    vis.yAxisCall = d3.axisLeft().ticks(6);

    // axis groups
    vis.xAxis = vis.g.append('g').attr('class', 'x axis');
    vis.yAxis = vis.g.append('g').attr('class', 'y axis');
    if (!this.data) {
      return;
    }
    this.update();
  }
  dispose() {
    this.tooltip && this.tooltip.destroy();
    this.element.innerHTML = '';
  }
}

class AreaChart extends Base {
  constructor(el, options = {}) {
    super(el, {
      chart: options,
      chartType: 'AreaChart'
    }, {
      margin: {
        top: 20,
        bottom: 90,
        left: 60,
        right: 20
      }
    });
  }
  getConfig() {}
  init() {}
  refresh() {
    this.update();
  }
  hideAllFocus() {
    this.config;
    this.focus.main.style('display', 'none');
    const tooltip = d3$1.select(this.element).select('.sq-chart-d-tooltip');
    tooltip.style('opacity', '0');
  }
  showAllFocus() {
    const {
      series
    } = this.config;
    this.focus.main.style('display', null);
    series.forEach(ser => {});
  }
  resetWidth() {
    this.svg.attr('class', 'chart-svg').attr('width', 'auto');
  }
  update() {
    const d3 = this.d3;
    const vis = this;
    this.element;
    const {
      xValue,
      margin,
      series = [],
      colorSet,
      xAxis = {},
      yAxis = {},
      tooltip = {},
      legendLabelWidth = 100
    } = this.config;
    const {
      format: xAxisFormatter,
      type: xAxisDataType
    } = xAxis;
    const {
      labelWidth = 80,
      format: yAxisFormatter,
      minValue: yAxisMinValue
    } = yAxis;
    const {
      formatter: tooltipFormatter = v => v
    } = tooltip;
    vis.svg.attr('class', 'chart-svg').attr('width', 'auto');
    const {
      width,
      height,
      innerWidth,
      innerHeight
    } = this.getWidth();
    vis.t = d3.transition().duration(1000);
    vis.x = d3.scaleTime().range([0, innerWidth]);
    vis.y = d3.scaleLinear().range([innerHeight, 0]);
    vis.data = vis.data.map(item => {
      return Object.assign(Object.assign({}, item), {
        [xValue]: xAxisDataType === 'date' && !(item[xValue] instanceof Date) ? new Date(item[xValue]) : item[xValue]
      });
    });
    const allValues = this.getValuesFromSeries(vis.data);
    const scale = 1.005;
    let minValue = d3.min(allValues, d => d) * scale;
    const maxValue = d3.max(allValues, d => d) * scale;
    if (yAxisMinValue !== undefined && minValue > yAxisMinValue) {
      minValue = yAxisMinValue;
    }
    vis.x.domain(d3.extent(vis.data, d => d[xValue]));
    vis.y.domain([minValue, maxValue]);
    vis.svg.attr('class', 'chart-svg').attr('width', width).attr('height', height);
    vis.g.attr('transform', `translate(${margin.left}, ${margin.top})`);
    vis.xAxis.attr('transform', `translate(0, ${innerHeight})`);
    // update axes
    const xTicksCount = innerWidth / labelWidth;
    vis.xAxisCall.ticks(xTicksCount > vis.data.length ? vis.data.length + 1 : xTicksCount);
    vis.xAxisCall.scale(vis.x);
    vis.xAxis.transition(vis.t).call(vis.xAxisCall.tickFormat(xAxisFormatter));
    vis.yAxisCall.scale(vis.y);
    vis.yAxis.transition(vis.t).call(vis.yAxisCall.tickFormat(yAxisFormatter));
    // clear old tooltips
    vis.g.select('.focus').remove();
    vis.g.select('.overlay').remove();
    /******************************** Tooltip Code ********************************/
    vis.focus = {};
    vis.focus.main = vis.g.append('g').attr('class', `focus`).style('display', 'none');
    vis.focus.main.append('line').attr('class', 'x-hover-line hover-line').attr('y1', 0).attr('y2', innerHeight);
    // vis.focus.main.append('rect').attr('class', 'x-tooltip').attr('y1', 0).attr('y2', innerHeight)
    // vis.focus.main.select('rect').attr('fill', '#fff').append('text').texchart('Test');
    series.forEach(ser => {
      vis.focus[ser.name] = vis.focus.main.append('g').attr('class', `circle-data ${ser.name}`);
      vis.focus[ser.name].append('circle').attr('r', 5.5).attr('class', `sq-line-chart-circle`).style('stroke', ser.color);
      // vis.focus[ser.name].append('text').attr('x', 15).attr('dy', '.31em').attr('class', `sq-line-chart-t-text`);
    });

    vis.overlay.attr('width', innerWidth).attr('height', innerHeight).on('mouseover', () => this.showAllFocus()).on('mouseout', () => this.hideAllFocus()).on('mousemove', mousemove);
    function mousemove(e) {
      const x0 = vis.x.invert(d3.pointer(e)[0]);
      const bisectDate = d3.bisector(function (d, x) {
        return d[xValue] - x;
      }).left;
      const i = bisectDate(vis.data, x0);
      const d0 = vis.data[i > 0 ? i - 1 : 0];
      const d1 = vis.data[i >= vis.data.length ? vis.data.length - 1 : i];
      const d = x0 - d0[xValue] > d1[xValue] - x0 ? d1 : d0;
      vis.focus.main.attr('transform', `translate(${vis.x(d[xValue])},0 )`);
      vis.focus.main.select('.x-hover-line').attr('y2', innerHeight);
      const tooltip = d3.select(vis.element).select('.sq-chart-d-tooltip');
      tooltip.html(tooltipFormatter(e, d, series));
      tooltip.style('left', `${vis.x(d[xValue])}px`);
      tooltip.style('opacity', `1`);
      tooltip.style('top', `0px`);
      series.forEach(ser => {
        vis.focus[ser.name].select('circle').attr('cy', vis.y(d[ser.yValue] || 0)).style('stroke', d[ser.yValue] < 0 ? ser.negativeColor : ser.color);
        // vis.focus[ser.name].select('text').attr('y', vis.y(d[ser.yValue]));
        // vis.focus[ser.name].select('text').text(tooltipFormatter(d[ser.yValue]));
      });
    }
    /******************************** Legend Code ********************************/
    const legRects = this.legend.selectAll('rect').data(series);
    const totalSeries = series.length;
    legRects.enter().append('rect').merge(legRects).attr('x', function (d, i) {
      return innerWidth - (totalSeries - i) * legendLabelWidth;
    }).attr('y', function (d, i) {
      return height - 70;
    }).attr('width', 10).attr('height', 10).style('fill', function (d) {
      const color = d.color;
      return color;
    });
    const legTexts = this.legend.selectAll('text').data(series);
    legTexts.enter().append('text').merge(legTexts).attr('x', function (d, i) {
      return innerWidth - (totalSeries - i) * legendLabelWidth + 16;
    }).attr('y', function (d, i) {
      return height - 70;
    }).attr('alignment-baseline', 'hanging').text(function (d) {
      const text = d.label || d.name;
      return text;
    });
    /******************************** End Legend Code ********************************/
    const pos_height = vis.y(0);
    const neg_height = vis.y(minValue);
    vis.defs.select(`#clip_pos`).select('rect').attr('x', 0).attr('y', 0).attr('width', innerWidth).attr('height', pos_height > 0 ? pos_height : 0);
    vis.defs.select(`#clip_neg`).select('rect').attr('x', 0).attr('y', vis.y(maxValue > 0 ? 0 : maxValue)).attr('width', innerWidth).attr('height', neg_height > 0 ? neg_height : 0);
    // Path generator
    // Update our line path
    series.forEach(ser => {
      vis.line = d3.line()
      // .curve(d3.curveCardinal)
      .x(d => vis.x(d[xValue])).y(d => vis.y(d[ser.yValue] || 0));
      vis.area = d3.area()
      // .curve(d3.curveCardinal)
      .x(d => vis.x(d[xValue])).y0(d => vis.y(minValue > 0 ? minValue : 0)).y1(d => vis.y(d[ser.yValue] || 0));
      vis.g.select(`.area.p-${ser.name}`).attr('stroke', 'none').transition(vis.t).attr('d', vis.area(vis.data)).style('clip-path', 'url(#clip_pos)');
      vis.g.select(`.area.n-${ser.name}`).attr('stroke', 'none').transition(vis.t).attr('d', vis.area(vis.data)).style('clip-path', 'url(#clip_neg)');
      vis.g.select(`.line.${ser.name}`).attr('stroke', ser.color).transition(vis.t).attr('d', vis.line(vis.data)).style('clip-path', 'url(#clip_pos)');
      vis.g.select(`.line-n.${ser.name}`).attr('stroke', ser.negativeColor).transition(vis.t).attr('d', vis.line(vis.data)).style('clip-path', 'url(#clip_neg)');
    });
  }
  draw() {
    const vis = this;
    const element = this.element;
    const d3 = this.d3;
    const {
      xValue,
      margin,
      yAxisLabel,
      xAxisLabel,
      series = [],
      xAxis = {}
    } = this.config;
    const {
      width,
      height,
      innerWidth,
      innerHeight
    } = this.getWidth();
    const svg = d3.select(element).append('svg');
    const g = svg.append('g');
    this.svg = svg;
    this.tooltipEl = d3.select(element).append('div').attr('class', 'sq-chart-d-tooltip');
    this.legend = g.append('g').attr('class', 'sq-chart-legend');
    vis.g = g;
    vis.parseTime = d3.timeParse('%d/%m/%Y');
    vis.formatTime = d3.timeFormat('%d/%m/%Y');
    // for tooltip
    vis.bisectDate = d3.bisector(d => d[xValue]).left;
    vis.defs = svg.append('defs');
    series.forEach(ser => {
      const {
        strokeWidth = '3px'
      } = ser;
      vis.g.append('path').attr('class', `area n-${ser.name}`).attr('fill', `url(#gradN${ser.name})`).attr('stroke', 'grey').attr('stroke-width', strokeWidth);
      vis.g.append('path').attr('class', `area p-${ser.name}`).attr('fill', `url(#grad${ser.name})`).attr('stroke', 'grey').attr('stroke-width', strokeWidth);
      vis.g.append('path').attr('class', `line ${ser.name}`).attr('fill', 'none').attr('stroke', 'grey').attr('stroke-width', strokeWidth);
      vis.g.append('path').attr('class', `line-n ${ser.name}`).attr('fill', 'none').attr('stroke', 'grey').attr('stroke-width', strokeWidth);
      vis.lg = vis.defs.append('linearGradient').attr('id', `grad${ser.name}`).attr('x1', '0%').attr('x2', '0%').attr('y1', '0%').attr('y2', '100%');
      vis.lg.append('stop').attr('offset', '0%').style('stop-color', ser.color).style('stop-opacity', 0.4);
      vis.lg.append('stop').attr('offset', '100%').style('stop-color', 'white').style('stop-opacity', 0.4);
      vis.lgN = vis.defs.append('linearGradient').attr('id', `gradN${ser.name}`).attr('x1', '0%').attr('x2', '0%').attr('y1', '0%').attr('y2', '100%');
      vis.lgN.append('stop').attr('offset', '0%').style('stop-color', 'white').style('stop-opacity', 0.4);
      vis.lgN.append('stop').attr('offset', '100%').style('stop-color', ser.negativeColor).style('stop-opacity', 0.4);
    });
    vis.defs.append('clipPath').attr('id', `clip_pos`).append('rect').attr('x', 0).attr('y', 0).attr('width', innerWidth);
    vis.defs.append('clipPath').attr('id', `clip_neg`).append('rect').attr('x', 0).attr('y', 200).attr('width', innerWidth);
    this.legend = g.append('g').attr('class', 'sq-chart-legend');
    // axis generators
    vis.xAxisCall = d3.axisBottom();
    vis.yAxisCall = d3.axisLeft().ticks(6);
    vis.overlay = vis.g.append('rect').attr('class', 'sq-chart-overlay');
    // axis groups
    vis.xAxis = vis.g.append('g').attr('class', 'x axis');
    vis.yAxis = vis.g.append('g').attr('class', 'y axis');
    if (!this.data) {
      return;
    }
    this.update();
  }
  dispose() {
    this.tooltip && this.tooltip.destroy();
    this.element.innerHTML = '';
  }
}

const _chartMap = {
  d3: {
    Column: ColumnChart,
    Pie: PieChart,
    Line: LineChart,
    Area: AreaChart
  }
};
class ChartFactory {
  constructor({
    provider = 'd3'
  } = {}) {
    this.provider = provider;
  }
  get() {
    return _chartMap[this.provider];
  }
}

charts.set(new ChartFactory().get());
class CustomChart extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.resizeChart = this.resizeChart.bind(this);
  }
  componentWillUnmount() {
    this.chart && this.chart.dispose();
    window.removeEventListener('resize', this.resizeChart);
  }
  componentDidMount() {
    this.renderChart();
    window.addEventListener('resize', this.resizeChart);
  }
  resizeChart() {
    var _a, _b;
    if (this.resizing) {
      return;
    }
    ((_a = this.chart) === null || _a === void 0 ? void 0 : _a.resetWidth) && ((_b = this.chart) === null || _b === void 0 ? void 0 : _b.resetWidth());
    this.resizing = window.setTimeout(() => {
      this.chart && this.chart.update();
      this.resizing = undefined;
    }, 500);
  }
  renderChart() {
    const {
      data,
      chartConfig = {},
      type,
      colorsSet = 'default'
    } = this.props;
    const ChartTypesMap = charts.get();
    const ChartTypeRender = ChartTypesMap[type] || ChartTypesMap.Pie;
    this.chart = new ChartTypeRender(this.chartContainer, Object.assign(Object.assign({}, chartConfig), {
      colorsSet
    }));
    this.chart.data = data;
    this.chart.draw();
  }
  componentDidUpdate(prevProps) {
    if (this.props.data !== prevProps.data || this.props.type !== prevProps.type) {
      if (!this.chart) {
        this.renderChart();
      } else {
        const {
          data,
          chartConfig = {},
          colorsSet = 'default'
        } = this.props;
        this.chart.setConfig(Object.assign(Object.assign({}, chartConfig), {
          colorsSet
        }));
        this.chart.data = data;
        this.chart.update();
      }
    }
  }
  render() {
    const {
      className = '',
      data = [],
      noDataMessage = 'No data found'
    } = this.props;
    return jsxs("div", {
      className: `sq-chart ${className}`,
      children: [data.length === 0 && jsx("div", {
        className: "sq-chart--no-data",
        children: noDataMessage
      }), jsx("div", {
        ref: div => this.chartContainer = div
      })]
    });
  }
}
CustomChart.propTypes = {
  type: PropTypes.string,
  colorsSet: PropTypes.string,
  chartConfig: PropTypes.object,
  data: PropTypes.array
};

export { CustomChart as default };
