text: function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  
  function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
  
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
  
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
  
  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 } }); if (superClass) _setPrototypeOf(subClass, superClass); }
  
  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
  
  import { select } from "d3-selection";
  import { accessor, BaseClass, constant, prefix, stylize } from "d3plus-common";
  import Popper from "popper.js";
  /**
      @class Tooltip
      @extends BaseClass
      @desc Creates HTML tooltips in the body of a webpage.
  */
  
  var Tooltip =
  /*#__PURE__*/
  function (_BaseClass) {
    _inherits(Tooltip, _BaseClass);
  
    /**
        @memberof Tooltip
        @desc Invoked when creating a new class instance, and sets any default parameters.
        @private
    */
    function Tooltip() {
      var _this;
  
      _classCallCheck(this, Tooltip);
  
      _this = _possibleConstructorReturn(this, _getPrototypeOf(Tooltip).call(this));
      _this._arrow = accessor("arrow", "");
      _this._arrowStyle = {
        "content": "",
        "background": "inherit",
        "border": "inherit",
        "border-width": "0 1px 1px 0",
        "height": "10px",
        "position": "absolute",
        "transform": "rotate(45deg)",
        "width": "10px",
        "z-index": "-1"
      };
      _this._background = constant("rgba(255, 255, 255, 1)");
      _this._body = accessor("body", "");
      _this._bodyStyle = {
        "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
        "font-size": "12px",
        "font-weight": "400",
        "z-index": "1"
      };
      _this._border = constant("1px solid rgba(0, 0, 0, 0.1)");
      _this._borderRadius = constant("2px");
      _this._className = "d3plus-tooltip";
      _this._data = [];
      _this._footer = accessor("footer", "");
      _this._footerStyle = {
        "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
        "font-size": "12px",
        "font-weight": "400",
        "z-index": "1"
      };
      _this._height = constant("auto");
  
      _this._id = function (d, i) {
        return "".concat(i);
      };
  
      _this._offset = constant(5);
      _this._padding = constant("5px");
      _this._pointerEvents = constant("auto");
      _this._popperClasses = {};
  
      _this._position = function (d) {
        return [d.x, d.y];
      };
  
      _this._prefix = prefix();
      _this._tableStyle = {
        "border-collapse": "collapse",
        "border-spacing": "0",
        "width": "100%"
      };
      _this._tbody = [];
      _this._tbodyStyle = {
        "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
        "font-size": "12px",
        "text-align": "center"
      };
      _this._thead = [];
      _this._theadStyle = {
        "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
        "font-size": "12px",
        "font-weight": "600",
        "text-align": "center"
      };
      _this._title = accessor("title", "");
      _this._titleStyle = {
        "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
        "font-size": "14px",
        "font-weight": "600"
      };
      _this._trStyle = {
        "border-top": "1px solid rgba(0, 0, 0, 0.1)"
      };
      _this._width = constant("auto");
      return _this;
    }
    /**
        The inner return object and draw function that gets assigned the public methods.
        @private
    */
  
  
    _createClass(Tooltip, [{
      key: "render",
      value: function render(callback) {
        var _this2 = this;
  
        var that = this;
        var tooltips = select("body").selectAll(".".concat(this._className)).data(this._data, this._id);
        var enter = tooltips.enter().append("div").attr("class", this._className);
        var update = tooltips.merge(enter);
        /**
            Creates DIV elements with a unique class and styles.
            @private
        */
  
        function divElement(cat) {
          enter.append("div").attr("class", "d3plus-tooltip-".concat(cat)).attr("id", function (d, i) {
            return "d3plus-tooltip-".concat(cat, "-").concat(d ? that._id(d, i) : "");
          });
          var div = update.select(".d3plus-tooltip-".concat(cat)).html(function (d, i) {
            return that["_".concat(cat)](d, i);
          }).style("display", function (d, i) {
            var val = that["_".concat(cat)](d, i);
            var visible = val !== false && val !== undefined && val !== null;
            return visible ? "block" : "none";
          });
          stylize(div, that["_".concat(cat, "Style")]);
        }
        /**
            Fetches table contents given functions or values.
            @private
        */
  
  
        function cellContent(d) {
          if (typeof d === "function") {
            var datum = select(this.parentNode.parentNode).datum();
            return d(datum, that._data.indexOf(datum));
          } else return d;
        }
        /**
            Sets styles for both enter and update.
            @private
        */
  
  
        function boxStyles(box) {
          box.style("background", that._background).style("".concat(that._prefix, "border-radius"), that._borderRadius).style("pointer-events", that._pointerEvents).style("padding", that._padding).style("width", that._width).style("height", that._height).style("border", function (d, i) {
            var b = select(this).style("border");
            return b !== "0px none rgb(0, 0, 0)" ? b : that._border(d, i);
          });
        }
  
        divElement("title");
        divElement("body");
        var tableEnter = enter.append("table").attr("class", "d3plus-tooltip-table");
        var table = update.select(".d3plus-tooltip-table");
        stylize(table, this._tableStyle);
        tableEnter.append("thead").attr("class", "d3plus-tooltip-thead");
        var tableHead = update.select(".d3plus-tooltip-thead");
        stylize(tableHead, this._theadStyle);
        var th = tableHead.selectAll("th").data(this._thead);
        th.enter().append("th").merge(th).html(cellContent);
        th.exit().remove();
        tableEnter.append("tbody").attr("class", "d3plus-tooltip-tbody");
        var tableBody = update.select(".d3plus-tooltip-tbody");
        stylize(tableBody, this._tbodyStyle);
        var tr = tableBody.selectAll("tr").data(this._tbody);
        var trEnter = tr.enter().append("tr");
        tr.exit().remove();
        var trUpdate = tr.merge(trEnter);
        stylize(trUpdate, this._trStyle);
        var td = trUpdate.selectAll("td").data(function (d) {
          return d;
        });
        td.enter().append("td").merge(td).html(cellContent);
        divElement("footer");
        divElement("arrow");
        enter.attr("id", function (d, i) {
          return "d3plus-tooltip-".concat(d ? _this2._id(d, i) : "");
        }).call(boxStyles).each(function (d, i) {
          var id = that._id(d, i);
  
          var tooltip = document.getElementById("d3plus-tooltip-".concat(id));
          var arrow = document.getElementById("d3plus-tooltip-arrow-".concat(id));
          var arrowHeight = arrow.offsetHeight;
          var arrowDistance = arrow.getBoundingClientRect().height / 2;
          arrow.style.bottom = "-".concat(arrowHeight / 2, "px");
  
          var position = that._position(d, i);
  
          var referenceObject = Array.isArray(position) ? {
            clientWidth: 0,
            clientHeight: 0,
            getBoundingClientRect: function getBoundingClientRect() {
              return {
                top: position[1],
                right: position[0],
                bottom: position[1],
                left: position[0],
                width: 0,
                height: 0
              };
            }
          } : position;
          _this2._popperClasses[id] = new Popper(referenceObject, tooltip, {
            placement: "top",
            placements: ["top", "bottom", "left", "right"],
            modifiers: {
              arrow: {
                element: arrow
              },
              offset: {
                offset: "0,".concat(that._offset(d, i) + arrowDistance)
              },
              preventOverflow: {
                boundariesElement: "scrollParent"
              },
              flip: {
                behavior: "flip",
                boundariesElement: "viewport"
              }
            },
            onUpdate: function onUpdate(_ref) {
              var arrowElement = _ref.arrowElement,
                  flipped = _ref.flipped;
  
              if (flipped) {
                arrowElement.style.transform = "rotate(225deg)";
                arrowElement.style.top = "-".concat(arrowHeight / 2, "px");
              } else {
                arrowElement.style.transform = "rotate(45deg)";
                arrowElement.style.bottom = "-".concat(arrowHeight / 2, "px");
              }
            },
            removeOnDestroy: true
          });
        });
        update.each(function (d, i) {
          var id = that._id(d, i);
  
          var position = that._position(d, i);
  
          var instance = _this2._popperClasses[id];
  
          if (instance) {
            var referenceObject = Array.isArray(position) ? {
              clientWidth: 0,
              clientHeight: 0,
              getBoundingClientRect: function getBoundingClientRect() {
                return {
                  top: position[1],
                  right: position[0],
                  bottom: position[1],
                  left: position[0],
                  width: 0,
                  height: 0
                };
              }
            } : position;
            instance.reference = referenceObject;
            instance.scheduleUpdate();
          }
        }).call(boxStyles);
        tooltips.exit().each(function (d, i) {
          var id = that._id(d, i);
  
          var instance = _this2._popperClasses[id];
  
          if (instance) {
            instance.destroy();
            delete _this2._popperClasses[id];
          }
        }).remove();
        if (callback) setTimeout(callback, 100);
        return this;
      }
      /**
       @memberof Tooltip
       @desc Sets the inner HTML content of the arrow element, which by default is empty.
       @param {Function|String} [*value*]
       @example <caption>default accessor</caption>
       function value(d) {
      return d.arrow || "";
      }
       */
  
    }, {
      key: "arrow",
      value: function arrow(_) {
        return arguments.length ? (this._arrow = typeof _ === "function" ? _ : constant(_), this) : this._arrow;
      }
      /**
       @memberof Tooltip
       @desc If *value* is specified, sets the arrow styles to the specified values and returns this generator. If *value* is not specified, returns the current arrow styles.
       @param {Object} [*value*]
       @example <caption>default styles</caption>
       {
         "content": "",
         "border-width": "10px",
         "border-style": "solid",
         "border-color": "rgba(255, 255, 255, 0.75) transparent transparent transparent",
         "position": "absolute"
       }
       */
  
    }, {
      key: "arrowStyle",
      value: function arrowStyle(_) {
        return arguments.length ? (this._arrowStyle = Object.assign(this._arrowStyle, _), this) : this._arrowStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the background accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current background accessor.
          @param {Function|String} [*value* = "rgba(255, 255, 255, 0.75)"]
      */
  
    }, {
      key: "background",
      value: function background(_) {
        return arguments.length ? (this._background = typeof _ === "function" ? _ : constant(_), this) : this._background;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the body accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current body accessor.
          @param {Function|String} [*value*]
          @example <caption>default accessor</caption>
      function value(d) {
      return d.body || "";
      }
      */
  
    }, {
      key: "body",
      value: function body(_) {
        return arguments.length ? (this._body = typeof _ === "function" ? _ : constant(_), this) : this._body;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the body styles to the specified values and returns this generator. If *value* is not specified, returns the current body styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
      "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
      "font-size": "12px",
      "font-weight": "400"
      }
      */
  
    }, {
      key: "bodyStyle",
      value: function bodyStyle(_) {
        return arguments.length ? (this._bodyStyle = Object.assign(this._bodyStyle, _), this) : this._bodyStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the border accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current border accessor.
          @param {Function|String} [*value* = "1px solid rgba(0, 0, 0, 0.1)"]
      */
  
    }, {
      key: "border",
      value: function border(_) {
        return arguments.length ? (this._border = typeof _ === "function" ? _ : constant(_), this) : this._border;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the border-radius accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current border-radius accessor.
          @param {Function|String} [*value* = "2px"]
      */
  
    }, {
      key: "borderRadius",
      value: function borderRadius(_) {
        return arguments.length ? (this._borderRadius = typeof _ === "function" ? _ : constant(_), this) : this._borderRadius;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the class name to the specified string and returns this generator. If *value* is not specified, returns the current class name.
          @param {String} [*value* = "d3plus-tooltip"]
      */
  
    }, {
      key: "className",
      value: function className(_) {
        return arguments.length ? (this._className = _, this) : this._className;
      }
      /**
          @memberof Tooltip
          @desc If *data* is specified, sets the data array to the specified array and returns this generator. If *data* is not specified, returns the current data array.
          @param {Array} [*data* = []]
      */
  
    }, {
      key: "data",
      value: function data(_) {
        return arguments.length ? (this._data = _, this) : this._data;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the footer accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current footer accessor.
          @param {Function|String} [*value*]
          @example <caption>default accessor</caption>
      function value(d) {
      return d.footer || "";
      }
      */
  
    }, {
      key: "footer",
      value: function footer(_) {
        return arguments.length ? (this._footer = typeof _ === "function" ? _ : constant(_), this) : this._footer;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the footer styles to the specified values and returns this generator. If *value* is not specified, returns the current footer styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
      "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
      "font-size": "12px",
      "font-weight": "400"
      }
      */
  
    }, {
      key: "footerStyle",
      value: function footerStyle(_) {
        return arguments.length ? (this._footerStyle = Object.assign(this._footerStyle, _), this) : this._footerStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the height accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current height accessor.
          @param {Function|String} [*value* = "auto"]
      */
  
    }, {
      key: "height",
      value: function height(_) {
        return arguments.length ? (this._height = typeof _ === "function" ? _ : constant(_), this) : this._height;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the id accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current id accessor.
          @param {Function|String} [*value*]
          @example <caption>default accessor</caption>
      function value(d, i) {
      return d.id || "" + i;
      }
      */
  
    }, {
      key: "id",
      value: function id(_) {
        return arguments.length ? (this._id = typeof _ === "function" ? _ : constant(_), this) : this._id;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the offset accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current offset accessor.
          @param {Function|Number} [*value* = 10]
      */
  
    }, {
      key: "offset",
      value: function offset(_) {
        return arguments.length ? (this._offset = typeof _ === "function" ? _ : constant(_), this) : this._offset;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the padding accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current padding accessor.
          @param {Function|String} [*value* = "5px"]
      */
  
    }, {
      key: "padding",
      value: function padding(_) {
        return arguments.length ? (this._padding = typeof _ === "function" ? _ : constant(_), this) : this._padding;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the pointer-events accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current pointer-events accessor.
          @param {Function|String} [*value* = "auto"]
      */
  
    }, {
      key: "pointerEvents",
      value: function pointerEvents(_) {
        return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant(_), this) : this._pointerEvents;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the position accessor to the specified function or array and returns this generator. If *value* is not specified, returns the current position accessor. If *value* is an HTMLElement, anchors the Tooltip to that HTMLElement. If *value* is a selection string, anchors the Tooltip to the HTMLElement selected by that string. Otherwise, coordinate points must be in reference to the client viewport, not the overall page.
          @param {Function|Array|HTMLElement|String} [*value*]
          @example <caption>default accessor</caption>
       function value(d) {
        return [d.x, d.y];
      }
       */
  
    }, {
      key: "position",
      value: function position(_) {
        return arguments.length ? (this._position = typeof _ === "string" ? constant(select(_).node() || [0, 0]) : typeof _ === "function" ? _ : constant(_), this) : this._position;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the table styles to the specified values and returns this generator. If *value* is not specified, returns the current table styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
      "border-collapse": "collapse",
      "border-spacing": "0",
      "width": "100%"
      }
      */
  
    }, {
      key: "tableStyle",
      value: function tableStyle(_) {
        return arguments.length ? (this._tableStyle = Object.assign(this._tableStyle, _), this) : this._tableStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the contents of the table body to the specified array of functions or strings and returns this generator. If *value* is not specified, returns the current table body data.
          @param {Array} [*value* = []]
      */
  
    }, {
      key: "tbody",
      value: function tbody(_) {
        return arguments.length ? (this._tbody = _, this) : this._tbody;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the table body styles to the specified values and returns this generator. If *value* is not specified, returns the current table body styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
      "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
      "font-size": "12px",
      "font-weight": "600",
      "text-align": "center"
      }
      */
  
    }, {
      key: "tbodyStyle",
      value: function tbodyStyle(_) {
        return arguments.length ? (this._tbodyStyle = Object.assign(this._tbodyStyle, _), this) : this._tbodyStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the contents of the table head to the specified array of functions or strings and returns this generator. If *value* is not specified, returns the current table head data.
          @param {Array} [*value* = []]
      */
  
    }, {
      key: "thead",
      value: function thead(_) {
        return arguments.length ? (this._thead = _, this) : this._thead;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the table head styles to the specified values and returns this generator. If *value* is not specified, returns the current table head styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
      "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
      "font-size": "12px",
      "font-weight": "600",
      "text-align": "center"
      }
      */
  
    }, {
      key: "theadStyle",
      value: function theadStyle(_) {
        return arguments.length ? (this._theadStyle = Object.assign(this._theadStyle, _), this) : this._theadStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the title accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current title accessor.
          @param {Function|String} [*value*]
          @example <caption>default accessor</caption>
      function value(d) {
      return d.title || "";
      }
      */
  
    }, {
      key: "title",
      value: function title(_) {
        return arguments.length ? (this._title = typeof _ === "function" ? _ : constant(_), this) : this._title;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the title styles to the specified values and returns this generator. If *value* is not specified, returns the current title styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
      "font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
      "font-size": "14px",
      "font-weight": "600",
      "padding-bottom": "5px"
      }
      */
  
    }, {
      key: "titleStyle",
      value: function titleStyle(_) {
        return arguments.length ? (this._titleStyle = Object.assign(this._titleStyle, _), this) : this._titleStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the table row styles to the specified values and returns this generator. If *value* is not specified, returns the current table row styles.
          @param {Object} [*value*]
          @example <caption>default styles</caption>
      {
        "border-top": "1px solid rgba(0, 0, 0, 0.1)"
      }
       */
  
    }, {
      key: "trStyle",
      value: function trStyle(_) {
        return arguments.length ? (this._trStyle = Object.assign(this._trStyle, _), this) : this._trStyle;
      }
      /**
          @memberof Tooltip
          @desc If *value* is specified, sets the width accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current width accessor.
          @param {Function|String} [*value* = "auto"]
      */
  
    }, {
      key: "width",
      value: function width(_) {
        return arguments.length ? (this._width = typeof _ === "function" ? _ : constant(_), this) : this._width;
      }
    }]);
  
    return Tooltip;
  }(BaseClass);
  
  export { Tooltip as default };