UNPKG

billboard.js

Version:

Re-usable easy interface JavaScript chart library, based on D3 v4+

36,509 lines • 1.31 MB
/*!
 * Copyright (c) 2017 ~ present NAVER Corp.
 * billboard.js project is licensed under the MIT license
 *
 * billboard.js, JavaScript chart library
 * https://naver.github.io/billboard.js/
 *
 * @version 4.1.1
 */
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("d3-brush"), require("d3-drag"), require("d3-hierarchy"), require("d3-interpolate"), require("d3-scale"), require("d3-selection"), require("d3-shape"), require("d3-time-format"), require("d3-transition"), require("d3-zoom"));
	else if(typeof define === 'function' && define.amd)
		define(["d3-brush", "d3-drag", "d3-hierarchy", "d3-interpolate", "d3-scale", "d3-selection", "d3-shape", "d3-time-format", "d3-transition", "d3-zoom"], factory);
	else {
		var a = typeof exports === 'object' ? factory(require("d3-brush"), require("d3-drag"), require("d3-hierarchy"), require("d3-interpolate"), require("d3-scale"), require("d3-selection"), require("d3-shape"), require("d3-time-format"), require("d3-transition"), require("d3-zoom")) : factory(root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"]);
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})(this, function(__WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__11__, __WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__5__, __WEBPACK_EXTERNAL_MODULE__8__, __WEBPACK_EXTERNAL_MODULE__9__) {
return /******/ (function() { // webpackBootstrap
/******/ 	// runtime can't be in strict mode because 'output.globalObject' reads 'this'.
/******/ 	var __webpack_modules__ = ([
/* 0 */,
/* 1 */,
/* 2 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__2__;

/***/ }),
/* 3 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__3__;

/***/ }),
/* 4 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__4__;

/***/ }),
/* 5 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__5__;

/***/ }),
/* 6 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__6__;

/***/ }),
/* 7 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__7__;

/***/ }),
/* 8 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__8__;

/***/ }),
/* 9 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__9__;

/***/ }),
/* 10 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__10__;

/***/ }),
/* 11 */
/***/ (function(module) {

"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE__11__;

/***/ })
/******/ 	]);
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	// define getter/value functions for harmony exports
/******/ 	__webpack_require__.d = function(exports, definition) {
/******/ 		for(var key in definition) {
/******/ 			if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 				Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 			}
/******/ 		}
/******/ 	};
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); };
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = function(exports) {
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 		}
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
!function() {
"use strict";
// extracted by mini-css-extract-plugin

}();
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
!function() {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  bb: function() { return /* reexport */ bb; },
  "default": function() { return /* reexport */ bb; }
});

// NAMESPACE OBJECT (decoupled): ./src/config/resolver/interaction/index.ts
var interaction_namespaceObject = {};
__webpack_require__.r(interaction_namespaceObject);
__webpack_require__.d(interaction_namespaceObject, {
  selection: function() { return selectionModule; },
  subchart: function() { return subchartModule; },
  zoom: function() { return zoomModule; }
});

// NAMESPACE OBJECT (decoupled): ./src/config/resolver/shape/index.ts
var shape_namespaceObject = {};
__webpack_require__.r(shape_namespaceObject);
__webpack_require__.d(shape_namespaceObject, {
  area: function() { return area_area; },
  areaLineRange: function() { return areaLineRange; },
  areaSpline: function() { return areaSpline; },
  areaSplineRange: function() { return areaSplineRange; },
  areaStep: function() { return areaStep; },
  areaStepRange: function() { return areaStepRange; },
  bar: function() { return bar_bar; },
  bubble: function() { return bubble_bubble; },
  candlestick: function() { return candlestick_candlestick; },
  donut: function() { return donut_donut; },
  funnel: function() { return funnel_funnel; },
  gauge: function() { return gauge_gauge; },
  line: function() { return line_line; },
  pie: function() { return pie_pie; },
  polar: function() { return polar_polar; },
  radar: function() { return radar_radar; },
  scatter: function() { return scatter_scatter; },
  spline: function() { return line_spline; },
  step: function() { return step; },
  treemap: function() { return treemap_treemap; }
});

// EXTERNAL MODULE: external {"commonjs":"d3-selection","commonjs2":"d3-selection","amd":"d3-selection","root":"d3"}
var external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_ = __webpack_require__(2);
;// ./src/config/const.ts
const TYPE = {
  AREA: "area",
  AREA_LINE_RANGE: "area-line-range",
  AREA_SPLINE: "area-spline",
  AREA_SPLINE_RANGE: "area-spline-range",
  AREA_STEP: "area-step",
  AREA_STEP_RANGE: "area-step-range",
  BAR: "bar",
  BUBBLE: "bubble",
  CANDLESTICK: "candlestick",
  DONUT: "donut",
  FUNNEL: "funnel",
  GAUGE: "gauge",
  LINE: "line",
  PIE: "pie",
  POLAR: "polar",
  RADAR: "radar",
  SCATTER: "scatter",
  SPLINE: "spline",
  STEP: "step",
  TREEMAP: "treemap"
};
const API_MODULE_NEEDED = {
  export: "exportApi",
  flow: "flow",
  xgrids: "grid",
  ygrids: "grid",
  regions: "regions",
  category: "category",
  categories: "category"
};
const RESIZE_FRAME_BUDGET = 16;
const AXIS_DEFAULT_TICK_COUNT = 10;
const AXIS_TICK_SIZE = 6;
const AXIS_TICK_PADDING = 3;
const AXIS_TICK_LENGTH = AXIS_TICK_SIZE + AXIS_TICK_PADDING;
const AXIS_TICK_LINE_OVERLAP_PADDING = 1;
const SUBCHART_BRUSH_HANDLE_PATH = {
  x: {
    start: "M0 -8.5 A6 6 0 0 0 -6.5 -3.5 V2.5 A6 6 0 0 0 0 8.5 Z M-2 -3.5 V3.5 M-4 -3.5 V3.5z",
    end: "M0 -8.5 A6 6 0 0 1 6.5 -3.5 V2.5 A6 6 0 0 1 0 8.5 Z M2 -3.5 V3.5 M4 -3.5 V3.5z"
  },
  y: {
    start: "M8.5 0 a6 6 0 0 0 -6 -6.5 H-2.5 a 6 6 0 0 0 -6 6.5 z m-5 -2 H-3.5 m7 -2 H-3.5z",
    end: "M8.5 0 a6 -6 0 0 1 -6 6.5 H-2.5 a 6 -6 0 0 1 -6 -6.5z m-5 2 H-3.5 m7 2 H-3.5z"
  }
};
const TYPE_METHOD_NEEDED = {
  AREA: "initArea",
  AREA_LINE_RANGE: "initArea",
  AREA_SPLINE: "initArea",
  AREA_SPLINE_RANGE: "initArea",
  AREA_STEP: "initArea",
  AREA_STEP_RANGE: "initArea",
  BAR: "initBar",
  BUBBLE: "initCircle",
  CANDLESTICK: "initCandlestick",
  DONUT: "initArc",
  FUNNEL: "initFunnel",
  GAUGE: "initArc",
  LINE: "initLine",
  PIE: "initArc",
  POLAR: "initPolar",
  RADAR: "initCircle",
  SCATTER: "initCircle",
  SPLINE: "initLine",
  STEP: "initLine",
  TREEMAP: "initTreemap"
};
const TYPE_BY_CATEGORY = {
  Area: [
    TYPE.AREA,
    TYPE.AREA_SPLINE,
    TYPE.AREA_SPLINE_RANGE,
    TYPE.AREA_LINE_RANGE,
    TYPE.AREA_STEP,
    TYPE.AREA_STEP_RANGE
  ],
  AreaRange: [
    TYPE.AREA_SPLINE_RANGE,
    TYPE.AREA_LINE_RANGE,
    TYPE.AREA_STEP_RANGE
  ],
  Arc: [
    TYPE.PIE,
    TYPE.DONUT,
    TYPE.GAUGE,
    TYPE.POLAR,
    TYPE.RADAR
  ],
  Line: [
    TYPE.LINE,
    TYPE.SPLINE,
    TYPE.AREA,
    TYPE.AREA_SPLINE,
    TYPE.AREA_SPLINE_RANGE,
    TYPE.AREA_LINE_RANGE,
    TYPE.STEP,
    TYPE.AREA_STEP,
    TYPE.AREA_STEP_RANGE
  ],
  Step: [
    TYPE.STEP,
    TYPE.AREA_STEP,
    TYPE.AREA_STEP_RANGE
  ],
  Spline: [
    TYPE.SPLINE,
    TYPE.AREA_SPLINE,
    TYPE.AREA_SPLINE_RANGE
  ]
};

// EXTERNAL MODULE: external {"commonjs":"d3-scale","commonjs2":"d3-scale","amd":"d3-scale","root":"d3"}
var external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_ = __webpack_require__(3);
;// ./src/module/util/type-checks.ts
const isValue = (v) => v || v === 0;
const isFunction = (v) => typeof v === "function";
const isString = (v) => typeof v === "string";
const isNumber = (v) => typeof v === "number";
const isUndefined = (v) => typeof v === "undefined";
const isDefined = (v) => typeof v !== "undefined";
const isBoolean = (v) => typeof v === "boolean";
const ceil10 = (v) => Math.ceil(v / 10) * 10;
const asHalfPixel = (n) => Math.ceil(n) + 0.5;
const diffDomain = (d) => d[1] - d[0];
const isObjectType = (v) => typeof v === "object";
const isEmptyObject = (obj) => {
  for (const x in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, x)) {
      return false;
    }
  }
  return true;
};
const isEmpty = (o) => isUndefined(o) || o === null || isString(o) && o.length === 0 || isObjectType(o) && !(o instanceof Date) && isEmptyObject(o) || isNumber(o) && isNaN(o);
const notEmpty = (o) => !isEmpty(o);
const isArray = (arr) => Array.isArray(arr);
const isObject = (obj) => obj && !(obj == null ? void 0 : obj.nodeType) && isObjectType(obj) && !isArray(obj);


;// ./src/module/browser.ts
function getGlobal() {
  return typeof globalThis === "object" && globalThis !== null && globalThis.Object === Object && globalThis || typeof self === "object" && self !== null && self.Object === Object && self || Function("return this")();
}
function getFallback(w) {
  const hasRAF = typeof (w == null ? void 0 : w.requestAnimationFrame) === "function" && typeof (w == null ? void 0 : w.cancelAnimationFrame) === "function";
  const hasRIC = typeof (w == null ? void 0 : w.requestIdleCallback) === "function" && typeof (w == null ? void 0 : w.cancelIdleCallback) === "function";
  const request = (cb) => setTimeout(cb, 1);
  const cancel = (id) => clearTimeout(id);
  return [
    hasRAF ? w.requestAnimationFrame : request,
    hasRAF ? w.cancelAnimationFrame : cancel,
    hasRIC ? w.requestIdleCallback : request,
    hasRIC ? w.cancelIdleCallback : cancel
  ];
}
const win = getGlobal();
const browser_doc = win == null ? void 0 : win.document;
const [
  requestAnimationFrame,
  cancelAnimationFrame,
  requestIdleCallback,
  cancelIdleCallback
] = getFallback(win);


;// ./src/module/sanitize.ts
const ALLOWED_TAGS = /* @__PURE__ */ new Set([
  // HTML tags for tooltip/legend templates
  "span",
  "div",
  "p",
  "br",
  "b",
  "i",
  "em",
  "small",
  "strong",
  "mark",
  "u",
  "s",
  "sub",
  "sup",
  "h1",
  "h2",
  "h3",
  "h4",
  "h5",
  "h6",
  "ul",
  "ol",
  "li",
  "dl",
  "dt",
  "dd",
  "table",
  "thead",
  "tbody",
  "tfoot",
  "tr",
  "th",
  "td",
  "caption",
  "colgroup",
  "col",
  "hr",
  "pre",
  "code",
  "blockquote",
  "abbr",
  "ins",
  "del",
  "a",
  "img",
  "figure",
  "figcaption",
  // SVG tags for point patterns
  "svg",
  "g",
  "path",
  "circle",
  "ellipse",
  "rect",
  "line",
  "polyline",
  "polygon",
  "text",
  "tspan",
  "textPath",
  "use",
  "defs",
  "symbol",
  "clipPath",
  "mask",
  "linearGradient",
  "radialGradient",
  "stop",
  "pattern",
  "marker",
  "title",
  "desc"
]);
const ALLOWED_ATTRS = /* @__PURE__ */ new Set([
  // Common attributes
  "class",
  "id",
  "style",
  "title",
  "lang",
  "dir",
  // HTML specific
  "href",
  "src",
  "alt",
  "width",
  "height",
  "colspan",
  "rowspan",
  "scope",
  "headers",
  // SVG presentation attributes
  "d",
  "points",
  "x",
  "y",
  "x1",
  "x2",
  "y1",
  "y2",
  "cx",
  "cy",
  "r",
  "rx",
  "ry",
  "dx",
  "dy",
  "viewBox",
  "preserveAspectRatio",
  "transform",
  "fill",
  "fill-opacity",
  "fill-rule",
  "stroke",
  "stroke-width",
  "stroke-opacity",
  "stroke-linecap",
  "stroke-linejoin",
  "stroke-dasharray",
  "stroke-dashoffset",
  "opacity",
  "clip-path",
  "clip-rule",
  "mask",
  "font-family",
  "font-size",
  "font-weight",
  "font-style",
  "text-anchor",
  "dominant-baseline",
  "offset",
  "stop-color",
  "stop-opacity",
  "gradientUnits",
  "gradientTransform",
  "spreadMethod",
  "patternUnits",
  "patternTransform",
  "marker-start",
  "marker-mid",
  "marker-end",
  "markerWidth",
  "markerHeight",
  "refX",
  "refY",
  "xlink:href"
]);
const TAG_CASE_MAP = /* @__PURE__ */ new Map();
ALLOWED_TAGS.forEach((tag) => TAG_CASE_MAP.set(tag.toLowerCase(), tag));
const ATTR_CASE_MAP = /* @__PURE__ */ new Map();
ALLOWED_ATTRS.forEach((attr) => ATTR_CASE_MAP.set(attr.toLowerCase(), attr));
const ALLOWED_URI_PROTOCOLS = /* @__PURE__ */ new Set([
  "http:",
  "https:",
  "mailto:"
]);
const URI_ATTRS = /* @__PURE__ */ new Set(["href", "src", "xlink:href"]);
const TAG_NAME_REGEX = /^<\/?([a-zA-Z][a-zA-Z0-9]*)/;
const CLOSING_TAG_REGEX = /^<\/([a-zA-Z][a-zA-Z0-9]*)\s*>$/;
const OPENING_TAG_REGEX = /^<([a-zA-Z][a-zA-Z0-9]*)([\s\S]*?)(\/?)>$/;
const ATTR_REGEX = /([a-zA-Z][\w:-]*)\s*(?:=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
const URL_IN_STYLE_REGEX = /url\s*\(\s*["']?([^"')]+)["']?\s*\)/gi;
const DANGEROUS_CSS_PATTERNS = [
  "expression(",
  "behavior:",
  "binding:",
  "@import",
  "@charset",
  "-moz-binding:"
];
function decodeHTMLEntities(str) {
  return str.replace(/&colon;/gi, ":").replace(/&newline;/gi, "\n").replace(/&tab;/gi, "	").replace(/&nbsp;/gi, " ").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&amp;/gi, "&").replace(/&quot;/gi, '"').replace(/&apos;/gi, "'").replace(/&#(\d+);?/gi, (_, code) => String.fromCharCode(parseInt(code, 10))).replace(/&#x([0-9a-f]+);?/gi, (_, code) => String.fromCharCode(parseInt(code, 16)));
}
function isSafeURI(uri) {
  const decoded = decodeHTMLEntities(uri).trim();
  const normalized = decoded.replace(/[\s\u0000-\u001f]/g, "").toLowerCase();
  if (!normalized || normalized.startsWith("#")) {
    return true;
  }
  const schemeMatch = normalized.match(/^[^/?#]*:/);
  if (schemeMatch) {
    return ALLOWED_URI_PROTOCOLS.has(schemeMatch[0]);
  }
  return true;
}
function sanitizeStyleValue(style) {
  const decoded = decodeHTMLEntities(style);
  const cleaned = decoded.replace(/[\u0000-\u001f]/g, "");
  URL_IN_STYLE_REGEX.lastIndex = 0;
  let match;
  while ((match = URL_IN_STYLE_REGEX.exec(cleaned)) !== null) {
    if (!isSafeURI(match[1])) {
      return null;
    }
  }
  const normalizedLower = cleaned.toLowerCase().replace(/\s/g, "");
  for (const pattern of DANGEROUS_CSS_PATTERNS) {
    if (normalizedLower.includes(pattern)) {
      return null;
    }
  }
  return style;
}
const ATTR_ENCODE_MAP = {
  '"': "&quot;",
  "'": "&#39;",
  "`": "&#96;"
};
const ATTR_ENCODE_REGEX = /["'`]/g;
function encodeAttrValue(value) {
  return value.replace(ATTR_ENCODE_REGEX, (char) => ATTR_ENCODE_MAP[char]);
}
function sanitizeAttrValue(name, value, wasUnquoted = false) {
  if (URI_ATTRS.has(name)) {
    if (!isSafeURI(value)) {
      return null;
    }
    return wasUnquoted ? encodeAttrValue(value) : value;
  }
  if (name === "style") {
    const sanitizedStyle = sanitizeStyleValue(value);
    if (sanitizedStyle === null) {
      return null;
    }
    return wasUnquoted ? encodeAttrValue(sanitizedStyle) : sanitizedStyle;
  }
  const decoded = decodeHTMLEntities(value).toLowerCase().replace(/\s/g, "");
  if (/\bon\w+=/.test(decoded)) {
    return null;
  }
  return wasUnquoted ? encodeAttrValue(value) : value;
}
function extractTagName(tag) {
  const match = tag.match(TAG_NAME_REGEX);
  return match ? match[1].toLowerCase() : null;
}
function isAllowedTag(tag) {
  const tagName = extractTagName(tag);
  return tagName !== null && TAG_CASE_MAP.has(tagName);
}
function sanitizeTag(fullTag) {
  var _a, _b, _c;
  const closingMatch = fullTag.match(CLOSING_TAG_REGEX);
  if (closingMatch) {
    const lowerName = closingMatch[1].toLowerCase();
    return `</${(_a = TAG_CASE_MAP.get(lowerName)) != null ? _a : lowerName}>`;
  }
  const openingMatch = fullTag.match(OPENING_TAG_REGEX);
  if (!openingMatch) {
    return "";
  }
  const [, tagName, attrString, selfClose] = openingMatch;
  const lowerTagName = tagName.toLowerCase();
  const canonicalTagName = (_b = TAG_CASE_MAP.get(lowerTagName)) != null ? _b : lowerTagName;
  const allowedAttrs = [];
  ATTR_REGEX.lastIndex = 0;
  let attrMatch;
  while ((attrMatch = ATTR_REGEX.exec(attrString)) !== null) {
    const lowerAttrName = attrMatch[1].toLowerCase();
    const doubleQuotedValue = attrMatch[2];
    const singleQuotedValue = attrMatch[3];
    const unquotedValue = attrMatch[4];
    if (lowerAttrName.startsWith("on")) {
      continue;
    }
    const canonicalAttrName = (_c = ATTR_CASE_MAP.get(lowerAttrName)) != null ? _c : lowerAttrName;
    let attrValue;
    let quoteChar;
    if (doubleQuotedValue !== void 0) {
      attrValue = doubleQuotedValue;
      quoteChar = '"';
    } else if (singleQuotedValue !== void 0) {
      attrValue = singleQuotedValue;
      quoteChar = "'";
    } else if (unquotedValue !== void 0) {
      attrValue = unquotedValue;
      quoteChar = '"';
    } else {
      if (ATTR_CASE_MAP.has(lowerAttrName)) {
        allowedAttrs.push(canonicalAttrName);
      }
      continue;
    }
    if (ATTR_CASE_MAP.has(lowerAttrName)) {
      const wasUnquoted = unquotedValue !== void 0;
      const sanitizedValue = sanitizeAttrValue(lowerAttrName, attrValue, wasUnquoted);
      if (sanitizedValue !== null) {
        allowedAttrs.push(`${canonicalAttrName}=${quoteChar}${sanitizedValue}${quoteChar}`);
      }
    }
  }
  const attrsStr = allowedAttrs.length > 0 ? ` ${allowedAttrs.join(" ")}` : "";
  const selfCloseStr = selfClose ? "/>" : ">";
  return `<${canonicalTagName}${attrsStr}${selfCloseStr}`;
}
function sanitize(str) {
  if (typeof str !== "string" || !str || str.indexOf("<") === -1) {
    return str;
  }
  return str.replace(
    /<\/?[^>]*>|[^<>\s]+>/g,
    (match) => {
      if (match.startsWith("<!--")) {
        return "";
      }
      if (!match.startsWith("<")) {
        return match.slice(0, -1) + "&gt;";
      }
      if (isAllowedTag(match)) {
        return sanitizeTag(match);
      }
      return match.replace(/</g, "&lt;");
    }
  );
}

;// ./src/module/util/object.ts
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};



function _forEachValidItem(items, callback) {
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item !== null && isDefined(item)) {
      callback(item, i);
    }
  }
}
function getOption(options, key, defaultValue) {
  return isDefined(options[key]) ? options[key] : defaultValue;
}
function hasValue(dict, value) {
  for (const key in dict) {
    if (dict[key] === value) return true;
  }
  return false;
}
function callFn(fn, thisArg, ...args) {
  const isFn = isFunction(fn);
  isFn && fn.call(thisArg, ...args);
  return isFn;
}
function endall(transition, cb) {
  let n = 0;
  const end = function(...args) {
    !--n && cb.apply(this, args);
  };
  if ("duration" in transition) {
    transition.each(() => ++n).on("end", end);
  } else {
    ++n;
    transition.call(end);
  }
}
const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
function camelize(str, separator = "-") {
  return str.split(separator).map((v, i) => i ? v.charAt(0).toUpperCase() + v.slice(1).toLowerCase() : v.toLowerCase()).join("");
}
const toArray = (v) => [].slice.call(v);
function deepClone(...objectN) {
  const clone = (v) => {
    if (isArray(v)) {
      return v.map(clone);
    } else if (isObject(v) && v.constructor) {
      const r = new v.constructor();
      for (const k in v) {
        r[k] = clone(v[k]);
      }
      return r;
    }
    return v;
  };
  return objectN.map((v) => clone(v)).reduce((a, c) => __spreadValues(__spreadValues({}, a), c));
}
function extend(target = {}, source) {
  if (isArray(source)) {
    source.forEach((v) => extend(target, v));
  }
  for (const p in source) {
    if (/^\d+$/.test(p) || p in target) {
      continue;
    }
    target[p] = source[p];
  }
  return target;
}
function getUnique(data) {
  const isDate = data[0] instanceof Date;
  const d = Array.from(new Set(isDate ? data.map(Number) : data));
  return isDate ? d.map((v) => new Date(v)) : d;
}
function mergeArray(arr) {
  return arr && arr.length ? arr.reduce((p, c) => p.concat(c)) : [];
}
function mergeObj(target, ...objectN) {
  if (!objectN.length || objectN.length === 1 && !objectN[0]) {
    return target;
  }
  const source = objectN.shift();
  if (isObject(target) && isObject(source)) {
    Object.keys(source).forEach((key) => {
      if (!/^(__proto__|constructor|prototype)$/i.test(key)) {
        const value = source[key];
        if (value instanceof Date) {
          target[key] = new Date(value.getTime());
        } else if (isObject(value)) {
          !target[key] && (target[key] = {});
          target[key] = mergeObj(target[key], value);
        } else {
          target[key] = isArray(value) ? value.concat() : value;
        }
      }
    });
  }
  return mergeObj(target, ...objectN);
}
function sortValue(data, isAsc = true) {
  let fn;
  if (data[0] instanceof Date) {
    fn = isAsc ? (a, b) => a - b : (a, b) => b - a;
  } else {
    if (isAsc && !data.every(isNaN)) {
      fn = (a, b) => a - b;
    } else if (!isAsc) {
      fn = (a, b) => a > b && -1 || a < b && 1 || a === b && 0;
    }
  }
  return data.concat().sort(fn);
}
function getMinMax(type, data) {
  let res = data.filter((v) => notEmpty(v));
  if (res.length) {
    if (isNumber(res[0])) {
      let result = type === "min" ? Infinity : -Infinity;
      for (const v of res) {
        if (type === "min" ? v < result : v > result) {
          result = v;
        }
      }
      res = result;
    } else if (res[0] instanceof Date) {
      res = sortValue(res, type === "min")[0];
    }
  } else {
    res = void 0;
  }
  return res;
}
const getRange = (start, end, step = 1) => {
  const res = [];
  const n = Math.max(0, Math.ceil((end - start) / step)) | 0;
  for (let i = 0; i < n; i++) {
    res.push(start + i * step);
  }
  return res;
};
let _transitionCounter = 0;
function getRandom(asStr = true) {
  const id = ++_transitionCounter;
  return asStr ? String(id) : id;
}
function findIndex(arr, v, start, end, isRotated) {
  if (start > end) {
    return -1;
  }
  const mid = Math.floor((start + end) / 2);
  let { x, w = 0 } = arr[mid];
  if (isRotated) {
    x = arr[mid].y;
    w = arr[mid].h;
  }
  if (v >= x && v <= x + w) {
    return mid;
  }
  return v < x ? findIndex(arr, v, start, mid - 1, isRotated) : findIndex(arr, v, mid + 1, end, isRotated);
}
function tplProcess(tpl, data) {
  return sanitize(tpl.replace(/\{=([^}]+)\}/g, (_, key) => {
    var _a;
    return (_a = data[key]) != null ? _a : "";
  }));
}
function parseDate(date) {
  var _a;
  let parsedDate;
  if (date instanceof Date) {
    parsedDate = date;
  } else if (isString(date)) {
    const { config, format } = this;
    parsedDate = (_a = format.dataTime(config.data_xFormat)(date)) != null ? _a : new Date(date);
  } else if (isNumber(date) && !isNaN(date)) {
    parsedDate = /* @__PURE__ */ new Date(+date);
  }
  if (!parsedDate || isNaN(+parsedDate)) {
    console && console.error && console.error(`Failed to parse x '${date}' to Date object`);
  }
  return parsedDate;
}
function parseShorthand(value) {
  if (isObject(value) && !isString(value)) {
    const obj = value;
    return {
      top: obj.top || 0,
      right: obj.right || 0,
      bottom: obj.bottom || 0,
      left: obj.left || 0
    };
  }
  const values = (isString(value) ? value.trim().split(/\s+/) : [value]).map((v) => +v || 0);
  const [a, b = a, c = a, d = b] = values;
  return { top: a, right: b, bottom: c, left: d };
}
function runUntil(fn, conditionFn) {
  if (conditionFn() === false) {
    requestAnimationFrame(() => runUntil(fn, conditionFn));
  } else {
    fn();
  }
}
function toSet(items, keyFn = ((item) => item)) {
  const set = /* @__PURE__ */ new Set();
  _forEachValidItem(items, (item, i) => {
    set.add(keyFn(item, i));
  });
  return set;
}
function toMap(items, keyFn, valueFn = ((item) => item)) {
  const map = /* @__PURE__ */ new Map();
  _forEachValidItem(items, (item, i) => {
    map.set(keyFn(item, i), valueFn(item, i));
  });
  return map;
}


;// ./src/ChartInternal/internals/scale.ts


function getScale(type = "linear", min, max) {
  const scale = {
    linear: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLinear,
    log: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleSymlog,
    _log: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLog,
    time: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleTime,
    utc: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleUtc
  }[type]();
  scale.type = type;
  /_?log/.test(type) && scale.clamp(true);
  return scale.range([min != null ? min : 0, max != null ? max : 1]);
}
/* harmony default export */ var scale = ({
  /**
   * Get x Axis scale function
   * @param {number} min Min range value
   * @param {number} max Max range value
   * @param {Array} domain Domain value
   * @param {function} offset The offset getter to be sum
   * @returns {function} scale
   * @private
   */
  getXScale(min, max, domain, offset) {
    const $$ = this;
    const scale = $$.state.loading !== "append" && $$.scale.zoom || getScale($$.axis.getAxisType("x"), min, max);
    return $$.getCustomizedXScale(
      domain ? scale.domain(domain) : scale,
      offset
    );
  },
  /**
   * Get y Axis scale function
   * @param {string} id Axis id: 'y' or 'y2'
   * @param {number} min Min value
   * @param {number} max Max value
   * @param {Array} domain Domain value
   * @param {object} [existing] Existing scale function to be updated
   * @returns {function} Scale function
   * @private
   */
  getYScale(id, min, max, domain, existing) {
    const $$ = this;
    const type = $$.axis.getAxisType(id);
    if (existing && existing.type === type) {
      existing.range([min, max]);
      domain && existing.domain(domain);
      return existing;
    }
    const scale = getScale(type, min, max);
    domain && scale.domain(domain);
    return scale;
  },
  /**
   * Get y Axis scale
   * @param {string} id Axis id
   * @param {boolean} isSub Weather is sub Axis
   * @returns {function} Scale function
   * @private
   */
  getYScaleById(id, isSub = false) {
    var _a;
    const isY2 = ((_a = this.axis) == null ? void 0 : _a.getId(id)) === "y2";
    const key = isSub ? isY2 ? "subY2" : "subY" : isY2 ? "y2" : "y";
    return this.scale[key];
  },
  /**
   * Get customized x axis scale
   * @param {d3.scaleLinear|d3.scaleTime} scaleValue Scale function
   * @param {function} offsetValue Offset getter to be sum
   * @returns {function} Scale function
   * @private
   */
  getCustomizedXScale(scaleValue, offsetValue) {
    const $$ = this;
    const offset = () => {
      const value = offsetValue ? offsetValue() : $$.axis.x.tickOffset();
      return value || ($$.axis.isCategorized() ? (scaleValue(1) - scaleValue(0)) / 2 : 0);
    };
    const isInverted = $$.config.axis_x_inverted;
    const scale = function(d) {
      return scaleValue(d) + offset();
    };
    for (const key in scaleValue) {
      scale[key] = scaleValue[key];
    }
    scale.orgDomain = () => scaleValue.domain();
    scale.orgScale = () => scaleValue;
    if ($$.axis.isCategorized()) {
      scale.domain = function(domainValue) {
        let domain = domainValue;
        if (!arguments.length) {
          domain = this.orgDomain();
          return isInverted ? [domain[0] + 1, domain[1]] : [domain[0], domain[1] + 1];
        }
        scaleValue.domain(domain);
        return scale;
      };
    }
    return scale;
  },
  /**
   * Update scale
   * @param {boolean} isInit Param is given at the init rendering
   * @param {boolean} updateXDomain If update x domain
   * @private
   */
  updateScales(isInit, updateXDomain = true) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i;
    const $$ = this;
    const {
      axis,
      config,
      format,
      org,
      scale,
      state: { current, width, height, width2, height2, hasAxis, hasTreemap }
    } = $$;
    if (hasAxis) {
      const isRotated = config.axis_rotated;
      const resettedPadding = $$.getResettedPadding(1);
      const min = {
        x: isRotated ? resettedPadding : 0,
        y: isRotated ? 0 : height,
        subX: isRotated ? 1 : 0,
        subY: isRotated ? 0 : height2
      };
      const max = {
        x: isRotated ? height : width,
        y: isRotated ? width : resettedPadding,
        subX: isRotated ? height : width,
        subY: isRotated ? width2 : 1
      };
      const xDomain = updateXDomain ? (_a = scale.x) == null ? void 0 : _a.orgDomain() : scale.zoom ? void 0 : (_c = (_b = scale.x) == null ? void 0 : _b.domain) == null ? void 0 : _c.call(_b);
      const xSubDomain = updateXDomain ? org.xDomain : scale.zoom ? void 0 : (_e = (_d = scale.subX) == null ? void 0 : _d.domain) == null ? void 0 : _e.call(_d);
      scale.x = $$.getXScale(min.x, max.x, xDomain, () => axis.x.tickOffset());
      scale.subX = $$.getXScale(min.x, max.x, xSubDomain, (d) => {
        var _a2;
        return d % 1 ? 0 : ((_a2 = axis.subX) != null ? _a2 : axis.x).tickOffset();
      });
      format.xAxisTick = axis.getXAxisTickFormat();
      format.subXAxisTick = axis.getXAxisTickFormat(true);
      axis.setAxis("x", scale.x, config.axis_x_tick_outer, isInit);
      if (config.subchart_show) {
        axis.setAxis(
          "subX",
          scale.subX,
          (_f = config.subchart_axis_x_tick_outer) != null ? _f : config.axis_x_tick_outer,
          isInit
        );
      }
      scale.y = $$.getYScale(
        "y",
        min.y,
        max.y,
        scale.y ? scale.y.domain() : config.axis_y_default,
        scale.y
      );
      scale.subY = $$.getYScale(
        "y",
        min.subY,
        max.subY,
        scale.subY ? scale.subY.domain() : config.axis_y_default,
        scale.subY
      );
      axis.setAxis("y", scale.y, config.axis_y_tick_outer, isInit);
      config.subchart_show && config.subchart_axis_y_show && axis.setAxis(
        "subY",
        scale.subY,
        (_g = config.subchart_axis_y_tick_outer) != null ? _g : config.axis_y_tick_outer,
        isInit
      );
      if (config.axis_y2_show || config.subchart_axis_y2_show) {
        scale.y2 = $$.getYScale(
          "y2",
          min.y,
          max.y,
          scale.y2 ? scale.y2.domain() : config.axis_y2_default,
          scale.y2
        );
        scale.subY2 = $$.getYScale(
          "y2",
          min.subY,
          max.subY,
          scale.subY2 ? scale.subY2.domain() : config.axis_y2_default,
          scale.subY2
        );
        axis.setAxis("y2", scale.y2, config.axis_y2_tick_outer, isInit);
        config.subchart_show && config.subchart_axis_y2_show && axis.setAxis(
          "subY2",
          scale.subY2,
          (_h = config.subchart_axis_y2_tick_outer) != null ? _h : config.axis_y2_tick_outer,
          isInit
        );
      }
    } else if (hasTreemap) {
      const padding = $$.getCurrentPadding();
      scale.x = (0,external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLinear)().rangeRound([padding.left, current.width - padding.right]);
      scale.y = (0,external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLinear)().rangeRound([padding.top, current.height - padding.bottom]);
    } else {
      (_i = $$.updateArc) == null ? void 0 : _i.call($$);
    }
  },
  /**
   * Get the zoom or unzoomed scaled value
   * @param {Date|number|object} d Data value
   * @returns {number|null}
   * @private
   */
  xx(d) {
    const $$ = this;
    const { config, scale: { x, zoom } } = $$;
    const fn = config.zoom_enabled && zoom ? zoom : x;
    return d ? fn(isValue(d.x) ? d.x : d) : null;
  },
  xv(d) {
    const $$ = this;
    const { axis, config, scale: { x, zoom } } = $$;
    const fn = config.zoom_enabled && zoom ? zoom : x;
    let value = $$.getBaseValue(d);
    if (axis.isTimeSeries()) {
      value = parseDate.call($$, value);
    } else if (axis.isCategorized() && isString(value)) {
      value = config.axis_x_categories.indexOf(value);
    }
    return fn(value);
  },
  yv(d) {
    const $$ = this;
    const { scale: { y, y2 } } = $$;
    const yScale = d.axis && d.axis === "y2" ? y2 : y;
    return yScale($$.getBaseValue(d));
  },
  subxx(d) {
    return d ? this.scale.subX(d.x) : null;
  }
});

;// ./src/canvas/util.ts

const DENSE_SCATTER_POINT_CULL_THRESHOLD = 1e5;
function getFontSize(font) {
  const match = /(\d+(?:\.\d+)?)px/.exec(font);
  const size = match ? parseFloat(match[1]) : parseFloat(font);
  return Number.isFinite(size) ? size : 12;
}
function getCanvasShapeIndices($$, shape, type, typeFilter) {
  return shape.indices[type] || $$.getShapeIndices(typeFilter);
}
function isCanvasTargetSupported($$, target, groupedTypeFilters = []) {
  var _a;
  const id = typeof target === "string" ? target : target == null ? void 0 : target.id;
  return !((_a = $$.isGrouped) == null ? void 0 : _a.call($$, id)) || groupedTypeFilters.some((filter) => filter($$, target));
}
function getCanvasTargetType(config, target) {
  var _a;
  const id = typeof target === "string" ? target : target == null ? void 0 : target.id;
  return id && ((_a = config.data_types) == null ? void 0 : _a[id]) || config.data_type || TYPE.LINE;
}
function getCanvasComparableValue(value) {
  const comparable = +value;
  return Number.isFinite(comparable) ? comparable : null;
}
function getCanvasComparableXDomain($$) {
  var _a, _b;
  const domain = (_b = (_a = $$.scale.zoom || $$.scale.x) == null ? void 0 : _a.domain) == null ? void 0 : _b.call(_a);
  const start = getCanvasComparableValue(domain == null ? void 0 : domain[0]);
  const end = getCanvasComparableValue(domain == null ? void 0 : domain[1]);
  return start === null || end === null ? null : [Math.min(start, end), Math.max(start, end)];
}
function getComparableRowX(row) {
  return getCanvasComparableValue(row == null ? void 0 : row.x);
}
function lowerBoundCanvasRows(values, target, ascending) {
  let low = 0;
  let high = values.length;
  while (low < high) {
    const mid = low + high >> 1;
    const value = getComparableRowX(values[mid]);
    if (value === null) {
      return 0;
    }
    if (ascending ? value < target : value > target) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return low;
}
function upperBoundCanvasRows(values, target, ascending) {
  let low = 0;
  let high = values.length;
  while (low < high) {
    const mid = low + high >> 1;
    const value = getComparableRowX(values[mid]);
    if (value === null) {
      return values.length;
    }
    if (ascending ? value <= target : value >= target) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return low;
}
function getCanvasTargetVisibleRange($$, target, padding = 1) {
  const values = (target == null ? void 0 : target.values) || [];
  const fullRange = { start: 0, end: values.length };
  const domain = getCanvasComparableXDomain($$);
  if (!values.length || !domain) {
    return fullRange;
  }
  const state = $$.state;
  const cache = state._canvasVisibleRangeCache || (state._canvasVisibleRangeCache = /* @__PURE__ */ new Map());
  const key = [
    target.id,
    values.length,
    state.dataGeneration,
    domain[0],
    domain[1],
    padding
  ].join(":");
  const cached = cache.get(target.id);
  if ((cached == null ? void 0 : cached.key) === key) {
    return cached.range;
  }
  const first = getComparableRowX(values[0]);
  const last = getComparableRowX(values[values.length - 1]);
  if (first === null || last === null) {
    return fullRange;
  }
  const ascending = first <= last;
  const start = lowerBoundCanvasRows(values, domain[0], ascending);
  const end = upperBoundCanvasRows(values, domain[1], ascending);
  const range = {
    start: Math.max(0, Math.min(start, end) - padding),
    end: Math.min(values.length, Math.max(start, end) + padding)
  };
  cache.set(target.id, { key, range });
  return range;
}
function isCanvasBarType($$, target) {
  return getCanvasTargetType($$.config, target) === TYPE.BAR;
}
function isCanvasAreaType($$, target) {
  return TYPE_BY_CATEGORY.Area.indexOf(getCanvasTargetType($$.config, target)) > -1;
}
function isCanvasLineType($$, target) {
  const type = getCanvasTargetType($$.config, target);
  return TYPE_BY_CATEGORY.Line.indexOf(type) > -1;
}
function isCanvasScatterType($$, target) {
  return getCanvasTargetType($$.config, target) === TYPE.SCATTER;
}
function isCanvasBubbleType($$, target) {
  return getCanvasTargetType($$.config, target) === TYPE.BUBBLE;
}
function isCanvasPointType($$, target) {
  return isCanvasLineType($$, target) || isCanvasScatterType($$, target) || isCanvasBubbleType($$, target);
}
function isCanvasCandlestickType($$, target) {
  return getCanvasTargetType($$.config, target) === TYPE.CANDLESTICK;
}
function isCanvasTreemapType($$, target) {
  return getCanvasTargetType($$.config, target) === TYPE.TREEMAP;
}
function isCanvasGroupedType(config, target) {
  const type = getCanvasTargetType(config, target);
  return type === TYPE.BAR || TYPE_BY_CATEGORY.Area.indexOf(type) > -1;
}
function hasCanvasDrawableValue($$, d) {
  const value = $$.getBaseValue(d);
  return value !== null && value !== void 0;
}
function isFiniteCanvasCoordinate(x, y) {
  return Number.isFinite(x) && Number.isFinite(y);
}
function createCanvasPointOccupancyGrid(width, height, radius) {
  const offset = Math.ceil(radius) + 1;
  const gridWidth = Math.max(1, Math.ceil(width) + offset * 2 + 1);
  const gridHeight = Math.max(1, Math.ceil(height) + offset * 2 + 1);
  return {
    data: new Uint8Array(gridWidth * gridHeight),
    height: gridHeight,
    offset,
    width: gridWidth
  };
}
function markCanvasPointOccupancy(grid, x, y) {
  const px = Math.round(x) + grid.offset;
  const py = Math.round(y) + grid.offset;
  if (px < 0 || px >= grid.width || py < 0 || py >= grid.height) {
    return false;
  }
  const index = py * grid.width + px;
  if (grid.data[index]) {
    return false;
  }
  grid.data[index] = 1;
  return true;
}

;// ./src/canvas/axisTicks.ts




function getAxisTickOption(config, id, key, prefix = `axis_${id}`) {
  const value = config[`${prefix}_tick_${key}`];
  return value !== void 0 ? value : config[`axis_${id}_tick_${key}`];
}
function getOptionTickValues(values, api) {
  const resolved = typeof values === "function" ? values.call(api) : values;
  return (resolved == null ? void 0 : resolved.length) ? resolved : void 0;
}
function normalizeAxisValue($$, value, id) {
  var _a, _b, _c, _d, _e, _f;
  if ((_b = (_a = $$.axis) == null ? void 0 : _a.isTimeSeries) == null ? void 0 : _b.call(_a, id)) {
    return value instanceof Date ? value : parseDate.call($$, value);
  }
  if (id === "x" && ((_d = (_c = $$.axis) == null ? void 0 : _c.isCategorized) == null ? void 0 : _d.call(_c)) && typeof value === "string") {
    const index = $$.config.axis_x_categories.indexOf(value);
    return index >= 0 ? index : value;
  }
  if (((_f = (_e = $$.axis) == null ? void 0 : _e.isLog) == null ? void 0 : _f.call(_e, id)) && value !== null && value !== void 0) {
    return +value;
  }
  return value;
}
function normalizeXValue($$, value) {
  return normalizeAxisValue($$, value, "x");
}
function normalizeYValue($$, value, id = "y") {
  return normalizeAxisValue($$, value, id);
}
function normalizeYTickValues($$, values, id = "y") {
  return values.map((value) => normalizeYValue($$, value, id));
}
function normalizeXTickValues($$, values) {
  return values.map((value) => normalizeXValue($$, value)).filter((value) => {
    var _a, _b;
    return !(typeof value === "string" && ((_b = (_a = $$.axis) == null ? void 0 : _a.isCategorized) == null ? void 0 : _b.call(_a)));
  });
}
function getScaleTicks(scale, count) {
  const tickCount = typeof count === "function" ? count() : count;
  return scale.ticks ? scale.ticks(tickCount) : scale.domain();
}
function getLogScaleTicks(scale, count) {
  const [start, end] = scale.domain();
  const numericStart = +start;
  const numericEnd = +end;
  if (count || !Number.isFinite(numericStart) || !Number.isFinite(numericEnd) || numericEnd <= 0) {
    return getScaleTicks(scale, count);
  }
  const logScale = getScale("_log").domain([numericStart > 0 ? numericStart : 1, numericEnd]).range(scale.range());
  let ticks = logScale.ticks();
  for (let cnt = numericEnd.toFixed().length; ticks.length > 15; cnt--) {
    ticks = logScale.ticks(cnt);
  }
  if (ticks.length) {
    ticks.splice(0, 1, start);
    ticks.splice(ticks.length - 1, 1, end);
  }
  return ticks;
}
function isSameTickValue(a, b) {
  const av = +a;
  const bv = +b;
  return Number.isFinite(av) && Number.isFinite(bv) ? Math.abs(av - bv) < 1e-6 : a === b;
}
function includeDomainEndpoints(ticks, domain) {
  const [start, end] = domain;
  const values = ticks.slice();
  if (start !== void 0 && !values.some((value) => isSameTickValue(value, start))) {
    values.unshift(start);
  }
  if (end !== void 0 && !values.some((value) => isSameTickValue(value, end))) {
    values.push(end);
  }
  return values;
}
function toComparableValue($$, value) {
  const normalized = normalizeXValue($$, value);
  return getCanvasComparableValue(normalized);
}
function hasActiveXZoom($$) {
  var _a, _b, _c, _d, _e, _f, _g, _h;
  const { scale } = $$;
  const zoomDomain = (_b = (_a = scale.zoom) == null ? void 0 : _a.domain) == null ? void 0 : _b.call(_a);
  const xDomain = ((_d = (_c = scale.subX) == null ? void 0 : _c.domain) == null ? void 0 : _d.call(_c)) || ((_f = (_e = scale.x) == null ? void 0 : _e.orgDomain) == null ? void 0 : _f.call(_e)) || ((_h = (_g = scale.x) == null ? void 0 : _g.domain) == null ? void 0 : _h.call(_g));
  if (!(zoomDomain == null ? void 0 : zoomDomain.length) || !(xDomain == null ? void 0 : xDomain.length)) {
    return false;
  }
  return !isSameTickValue(zoomDomain[0], xDomain[0]) || !isSameTickValue(zoomDomain[1], xDomain[1]);
}
function getXScale($$) {
  return hasActiveXZoom($$) ? $$.scale.zoom : $$.scale.x;
}
function isInCurrentXDomain($$, value, tolerance = 0) {
  var _a, _b;
  const domain = (_b = (_a = getXScale($$)).domain) == null ? void 0 : _b.call(_a);
  if (!(domain == null ? void 0 : domain.length)) {
    return true;
  }
  const target = toComparableValue($$, value);
  const min = +domain[0];
  const max = +domain[1];
  if (target === null || !Number.isFinite(min) || !Number.isFinite(max)) {
    return true;
  }
  return target >= Math.min(min, max) - tolerance && target <= Math.max(min, max) + tolerance;
}
function getHalfNeighborDistance(comparableValues, index) {
  const distances = [
    index > 0 ? Math.abs(comparableValues[index] - comparableValues[index - 1]) : Infinity,
    index < comparableValues.length - 1 ? Math.abs(comparableValues[index + 1] - comparableValues[index]) : Infinity
  ].filter(Number.isFinite);
  const distance = Math.min(...distances);
  return Number.isFinite(distance) ? distance / 2 : 0;
}
function lowerBoundNumbers(values, target) {
  let low = 0;
  let high = values.length;
  while (low < high) {
    const mid = low + high >> 1;
    if (values[mid] < target) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return low;
}
function upperBoundNumbers(values, target) {
  let low = 0;
  let high = values.length;
  while (low < high) {
    const mid = low + high >> 1;
    if (values[mid] <= target) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return low;
}
function getCachedXDataTicks($$, targets) {
  var _a;
  const { axis, state } = $$;
  const key = [
    state.dataGeneration,
    ((_a = axis == null ? void 0 : axis.isTimeSeries) == null ? void 0 : _a.call(axis)) ? 1 : 0,
    targets.map((target) => `${target.id}:${target.values.length}`).join(",")
  ].join("|");
  const cached = state._canvasXDataTickCache;
  if ((cached == null ? void 0 : cached.key) === key) {
    return cached;
  }
  const values = $$.mapTargetsToUniqueXs(targets);
  const entry = {
    key,
    values,
    comparable: values.map((value) => {
      var _a2;
      return (_a2 = toComparableValue($$, value)) != null ? _a2 : NaN;
    })
  };
  state._canvasXDataTickCache = entry;
  return entry;
}
function filterXDataTicksForZoom($$, dataTicks) {
  const { values: ticks, comparable } = dataTicks;
  if (!hasActiveXZoom($$)) {
    return ticks;
  }
  const domain = getCanvasComparableXDomain($$);
  if (!domain || comparable.length !== ticks.length || !Number.isFinite(comparable[0])) {
    return ticks.filter((value) => isInCurrentXDomain($$, value));
  }
  const [start, end] = domain;
  let startIndex = lowerBoundNumbers(comparable, start);
  let endIndex = upperBoundNumbers(comparable, end);
  const includeNearest = (edge) => {
    const index = lowerBoundNumbers(comparable, edge);
    let nearestIndex = -1;
    let nearestDistance = Infinity;
    for (const candidate of [index - 1, index]) {
      const value = comparable[candidate];
      const distance = Math.abs(value - edge);
      if (distance < nearestDistance) {
        nearestDistance = distance;
        nearestIndex = candidate;
      }
    }
    if (nearestIndex > -1 && nearestIndex < comparable.length && nearestDistance <= getHalfNeighborDistance(comparable, nearestIndex) + 1e-6) {
      startIndex = Math.min(startIndex, nearestIndex);
      endIndex = Math.max(endIndex, nearestIndex + 1);
    }
  };
  includeNearest(start);
  includeNearest(end);
  return ticks.slice(
    Math.max(0, startIndex),
    Math.min(ticks.length, endIndex)
  );
}
function getTickOptionCacheKey(values, generation) {
  if (typeof values === "function") {
    return `fn:${generation}`;
  }
  return Array.isArray(values) ? values.map((value) => value instanceof Date ? +value : String(value)).join(",") : "";
}
function getXTickCacheKey($$, cull) {
  var _a, _b, _c;
  const { config, state } = $$;
  const domain = ((_b = (_a = getXScale($$)).domain) == null ? void 0 : _b.call(_a)) || [];
  const domainKey = domain.map((value) => value instanceof Date ? +value : String(value)).join(",");
  const size = config.axis_rotated ? state.height : state.width;
  return [
    cull ? 1 : 0,
    state.dataGeneration,
    domainKey,
    size,
    config.axis_x_tick_fit ? 1 : 0,
    config.axis_x_tick_count || "",
    config.axis_x_tick_culling,
    config.axis_x_tick_culling_max || "",
    config.axis_x_tick_culling_reverse ? 1 : 0,
    ((_c = config.axis_x_categories) == null ? void 0 : _c.length) || 0,
    getTickOptionCacheKey(config.axis_x_tick_values, state.redrawGeneration)
  ].join("|");
}
function generateTickValues($$, values, count, forTimeSeries = false) {
  var _a;
  return ((_a = $$.axis) == null ? void 0 : _a.generateTickValues) ? $$.axis.generateTickValues(values, count, forTimeSeries) : values;
}
function getStepTicks(domain, stepSize) {
  const [start, end] = domain;
  const ticks = [];
  if (!stepSize || !Number.isFinite(stepSize)) {
    return ticks;
  }
  for (let value = Math.round(start); value <= end; value += stepSize) {
    ticks.push(value);
  }
  return ticks;
}
function getXTickValues($$, cull = true) {
  var _a, _b, _c, _d, _e, _f, _g;
  const { axis, config } = $$;
  const targetScale = getXScale($$);
  const targetsToShow = ((_a = $$.getTargetsToShow) == null ? void 0 : _a.call($$)) || $$.filterTargetsToShow();
  const cache = $$.state._canvasXTickValuesCache || ($$.state._canvasXTickValuesCache = /* @__PURE__ */ new Map());
  const cacheKey = getXTickCacheKey($$, cull);
  const cached = cache.get(cacheKey);
  if (cached) {
    return cached;
  }
  const setCache = (ticks) => {
    cache.set(cacheKey, ticks);
    return ticks;
  };
  if (!(targetsToShow == null ? void 0 : targetsToShow.length)) {
    return setCache([]);
  }
  const explicit = getOptionTickValues(config.axis_x_tick_values, $$.api);
  if (explicit) {
    const values = normalizeXTickValues($$, explicit);
    return setCache(cull ? cullDataTicks($$, values) : values);
  }
  if (config.axis_x_tick_fit && (targetsToShow == null ? void 0 : targetsToShow.length) && $$.mapTargetsToUniqueXs) {
    const dataTicks = getCachedXDataTicks($$, targetsToShow);
    const values = filterXDataTicksForZoom($$, dataTicks);
    const generated2 = generateTickValues(
      $$,
      values,
      config.axis_x_tick_count,
      (_b = axis == null ? void 0 : axis.isTimeSeries) == null ? void 0 : _b.call(axis)
    );
    return setCache(cull ? cullDataTicks($$, generated2, true) : generated2);
  }
  if (hasActiveXZoom($$) && !((_c = axis == null ? void 0 : axis.isCategorized) == null ? void 0 : _c.call(axis))) {
    const domain = ((_e = (_d = $$.zoom) == null ? void 0 : _d.getDomain) == null ? void 0 : _e.call(_d)) || targetScale.domain();
    const generated2 = includeDomainEndpoints(
      getScaleTicks(targetScale, config.axis_x_tick_count || AXIS_DEFAULT_TICK_COUNT),
      domain
    );
    return setCache(cull ? cullTicks(generated2, getXTickCullMax($$)) : generated2);
  }
  if (((_f = axis == null ? void 0 : axis.isCategorized) == null ? void 0 : _f.call(axis)) && ((_g = config.axis_x_categories) == null ? void 0 : _g.length)) {
    const generated2 = config.axis_x_categories.map((_, i) => i);
    return setCache(cull ? cullTicks(generated2, getXTickCullMax($$)) : generated2);
  }
  const generated = getScaleTicks(
    targetScale,
    config.axis_x_tick_count || AXIS_DEFAULT_TICK_COUNT
  );
  return setCache(cull ? cullTicks(generated, getXTickCullMax($$)) : generated);
}
function getSubXTickCullMax($$) {
  const { config, state: { height2, width2 } } = $$;
  const size = config.axis_rotated ? height2 : width2;
  const count = getAxisTickOption(config, "x", "count", "subchart_axis_x");
  const culling = getAxisTickOption(config, "x", "culling", "subchart_axis_x");
  const cullingMax = getAxisTickOption(config, "x", "culling_max", "subchart_axis_x");
  if (count) {
    return count;
  }
  if (culling !== false) {
    return Math.min(
      cullingMax || AXIS_DEFAULT_TICK_COUNT,
      Math.max(2, Math.floor(size / 70))
    );
  }
  return void 0;
}
function getSubXTickValues($$, culling = true) {
  var _a, _b, _c, _d;
  const { axis, config, scale } = $$;
  const targetScale = scale.subX;
  const targetsToShow = ((_a = $$.getTargetsToShow) == null ? void 0 : _a.call($$)) || $$.filterTargetsToShow();
  const tickCount = getAxisTickOption(config, "x", "count", "subchart_axis_x");
  const cullMax = getSubXTickCullMax($$);
  const cullData = (ticks, sorted = false) => culling ? cullDataTicks($$, ticks, sorted, "subchart_axis_x", cullMax) : ticks;
  if (!targetScale || !(targetsToShow == null ? void 0 : targetsToShow.length)) {
    return [];
  }
  const explicit = getOptionTickValues(
    getAxisTickOption(config, "x", "values", "subchart_axis_x"),
    $$.api
  );
  if (explicit) {
    return cullData(normalizeXTickValues($$, explicit));
  }
  if (config.axis_x_tick_fit && $$.mapTargetsToUniqueXs) {
    const generated2 = generateTickValues(
      $$,
      $$.mapTargetsToUniqueXs(targetsToShow),
      tickCount,
      (_b = axis == null ? void 0 : axis.isTimeSeries) == null ? void 0 : _b.call(axis)
    );
    return cullData(generated2, true);
  }
  if (((_c = axis == null ? void 0 : axis.isCategorized) == null ? void 0 : _c.call(axis)) && ((_d = config.axis_x_categories) == null ? void 0 : _d.length)) {
    return cullData(config.axis_x_categories.map((_, i) => i), true);
  }
  const generated = getScaleTicks(
    targetScale,
    tickCount || AXIS_DEFAULT_TICK_COUNT
  );
  return cullData(generated, true);
}
function getCategoryXTickLineValues($$, targetScale = getXScale($$), outerTick = $$.config.axis_x_tick_outer) {
  var _a, _b;
  const scale = targetScale;
  const domain = ((_a = scale.orgDomain) == null ? void 0 : _a.call(scale)) || ((_b = scale.domain) == null ? void 0 : _b.call(scale));
  if (!(domain == null ? void 0 : domain.length)) {
    return [];
  }
  const start = +domain[0];
  const end = +domain[domain.length - 1];
  if (!Number.isFinite(start) || !Number.isFinite(end)) {
    return [];
  }
  const min = Math.ceil(Math.min(start, end));
  const max = Math.floor(Math.max(start, end));
  const values = Array.from({ length: Math.max(0, max - min + 1) }, (_, i) => min + i);
  return outerTick ? values.slice(1, -1) : values;
}
function getXTickLinePosition($$, value, targetScale = getXScale($$)) {
  var _a, _b, _c, _d, _e;
  const scale = targetScale;
  const normalized = normalizeXValue($$, value);
  if ((_b = (_a = $$.axis) == null ? void 0 : _a.isCategorized) == null ? void 0 : _b.call(_a)) {
    const rawScale = (_c = scale.orgScale) == null ? void 0 : _c.call(scale);
    if (rawScale) {
      return rawScale(normalized);
    }
    const offset = ((_e = (_d = $$.axis.x) == null ? void 0 : _d.tickOffset) == null ? void 0 : _e.call(_d)) || (scale(1) - scale(0)) / 2;
    return scale(normalized) - offset;
  }
  return scale(normalized);
}
function hasOverlappedXTickLineIntervals($$, ticks, tickLineWidth, targetScale = getXScale($$)) {
  if (ticks.length < 2) {
    return false;
  }
  const halfWidth = Math.max(1, tickLineWidth) / 2;
  const positions = ticks.map((tick) => getXTickLinePosition($$, tick, targetScale)).filter(Number.isFinite).sort((a, b) => a - b);
  if (positions.length < 2) {
    return false;
  }
  let previousEnd = positions[0] + halfWidth;
  for (let i = 1; i < positions.length; i++) {
    const start = positions[i] - halfWidth;
    const end = positions[i] + halfWidth;
    if (start <= previousEnd + AXIS_TICK_LINE_OVERLAP_PADDING) {
      return true;
    }
    previousEnd = Math.max(previousEnd, end);
  }
  return false;
}
function dedupeXTickLineValues($$, ticks, targetScale = getXScale($$)) {
  const seen = /* @__PURE__ */ new Set();
  return ticks.filter((tick) => {
    const pos = getXTickLinePosition($$, tick, targetScale);
    const key = Math.round(pos);
    if (!Number.isFinite(pos) || seen.has(key)) {
      return false;
    }
    seen.add(key);
    return true;
  });
}
function getXTickLineValues($$, textTicks, tickLineWidth = 1) {
  var _a;
  const { axis, config } = $$;
  if ((_a = axis == null ? void 0 : axis.isCategorized) == null ? void 0 : _a.call(axis)) {
    const categoryLineTicks = getCategoryXTickLineValues($$);
    return dedupeXTickLineValues($$, categoryLineTicks);
  }
  if (config.axis_x_tick_culling === false || config.axis_x_tick_culling_lines === false) {
    return textTicks;
  }
  const lineTicks = getXTickValues($$, false);
  return hasOverlappedXTickLineIntervals($$, lineTicks, tickLineWidth) ? textTicks : dedupeXTickLineValues($$, lineTicks);
}
function getSubXTickLineValues($$, textTicks, tickLineWidth = 1) {
  var _a;
  const { axis, config, scale } = $$;
  const targetScale = scale.subX;
  const culling = getAxisTickOption(config, "x", "culling", "subchart_axis_x");
  const cullingLines = getAxisTickOption(config, "x", "culling_lines", "subchart_axis_x");
  const outerTick = getAxisTickOption(config, "x", "outer", "subchart_axis_x");
  if (!targetScale) {
    return [];
  }
  if ((_a = axis == null ? void 0 : axis.isCategorized) == null ? void 0 : _a.call(axis)) {
    const categoryLineTicks = getCategoryXTickLineValues($$, targetScale, outerTick);
    return dedupeXTickLineValues($$, categoryLineTicks, targetScale);
  }
  if (culling === false || cullingLines === false) {
    return textTicks;
  }
  const lineTicks = getSubXTickValues($$, false);
  return hasOverlappedXTickLineIntervals($$, lineTicks, tickLineWidth, targetScale) ? textTicks : dedupeXTickLineValues($$, lineTicks, targetScale);
}
function getYTickValues($$, id = "y", count, culling = true, targetScale = $$.scale[id], optionPrefix = `axis_${id}`) {
  var _a, _b, _c;
  const { axis, config } = $$;
  const prefix = `axis_${id}`;
  const explicit = getOptionTickValues(
    getAxisTickOption(config, id, "values", optionPrefix),
    $$.api
  );
  const maybeCull = (ticks) => culling ? cullAxisTicks($$, id, ticks, optionPrefix) : ticks;
  if (explicit) {
    return maybeCull(normalizeYTickValues($$, explicit, id));
  }
  const stepTicks = getStepTicks(targetScale.domain(), config[`${prefix}_tick_stepSize`]);
  if (stepTicks.length) {
    return maybeCull(stepTicks);
  }
  const tickCount = count != null ? count : getAxisTickOption(config, id, "count", optionPrefix);
  if (((_a = axis == null ? void 0 : axis.isTimeSeries) == null ? void 0 : _a.call(axis, id)) && config[`${prefix}_tick_time_value`]) {
    return maybeCull(getScaleTicks(targetScale, config[`${prefix}_tick_time_value`]));
  }
  if ((_b = axis == null ? void 0 : axis.isLog) == null ? void 0 : _b.call(axis, id)) {
    return maybeCull(getLogScaleTicks(targetScale, tickCount));
  }
  if (tickCount) {
    const domain = targetScale.domain();
    return maybeCull(generateTickValues(
      $$,
      domain,
      domain.every((v) => v === 0) ? 1 : tickCount,
      (_c = axis == null ? void 0 : axis.isTimeSeries) == null ? void 0 : _c.call(axis, id)
    ));
  }
  return maybeCull(getScaleTicks(targetScale, AXIS_DEFAULT_TICK_COUNT));
}
function getAdditionalAxisScale($$, id, axisConfig) {
  const baseScale = id === "x" ? getXScale($$) : $$.scale[id];
  const scale = (baseScale == null ? void 0 : baseScale.copy) ? baseScale.copy() : baseScale;
  if (axisConfig.domain && (scale == null ? void 0 : scale.domain)) {
    scale.domain(axisConfig.domain);
  }
  return scale;
}
function getAdditionalAxisTickValues($$, id, scale, axisConfig) {
  var _a, _b, _c;
  const tick = axisConfig.tick || {};
  const explicit = getOptionTickValues(tick.values, $$.api);
  if (explicit) {
    return id === "x" ? normalizeXTickValues($$, explicit) : normalizeYTickValues($$, explicit, id);
  }
  if (id !== "x" && ((_b = (_a = $$.axis) == null ? void 0 : _a.isLog) == null ? void 0 : _b.call(_a, id))) {
    return getLogScaleTicks(scale, tick.count);
  }
  return getScaleTicks(scale, (_c = tick.count) != null ? _c : AXIS_DEFAULT_TICK_COUNT);
}
function getAdditionalAxisTickFormat($$, axisConfig) {
  var _a;
  const format = (_a = axisConfig.tick) == null ? void 0 : _a.format;
  return typeof format === "function" ? format.bind($$.api) : ((value) => value);
}
function cullTicks(ticks, count) {
  const len = ticks.length - 1;
  if (count && len > count) {
    const last = ticks.length - 1;
    if (count <= 1) {
      return [ticks[0]];
    }
    return Array.from({ length: count }, (_, i) => ticks[Math.round(i * last / (count - 1))]);
  }
  return ticks;
}
function cullAxisTicks($$, id, ticks, optionPrefix = `axis_${id}`) {
  const { config } = $$;
  const culling = getAxisTickOption(config, id, "culling", optionPrefix);
  if (!culling) {
    return ticks;
  }
  const cullingMax = getAxisTickOption(config, id, "culling_max", optionPrefix) || AXIS_DEFAULT_TICK_COUNT;
  const reverse = getAxisTickOption(config, id, "culling_reverse", optionPrefix);
  const sortedTicks = ticks.slice().sort((a, b) => {
    const av = +a;
    const bv = +b;
    const order = Number.isFinite(av) && Number.isFinite(bv) ? av - bv : String(a).localeCompare(String(b));
    return reverse ? -order : order;
  });
  const tickSize = sortedTicks.length;
  let intervalForCulling = 0;
  for (let i = 1; i < tickSize; i++) {
    if (tickSize / i < cullingMax) {
      intervalForCulling = i;
      break;
    }
  }
  if (!intervalForCulling) {
    return ticks;
  }
  const visible = new Set(
    sortedTicks.filter((_, i) => i % intervalForCulling === 0)
  );
  return ticks.filter((tick) => visible.has(tick));
}
function cullDataTicks($$, ticks, sorted = false, optionPrefix = "axis_x", max) {
  const { config } = $$;
  const culling = getAxisTickOption(config, "x", "culling", optionPrefix);
  if (culling === false) {
    return ticks;
  }
  const cullingMax = max || getAxisTickOption(config, "x", "culling_max", optionPrefix) || AXIS_DEFAULT_TICK_COUNT;
  const reverse = getAxisTickOption(config, "x", "culling_reverse", optionPrefix);
  const sortedTicks = sorted ? ticks : ticks.slice().sort((a, b) => {
    const av = +a;
    const bv = +b;
    if (Number.isFinite(av) && Number.isFinite(bv)) {
      return reverse ? bv - av : av - bv;
    }
    return reverse ? String(b).localeCompare(String(a)) : String(a).localeCompare(String(b));
  });
  const tickSize = sortedTicks.length;
  let intervalForCulling = 0;
  for (let i = 1; i < tickSize; i++) {
    if (tickSize / i < cullingMax) {
      intervalForCulling = i;
      break;
    }
  }
  if (!intervalForCulling) {
    return ticks;
  }
  if (sorted) {
    return ticks.filter(
      (_, i) => reverse ? (tickSize - 1 - i) % intervalForCulling === 0 : i % intervalForCulling === 0
    );
  }
  const visible = new Set(
    sortedTicks.filter((_, i) => i % intervalForCulling === 0)
  );
  return ticks.filter((tick) => visible.has(tick));
}
function getXTickCullMax($$) {
  const { config, state: { height, width } } = $$;
  const size = config.axis_rotated ? height : width;
  if (config.axis_x_tick_count) {
    return config.axis_x_tick_count;
  }
  if (config.axis_x_tick_culling !== false) {
    return Math.min(
      config.axis_x_tick_culling_max || AXIS_DEFAULT_TICK_COUNT,
      Math.max(2, Math.floor(size / 70))
    );
  }
  return void 0;
}
function getYGridTickValues($$) {
  var _a, _b;
  const { axis, config } = $$;
  const generated = (_b = (_a = axis == null ? void 0 : axis.y) == null ? void 0 : _a.getGeneratedTicks) == null ? void 0 : _b.call(_a, config.grid_y_ticks);
  if (generated == null ? void 0 : generated.length) {
    return generated;
  }
  return config.grid_y_ticks ? cullTicks(getYTickValues($$, "y", void 0, false), config.grid_y_ticks) : getYTickValues($$, "y", void 0, false);
}

;// ./src/canvas/CanvasPainter.ts
var CanvasPainter_defProp = Object.defineProperty;
var CanvasPainter_defNormalProp = (obj, key, value) => key in obj ? CanvasPainter_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => CanvasPainter_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);

class CanvasPainter {
  /**
   * Constructor.
   * @param {CanvasRenderingContext2D} ctx Canvas drawing context
   * @private
   */
  constructor(ctx) {
    __publicField(this, "ctx", ctx);
  }
  /**
   * Get current drawing context.
   * @returns {CanvasRenderingContext2D} Canvas drawing context
   * @private
   */
  get context() {
    return this.ctx;
  }
  /**
   * Run a draw operation on another canvas context.
   * @param {CanvasRenderingContext2D} ctx Canvas drawing context
   * @param {function} draw Draw callback
   * @private
   */
  withContext(ctx, draw) {
    const prev = this.ctx;
    this.ctx = ctx;
    try {
      draw();
    } finally {
      this.ctx = prev;
    }
  }
  /**
   * Run a draw operation in an isolated canvas state.
   * @param {DrawCallback} draw Draw callback
   * @private
   */
  withState(draw) {
    const { ctx } = this;
    ctx.save();
    try {
      draw(ctx);
    } finally {
      ctx.restore();
    }
  }
  /**
   * Run a draw operation with a translated origin.
   * @param {number} x Translation x
   * @param {number} y Translation y
   * @param {DrawCallback} draw Draw callback
   * @private
   */
  withTranslation(x, y, draw) {
    this.withState((ctx) => {
      ctx.translate(x, y);
      draw(ctx);
    });
  }
  /**
   * Run a draw operation clipped to a rectangle.
   * @param {object} rect Clip rectangle
   * @param {DrawCallback} draw Draw callback
   * @private
   */
  clipRect(rect, draw) {
    this.withState((ctx) => {
      ctx.beginPath();
      ctx.rect(rect.x, rect.y, rect.w, rect.h);
      ctx.clip();
      draw(ctx);
    });
  }
  /**
   * Measure text using the current canvas state.
   * @param {string} text Text value
   * @returns {TextMetrics} Text metrics
   * @private
   */
  measureText(text) {
    return this.ctx.measureText(text);
  }
  /**
   * Add a line segment to the current path.
   * @param {number} x1 Start x
   * @param {number} y1 Start y
   * @param {number} x2 End x
   * @param {number} y2 End y
   * @private
   */
  traceLine(x1, y1, x2, y2) {
    const { ctx } = this;
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
  }
  /**
   * Add a crisp line segment to the current path.
   * @param {number} x1 Start x
   * @param {number} y1 Start y
   * @param {number} x2 End x
   * @param {number} y2 End y
   * @param {number} lineWidth Stroke width
   * @private
   */
  traceCrispLine(x1, y1, x2, y2, lineWidth) {
    this.traceLine(
      this.crisp(x1, lineWidth),
      this.crisp(y1, lineWidth),
      this.crisp(x2, lineWidth),
      this.crisp(y2, lineWidth)
    );
  }
  /**
   * Add a circle to the current path.
   * @param {number} x Center x
   * @param {number} y Center y
   * @param {number} r Radius
   * @private
   */
  traceCircle(x, y, r) {
    this.ctx.moveTo(x + r, y);
    this.ctx.arc(x, y, r, 0, Math.PI * 2);
  }
  /**
   * Stroke a path.
   * @param {DrawCallback} draw Path callback
   * @param {object} style Optional style
   * @private
   */
  strokePath(draw, style) {
    this.withStyle(style, (ctx) => {
      ctx.beginPath();
      draw(ctx);
      ctx.stroke();
    });
  }
  /**
   * Fill a path.
   * @param {DrawCallback} draw Path callback
   * @param {object} style Optional style
   * @private
   */
  fillPath(draw, style) {
    this.withStyle(style, (ctx) => {
      ctx.beginPath();
      draw(ctx);
      ctx.fill();
    });
  }
  /**
   * Fill a rectangle.
   * @param {object} rect Rectangle
   * @param {object} style Optional style
   * @private
   */
  fillRect(rect, style) {
    this.withStyle(style, (ctx) => {
      ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
    });
  }
  /**
   * Fill a rectangle with optional corner radii.
   * @param {object} rect Rectangle
   * @param {number|object} radius Corner radius
   * @param {object} style Optional style
   * @private
   */
  fillRoundRect(rect, radius = 0, style) {
    const normalized = this.normalizeRect(rect);
    const corners = this.getRectRadii(normalized, radius);
    if (!corners.tl && !corners.tr && !corners.br && !corners.bl) {
      this.fillRect(normalized, style);
      return;
    }
    this.fillPath((ctx) => {
      this.traceRoundRect(ctx, normalized, corners);
    }, style);
  }
  /**
   * Stroke a rectangle with optional corner radii.
   * @param {object} rect Rectangle
   * @param {number|object} radius Corner radius
   * @param {object} style Optional style
   * @private
   */
  strokeRoundRect(rect, radius = 0, style) {
    const normalized = this.normalizeRect(rect);
    const corners = this.getRectRadii(normalized, radius);
    if (!corners.tl && !corners.tr && !corners.br && !corners.bl) {
      this.strokeRect(normalized, style);
      return;
    }
    this.strokePath((ctx) => {
      this.traceRoundRect(ctx, normalized, corners);
    }, style);
  }
  /**
   * Stroke a rectangle.
   * @param {object} rect Rectangle
   * @param {object} style Optional style
   * @private
   */
  strokeRect(rect, style) {
    this.withStyle(style, (ctx) => {
      ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
    });
  }
  /**
   * Draw text.
   * @param {string} text Text value
   * @param {number} x X coordinate
   * @param {number} y Y coordinate
   * @param {object} style Optional style
   * @private
   */
  text(text, x, y, style) {
    const fillText = (ctx, textX, textY) => {
      (style == null ? void 0 : style.maxWidth) === void 0 ? ctx.fillText(text, textX, textY) : ctx.fillText(text, textX, textY, style.maxWidth);
    };
    const draw = (ctx) => {
      if (style == null ? void 0 : style.angle) {
        ctx.translate(x, y);
        ctx.rotate(style.angle * Math.PI / 180);
        fillText(ctx, 0, 0);
      } else {
        fillText(ctx, x, y);
      }
    };
    if (style == null ? void 0 : style.angle) {
      this.withState((ctx) => {
        this.applyStyle(style);
        draw(ctx);
      });
    } else {
      this.withStyle(style, draw);
    }
  }
  /**
   * Draw a possibly rotated multiline text block.
   * @param {string} text Text value
   * @param {number} x X coordinate
   * @param {number} y Y coordinate
   * @param {object} style Optional style
   * @private
   */
  textLines(text, x, y, style) {
    this.withState((ctx) => {
      const lines = text.split("\n");
      const lineHeight = getFontSize((style == null ? void 0 : style.font) || ctx.font);
      const firstLineY = lines.length > 1 ? -((lines.length - 1) * lineHeight) : 0;
      this.applyStyle(style);
      ctx.translate(x, y);
      (style == null ? void 0 : style.angle) && ctx.rotate(style.angle * Math.PI / 180);
      lines.forEach((line, i) => {
        const lineY = firstLineY + i * lineHeight;
        (style == null ? void 0 : style.maxWidth) === void 0 ? ctx.fillText(line, 0, lineY) : ctx.fillText(line, 0, lineY, style.maxWidth);
      });
    });
  }
  /**
   * Draw a point shape.
   * @param {string} type Point shape
   * @param {number} x X coordinate
   * @param {number} y Y coordinate
   * @param {number} r Radius
   * @param {object} style Optional style
   * @private
   */
  point(type, x, y, r, style) {
    this.withStyle(style, (ctx) => {
      const shouldFill = !(style == null ? void 0 : style.stroke) || style.fill !== void 0;
      const shouldStroke = (style == null ? void 0 : style.stroke) !== void 0;
      if (type === "rectangle") {
        const size = r * 2;
        const rect = { x: x - r, y: y - r, w: size, h: size };
        shouldFill && ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
        shouldStroke && ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
      } else {
        ctx.beginPath();
        ctx.arc(x, y, r, 0, Math.PI * 2);
        shouldFill && ctx.fill();
        shouldStroke && ctx.stroke();
      }
    });
  }
  /**
   * Normalize rounded rectangle corner radii.
   * @param {object} rect Rectangle
   * @param {number|object} radius Corner radius
   * @returns {object} Corner radii
   * @private
   */
  getRectRadii(rect, radius) {
    const base = typeof radius === "number" ? { tl: radius, tr: radius, br: radius, bl: radius } : {
      tl: radius.tl || 0,
      tr: radius.tr || 0,
      br: radius.br || 0,
      bl: radius.bl || 0
    };
    const max = Math.max(0, Math.min(Math.abs(rect.w), Math.abs(rect.h)) / 2);
    return {
      tl: Math.max(0, Math.min(base.tl, max)),
      tr: Math.max(0, Math.min(base.tr, max)),
      br: Math.max(0, Math.min(base.br, max)),
      bl: Math.max(0, Math.min(base.bl, max))
    };
  }
  /**
   * Add a rounded rectangle to the current path.
   * @param {CanvasRenderingContext2D} ctx Canvas context
   * @param {object} rect Rectangle
   * @param {object} radius Corner radii
   * @private
   */
  traceRoundRect(ctx, rect, radius) {
    const { x, y, w, h } = rect;
    const right = x + w;
    const bottom = y + h;
    ctx.moveTo(x + radius.tl, y);
    ctx.lineTo(right - radius.tr, y);
    radius.tr ? ctx.quadraticCurveTo(right, y, right, y + radius.tr) : ctx.lineTo(right, y);
    ctx.lineTo(right, bottom - radius.br);
    radius.br ? ctx.quadraticCurveTo(right, bottom, right - radius.br, bottom) : ctx.lineTo(right, bottom);
    ctx.lineTo(x + radius.bl, bottom);
    radius.bl ? ctx.quadraticCurveTo(x, bottom, x, bottom - radius.bl) : ctx.lineTo(x, bottom);
    ctx.lineTo(x, y + radius.tl);
    radius.tl ? ctx.quadraticCurveTo(x, y, x + radius.tl, y) : ctx.lineTo(x, y);
    ctx.closePath();
  }
  /**
   * Normalize rectangle coordinates for path drawing.
   * @param {object} rect Rectangle
   * @returns {object} Normalized rectangle
   * @private
   */
  normalizeRect(rect) {
    const x = rect.w < 0 ? rect.x + rect.w : rect.x;
    const y = rect.h < 0 ? rect.y + rect.h : rect.y;
    return {
      x,
      y,
      w: Math.abs(rect.w),
      h: Math.abs(rect.h)
    };
  }
  /**
   * Apply drawing style.
   * @param {object} style Drawing style
   * @private
   */
  applyStyle(style) {
    if (!style) {
      return;
    }
    const { ctx } = this;
    style.fill !== void 0 && (ctx.fillStyle = style.fill);
    style.stroke !== void 0 && (ctx.strokeStyle = style.stroke);
    style.lineWidth !== void 0 && (ctx.lineWidth = style.lineWidth);
    style.alpha !== void 0 && (ctx.globalAlpha = style.alpha);
    style.font !== void 0 && (ctx.font = style.font);
    style.textAlign !== void 0 && (ctx.textAlign = style.textAlign);
    style.textBaseline !== void 0 && (ctx.textBaseline = style.textBaseline);
    style.lineDash !== void 0 && ctx.setLineDash(style.lineDash);
  }
  /**
   * Run with optional style state.
   * @param {object} style Optional drawing style
   * @param {DrawCallback} draw Draw callback
   * @private
   */
  withStyle(style, draw) {
    if (style) {
      this.withState((ctx) => {
        this.applyStyle(style);
        draw(ctx);
      });
    } else {
      draw(this.ctx);
    }
  }
  /**
   * Get crisp canvas coordinate for axis/grid strokes.
   * @param {number} value Coordinate value
   * @param {number} lineWidth Stroke width
   * @returns {number} Crisp coordinate
   * @private
   */
  crisp(value, lineWidth) {
    return lineWidth % 2 ? Math.round(value) + 0.5 : Math.round(value);
  }
}

;// ./src/canvas/CanvasAxisRenderer.ts
var CanvasAxisRenderer_defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var CanvasAxisRenderer_getOwnPropSymbols = Object.getOwnPropertySymbols;
var CanvasAxisRenderer_hasOwnProp = Object.prototype.hasOwnProperty;
var CanvasAxisRenderer_propIsEnum = Object.prototype.propertyIsEnumerable;
var CanvasAxisRenderer_defNormalProp = (obj, key, value) => key in obj ? CanvasAxisRenderer_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var CanvasAxisRenderer_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (CanvasAxisRenderer_hasOwnProp.call(b, prop))
      CanvasAxisRenderer_defNormalProp(a, prop, b[prop]);
  if (CanvasAxisRenderer_getOwnPropSymbols)
    for (var prop of CanvasAxisRenderer_getOwnPropSymbols(b)) {
      if (CanvasAxisRenderer_propIsEnum.call(b, prop))
        CanvasAxisRenderer_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var CanvasAxisRenderer_publicField = (obj, key, value) => CanvasAxisRenderer_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);




const X_AXIS_TICK_TEXT_HORIZONTAL_CLIP_PADDING = 20;
const X_AXIS_TICK_TEXT_VERTICAL_CLIP_PADDING = 15;
function getXTickTextDirection(isRotated) {
  return isRotated ? -1 : 1;
}
function getYTickTextDirection(isRotated, isY2) {
  return isRotated ? isY2 ? -1 : 1 : isY2 ? 1 : -1;
}
function getSubYTickFormat($$, id) {
  var _a, _b, _c;
  const subAxisId = id === "y2" ? "subY2" : "subY";
  const axisFormat = (_c = (_b = (_a = $$.axis) == null ? void 0 : _a[subAxisId]) == null ? void 0 : _b.tickFormat) == null ? void 0 : _c.call(_b);
  const configFormat = $$.config[`subchart_axis_${id}_tick_format`] || $$.config[`axis_${id}_tick_format`];
  if (axisFormat) {
    return axisFormat;
  }
  return typeof configFormat === "function" ? configFormat.bind($$.api) : ((v) => v);
}
function getGridLineCanvasStyle(style) {
  return style ? {
    stroke: style.lineColor,
    lineWidth: style.lineWidth,
    lineDash: style.dashArray
  } : void 0;
}
function getGridTextCanvasStyle(style) {
  return style ? {
    fill: style.labelColor,
    font: style.labelFont
  } : void 0;
}
function getHorizontalXAxisClipRect(margin, width, height) {
  return {
    x: margin.left - X_AXIS_TICK_TEXT_HORIZONTAL_CLIP_PADDING,
    y: 0,
    w: width + X_AXIS_TICK_TEXT_HORIZONTAL_CLIP_PADDING * 2,
    h: height
  };
}
function getRotatedXAxisClipRect(margin, width, height) {
  return {
    x: 0,
    y: margin.top - X_AXIS_TICK_TEXT_VERTICAL_CLIP_PADDING,
    w: width,
    h: height + X_AXIS_TICK_TEXT_VERTICAL_CLIP_PADDING * 2
  };
}
function getAxisTooltipBackgroundColor($$, id) {
  var _a, _b;
  const bgColor = (_b = (_a = $$.config.axis_tooltip) == null ? void 0 : _a.backgroundColor) != null ? _b : "black";
  return typeof bgColor === "string" ? bgColor : (bgColor == null ? void 0 : bgColor[id]) || null;
}
function formatAxisTooltipValue($$, id, value) {
  var _a, _b;
  const scale = $$.scale[id];
  if (!(scale == null ? void 0 : scale.invert)) {
    return null;
  }
  const scaleValue = scale.invert(value);
  if (scaleValue === null || scaleValue === void 0) {
    return null;
  }
  if (id === "x" && ((_b = (_a = $$.axis) == null ? void 0 : _a.isTimeSeries) == null ? void 0 : _b.call(_a))) {
    return $$.format.xAxisTick(scaleValue);
  }
  const numeric = Number(scaleValue);
  return Number.isFinite(numeric) ? numeric.toFixed(2) : `${scaleValue}`;
}
function getAxisLabelBasePosition($$, id) {
  const { config, state: { height, margin, width } } = $$;
  const isRotated = config.axis_rotated;
  const base = {
    x: margin.left,
    y: margin.top
  };
  if (id === "x") {
    !isRotated && (base.y += height);
  } else if (id === "y") {
    isRotated && (base.y += height);
  } else if (isRotated) {
    base.y -= 1;
  } else {
    base.x += width;
  }
  return base;
}
function getAxisLabelCanvasPosition(base, localX, localY, isRotated) {
  return isRotated ? {
    x: base.x + localY,
    y: base.y - localX
  } : {
    x: base.x + localX,
    y: base.y + localY
  };
}
function formatTick(format, tick) {
  const value = format ? format(tick) : tick;
  return value == null ? "" : String(value);
}
function getAxisTickFont(axisStyle, id) {
  return axisStyle[`${id}TickFont`] || axisStyle.labelFont;
}
function getXTickTextLineHeight(painter, fontSize) {
  const metrics = painter.measureText("0");
  const fontBoxHeight = (metrics.fontBoundingBoxAscent || 0) + (metrics.fontBoundingBoxDescent || 0);
  const actualBoxHeight = (metrics.actualBoundingBoxAscent || 0) + (metrics.actualBoundingBoxDescent || 0);
  const svgFallbackHeight = (fontSize || 10) * (11.5 / 10);
  return Math.max(fontSize, fontBoxHeight, actualBoxHeight, svgFallbackHeight);
}
function getRotatedXTickTextY(rotate) {
  const r2 = rotate / 15;
  return 11.5 - 2.5 * r2 * (rotate > 0 ? 1 : -1);
}
function getRotatedXTickTextDx(rotate) {
  return 8 * Math.sin(Math.PI * (rotate / 180));
}
function resolveTextOffset(value, fontSize) {
  if (typeof value === "number") {
    return value;
  }
  if (typeof value === "string") {
    const parsed = parseFloat(value);
    if (!Number.isFinite(parsed)) {
      return 0;
    }
    return /em$/.test(value.trim()) ? parsed * fontSize : parsed;
  }
  return 0;
}
function splitTickTextByWidth(text, width, painter) {
  if (!width) {
    return [text];
  }
  const charWidth = painter.measureText("0").width || 5.5;
  function split(lines, value) {
    let spaceIndex;
    for (let i = 1; i < value.length; i++) {
      if (value.charAt(i) === " ") {
        spaceIndex = i;
      }
      if (width < charWidth * (i + 1)) {
        const splitIndex = spaceIndex || i;
        return split(
          lines.concat(value.slice(0, splitIndex)),
          value.slice(spaceIndex ? spaceIndex + 1 : i)
        );
      }
    }
    return lines.concat(value);
  }
  return split([], text);
}
function getXTickTextWidth($$, ticks, isRotated, targetScale) {
  var _a, _b;
  const configured = $$.config.axis_x_tick_width;
  if (configured && configured > 0) {
    return configured;
  }
  if (isRotated) {
    return 95;
  }
  if (((_b = (_a = $$.axis) == null ? void 0 : _a.isCategorized) == null ? void 0 : _b.call(_a)) && ticks.length > 1) {
    const start = targetScale(normalizeXValue($$, ticks[0]));
    const end = targetScale(normalizeXValue($$, ticks[1]));
    return Math.max(0, Math.abs(end - start) - 12);
  }
  return 110;
}
function getXTickTextLines($$, painter, format, tick, ticks = [], isRotated = false, targetScale = getXScale($$), maxWidth) {
  const value = format ? format(tick) : tick;
  if (value == null) {
    return [""];
  }
  if (Array.isArray(value)) {
    return value.map((v) => String(v));
  }
  const text = String(value);
  if (text.indexOf("\n") > -1) {
    return text.split("\n");
  }
  return $$.config.axis_x_tick_multiline ? splitTickTextByWidth(
    text,
    maxWidth != null ? maxWidth : getXTickTextWidth($$, ticks, isRotated, targetScale),
    painter
  ) : [text];
}
function getXTickTextAlign($$, options) {
  const {
    isRotated,
    tickCount,
    tickIndex,
    tickRotate,
    tickTextDirection
  } = options;
  const inner = $$.config.axis_x_tick_text_inner;
  let align = isRotated ? tickTextDirection > 0 ? "left" : "right" : tickRotate ? tickRotate > 0 ? "left" : "right" : "center";
  if (!isRotated && tickIndex === 0 && (inner === true || (inner == null ? void 0 : inner.first))) {
    align = "left";
  } else if (!isRotated && tickIndex === tickCount - 1 && (inner === true || (inner == null ? void 0 : inner.last))) {
    align = "right";
  }
  return align;
}
function getTitleTextPosition(position, width) {
  var _a, _b;
  if (((_a = position == null ? void 0 : position.indexOf("center")) != null ? _a : -1) > -1) {
    return { x: width / 2, align: "center" };
  }
  if (((_b = position == null ? void 0 : position.indexOf("right")) != null ? _b : -1) > -1) {
    return { x: width, align: "right" };
  }
  return { x: 0, align: "left" };
}
function isDrawable(value) {
  return Number.isFinite(value);
}
function isInAxisRange(value, start, end) {
  return isDrawable(value) && value >= Math.min(start, end) && value <= Math.max(start, end);
}
function getXOuterTickDirection(isRotated) {
  return isRotated ? -1 : 1;
}
function getYOuterTickDirection(config, isRotated, isY2) {
  if (isRotated) {
    return isY2 ? config.axis_y2_inner ? 1 : -1 : config.axis_y_inner ? -1 : 1;
  }
  return isY2 ? config.axis_y2_inner ? -1 : 1 : config.axis_y_inner ? 1 : -1;
}
function getXPosition($$, value, targetScale = getXScale($$)) {
  return targetScale(normalizeXValue($$, value));
}
function normalizeXRegionBoundaryValue($$, value) {
  var _a, _b;
  if (((_b = (_a = $$.axis) == null ? void 0 : _a.isCategorized) == null ? void 0 : _b.call(_a)) && typeof value === "string" && Number.isNaN(Number(value))) {
    return $$.config.axis_x_categories.indexOf(value);
  }
  return normalizeXValue($$, value);
}
function hasCategoryRegionBoundaryOffset($$, value) {
  var _a, _b;
  return Boolean(((_b = (_a = $$.axis) == null ? void 0 : _a.isCategorized) == null ? void 0 : _b.call(_a)) && Number.isNaN(Number(value)));
}
function getXBoundary($$, value, fallback, key) {
  var _a, _b;
  if (value === void 0) {
    return fallback;
  }
  let pos = getXScale($$)(normalizeXRegionBoundaryValue($$, value));
  if (hasCategoryRegionBoundaryOffset($$, value)) {
    const xScale = getXScale($$);
    const tickOffset = ((_b = (_a = $$.axis.x) == null ? void 0 : _a.tickOffset) == null ? void 0 : _b.call(_a)) || (xScale(1) - xScale(0)) / 2;
    pos += tickOffset * (key === "start" ? -1 : 1);
  }
  return pos;
}
function getYPosition($$, value, axis = "y") {
  return $$.scale[axis || "y"](normalizeYValue($$, value, axis));
}
function getLineTextPosition(position, start, end) {
  if (position === "start") {
    return start + 4;
  }
  if (position === "middle") {
    return (start + end) / 2;
  }
  return end - 4;
}
function getRotatedLineTextPosition(position, start, end) {
  if (position === "start") {
    return end - 4;
  }
  if (position === "middle") {
    return (start + end) / 2;
  }
  return start + 4;
}
function getRegionRect($$, region) {
  const { config, scale, state: { width, height } } = $$;
  const axis = region.axis || "x";
  const isRotated = config.axis_rotated;
  if (axis === "x") {
    const start2 = getXBoundary($$, region.start, 0, "start");
    const end2 = getXBoundary($$, region.end, isRotated ? height : width, "end");
    const min2 = Math.min(start2, end2);
    const size2 = Math.abs(end2 - start2);
    return isRotated ? { x: 0, y: min2, w: width, h: size2 } : { x: min2, y: 0, w: size2, h: height };
  }
  if (!scale[axis]) {
    return null;
  }
  const start = region.start === void 0 ? isRotated ? 0 : height : getYPosition($$, region.start, axis);
  const end = region.end === void 0 ? isRotated ? width : 0 : getYPosition($$, region.end, axis);
  const min = Math.min(start, end);
  const size = Math.abs(end - start);
  return isRotated ? { x: min, y: 0, w: size, h: height } : { x: 0, y: min, w: width, h: size };
}
class CanvasAxisRenderer {
  /**
   * Constructor.
   * @param {CanvasEngine} engine Canvas drawing engine
   * @param {CanvasTheme} theme Canvas theme resolver
   * @private
   */
  constructor(engine, theme) {
    CanvasAxisRenderer_publicField(this, "engine", engine);
    CanvasAxisRenderer_publicField(this, "theme", theme);
    CanvasAxisRenderer_publicField(this, "painter");
    this.painter = new CanvasPainter(engine.ctx);
  }
  /**
   * Get the drawing context for the main canvas.
   * @returns {CanvasRenderingContext2D} Canvas drawing context
   * @private
   */
  get ctx() {
    return this.painter.context;
  }
  /**
   * Run axis renderer draw calls on another canvas context.
   * @param {CanvasRenderingContext2D} ctx Canvas drawing context
   * @param {function} draw Draw callback
   * @private
   */
  withContext(ctx, draw) {
    this.painter.withContext(ctx, draw);
  }
  /**
   * Draw grid and axis layers.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  draw($$) {
    this.drawRegions($$);
    this.drawGrid($$);
    this.drawAxis($$);
  }
  /**
   * Draw visible axes.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawAxis($$) {
    const { config } = $$;
    config.axis_x_show && this.drawXAxis($$);
    config.axis_y_show && this.drawYAxis($$);
    config.axis_y2_show && $$.scale.y2 && this.drawYAxis($$, "y2");
    this.drawAdditionalAxes($$);
    this.drawAxisLabels($$);
  }
  /**
   * Draw the canvas subchart x axis.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawSubXAxis($$) {
    var _a, _b, _c, _d;
    const { ctx, painter, theme: { style: { axis } } } = this;
    const {
      config,
      format,
      scale,
      state: { current, margin2, width2, height2 }
    } = $$;
    if (!config.subchart_show || !config.subchart_axis_x_show || !scale.subX || width2 <= 0 || height2 <= 0) {
      return;
    }
    const isRotated = config.axis_rotated;
    const x = painter.crisp(margin2.left, axis.lineWidth);
    const y = painter.crisp(margin2.top + height2, axis.lineWidth);
    const x1 = margin2.left;
    const x2 = margin2.left + width2;
    const y1 = margin2.top;
    const y2 = margin2.top + height2;
    const rangeStart = isRotated ? y1 : x1;
    const rangeEnd = isRotated ? y2 : x2;
    const ticks = getSubXTickValues($$);
    const lineTicks = getSubXTickLineValues($$, ticks, axis.tickWidth);
    const outerTick = (_a = config.subchart_axis_x_tick_outer) != null ? _a : config.axis_x_tick_outer;
    const tickDirection = isRotated ? config.axis_x_tick_inner ? 1 : -1 : config.axis_x_tick_inner ? -1 : 1;
    const outerTickDirection = getXOuterTickDirection(isRotated);
    const tickTextDirection = getXTickTextDirection(isRotated);
    const tickTextPosition = config.axis_x_tick_text_position;
    const tickRotate = !isRotated ? ((_b = $$.getAxisTickRotate) == null ? void 0 : _b.call($$, "x")) || 0 : 0;
    const tickFormat = format.subXAxisTick || ((_d = (_c = $$.axis) == null ? void 0 : _c.getXAxisTickFormat) == null ? void 0 : _d.call(_c, true));
    painter.clipRect(
      isRotated ? getRotatedXAxisClipRect(margin2, current.width, height2) : __spreadProps(CanvasAxisRenderer_spreadValues({}, getHorizontalXAxisClipRect(
        margin2,
        width2,
        current.height - margin2.top
      )), {
        y: margin2.top
      }),
      () => {
        ctx.globalAlpha = 1;
        ctx.strokeStyle = axis.lineColor;
        ctx.lineWidth = axis.lineWidth;
        ctx.setLineDash([]);
        painter.strokePath(() => {
          if (isRotated) {
            painter.traceLine(x, y1, x, y2);
          } else {
            painter.traceLine(x1, y, x2, y);
          }
          if (outerTick) {
            if (isRotated) {
              painter.traceLine(x, y1, x + AXIS_TICK_SIZE * outerTickDirection, y1);
              painter.traceLine(x, y2, x + AXIS_TICK_SIZE * outerTickDirection, y2);
            } else {
              painter.traceLine(x1, y, x1, y + AXIS_TICK_SIZE * outerTickDirection);
              painter.traceLine(x2, y, x2, y + AXIS_TICK_SIZE * outerTickDirection);
            }
          }
        });
        const tickFont = getAxisTickFont(axis, "x");
        ctx.font = tickFont;
        ctx.fillStyle = axis.labelColor;
        ctx.textAlign = isRotated ? tickTextDirection > 0 ? "left" : "right" : "center";
        ctx.textBaseline = isRotated ? "middle" : tickTextDirection > 0 ? "top" : "bottom";
        ctx.strokeStyle = axis.tickColor;
        ctx.lineWidth = axis.tickWidth;
        const lineHeight = getXTickTextLineHeight(painter, getFontSize(tickFont));
        const tickTextWidth = getXTickTextWidth($$, ticks, isRotated, scale.subX);
        if (config.subchart_axis_x_tick_show) {
          for (const tick of lineTicks) {
            const tickPos = scale.subX(normalizeXValue($$, tick));
            const tx = margin2.left + tickPos;
            const ty = margin2.top + tickPos;
            const pos = isRotated ? ty : tx;
            if (!isInAxisRange(pos, rangeStart, rangeEnd)) {
              continue;
            }
            painter.strokePath(() => {
              if (isRotated) {
                painter.traceLine(x, ty, x + AXIS_TICK_SIZE * tickDirection, ty);
              } else {
                painter.traceLine(tx, y, tx, y + AXIS_TICK_SIZE * tickDirection);
              }
            });
          }
        }
        for (const tick of ticks) {
          const tickPos = scale.subX(normalizeXValue($$, tick));
          const tx = margin2.left + tickPos;
          const ty = margin2.top + tickPos;
          const pos = isRotated ? ty : tx;
          if (!isInAxisRange(pos, rangeStart, rangeEnd)) {
            continue;
          }
          if (!config.subchart_axis_x_tick_text_show) {
            continue;
          }
          const lines = getXTickTextLines(
            $$,
            painter,
            tickFormat,
            tick,
            ticks,
            isRotated,
            scale.subX,
            tickTextWidth
          );
          let textX;
          let textY;
          if (isRotated) {
            textX = x + (AXIS_TICK_SIZE + AXIS_TICK_PADDING) * tickTextDirection + (tickTextPosition.x || 0);
            textY = ty + (tickTextPosition.y || 0);
            ctx.textAlign = tickTextDirection > 0 ? "left" : "right";
            ctx.textBaseline = "middle";
          } else {
            textX = tx + (tickTextPosition.x || 0);
            textY = y + (AXIS_TICK_SIZE + AXIS_TICK_PADDING) * tickTextDirection + (tickTextPosition.y || 0);
            ctx.textAlign = tickRotate ? tickRotate > 0 ? "left" : "right" : "center";
            ctx.textBaseline = tickTextDirection > 0 ? "top" : "bottom";
          }
          painter.withState((textCtx) => {
            textCtx.translate(textX, textY);
            tickRotate && textCtx.rotate(tickRotate * Math.PI / 180);
            lines.forEach((line, i) => {
              textCtx.fillText(line, 0, i * lineHeight);
            });
          });
        }
      }
    );
  }
  /**
   * Draw the canvas subchart y/y2 axes.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawSubYAxes($$) {
    const {
      config,
      scale,
      state: { margin2, width2, height2 }
    } = $$;
    if (!config.subchart_show || width2 <= 0 || height2 <= 0) {
      return;
    }
    ["y", "y2"].forEach((id) => {
      var _a;
      const subScale = id === "y2" ? scale.subY2 : scale.subY;
      if (!config[`subchart_axis_${id}_show`] || !subScale) {
        return;
      }
      this.drawYAxis($$, id, {
        scale: subScale,
        ticks: getYTickValues($$, id, void 0, true, subScale, `subchart_axis_${id}`),
        format: getSubYTickFormat($$, id),
        index: 0,
        outerTick: (_a = config[`subchart_axis_${id}_tick_outer`]) != null ? _a : config[`axis_${id}_tick_outer`],
        margin: margin2,
        width: width2,
        height: height2,
        prefix: `subchart_axis_${id}`,
        tickShow: config[`subchart_axis_${id}_tick_show`],
        tickTextShow: config[`subchart_axis_${id}_tick_text_show`],
        tickTextPosition: config[`axis_${id}_tick_text_position`]
      });
    });
  }
  /**
   * Draw chart title.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawTitle($$) {
    var _a, _b;
    const { ctx, painter, theme: { style: { title } } } = this;
    const { config, state: { current } } = $$;
    if (!config.title_text) {
      return;
    }
    const lines = String(config.title_text).split("\n");
    const fontSize = getFontSize(title.font);
    const lineHeight = fontSize * 1.5;
    const { x, align } = getTitleTextPosition(config.title_position, current.width);
    const titleHeight = (_b = (_a = $$.getCanvasTitleHeight) == null ? void 0 : _a.call($$)) != null ? _b : fontSize;
    const y = (config.title_padding.top || 0) + titleHeight;
    painter.withState(() => {
      ctx.font = title.font;
      ctx.fillStyle = title.color;
      ctx.textAlign = align;
      ctx.textBaseline = "alphabetic";
      lines.forEach((line, i) => {
        ctx.fillText(line, x, y + (i ? fontSize + (i - 1) * lineHeight : 0));
      });
    });
  }
  /**
   * Draw axis labels.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawAxisLabels($$) {
    const { ctx, painter, theme: { style: { axis: style } } } = this;
    const { axis, config } = $$;
    const fontSize = getFontSize(style.labelFont);
    const ids = ["x", "y", "y2"];
    const labelColorById = {
      x: style.xLabelColor,
      y: style.yLabelColor,
      y2: style.y2LabelColor
    };
    const alignMap = {
      start: "left",
      middle: "center",
      end: "right"
    };
    if (!axis) {
      return;
    }
    painter.withState(() => {
      ctx.font = style.labelFont;
      ctx.textBaseline = "alphabetic";
      ids.forEach((id) => {
        const text = axis.getLabelText(id);
        if (!text || !config[`axis_${id}_show`] || id === "y2" && !$$.scale.y2) {
          return;
        }
        const isRotatedLabel = id === "x" && config.axis_rotated || id !== "x" && !config.axis_rotated;
        const base = getAxisLabelBasePosition($$, id);
        const localX = axis.xForAxisLabel(id) + resolveTextOffset(axis.dxForAxisLabel(id), fontSize);
        const localY = resolveTextOffset(axis.dyForAxisLabel(id), fontSize);
        const { x, y } = getAxisLabelCanvasPosition(
          base,
          localX,
          localY,
          isRotatedLabel
        );
        const anchor = axis.textAnchorForAxisLabel(id);
        ctx.fillStyle = labelColorById[id] || style.labelColor;
        ctx.textAlign = alignMap[anchor] || "center";
        painter.text(String(text), x, y, {
          angle: isRotatedLabel ? -90 : 0
        });
      });
    });
  }
  /**
   * Draw visible grid lines.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawGrid($$) {
    const { ctx, painter, theme: { style: { grid } } } = this;
    const { config, scale, state: { height, margin, width } } = $$;
    if (!grid.lineColor) {
      return;
    }
    const isRotated = config.axis_rotated;
    const x1 = margin.left;
    const x2 = margin.left + width;
    const y1 = margin.top;
    const y2 = margin.top + height;
    painter.withState(() => {
      ctx.strokeStyle = grid.lineColor;
      ctx.lineWidth = grid.lineWidth;
      grid.dashArray.length && ctx.setLineDash(grid.dashArray);
      if (config.grid_x_show && scale.x) {
        painter.strokePath(() => {
          for (const tick of getXTickValues($$)) {
            const pos = getXPosition($$, tick);
            if (!isDrawable(pos)) {
              continue;
            }
            if (isRotated) {
              painter.traceCrispLine(
                x1,
                margin.top + pos,
                x2,
                margin.top + pos,
                grid.lineWidth
              );
            } else {
              painter.traceCrispLine(
                margin.left + pos,
                y1,
                margin.left + pos,
                y2,
                grid.lineWidth
              );
            }
          }
        });
      }
      if (config.grid_y_show && scale.y) {
        painter.strokePath(() => {
          for (const tick of getYGridTickValues($$)) {
            const value = normalizeYValue($$, tick);
            const pos = scale.y(value);
            if (!isDrawable(pos)) {
              continue;
            }
            if (isRotated) {
              painter.traceCrispLine(
                margin.left + pos,
                y1,
                margin.left + pos,
                y2,
                grid.lineWidth
              );
            } else {
              painter.traceCrispLine(
                x1,
                margin.top + pos,
                x2,
                margin.top + pos,
                grid.lineWidth
              );
            }
          }
        });
      }
      !config.grid_lines_front && this.drawGridLines($$);
    });
  }
  /**
   * Draw configured global regions.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawRegions($$) {
    const { ctx, painter, theme: { style: { region: style } } } = this;
    const { config, state: { height, margin, width } } = $$;
    const regions = config.regions || [];
    if (!regions.length) {
      return;
    }
    painter.clipRect({ x: margin.left, y: margin.top, w: width, h: height }, () => {
      var _a;
      ctx.fillStyle = style.fill;
      ctx.font = style.labelFont;
      ctx.textBaseline = "top";
      for (const region of regions) {
        const rect = getRegionRect($$, region);
        if (!rect || !isDrawable(rect.x) || !isDrawable(rect.y) || !rect.w || !rect.h) {
          continue;
        }
        const x = margin.left + rect.x;
        const y = margin.top + rect.y;
        const w = rect.w;
        const h = rect.h;
        ctx.globalAlpha = Number.isFinite(region.opacity) ? region.opacity : style.opacity;
        painter.fillRect({ x, y, w, h });
        if ((_a = region.label) == null ? void 0 : _a.text) {
          const label = region.label;
          const center = label.center || "";
          const text = String(label.text);
          const textWidth = painter.measureText(text).width;
          const lineHeight = parseFloat(ctx.font) || 12;
          let tx = x + (label.x || 0);
          let ty = y + (label.y || 0);
          if (center.indexOf("x") > -1) {
            tx += (w - textWidth) / 2;
          }
          if (center.indexOf("y") > -1) {
            ty += (h - lineHeight) / 2;
          }
          painter.text(text, tx, ty, {
            angle: label.rotated ? -90 : 0,
            alpha: 1,
            fill: label.color || style.labelColor
          });
        }
      }
    });
  }
  /**
   * Draw configured x/y grid lines and labels.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawGridLines($$) {
    const { ctx, painter, theme: { style: { axis, grid } } } = this;
    const { config, scale, state: { height, margin, width } } = $$;
    const isRotated = config.axis_rotated;
    const x1 = margin.left;
    const x2 = margin.left + width;
    const y1 = margin.top;
    const y2 = margin.top + height;
    if (!grid.lineColor) {
      return;
    }
    painter.withState(() => {
      ctx.strokeStyle = grid.lineColor;
      ctx.lineWidth = grid.lineWidth;
      ctx.font = grid.labelFont || axis.labelFont;
      ctx.fillStyle = grid.labelColor;
      ctx.textBaseline = "middle";
      ctx.setLineDash([]);
      const drawLabel = (text, x, y, rotated = false, style) => {
        if (!text) {
          return;
        }
        painter.text(text, x, y, __spreadProps(CanvasAxisRenderer_spreadValues({}, style), {
          angle: rotated ? -90 : 0
        }));
      };
      const drawLine = (line, axisId, draw) => {
        const style = getGridLineCanvasStyle(
          this.theme.getGridLineStyle(axisId, line, "line")
        );
        painter.strokePath(draw, style);
      };
      const getTextStyle = (axisId, line) => getGridTextCanvasStyle(this.theme.getGridLineStyle(axisId, line, "text"));
      const drawXLine = (line) => {
        if (line.value === void 0 || !scale.x) {
          return;
        }
        const pos = getXPosition($$, line.value);
        if (!isDrawable(pos)) {
          return;
        }
        if (isRotated) {
          const y = margin.top + pos;
          drawLine(line, "x", () => {
            painter.traceLine(x1, y, x2, y);
          });
          ctx.textAlign = line.position === "start" ? "left" : line.position === "middle" ? "center" : "right";
          drawLabel(
            line.text,
            getLineTextPosition(line.position, x1, x2),
            y - 5,
            false,
            getTextStyle("x", line)
          );
        } else {
          const x = margin.left + pos;
          drawLine(line, "x", () => {
            painter.traceLine(x, y1, x, y2);
          });
          ctx.textAlign = line.position === "start" ? "left" : line.position === "middle" ? "center" : "right";
          drawLabel(
            line.text,
            x - 5,
            getRotatedLineTextPosition(line.position, y1, y2),
            true,
            getTextStyle("x", line)
          );
        }
      };
      const drawYLine = (line) => {
        const targetScale = line.axis === "y2" ? scale.y2 : scale.y;
        const axisId = line.axis === "y2" ? "y2" : "y";
        if (line.value === void 0 || !targetScale) {
          return;
        }
        const value = normalizeYValue($$, line.value, axisId);
        const pos = targetScale(value);
        if (!isDrawable(pos)) {
          return;
        }
        if (isRotated) {
          const x = margin.left + pos;
          drawLine(line, "y", () => {
            painter.traceLine(x, y1, x, y2);
          });
          ctx.textAlign = line.position === "start" ? "left" : line.position === "middle" ? "center" : "right";
          drawLabel(
            line.text,
            x - 5,
            getRotatedLineTextPosition(line.position, y1, y2),
            true,
            getTextStyle("y", line)
          );
        } else {
          const y = margin.top + pos;
          drawLine(line, "y", () => {
            painter.traceLine(x1, y, x2, y);
          });
          ctx.textAlign = line.position === "start" ? "left" : line.position === "middle" ? "center" : "right";
          drawLabel(
            line.text,
            getLineTextPosition(line.position, x1, x2),
            y - 5,
            false,
            getTextStyle("y", line)
          );
        }
      };
      (config.grid_x_lines || []).forEach(drawXLine);
      (config.grid_y_lines || []).forEach(drawYLine);
    });
  }
  /**
   * Draw axes configured with axis.x/y/y2.axes.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawAdditionalAxes($$) {
    ["x", "y", "y2"].forEach((id) => {
      const axesConfig = $$.config[`axis_${id}_axes`] || [];
      if (!axesConfig.length || !$$.scale[id] || !$$.config[`axis_${id}_show`]) {
        return;
      }
      axesConfig.forEach((axisConfig, index) => {
        var _a;
        const scale = getAdditionalAxisScale($$, id, axisConfig);
        if (!scale) {
          return;
        }
        const options = {
          scale,
          ticks: getAdditionalAxisTickValues($$, id, scale, axisConfig),
          format: getAdditionalAxisTickFormat($$, axisConfig),
          index: index + 1,
          outerTick: ((_a = axisConfig.tick) == null ? void 0 : _a.outer) !== false
        };
        id === "x" ? this.drawXAxis($$, options) : this.drawYAxis($$, id, options);
      });
    });
  }
  /**
   * Draw the x axis.
   * @param {object} $$ ChartInternal instance
   * @param {object} axisOptions Additional axis options
   * @private
   */
  drawXAxis($$, axisOptions) {
    var _a;
    const { ctx, painter, theme: { style: { axis } } } = this;
    const { axis: axisInstance, config, state: { current, margin, width, height } } = $$;
    const isRotated = config.axis_rotated;
    const axisOffset = (axisOptions == null ? void 0 : axisOptions.index) ? $$.getAxisSize("x") * axisOptions.index : 0;
    const targetScale = (axisOptions == null ? void 0 : axisOptions.scale) || getXScale($$);
    const x = painter.crisp(margin.left - (isRotated ? axisOffset : 0), axis.lineWidth);
    const y = painter.crisp(
      margin.top + height + (isRotated ? 0 : axisOffset),
      axis.lineWidth
    );
    const x1 = margin.left;
    const x2 = margin.left + width;
    const y1 = margin.top;
    const y2 = margin.top + height;
    const rangeStart = isRotated ? y1 : x1;
    const rangeEnd = isRotated ? y2 : x2;
    const ticks = (axisOptions == null ? void 0 : axisOptions.ticks) || getXTickValues($$);
    const lineTicks = (axisOptions == null ? void 0 : axisOptions.ticks) || getXTickLineValues($$, ticks, axis.tickWidth);
    const format = (axisOptions == null ? void 0 : axisOptions.format) || axisInstance.getXAxisTickFormat();
    const outerTick = axisOptions ? axisOptions.outerTick : config.axis_x_tick_outer;
    const tickDirection = isRotated ? config.axis_x_tick_inner ? 1 : -1 : config.axis_x_tick_inner ? -1 : 1;
    const outerTickDirection = getXOuterTickDirection(isRotated);
    const tickTextDirection = getXTickTextDirection(isRotated);
    const tickTextPosition = config.axis_x_tick_text_position;
    const tickRotate = !isRotated ? ((_a = $$.getAxisTickRotate) == null ? void 0 : _a.call($$, "x")) || 0 : 0;
    painter.clipRect(
      isRotated ? getRotatedXAxisClipRect(margin, current.width, height) : getHorizontalXAxisClipRect(margin, width, current.height),
      () => {
        ctx.strokeStyle = axis.lineColor;
        ctx.lineWidth = axis.lineWidth;
        painter.strokePath(() => {
          if (isRotated) {
            painter.traceLine(x, y1, x, y2);
          } else {
            painter.traceLine(x1, y, x2, y);
          }
          if (outerTick) {
            if (isRotated) {
              painter.traceLine(x, y1, x + AXIS_TICK_SIZE * outerTickDirection, y1);
              painter.traceLine(x, y2, x + AXIS_TICK_SIZE * outerTickDirection, y2);
            } else {
              painter.traceLine(x1, y, x1, y + AXIS_TICK_SIZE * outerTickDirection);
              painter.traceLine(x2, y, x2, y + AXIS_TICK_SIZE * outerTickDirection);
            }
          }
        });
        ctx.font = getAxisTickFont(axis, "x");
        ctx.fillStyle = axis.labelColor;
        ctx.textAlign = isRotated ? tickTextDirection > 0 ? "left" : "right" : "center";
        ctx.textBaseline = isRotated ? "middle" : tickTextDirection > 0 ? "top" : "bottom";
        ctx.strokeStyle = axis.tickColor;
        ctx.lineWidth = axis.tickWidth;
        if (config.axis_x_tick_show) {
          painter.strokePath(() => {
            for (const tick of lineTicks) {
              const tickPos = getXTickLinePosition($$, tick, targetScale);
              const tx = margin.left + tickPos;
              const ty = margin.top + tickPos;
              const pos = isRotated ? ty : tx;
              if (!isInAxisRange(pos, rangeStart, rangeEnd)) {
                continue;
              }
              if (isRotated) {
                painter.traceLine(x, ty, x + AXIS_TICK_SIZE * tickDirection, ty);
              } else {
                painter.traceLine(tx, y, tx, y + AXIS_TICK_SIZE * tickDirection);
              }
            }
          });
        }
        if (!axisOptions && !config.axis_x_tick_text_show) {
          return;
        }
        const tickFont = getAxisTickFont(axis, "x");
        const tickLineHeight = getXTickTextLineHeight(painter, getFontSize(tickFont));
        const tickTextWidth = getXTickTextWidth($$, ticks, isRotated, targetScale);
        ticks.forEach((tick, tickIndex) => {
          this.drawXAxisTickText($$, tick, format, axis.labelColor, {
            isRotated,
            rangeEnd,
            rangeStart,
            tickCount: ticks.length,
            tickFont,
            tickIndex,
            tickLineHeight,
            tickTextDirection,
            tickTextWidth,
            tickRotate,
            tickTextPosition,
            targetScale,
            ticks,
            x,
            y
          });
        });
      }
    );
  }
  /**
   * Draw the focused x-axis tick text with the SVG active tick color.
   * @param {object} $$ ChartInternal instance
   * @param {Array} focusData Focused data rows
   * @private
   */
  drawFocusedXAxisTick($$, focusData) {
    var _a;
    const { painter, theme: { style: { axis } } } = this;
    const { axis: axisInstance, config, state: { current, margin, width, height } } = $$;
    const focusX = (_a = focusData == null ? void 0 : focusData[0]) == null ? void 0 : _a.x;
    if (focusX === void 0 || !axisInstance || !config.axis_x_show || !config.axis_x_tick_text_show || !axis.activeLabelColor || axis.activeLabelColor === axis.labelColor) {
      return;
    }
    const ticks = getXTickValues($$);
    const tickIndex = ticks.findIndex((value) => isSameTickValue(value, focusX));
    const tick = ticks[tickIndex];
    if (tick === void 0) {
      return;
    }
    const isRotated = config.axis_rotated;
    const x = painter.crisp(margin.left, axis.lineWidth);
    const y = painter.crisp(margin.top + height, axis.lineWidth);
    const rangeStart = isRotated ? margin.top : margin.left;
    const rangeEnd = isRotated ? margin.top + height : margin.left + width;
    const format = axisInstance.getXAxisTickFormat();
    const tickTextDirection = getXTickTextDirection(isRotated);
    painter.clipRect(
      isRotated ? getRotatedXAxisClipRect(margin, current.width, height) : getHorizontalXAxisClipRect(margin, width, current.height),
      () => {
        var _a2;
        this.drawXAxisTickText($$, tick, format, axis.activeLabelColor, {
          isRotated,
          rangeEnd,
          rangeStart,
          targetScale: getXScale($$),
          tickCount: ticks.length,
          tickIndex,
          tickTextDirection,
          tickRotate: !isRotated ? ((_a2 = $$.getAxisTickRotate) == null ? void 0 : _a2.call($$, "x")) || 0 : 0,
          tickTextPosition: config.axis_x_tick_text_position,
          ticks,
          x,
          y
        });
      }
    );
  }
  /**
   * Draw axis tooltip guide lines and scale labels on canvas overlay.
   * @param {object} $$ ChartInternal instance
   * @param {Array} point Canvas-local pointer coordinate
   * @private
   */
  drawAxisTooltip($$, point) {
    const { ctx, painter, theme: { style: { axis, grid } } } = this;
    const { config, state: { margin, width, height } } = $$;
    if (!config.axis_tooltip || !point) {
      return;
    }
    const isRotated = config.axis_rotated;
    const localX = point[0] - margin.left;
    const localY = point[1] - margin.top;
    const isInXRange = localX >= 0 && localX <= width;
    const isInYRange = localY >= 0 && localY <= height;
    if (!isInXRange && !isInYRange) {
      return;
    }
    const absX = margin.left + localX;
    const absY = margin.top + localY;
    const fontSize = getFontSize(axis.labelFont);
    const lineHeight = fontSize || 10;
    const drawLabel = (id, scaleValue, x, y, textAlign) => {
      const bg = getAxisTooltipBackgroundColor($$, id);
      const text = bg && formatAxisTooltipValue($$, id, scaleValue);
      if (!text) {
        return;
      }
      ctx.font = axis.labelFont;
      ctx.textAlign = textAlign;
      ctx.textBaseline = "alphabetic";
      const metrics = ctx.measureText(text);
      const textWidth = metrics.width;
      const ascent = metrics.actualBoundingBoxAscent || lineHeight * 0.8;
      const descent = metrics.actualBoundingBoxDescent || lineHeight * 0.2;
      const paddingX = Math.max(2, textWidth * 0.15);
      const paddingY = Math.max(3, lineHeight * 0.25);
      const textLeft = textAlign === "right" ? x - textWidth : textAlign === "center" ? x - textWidth / 2 : x;
      const textTop = y - ascent;
      ctx.fillStyle = bg;
      ctx.fillRect(
        textLeft - paddingX,
        textTop - paddingY,
        textWidth + paddingX * 2,
        ascent + descent + paddingY * 2
      );
      ctx.fillStyle = "#fff";
      ctx.fillText(text, x, y);
    };
    painter.withState(() => {
      ctx.strokeStyle = grid.lineColor;
      ctx.lineWidth = grid.lineWidth;
      ctx.setLineDash([]);
      painter.strokePath(() => {
        if (isInXRange) {
          painter.traceLine(absX, margin.top, absX, margin.top + height);
        }
        if (isInYRange) {
          painter.traceLine(margin.left, absY, margin.left + width, absY);
        }
      });
      ctx.setLineDash([]);
      if (isRotated) {
        isInYRange && config.axis_x_show && drawLabel(
          "x",
          localY,
          margin.left - fontSize * 0.3,
          absY + fontSize * 0.4,
          "right"
        );
        isInXRange && config.axis_y_show && drawLabel(
          "y",
          localX,
          absX - fontSize * 1.3,
          margin.top + height + fontSize * 1.15,
          "left"
        );
        isInXRange && config.axis_y2_show && $$.scale.y2 && drawLabel(
          "y2",
          localX,
          absX - fontSize * 1.3,
          margin.top - fontSize * 0.4,
          "left"
        );
      } else {
        isInXRange && config.axis_x_show && drawLabel(
          "x",
          localX,
          absX - fontSize,
          margin.top + height + fontSize * 1.15,
          "left"
        );
        isInYRange && config.axis_y_show && drawLabel(
          "y",
          localY,
          margin.left - fontSize * 0.4,
          absY + fontSize * 0.3,
          "right"
        );
        isInYRange && config.axis_y2_show && $$.scale.y2 && drawLabel(
          "y2",
          localY,
          margin.left + width + fontSize * 0.4,
          absY + fontSize * 0.3,
          "left"
        );
      }
    });
  }
  /**
   * Draw one x-axis tick text using the same layout as SVG axis ticks.
   * @param {object} $$ ChartInternal instance
   * @param {number|string|Date} tick Tick value
   * @param {function} format Tick formatter
   * @param {string} fill Text fill color
   * @param {object} options X-axis drawing options
   * @private
   */
  drawXAxisTickText($$, tick, format, fill, options) {
    var _a, _b;
    const { ctx, painter, theme: { style: { axis } } } = this;
    const { state: { margin } } = $$;
    const {
      isRotated,
      rangeEnd,
      rangeStart,
      tickTextDirection,
      tickRotate,
      tickTextPosition,
      targetScale,
      ticks,
      x,
      y
    } = options;
    const tickPos = getXPosition($$, tick, targetScale);
    const tx = margin.left + tickPos;
    const ty = margin.top + tickPos;
    const pos = isRotated ? ty : tx;
    if (!isInAxisRange(pos, rangeStart, rangeEnd)) {
      return;
    }
    const tickFont = (_a = options.tickFont) != null ? _a : getAxisTickFont(axis, "x");
    ctx.font = tickFont;
    ctx.fillStyle = fill;
    const lines = getXTickTextLines(
      $$,
      painter,
      format,
      tick,
      ticks,
      isRotated,
      targetScale,
      options.tickTextWidth
    );
    const lineHeight = (_b = options.tickLineHeight) != null ? _b : getXTickTextLineHeight(painter, getFontSize(tickFont));
    let textX;
    let textY;
    if (isRotated) {
      textX = x + (AXIS_TICK_SIZE + AXIS_TICK_PADDING) * tickTextDirection + (tickTextPosition.x || 0);
      textY = ty + (tickTextPosition.y || 0);
      ctx.textAlign = getXTickTextAlign($$, options);
      ctx.textBaseline = "middle";
    } else if (tickRotate) {
      const fontSize = getFontSize(tickFont);
      const firstDy = tickTextPosition.y ? resolveTextOffset(tickTextPosition.y, fontSize) : 0.71 * fontSize;
      const textDx = getRotatedXTickTextDx(tickRotate) + (tickTextPosition.x || 0);
      const textY2 = getRotatedXTickTextY(tickRotate) + firstDy;
      ctx.textAlign = getXTickTextAlign($$, options);
      ctx.textBaseline = "alphabetic";
      painter.withState((textCtx) => {
        textCtx.translate(tx, y);
        textCtx.rotate(tickRotate * Math.PI / 180);
        lines.forEach((line, i) => {
          textCtx.fillText(line, textDx, textY2 + i * lineHeight);
        });
      });
      return;
    } else {
      textX = tx + (tickTextPosition.x || 0);
      textY = y + (AXIS_TICK_SIZE + AXIS_TICK_PADDING) * tickTextDirection + (tickTextPosition.y || 0);
      ctx.textAlign = getXTickTextAlign($$, options);
      ctx.textBaseline = tickTextDirection > 0 ? "top" : "bottom";
    }
    painter.withState((textCtx) => {
      textCtx.translate(textX, textY);
      tickRotate && textCtx.rotate(tickRotate * Math.PI / 180);
      lines.forEach((line, i) => {
        textCtx.fillText(line, 0, i * lineHeight);
      });
    });
  }
  /**
   * Draw the y axis.
   * @param {object} $$ ChartInternal instance
   * @param {string} id Axis id
   * @param {object} axisOptions Additional axis options
   * @private
   */
  drawYAxis($$, id = "y", axisOptions) {
    var _a, _b, _c, _d, _e, _f, _g, _h;
    const { ctx, painter, theme: { style: { axis } } } = this;
    const { config, scale, state } = $$;
    const { margin, width, height } = state;
    const plotMargin = (axisOptions == null ? void 0 : axisOptions.margin) || margin;
    const plotWidth = (_a = axisOptions == null ? void 0 : axisOptions.width) != null ? _a : width;
    const plotHeight = (_b = axisOptions == null ? void 0 : axisOptions.height) != null ? _b : height;
    const prefix = (axisOptions == null ? void 0 : axisOptions.prefix) || `axis_${id}`;
    const targetScale = (axisOptions == null ? void 0 : axisOptions.scale) || scale[id];
    const isY2 = id === "y2";
    const isRotated = config.axis_rotated;
    const axisOffset = (axisOptions == null ? void 0 : axisOptions.index) ? $$.getAxisSize(id) * axisOptions.index : 0;
    const x = painter.crisp(
      plotMargin.left + (isY2 ? plotWidth + (isRotated ? 0 : axisOffset) : -axisOffset),
      axis.lineWidth
    );
    const y = painter.crisp(plotMargin.top + (isRotated ? isY2 ? -axisOffset - 1 : plotHeight + axisOffset : 0), axis.lineWidth);
    const x1 = plotMargin.left;
    const x2 = plotMargin.left + plotWidth;
    const y1 = plotMargin.top;
    const y2 = plotMargin.top + plotHeight;
    const ticks = (axisOptions == null ? void 0 : axisOptions.ticks) || getYTickValues($$, id);
    const lineTicks = (axisOptions == null ? void 0 : axisOptions.ticks) || (config[`${prefix}_tick_culling`] && config[`${prefix}_tick_culling_lines`] !== false ? getYTickValues($$, id, void 0, false) : ticks);
    const format = (axisOptions == null ? void 0 : axisOptions.format) || ((_e = (_d = (_c = $$.axis) == null ? void 0 : _c[id]) == null ? void 0 : _d.tickFormat) == null ? void 0 : _e.call(_d)) || ((_f = config[`${prefix}_tick_format`]) == null ? void 0 : _f.bind($$.api)) || ((v) => v);
    const outerTick = axisOptions ? axisOptions.outerTick : config[`${prefix}_tick_outer`];
    const tickDirection = isRotated ? isY2 ? config.axis_y2_tick_inner ? 1 : -1 : config.axis_y_tick_inner ? -1 : 1 : isY2 ? config.axis_y2_tick_inner ? -1 : 1 : config.axis_y_tick_inner ? 1 : -1;
    const outerTickDirection = getYOuterTickDirection(config, isRotated, isY2);
    const tickTextDirection = getYTickTextDirection(isRotated, isY2);
    const tickTextPosition = (axisOptions == null ? void 0 : axisOptions.tickTextPosition) || config[`${prefix}_tick_text_position`] || config[`axis_${id}_tick_text_position`];
    const tickShow = (_g = axisOptions == null ? void 0 : axisOptions.tickShow) != null ? _g : axisOptions ? true : config[`${prefix}_tick_show`];
    const tickTextShow = (_h = axisOptions == null ? void 0 : axisOptions.tickTextShow) != null ? _h : axisOptions ? true : config[`${prefix}_tick_text_show`];
    painter.withState(() => {
      ctx.strokeStyle = axis.lineColor;
      ctx.lineWidth = axis.lineWidth;
      painter.strokePath(() => {
        if (isRotated) {
          painter.traceLine(x1, y, x2, y);
        } else {
          painter.traceLine(x, y1, x, y2);
        }
        if (outerTick) {
          if (isRotated) {
            painter.traceLine(x1, y, x1, y + AXIS_TICK_SIZE * outerTickDirection);
            painter.traceLine(x2, y, x2, y + AXIS_TICK_SIZE * outerTickDirection);
          } else {
            painter.traceLine(x, y1, x + AXIS_TICK_SIZE * outerTickDirection, y1);
            painter.traceLine(x, y2, x + AXIS_TICK_SIZE * outerTickDirection, y2);
          }
        }
      });
      const tickFont = getAxisTickFont(axis, id);
      ctx.font = tickFont;
      ctx.fillStyle = axis.labelColor;
      ctx.textAlign = isRotated ? "center" : tickTextDirection > 0 ? "left" : "right";
      ctx.textBaseline = isRotated ? tickTextDirection > 0 ? "top" : "bottom" : "middle";
      ctx.strokeStyle = axis.tickColor;
      ctx.lineWidth = axis.tickWidth;
      const drawableTicks = [];
      const drawableLineTicks = [];
      const addDrawableTick = (tick, target) => {
        const value = normalizeYValue($$, tick, id);
        const tx = plotMargin.left + targetScale(value);
        const ty = plotMargin.top + targetScale(value);
        const pos = isRotated ? tx : ty;
        if (!isDrawable(pos)) {
          return;
        }
        target.push({ tick, tx, ty });
      };
      for (const tick of ticks) {
        addDrawableTick(tick, drawableTicks);
      }
      for (const tick of lineTicks) {
        addDrawableTick(tick, drawableLineTicks);
      }
      if (tickShow) {
        painter.strokePath(() => {
          for (const { tx, ty } of drawableLineTicks) {
            if (isRotated) {
              painter.traceLine(tx, y, tx, y + AXIS_TICK_SIZE * tickDirection);
            } else {
              painter.traceLine(x, ty, x + AXIS_TICK_SIZE * tickDirection, ty);
            }
          }
        });
      }
      if (tickTextShow) {
        for (const { tick, tx, ty } of drawableTicks) {
          if (isRotated) {
            painter.text(
              formatTick(format, tick),
              tx + (tickTextPosition.x || 0),
              y + AXIS_TICK_SIZE * tickTextDirection + (tickTextPosition.y || 0)
            );
          } else {
            painter.text(
              formatTick(format, tick),
              x + (AXIS_TICK_SIZE + AXIS_TICK_PADDING) * tickTextDirection + (tickTextPosition.x || 0),
              ty + (tickTextPosition.y || 0)
            );
          }
        }
      }
    });
  }
}

;// ./src/canvas/classes.ts
const $CANVAS = {
  canvas: "bb-canvas",
  overlay: "bb-canvas-overlay",
  legend: "bb-canvas-legend",
  legendBottom: "bb-canvas-legend-bottom",
  legendInset: "bb-canvas-legend-inset",
  legendItemInteractive: "bb-legend-item-interactive",
  legendItemTileCircle: "bb-legend-item-tile-circle",
  legendItemTitle: "bb-legend-item-title",
  legendRight: "bb-canvas-legend-right"
};
/* harmony default export */ var classes = ($CANVAS);

;// ./src/canvas/CanvasEngine.ts
var CanvasEngine_defProp = Object.defineProperty;
var CanvasEngine_defNormalProp = (obj, key, value) => key in obj ? CanvasEngine_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var CanvasEngine_publicField = (obj, key, value) => CanvasEngine_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);


class CanvasEngine {
  constructor() {
    CanvasEngine_publicField(this, "canvas");
    CanvasEngine_publicField(this, "ctx");
    CanvasEngine_publicField(this, "dpr", 1);
    CanvasEngine_publicField(this, "frame", null);
    CanvasEngine_publicField(this, "frameCtx", null);
    CanvasEngine_publicField(this, "frameValid", false);
  }
  /**
   * Create and attach the canvas element.
   * @param {HTMLElement} container Chart container
   * @param {number} w Canvas width
   * @param {number} h Canvas height
   * @private
   */
  init(container, w, h) {
    this.canvas = browser_doc.createElement("canvas");
    this.canvas.className = $CANVAS.canvas;
    this.canvas.style.display = "block";
    container.appendChild(this.canvas);
    this.dpr = win.devicePixelRatio || 1;
    this.ctx = this.canvas.getContext("2d");
    this.resize(w, h);
  }
  /**
   * Resize the canvas backing store and CSS box.
   * @param {number} w Canvas width
   * @param {number} h Canvas height
   * @private
   */
  resize(w, h) {
    const width = Math.max(0, w);
    const height = Math.max(0, h);
    this.dpr = win.devicePixelRatio || 1;
    this.canvas.width = width * this.dpr;
    this.canvas.height = height * this.dpr;
    this.canvas.style.width = `${width}px`;
    this.canvas.style.height = `${height}px`;
    this.ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
    this.frame = null;
    this.frameCtx = null;
    this.frameValid = false;
  }
  /**
   * Clear transient overlay drawings by restoring the captured frame.
   * @private
   */
  clearOverlay() {
    this.frameValid && this.restoreFrame();
  }
  /**
   * Draw transient overlay content on the single visible canvas.
   * @param {function} draw Draw callback
   * @private
   */
  withOverlay(draw) {
    const { ctx } = this;
    const hasFrame = this.frameValid;
    if (hasFrame) {
      this.clearOverlay();
    } else {
      this.captureFrame();
    }
    ctx.save();
    ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
    try {
      draw(ctx);
    } finally {
      ctx.restore();
    }
  }
  /**
   * Prepare the context for a new frame.
   * @param {number} w Canvas width
   * @param {number} h Canvas height
   * @private
   */
  beginFrame(w, h) {
    const { ctx } = this;
    this.frameValid = false;
    ctx.save();
    ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
    ctx.clearRect(0, 0, w, h);
  }
  /**
   * Restore context state after drawing a frame.
   * @private
   */
  endFrame() {
    this.ctx.restore();
  }
  /**
   * Capture the rendered frame for focus overlay restoration.
   * @private
   */
  captureFrame() {
    const { canvas } = this;
    this.frameValid = false;
    if (canvas.width && canvas.height) {
      let { frame, frameCtx } = this;
      if (!frame) {
        const newFrame = browser_doc.createElement("canvas");
        frame = newFrame;
        frameCtx = newFrame.getContext("2d");
        this.frame = frame;
        this.frameCtx = frameCtx;
      }
      if (!frame || !frameCtx) {
        return;
      }
      frameCtx.setTransform(1, 0, 0, 1, 0, 0);
      if (frame.width !== canvas.width || frame.height !== canvas.height) {
        frame.width = canvas.width;
        frame.height = canvas.height;
      } else {
        frameCtx.clearRect(0, 0, canvas.width, canvas.height);
      }
      frameCtx.drawImage(canvas, 0, 0);
      this.frameValid = true;
    }
  }
  /**
   * Restore the latest captured frame.
   * @private
   */
  restoreFrame() {
    if (!this.frameValid || !this.frame || !this.frameCtx) {
      return;
    }
    const { canvas, ctx } = this;
    ctx.save();
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(this.frame, 0, 0);
    ctx.restore();
    ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
  }
  /**
   * Remove canvas resources.
   * @private
   */
  destroy() {
    var _a;
    (_a = this.canvas) == null ? void 0 : _a.remove();
    this.frame = null;
    this.frameCtx = null;
    this.frameValid = false;
  }
}

;// ./src/ChartInternal/internals/subchart.util.ts
function isContinuousGridFocusEnabled($$) {
  const { config, state } = $$;
  return !!(config.subchart_grid_focus_continuous && config.subchart_grid_focus !== false && config.subchart_show && config.subchart_brush_enabled === false && state.width2 > 0 && state.height2 > 0);
}
function getMainCoordFromSubchartCoord($$, subCoord) {
  var _a;
  const { config, scale, state } = $$;
  const mainX = scale.zoom || scale.x;
  const subX = scale.subX;
  if (!mainX || !subX) {
    return null;
  }
  const subLength = config.axis_rotated ? state.height2 : state.width2;
  const mainLength = config.axis_rotated ? state.height : state.width;
  const domainValue = (_a = subX.invert) == null ? void 0 : _a.call(subX, subCoord);
  let mainCoord = domainValue == null ? NaN : mainX(domainValue);
  if (!Number.isFinite(mainCoord) && subLength > 0) {
    mainCoord = Math.max(0, Math.min(1, subCoord / subLength)) * mainLength;
  }
  return Number.isFinite(mainCoord) ? Math.max(0, Math.min(mainLength, mainCoord)) : null;
}

;// ./src/ChartInternal/shape/core/barRadius.ts

const RE_PATH_NUMBER = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
const RE_PATH_TOKEN = /([aAcChHlLmMqQsStTvVzZ])|([-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?)/g;
function getArcFlagTokenIndexes(path) {
  const flags = /* @__PURE__ */ new Set();
  let numIndex = -1;
  let argIndex = 0;
  let inArc = false;
  let token;
  RE_PATH_TOKEN.lastIndex = 0;
  while (token = RE_PATH_TOKEN.exec(path)) {
    if (token[1]) {
      inArc = token[1] === "a" || token[1] === "A";
      argIndex = 0;
    } else {
      numIndex++;
      if (inArc) {
        const pos = argIndex % 7;
        if (pos === 2 || pos === 3 || pos === 4) {
          flags.add(numIndex);
        }
        argIndex++;
      }
    }
  }
  return flags;
}
function getBarPathInterpolator(a, b) {
  const flagSet = getArcFlagTokenIndexes(b);
  const segments = [];
  const interpolators = [];
  let bIndex = 0;
  let segIndex = -1;
  let numIndex = -1;
  let am;
  let bm;
  const append = (text) => {
    if (segments[segIndex]) {
      segments[segIndex] += text;
    } else {
      segments[++segIndex] = text;
    }
  };
  RE_PATH_NUMBER.lastIndex = 0;
  const reA = RE_PATH_NUMBER;
  const reB = new RegExp(RE_PATH_NUMBER.source, "g");
  a += "";
  b += "";
  while ((am = reA.exec(a)) && (bm = reB.exec(b))) {
    numIndex++;
    if (bm.index > bIndex) {
      append(b.slice(bIndex, bm.index));
    }
    if (am[0] === bm[0]) {
      append(bm[0]);
    } else {
      const from = +am[0];
      const to = +bm[0];
      const isFlag = flagSet.has(numIndex);
      segments[++segIndex] = null;
      interpolators.push({
        index: segIndex,
        fn: isFlag ? (t) => Math.round(from + (to - from) * t) : (t) => from + (to - from) * t
      });
    }
    bIndex = reB.lastIndex;
  }
  if (bIndex < b.length) {
    append(b.slice(bIndex));
  }
  if (!interpolators.length) {
    const result = segments.join("");
    return () => result;
  }
  return (t) => {
    for (let i = 0, len = interpolators.length; i < len; i++) {
      const { index, fn } = interpolators[i];
      segments[index] = String(fn(t));
    }
    return segments.join("");
  };
}
function getBarRadiusResolver($$) {
  const { bar_radius: radius, bar_radius_ratio: ratio } = $$.config;
  return isNumber(radius) && radius > 0 ? () => radius : isNumber(ratio) ? (width) => width * ratio : null;
}
function getStackingBarRadiusSet($$) {
  const { config, data } = $$;
  const set = /* @__PURE__ */ new Set();
  if (!config.data_groups.length) {
    return set;
  }
  const orderedTargets = $$.orderTargets(
    $$.filterTargetsToShow(data.targets.filter($$.isBarType, $$))
  );
  for (const group of config.data_groups) {
    const ids = new Set(group);
    const lastPosByIndex = /* @__PURE__ */ new Map();
    const lastNegByIndex = /* @__PURE__ */ new Map();
    for (const target of orderedTargets) {
      if (!ids.has(target.id)) {
        continue;
      }
      for (const d of target.values) {
        if (d.value === null || d.value === 0) {
          continue;
        }
        (d.value > 0 ? lastPosByIndex : lastNegByIndex).set(d.index, target.id);
      }
    }
    for (const [index, id] of lastPosByIndex) {
      set.add(`${id}:${index}`);
    }
    for (const [index, id] of lastNegByIndex) {
      set.add(`${id}:${index}`);
    }
  }
  return set;
}
function getBarRadiusCorners(isRotated, isNegative, radius) {
  if (!radius) {
    return 0;
  }
  return isRotated ? isNegative ? { tl: radius, bl: radius } : { tr: radius, br: radius } : isNegative ? { br: radius, bl: radius } : { tl: radius, tr: radius };
}
function getBarRadiusClipPath(init, pos, isRotated, isNegative) {
  let clipPath = "";
  if (isRotated) {
    if (isNegative && init[0] < pos) {
      clipPath = `0 ${pos - init[0]}px 0 0`;
    } else if (!isNegative && init[0] > pos) {
      clipPath = `0 0 0 ${init[0] - pos}px`;
    }
  } else {
    if (isNegative && init[1] > pos) {
      clipPath = `${init[1] - pos}px 0 0 0`;
    } else if (!isNegative && init[1] < pos) {
      clipPath = `0 0 ${pos - init[1]}px 0`;
    }
  }
  return clipPath ? `inset(${clipPath})` : null;
}
function getBarRadiusInfo($$, d, points, getRadius, stackingRadiusSet, isStackingRadiusData) {
  const { config, state } = $$;
  const isRotated = config.axis_rotated;
  const indexX = +isRotated;
  const indexY = +!indexX;
  const isUnderZero = d.value < 0;
  const isInverted = config[`axis_${$$.axis.getId(d.id)}_inverted`];
  const isNegative = !isInverted && isUnderZero || isInverted && !isUnderZero;
  const isGrouped = $$.isGrouped(d.id);
  const isRadiusData = getRadius && isGrouped && d.value !== 0 ? state.hiddenTargetIds.has(d.id) && isStackingRadiusData ? isStackingRadiusData(d) : stackingRadiusSet.has(`${d.id}:${d.index}`) : false;
  const init = [
    points[0][indexX],
    points[0][indexY]
  ];
  let radius = 0;
  if (getRadius) {
    const index = isRotated ? indexY : indexX;
    const barW = Math.abs(points[2][index] - points[0][index]);
    radius = Math.max(0, !isGrouped || isRadiusData ? getRadius(barW) : 0);
  }
  const pos = isRotated ? points[1][indexX] + (isNegative ? radius : -radius) : points[1][indexY] + (isNegative ? -radius : radius);
  return {
    radius,
    corners: getBarRadiusCorners(isRotated, isNegative, radius),
    clipPath: radius ? getBarRadiusClipPath(init, pos, isRotated, isNegative) : null,
    indexX,
    indexY,
    isNegative,
    pos
  };
}

;// ./src/ChartInternal/shape/core/dataRegion.ts

const DEFAULT_DASHARRAY = "2 2";
function normalizeDataRegions($$, values, regions) {
  const isTimeSeries = $$.axis.isTimeSeries();
  const getValue = (value, fallback) => isUndefined(value) ? fallback : isTimeSeries ? parseDate.call($$, value) : value;
  return (regions || []).map((region) => {
    var _a, _b;
    return {
      start: getValue(region.start, (_a = values[0]) == null ? void 0 : _a.x),
      end: getValue(region.end, (_b = values[values.length - 1]) == null ? void 0 : _b.x),
      style: region.style || { dasharray: DEFAULT_DASHARRAY }
    };
  });
}
function getDataRegionStyle(x, regions) {
  for (let i = 0, region; region = regions[i]; i++) {
    if (region.start < x && x <= region.end) {
      return region.style;
    }
  }
  return false;
}
function getDataRegionDash(style) {
  const dash = String((style == null ? void 0 : style.dasharray) || DEFAULT_DASHARRAY).split(/[\s,]+/).map(Number).filter(Number.isFinite);
  return dash.length ? dash : [2, 2];
}
function getLineRegionSegments($$, values, x, y, regions) {
  const isRotated = $$.config.axis_rotated;
  const normalizedRegions = normalizeDataRegions($$, values, regions);
  const segments = [];
  for (let i = 1; i < values.length; i++) {
    const prev = values[i - 1];
    const current = values[i];
    if (!isValue(prev.value) || !isValue(current.value)) {
      segments.push({ isBreak: true });
      continue;
    }
    const style = getDataRegionStyle(current.x, normalizedRegions);
    const x0 = x(prev.x);
    const y0 = y(prev.value);
    const x1 = x(current.x);
    const y1 = y(current.value);
    segments.push({
      start: isRotated ? [y0, x0] : [x0, y0],
      end: isRotated ? [y1, x1] : [x1, y1],
      dash: style ? getDataRegionDash(style) : []
    });
  }
  return segments;
}

;// ./src/ChartInternal/shape/core/geometry.ts
function getRenderPoint($$, point) {
  return $$.config.axis_rotated ? [point[1], point[0]] : [point[0], point[1]];
}
function getRenderRect($$, points, minSize = 1) {
  const renderPoints = points.map((point) => getRenderPoint($$, point));
  const xs = renderPoints.map(([x]) => x);
  const ys = renderPoints.map(([, y]) => y);
  const rawX = Math.min(...xs);
  const rawY = Math.min(...ys);
  const rawW = Math.max(...xs) - rawX;
  const rawH = Math.max(...ys) - rawY;
  const w = Math.max(minSize, rawW);
  const h = Math.max(minSize, rawH);
  return {
    x: rawX - (w - rawW) / 2,
    y: rawY - (h - rawH) / 2,
    w,
    h
  };
}
function getRenderDataPoint($$, d) {
  var _a, _b;
  const value = ((_a = $$.isGrouped) == null ? void 0 : _a.call($$, d.id)) && $$.circleY ? $$.circleY(d, d.index) : $$.getYScaleById(d.id)($$.getBaseValue(d));
  const index = (_b = $$.xx(d)) != null ? _b : NaN;
  return $$.config.axis_rotated ? { x: value, y: index } : { x: index, y: value };
}
function getShapePoint(pos, d, i) {
  return {
    x: pos.cx(d, i),
    y: pos.cy(d, i)
  };
}
function getCandlestickGeometry($$, points) {
  return {
    body: getRenderRect($$, [points[0], points[1]]),
    wickStart: getRenderPoint($$, [points[2][0], points[2][1]]),
    wickEnd: getRenderPoint($$, [points[2][0], points[2][2]])
  };
}
function getTreemapNodeRect($$, node, root, clamp = false) {
  if (node === root) {
    return {
      x: 0,
      y: 0,
      w: $$.state.width,
      h: 0
    };
  }
  const { scale: { x, y } } = $$;
  const left = x(node.x0);
  const top = y(node.y0);
  const w = x(node.x1) - left;
  const h = y(node.y1) - top;
  return {
    x: left,
    y: top,
    w: clamp ? Math.max(0, w) : w,
    h: clamp ? Math.max(0, h) : h
  };
}
function getTreemapLabelText($$, data, width, height) {
  const { config } = $$;
  const { id, value, ratio = 0 } = data;
  const format = config.treemap_label_format;
  const text = typeof format === "function" ? format.bind($$.api)(value, ratio, id, { width, height }) : `${id}
${(ratio * 100).toFixed(2)}%`;
  return text === null || text === void 0 ? null : String(text);
}

// EXTERNAL MODULE: external {"commonjs":"d3-shape","commonjs2":"d3-shape","amd":"d3-shape","root":"d3"}
var external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_ = __webpack_require__(4);
;// ./src/ChartInternal/shape/core/path.ts
var path_defProp = Object.defineProperty;
var path_defProps = Object.defineProperties;
var path_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var path_getOwnPropSymbols = Object.getOwnPropertySymbols;
var path_hasOwnProp = Object.prototype.hasOwnProperty;
var path_propIsEnum = Object.prototype.propertyIsEnumerable;
var path_defNormalProp = (obj, key, value) => key in obj ? path_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var path_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (path_hasOwnProp.call(b, prop))
      path_defNormalProp(a, prop, b[prop]);
  if (path_getOwnPropSymbols)
    for (var prop of path_getOwnPropSymbols(b)) {
      if (path_propIsEnum.call(b, prop))
        path_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var path_spreadProps = (a, b) => path_defProps(a, path_getOwnPropDescs(b));

function getPathValueFn($$, isSub) {
  if (!isSub) {
    return (d) => $$.getBaseValue(d);
  }
  return (d) => {
    var _a;
    const value = (_a = $$.getSubchartCandlestickShapeValue) == null ? void 0 : _a.call($$, d, true);
    return value === void 0 ? $$.getBaseValue(d) : value;
  };
}
function getProjectedValues($$, values, isSub) {
  if (!isSub) {
    return values;
  }
  return values.map((d) => {
    var _a;
    const value = (_a = $$.getSubchartCandlestickShapeValue) == null ? void 0 : _a.call($$, d, isSub);
    return value === void 0 ? d : path_spreadProps(path_spreadValues({}, d), { value });
  });
}
function getLineValues($$, d, values) {
  return $$.isStepType(d) ? $$.convertValuesToStep(values) : values;
}
function generateDrawLinePath($$, lineIndices, isSub, context) {
  const { config, scale } = $$;
  const lineConnectNull = config.line_connectNull;
  const isRotated = config.axis_rotated;
  const getPoints = $$.generateGetLinePoints(lineIndices, isSub);
  const yScale = $$.getYScaleById.bind($$);
  const pathValue = getPathValueFn($$, isSub);
  const xValue = (d) => (isSub ? $$.subxx : $$.xx).call($$, d);
  const yValue = (d, i) => $$.isGrouped(d.id) ? getPoints(d, i)[0][1] : yScale(d.id, isSub)(
    pathValue(d)
  );
  let line = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.line)();
  line = isRotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
  context && (line = line.context(context));
  if (!lineConnectNull) {
    line = line.defined((d) => pathValue(d) !== null);
  }
  const x = isSub ? scale.subX : scale.x;
  return (d) => {
    const y = yScale(d.id, isSub);
    let values = lineConnectNull ? $$.filterRemoveNull(d.values) : d.values;
    let x0 = 0;
    let y0 = 0;
    let path;
    if ($$.isLineType(d)) {
      const regions = config.data_regions[d.id];
      if (regions && !context && $$.lineWithRegions) {
        values = getProjectedValues($$, values, isSub);
        if ($$.isAreaRangeType(d)) {
          values = values.map((dv) => path_spreadProps(path_spreadValues({}, dv), { value: $$.getRangedData(dv, "mid") }));
        }
        if ($$.isStepType(d)) {
          values = $$.convertValuesToStep(values);
        }
        path = $$.lineWithRegions(values, scale.zoom || x, y, regions);
      } else {
        path = line.curve($$.getCurve(d))(getLineValues($$, d, values));
      }
    } else {
      if (values[0]) {
        x0 = x(values[0].x);
        y0 = y(pathValue(values[0]));
      }
      path = isRotated ? `M ${y0} ${x0}` : `M ${x0} ${y0}`;
    }
    return path || (context ? void 0 : "M 0 0");
  };
}
function generateDrawAreaPath($$, areaIndices, isSub, context) {
  const { config } = $$;
  const lineConnectNull = config.line_connectNull;
  const isRotated = config.axis_rotated;
  const getPoints = $$.generateGetAreaPoints(areaIndices, isSub);
  const yScale = $$.getYScaleById.bind($$);
  const pathValue = getPathValueFn($$, isSub);
  const shapeYMin = /* @__PURE__ */ new Map();
  const getShapeYMin = (id) => {
    let min = shapeYMin.get(id);
    if (min === void 0) {
      min = $$.getShapeYMin(id, isSub);
      shapeYMin.set(id, min);
    }
    return min;
  };
  const xValue = (d) => (isSub ? $$.subxx : $$.xx).call($$, d);
  const value0 = (d, i) => $$.isGrouped(d.id) ? getPoints(d, i)[0][1] : yScale(d.id, isSub)(
    $$.isAreaRangeType(d) ? $$.getRangedData(d, "high") : getShapeYMin(d.id)
  );
  const value1 = (d, i) => $$.isGrouped(d.id) ? getPoints(d, i)[1][1] : yScale(d.id, isSub)(
    $$.isAreaRangeType(d) ? $$.getRangedData(d, "low") : pathValue(d)
  );
  return (d) => {
    let values = lineConnectNull ? $$.filterRemoveNull(d.values) : d.values;
    let x0 = 0;
    let y0 = 0;
    let path;
    if ($$.isAreaType(d)) {
      let area = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.area)();
      area = isRotated ? area.y(xValue).x0(value0).x1(value1) : area.x(xValue).y0(config.area_above ? 0 : config.area_below ? isSub ? $$.state.height2 : $$.state.height : value0).y1(value1);
      context && (area = area.context(context));
      if (!lineConnectNull) {
        area = area.defined((d2) => pathValue(d2) !== null);
      }
      values = getProjectedValues($$, values, isSub);
      if ($$.isStepType(d)) {
        values = $$.convertValuesToStep(values);
      }
      path = area.curve($$.getCurve(d))(values);
    } else {
      if (values[0]) {
        x0 = (isSub ? $$.scale.subX : $$.scale.x)(values[0].x);
        y0 = $$.getYScaleById(d.id, isSub)(pathValue(values[0]));
      }
      path = isRotated ? `M ${y0} ${x0}` : `M ${x0} ${y0}`;
    }
    return path || (context ? void 0 : "M 0 0");
  };
}

;// ./src/canvas/color.ts


let colorParserContext;
function withOpacity(color, opacity) {
  if (!isNumber(opacity) || opacity >= 1) {
    return color;
  }
  const hex = color.match(/^#([\da-f]{3}|[\da-f]{6})$/i);
  if (hex) {
    const value = hex[1].length === 3 ? hex[1].split("").map((v) => v + v).join("") : hex[1];
    const matches = value.match(/.{2}/g);
    if (!matches) {
      return color;
    }
    const rgb = matches.map((v) => parseInt(v, 16));
    return `rgba(${rgb.join(",")},${opacity})`;
  }
  if (/^rgb\(/i.test(color)) {
    return color.replace(/^rgb\((.*)\)$/i, `rgba($1,${opacity})`);
  }
  if (/^rgba\(/i.test(color)) {
    return color.replace(
      /^rgba\((.*),\s*([\d.]+)\)$/i,
      (_, rgb, alpha) => `rgba(${rgb},${Number(alpha) * opacity})`
    );
  }
  const parsed = parseCanvasColor(color);
  if (parsed && parsed !== color) {
    return withOpacity(parsed, opacity);
  }
  return color;
}
function parseCanvasColor(color) {
  if (!win.document) {
    return null;
  }
  if (colorParserContext === void 0) {
    colorParserContext = win.document.createElement("canvas").getContext("2d");
  }
  if (!colorParserContext) {
    return null;
  }
  colorParserContext.fillStyle = "#000";
  colorParserContext.fillStyle = color;
  const parsedOnBlack = colorParserContext.fillStyle;
  colorParserContext.fillStyle = "#fff";
  colorParserContext.fillStyle = color;
  const parsedOnWhite = colorParserContext.fillStyle;
  return parsedOnBlack === parsedOnWhite ? parsedOnBlack : null;
}

;// ./src/canvas/geometry.ts


function getCanvasBarGeometry($$, getPoints, d, index) {
  const points = getPoints(d, index);
  const rect = getRenderRect($$, points);
  return isFiniteCanvasCoordinate(rect.x, rect.y) && isFiniteCanvasCoordinate(rect.x + rect.w, rect.y + rect.h) ? { points, rect } : null;
}
function getCanvasCandlestickGeometry($$, getPoints, d, index) {
  const points = getPoints(d, index);
  const { body, wickStart, wickEnd } = getCandlestickGeometry($$, points);
  return isFiniteCanvasCoordinate(body.x, body.y) && isFiniteCanvasCoordinate(body.x + body.w, body.y + body.h) && isFiniteCanvasCoordinate(wickStart[0], wickStart[1]) && isFiniteCanvasCoordinate(wickEnd[0], wickEnd[1]) ? { body, points, wickStart, wickEnd } : null;
}

;// ./src/canvas/labels.ts


const LABEL_LINE_HEIGHT_RATIO = 1.2;
function getLabelValue($$, d) {
  var _a, _b, _c;
  let { value } = d;
  if ((_a = $$.isBubbleZType) == null ? void 0 : _a.call($$, d)) {
    value = $$.getBubbleZData(value, "z");
  } else if ((_b = $$.isCandlestickType) == null ? void 0 : _b.call($$, d)) {
    const data = (_c = $$.getCandlestickData) == null ? void 0 : _c.call($$, d);
    if (data) {
      value = data.close;
    }
  }
  return value;
}
function getLabelText($$, d) {
  const value = $$.dataLabelFormat(d.id)(getLabelValue($$, d), d.id, d.index, []);
  return value === null || value === void 0 ? null : String(value);
}
function getLabelRowKey(d) {
  return `${d.id}:${d.index}`;
}
function getExpandedFocusMatcher($$, selectedData, typeFilter) {
  var _a;
  if (!(selectedData == null ? void 0 : selectedData.length)) {
    return () => false;
  }
  if ($$.config.tooltip_grouped && selectedData.length > 1) {
    const index = (_a = selectedData[0]) == null ? void 0 : _a.index;
    return (d) => index !== void 0 && d.index === index && typeFilter($$, d);
  }
  const keys = new Set(
    selectedData.filter((d) => d && typeFilter($$, d)).map(getLabelRowKey)
  );
  return (d) => keys.has(getLabelRowKey(d));
}
function getLabelPosition($$, d, type, texts) {
  const position = $$.config.data_labels_position;
  let value;
  if (isFunction(position)) {
    value = position.bind($$.api)(type, getLabelValue($$, d), d.id, d.index, texts);
  } else if (position) {
    const targetPosition = d.id in position ? position[d.id] : position;
    value = targetPosition == null ? void 0 : targetPosition[type];
  }
  return isNumber(value) ? value : 0;
}
function getLabelImageOption($$, d) {
  var _a, _b;
  const option = (_a = $$.config.data_labels) == null ? void 0 : _a.image;
  if (isFunction(option)) {
    return (_b = option.call($$.api, getLabelValue($$, d), d.id, d.index)) != null ? _b : null;
  } else if (option) {
    const { url = "", width = 0, height = 0, pos } = option;
    return { url, width, height, pos };
  }
  return null;
}
function getLabelImageUrl(option, d) {
  return tplProcess(option.url, {
    ID: d.id
  });
}
function getLabelImagePosition($$, option, text, x, y, d) {
  var _a, _b, _c;
  const { width = 0, height = 0, pos } = option;
  const w = width / 2;
  const h = height / 2;
  const textHeight = getLabelDecorationBox($$.canvasEngine.ctx, text, x, y).h;
  const fontSize = getFontSize($$.canvasEngine.ctx.font);
  const imageX = x - w;
  const imageY = y - h - (((_a = $$.isTreemapType) == null ? void 0 : _a.call($$, d)) ? fontSize * 0.7 : textHeight / 2);
  let textX = x;
  let textY = y;
  if ($$.config.axis_rotated) {
    textX += w;
  } else {
    textY += h;
  }
  return {
    x: imageX + ((_b = pos == null ? void 0 : pos.x) != null ? _b : 0),
    y: imageY + ((_c = pos == null ? void 0 : pos.y) != null ? _c : 0),
    textX,
    textY
  };
}
function getLabelColor($$, d, fallback) {
  var _a, _b, _c;
  const color = (_a = $$.updateTextColor) == null ? void 0 : _a.call($$, d);
  return typeof color === "string" ? color : ((_b = $$.isTreemapType) == null ? void 0 : _b.call($$, d)) ? fallback : ((_c = $$.color) == null ? void 0 : _c.call($$, d)) || fallback;
}
function getLabelBackgroundColor($$, d) {
  var _a;
  const option = $$.config.data_labels_backgroundColors;
  if (!option) {
    return null;
  }
  if (isString(option)) {
    return option;
  }
  if (isFunction(option)) {
    const defaultColor = (_a = $$.color) == null ? void 0 : _a.call($$, d);
    const color2 = option.bind($$.api)(defaultColor, d);
    return color2 === null || color2 === void 0 ? null : String(color2);
  }
  const color = option[d.id];
  return color === null || color === void 0 ? null : String(color);
}
function getLabelBorderOption(border) {
  var _a, _b, _c;
  if (!border) {
    return null;
  }
  const option = isObject(border) ? border : {};
  return {
    padding: parseShorthand((_a = option.padding) != null ? _a : "3 5"),
    radius: isNumber(option.radius) ? option.radius : 10,
    stroke: (_b = option.stroke) != null ? _b : "#000",
    strokeWidth: isNumber(option.strokeWidth) ? option.strokeWidth : 1,
    fill: (_c = option.fill) != null ? _c : "none"
  };
}
function getLabelDecorationBox(ctx, text, x, y, padding = { top: 0, right: 0, bottom: 0, left: 0 }) {
  var _a, _b;
  const lines = text.split("\n");
  const metrics = lines.map((line) => ctx.measureText(line));
  const width = Math.max(...metrics.map((metric) => metric.width), 0);
  const fontSize = getFontSize(ctx.font);
  const lineHeight = fontSize * LABEL_LINE_HEIGHT_RATIO;
  const fontBoundingHeight = metrics[0] ? (metrics[0].fontBoundingBoxAscent || 0) + (metrics[0].fontBoundingBoxDescent || 0) : 0;
  const baselineDescent = metrics[0] ? metrics[0].fontBoundingBoxDescent || metrics[0].actualBoundingBoxDescent || 0 : 0;
  const height = lines.length > 1 ? lineHeight * lines.length : Math.max(
    fontSize,
    fontBoundingHeight,
    ((_a = metrics[0]) == null ? void 0 : _a.actualBoundingBoxAscent) + ((_b = metrics[0]) == null ? void 0 : _b.actualBoundingBoxDescent) || 0
  );
  let textX = x;
  let textY = y;
  if (ctx.textAlign === "center") {
    textX -= width / 2;
  } else if (ctx.textAlign === "right" || ctx.textAlign === "end") {
    textX -= width;
  }
  if (ctx.textBaseline === "middle") {
    textY -= height / 2;
  } else if (ctx.textBaseline === "alphabetic") {
    textY -= height - baselineDescent;
  } else if (ctx.textBaseline === "bottom" || ctx.textBaseline === "ideographic") {
    textY -= height;
  }
  return {
    x: textX - padding.left,
    y: textY - padding.top,
    w: width + padding.left + padding.right,
    h: height + padding.top + padding.bottom
  };
}
function drawLabelDecorations($$, painter, d, text, x, y) {
  var _a, _b;
  const ctx = painter.context;
  const backgroundColor = getLabelBackgroundColor($$, d);
  const border = getLabelBorderOption((_a = $$.config.data_labels) == null ? void 0 : _a.border);
  const padding = (_b = border == null ? void 0 : border.padding) != null ? _b : { top: 0, right: 0, bottom: 0, left: 0 };
  const box = getLabelDecorationBox(ctx, text, x, y, padding);
  const angle = $$.config.data_labels.rotate;
  painter.withState((canvas) => {
    var _a2;
    if (angle) {
      canvas.translate(x, y);
      canvas.rotate(angle * Math.PI / 180);
      box.x -= x;
      box.y -= y;
    }
    if (backgroundColor) {
      painter.fillRoundRect(box, (_a2 = border == null ? void 0 : border.radius) != null ? _a2 : 0, { fill: backgroundColor });
    }
    if (border) {
      if (border.fill !== "none") {
        painter.fillRoundRect(box, border.radius, { fill: border.fill });
      }
      painter.strokeRoundRect(box, border.radius, {
        stroke: border.stroke,
        lineWidth: border.strokeWidth
      });
    }
  });
}
function getLabelRotateAnchor(angle) {
  let anchor = "middle";
  if (angle > 0 && angle <= 170) {
    anchor = "end";
  } else if (angle > 190 && angle <= 360) {
    anchor = "start";
  }
  return anchor;
}
function getCanvasTextAlign(anchor) {
  return anchor === "start" ? "left" : anchor === "end" ? "right" : "center";
}
function getRotatedLabelPosition($$, d, x, y) {
  var _a, _b, _c;
  const anchor = getLabelRotateAnchor($$.config.data_labels.rotate);
  const isRotated = $$.config.axis_rotated;
  const isInverted = $$.config[`axis_${(_a = $$.axis) == null ? void 0 : _a.getId(d.id)}_inverted`];
  const isCandlestickType = isCanvasCandlestickType($$, d);
  const { value } = d;
  const isNegative = isNumber(value) && value < 0 || isCandlestickType && !((_c = (_b = $$.getCandlestickData) == null ? void 0 : _b.call($$, d)) == null ? void 0 : _c._isUp);
  const gap = 4;
  const doubleGap = gap * 2;
  if (isRotated) {
    if (anchor === "start") {
      x += isNegative ? 0 : doubleGap;
      y += gap;
    } else if (anchor === "middle") {
      x += doubleGap;
      y -= doubleGap;
    } else if (anchor === "end") {
      isNegative && (x -= doubleGap);
      y += gap;
    }
  } else {
    if (anchor === "start") {
      x += gap;
      isNegative && (y += doubleGap * 2);
    } else if (anchor === "middle") {
      y -= doubleGap;
    } else if (anchor === "end") {
      x -= gap;
      isNegative && (y += doubleGap * 2);
    }
    if (isInverted) {
      y += isNegative ? -17 : isCandlestickType ? 13 : 7;
    }
  }
  return {
    x,
    y,
    textAlign: getCanvasTextAlign(anchor)
  };
}
function getPointLabelAnchor($$, ctx, d, x, y) {
  var _a;
  if ($$.config.axis_rotated) {
    x += 6;
    ctx.textAlign = "left";
    ctx.textBaseline = "middle";
  } else if (isCanvasBubbleType($$, d)) {
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
  } else {
    const { config, state } = $$;
    const isInverted = config[`axis_${(_a = $$.axis) == null ? void 0 : _a.getId(d.id)}_inverted`];
    const isNegative = d.value < 0 || d.value === 0 && !state.hasPositiveValue && state.hasNegativeValue;
    let baseY = 3;
    if (isNumber(config.point_r) && config.point_r > 5 && (isCanvasLineType($$, d) || isCanvasScatterType($$, d))) {
      baseY += config.point_r / 2.3;
    }
    ctx.textAlign = "center";
    if (isInverted ? !isNegative : isNegative) {
      y += baseY;
      ctx.textBaseline = "top";
    } else {
      y -= baseY * 2;
      ctx.textBaseline = "bottom";
    }
  }
  return { x, y };
}

;// ./src/canvas/pointPattern.ts
var pointPattern_defProp = Object.defineProperty;
var pointPattern_getOwnPropSymbols = Object.getOwnPropertySymbols;
var pointPattern_hasOwnProp = Object.prototype.hasOwnProperty;
var pointPattern_propIsEnum = Object.prototype.propertyIsEnumerable;
var pointPattern_defNormalProp = (obj, key, value) => key in obj ? pointPattern_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var pointPattern_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (pointPattern_hasOwnProp.call(b, prop))
      pointPattern_defNormalProp(a, prop, b[prop]);
  if (pointPattern_getOwnPropSymbols)
    for (var prop of pointPattern_getOwnPropSymbols(b)) {
      if (pointPattern_propIsEnum.call(b, prop))
        pointPattern_defNormalProp(a, prop, b[prop]);
    }
  return a;
};



const DEFAULT_POINT_VIEWBOX = { x: 0, y: 0, w: 8, h: 8 };
const customPointPatternCache = /* @__PURE__ */ new Map();
const IDENTITY_POINT_MATRIX = [1, 0, 0, 1, 0, 0];
function isBuiltinPointType(type) {
  return type === "circle" || type === "rectangle";
}
function getSvgNumber(node, name, fallback = 0) {
  const value = node.getAttribute(name);
  const parsed = value === null ? NaN : parseFloat(value);
  return Number.isFinite(parsed) ? parsed : fallback;
}
function parseSvgPoints(value) {
  const nums = (value.match(/[-+]?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?/gi) || []).map(Number).filter(Number.isFinite);
  const points = [];
  for (let i = 0; i < nums.length - 1; i += 2) {
    points.push([nums[i], nums[i + 1]]);
  }
  return points;
}
function parseViewBox(value) {
  const values = (value == null ? void 0 : value.trim().split(/[\s,]+/).map(Number).filter(Number.isFinite)) || [];
  return values.length === 4 ? {
    x: values[0],
    y: values[1],
    w: values[2],
    h: values[3]
  } : null;
}
function getPointsBox(points) {
  const xs = points.map(([x2]) => x2);
  const ys = points.map(([, y2]) => y2);
  const x = Math.min(...xs);
  const y = Math.min(...ys);
  return {
    x,
    y,
    w: Math.max(...xs) - x,
    h: Math.max(...ys) - y
  };
}
function mergePointBoxes(boxes) {
  const validBoxes = boxes.filter(
    (box) => Number.isFinite(box.x) && Number.isFinite(box.y) && Number.isFinite(box.w) && Number.isFinite(box.h)
  );
  if (!validBoxes.length) {
    return pointPattern_spreadValues({}, DEFAULT_POINT_VIEWBOX);
  }
  const x = Math.min(...validBoxes.map((box) => box.x));
  const y = Math.min(...validBoxes.map((box) => box.y));
  const right = Math.max(...validBoxes.map((box) => box.x + box.w));
  const bottom = Math.max(...validBoxes.map((box) => box.y + box.h));
  return {
    x,
    y,
    w: right - x,
    h: bottom - y
  };
}
function multiplyPointMatrix(a, b) {
  return [
    a[0] * b[0] + a[2] * b[1],
    a[1] * b[0] + a[3] * b[1],
    a[0] * b[2] + a[2] * b[3],
    a[1] * b[2] + a[3] * b[3],
    a[0] * b[4] + a[2] * b[5] + a[4],
    a[1] * b[4] + a[3] * b[5] + a[5]
  ];
}
function parsePointTransform(value) {
  let matrix = [...IDENTITY_POINT_MATRIX];
  ((value == null ? void 0 : value.match(/[a-z]+\([^)]*\)/gi)) || []).forEach((token) => {
    var _a;
    const [, rawName, body] = token.match(/^([a-z]+)\(([^)]*)\)$/i) || [];
    const name = rawName == null ? void 0 : rawName.toLowerCase();
    const values = ((body == null ? void 0 : body.match(/[-+]?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?/gi)) || []).map(Number).filter(Number.isFinite);
    let next = null;
    if (name === "matrix" && values.length >= 6) {
      next = values.slice(0, 6);
    } else if (name === "translate" && values.length) {
      next = [1, 0, 0, 1, values[0], values[1] || 0];
    } else if (name === "scale" && values.length) {
      next = [values[0], 0, 0, (_a = values[1]) != null ? _a : values[0], 0, 0];
    } else if (name === "rotate" && values.length) {
      const angle = values[0] * Math.PI / 180;
      const cos = Math.cos(angle);
      const sin = Math.sin(angle);
      const rotate = [cos, sin, -sin, cos, 0, 0];
      next = values.length >= 3 ? multiplyPointMatrix(
        multiplyPointMatrix([1, 0, 0, 1, values[1], values[2]], rotate),
        [1, 0, 0, 1, -values[1], -values[2]]
      ) : rotate;
    } else if (name === "skewx" && values.length) {
      next = [1, 0, Math.tan(values[0] * Math.PI / 180), 1, 0, 0];
    } else if (name === "skewy" && values.length) {
      next = [1, Math.tan(values[0] * Math.PI / 180), 0, 1, 0, 0];
    }
    next && (matrix = multiplyPointMatrix(matrix, next));
  });
  return matrix;
}
function getPointPresentationValue(node, name) {
  const style = node.getAttribute("style");
  const attr = node.getAttribute(name);
  const match = style == null ? void 0 : style.match(new RegExp(`(?:^|;)\\s*${name}\\s*:\\s*([^;]+)`, "i"));
  return ((match == null ? void 0 : match[1]) || attr || "").trim() || null;
}
function parsePointStyle(node, inherited) {
  const style = pointPattern_spreadValues({}, inherited);
  const fill = getPointPresentationValue(node, "fill");
  const stroke = getPointPresentationValue(node, "stroke");
  const strokeWidth = getPointPresentationValue(node, "stroke-width");
  const opacity = getPointPresentationValue(node, "opacity");
  const fillOpacity = getPointPresentationValue(node, "fill-opacity");
  const strokeOpacity = getPointPresentationValue(node, "stroke-opacity");
  if (fill) {
    style.fill = fill === "none" ? null : fill;
  }
  if (stroke) {
    style.stroke = stroke === "none" ? null : stroke;
  }
  if (strokeWidth) {
    const lineWidth = parseFloat(strokeWidth);
    Number.isFinite(lineWidth) && (style.lineWidth = lineWidth);
  }
  [opacity, fillOpacity, strokeOpacity].forEach((value) => {
    var _a;
    const alpha = value === null ? NaN : parseFloat(value);
    Number.isFinite(alpha) && (style.alpha = ((_a = style.alpha) != null ? _a : 1) * alpha);
  });
  return style;
}
function collectPointDefs(root) {
  const defs = /* @__PURE__ */ new Map();
  Array.from(root.querySelectorAll("[id]")).forEach((node) => {
    const id = node.getAttribute("id");
    id && defs.set(id, node);
  });
  return defs;
}
function parsePointPaintLength(value, fallback) {
  const text = value == null ? void 0 : value.trim();
  if (!text) {
    return fallback;
  }
  return /%$/.test(text) ? text : parseFloat(text);
}
function pointPaintCoord(value, origin, size, fallback) {
  if (typeof value === "number") {
    return Number.isFinite(value) ? value : fallback;
  }
  if (typeof value === "string" && /%$/.test(value)) {
    const percent = parseFloat(value);
    return Number.isFinite(percent) ? origin + size * percent / 100 : fallback;
  }
  const parsed = parseFloat(value != null ? value : "");
  return Number.isFinite(parsed) ? parsed : fallback;
}
function parsePointPaintOffset(value) {
  const text = (value == null ? void 0 : value.trim()) || "0";
  const parsed = parseFloat(text);
  const offset = /%$/.test(text) ? parsed / 100 : parsed;
  return Math.max(0, Math.min(1, Number.isFinite(offset) ? offset : 0));
}
function parsePointPaintStops(node) {
  return Array.from(node.children || []).filter((child) => child.tagName.toLowerCase() === "stop").map((stop) => {
    const color = getPointPresentationValue(stop, "stop-color") || "#000";
    const opacity = getPointPresentationValue(stop, "stop-opacity");
    const parsedOpacity = opacity === null ? NaN : parseFloat(opacity);
    return {
      offset: parsePointPaintOffset(stop.getAttribute("offset")),
      color,
      opacity: Number.isFinite(parsedOpacity) ? parsedOpacity : void 0
    };
  });
}
function collectPointPaints(defs) {
  const paints = /* @__PURE__ */ new Map();
  defs.forEach((node, id) => {
    const tagName = node.tagName.toLowerCase();
    const stops = parsePointPaintStops(node);
    if (!stops.length) {
      return;
    }
    if (tagName === "lineargradient") {
      paints.set(id, {
        type: "linearGradient",
        x1: parsePointPaintLength(node.getAttribute("x1"), "0%"),
        y1: parsePointPaintLength(node.getAttribute("y1"), "0%"),
        x2: parsePointPaintLength(node.getAttribute("x2"), "100%"),
        y2: parsePointPaintLength(node.getAttribute("y2"), "0%"),
        stops
      });
    } else if (tagName === "radialgradient") {
      paints.set(id, {
        type: "radialGradient",
        cx: parsePointPaintLength(node.getAttribute("cx"), "50%"),
        cy: parsePointPaintLength(node.getAttribute("cy"), "50%"),
        r: parsePointPaintLength(node.getAttribute("r"), "50%"),
        fx: parsePointPaintLength(node.getAttribute("fx"), "50%"),
        fy: parsePointPaintLength(node.getAttribute("fy"), "50%"),
        fr: parsePointPaintLength(node.getAttribute("fr"), 0),
        stops
      });
    }
  });
  return paints;
}
function parseCustomPointNode(node, fallbackBox, defs, matrix = IDENTITY_POINT_MATRIX, inheritedStyle = {}, seen = /* @__PURE__ */ new Set()) {
  const tagName = node.tagName.toLowerCase();
  const children = Array.from(node.children || []);
  const style = parsePointStyle(node, inheritedStyle);
  const transform = multiplyPointMatrix(
    matrix,
    parsePointTransform(node.getAttribute("transform"))
  );
  const shapeBase = { matrix: transform, style };
  if (tagName === "defs") {
    return [];
  }
  if (tagName === "svg" || tagName === "g" || tagName === "symbol") {
    return children.reduce(
      (shapes, child) => shapes.concat(
        parseCustomPointNode(child, fallbackBox, defs, transform, style, seen)
      ),
      []
    );
  }
  if (tagName === "use") {
    const href = node.getAttribute("href") || node.getAttribute("xlink:href") || "";
    const id = href.charAt(0) === "#" ? href.slice(1) : "";
    const target = id && defs.get(id);
    if (!target || seen.has(id)) {
      return [];
    }
    const x = getSvgNumber(node, "x", 0);
    const y = getSvgNumber(node, "y", 0);
    const useTransform = multiplyPointMatrix(transform, [1, 0, 0, 1, x, y]);
    seen.add(id);
    const shapes = parseCustomPointNode(target, fallbackBox, defs, useTransform, style, seen);
    seen.delete(id);
    return shapes;
  }
  if (tagName === "polygon" || tagName === "polyline") {
    const points = parseSvgPoints(node.getAttribute("points") || "");
    return points.length ? [pointPattern_spreadValues({
      type: tagName,
      points,
      box: getPointsBox(points)
    }, shapeBase)] : [];
  }
  if (tagName === "circle") {
    const cx = getSvgNumber(node, "cx", 0);
    const cy = getSvgNumber(node, "cy", 0);
    const r = getSvgNumber(node, "r", 0);
    return r > 0 ? [pointPattern_spreadValues({
      type: "circle",
      cx,
      cy,
      r,
      box: { x: cx - r, y: cy - r, w: r * 2, h: r * 2 }
    }, shapeBase)] : [];
  }
  if (tagName === "ellipse") {
    const cx = getSvgNumber(node, "cx", 0);
    const cy = getSvgNumber(node, "cy", 0);
    const rx = getSvgNumber(node, "rx", 0);
    const ry = getSvgNumber(node, "ry", 0);
    return rx > 0 && ry > 0 ? [pointPattern_spreadValues({
      type: "ellipse",
      cx,
      cy,
      rx,
      ry,
      box: { x: cx - rx, y: cy - ry, w: rx * 2, h: ry * 2 }
    }, shapeBase)] : [];
  }
  if (tagName === "rect") {
    const x = getSvgNumber(node, "x", 0);
    const y = getSvgNumber(node, "y", 0);
    const w = getSvgNumber(node, "width", 0);
    const h = getSvgNumber(node, "height", 0);
    return w > 0 && h > 0 ? [pointPattern_spreadValues({
      type: "rect",
      x,
      y,
      w,
      h,
      box: { x, y, w, h }
    }, shapeBase)] : [];
  }
  if (tagName === "line") {
    const x1 = getSvgNumber(node, "x1", 0);
    const y1 = getSvgNumber(node, "y1", 0);
    const x2 = getSvgNumber(node, "x2", 0);
    const y2 = getSvgNumber(node, "y2", 0);
    return [pointPattern_spreadValues({
      type: "line",
      x1,
      y1,
      x2,
      y2,
      box: getPointsBox([[x1, y1], [x2, y2]])
    }, shapeBase)];
  }
  if (tagName === "path") {
    const d = node.getAttribute("d") || "";
    return d ? [pointPattern_spreadValues({
      type: "path",
      d,
      box: fallbackBox
    }, shapeBase)] : [];
  }
  return [];
}
function parseCustomPointPattern(pattern) {
  if (!/^</.test(pattern)) {
    return null;
  }
  if (customPointPatternCache.has(pattern)) {
    return customPointPatternCache.get(pattern) || null;
  }
  let parsed = null;
  try {
    const doc = new win.DOMParser().parseFromString(sanitize(pattern), "image/svg+xml");
    const root = doc.documentElement;
    const fallbackBox = parseViewBox(root.getAttribute("viewBox")) || DEFAULT_POINT_VIEWBOX;
    const defs = collectPointDefs(root);
    const shapes = parseCustomPointNode(root, fallbackBox, defs);
    if (shapes.length) {
      parsed = {
        shapes,
        box: root.tagName.toLowerCase() === "svg" ? fallbackBox : mergePointBoxes(shapes.map((shape) => shape.box)),
        paints: collectPointPaints(defs)
      };
    }
  } catch (e) {
    parsed = null;
  }
  customPointPatternCache.set(pattern, parsed);
  return parsed;
}
function traceCustomPointShape(ctx, shape) {
  if (shape.type === "polygon" || shape.type === "polyline") {
    const [start, ...rest] = shape.points;
    ctx.moveTo(start[0], start[1]);
    rest.forEach(([x, y]) => ctx.lineTo(x, y));
    shape.type === "polygon" && ctx.closePath();
  } else if (shape.type === "circle") {
    ctx.moveTo(shape.cx + shape.r, shape.cy);
    ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2);
  } else if (shape.type === "ellipse") {
    ctx.moveTo(shape.cx + shape.rx, shape.cy);
    ctx.ellipse(shape.cx, shape.cy, shape.rx, shape.ry, 0, 0, Math.PI * 2);
  } else if (shape.type === "rect") {
    ctx.rect(shape.x, shape.y, shape.w, shape.h);
  } else if (shape.type === "line") {
    ctx.moveTo(shape.x1, shape.y1);
    ctx.lineTo(shape.x2, shape.y2);
  }
}
function getCustomPointPaintId(value) {
  const match = value == null ? void 0 : value.match(/^url\(#([^)]+)\)$/);
  return (match == null ? void 0 : match[1]) || null;
}
function createCustomPointPaint(ctx, paint, box) {
  const { x, y, w, h } = box;
  const gradient = paint.type === "linearGradient" ? ctx.createLinearGradient(
    pointPaintCoord(paint.x1, x, w, x),
    pointPaintCoord(paint.y1, y, h, y),
    pointPaintCoord(paint.x2, x, w, x + w),
    pointPaintCoord(paint.y2, y, h, y)
  ) : ctx.createRadialGradient(
    pointPaintCoord(paint.fx, x, w, x + w / 2),
    pointPaintCoord(paint.fy, y, h, y + h / 2),
    pointPaintCoord(paint.fr, x, Math.max(w, h), 0),
    pointPaintCoord(paint.cx, x, w, x + w / 2),
    pointPaintCoord(paint.cy, y, h, y + h / 2),
    Math.max(0.01, pointPaintCoord(paint.r, 0, Math.max(w, h), Math.max(w, h) / 2))
  );
  paint.stops.forEach(({ offset, color, opacity }) => {
    gradient.addColorStop(offset, opacity === void 0 ? color : withOpacity(color, opacity));
  });
  return gradient;
}
function getCustomPointDrawStyle(ctx, base, shapeStyle, paints, box) {
  const style = pointPattern_spreadValues({}, base || {});
  if (shapeStyle.fill !== void 0) {
    if (shapeStyle.fill === null) {
      delete style.fill;
    } else if (getCustomPointPaintId(shapeStyle.fill)) {
      const paint = paints.get(getCustomPointPaintId(shapeStyle.fill));
      paint && (style.fill = createCustomPointPaint(ctx, paint, box));
    } else if (!/^url\(/.test(shapeStyle.fill)) {
      style.fill = shapeStyle.fill;
    }
  }
  if (shapeStyle.stroke !== void 0) {
    if (shapeStyle.stroke === null) {
      delete style.stroke;
    } else if (getCustomPointPaintId(shapeStyle.stroke)) {
      const paint = paints.get(getCustomPointPaintId(shapeStyle.stroke));
      paint && (style.stroke = createCustomPointPaint(ctx, paint, box));
    } else if (!/^url\(/.test(shapeStyle.stroke)) {
      style.stroke = shapeStyle.stroke;
    }
  }
  shapeStyle.lineWidth !== void 0 && (style.lineWidth = shapeStyle.lineWidth);
  return {
    style,
    shouldFill: shapeStyle.fill !== null && (!style.stroke || style.fill !== void 0),
    shouldStroke: shapeStyle.stroke !== null && style.stroke !== void 0,
    alpha: shapeStyle.alpha
  };
}
function drawPointPattern(painter, pattern, x, y, r, style, baseR = r) {
  if (isBuiltinPointType(pattern)) {
    painter.point(pattern, x, y, r, style);
    return;
  }
  const parsed = parseCustomPointPattern(pattern);
  if (!parsed || r <= 0) {
    painter.point("circle", x, y, r, style);
    return;
  }
  painter.withState((ctx) => {
    const { box, paints, shapes } = parsed;
    const scale = baseR > 0 ? r / baseR : 1;
    const drawShape = (shape) => {
      const {
        style: drawStyle,
        shouldFill,
        shouldStroke,
        alpha
      } = getCustomPointDrawStyle(ctx, style, shape.style, paints, box);
      ctx.save();
      painter.applyStyle(drawStyle);
      alpha !== void 0 && (ctx.globalAlpha *= alpha);
      ctx.transform(...shape.matrix);
      ctx.beginPath();
      if (shape.type === "path") {
        if (win.Path2D) {
          const path = shape.path2D || (shape.path2D = new win.Path2D(shape.d));
          shouldFill && ctx.fill(path);
          shouldStroke && ctx.stroke(path);
        }
      } else {
        traceCustomPointShape(ctx, shape);
        shouldFill && ctx.fill();
        shouldStroke && ctx.stroke();
      }
      ctx.restore();
    };
    ctx.translate(
      x - (box.x + box.w / 2) * scale,
      y - (box.y + box.h / 2) * scale
    );
    ctx.scale(scale, scale);
    shapes.forEach(drawShape);
  });
}

;// ./src/canvas/CanvasRenderer.ts
var CanvasRenderer_defProp = Object.defineProperty;
var CanvasRenderer_defProps = Object.defineProperties;
var CanvasRenderer_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var CanvasRenderer_getOwnPropSymbols = Object.getOwnPropertySymbols;
var CanvasRenderer_hasOwnProp = Object.prototype.hasOwnProperty;
var CanvasRenderer_propIsEnum = Object.prototype.propertyIsEnumerable;
var CanvasRenderer_defNormalProp = (obj, key, value) => key in obj ? CanvasRenderer_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var CanvasRenderer_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (CanvasRenderer_hasOwnProp.call(b, prop))
      CanvasRenderer_defNormalProp(a, prop, b[prop]);
  if (CanvasRenderer_getOwnPropSymbols)
    for (var prop of CanvasRenderer_getOwnPropSymbols(b)) {
      if (CanvasRenderer_propIsEnum.call(b, prop))
        CanvasRenderer_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var CanvasRenderer_spreadProps = (a, b) => CanvasRenderer_defProps(a, CanvasRenderer_getOwnPropDescs(b));
var CanvasRenderer_publicField = (obj, key, value) => CanvasRenderer_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);














const RENDERER_GROUPED_TYPE_FILTERS = [
  isCanvasAreaType,
  isCanvasBarType,
  isCanvasPointType,
  isCanvasCandlestickType
];
const MAX_BATCHED_CIRCLE_POINTS = 1e3;
const canvasFocusLookupCache = /* @__PURE__ */ new WeakMap();
const subchartBrushHandlePathCache = /* @__PURE__ */ new Map();
function applyCssMatrixTransform(ctx, transform) {
  if (!transform || transform === "none") {
    return;
  }
  const matrix = transform.match(/^matrix\(([^)]+)\)$/);
  const matrix3d = transform.match(/^matrix3d\(([^)]+)\)$/);
  if (matrix) {
    const values = matrix[1].split(",").map((value) => Number(value.trim()));
    values.length === 6 && values.every(Number.isFinite) && ctx.transform(values[0], values[1], values[2], values[3], values[4], values[5]);
  } else if (matrix3d) {
    const values = matrix3d[1].split(",").map((value) => Number(value.trim()));
    values.length === 16 && values.every(Number.isFinite) && ctx.transform(values[0], values[1], values[4], values[5], values[12], values[13]);
  }
}
function getPreservedAspectRatioRect(image, width, height) {
  const imageWidth = image.naturalWidth || image.width;
  const imageHeight = image.naturalHeight || image.height;
  if (!imageWidth || !imageHeight || !width || !height) {
    return { x: 0, y: 0, w: width, h: height };
  }
  const scale = Math.min(width / imageWidth, height / imageHeight);
  const w = imageWidth * scale;
  const h = imageHeight * scale;
  return {
    x: (width - w) / 2,
    y: (height - h) / 2,
    w,
    h
  };
}
function getBackgroundImageOffset($$) {
  const { state } = $$;
  return state.hasFunnel || state.hasTreemap ? { x: 0, y: 0 } : {
    x: asHalfPixel(state.margin.left),
    y: asHalfPixel(state.margin.top)
  };
}
function drawCanvasLine($$, target, indices, painter, isSub = false) {
  painter.strokePath((ctx) => {
    generateDrawLinePath($$, indices, isSub, ctx)(target);
  }, { lineDash: [] });
}
function drawCanvasArea($$, target, indices, painter, isSub = false) {
  painter.fillPath((ctx) => {
    generateDrawAreaPath($$, indices, isSub, ctx)(target);
  });
}
function getVisibleCanvasTarget($$, target) {
  const range = getCanvasTargetVisibleRange($$, target);
  return range.start === 0 && range.end === target.values.length ? target : CanvasRenderer_spreadProps(CanvasRenderer_spreadValues({}, target), {
    values: target.values.slice(range.start, range.end)
  });
}
function getFocusedCanvasDatum(focusData, d) {
  if (!(focusData == null ? void 0 : focusData.length) || !(d == null ? void 0 : d.id)) {
    return null;
  }
  let lookup = canvasFocusLookupCache.get(focusData);
  if (!lookup) {
    lookup = /* @__PURE__ */ new Map();
    for (const focus of focusData) {
      if (!(focus == null ? void 0 : focus.id)) {
        continue;
      }
      const targetKey = `${focus.id}:*`;
      if (!lookup.has(targetKey)) {
        lookup.set(targetKey, focus);
      }
      if ("index" in focus) {
        lookup.set(`${focus.id}:${focus.index}`, focus);
      }
    }
    canvasFocusLookupCache.set(focusData, lookup);
  }
  return "index" in d ? lookup.get(`${d.id}:${d.index}`) || null : lookup.get(`${d.id}:*`) || null;
}
function getSubchartBrushHandlePath(axis, type) {
  const Path2DCtor = win.Path2D;
  if (!Path2DCtor) {
    return null;
  }
  const key = `${axis}:${type}`;
  const cached = subchartBrushHandlePathCache.get(key);
  if (cached) {
    return cached;
  }
  const path = new Path2DCtor(SUBCHART_BRUSH_HANDLE_PATH[axis][type]);
  subchartBrushHandlePathCache.set(key, path);
  return path;
}
function getCanvasOverColor($$, d) {
  const onover = $$.config.color_onover;
  if (!onover || !d) {
    return null;
  }
  if (isObject(onover)) {
    return d.id in onover ? onover[d.id] : null;
  } else if (isString(onover)) {
    return onover;
  } else if (isFunction(onover)) {
    return onover.call($$.api, d);
  }
  return null;
}
function getCanvasRenderColor($$, d, focusData) {
  const focus = getFocusedCanvasDatum(focusData, d);
  const overColor = getCanvasOverColor($$, focus);
  return overColor || $$.color(d.id);
}
function getCanvasTargetId(d) {
  var _a;
  return (d == null ? void 0 : d.id) || ((_a = d == null ? void 0 : d.data) == null ? void 0 : _a.id);
}
function isCanvasTargetFocused($$, d) {
  var _a;
  const id = getCanvasTargetId(d);
  return !!id && ((_a = $$.state.focusedTargetIds) == null ? void 0 : _a.has(id));
}
function getCanvasTargetFocusOpacity($$, d) {
  var _a;
  const id = getCanvasTargetId(d);
  return id && ((_a = $$.state.defocusedTargetIds) == null ? void 0 : _a.has(id)) ? $$.canvasTheme.style.shape.targetDefocusedOpacity : 1;
}
function getCanvasAreaBounds($$, target, indices, isSub = false) {
  var _a;
  const getPoints = (_a = $$.generateGetAreaPoints) == null ? void 0 : _a.call($$, indices, isSub);
  if (!getPoints) {
    return null;
  }
  const range = getCanvasTargetVisibleRange($$, target);
  let minX = Infinity;
  let minY = Infinity;
  let maxX = -Infinity;
  let maxY = -Infinity;
  for (let i = range.start; i < range.end; i++) {
    const d = target.values[i];
    if (!hasCanvasDrawableValue($$, d)) {
      continue;
    }
    getPoints(d, i).forEach(([x, y]) => {
      if (!isFiniteCanvasCoordinate(x, y)) {
        return;
      }
      minX = Math.min(minX, x);
      minY = Math.min(minY, y);
      maxX = Math.max(maxX, x);
      maxY = Math.max(maxY, y);
    });
  }
  return Number.isFinite(minX) && Number.isFinite(minY) ? { x: minX, y: minY, w: maxX - minX, h: maxY - minY } : null;
}
function getLinearGradientCoord(value, origin, size) {
  return origin + size * (isNumber(value) ? value : 0);
}
function getCanvasLinearGradientFill($$, ctx, target, shape, rect, baseColor) {
  const option = $$.config[`${shape}_linearGradient`];
  if (!option || !rect || !rect.w || !rect.h) {
    return baseColor;
  }
  const isRotated = $$.config.axis_rotated;
  const gradientOption = typeof option === "object" ? option : {};
  const x = gradientOption.x || (isRotated ? [1, 0] : [0, 0]);
  const y = gradientOption.y || (isRotated ? [0, 0] : [0, 1]);
  const stops = Array.isArray(gradientOption.stops) ? gradientOption.stops : [[0, baseColor, 1], [1, baseColor, 0]];
  const gradient = ctx.createLinearGradient(
    getLinearGradientCoord(x[0], rect.x, rect.w),
    getLinearGradientCoord(y[0], rect.y, rect.h),
    getLinearGradientCoord(x[1], rect.x, rect.w),
    getLinearGradientCoord(y[1], rect.y, rect.h)
  );
  stops.forEach(([offset, stopColor, stopOpacity]) => {
    const colorValue = isFunction(stopColor) ? stopColor.call($$.api, target.id) : stopColor;
    const color = String(colorValue || baseColor);
    const numericOffset = Number(offset);
    const parsedOffset = Number.isFinite(numericOffset) ? Math.max(0, Math.min(1, numericOffset)) : 0;
    gradient.addColorStop(parsedOffset, withOpacity(color, stopOpacity));
  });
  return gradient;
}
function isCanvasRenderableTarget($$, target) {
  return isCanvasTargetSupported($$, target, RENDERER_GROUPED_TYPE_FILTERS);
}
function getPointOpacity($$, target) {
  const opacity = $$.config.point_opacity;
  return Number.isFinite(opacity) ? opacity : isCanvasScatterType($$, target) || isCanvasBubbleType($$, target) ? 0.5 : 1;
}
function getTargetPointRadius($$, target, d) {
  var _a, _b;
  const pointR = $$.config.point_r;
  return isCanvasBubbleType($$, target) || isFunction(pointR) ? (_b = (_a = $$.pointR) == null ? void 0 : _a.call($$, d)) != null ? _b : 2.5 : pointR;
}
function shouldCullDenseScatterPoints($$, target, pointType, hasGradient) {
  return !hasGradient && pointType === "circle" && isCanvasScatterType($$, target) && !isFunction($$.config.point_r) && target.values.length > DENSE_SCATTER_POINT_CULL_THRESHOLD;
}
function getBarConnectLineType($$, id) {
  const { bar_connectLine: connectLine } = $$.config;
  const type = isObject(connectLine) ? connectLine[id] : connectLine;
  return /^(start|end)-(start|end)$/.test(type) ? type : null;
}
function getBarConnectLineBox($$, points, radiusInfo) {
  const { indexX, indexY, pos } = radiusInfo;
  return $$.config.axis_rotated ? {
    x: points[0][indexX],
    y: points[0][indexY],
    width: points[0][indexX] - pos,
    height: points[2][indexY] - points[0][indexY]
  } : {
    x: points[0][indexX],
    y: pos,
    width: points[2][indexX] - points[0][indexX],
    height: points[3][indexY] - pos
  };
}
function drawBarConnectLine($$, painter, type, boxes, alpha = 1) {
  if (boxes.length < 2) {
    return;
  }
  const isRotated = $$.config.axis_rotated;
  const isStart = /^start-(start|end)$/.test(type);
  const isEnd = /^end-(start|end)$/.test(type);
  const isToEnd = /\w+-end$/.test(type);
  const isToStart = /\w+-start$/.test(type);
  const getMovePoint = (box) => ({
    x: isRotated ? isEnd ? box.x - box.width : box.x : box.x + box.width,
    y: isRotated ? box.y + box.height : isStart ? box.y + box.height : box.y
  });
  const getLinePoint = (box) => ({
    x: isRotated ? box.x - (isToEnd ? box.width : 0) : box.x,
    y: isRotated ? box.y : box.y + (isToStart ? box.height : 0)
  });
  let movePoint = getMovePoint(boxes[0]);
  painter.strokePath(() => {
    for (let i = 1; i < boxes.length; i++) {
      const linePoint = getLinePoint(boxes[i]);
      painter.traceLine(movePoint.x, movePoint.y, linePoint.x, linePoint.y);
      if (i < boxes.length - 1) {
        movePoint = getMovePoint(boxes[i]);
      }
    }
  }, {
    alpha,
    stroke: $$.canvasTheme.style.shape.barConnectLineColor,
    lineWidth: $$.canvasTheme.style.shape.barConnectLineWidth,
    lineDash: []
  });
}
function getPointType($$, target) {
  var _a;
  const { config } = $$;
  if (isCanvasBubbleType($$, target)) {
    return "circle";
  }
  const targetIds = ((_a = $$.mapToIds) == null ? void 0 : _a.call($$, $$.data.targets)) || [];
  const pattern = Array.isArray(config.point_pattern) && config.point_pattern.length ? config.point_pattern : [config.point_type];
  const index = Math.max(0, targetIds.indexOf(target.id));
  const type = pattern[index % pattern.length];
  return /^rect(angle)?$/i.test(type) || type === "rectangle" ? "rectangle" : type || "circle";
}
function getPointFillStyle($$, ctx, d, x, y, r, fallback) {
  const option = $$.config.point_radialGradient;
  if (!option || !r) {
    return fallback;
  }
  const gradientOption = isObject(option) ? option : {};
  const cx = isNumber(gradientOption.cx) ? gradientOption.cx : 0.3;
  const cy = isNumber(gradientOption.cy) ? gradientOption.cy : 0.3;
  const radius = isNumber(gradientOption.r) ? gradientOption.r : 0.7;
  const stops = Array.isArray(gradientOption.stops) ? gradientOption.stops : [[0.1, null, 1], [0.9, null, 0]];
  const gradientX = x + (cx - 0.5) * r * 2;
  const gradientY = y + (cy - 0.5) * r * 2;
  const gradient = ctx.createRadialGradient(
    gradientX,
    gradientY,
    0,
    gradientX,
    gradientY,
    Math.max(1, r * radius * 2)
  );
  stops.forEach(([offset, stopColor, stopOpacity]) => {
    let color = isFunction(stopColor) ? stopColor.bind($$.api)(d.id) : stopColor;
    if (!color) {
      color = fallback;
    }
    const numericOffset = Number(offset);
    const parsedOffset = Number.isFinite(numericOffset) ? Math.max(0, Math.min(1, numericOffset)) : 0;
    gradient.addColorStop(parsedOffset, withOpacity(color, stopOpacity));
  });
  return gradient;
}
function getCandlestickColor($$, d, value) {
  const downColor = $$.config.candlestick_color_down;
  const color = (value == null ? void 0 : value._isUp) ? $$.color(d) : downColor && typeof downColor === "object" ? downColor[d.id] : downColor;
  return color || $$.color(d);
}
function shouldDrawPoints($$, target) {
  return $$.shouldDrawPointsForLine ? $$.shouldDrawPointsForLine(target) : true;
}
function isSameDash(a, b) {
  return a.length === b.length && a.every((value, index) => value === b[index]);
}
function drawCanvasLineWithDataRegions($$, target, painter) {
  const { config, scale } = $$;
  const x = scale.zoom || scale.x;
  const y = $$.getYScaleById(target.id);
  const rawValues = config.line_connectNull ? $$.filterRemoveNull(target.values) : target.values;
  let values = $$.isAreaRangeType(target) ? rawValues.map((d) => CanvasRenderer_spreadProps(CanvasRenderer_spreadValues({}, d), { value: $$.getRangedData(d, "mid") })) : rawValues;
  if ($$.isStepType(target)) {
    values = $$.convertValuesToStep(values);
  }
  const segments = getLineRegionSegments($$, values, x, y, config.data_regions[target.id]);
  let currentDash = null;
  let currentPoints = [];
  const flush = () => {
    if (currentPoints.length < 2 || !currentDash) {
      currentPoints = [];
      return;
    }
    painter.strokePath((ctx) => {
      const [start, ...rest] = currentPoints;
      ctx.moveTo(start[0], start[1]);
      rest.forEach((point) => {
        ctx.lineTo(point[0], point[1]);
      });
    }, { lineDash: currentDash });
    currentPoints = [];
  };
  const appendSegment = (start, end, dash) => {
    if (!currentDash || !isSameDash(currentDash, dash)) {
      flush();
      currentDash = dash;
      currentPoints = [start, end];
    } else {
      currentPoints.push(end);
    }
  };
  for (const { start, end, dash, isBreak } of segments) {
    if (isBreak || !start || !end || !dash) {
      flush();
      currentDash = null;
      continue;
    }
    if (!isFiniteCanvasCoordinate(start[0], start[1]) || !isFiniteCanvasCoordinate(end[0], end[1])) {
      flush();
      currentDash = null;
      continue;
    }
    appendSegment(start, end, dash);
  }
  flush();
}
class CanvasRenderer {
  /**
   * Constructor.
   * @param {CanvasEngine} engine Canvas drawing engine
   * @param {CanvasTheme} theme Canvas theme resolver
   * @private
   */
  constructor(engine, theme) {
    CanvasRenderer_publicField(this, "engine", engine);
    CanvasRenderer_publicField(this, "theme", theme);
    CanvasRenderer_publicField(this, "painter");
    CanvasRenderer_publicField(this, "labelImageCache", /* @__PURE__ */ new Map());
    CanvasRenderer_publicField(this, "backgroundImageCache", /* @__PURE__ */ new Map());
    CanvasRenderer_publicField(this, "backgroundClassStyleCache", /* @__PURE__ */ new Map());
    this.painter = new CanvasPainter(engine.ctx);
  }
  /**
   * Get the drawing context for the main canvas.
   * @returns {CanvasRenderingContext2D} Canvas drawing context
   * @private
   */
  get ctx() {
    return this.painter.context;
  }
  /**
   * Run renderer draw calls on another canvas context.
   * @param {CanvasRenderingContext2D} ctx Canvas drawing context
   * @param {function} draw Draw callback
   * @private
   */
  withContext(ctx, draw) {
    this.painter.withContext(ctx, draw);
  }
  /**
   * Release renderer caches that can hold chart or DOM references.
   * @private
   */
  destroy() {
    const clearImageHandler = (entry) => {
      entry.image.onload = null;
      entry.image.onerror = null;
    };
    this.labelImageCache.forEach(clearImageHandler);
    this.backgroundImageCache.forEach(clearImageHandler);
    this.labelImageCache.clear();
    this.backgroundImageCache.clear();
    this.backgroundClassStyleCache.clear();
  }
  /**
   * Get cached image for data label.
   * @param {string} url Image URL
   * @param {object} $$ ChartInternal instance
   * @returns {object|null} Cached image entry
   * @private
   */
  getLabelImage(url, $$) {
    if (!url || !win.Image) {
      return null;
    }
    let entry = this.labelImageCache.get(url);
    if (!entry) {
      const nextEntry = {
        image: new win.Image(),
        loaded: false,
        loading: true
      };
      entry = nextEntry;
      this.labelImageCache.set(url, entry);
      nextEntry.image.onload = () => {
        var _a;
        nextEntry.loaded = true;
        nextEntry.loading = false;
        (_a = $$.redraw) == null ? void 0 : _a.call($$);
      };
      nextEntry.image.onerror = () => {
        nextEntry.loaded = false;
        nextEntry.loading = false;
      };
      nextEntry.image.src = url;
    }
    return entry;
  }
  /**
   * Get cached chart background image.
   * @param {string} url Image URL
   * @param {object} $$ ChartInternal instance
   * @returns {object|null} Cached image entry
   * @private
   */
  getBackgroundImage(url, $$) {
    if (!url || !win.Image) {
      return null;
    }
    let entry = this.backgroundImageCache.get(url);
    if (!entry) {
      const nextEntry = {
        image: new win.Image(),
        loaded: false,
        loading: true
      };
      entry = nextEntry;
      this.backgroundImageCache.set(url, entry);
      nextEntry.image.onload = () => {
        var _a;
        nextEntry.loaded = true;
        nextEntry.loading = false;
        (_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false);
      };
      nextEntry.image.onerror = () => {
        nextEntry.loaded = false;
        nextEntry.loading = false;
      };
      nextEntry.image.src = url;
    }
    return entry;
  }
  /**
   * Resolve background.class CSS values that canvas can reasonably mirror.
   * @param {object} $$ ChartInternal instance
   * @param {string} className Background class name
   * @returns {object} Class style
   * @private
   */
  getBackgroundClassStyle($$, className) {
    if (!className || !win.document) {
      return {};
    }
    const cached = this.backgroundClassStyleCache.get(className);
    if (cached) {
      return cached;
    }
    const probe = win.document.createElement("div");
    probe.className = className;
    probe.style.cssText = "position:absolute;visibility:hidden;pointer-events:none;width:1px;height:1px;";
    $$.$el.chart.node().appendChild(probe);
    const style = win.getComputedStyle(probe);
    const opacity = parseFloat(style.opacity);
    const result = {
      opacity: Number.isFinite(opacity) ? opacity : void 0,
      transform: style.transform || void 0
    };
    probe.remove();
    this.backgroundClassStyleCache.set(className, result);
    return result;
  }
  /**
   * Draw configured chart background behind all canvas layers.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawBackground($$) {
    const bg = $$.config.background;
    if (!(bg == null ? void 0 : bg.imgUrl) && !(bg == null ? void 0 : bg.color)) {
      return;
    }
    const { ctx, painter } = this;
    const { current, margin, width, height } = $$.state;
    const classStyle = this.getBackgroundClassStyle($$, bg.class);
    painter.withState(() => {
      if (classStyle.opacity !== void 0) {
        ctx.globalAlpha *= classStyle.opacity;
      }
      if (bg.imgUrl) {
        const entry = this.getBackgroundImage(bg.imgUrl, $$);
        if (entry == null ? void 0 : entry.loaded) {
          const offset = getBackgroundImageOffset($$);
          const rect = getPreservedAspectRatioRect(
            entry.image,
            current.width,
            current.height
          );
          ctx.translate(offset.x, offset.y);
          applyCssMatrixTransform(ctx, classStyle.transform);
          ctx.drawImage(entry.image, rect.x, rect.y, rect.w, rect.h);
        }
      } else if (bg.color) {
        applyCssMatrixTransform(ctx, classStyle.transform);
        painter.fillRect({
          x: margin.left,
          y: margin.top,
          w: width,
          h: height
        }, { fill: bg.color });
      }
    });
  }
  /**
   * Draw data label image when loaded, or queue it for loading.
   * @param {object} $$ ChartInternal instance
   * @param {object} d Data row
   * @param {string} text Label text
   * @param {number} x Label x coordinate
   * @param {number} y Label y coordinate
   * @returns {object} Adjusted text position
   * @private
   */
  drawLabelImage($$, d, text, x, y) {
    const option = getLabelImageOption($$, d);
    if (!(option == null ? void 0 : option.url)) {
      return { x, y };
    }
    const url = getLabelImageUrl(option, d);
    const position = getLabelImagePosition($$, option, text, x, y, d);
    const entry = this.getLabelImage(url, $$);
    if (entry == null ? void 0 : entry.loaded) {
      this.ctx.drawImage(
        entry.image,
        position.x,
        position.y,
        option.width,
        option.height
      );
    }
    return {
      x: position.textX,
      y: position.textY
    };
  }
  /**
   * Draw a data label at a resolved canvas position.
   * @param {object} $$ ChartInternal instance
   * @param {object} d Data row
   * @param {string} text Label text
   * @param {number} x Label x coordinate
   * @param {number} y Label y coordinate
   * @private
   */
  drawDataLabel($$, d, text, x, y) {
    const { painter, theme: { style } } = this;
    ({ x, y } = this.drawLabelImage($$, d, text, x, y));
    if ($$.config.data_labels.rotate) {
      const position = getRotatedLabelPosition($$, d, x, y);
      x = position.x;
      y = position.y;
      this.ctx.textAlign = position.textAlign;
    }
    this.ctx.fillStyle = getLabelColor($$, d, style.label.color);
    drawLabelDecorations($$, painter, d, text, x, y);
    painter.textLines(text, x, y, {
      angle: $$.config.data_labels.rotate
    });
  }
  /**
   * Redraw focused point data labels over the hover overlay.
   * @param {object} $$ ChartInternal instance
   * @param {Array} selectedData Focused data rows
   * @private
   */
  drawFocusLabels($$, selectedData) {
    var _a;
    if (!((_a = $$.hasDataLabel) == null ? void 0 : _a.call($$))) {
      return;
    }
    const { ctx, theme: { style } } = this;
    const rows = selectedData.filter(
      (d) => d && hasCanvasDrawableValue($$, d) && isCanvasPointType($$, d) && isCanvasRenderableTarget($$, { id: d.id })
    );
    const texts = {
      size: () => rows.length
    };
    if (!rows.length) {
      return;
    }
    ctx.font = style.label.font;
    rows.forEach((d) => {
      const text = getLabelText($$, d);
      let { x, y } = getRenderDataPoint($$, d);
      if (!text) {
        return;
      }
      ({ x, y } = getPointLabelAnchor($$, ctx, d, x, y));
      x += getLabelPosition($$, d, "x", texts);
      y += getLabelPosition($$, d, "y", texts);
      if (!isFiniteCanvasCoordinate(x, y)) {
        return;
      }
      this.drawDataLabel($$, d, text, x, y);
    });
  }
  /**
   * Draw all supported canvas shape layers.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @param {Array} focusData Focused data rows
   * @private
   */
  draw($$, shape, focusData) {
    if ($$.state.hasTreemap) {
      this.drawTreemaps($$);
      return;
    }
    const { margin, width, height } = $$.state;
    const drawLineLayers = () => {
      if (!$$.config.area_front) {
        this.drawAreas($$, shape, focusData);
      }
      this.drawLines($$, shape);
      if ($$.config.area_front) {
        this.drawAreas($$, shape, focusData);
      }
      this.drawCircles($$, shape, focusData);
    };
    const drawContent = () => {
      if (!$$.config.bar_front) {
        this.drawBars($$, shape, focusData);
      }
      this.drawCandlesticks($$, shape, focusData);
      drawLineLayers();
      if ($$.config.bar_front) {
        this.drawBars($$, shape, focusData);
      }
      this.drawSelections($$, shape);
      this.drawLabels($$, shape);
    };
    $$.config.clipPath === false ? drawContent() : this.painter.clipRect(
      { x: margin.left, y: margin.top, w: width, h: height },
      drawContent
    );
  }
  /**
   * Draw the canvas subchart overview and brush selection.
   * @param {object} $$ ChartInternal instance
   * @param {object} _shape Cached main shape object
   * @private
   */
  drawSubchart($$, _shape) {
    const { config, state } = $$;
    void _shape;
    if (!config.subchart_show || !state.hasAxis || state.width2 <= 0 || state.height2 <= 0) {
      return;
    }
    const { ctx, painter, theme: { style } } = this;
    const { margin2, width2, height2 } = state;
    const rect = { x: margin2.left, y: margin2.top, w: width2, h: height2 };
    $$.withSubchartTypeContext(() => {
      var _a;
      const targets = $$.filterTargetsToShow().filter(isCanvasRenderableTarget.bind(null, $$));
      const shape = $$.getDrawShape();
      (_a = $$.updateSubchartYDomain) == null ? void 0 : _a.call($$, targets);
      painter.withState(() => {
        painter.clipRect(rect, () => {
          painter.withTranslation(rect.x, rect.y, () => {
            var _a2, _b, _c, _d, _e, _f;
            const areaTargets = targets.filter(isCanvasAreaType.bind(null, $$));
            const areaIndices = getCanvasShapeIndices(
              $$,
              shape,
              TYPE.AREA,
              isCanvasAreaType.bind(null, $$)
            );
            for (const target of areaTargets) {
              if (!target.values.some(hasCanvasDrawableValue.bind(null, $$))) {
                continue;
              }
              ctx.globalAlpha = style.shape.areaOpacity * getCanvasTargetFocusOpacity($$, target);
              ctx.fillStyle = $$.color(target.id);
              drawCanvasArea($$, target, areaIndices, painter, true);
            }
            ctx.globalAlpha = 1;
            const barTargets = targets.filter(isCanvasBarType.bind(null, $$));
            const barIndices = getCanvasShapeIndices(
              $$,
              shape,
              TYPE.BAR,
              isCanvasBarType.bind(null, $$)
            );
            const getBarPoints = (_a2 = $$.generateGetBarPoints) == null ? void 0 : _a2.call($$, barIndices, true);
            if (getBarPoints) {
              for (const target of barTargets) {
                ctx.globalAlpha = style.shape.barOpacity * getCanvasTargetFocusOpacity($$, target);
                ctx.fillStyle = $$.color(target.id);
                target.values.forEach((d, i) => {
                  var _a3;
                  if (!hasCanvasDrawableValue($$, d)) {
                    return;
                  }
                  const geometry = getCanvasBarGeometry($$, getBarPoints, d, i);
                  const fill = ((_a3 = $$.getSubchartCandlestickBarColor) == null ? void 0 : _a3.call($$, d, true)) || ctx.fillStyle;
                  geometry && painter.fillRect(geometry.rect, { fill });
                });
              }
              ctx.globalAlpha = 1;
            }
            const candlestickTargets = targets.filter(
              isCanvasCandlestickType.bind(null, $$)
            );
            const candlestickIndices = getCanvasShapeIndices(
              $$,
              shape,
              TYPE.CANDLESTICK,
              isCanvasCandlestickType.bind(null, $$)
            );
            const getCandlestickPoints = (_b = $$.generateGetCandlestickPoints) == null ? void 0 : _b.call(
              $$,
              candlestickIndices,
              true
            );
            if (getCandlestickPoints) {
              ctx.lineWidth = style.shape.candlestickLineWidth;
              for (const target of candlestickTargets) {
                const targetOpacity = getCanvasTargetFocusOpacity($$, target);
                ctx.globalAlpha = targetOpacity;
                target.values.forEach((d, i) => {
                  var _a3;
                  const value = (_a3 = $$.getCandlestickData) == null ? void 0 : _a3.call($$, d);
                  const geometry = value && getCanvasCandlestickGeometry(
                    $$,
                    getCandlestickPoints,
                    d,
                    i
                  );
                  if (!geometry) {
                    return;
                  }
                  const color = getCandlestickColor($$, { id: target.id }, value);
                  ctx.strokeStyle = color;
                  ctx.fillStyle = color;
                  painter.strokePath(() => {
                    painter.traceLine(
                      geometry.wickStart[0],
                      geometry.wickStart[1],
                      geometry.wickEnd[0],
                      geometry.wickEnd[1]
                    );
                  });
                  painter.fillRect(geometry.body, { fill: ctx.fillStyle });
                });
              }
            }
            const lineTargets = targets.filter(isCanvasLineType.bind(null, $$));
            const lineIndices = getCanvasShapeIndices(
              $$,
              shape,
              TYPE.LINE,
              isCanvasLineType.bind(null, $$)
            );
            ctx.globalAlpha = 1;
            for (const target of lineTargets) {
              if (!target.values.some(hasCanvasDrawableValue.bind(null, $$))) {
                continue;
              }
              ctx.globalAlpha = getCanvasTargetFocusOpacity($$, target);
              ctx.lineWidth = isCanvasTargetFocused($$, target) ? style.shape.lineFocusedWidth : style.shape.lineWidth;
              ctx.strokeStyle = $$.color(target.id);
              drawCanvasLine($$, target, lineIndices, painter, true);
            }
            ctx.globalAlpha = 1;
            if (config.point_show && !((_c = $$.isPointFocusOnly) == null ? void 0 : _c.call($$))) {
              const cy = (_d = $$.updateCircleY) == null ? void 0 : _d.call($$, true);
              const cx = (_e = $$.subxx) == null ? void 0 : _e.bind($$);
              if (cx && cy) {
                for (const target of targets) {
                  if (!isCanvasScatterType($$, target) && !isCanvasBubbleType($$, target)) {
                    continue;
                  }
                  const color = $$.color(target.id);
                  const pointFill = style.shape.pointFillColor || color;
                  const pointStroke = style.shape.pointStrokeColor || color;
                  const pointLineWidth = pointStroke ? (_f = style.shape.pointLineWidth) != null ? _f : 1 : 0;
                  const pointStyle = pointStroke && pointLineWidth > 0 ? {
                    fill: pointFill,
                    stroke: pointStroke,
                    lineWidth: pointLineWidth
                  } : { fill: pointFill };
                  ctx.globalAlpha = getPointOpacity($$, target) * getCanvasTargetFocusOpacity($$, target);
                  target.values.forEach((d, i) => {
                    if (!hasCanvasDrawableValue($$, d)) {
                      return;
                    }
                    const x = config.axis_rotated ? cy(d, i) : cx(d);
                    const y = config.axis_rotated ? cx(d) : cy(d, i);
                    const r = Math.min(getTargetPointRadius($$, target, d), 3);
                    if (isFiniteCanvasCoordinate(x, y)) {
                      drawPointPattern(
                        painter,
                        "circle",
                        x,
                        y,
                        r,
                        pointStyle
                      );
                    }
                  });
                }
                ctx.globalAlpha = 1;
              }
            }
          });
        });
        this.drawSubchartBrush($$);
      });
    });
  }
  /**
   * Draw current subchart brush selection.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawSubchartBrush($$) {
    var _a, _b;
    const { config, scale, state } = $$;
    const domain = state.domain;
    if (!config.subchart_show || config.subchart_brush_enabled === false || !(domain == null ? void 0 : domain.length) || !scale.subX) {
      return;
    }
    const { margin2, width2, height2 } = state;
    const p0 = scale.subX(domain[0]);
    const p1 = scale.subX(domain[1]);
    const axisLength = config.axis_rotated ? height2 : width2;
    const extent = (_b = (_a = $$.axis) == null ? void 0 : _a.getExtent) == null ? void 0 : _b.call(_a);
    const extentValues = Array.isArray(extent) && extent.length >= 2 && extent.every(Number.isFinite) ? extent.slice(0, 2) : [0, axisLength];
    const extentStart = Math.max(0, Math.min(axisLength, Math.min(...extentValues)));
    const extentEnd = Math.max(0, Math.min(axisLength, Math.max(...extentValues)));
    const start = Math.max(extentStart, Math.min(extentEnd, Math.min(p0, p1)));
    const end = Math.max(extentStart, Math.min(extentEnd, Math.max(p0, p1)));
    const size = end - start;
    if (size <= 0) {
      return;
    }
    const rect = config.axis_rotated ? { x: margin2.left, y: margin2.top + start, w: width2, h: size } : { x: margin2.left + start, y: margin2.top, w: size, h: height2 };
    this.painter.fillRect(rect, {
      fill: this.theme.style.subchartBrush.fill,
      alpha: this.theme.style.subchartBrush.opacity
    });
    if (config.subchart_showHandle) {
      this.drawSubchartBrushHandle($$, start, "start");
      this.drawSubchartBrushHandle($$, end, "end");
    }
  }
  /**
   * Draw a visible subchart brush resize handle.
   * @param {object} $$ ChartInternal instance
   * @param {number} coord Brush handle coordinate
   * @param {string} type Brush handle side
   * @private
   */
  drawSubchartBrushHandle($$, coord, type) {
    const { config, state: { margin2, width2, height2 } } = $$;
    const { ctx, painter, theme: { style } } = this;
    const isRotated = config.axis_rotated;
    const fill = style.subchartBrush.handleFill;
    const stroke = style.subchartBrush.handleStroke;
    const x = isRotated ? margin2.left + width2 / 2 : margin2.left + coord;
    const y = isRotated ? margin2.top + coord : margin2.top + height2 / 2;
    const path = getSubchartBrushHandlePath(isRotated ? "y" : "x", type);
    if (!path) {
      return;
    }
    painter.withState(() => {
      ctx.translate(x, y);
      ctx.fillStyle = fill;
      ctx.strokeStyle = stroke;
      ctx.lineWidth = style.subchartBrush.handleLineWidth;
      ctx.globalAlpha = style.subchartBrush.handleOpacity;
      ctx.fill(path);
      ctx.globalAlpha = 1;
      ctx.stroke(path);
    });
  }
  /**
   * Draw bar shapes on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @param {Array} focusData Focused data rows
   * @private
   */
  drawBars($$, shape, focusData) {
    const { ctx, painter, theme: { style } } = this;
    const isBar = isCanvasBarType.bind(null, $$);
    const isExpanded = getExpandedFocusMatcher($$, focusData, isCanvasBarType);
    const targets = $$.filterTargetsToShow().filter(isBar).filter(isCanvasRenderableTarget.bind(null, $$));
    const getPoints = $$.generateGetBarPoints(
      getCanvasShapeIndices($$, shape, TYPE.BAR, isBar),
      false
    );
    const { margin } = $$.state;
    const getRadius = getBarRadiusResolver($$);
    const stackingRadiusSet = getRadius ? getStackingBarRadiusSet($$) : /* @__PURE__ */ new Set();
    if (!getPoints) {
      return;
    }
    painter.withTranslation(margin.left, margin.top, () => {
      var _a;
      for (const target of targets) {
        const range = getCanvasTargetVisibleRange($$, target);
        const connectLineType = getBarConnectLineType($$, target.id);
        const targetOpacity = getCanvasTargetFocusOpacity($$, target);
        const connectLineBoxes = [];
        const bars = [];
        for (let i = range.start; i < range.end; i++) {
          const d = target.values[i];
          if (!hasCanvasDrawableValue($$, d)) {
            continue;
          }
          const geometry = getCanvasBarGeometry($$, getPoints, d, i);
          if (!geometry) {
            continue;
          }
          const { points, rect } = geometry;
          const radiusInfo = getBarRadiusInfo(
            $$,
            d,
            points,
            getRadius,
            stackingRadiusSet,
            (_a = $$.isStackingRadiusData) == null ? void 0 : _a.bind($$)
          );
          bars.push({ d, points, rect, radiusInfo });
          if (connectLineType) {
            connectLineBoxes.push(getBarConnectLineBox($$, points, radiusInfo));
          }
        }
        if (connectLineType && style.shape.barConnectLineWidth > 0) {
          drawBarConnectLine(
            $$,
            painter,
            connectLineType,
            connectLineBoxes,
            targetOpacity
          );
        }
        for (const { d, rect, radiusInfo } of bars) {
          const overColor = getCanvasOverColor($$, getFocusedCanvasDatum(focusData, d));
          const color = overColor || $$.color(target.id);
          const fillAlpha = isExpanded(d) ? style.shape.barExpandedOpacity : style.shape.barOpacity;
          const alpha = fillAlpha * targetOpacity;
          ctx.fillStyle = overColor ? color : getCanvasLinearGradientFill($$, ctx, target, "bar", rect, color);
          getRadius ? painter.fillRoundRect(
            rect,
            radiusInfo.corners,
            { alpha }
          ) : painter.fillRect(rect, { alpha });
          if (style.shape.barLineWidth > 0) {
            ctx.strokeStyle = style.shape.barStrokeColor;
            ctx.lineWidth = style.shape.barLineWidth;
            getRadius ? painter.strokeRoundRect(
              rect,
              radiusInfo.corners,
              { alpha: style.shape.barOpacity * targetOpacity }
            ) : painter.strokeRect(rect, {
              alpha: style.shape.barOpacity * targetOpacity
            });
          }
        }
      }
    });
  }
  /**
   * Draw candlestick shapes on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @param {Array} focusData Focused data rows
   * @private
   */
  drawCandlesticks($$, shape, focusData) {
    var _a;
    const { ctx, painter, theme: { style } } = this;
    const isCandlestick = isCanvasCandlestickType.bind(null, $$);
    const isExpanded = getExpandedFocusMatcher($$, focusData, isCanvasCandlestickType);
    const targets = $$.filterTargetsToShow().filter(isCandlestick).filter(isCanvasRenderableTarget.bind(null, $$));
    const getPoints = (_a = $$.generateGetCandlestickPoints) == null ? void 0 : _a.call(
      $$,
      getCanvasShapeIndices($$, shape, TYPE.CANDLESTICK, isCandlestick),
      false
    );
    const { margin } = $$.state;
    if (!getPoints) {
      return;
    }
    painter.withTranslation(margin.left, margin.top, () => {
      var _a2;
      ctx.lineWidth = style.shape.candlestickLineWidth;
      for (const target of targets) {
        const range = getCanvasTargetVisibleRange($$, target);
        const targetOpacity = getCanvasTargetFocusOpacity($$, target);
        const lineWidth = style.shape.candlestickLineWidth;
        const strokeColor = style.shape.candlestickStrokeColor || "#000";
        for (let i = range.start; i < range.end; i++) {
          const d = target.values[i];
          const value = (_a2 = $$.getCandlestickData) == null ? void 0 : _a2.call($$, d);
          if (!value) {
            continue;
          }
          const geometry = getCanvasCandlestickGeometry($$, getPoints, d, i);
          if (!geometry) {
            continue;
          }
          const { body: rect, wickStart, wickEnd } = geometry;
          ctx.fillStyle = getCanvasOverColor($$, getFocusedCanvasDatum(focusData, d)) || getCandlestickColor($$, d, value);
          ctx.strokeStyle = strokeColor;
          ctx.globalAlpha = targetOpacity;
          lineWidth > 0 && painter.strokePath(() => {
            painter.traceLine(wickStart[0], wickStart[1], wickEnd[0], wickEnd[1]);
          });
          painter.fillRect(rect, {
            alpha: (isExpanded(d) ? style.shape.candlestickExpandedOpacity : 1) * targetOpacity
          });
          lineWidth > 0 && painter.strokeRect(rect, {
            alpha: targetOpacity,
            lineWidth,
            stroke: strokeColor
          });
        }
      }
      ctx.globalAlpha = 1;
    });
  }
  /**
   * Check whether focus data requires a full redraw to reflect _expanded_ shape styles.
   * @param {object} $$ ChartInternal instance
   * @param {Array} selectedData Focused data rows
   * @returns {boolean} Whether focused shapes need a main redraw
   * @private
   */
  hasExpandedShapeFocus($$, selectedData) {
    return !!(selectedData == null ? void 0 : selectedData.some(
      (d) => d && (isCanvasBarType($$, d) || isCanvasCandlestickType($$, d))
    ));
  }
  /**
   * Draw line strokes on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @private
   */
  drawLines($$, shape) {
    const { ctx, painter, theme: { style } } = this;
    const isLine = isCanvasLineType.bind(null, $$);
    const targets = $$.filterTargetsToShow().filter(isLine).filter(isCanvasRenderableTarget.bind(null, $$));
    const indices = getCanvasShapeIndices($$, shape, TYPE.LINE, isLine);
    const { margin } = $$.state;
    if (!$$.generateGetLinePoints) {
      return;
    }
    painter.withTranslation(margin.left, margin.top, () => {
      var _a;
      for (const target of targets) {
        const visibleTarget = getVisibleCanvasTarget($$, target);
        if (!visibleTarget.values.some(hasCanvasDrawableValue.bind(null, $$))) {
          continue;
        }
        ctx.globalAlpha = getCanvasTargetFocusOpacity($$, target);
        ctx.lineWidth = isCanvasTargetFocused($$, target) ? style.shape.lineFocusedWidth : style.shape.lineWidth;
        ctx.strokeStyle = $$.color(target.id);
        ((_a = $$.config.data_regions) == null ? void 0 : _a[visibleTarget.id]) ? drawCanvasLineWithDataRegions($$, visibleTarget, painter) : drawCanvasLine($$, visibleTarget, indices, painter);
      }
      ctx.globalAlpha = 1;
    });
  }
  /**
   * Draw area fills on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @param {Array} focusData Focused data rows
   * @private
   */
  drawAreas($$, shape, focusData) {
    const { ctx, painter, theme: { style } } = this;
    const isArea = isCanvasAreaType.bind(null, $$);
    const targets = $$.filterTargetsToShow().filter(isArea).filter(isCanvasRenderableTarget.bind(null, $$));
    const indices = getCanvasShapeIndices($$, shape, TYPE.AREA, isArea);
    const { margin } = $$.state;
    if (!$$.generateGetAreaPoints) {
      return;
    }
    painter.withTranslation(margin.left, margin.top, () => {
      for (const target of targets) {
        const visibleTarget = getVisibleCanvasTarget($$, target);
        if (!visibleTarget.values.some(hasCanvasDrawableValue.bind(null, $$))) {
          continue;
        }
        const color = getCanvasRenderColor($$, visibleTarget, focusData);
        ctx.globalAlpha = style.shape.areaOpacity * getCanvasTargetFocusOpacity($$, target);
        ctx.fillStyle = getCanvasLinearGradientFill(
          $$,
          ctx,
          visibleTarget,
          "area",
          // Bounds computation walks visible rows, so skip it when no gradient is set.
          // Use the original target so the range cache stays aligned with unsliced values.
          $$.config.area_linearGradient ? getCanvasAreaBounds($$, target, indices) : null,
          color
        );
        drawCanvasArea($$, visibleTarget, indices, painter);
      }
      ctx.globalAlpha = 1;
    });
  }
  /**
   * Draw point circles on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @param {Array} focusData Focused data rows
   * @private
   */
  drawCircles($$, shape, focusData) {
    var _a;
    if (!$$.config.point_show || ((_a = $$.isPointFocusOnly) == null ? void 0 : _a.call($$))) {
      return;
    }
    const { ctx, painter, theme: { style } } = this;
    const { cx, cy } = shape.pos;
    const { margin } = $$.state;
    const isExpanded = getExpandedFocusMatcher($$, focusData, isCanvasPointType);
    const hasExpandedFocus = !!(focusData == null ? void 0 : focusData.some((d) => d && isCanvasPointType($$, d)));
    if (!cx || !cy) {
      return;
    }
    painter.withTranslation(margin.left, margin.top, () => {
      var _a2, _b, _c;
      for (const target of $$.filterTargetsToShow()) {
        if (!isCanvasPointType($$, target) || !isCanvasRenderableTarget($$, target) || isCanvasLineType($$, target) && !shouldDrawPoints($$, target)) {
          continue;
        }
        const color = $$.color(target.id);
        const pointType = getPointType($$, target);
        const targetOpacity = getCanvasTargetFocusOpacity($$, target);
        const hasGradient = !!$$.config.point_radialGradient;
        const cullDenseScatter = shouldCullDenseScatterPoints(
          $$,
          target,
          pointType,
          hasGradient
        );
        const range = getCanvasTargetVisibleRange($$, target);
        const visibleCount = range.end - range.start;
        const occupancy = cullDenseScatter ? createCanvasPointOccupancyGrid(
          $$.state.width,
          $$.state.height,
          getTargetPointRadius(
            $$,
            target,
            target.values[range.start] || target.values[0]
          )
        ) : null;
        const pointAlpha = getPointOpacity($$, target) * targetOpacity;
        ctx.fillStyle = color;
        ctx.globalAlpha = pointAlpha;
        const pointFill = style.shape.pointFillColor || color;
        const pointStroke = style.shape.pointStrokeColor || color;
        const pointLineWidth = pointStroke ? (_a2 = style.shape.pointLineWidth) != null ? _a2 : 1 : 0;
        const hasPointStroke = !!pointStroke && pointLineWidth > 0;
        const mergeSameColorStroke = hasPointStroke && pointType === "circle" && isNumber(pointAlpha) && pointAlpha < 1 && pointFill === pointStroke;
        if (!hasExpandedFocus && !hasGradient && pointType === "circle") {
          ctx.fillStyle = pointFill;
          if (hasPointStroke && !mergeSameColorStroke) {
            ctx.strokeStyle = pointStroke;
            ctx.lineWidth = pointLineWidth;
          }
          if (visibleCount > MAX_BATCHED_CIRCLE_POINTS) {
            for (let i = range.start; i < range.end; i++) {
              const d = target.values[i];
              if (!hasCanvasDrawableValue($$, d)) {
                continue;
              }
              const baseR = getTargetPointRadius($$, target, d);
              const r = mergeSameColorStroke ? baseR + pointLineWidth / 2 : baseR;
              const x = cx(d, i);
              const y = cy(d, i);
              if (!isFiniteCanvasCoordinate(x, y)) {
                continue;
              }
              if (occupancy && !markCanvasPointOccupancy(occupancy, x, y)) {
                continue;
              }
              ctx.beginPath();
              ctx.arc(x, y, r, 0, Math.PI * 2);
              ctx.fill();
              hasPointStroke && !mergeSameColorStroke && ctx.stroke();
            }
          } else {
            ctx.beginPath();
            for (let i = range.start; i < range.end; i++) {
              const d = target.values[i];
              if (!hasCanvasDrawableValue($$, d)) {
                continue;
              }
              const baseR = getTargetPointRadius($$, target, d);
              const r = mergeSameColorStroke ? baseR + pointLineWidth / 2 : baseR;
              const x = cx(d, i);
              const y = cy(d, i);
              if (!isFiniteCanvasCoordinate(x, y)) {
                continue;
              }
              painter.traceCircle(x, y, r);
            }
            ctx.fill();
            hasPointStroke && !mergeSameColorStroke && ctx.stroke();
          }
        } else {
          for (let i = range.start; i < range.end; i++) {
            const d = target.values[i];
            if (!hasCanvasDrawableValue($$, d)) {
              continue;
            }
            const expanded = isExpanded(d);
            const baseR = getTargetPointRadius($$, target, d);
            const r = expanded ? (_c = (_b = $$.pointExpandedR) == null ? void 0 : _b.call($$, d)) != null ? _c : baseR * 1.75 : baseR;
            const x = cx(d, i);
            const y = cy(d, i);
            const overColor = getCanvasOverColor($$, d);
            const renderColor = overColor || color;
            const renderPointFill = style.shape.pointFillColor || renderColor;
            const renderPointStroke = style.shape.pointStrokeColor || renderColor;
            const fill = expanded ? overColor || style.focusPoint.fill || renderPointFill : renderPointFill;
            const stroke = expanded ? overColor || style.focusPoint.stroke || renderColor : renderPointStroke;
            const lineWidth = expanded ? style.focusPoint.lineWidth : pointLineWidth;
            const alpha = getPointOpacity($$, d) * targetOpacity;
            const hasStroke = !!stroke && (lineWidth != null ? lineWidth : 0) > 0;
            const mergeSameColorStroke2 = pointType === "circle" && hasStroke && isNumber(alpha) && alpha < 1 && fill === stroke;
            const drawR = mergeSameColorStroke2 ? r + (lineWidth || 0) / 2 : r;
            if (!isFiniteCanvasCoordinate(x, y)) {
              continue;
            }
            ctx.fillStyle = hasGradient ? getPointFillStyle($$, ctx, d, x, y, r, renderColor) : fill;
            ctx.globalAlpha = alpha;
            drawPointPattern(
              painter,
              pointType,
              x,
              y,
              drawR,
              hasStroke && !mergeSameColorStroke2 ? {
                fill: ctx.fillStyle,
                stroke,
                lineWidth
              } : void 0,
              baseR
            );
          }
        }
      }
    });
  }
  /**
   * Draw selected canvas shapes.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @private
   */
  drawSelections($$, shape) {
    var _a, _b;
    const selectedData = (_a = $$.getCanvasSelectedData) == null ? void 0 : _a.call($$);
    if (!$$.config.data_selection_enabled || !(selectedData == null ? void 0 : selectedData.length) || $$.state.hasTreemap) {
      return;
    }
    const { ctx, painter, theme: { style } } = this;
    const { margin } = $$.state;
    const isBar = isCanvasBarType.bind(null, $$);
    const isCandlestick = isCanvasCandlestickType.bind(null, $$);
    const barPoints = selectedData.some(isBar) ? $$.generateGetBarPoints(
      getCanvasShapeIndices($$, shape, TYPE.BAR, isBar),
      false
    ) : null;
    const candlestickPoints = selectedData.some(isCandlestick) ? (_b = $$.generateGetCandlestickPoints) == null ? void 0 : _b.call(
      $$,
      getCanvasShapeIndices($$, shape, TYPE.CANDLESTICK, isCandlestick),
      false
    ) : null;
    const getRadius = barPoints ? getBarRadiusResolver($$) : null;
    const stackingRadiusSet = getRadius ? getStackingBarRadiusSet($$) : /* @__PURE__ */ new Set();
    painter.withTranslation(margin.left, margin.top, () => {
      selectedData.forEach((d) => {
        var _a2, _b2, _c, _d, _e, _f, _g;
        const color = $$.color(d.id);
        if (isBar(d) && barPoints) {
          const geometry = getCanvasBarGeometry($$, barPoints, d, d.index);
          if (!geometry) {
            return;
          }
          const { points, rect } = geometry;
          const corners = getRadius ? getBarRadiusInfo($$, d, points, getRadius, stackingRadiusSet).corners : 0;
          getRadius ? painter.fillRoundRect(rect, corners, { fill: "#fff", alpha: 0.3 }) : painter.fillRect(rect, { fill: "#fff", alpha: 0.3 });
          getRadius ? painter.strokeRoundRect(rect, corners, { stroke: color, lineWidth: 2 }) : painter.strokeRect(rect, { stroke: color, lineWidth: 2 });
        } else if (isCandlestick(d) && candlestickPoints) {
          const value = (_a2 = $$.getCandlestickData) == null ? void 0 : _a2.call($$, d);
          if (!value) {
            return;
          }
          const geometry = getCanvasCandlestickGeometry(
            $$,
            candlestickPoints,
            d,
            d.index
          );
          if (!geometry) {
            return;
          }
          const { body, wickStart, wickEnd } = geometry;
          painter.strokePath(() => {
            painter.traceLine(wickStart[0], wickStart[1], wickEnd[0], wickEnd[1]);
          }, { stroke: color, lineWidth: 3 });
          painter.fillRect(body, { fill: "#fff", alpha: 0.3 });
          painter.strokeRect(body, { stroke: color, lineWidth: 2 });
        } else if (isCanvasPointType($$, d)) {
          const pointType = getPointType($$, { id: d.id });
          const { x, y } = getRenderDataPoint($$, d);
          const r = (_c = (_b2 = $$.pointR) == null ? void 0 : _b2.call($$, d)) != null ? _c : 2.5;
          const selectR = (_e = (_d = $$.pointSelectR) == null ? void 0 : _d.call($$, d)) != null ? _e : r * 2;
          if (!isFiniteCanvasCoordinate(x, y)) {
            return;
          }
          drawPointPattern(painter, "circle", x, y, selectR, {
            fill: style.selectedPoint.fill,
            lineWidth: style.selectedPoint.lineWidth,
            stroke: style.selectedPoint.stroke || color
          });
          if (!((_f = $$.isPointFocusOnly) == null ? void 0 : _f.call($$))) {
            drawPointPattern(painter, pointType, x, y, r, {
              fill: style.shape.pointFillColor || color,
              stroke: style.shape.pointStrokeColor || color,
              lineWidth: (_g = style.shape.pointLineWidth) != null ? _g : 1
            });
          }
        }
      });
      ctx.globalAlpha = 1;
    });
  }
  /**
   * Draw data labels on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @private
   */
  drawLabels($$, shape) {
    var _a;
    if (!((_a = $$.hasDataLabel) == null ? void 0 : _a.call($$))) {
      return;
    }
    const { ctx, painter, theme: { style } } = this;
    const { margin } = $$.state;
    const { cx, cy } = shape.pos;
    const barPoints = shape.indices[TYPE.BAR] ? $$.generateGetBarPoints(shape.indices[TYPE.BAR], false) : null;
    const candlestickPoints = $$.generateGetCandlestickPoints ? $$.generateGetCandlestickPoints(
      getCanvasShapeIndices(
        $$,
        shape,
        TYPE.CANDLESTICK,
        isCanvasCandlestickType.bind(null, $$)
      ),
      false
    ) : null;
    const targets = $$.filterTargetsToShow().filter(
      (target) => (isCanvasBarType($$, target) || isCanvasPointType($$, target) || isCanvasAreaType($$, target) || isCanvasCandlestickType($$, target)) && isCanvasRenderableTarget($$, target)
    );
    const targetRows = [];
    let labelCount = 0;
    targets.forEach((target) => {
      const range = getCanvasTargetVisibleRange($$, target);
      const data = $$.labelishData(target);
      const rows = [];
      for (let i = 0; i < data.length; i++) {
        const d = data[i];
        const text = getLabelText($$, d);
        if (text && d.index >= range.start && d.index < range.end && hasCanvasDrawableValue($$, d)) {
          rows.push({ d, text });
        }
      }
      labelCount += rows.length;
      rows.length && targetRows.push(rows);
    });
    const texts = {
      size: () => labelCount
    };
    painter.withTranslation(margin.left, margin.top, () => {
      ctx.font = style.label.font;
      ctx.textAlign = "center";
      targetRows.forEach((rows) => {
        var _a2, _b;
        for (const { d, text } of rows) {
          let x;
          let y;
          if (isCanvasBarType($$, d) && barPoints) {
            const geometry = getCanvasBarGeometry($$, barPoints, d, d.index);
            if (!geometry) {
              continue;
            }
            const { points, rect } = geometry;
            const value = $$.getBaseValue(d);
            const end = getRenderPoint($$, points[2]);
            const isNegative = value < 0;
            const labelHeight = getLabelDecorationBox(ctx, text, 0, 0).h;
            x = $$.config.axis_rotated && !$$.config.data_labels.centered ? end[0] + (isNegative ? -4 : 4) : rect.x + rect.w / 2;
            y = $$.config.data_labels.centered ? rect.y + rect.h / 2 : $$.config.axis_rotated ? rect.y + rect.h / 2 : end[1] + (isNegative ? labelHeight - 3 : -3);
            ctx.textAlign = $$.config.axis_rotated && !$$.config.data_labels.centered ? isNegative ? "right" : "left" : "center";
            ctx.textBaseline = $$.config.data_labels.centered ? "middle" : $$.config.axis_rotated ? "middle" : "alphabetic";
          } else if (isCanvasCandlestickType($$, d) && candlestickPoints) {
            const value = (_a2 = $$.getCandlestickData) == null ? void 0 : _a2.call($$, d);
            const geometry = getCanvasCandlestickGeometry(
              $$,
              candlestickPoints,
              d,
              d.index
            );
            const isUp = value == null ? void 0 : value._isUp;
            if (!geometry) {
              continue;
            }
            const { wickEnd, wickStart } = geometry;
            const isInverted = $$.config[`axis_${(_b = $$.axis) == null ? void 0 : _b.getId(d.id)}_inverted`];
            x = $$.config.axis_rotated ? isUp ? wickEnd[0] + 4 : wickStart[0] - 4 : wickStart[0];
            y = $$.config.axis_rotated ? wickStart[1] + 3 : isUp ? wickEnd[1] - 3 : wickStart[1] + 12;
            !$$.config.axis_rotated && isInverted && (y += 15 * (isUp ? 1 : -1));
            ctx.textAlign = $$.config.axis_rotated ? isUp ? "left" : "right" : "center";
            ctx.textBaseline = "alphabetic";
          } else if (cx && cy) {
            ({ x, y } = getShapePoint(shape.pos, d, d.index));
            ({ x, y } = getPointLabelAnchor($$, ctx, d, x, y));
          }
          x += getLabelPosition($$, d, "x", texts);
          y += getLabelPosition($$, d, "y", texts);
          if (!isFiniteCanvasCoordinate(x, y)) {
            continue;
          }
          this.drawDataLabel($$, d, text, x, y);
        }
      });
    });
  }
  /**
   * Draw empty-data label on canvas.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawEmptyLabel($$) {
    const text = $$.config.data_empty_label_text;
    const targetsToShow = $$.filterTargetsToShow();
    if (!text || targetsToShow.length) {
      return;
    }
    const { margin, width, height } = $$.state;
    const { style } = this.theme;
    this.painter.text(String(text), margin.left + width / 2, margin.top + height / 2, {
      fill: style.emptyLabel.color,
      font: style.emptyLabel.font,
      textAlign: "center",
      textBaseline: "middle"
    });
  }
  /**
   * Draw drag-zoom brush overlay.
   * @param {object} $$ ChartInternal instance
   * @param {number} start Start coordinate
   * @param {number} end End coordinate
   * @private
   */
  drawZoomBrush($$, start, end) {
    const { axis_rotated } = $$.config;
    const { height, margin, width } = $$.state;
    const brushStart = Math.min(start, end);
    const brushSize = Math.abs(end - start);
    const rect = axis_rotated ? { x: margin.left, y: margin.top + brushStart, w: width, h: brushSize } : { x: margin.left + brushStart, y: margin.top, w: brushSize, h: height };
    if (brushSize <= 0) {
      return;
    }
    this.painter.fillRect(rect, {
      fill: this.theme.style.zoomBrush.fill,
      alpha: this.theme.style.zoomBrush.opacity
    });
  }
  /**
   * Draw data selection drag area.
   * @param {object} $$ ChartInternal instance
   * @param {object} rect Selection rectangle
   * @private
   */
  drawSelectionDragArea($$, rect) {
    const { margin, width, height } = $$.state;
    const plot = {
      x: margin.left,
      y: margin.top,
      w: width,
      h: height
    };
    const x = Math.max(plot.x, rect.x);
    const y = Math.max(plot.y, rect.y);
    const right = Math.min(plot.x + plot.w, rect.x + rect.w);
    const bottom = Math.min(plot.y + plot.h, rect.y + rect.h);
    if (right <= x || bottom <= y) {
      return;
    }
    this.painter.fillRect({
      x,
      y,
      w: right - x,
      h: bottom - y
    }, {
      fill: this.theme.style.zoomBrush.fill,
      alpha: this.theme.style.zoomBrush.opacity
    });
  }
  /**
   * Draw treemap tiles and labels on canvas.
   * @param {object} $$ ChartInternal instance
   * @private
   */
  drawTreemaps($$) {
    var _a;
    const { ctx, painter, theme: { style } } = this;
    const { config } = $$;
    const root = (_a = $$.getTreemapRoot) == null ? void 0 : _a.call($$, $$.data.targets);
    const nodes = (root == null ? void 0 : root.children) || [];
    painter.withState(() => {
      var _a2;
      ctx.lineWidth = style.treemap.lineWidth;
      ctx.strokeStyle = style.treemap.stroke;
      for (const node of nodes) {
        const { data } = node;
        if (!isCanvasTreemapType($$, data)) {
          continue;
        }
        const { x, y, w, h } = getTreemapNodeRect($$, node, root, true);
        if (!isFiniteCanvasCoordinate(x, y) || !isFiniteCanvasCoordinate(x + w, y + h) || w <= 0 || h <= 0) {
          continue;
        }
        const rect = { x, y, w, h };
        ctx.fillStyle = $$.color(data.name);
        painter.fillRect(rect);
        painter.strokeRect(rect);
        if (!config.treemap_label_show || (data.ratio || 0) < (config.treemap_label_threshold || 0)) {
          continue;
        }
        const label = getTreemapLabelText($$, data, w, h);
        if (!label) {
          continue;
        }
        const lines = label.split("\n");
        const isCentered = !!config.data_labels.centered;
        ctx.font = style.label.font;
        const lineHeight = getFontSize(ctx.font);
        const metrics = ctx.measureText((_a2 = lines[0]) != null ? _a2 : "");
        const fontBoundingHeight = (metrics.fontBoundingBoxAscent || 0) + (metrics.fontBoundingBoxDescent || 0) || (metrics.actualBoundingBoxAscent || 0) + (metrics.actualBoundingBoxDescent || 0);
        const textHeight = Math.max(lineHeight, fontBoundingHeight) + (lines.length - 1) * lineHeight;
        const blockY = isCentered ? y + h / 2 : y + textHeight + 5;
        let textX = isCentered ? x + w / 2 : x + 5;
        let textY = blockY - (lines.length - 1) * lineHeight / (isCentered ? 2 : 1);
        ctx.textAlign = isCentered ? "center" : "left";
        ctx.textBaseline = isCentered ? "middle" : "alphabetic";
        ({ x: textX, y: textY } = this.drawLabelImage($$, data, label, textX, textY));
        ctx.fillStyle = getLabelColor($$, data, style.label.color);
        drawLabelDecorations(
          $$,
          painter,
          data,
          label,
          textX,
          isCentered ? textY + (lines.length - 1) * lineHeight / 2 : blockY
        );
        lines.forEach((line, i) => {
          painter.text(line, textX, textY + i * lineHeight, {
            maxWidth: Math.max(0, w - 8)
          });
        });
      }
    });
  }
  /**
   * Draw synchronized focus grid on the canvas subchart.
   * @param {object} $$ ChartInternal instance
   * @param {Array} selectedData Focused data rows
   * @private
   */
  drawSubchartFocus($$, selectedData) {
    const { config, scale, state } = $$;
    const focus = selectedData == null ? void 0 : selectedData.find(
      (d) => d && hasCanvasDrawableValue($$, d)
    );
    if (!focus || !config.subchart_show || config.subchart_grid_focus_continuous || config.subchart_brush_enabled !== false || config.grid_focus_show === false || config.subchart_grid_focus === false || !config.tooltip_show || config.axis_tooltip || !scale.subX || state.width2 <= 0 || state.height2 <= 0) {
      return;
    }
    const { margin2, width2, height2 } = state;
    const pos = scale.subX(focus.x);
    if (!Number.isFinite(pos)) {
      return;
    }
    const { painter, theme: { style } } = this;
    const lineWidth = style.axis.lineWidth;
    const x = painter.crisp(margin2.left + pos, lineWidth);
    const y = painter.crisp(margin2.top + pos, lineWidth);
    painter.strokePath(() => {
      config.axis_rotated ? painter.traceLine(margin2.left, y, margin2.left + width2, y) : painter.traceLine(x, margin2.top, x, margin2.top + height2);
    }, {
      lineDash: style.focusGrid.dashArray,
      lineWidth: style.focusGrid.lineWidth,
      stroke: style.focusGrid.lineColor
    });
  }
  /**
   * Draw focus grid and focused points on canvas.
   * @param {object} $$ ChartInternal instance
   * @param {Array} selectedData Focused data rows
   * @private
   */
  drawFocus($$, selectedData) {
    if (!(selectedData == null ? void 0 : selectedData.length)) {
      return;
    }
    const { painter } = this;
    const { style } = this.theme;
    const { margin } = $$.state;
    const focus = selectedData.find(
      (d) => d && hasCanvasDrawableValue($$, d)
    );
    $$.config.subchart_grid_focus !== false && !isContinuousGridFocusEnabled($$) && this.drawSubchartFocus($$, selectedData);
    painter.withTranslation(margin.left, margin.top, () => {
      if ($$.config.tooltip_show && $$.config.grid_focus_show !== false && !$$.config.axis_tooltip && focus) {
        const { x, y } = getRenderDataPoint($$, focus);
        const axisLineWidth = style.axis.lineWidth;
        const isRotated = $$.config.axis_rotated;
        const hasIndexCoordinate = Number.isFinite(isRotated ? y : x);
        const hasValueCoordinate = Number.isFinite(isRotated ? x : y);
        const crispEdgeX = (value) => painter.crisp(margin.left + value, axisLineWidth) - margin.left;
        const crispEdgeY = (value) => painter.crisp(margin.top + value, axisLineWidth) - margin.top;
        const isEdge = $$.config.grid_focus_edge && !$$.config.tooltip_grouped;
        const continuousFocus = isContinuousGridFocusEnabled($$);
        const focusEndX = continuousFocus ? $$.state.margin2.left - margin.left + $$.state.width2 : $$.state.width;
        const focusEndY = continuousFocus ? $$.state.margin2.top - margin.top + $$.state.height2 : $$.state.height;
        if (hasIndexCoordinate) {
          painter.strokePath(() => {
            var _a, _b;
            if (isRotated) {
              painter.traceLine(
                crispEdgeX(0),
                y,
                isEdge && hasValueCoordinate ? x : crispEdgeX(focusEndX),
                y
              );
              if (hasValueCoordinate && $$.config.grid_focus_y && !$$.config.tooltip_grouped) {
                const isY2 = ((_a = $$.axis) == null ? void 0 : _a.getId(focus.id)) === "y2";
                painter.traceLine(
                  x,
                  isEdge && !isY2 ? y : crispEdgeY(0),
                  x,
                  isEdge && isY2 ? y : crispEdgeY($$.state.height)
                );
              }
            } else {
              painter.traceLine(
                x,
                isEdge && hasValueCoordinate ? y : crispEdgeY(0),
                x,
                crispEdgeY(focusEndY)
              );
              if (hasValueCoordinate && $$.config.grid_focus_y && !$$.config.tooltip_grouped) {
                const isY2 = ((_b = $$.axis) == null ? void 0 : _b.getId(focus.id)) === "y2";
                painter.traceLine(
                  isEdge && isY2 ? x : crispEdgeX(0),
                  y,
                  isEdge && !isY2 ? x : crispEdgeX($$.state.width),
                  y
                );
              }
            }
          }, {
            lineDash: style.focusGrid.dashArray,
            lineWidth: style.focusGrid.lineWidth,
            stroke: style.focusGrid.lineColor
          });
        }
      }
      if ($$.config.point_show && !$$.state.canvasFocusMainRedraw) {
        selectedData.filter(
          (d) => d && hasCanvasDrawableValue($$, d) && isCanvasPointType($$, d) && isCanvasRenderableTarget($$, { id: d.id })
        ).forEach((d) => {
          var _a, _b, _c, _d;
          const pointType = getPointType($$, { id: d.id });
          const { x, y } = getRenderDataPoint($$, d);
          const baseR = (_b = (_a = $$.pointR) == null ? void 0 : _a.call($$, d)) != null ? _b : 2.5;
          const r = (_d = (_c = $$.pointExpandedR) == null ? void 0 : _c.call($$, d)) != null ? _d : baseR * 1.75;
          const overColor = getCanvasOverColor($$, d);
          const color = overColor || $$.color(d.id);
          const fill = overColor || style.focusPoint.fill || style.shape.pointFillColor || color;
          const stroke = overColor || style.focusPoint.stroke || color;
          const lineWidth = style.focusPoint.lineWidth;
          const alpha = getPointOpacity($$, d);
          const hasStroke = !!stroke && (lineWidth != null ? lineWidth : 0) > 0;
          const mergeSameColorStroke = pointType === "circle" && hasStroke && isNumber(alpha) && alpha < 1 && fill === stroke;
          if (!isFiniteCanvasCoordinate(x, y)) {
            return;
          }
          drawPointPattern(
            painter,
            pointType,
            x,
            y,
            mergeSameColorStroke ? r + (lineWidth || 0) / 2 : r,
            hasStroke && !mergeSameColorStroke ? { fill, lineWidth, stroke, alpha } : { fill, alpha },
            baseR
          );
        });
      }
      this.drawFocusLabels($$, selectedData);
    });
  }
}

;// ./src/canvas/CanvasTheme.ts
var CanvasTheme_defProp = Object.defineProperty;
var CanvasTheme_getOwnPropSymbols = Object.getOwnPropertySymbols;
var CanvasTheme_hasOwnProp = Object.prototype.hasOwnProperty;
var CanvasTheme_propIsEnum = Object.prototype.propertyIsEnumerable;
var CanvasTheme_defNormalProp = (obj, key, value) => key in obj ? CanvasTheme_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __objRest = (source, exclude) => {
  var target = {};
  for (var prop in source)
    if (CanvasTheme_hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
      target[prop] = source[prop];
  if (source != null && CanvasTheme_getOwnPropSymbols)
    for (var prop of CanvasTheme_getOwnPropSymbols(source)) {
      if (exclude.indexOf(prop) < 0 && CanvasTheme_propIsEnum.call(source, prop))
        target[prop] = source[prop];
    }
  return target;
};
var CanvasTheme_publicField = (obj, key, value) => CanvasTheme_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);


const SVG_NS = "http://www.w3.org/2000/svg";
function toNumber(value, fallback) {
  const parsed = typeof value === "number" ? value : parseFloat(value != null ? value : "");
  return Number.isFinite(parsed) ? parsed : fallback;
}
function toPaintOpacity(value, fallback) {
  const opacity = toNumber(value.opacity, 1);
  const fillOpacity = toNumber(value["fill-opacity"], 1);
  const result = opacity * fillOpacity;
  return Number.isFinite(result) ? result : fallback;
}
function toColor(value, fallback) {
  const color = value == null ? void 0 : value.trim();
  return color && !/^(none|transparent|rgba\(0,\s*0,\s*0,\s*0\))$/i.test(color) ? color : fallback;
}
function toOptionalColor(value, ignored) {
  const color = toColor(value, "");
  const ignoredColor = ignored ? toColor(ignored, "") : "";
  return color && color !== ignoredColor ? color : void 0;
}
function toOptionalNumber(value, ignored) {
  const parsed = typeof value === "number" ? value : parseFloat(value != null ? value : "");
  const ignoredParsed = typeof ignored === "number" ? ignored : parseFloat(ignored != null ? ignored : "");
  return Number.isFinite(parsed) && (!Number.isFinite(ignoredParsed) || parsed !== ignoredParsed) ? parsed : void 0;
}
function toDashArray(value) {
  if (Array.isArray(value)) {
    return value.filter((v) => Number.isFinite(v) && v > 0);
  }
  return (value || "").split(/[,\s]+/).map((v) => parseFloat(v)).filter((v) => Number.isFinite(v) && v > 0);
}
function toFont(style, fallback) {
  const font = style.getPropertyValue("font").trim();
  if (font) {
    return font;
  }
  const fontSize = style.getPropertyValue("font-size").trim();
  const fontFamily = style.getPropertyValue("font-family").trim();
  if (!fontSize || !fontFamily) {
    return fallback;
  }
  const fontStyle = style.getPropertyValue("font-style").trim();
  const fontVariant = style.getPropertyValue("font-variant").trim();
  const fontWeight = style.getPropertyValue("font-weight").trim();
  const lineHeight = style.getPropertyValue("line-height").trim();
  const size = lineHeight && lineHeight !== "normal" ? `${fontSize}/${lineHeight}` : fontSize;
  return [
    fontStyle && fontStyle !== "normal" ? fontStyle : "",
    fontVariant && fontVariant !== "normal" ? fontVariant : "",
    fontWeight && !/^(normal|400)$/.test(fontWeight) ? fontWeight : "",
    size,
    fontFamily
  ].filter(Boolean).join(" ");
}
function getStyleValue(style, prop) {
  var _a;
  const camelProp = prop.replace(/-([a-z])/g, (all, chr) => chr.toUpperCase());
  return (_a = style[prop]) != null ? _a : style[camelProp];
}
function readColorValue(style, prop) {
  const value = getStyleValue(style, prop);
  const color = value == null ? "" : toColor(String(value), "");
  return color || void 0;
}
function readNumberValue(style, prop) {
  const value = getStyleValue(style, prop);
  const parsed = typeof value === "number" ? value : parseFloat(String(value != null ? value : ""));
  return Number.isFinite(parsed) ? parsed : void 0;
}
function readPaintOpacityValue(style) {
  const opacity = readNumberValue(style, "opacity");
  const fillOpacity = readNumberValue(style, "fill-opacity");
  return opacity === void 0 && fillOpacity === void 0 ? void 0 : (opacity != null ? opacity : 1) * (fillOpacity != null ? fillOpacity : 1);
}
function readDashArrayValue(style) {
  const value = getStyleValue(style, "stroke-dasharray");
  const dashArray = value == null ? [] : toDashArray(value);
  return dashArray.length ? dashArray : void 0;
}
function readFontValue(style) {
  var _a, _b, _c, _d;
  const font = getStyleValue(style, "font");
  if (font != null && String(font).trim()) {
    return String(font).trim();
  }
  const fontSize = getStyleValue(style, "font-size");
  const fontFamily = getStyleValue(style, "font-family");
  if (fontSize == null || fontFamily == null) {
    return void 0;
  }
  const size = String(fontSize).trim();
  const family = String(fontFamily).trim();
  if (!size || !family) {
    return void 0;
  }
  const fontStyle = String((_a = getStyleValue(style, "font-style")) != null ? _a : "").trim();
  const fontVariant = String((_b = getStyleValue(style, "font-variant")) != null ? _b : "").trim();
  const fontWeight = String((_c = getStyleValue(style, "font-weight")) != null ? _c : "").trim();
  const lineHeight = String((_d = getStyleValue(style, "line-height")) != null ? _d : "").trim();
  return [
    fontStyle && fontStyle !== "normal" ? fontStyle : "",
    fontVariant && fontVariant !== "normal" ? fontVariant : "",
    fontWeight && !/^(normal|400)$/.test(fontWeight) ? fontWeight : "",
    lineHeight && lineHeight !== "normal" ? `${size}/${lineHeight}` : size,
    family
  ].filter(Boolean).join(" ");
}
function mergeThemeSection(target, section, values) {
  var _a;
  const override = Object.keys(values).reduce((acc, key) => {
    values[key] !== void 0 && (acc[key] = values[key]);
    return acc;
  }, {});
  if (Object.keys(override).length) {
    target[section] = mergeObj((_a = target[section]) != null ? _a : {}, override);
  }
}
function normalizeThemeSelectors(selector) {
  return selector.split(",").map(
    (value) => value.trim().replace(/\s*>\s*/g, " ").replace(/\s+/g, " ").replace(/^(?:svg)?\.bb\s+/, "").replace(/(^|\s)(?:g|path|rect|line|text|circle)\./g, "$1.")
  ).filter(Boolean);
}
function getDefinedKeys(values) {
  return Object.keys(values).filter((key) => values[key] !== void 0);
}
function assignDefined(target, source, skip) {
  getDefinedKeys(source).forEach((key) => {
    if (!(skip == null ? void 0 : skip.has(key))) {
      target[key] = source[key];
    }
  });
  return target;
}
function isSimpleGridLineSelector(selector) {
  const tokens = selector.split(" ");
  return tokens.every(
    (token, index) => token === "line" || token === "text" ? index === tokens.length - 1 : /^(\.[A-Za-z_-][\w-]*)+$/.test(token)
  );
}
function getGridLineSelectorTarget(selector) {
  const tokens = selector.split(" ");
  const target = tokens[tokens.length - 1];
  return target === "line" || target === "text" ? target : null;
}
function getClassNames(className) {
  return (className || "").split(/\s+/).filter(Boolean);
}
function getGridLineSelectorStyle(style, target) {
  const values = target === "text" ? {
    labelColor: readColorValue(style, "fill"),
    labelFont: readFontValue(style)
  } : {
    lineColor: readColorValue(style, "stroke"),
    lineWidth: readNumberValue(style, "stroke-width"),
    dashArray: readDashArrayValue(style)
  };
  return assignDefined({}, values);
}
function getGridLineSelectorOverrides(selectors) {
  const overrides = [];
  Object.keys(selectors != null ? selectors : {}).forEach((selector) => {
    normalizeThemeSelectors(selector).forEach((normalizedSelector) => {
      const target = getGridLineSelectorTarget(normalizedSelector) || "line";
      const style = getGridLineSelectorStyle(selectors[selector], target);
      if (isSimpleGridLineSelector(normalizedSelector) && getDefinedKeys(style).length) {
        overrides.push({ selector: normalizedSelector, target, style });
      }
    });
  });
  return overrides;
}
function matchesGridLineSelector(selector, axis, className, target) {
  if (!isSimpleGridLineSelector(selector)) {
    return false;
  }
  const selectorTarget = getGridLineSelectorTarget(selector);
  if (selectorTarget && selectorTarget !== target) {
    return false;
  } else if (!selectorTarget && target === "text") {
    return false;
  }
  const customClasses = getClassNames(className);
  const axisLineClass = `bb-${axis}grid-line`;
  const availableClasses = /* @__PURE__ */ new Set([
    "bb-grid",
    "bb-grid-lines",
    `bb-${axis}grid-lines`,
    axisLineClass,
    ...customClasses
  ]);
  const selectorClasses = (selector.match(/\.[A-Za-z_-][\w-]*/g) || []).map((match) => match.slice(1));
  return !!selectorClasses.length && selectorClasses.every((cls) => availableClasses.has(cls)) && (selectorClasses.includes(axisLineClass) || customClasses.some((cls) => selectorClasses.includes(cls)));
}
function applySelectorStyle(target, selector, style) {
  switch (selector) {
    case ".bb-axis path.domain":
    case ".bb-axis .domain":
    case ".bb-axis-x path.domain":
    case ".bb-axis-x .domain":
    case ".bb-axis-y path.domain":
    case ".bb-axis-y .domain":
    case ".bb-axis-y2 path.domain":
    case ".bb-axis-y2 .domain":
      mergeThemeSection(target, "axis", {
        lineColor: readColorValue(style, "stroke"),
        lineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-axis line":
    case ".bb-axis .tick line":
    case ".bb-axis-x line":
    case ".bb-axis-x .tick line":
    case ".bb-axis-y line":
    case ".bb-axis-y .tick line":
    case ".bb-axis-y2 line":
    case ".bb-axis-y2 .tick line":
      mergeThemeSection(target, "axis", {
        tickColor: readColorValue(style, "stroke"),
        tickWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-axis text":
    case ".bb-axis .tick text": {
      const font = readFontValue(style);
      mergeThemeSection(target, "axis", {
        labelColor: readColorValue(style, "fill"),
        xTickFont: font,
        yTickFont: font,
        y2TickFont: font
      });
      break;
    }
    case ".bb-axis-x text":
    case ".bb-axis-x .tick text":
      mergeThemeSection(target, "axis", {
        labelColor: readColorValue(style, "fill"),
        xTickFont: readFontValue(style)
      });
      break;
    case ".bb-axis-y text":
    case ".bb-axis-y .tick text":
      mergeThemeSection(target, "axis", {
        labelColor: readColorValue(style, "fill"),
        yTickFont: readFontValue(style)
      });
      break;
    case ".bb-axis-y2 text":
    case ".bb-axis-y2 .tick text":
      mergeThemeSection(target, "axis", {
        labelColor: readColorValue(style, "fill"),
        y2TickFont: readFontValue(style)
      });
      break;
    case ".tick._active_ text":
    case ".bb-axis .tick._active_ text":
    case ".bb-axis-x .tick._active_ text":
      mergeThemeSection(target, "axis", {
        activeLabelColor: readColorValue(style, "fill")
      });
      break;
    case ".bb-axis-x-label":
    case ".bb-axis-x .bb-axis-x-label":
      mergeThemeSection(target, "axis", {
        labelFont: readFontValue(style),
        xLabelColor: readColorValue(style, "fill")
      });
      break;
    case ".bb-axis-y-label":
    case ".bb-axis-y .bb-axis-y-label":
      mergeThemeSection(target, "axis", {
        labelFont: readFontValue(style),
        yLabelColor: readColorValue(style, "fill")
      });
      break;
    case ".bb-axis-y2-label":
    case ".bb-axis-y2 .bb-axis-y2-label":
      mergeThemeSection(target, "axis", {
        labelFont: readFontValue(style),
        y2LabelColor: readColorValue(style, "fill")
      });
      break;
    case ".bb-grid line":
    case ".bb-grid .bb-xgrid":
    case ".bb-grid .bb-ygrid":
    case ".bb-xgrid":
    case ".bb-ygrid":
      mergeThemeSection(target, "grid", {
        lineColor: readColorValue(style, "stroke"),
        lineWidth: readNumberValue(style, "stroke-width"),
        dashArray: readDashArrayValue(style)
      });
      break;
    case ".bb-grid text":
      mergeThemeSection(target, "grid", {
        labelColor: readColorValue(style, "fill"),
        labelFont: readFontValue(style)
      });
      break;
    case ".bb-xgrid-focus line":
    case ".bb-grid .bb-xgrid-focus line":
    case ".bb-grid .bb-xgrid-focus":
      mergeThemeSection(target, "focusGrid", {
        lineColor: readColorValue(style, "stroke"),
        lineWidth: readNumberValue(style, "stroke-width"),
        dashArray: readDashArrayValue(style)
      });
      break;
    case ".bb-region rect":
    case ".bb-region":
      mergeThemeSection(target, "region", {
        fill: readColorValue(style, "fill"),
        opacity: readPaintOpacityValue(style)
      });
      break;
    case ".bb-region text":
      mergeThemeSection(target, "region", {
        labelColor: readColorValue(style, "fill"),
        labelFont: readFontValue(style)
      });
      break;
    case ".bb-bar":
      mergeThemeSection(target, "shape", {
        barOpacity: readPaintOpacityValue(style),
        barStrokeColor: readColorValue(style, "stroke"),
        barLineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-bar._expanded_":
      mergeThemeSection(target, "shape", {
        barExpandedOpacity: readPaintOpacityValue(style)
      });
      break;
    case ".bb-candlestick":
      mergeThemeSection(target, "shape", {
        candlestickStrokeColor: readColorValue(style, "stroke"),
        candlestickLineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-candlestick._expanded_":
      mergeThemeSection(target, "shape", {
        candlestickExpandedOpacity: readPaintOpacityValue(style)
      });
      break;
    case ".bb-line":
      mergeThemeSection(target, "shape", {
        barConnectLineColor: readColorValue(style, "stroke"),
        barConnectLineWidth: readNumberValue(style, "stroke-width"),
        lineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-target.bb-focused .bb-line":
    case ".bb-target.bb-focused path.bb-line":
      mergeThemeSection(target, "shape", {
        lineFocusedWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-target.bb-defocused":
      mergeThemeSection(target, "shape", {
        targetDefocusedOpacity: readNumberValue(style, "opacity")
      });
      break;
    case ".bb-area":
      mergeThemeSection(target, "shape", {
        areaOpacity: readPaintOpacityValue(style)
      });
      break;
    case ".bb-circle":
      mergeThemeSection(target, "shape", {
        pointFillColor: readColorValue(style, "fill"),
        pointStrokeColor: readColorValue(style, "stroke"),
        pointLineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-selected-circle":
      mergeThemeSection(target, "selectedPoint", {
        fill: readColorValue(style, "fill"),
        stroke: readColorValue(style, "stroke"),
        lineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-circle._expanded_":
      mergeThemeSection(target, "focusPoint", {
        fill: readColorValue(style, "fill"),
        stroke: readColorValue(style, "stroke"),
        lineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-zoom-brush":
      mergeThemeSection(target, "zoomBrush", {
        fill: readColorValue(style, "fill"),
        opacity: readPaintOpacityValue(style)
      });
      break;
    case ".bb-brush .extent":
    case ".bb-brush .selection":
      mergeThemeSection(target, "subchartBrush", {
        fill: readColorValue(style, "fill"),
        opacity: readPaintOpacityValue(style)
      });
      break;
    case ".bb-brush .handle--custom":
      mergeThemeSection(target, "subchartBrush", {
        handleFill: readColorValue(style, "fill"),
        handleOpacity: readPaintOpacityValue(style),
        handleStroke: readColorValue(style, "stroke"),
        handleLineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-chart-treemaps rect":
    case ".bb-chart-treemaps":
      mergeThemeSection(target, "treemap", {
        stroke: readColorValue(style, "stroke"),
        lineWidth: readNumberValue(style, "stroke-width")
      });
      break;
    case ".bb-text.bb-empty":
    case ".bb-text .bb-empty":
    case ".bb-empty":
      mergeThemeSection(target, "emptyLabel", {
        color: readColorValue(style, "fill"),
        font: readFontValue(style)
      });
      break;
    case ".bb-text":
      mergeThemeSection(target, "label", {
        color: readColorValue(style, "fill"),
        font: readFontValue(style)
      });
      break;
    case ".bb-title":
      mergeThemeSection(target, "title", {
        color: readColorValue(style, "fill"),
        font: readFontValue(style)
      });
      break;
  }
}
function getSelectorThemeOverride(selectors) {
  const override = {};
  Object.keys(selectors != null ? selectors : {}).forEach((selector) => {
    normalizeThemeSelectors(selector).forEach((normalizedSelector) => {
      applySelectorStyle(override, normalizedSelector, selectors[selector]);
    });
  });
  return override;
}
function getThemeOverride(userOverride) {
  if (!userOverride) {
    return {};
  }
  const _a = userOverride, { selectors } = _a, styleOverride = __objRest(_a, ["selectors"]);
  return mergeObj({}, getSelectorThemeOverride(selectors), styleOverride);
}
function getThemeCacheKey(container, userOverride) {
  try {
    return JSON.stringify({
      className: container.className,
      style: container.getAttribute("style") || "",
      override: userOverride || null
    });
  } catch (e) {
    return null;
  }
}
class CanvasTheme {
  constructor() {
    CanvasTheme_publicField(this, "style");
    CanvasTheme_publicField(this, "cacheContainer", null);
    CanvasTheme_publicField(this, "cacheKey", null);
    CanvasTheme_publicField(this, "gridLineSelectorOverrides", []);
    CanvasTheme_publicField(this, "directGridOverrideKeys", /* @__PURE__ */ new Set());
  }
  /**
   * Read theme values from temporary SVG probes.
   * @param {HTMLElement} container Chart container
   * @param {object} userOverride Canvas theme override
   * @private
   */
  load(container, userOverride) {
    var _a, _b, _c, _d, _e;
    const svg = browser_doc.createElementNS(SVG_NS, "svg");
    this.gridLineSelectorOverrides = getGridLineSelectorOverrides(userOverride == null ? void 0 : userOverride.selectors);
    this.directGridOverrideKeys = new Set(
      Object.keys((_a = userOverride == null ? void 0 : userOverride.grid) != null ? _a : {})
    );
    svg.setAttribute("class", "bb");
    svg.style.cssText = "position:absolute;visibility:hidden;pointer-events:none;width:0;height:0;overflow:hidden";
    container.appendChild(svg);
    const read = (el, props) => {
      const style2 = win.getComputedStyle(el);
      const values = {};
      for (const prop of props) {
        values[prop] = prop === "font" ? toFont(style2, "") : style2.getPropertyValue(prop).trim();
      }
      return values;
    };
    const probe = (tag, cls, props) => {
      const el = browser_doc.createElementNS(SVG_NS, tag);
      el.setAttribute("class", cls);
      svg.appendChild(el);
      const value = read(el, props);
      svg.removeChild(el);
      return value;
    };
    const probeIn = (parentCls, tag, cls, props) => {
      const parent = browser_doc.createElementNS(SVG_NS, "g");
      const el = browser_doc.createElementNS(SVG_NS, tag);
      parent.setAttribute("class", parentCls);
      cls && el.setAttribute("class", cls);
      parent.appendChild(el);
      svg.appendChild(parent);
      const value = read(el, props);
      svg.removeChild(parent);
      return value;
    };
    const probeInNested = (parentCls, groupCls, tag, cls, props) => {
      const parent = browser_doc.createElementNS(SVG_NS, "g");
      const group = browser_doc.createElementNS(SVG_NS, "g");
      const el = browser_doc.createElementNS(SVG_NS, tag);
      parent.setAttribute("class", parentCls);
      group.setAttribute("class", groupCls);
      cls && el.setAttribute("class", cls);
      group.appendChild(el);
      parent.appendChild(group);
      svg.appendChild(parent);
      const value = read(el, props);
      svg.removeChild(parent);
      return value;
    };
    const probeTick = (axisCls, tag, props, tickCls = "") => {
      const axis = browser_doc.createElementNS(SVG_NS, "g");
      const tick = browser_doc.createElementNS(SVG_NS, "g");
      const el = browser_doc.createElementNS(SVG_NS, tag);
      axis.setAttribute("class", `bb-axis ${axisCls}`);
      tick.setAttribute("class", ["tick", tickCls].filter(Boolean).join(" "));
      el.textContent = tag === "text" ? "0" : "";
      tick.appendChild(el);
      axis.appendChild(tick);
      svg.appendChild(axis);
      const value = read(el, props);
      svg.removeChild(axis);
      return value;
    };
    const targetPointPaint = "rgb(1, 2, 3)";
    const probeTargetPoint = (cls, props) => {
      const style2 = browser_doc.createElement("style");
      style2.textContent = `
				.bb-shapes-canvas-probe .bb-circle {
					fill: ${targetPointPaint};
					stroke: ${targetPointPaint};
				}
			`;
      browser_doc.head.appendChild(style2);
      try {
        return probeIn("bb-shapes bb-shapes-canvas-probe", "circle", cls, props);
      } finally {
        style2.remove();
      }
    };
    const axisLine = probeIn("bb-axis bb-axis-x", "path", "domain", ["stroke", "stroke-width"]);
    const tickLine = probeTick("bb-axis-x", "line", ["stroke", "stroke-width"]);
    const xAxisText = probeTick("bb-axis-x", "text", ["fill", "font"]);
    const activeAxisText = probeTick("bb-axis-x", "text", ["fill"], "_active_");
    const axisText = probeTick("bb-axis-y", "text", ["fill", "font"]);
    const y2AxisText = probeTick("bb-axis-y2", "text", ["fill", "font"]);
    const xAxisLabel = probeIn(
      "bb-axis bb-axis-x",
      "text",
      "bb-axis-x-label",
      ["fill", "font"]
    );
    const yAxisLabel = probeIn(
      "bb-axis bb-axis-y",
      "text",
      "bb-axis-y-label",
      ["fill", "font"]
    );
    const y2AxisLabel = probeIn(
      "bb-axis bb-axis-y2",
      "text",
      "bb-axis-y2-label",
      ["fill", "font"]
    );
    const plainCircle = probe("circle", "", ["fill", "stroke", "stroke-width"]);
    const gridLine = probeIn(
      "bb-grid",
      "line",
      "bb-ygrid",
      ["stroke", "stroke-width", "stroke-dasharray"]
    );
    const gridText = probeIn("bb-grid", "text", "", ["fill", "font"]);
    const focusGridLine = probeInNested(
      "bb-grid",
      "bb-xgrid-focus",
      "line",
      "bb-xgrid-focus",
      ["stroke", "stroke-width", "stroke-dasharray"]
    );
    const emptyLabel = probe("text", "bb-text bb-empty", ["fill", "font"]);
    const regionRect = probeIn("bb-region", "rect", "", ["fill", "fill-opacity"]);
    const regionLabel = probeIn("bb-region", "text", "", ["fill", "font"]);
    const bar = probe("path", "bb-bar", ["opacity", "fill-opacity", "stroke", "stroke-width"]);
    const barExpanded = probe("path", "bb-bar _expanded_", ["opacity", "fill-opacity"]);
    const candlestick = probe("path", "bb-candlestick", ["stroke", "stroke-width"]);
    const candlestickExpanded = probe("path", "bb-candlestick _expanded_", [
      "opacity",
      "fill-opacity"
    ]);
    const line = probe("path", "bb-line", ["stroke-width"]);
    const focusedLine = probeIn("bb-target bb-focused", "path", "bb-line", ["stroke-width"]);
    const defocusedTarget = probe("g", "bb-target bb-defocused", ["opacity"]);
    const area = probe("path", "bb-area", ["opacity", "fill-opacity"]);
    const point = probe("circle", "bb-circle", ["fill", "stroke", "stroke-width"]);
    const selectedPoint = probe("circle", "bb-selected-circle", [
      "fill",
      "stroke",
      "stroke-width"
    ]);
    const focusPoint = probeTargetPoint(
      "bb-circle _expanded_",
      ["fill", "stroke", "stroke-width"]
    );
    const zoomBrush = probe("rect", "bb-zoom-brush", ["fill", "fill-opacity", "opacity"]);
    const subchartBrushExtent = probeIn("bb-brush", "rect", "extent", [
      "fill",
      "fill-opacity",
      "opacity"
    ]);
    const subchartBrushSelection = probeIn("bb-brush", "rect", "selection", [
      "fill",
      "fill-opacity",
      "opacity"
    ]);
    const subchartBrushHandle = probeIn("bb-brush", "path", "handle--custom", [
      "fill",
      "fill-opacity",
      "opacity",
      "stroke",
      "stroke-width"
    ]);
    const treemap = probeIn("bb-chart-treemaps", "rect", "", ["stroke", "stroke-width"]);
    const label = probe("text", "bb-text", ["fill", "font"]);
    const title = probeIn("", "text", "bb-title", ["fill", "font"]);
    const zoomBrushFill = toColor(zoomBrush.fill, "#000");
    const zoomBrushOpacity = toNumber(zoomBrush["fill-opacity"] || zoomBrush.opacity, 0.1);
    const subchartBrushFill = toColor(
      subchartBrushSelection.fill,
      toColor(subchartBrushExtent.fill, zoomBrushFill)
    );
    const subchartBrushOpacity = (_e = (_d = (_c = (_b = toOptionalNumber(subchartBrushSelection["fill-opacity"], 1)) != null ? _b : toOptionalNumber(subchartBrushSelection.opacity, 1)) != null ? _c : toOptionalNumber(subchartBrushExtent["fill-opacity"], 1)) != null ? _d : toOptionalNumber(subchartBrushExtent.opacity, 1)) != null ? _e : zoomBrushOpacity;
    const subchartBrushHandleStroke = toColor(subchartBrushHandle.stroke, "transparent");
    const defaultStyle = {
      axis: {
        lineColor: toColor(axisLine.stroke, "#000"),
        lineWidth: toNumber(axisLine["stroke-width"], 1),
        tickColor: toColor(tickLine.stroke, toColor(axisLine.stroke, "#000")),
        tickWidth: toNumber(
          tickLine["stroke-width"],
          toNumber(axisLine["stroke-width"], 1)
        ),
        labelFont: yAxisLabel.font || axisText.font || "10px sans-serif",
        xTickFont: xAxisText.font || axisText.font || "10px sans-serif",
        yTickFont: axisText.font || "10px sans-serif",
        y2TickFont: y2AxisText.font || axisText.font || "10px sans-serif",
        labelColor: toColor(axisText.fill, "#000"),
        xLabelColor: toColor(xAxisLabel.fill, toColor(xAxisText.fill, "#000")),
        yLabelColor: toColor(yAxisLabel.fill, toColor(axisText.fill, "#000")),
        y2LabelColor: toColor(
          y2AxisLabel.fill,
          toColor(yAxisLabel.fill, toColor(axisText.fill, "#000"))
        ),
        activeLabelColor: toOptionalColor(activeAxisText.fill, xAxisText.fill) || toColor(axisText.fill, "#000")
      },
      grid: {
        lineColor: toColor(gridLine.stroke, "#aaa"),
        lineWidth: toNumber(gridLine["stroke-width"], 1),
        dashArray: toDashArray(gridLine["stroke-dasharray"]),
        labelFont: gridText.font || axisText.font || "10px sans-serif",
        labelColor: toColor(gridText.fill, "#aaa")
      },
      focusGrid: {
        lineColor: toColor(focusGridLine.stroke, toColor(gridLine.stroke, "#aaa")),
        lineWidth: toNumber(
          focusGridLine["stroke-width"],
          toNumber(gridLine["stroke-width"], 1)
        ),
        dashArray: toDashArray(
          focusGridLine["stroke-dasharray"] || gridLine["stroke-dasharray"]
        )
      },
      emptyLabel: {
        font: emptyLabel.font || label.font || axisText.font || "20px sans-serif",
        color: toColor(emptyLabel.fill, "#808080")
      },
      region: {
        fill: toColor(regionRect.fill, "steelblue"),
        opacity: toNumber(regionRect["fill-opacity"], 0.1),
        labelFont: regionLabel.font || axisText.font || "10px sans-serif",
        labelColor: toColor(regionLabel.fill, "#000")
      },
      shape: {
        barOpacity: toPaintOpacity(bar, 1),
        barExpandedOpacity: toNumber(
          toPaintOpacity(barExpanded, toPaintOpacity(bar, 1)),
          toPaintOpacity(bar, 1)
        ),
        barStrokeColor: toColor(bar.stroke, "#000"),
        barLineWidth: toNumber(bar["stroke-width"], 0),
        barConnectLineColor: toColor(line.stroke, "#000"),
        barConnectLineWidth: toNumber(line["stroke-width"], 1),
        candlestickStrokeColor: toColor(candlestick.stroke, "#000"),
        candlestickLineWidth: toNumber(candlestick["stroke-width"], 1),
        candlestickExpandedOpacity: toNumber(
          toPaintOpacity(candlestickExpanded, 1),
          1
        ),
        lineWidth: toNumber(line["stroke-width"], 1),
        lineFocusedWidth: toNumber(focusedLine["stroke-width"], 2),
        areaOpacity: toPaintOpacity(area, 0.2),
        targetDefocusedOpacity: toNumber(defocusedTarget.opacity, 0.3),
        pointFillColor: toOptionalColor(point.fill, plainCircle.fill),
        pointStrokeColor: toOptionalColor(point.stroke, plainCircle.stroke),
        pointLineWidth: toOptionalNumber(point["stroke-width"], plainCircle["stroke-width"])
      },
      selectedPoint: {
        fill: toColor(selectedPoint.fill, "#fff"),
        stroke: toOptionalColor(selectedPoint.stroke),
        lineWidth: toNumber(selectedPoint["stroke-width"], 2)
      },
      focusPoint: {
        fill: toOptionalColor(focusPoint.fill, targetPointPaint),
        stroke: toOptionalColor(focusPoint.stroke, targetPointPaint),
        lineWidth: toNumber(focusPoint["stroke-width"], 1)
      },
      zoomBrush: {
        fill: zoomBrushFill,
        opacity: zoomBrushOpacity
      },
      subchartBrush: {
        fill: subchartBrushFill,
        opacity: subchartBrushOpacity,
        handleFill: toColor(subchartBrushHandle.fill, "transparent"),
        handleOpacity: toPaintOpacity(subchartBrushHandle, 1),
        handleStroke: subchartBrushHandleStroke,
        handleLineWidth: toNumber(
          subchartBrushHandle["stroke-width"],
          subchartBrushHandleStroke === "transparent" ? 0 : 1
        )
      },
      treemap: {
        stroke: toColor(treemap.stroke, "#fff"),
        lineWidth: toNumber(treemap["stroke-width"], 1)
      },
      label: {
        font: label.font || axisText.font || "10px sans-serif",
        color: toColor(label.fill, "#000")
      },
      title: {
        font: title.font || label.font || axisText.font || "14px sans-serif",
        color: toColor(title.fill, "#000")
      }
    };
    const themeOverride = getThemeOverride(userOverride);
    const style = mergeObj(defaultStyle, themeOverride);
    const userAxisOverride = userOverride == null ? void 0 : userOverride.axis;
    const hasUserAxisLabelColor = !!userAxisOverride && Object.prototype.hasOwnProperty.call(userAxisOverride, "labelColor");
    const hasUserAxisLabelFont = !!userAxisOverride && Object.prototype.hasOwnProperty.call(userAxisOverride, "labelFont");
    style.axis.lineWidth = toNumber(style.axis.lineWidth, defaultStyle.axis.lineWidth);
    style.axis.tickWidth = toNumber(style.axis.tickWidth, style.axis.lineWidth);
    if (hasUserAxisLabelFont) {
      const axisOverride = userAxisOverride;
      const labelFont = style.axis.labelFont;
      axisOverride.xTickFont === void 0 && (style.axis.xTickFont = labelFont);
      axisOverride.yTickFont === void 0 && (style.axis.yTickFont = labelFont);
      axisOverride.y2TickFont === void 0 && (style.axis.y2TickFont = labelFont);
    }
    style.axis.labelFont = style.axis.labelFont || defaultStyle.axis.labelFont;
    style.axis.xTickFont = style.axis.xTickFont || style.axis.labelFont;
    style.axis.yTickFont = style.axis.yTickFont || style.axis.labelFont;
    style.axis.y2TickFont = style.axis.y2TickFont || style.axis.yTickFont;
    style.axis.labelColor = toColor(style.axis.labelColor, defaultStyle.axis.labelColor);
    if (hasUserAxisLabelColor) {
      const labelColor = style.axis.labelColor;
      userAxisOverride.xLabelColor === void 0 && (style.axis.xLabelColor = labelColor);
      userAxisOverride.yLabelColor === void 0 && (style.axis.yLabelColor = labelColor);
      userAxisOverride.y2LabelColor === void 0 && (style.axis.y2LabelColor = labelColor);
    }
    style.axis.xLabelColor = toColor(style.axis.xLabelColor, style.axis.labelColor);
    style.axis.yLabelColor = toColor(style.axis.yLabelColor, style.axis.labelColor);
    style.axis.y2LabelColor = toColor(style.axis.y2LabelColor, style.axis.yLabelColor);
    style.axis.activeLabelColor = toColor(style.axis.activeLabelColor, style.axis.labelColor);
    style.grid.lineWidth = toNumber(style.grid.lineWidth, defaultStyle.grid.lineWidth);
    style.grid.dashArray = toDashArray(style.grid.dashArray);
    style.focusGrid.lineWidth = toNumber(
      style.focusGrid.lineWidth,
      defaultStyle.focusGrid.lineWidth
    );
    style.focusGrid.dashArray = toDashArray(style.focusGrid.dashArray);
    style.region.opacity = toNumber(style.region.opacity, defaultStyle.region.opacity);
    style.shape.barOpacity = toNumber(style.shape.barOpacity, defaultStyle.shape.barOpacity);
    style.shape.barExpandedOpacity = toNumber(
      style.shape.barExpandedOpacity,
      style.shape.barOpacity
    );
    style.shape.barLineWidth = toNumber(
      style.shape.barLineWidth,
      defaultStyle.shape.barLineWidth
    );
    style.shape.barConnectLineWidth = toNumber(
      style.shape.barConnectLineWidth,
      defaultStyle.shape.barConnectLineWidth
    );
    style.shape.candlestickLineWidth = toNumber(
      style.shape.candlestickLineWidth,
      defaultStyle.shape.candlestickLineWidth
    );
    style.shape.candlestickStrokeColor = toColor(
      style.shape.candlestickStrokeColor,
      defaultStyle.shape.candlestickStrokeColor
    );
    style.shape.candlestickExpandedOpacity = toNumber(
      style.shape.candlestickExpandedOpacity,
      defaultStyle.shape.candlestickExpandedOpacity
    );
    style.shape.lineWidth = toNumber(style.shape.lineWidth, defaultStyle.shape.lineWidth);
    style.shape.lineFocusedWidth = toNumber(
      style.shape.lineFocusedWidth,
      defaultStyle.shape.lineFocusedWidth
    );
    style.shape.areaOpacity = toNumber(style.shape.areaOpacity, defaultStyle.shape.areaOpacity);
    style.shape.targetDefocusedOpacity = toNumber(
      style.shape.targetDefocusedOpacity,
      defaultStyle.shape.targetDefocusedOpacity
    );
    style.shape.pointLineWidth = toOptionalNumber(style.shape.pointLineWidth);
    style.selectedPoint.lineWidth = toNumber(
      style.selectedPoint.lineWidth,
      defaultStyle.selectedPoint.lineWidth
    );
    style.focusPoint.lineWidth = toNumber(
      style.focusPoint.lineWidth,
      defaultStyle.focusPoint.lineWidth
    );
    style.zoomBrush.opacity = toNumber(style.zoomBrush.opacity, defaultStyle.zoomBrush.opacity);
    style.subchartBrush.opacity = toNumber(
      style.subchartBrush.opacity,
      defaultStyle.subchartBrush.opacity
    );
    style.subchartBrush.handleOpacity = toNumber(
      style.subchartBrush.handleOpacity,
      defaultStyle.subchartBrush.handleOpacity
    );
    style.subchartBrush.handleLineWidth = toNumber(
      style.subchartBrush.handleLineWidth,
      defaultStyle.subchartBrush.handleLineWidth
    );
    style.treemap.lineWidth = toNumber(style.treemap.lineWidth, defaultStyle.treemap.lineWidth);
    this.style = style;
    this.cacheContainer = container;
    this.cacheKey = getThemeCacheKey(container, userOverride);
    svg.remove();
  }
  /**
   * Reload theme values after resize or option changes.
   * @param {HTMLElement} container Chart container
   * @param {object} userOverride Canvas theme override
   * @private
   */
  reload(container, userOverride) {
    const key = getThemeCacheKey(container, userOverride);
    if (key !== null && this.style && this.cacheContainer === container && this.cacheKey === key) {
      return;
    }
    this.load(container, userOverride);
  }
  /**
   * Resolve selector based style for one configured optional grid line.
   * @param {string} axis Grid axis
   * @param {object} line Grid line options
   * @param {string} line.class Grid line custom class
   * @param {string} target Draw target
   * @returns {object|undefined} Grid line style override
   * @private
   */
  getGridLineStyle(axis, line = {}, target = "line") {
    const style = {};
    for (const override of this.gridLineSelectorOverrides) {
      if (!matchesGridLineSelector(override.selector, axis, line.class, target)) {
        continue;
      }
      assignDefined(style, override.style, this.directGridOverrideKeys);
    }
    return getDefinedKeys(style).length ? style : void 0;
  }
}

;// ./src/canvas/HitDetector.ts
var HitDetector_defProp = Object.defineProperty;
var HitDetector_defNormalProp = (obj, key, value) => key in obj ? HitDetector_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var HitDetector_publicField = (obj, key, value) => HitDetector_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);




const HIT_DISTANCE = 24;
const BAR_CELL_SIZE = 64;
const HIT_GROUPED_TYPE_FILTERS = [
  isCanvasPointType,
  isCanvasBarType,
  isCanvasCandlestickType
];
function getCell(value, size) {
  return Math.floor(value / size);
}
function addGridItem(grid, item, size) {
  var _a, _b;
  const minX = getCell(item.x, size);
  const maxX = getCell(item.x + ((_a = item.w) != null ? _a : 0), size);
  const minY = getCell(item.y, size);
  const maxY = getCell(item.y + ((_b = item.h) != null ? _b : 0), size);
  for (let x = minX; x <= maxX; x++) {
    for (let y = minY; y <= maxY; y++) {
      const key = `${x}:${y}`;
      const items = grid.get(key);
      items ? items.push(item) : grid.set(key, [item]);
    }
  }
}
function getGridItems(grid, x, y, size, radius = 0) {
  const cellX = getCell(x, size);
  const cellY = getCell(y, size);
  const items = [];
  for (let dx = -radius; dx <= radius; dx++) {
    for (let dy = -radius; dy <= radius; dy++) {
      const values = grid.get(`${cellX + dx}:${cellY + dy}`);
      if (values == null ? void 0 : values.length) {
        for (let i = 0; i < values.length; i++) {
          items.push(values[i]);
        }
      }
    }
  }
  return items;
}
function getPointHitSensitivity($$, d) {
  var _a, _b, _c;
  const sensitivity = $$.config.point_sensitivity;
  if (Number.isFinite(sensitivity)) {
    return sensitivity;
  }
  (_a = $$.pointR) == null ? void 0 : _a.call($$, d);
  const resolved = (_c = (_b = $$.getPointSensitivity) == null ? void 0 : _b.call($$, d)) != null ? _c : HIT_DISTANCE;
  return Number.isFinite(resolved) ? resolved : HIT_DISTANCE;
}
function shouldCullDenseScatterHitPoints($$, target) {
  return isCanvasScatterType($$, target) && target.values.length > DENSE_SCATTER_POINT_CULL_THRESHOLD && !$$.config.data_selection_enabled && Number.isFinite($$.config.point_sensitivity) && Number.isFinite($$.config.point_r);
}
class HitDetector {
  constructor() {
    HitDetector_publicField(this, "bars", []);
    HitDetector_publicField(this, "points", []);
    HitDetector_publicField(this, "indices", []);
    HitDetector_publicField(this, "barGrid", /* @__PURE__ */ new Map());
    HitDetector_publicField(this, "pointGrid", /* @__PURE__ */ new Map());
    HitDetector_publicField(this, "plot", { x: 0, y: 0, w: 0, h: 0 });
    HitDetector_publicField(this, "pointCellSize", HIT_DISTANCE);
    HitDetector_publicField(this, "maxPointSensitivity", HIT_DISTANCE);
    HitDetector_publicField(this, "grouped", false);
    HitDetector_publicField(this, "pointBased", false);
    HitDetector_publicField(this, "indexAxis", "x");
  }
  /**
   * Rebuild hit-test indexes from current chart geometry.
   * @param {object} $$ ChartInternal instance
   * @param {object} shape Cached draw shape object
   * @private
   */
  rebuild($$, shape) {
    var _a, _b, _c;
    const { current, margin, width, height } = $$.state;
    const targets = $$.filterTargetsToShow();
    this.bars = [];
    this.points = [];
    this.indices = [];
    this.barGrid = /* @__PURE__ */ new Map();
    this.pointGrid = /* @__PURE__ */ new Map();
    this.maxPointSensitivity = HIT_DISTANCE;
    this.indexAxis = $$.config.axis_rotated ? "y" : "x";
    this.plot = $$.state.hasTreemap ? { x: 0, y: 0, w: current.width, h: current.height } : { x: margin.left, y: margin.top, w: width, h: height };
    this.grouped = !!$$.config.tooltip_grouped && !$$.state.hasTreemap;
    this.pointBased = !($$.config.axis_x_forceAsSingle && this.grouped) && (!!((_a = $$.isMultipleX) == null ? void 0 : _a.call($$)) || targets.some(
      (target) => isCanvasScatterType($$, target) || isCanvasBubbleType($$, target)
    ));
    const needsIndex = this.grouped && (!this.pointBased || $$.config.data_selection_enabled && $$.config.data_selection_grouped);
    const indexMap = needsIndex ? /* @__PURE__ */ new Map() : null;
    const addIndex = (x, y, data) => {
      var _a2, _b2;
      if (!indexMap) {
        return;
      }
      const key = (_b2 = (_a2 = $$.getXCacheKey) == null ? void 0 : _a2.call($$, data.x)) != null ? _b2 : data.index;
      if (Number.isFinite(data.index) && !indexMap.has(key) && isFiniteCanvasCoordinate(x, y)) {
        indexMap.set(key, { x, y, data });
      }
    };
    if ($$.state.hasTreemap) {
      const root = (_b = $$.getTreemapRoot) == null ? void 0 : _b.call($$, $$.data.targets);
      const nodes = (root == null ? void 0 : root.children) || [];
      for (const node of nodes) {
        const { data } = node;
        if (!isCanvasTreemapType($$, data)) {
          continue;
        }
        const { x, y, w, h } = getTreemapNodeRect($$, node, root, true);
        if (!isFiniteCanvasCoordinate(x, y) || !isFiniteCanvasCoordinate(x + w, y + h)) {
          continue;
        }
        this.addBar({ x, y, w, h, data });
      }
      this.indices = [];
      return;
    }
    if (shape.indices[TYPE.BAR] || targets.some(isCanvasBarType.bind(null, $$))) {
      const isBar = isCanvasBarType.bind(null, $$);
      const indices = getCanvasShapeIndices($$, shape, TYPE.BAR, isBar);
      const getPoints = $$.generateGetBarPoints(indices, false);
      targets.filter(isBar).filter((target) => isCanvasTargetSupported($$, target, HIT_GROUPED_TYPE_FILTERS)).forEach((target) => {
        const range = getCanvasTargetVisibleRange($$, target);
        for (let i = range.start; i < range.end; i++) {
          const d = target.values[i];
          if (!hasCanvasDrawableValue($$, d)) {
            continue;
          }
          const geometry = getCanvasBarGeometry($$, getPoints, d, i);
          if (!geometry) {
            continue;
          }
          const { rect } = geometry;
          const x = margin.left + rect.x;
          const y = margin.top + rect.y;
          const { w, h } = rect;
          this.addBar({ x, y, w, h, data: d });
          addIndex(x + w / 2, y + h / 2, d);
        }
      });
    }
    if (shape.indices[TYPE.CANDLESTICK] || targets.some(isCanvasCandlestickType.bind(null, $$))) {
      const isCandlestick = isCanvasCandlestickType.bind(null, $$);
      const indices = getCanvasShapeIndices($$, shape, TYPE.CANDLESTICK, isCandlestick);
      const getPoints = (_c = $$.generateGetCandlestickPoints) == null ? void 0 : _c.call($$, indices, false);
      if (getPoints) {
        targets.filter(isCandlestick).filter((target) => isCanvasTargetSupported($$, target, HIT_GROUPED_TYPE_FILTERS)).forEach((target) => {
          var _a2;
          const range = getCanvasTargetVisibleRange($$, target);
          for (let i = range.start; i < range.end; i++) {
            const d = target.values[i];
            const value = (_a2 = $$.getCandlestickData) == null ? void 0 : _a2.call($$, d);
            if (!value) {
              continue;
            }
            const geometry = getCanvasCandlestickGeometry($$, getPoints, d, i);
            if (!geometry) {
              continue;
            }
            const { body: rect } = geometry;
            const x = margin.left + rect.x;
            const y = margin.top + rect.y;
            const { w, h } = rect;
            this.addBar({
              x,
              y,
              w: Math.max(1, w),
              h: Math.max(1, h),
              data: d
            });
            addIndex(x + w / 2, y + h / 2, d);
          }
        });
      }
    }
    const { cx, cy } = shape.pos;
    if (cx && cy) {
      targets.filter(isCanvasPointType.bind(null, $$)).filter((target) => isCanvasTargetSupported($$, target, HIT_GROUPED_TYPE_FILTERS)).forEach((target) => {
        const range = getCanvasTargetVisibleRange($$, target);
        const occupancy = shouldCullDenseScatterHitPoints($$, target) ? createCanvasPointOccupancyGrid(width, height, $$.config.point_r) : null;
        for (let i = range.start; i < range.end; i++) {
          const d = target.values[i];
          if (!hasCanvasDrawableValue($$, d)) {
            continue;
          }
          const x = margin.left + cx(d, i);
          const y = margin.top + cy(d, i);
          const sensitivity = getPointHitSensitivity($$, d);
          if (!isFiniteCanvasCoordinate(x, y)) {
            continue;
          }
          if (occupancy && !markCanvasPointOccupancy(
            occupancy,
            x - margin.left,
            y - margin.top
          )) {
            continue;
          }
          this.addPoint({
            x,
            y,
            sensitivity,
            data: d
          });
          addIndex(x, y, d);
        }
      });
    }
    this.buildPointGrid();
    this.indices = indexMap ? Array.from(indexMap.values()).sort((a, b) => a[this.indexAxis] - b[this.indexAxis]) : [];
  }
  /**
   * Hit-test bars at the given canvas coordinates.
   * @param {number} mx Mouse x coordinate
   * @param {number} my Mouse y coordinate
   * @returns {object|null} Matching data row
   * @private
   */
  hitBar(mx, my) {
    for (const item of getGridItems(this.barGrid, mx, my, BAR_CELL_SIZE)) {
      const { w = 0, h = 0 } = item;
      if (mx >= item.x && mx <= item.x + w && my >= item.y && my <= item.y + h) {
        return item.data;
      }
    }
    return null;
  }
  /**
   * Find the nearest point within sensitivity at the given canvas coordinates.
   * @param {number} mx Mouse x coordinate
   * @param {number} my Mouse y coordinate
   * @returns {object|null} Matching data row
   * @private
   */
  hitPoint(mx, my) {
    var _a, _b;
    let nearest = null;
    let min = Number.POSITIVE_INFINITY;
    for (const item of getGridItems(this.pointGrid, mx, my, this.pointCellSize, 1)) {
      const dx = item.x - mx;
      const dy = item.y - my;
      const dist = Math.sqrt(dx * dx + dy * dy);
      const sensitivity = (_a = item.sensitivity) != null ? _a : HIT_DISTANCE;
      if (dist <= sensitivity && dist < min) {
        min = dist;
        nearest = item;
      }
    }
    return (_b = nearest == null ? void 0 : nearest.data) != null ? _b : null;
  }
  /**
   * Find the nearest data row for the given canvas coordinates.
   * @param {number} mx Mouse x coordinate
   * @param {number} my Mouse y coordinate
   * @returns {object|null} Matching data row
   * @private
   */
  findNearest(mx, my) {
    const bar = this.hitBar(mx, my);
    if (bar) {
      return bar;
    }
    if (!this.pointBased && this.grouped && this.isWithinPlot(mx, my)) {
      const item = this.findNearestIndexItem(mx, my);
      if (item) {
        return item.data;
      }
    }
    return this.hitPoint(mx, my);
  }
  /**
   * Find the nearest directly hit shape row, excluding grouped index fallback.
   * @param {number} mx Mouse x coordinate
   * @param {number} my Mouse y coordinate
   * @returns {object|null} Matching data row
   * @private
   */
  findNearestShape(mx, my) {
    var _a;
    return (_a = this.hitBar(mx, my)) != null ? _a : this.hitPoint(mx, my);
  }
  /**
   * Find the nearest grouped x-index row for an axis-adjacent pointer coordinate.
   * @param {number} mx Mouse x coordinate
   * @param {number} my Mouse y coordinate
   * @returns {object|null} Matching data row
   * @private
   */
  findNearestIndexByCoord(mx, my) {
    var _a, _b;
    return (_b = (_a = this.findNearestIndexItem(mx, my)) == null ? void 0 : _a.data) != null ? _b : null;
  }
  /**
   * Find data rows included by a rectangular selection area.
   * @param {object} rect Selection rectangle in canvas coordinates
   * @param {boolean} grouped Whether to match by the index axis only
   * @returns {Array} Matching data rows
   * @private
   */
  findInRect(rect, grouped = false) {
    const x1 = Math.min(rect.x, rect.x + rect.w);
    const x2 = Math.max(rect.x, rect.x + rect.w);
    const y1 = Math.min(rect.y, rect.y + rect.h);
    const y2 = Math.max(rect.y, rect.y + rect.h);
    const seen = /* @__PURE__ */ new Set();
    const data = [];
    const add = (item) => {
      const d = item.data;
      const key = `${d.id}:${d.index}`;
      if (!seen.has(key)) {
        seen.add(key);
        data.push(d);
      }
    };
    if (grouped) {
      const axis = this.indexAxis;
      const min = axis === "y" ? y1 : x1;
      const max = axis === "y" ? y2 : x2;
      this.indices.filter((item) => item[axis] >= min && item[axis] <= max).forEach(add);
      return data;
    }
    this.bars.filter((item) => {
      var _a, _b;
      const w = (_a = item.w) != null ? _a : 0;
      const h = (_b = item.h) != null ? _b : 0;
      return !(x2 < item.x || item.x + w < x1) && !(y2 < item.y || item.y + h < y1);
    }).forEach(add);
    this.points.filter((item) => item.x >= x1 && item.x <= x2 && item.y >= y1 && item.y <= y2).forEach(add);
    return data;
  }
  /**
   * Add bar-like hit item and register its grid coverage.
   * @param {object} item Hit item
   * @private
   */
  addBar(item) {
    this.bars.push(item);
    addGridItem(this.barGrid, item, BAR_CELL_SIZE);
  }
  /**
   * Add point-like hit item.
   * @param {object} item Hit item
   * @private
   */
  addPoint(item) {
    var _a;
    const sensitivity = (_a = item.sensitivity) != null ? _a : HIT_DISTANCE;
    this.maxPointSensitivity = Math.max(this.maxPointSensitivity, sensitivity);
    this.points.push(item);
  }
  /**
   * Build point spatial grid after the maximum sensitivity is known.
   * @private
   */
  buildPointGrid() {
    this.pointCellSize = Math.max(1, this.maxPointSensitivity);
    this.pointGrid = /* @__PURE__ */ new Map();
    for (const point of this.points) {
      addGridItem(this.pointGrid, point, this.pointCellSize);
    }
  }
  /**
   * Check if coordinates are inside the plot area.
   * @param {number} x X coordinate
   * @param {number} y Y coordinate
   * @returns {boolean} Whether the coordinates are inside the plot
   * @private
   */
  isWithinPlot(x, y) {
    const { plot } = this;
    return x >= plot.x && x <= plot.x + plot.w && y >= plot.y && y <= plot.y + plot.h;
  }
  /**
   * Find the nearest indexed data row by current index-axis coordinate.
   * @param {number} x X coordinate
   * @param {number} y Y coordinate
   * @returns {object|null} Matching hit item
   * @private
   */
  findNearestIndexItem(x, y) {
    const { indexAxis, indices } = this;
    const value = indexAxis === "y" ? y : x;
    if (!indices.length) {
      return null;
    }
    let start = 0;
    let end = indices.length - 1;
    while (start < end) {
      const mid = start + end >> 1;
      if (indices[mid][indexAxis] < value) {
        start = mid + 1;
      } else {
        end = mid;
      }
    }
    const current = indices[start];
    const previous = indices[start - 1];
    return previous && Math.abs(previous[indexAxis] - value) < Math.abs(current[indexAxis] - value) ? previous : current;
  }
}

// EXTERNAL MODULE: external {"commonjs":"d3-time-format","commonjs2":"d3-time-format","amd":"d3-time-format","root":"d3"}
var external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_ = __webpack_require__(5);
;// ./src/config/classes.ts
var classes_defProp = Object.defineProperty;
var classes_getOwnPropSymbols = Object.getOwnPropertySymbols;
var classes_hasOwnProp = Object.prototype.hasOwnProperty;
var classes_propIsEnum = Object.prototype.propertyIsEnumerable;
var classes_defNormalProp = (obj, key, value) => key in obj ? classes_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var classes_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (classes_hasOwnProp.call(b, prop))
      classes_defNormalProp(a, prop, b[prop]);
  if (classes_getOwnPropSymbols)
    for (var prop of classes_getOwnPropSymbols(b)) {
      if (classes_propIsEnum.call(b, prop))
        classes_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
const $COMMON = {
  button: "bb-button",
  chart: "bb-chart",
  empty: "bb-empty",
  main: "bb-main",
  target: "bb-target",
  EXPANDED: "_expanded_",
  dummy: "_dummy_"
};
const $ARC = {
  arc: "bb-arc",
  arcLabelLine: "bb-arc-label-line",
  arcLabelLineText: "bb-arc-label-line-text",
  arcRange: "bb-arc-range",
  arcs: "bb-arcs",
  chartArc: "bb-chart-arc",
  chartArcs: "bb-chart-arcs",
  chartArcsBackground: "bb-chart-arcs-background",
  chartArcsTitle: "bb-chart-arcs-title",
  needle: "bb-needle"
};
const $AREA = {
  area: "bb-area",
  areas: "bb-areas"
};
const $AXIS = {
  axis: "bb-axis",
  axisX: "bb-axis-x",
  axisXLabel: "bb-axis-x-label",
  axisY: "bb-axis-y",
  axisY2: "bb-axis-y2",
  axisY2Label: "bb-axis-y2-label",
  axisYLabel: "bb-axis-y-label",
  axisXTooltip: "bb-axis-x-tooltip",
  axisYTooltip: "bb-axis-y-tooltip",
  axisY2Tooltip: "bb-axis-y2-tooltip",
  axisTooltipX: "bb-axis-tooltip-x",
  axisTooltipY: "bb-axis-tooltip-y"
};
const $BAR = {
  bar: "bb-bar",
  bars: "bb-bars",
  chartBar: "bb-chart-bar",
  chartBars: "bb-chart-bars",
  barConnectLine: "bb-bar-connectLine"
};
const $CANDLESTICK = {
  candlestick: "bb-candlestick",
  candlesticks: "bb-candlesticks",
  chartCandlestick: "bb-chart-candlestick",
  chartCandlesticks: "bb-chart-candlesticks",
  valueDown: "bb-value-down",
  valueUp: "bb-value-up"
};
const $CIRCLE = {
  chartCircles: "bb-chart-circles",
  circle: "bb-circle",
  circles: "bb-circles"
};
const $COLOR = {
  colorPattern: "bb-color-pattern",
  colorScale: "bb-colorscale"
};
const $DRAG = {
  dragarea: "bb-dragarea",
  INCLUDED: "_included_"
};
const $FUNNEL = {
  funnel: "bb-funnel",
  chartFunnel: "bb-chart-funnel",
  chartFunnels: "bb-chart-funnels",
  funnelBackground: "bb-funnel-background"
};
const $GAUGE = {
  chartArcsGaugeMax: "bb-chart-arcs-gauge-max",
  chartArcsGaugeMin: "bb-chart-arcs-gauge-min",
  chartArcsGaugeUnit: "bb-chart-arcs-gauge-unit",
  chartArcsGaugeTitle: "bb-chart-arcs-gauge-title",
  gaugeValue: "bb-gauge-value"
};
const $LEGEND = {
  legend: "bb-legend",
  legendBackground: "bb-legend-background",
  legendItem: "bb-legend-item",
  legendItemEvent: "bb-legend-item-event",
  legendItemHidden: "bb-legend-item-hidden",
  legendItemPoint: "bb-legend-item-point",
  legendItemTile: "bb-legend-item-tile"
};
const $LINE = {
  chartLine: "bb-chart-line",
  chartLines: "bb-chart-lines",
  line: "bb-line",
  lines: "bb-lines"
};
const $EVENT = {
  eventRect: "bb-event-rect",
  eventRects: "bb-event-rects",
  eventRectsMultiple: "bb-event-rects-multiple",
  eventRectsSingle: "bb-event-rects-single"
};
const $FOCUS = {
  focused: "bb-focused",
  defocused: "bb-defocused",
  legendItemFocused: "bb-legend-item-focused",
  xgridFocus: "bb-xgrid-focus",
  xgridFocusContinuous: "bb-xgrid-focus-continuous",
  ygridFocus: "bb-ygrid-focus"
};
const $GRID = {
  grid: "bb-grid",
  gridLines: "bb-grid-lines",
  xgrid: "bb-xgrid",
  xgridLine: "bb-xgrid-line",
  xgridLines: "bb-xgrid-lines",
  xgrids: "bb-xgrids",
  ygrid: "bb-ygrid",
  ygridLine: "bb-ygrid-line",
  ygridLines: "bb-ygrid-lines",
  ygrids: "bb-ygrids"
};
const $LEVEL = {
  level: "bb-level",
  levels: "bb-levels"
};
const $RADAR = {
  chartRadar: "bb-chart-radar",
  chartRadars: "bb-chart-radars"
};
const $REGION = {
  region: "bb-region",
  regions: "bb-regions"
};
const $SELECT = {
  selectedCircle: "bb-selected-circle",
  selectedCircles: "bb-selected-circles",
  SELECTED: "_selected_"
};
const $SHAPE = {
  shape: "bb-shape",
  shapes: "bb-shapes"
};
const $SUBCHART = {
  brush: "bb-brush",
  subchart: "bb-subchart"
};
const $TEXT = {
  chartText: "bb-chart-text",
  chartTexts: "bb-chart-texts",
  text: "bb-text",
  texts: "bb-texts",
  title: "bb-title",
  textBorderRect: "bb-text-border",
  textLabelImage: "bb-text-label-image",
  TextOverlapping: "text-overlapping"
};
const $TOOLTIP = {
  tooltip: "bb-tooltip",
  tooltipContainer: "bb-tooltip-container",
  tooltipName: "bb-tooltip-name"
};
const $TREEMAP = {
  treemap: "bb-treemap",
  chartTreemap: "bb-chart-treemap",
  chartTreemaps: "bb-chart-treemaps"
};
const $ZOOM = {
  buttonZoomReset: "bb-zoom-reset",
  zoomBrush: "bb-zoom-brush"
};
/* harmony default export */ var config_classes = (classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues(classes_spreadValues({}, $COMMON), $ARC), $AREA), $AXIS), $BAR), $CANDLESTICK), $CIRCLE), $COLOR), $DRAG), $GAUGE), $LEGEND), $LINE), $EVENT), $FOCUS), $FUNNEL), $GRID), $LEVEL), $RADAR), $REGION), $SELECT), $SHAPE), $SUBCHART), $TEXT), $TOOLTIP), $TREEMAP), $ZOOM));

;// ./src/config/Options/common/boost.ts
/* harmony default export */ var boost = ({
  /**
   * Set boost options
   * @name boost
   * @memberof Options
   * @type {object}
   * @property {object} boost boost object
   * @property {boolean} [boost.useCssRule=false] Avoid setting inline styles for each shape elements.
   * - **NOTE:**
   *   - Will append &lt;style> to the head tag and will add shpes' CSS rules dynamically.
   *   - For now, covers colors related properties (fill, stroke, etc.) only.
   * @property {boolean|string} [boost.useWorker=false] Use Web Worker as possible for processing.
   * - **Available values:**
   *   - `false`: never offload.
   *   - `true`: always offload when a Worker can be created.
   *   - `"auto"`: offload only when the given data exceeds ~5,000 cells, since smaller
   *     payloads lose more to structured cloning than they gain.
   * - **NOTE:**
   *   - For now, only applies for data conversion at the initial time.
   *   - As of Web Worker's async nature, handling chart instance synchronously is not recommended.
   *   - When Worker isn't available, fails or times out, data conversion falls back to main thread.
   *   - When given data is empty, useWorker will be ignored.
   * @property {string} [boost.workerUrl=undefined] Use a custom static worker script URL instead of an inline Blob worker.
   * - **NOTE:**
   *   - **Requires `boost.useWorker` to be enabled** — this option only selects where the
   *     worker source comes from, it does not turn offloading on by itself.
   *   - Useful for strict CSP environments that disallow `blob:` workers. Without it under
   *     such a policy, worker creation throws and each conversion waits out the 5s timeout
   *     before falling back, so the chart still renders but the initial draw is delayed.
   *   - Point it at `dist/billboard.worker.js`, shipped in the package, or any script
   *     implementing the same protocol: receive `{id, op, args}` and post back
   *     `{id, result}` or `{id, error}`. No `eval()` is involved.
   *   - With a bundler, make sure the file is emitted as a **real asset**, not inlined:
   *     it is ~1.5KB, and inlining turns it into a `data:` URI, which a strict CSP
   *     blocks exactly like `blob:`. Copying it into the static/public directory is the
   *     option that works everywhere.
   *   - Any failure (load error, unknown op, timeout, result mismatch) falls back to the main thread.
   * @example
   * // offload data conversion on a Worker, using the inline Blob worker
   *  boost: {
   *      useCssRule: true,
   *      useWorker: true
   *  }
   * @example
   * // offload only past ~5,000 cells
   *  boost: {
   *      useWorker: "auto"
   *  }
   * @example
   * // strict CSP: serve the shipped script and point at it.
   * // 'useWorker' still has to be on - 'workerUrl' alone offloads nothing.
   *  boost: {
   *      useWorker: true,
   *      workerUrl: "$YOUR_PATH/dist/billboard.worker.js"
   *  }
   * @example
   * // ESM: the file is reachable as a package subpath.
   * // Vite - '?url' resolves it, but assets under 4KB are inlined as a 'data:' URI,
   * // which a strict CSP rejects. Opt that one file out of inlining:
   * //
   * //   // vite.config.js
   * //   export default {
   * //     build: {
   * //       assetsInlineLimit: path => /billboard\.worker\.js$/.test(path) ? false : undefined
   * //     }
   * //   };
   * import bb, {bar} from "billboard.js";
   * import workerUrl from "billboard.js/dist/billboard.worker.js?url";
   *
   * bb.generate({
   *     boost: {useWorker: true, workerUrl},
   *     data: {columns: [["data1", 30, 200, 100]], type: bar()}
   * });
   * @example
   * // ESM, bundler-agnostic: copy the file into the served static directory
   * //   cp node_modules/billboard.js/dist/billboard.worker.js public/
   * bb.generate({
   *     boost: {useWorker: true, workerUrl: "/billboard.worker.js"},
   *     data: {columns: [["data1", 30, 200, 100]]}
   * });
   */
  boost_useCssRule: false,
  boost_useWorker: false,
  boost_workerUrl: void 0
});

;// ./src/config/Options/common/color.ts
/* harmony default export */ var color = ({
  /**
   * Set color of the data values
   * @name color
   * @memberof Options
   * @type {object}
   * @property {object} color color object
   * @property {string|object|function(DataItem): string} [color.onover] Set the color value for each data point when mouse/touch onover event occurs.
   * @property {Array|null} [color.pattern=[]] Set custom color pattern. Passing `null` will not set a color for these elements, which requires the usage of custom CSS-based theming to work.
   * @property {function(): Array.<SVGPatternElement>} [color.tiles] if defined, allows use svg's patterns to fill data area. It should return an array of [SVGPatternElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGPatternElement).
   *  - **NOTE:** The pattern element's id will be defined as `bb-colorize-pattern-$COLOR-VALUE`.<br>
   *    ex. When color pattern value is `['red', '#fff']` and defined 2 patterns,then ids for pattern elements are:<br>
   *    - `bb-colorize-pattern-red`
   *    - `bb-colorize-pattern-fff`
   * @property {object} [color.threshold] color threshold for gauge and tooltip color
   * @property {string} [color.threshold.unit] If set to `value`, the threshold will be based on the data value. Otherwise it'll be based on equation of the `threshold.max` option value.
   * @property {Array} [color.threshold.values] Threshold values for each steps
   * @property {number} [color.threshold.max=100] The base value to determine threshold step value condition. When the given value is 15 and max 10, then the value for threshold is `15*100/10`.
   * @example
   *  color: {
   *      pattern: ["#1f77b4", "#aec7e8", ...],
   *
   *      // Set colors' patterns
   *      // it should return an array of SVGPatternElement
   *      tiles: function() {
   *         var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern");
   *         var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
   *         var circle1 = document.createElementNS("http://www.w3.org/2000/svg", "circle");
   *
   *         pattern.setAttribute("patternUnits", "userSpaceOnUse");
   *         pattern.setAttribute("width", "32");
   *         pattern.setAttribute("height", "32");
   *
   *         g.style.fill = "#000";
   *         g.style.opacity = "0.2";
   *
   *         circle1.setAttribute("cx", "3");
   *         circle1.setAttribute("cy", "3");
   *         circle1.setAttribute("r", "3");
   *
   *         g.appendChild(circle1);
   *         pattern.appendChild(g);
   *
   *         return [pattern];
   *      },
   *
   *      // for threshold usage, pattern values should be set for each steps
   *      pattern: ["grey", "green", "yellow", "orange", "red"],
   *      threshold: {
   *          unit: "value",
   *
   *          // when value is 20 => 'green', value is 40 => 'orange' will be set.
   *          values: [10, 20, 30, 40, 50],
   *
   *          // the equation for max:
   *          // - unit == 'value': max => 30
   *          // - unit != 'value': max => value*100/30
   *          max: 30
   *      },
   *
   *      // set all data to 'red'
   *      onover: "red",
   *
   *      // set different color for data
   *      onover: {
   *          data1: "red",
   *          data2: "yellow"
   *      },
   *
   *      // will pass data object to the callback
   *      onover: function(d) {
   *          return d.id === "data1" ? "red" : "green";
   *      }
   *  }
   */
  color_pattern: [],
  color_tiles: void 0,
  color_threshold: {},
  color_onover: void 0
});

;// ./src/config/Options/common/legend.ts
/* harmony default export */ var legend = ({
  /**
   * Legend options
   * @name legend
   * @memberof Options
   * @type {object}
   * @property {object} legend Legend object
   * @property {boolean} [legend.show=true] Show or hide legend.
   * @property {boolean} [legend.hide=false] Hide legend
   *  If true given, all legend will be hidden. If string or array given, only the legend that has the id will be hidden.
   * @property {string|HTMLElement} [legend.contents.bindto=undefined] Set CSS selector or element reference to bind legend items.
   * - **NOTE:** Should be used along with `legend.contents.template`.
   * @property {string|function} [legend.contents.template="<span style='color:#fff;padding:5px;background-color:{=COLOR}'>{=TITLE}</span>"] Set item's template.<br>
   *  - **NOTE:** Only common HTML tags are allowed to prevent XSS attacks. If creating charts from user input, it is recommended to sanitize input values to avoid potential vulnerabilities.
   *  - If set `string` value, within template the 'color' and 'title' can be replaced using template-like syntax string:
   *    - {=COLOR}: data color value
   *    - {=TITLE}: data title value
   *  - If set `function` value, will pass following arguments to the given function:
   *   - title {string}: data's id value
   *   - color {string}: color string
   *   - data {Array}: data array
   *  - **NOTE:** While basic XSS sanitization is applied, if you're allowing user-provided chart options in a service exposed to other users, you should implement additional security measures to prevent sophisticated XSS attacks.
   * @property {string} [legend.position=bottom] Change the position of legend.<br>
   *  Available values are: `bottom`, `right` and `inset` are supported.
   * @property {object} [legend.inset={anchor: 'top-left',x: 10,y: 0,step: undefined}] Change inset legend attributes.<br>
   *  This option accepts object that has the keys `anchor`, `x`, `y` and `step`.
   *  - **anchor** decides the position of the legend:
   *   - top-left
   *   - top-right
   *   - bottom-left
   *   - bottom-right
   *  - **x** and **y**:
   *   - set the position of the legend based on the anchor.
   *  - **step**:
   *   - defines the max step the legend has (e.g. If 2 set and legend has 3 legend item, the legend 2 columns).
   * @property {boolean} [legend.equally=false] Set to all items have same width size.
   * @property {number} [legend.padding=0] Set padding value
   * @property {boolean} [legend.item.interaction=true] Set legend item interaction.
   *  - **NOTE:**
   *    - This setting will not have effect on `.toggle()` method.
   *    - `legend.item.onXXX` listener options will work if set, regardless of this option value.
   * @property {boolean} [legend.item.interaction.dblclick=false] Set legend item to interact on double click.
   *  - **NOTE:**
   *    - Double clicking will make focused clicked dataseries only, hiding all others.
   *      - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
   *    - To return initial state(which all dataseries are showing), double click current focused legend item again.
   *      - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
   *    - In this case, default `click` interaction will be disabled.
   * @property {function} [legend.item.onclick=undefined] Set click event handler to the legend item.
   *  - **NOTE:**
   *    - When set, default `click` interaction will be disabled.
   *    - When `interaction.dblclick=true` is set, will be called on double click.
   * @property {function} [legend.item.onover=undefined] Set mouse/touch over event handler to the legend item.
   *  - **NOTE:** When set, default `mouseover` interaction will be disabled.
   * @property {function} [legend.item.onout=undefined] Set mouse/touch out event handler to the legend item.
   *  - **NOTE:** When set, default `mouseout` interaction will be disabled.
   * @property {number} [legend.item.tile.width=10] Set width for 'rectangle' legend item tile element.
   * @property {number} [legend.item.tile.height=10] Set height for 'rectangle' legend item tile element.
   * @property {number} [legend.item.tile.r=5] Set the radius for 'circle' legend item tile type.
   * @property {string} [legend.item.tile.type="rectangle"] Set legend item shape type.<br>
   * - **Available Values:**
   *   - circle
   *   - rectangle
   * @property {boolean} [legend.format] Set formatter function for legend text.
   * The argument:<br>
   *  - `id`: Legend text value. When `data.names` is specified, will pass from it, otherwise will pass data id.
   *  - `dataId`: When `data.names` specified, will pass the original data id. Otherwise will be undefined.
   * @property {boolean} [legend.tooltip=false] Show full legend text value using system tooltip(via `<title>` element).
   * @property {boolean} [legend.usePoint=false] Whether to use custom points in legend.
   * @see [Demo: format](https://naver.github.io/billboard.js/demo/#Legend.LegendFormat)
   * @see [Demo: item.interaction](https://naver.github.io/billboard.js/demo/#Legend.LegendItemInteraction)
   * @see [Demo: item.tile.type](https://naver.github.io/billboard.js/demo/#Legend.LegendItemTileType)
   * @see [Demo: position](https://naver.github.io/billboard.js/demo/#Legend.LegendPosition)
   * @see [Demo: contents.template](https://naver.github.io/billboard.js/demo/#Legend.LegendTemplate1)
   * @see [Demo: usePoint](https://naver.github.io/billboard.js/demo/#Legend.usePoint)
   * @example
   *  legend: {
   *      show: true,
   *      hide: true,
   *      //or hide: "data1"
   *      //or hide: ["data1", "data2"]
   *      contents: {
   *          bindto: "#legend",   // <ul id='legend'></ul>
   *
   *          // will be as: <li style='background-color:#1f77b4'>data1</li>
   *          template: "<li style='background-color:{=COLOR}'>{=TITLE}</li>"
   *
   *          // or using function
   *          template: function(id, color, data) {
   *               // if you want omit some legend, return falsy value
   *               if (id !== "data1") {
   *                    return "<li style='background-color:"+ color +">"+ id +"</li>";
   *               }
   *          }
   *      },
   *      position: "bottom",  // bottom, right, inset
   *      inset: {
   *          anchor: "top-right"  // top-left, top-right, bottom-left, bottom-right
   *          x: 20,
   *          y: 10,
   *          step: 2
   *      },
   *      equally: false,
   *      padding: 10,
   *      item: {
   *          // will disable default interaction
   *          interaction: false,
   *
   *          // set legend interact on double click
   *          // by double clicking, will make focused clicked dataseries only, hiding all others.
   *          interaction: {
   *            dblclick: true
   *          }
   *
   *          // when set below callback, will disable corresponding default interactions
   *          onclick: function(id, visible) {
   *           	// toggle based on the data visibility
   *           	this[visible ? "hide" : "show"](id);
   *          },
   *          onover: function(id, visible) { ... },
   *          onout: function(id, visible) { ... },
   *
   *          // set tile's size
   *          tile: {
   *              // set tile type
   *              type: "circle"  // or "rectangle" (default)
   *
   *              // width & height, are only applicable for 'rectangle' legend type
   *              width: 15,
   *              height: 15
   *
   *              // radius is only applicable for 'circle' legend type
   *              r: 10
   *          }
   *      },
   *      format: function(id, dataId) {
   *          // set ellipsis string when length is > 5
   *          // to get full legend value, combine with 'legend.tooltip=true'
   *          if (id.length > 5) {
   *            	id = id.substr(0, 5) + "...";
   *          }
   *
   *          return id;
   *      },
   *      tooltip: true,
   *      usePoint: true
   *  }
   */
  legend_contents_bindto: void 0,
  legend_contents_template: "<span style='color:#fff;padding:5px;background-color:{=COLOR}'>{=TITLE}</span>",
  legend_equally: false,
  legend_hide: false,
  legend_inset_anchor: "top-left",
  legend_inset_x: 10,
  legend_inset_y: 0,
  legend_inset_step: void 0,
  legend_item_interaction: true,
  legend_item_dblclick: false,
  legend_item_onclick: void 0,
  legend_item_onover: void 0,
  legend_item_onout: void 0,
  legend_item_tile_width: 10,
  legend_item_tile_height: 10,
  legend_item_tile_r: 5,
  legend_item_tile_type: "rectangle",
  legend_format: void 0,
  legend_padding: 0,
  legend_position: "bottom",
  legend_show: true,
  legend_tooltip: false,
  legend_usePoint: false
});

;// ./src/config/Options/common/main.ts
/* harmony default export */ var main = ({
  /**
   * Specify the CSS selector or the element which the chart will be set to. D3 selection object can be specified also.<br>
   * If another chart is already set, it will be replaced with the new one (only one chart can be set in one element).
   * - **NOTE:** In case the element doesn't exist or not specified, will add a `<div>` element to the body.
   * @name bindto
   * @memberof Options
   * @property {string|HTMLElement|d3.selection|object} [bindto="#chart"] Specify the element where chart will be drawn.
   * @property {string|HTMLElement|d3.selection} bindto.element="#chart" Specify the element where chart will be drawn.
   * @property {string} [bindto.classname=bb] Specify the class name of bind element.<br>
   *     **NOTE:** When the class name isn't `bb`, then you also need to update the default CSS to be rendered correctly.
   * @default #chart
   * @example
   * bindto: "#myContainer"
   *
   * // or HTMLElement
   * bindto: document.getElementById("myContainer")
   *
   * // or D3 selection object
   * bindto: d3.select("#myContainer")
   *
   * // or to change default classname
   * bindto: {
   *    element: "#chart",
   *    classname: "bill-board"  // ex) <div id='chart' class='bill-board'>
   * }
   */
  bindto: "#chart",
  /**
   * Set chart background.
   * @name background
   * @memberof Options
   * @property {object} background background object
   * @property {string} background.class Specify the class name for background element.
   * @property {string} background.color Specify the fill color for background element.<br>**NOTE:** Will be ignored if `imgUrl` option is set.
   * @property {string} background.imgUrl Specify the image url string for background.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Background)
   * @example
   * background: {
   *    class: "myClass",
   *    color: "red",
   *
   *    // Set image url for background.
   *    // If specified, 'color' option will be ignored.
   *    imgUrl: "https://naver.github.io/billboard.js/img/logo/billboard.js.svg",
   * }
   */
  background: {},
  /**
   * Set 'clip-path' attribute for chart element
   * - **NOTE:**
   *  > When false, chart node element is positioned after the axis node in DOM tree hierarchy.
   *  > This is to make the chart element positioned over axis element.
   * @name clipPath
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.clipPath)
   * @example
   * // don't set 'clip-path' attribute
   * clipPath: false
   */
  clipPath: true,
  /**
   * Set svg element's class name
   * @name svg
   * @memberof Options
   * @type {object}
   * @property {object} [svg] svg object
   * @property {string} [svg.classname] class name for svg element
   * @example
   * svg: {
   *   classname: "test_class"
   * }
   */
  svg_classname: void 0,
  /**
   * The desired size of the chart element.
   * If the value is not specified, the width of the chart will be calculated by the size of the parent element it's appended to.
   * @name size
   * @memberof Options
   * @type {object}
   * @property {object} [size] size object
   * @property {number} [size.width] width of the chart element
   * @property {number} [size.height] height of the chart element
   * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.ChartSize)
   * @example
   * size: {
   *   width: 640,
   *   height: 480
   * }
   */
  size_width: void 0,
  size_height: void 0,
  /**
   * The padding of the chart element.
   * - **NOTE:** for more information, see the "[`Understanding padding`](https://github.com/naver/billboard.js/wiki/Understanding-padding)" wiki documentation.
   * @name padding
   * @memberof Options
   * @type {object}
   * @property {object|boolean} [padding=true] Set padding of chart, and accepts object or boolean type.
   * - `Object`: Specify each side's padding.
   * - `false`: Remove padding completely and make the shape fully occupy the container element.
   *   - In this case, axes and subchart will be hidden.
   *   - To adjust some padding from this state, use `axis.[x|y].padding` option.
   * @property {string} [padding.mode] padding mode
   * - `"fit"`: Reduce padding as much as possible to make chart fit to the container element for chart types w/axis.<br>When specified, all padding values will be relative from fitted value.
   * @property {number} [padding.top] padding on the top of chart
   * @property {number} [padding.right] padding on the right of chart
   * @property {number} [padding.bottom] padding on the bottom of chart
   * @property {number} [padding.left] padding on the left of chart
   * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Padding)
   * @see [Demo: Fit padding](https://naver.github.io/billboard.js/demo/#ChartOptions.FitPadding)
   * @example
   * // remove padding completely.
   * padding: false,
   *
   * padding: {
   *   // specifying mode value, will reduce padding and make fit to the container element.
   *   mode: "fit"
   *
   *   // when mode is "fit", all padding values will be relative from fitted value.
   *   // so, 0 will be initial fitted value.
   *   top: 20,
   *   right: 20,
   *   bottom: 20,
   *   left: 20
   * }
   *
   * // or specify padding value for each side
   * padding: {
   *   top: 20,
   *   right: 20,
   *   bottom: 20,
   *   left: 20
   * }
   */
  padding: true,
  padding_mode: void 0,
  padding_left: void 0,
  padding_right: void 0,
  padding_top: void 0,
  padding_bottom: void 0,
  /**
   * Set chart resize options
   * @name resize
   * @memberof Options
   * @type {object}
   * @property {object} [resize] resize object
   * @property {boolean|string} [resize.auto=true] Set chart resize automatically on viewport changes.
   * - **NOTE:** Available options
   *   - true: Enables automatic resize.
   *   - false: Disables automatic resize.
   *   - "parent": Enables automatic resize when the parent node is resized.
   *   - "viewBox": Enables automatic resize, and size will be fixed based on the viewbox.
   * - **NOTE:** `true` listens to the window's resize event, so a container resized by anything
   *   else(a splitter drag, a sibling element growing, a CSS resize handle) is not detected.
   *   Use `"parent"`, which observes the parent node itself, for those.
   * @property {boolean|number} [resize.timer=true] Set resize timer option.
   * - **NOTE:** Available options
   *   - The resize function will be called using:
   *     - true: `setTimeout()`
   *     - false: `requestIdleCallback()`
   *   - Given number(delay in ms) value, resize function will be triggered using `setTimeout()` with given delay.
   * - **NOTE:** With `resize.live`, this no longer decides when the size is reflected(every
   *   animation frame does), but when the resize is treated as finished:
   *   - `onresize`/`onresized` are called then, as they are without it.
   *   - When the rendering is being stretched, this is also when it's redrawn to the exact
   *     size. The stretched rendering stays on screen for this long after the resize stops,
   *     so keep the delay short for charts large enough to be stretched.
   *   - When every frame is redrawn, the last frame already drew the final size, so the
   *     delayed call changes nothing on screen.
   * @property {boolean} [resize.live=false] Follow the container size while resizing, instead of
   * only when the delayed resize(`resize.timer`) runs.
   * - **NOTE:** Applies only when `resize.auto` is `true` or `"parent"`.
   * - **Strategy:** How the size is followed is measured, not configured. Two of them are used:
   *   - **Redraw**: while a resize redraw fits in one animation frame(16ms), the chart is
   *     redrawn on every frame, giving an exact rendering at every size.
   *   - **Stretch**: once a redraw misses that budget, the rendering is stretched to the new
   *     size for the rest of the resize, and redrawn when the resize settles. Stretching runs
   *     no redraw at all: for SVG the `viewBox` is set to the drawn size and the width/height
   *     attributes to the new one, and for canvas only the element's CSS box is resized, with
   *     the backing store left as is. The size keeps following the container at any data amount.
   * - **Switching:** within a resize the strategy only goes from redraw to stretch, never back,
   *   so frames can't alternate between an exact and a stretched rendering. The measured time
   *   outlives the resize, so a chart already known to be expensive stretches from the first
   *   frame of the next one.
   * - **While stretched:** text and stroke width are scaled with the box(SVG) and the drawn
   *   bitmap is upscaled(canvas). Interaction is unaffected, as pointer coordinates are mapped
   *   back through the element's transform. The redraw on settle restores the exact rendering.
   * - **Cost:** resize redraws skip the shape data join and the axis tick measurement, so they
   *   are far cheaper than an initial render. A 5x1,000 line chart redraws in about 6ms(SVG)
   *   and 3ms(canvas), a 10x10,000 one in about 78ms and 53ms. Ordinary charts therefore redraw
   *   on every frame, and only the large ones fall back to stretching.
   * - **Several charts on a page:** the budget is measured per chart, and charts don't know
   *   about each other. Eight charts of 2,000 points each spend about 75ms per frame together
   *   while each one measures about 9ms and keeps redrawing. Turn it on for the charts the user
   *   actually watches while resizing, rather than for every chart on a dense page.
   * - `onrendered` is called on every redrawn frame while resizing, not once per resize.
   * @see [Demo: resize "parent"](https://naver.github.io/billboard.js/demo/#ChartOptions.resizeParent)
   * @see [Demo: resize "viewBox"](https://naver.github.io/billboard.js/demo/#ChartOptions.resizeViewBox)
   * @example
   *  resize: {
   *      auto: false,
   *
   *      // set resize based on parent node width value
   *      auto: "parent",
   *
   *      // set resize based on viewBox value
   *      auto: "viewBox",
   *
   *      // set resize function will be triggered using `setTimeout()`
   *      timer: true,
   *
   *      // set resize function will be triggered using `requestIdleCallback()`
   *      timer: false,
   *
   *      // set resize function will be triggered using `setTimeout()` with a delay of `100ms`.
   *      timer: 100,
   *
   *      // follow the container size while resizing
   *      live: true
   *  }
   */
  resize_auto: true,
  resize_timer: true,
  resize_live: false,
  /**
   * Set a callback to execute when the chart is clicked.
   * @name onclick
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onclick: function(event) {
   *   this; // chart instance itself
   *   event; // native event object
   *   ...
   * }
   */
  onclick: void 0,
  /**
   * Set a callback to execute when mouse/touch enters the chart.
   * @name onover
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onover: function(event) {
   *   this; // chart instance itself
   *   event; // native event object
   *   ...
   * }
   */
  onover: void 0,
  /**
   * Set a callback to execute when mouse/touch leaves the chart.
   * @name onout
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onout: function(event) {
   *   this; // chart instance itself
   *   event; // native event object
   *   ...
   * }
   */
  onout: void 0,
  /**
   * Set a callback to execute when user resizes the screen.
   * @name onresize
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onresize: function() {
   *   this; // chart instance itself
   *   ...
   * }
   */
  onresize: void 0,
  /**
   * Set a callback to execute when screen resize finished.
   * @name onresized
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onresized: function() {
   *   this; // chart instance itself
   *   ...
   * }
   */
  onresized: void 0,
  /**
   * Set a callback to execute before the chart is initialized
   * @name onbeforeinit
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onbeforeinit: function() {
   *   this; // chart instance itself
   *   ...
   * }
   */
  onbeforeinit: void 0,
  /**
   * Set a callback to execute when the chart is initialized.
   * @name oninit
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * oninit: function() {
   *   this; // chart instance itself
   *   ...
   * }
   */
  oninit: void 0,
  /**
   * Set a callback to execute after the chart is initialized
   * @name onafterinit
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onafterinit: function() {
   *   this; // chart instance itself
   *   ...
   * }
   */
  onafterinit: void 0,
  /**
   * Set a callback which is executed when the chart is rendered. Basically, this callback will be called in each time when the chart is redrawn.
   * @name onrendered
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * onrendered: function() {
   *   this; // chart instance itself
   *   ...
   * }
   */
  onrendered: void 0,
  /**
   * Set duration of transition (in milliseconds) for chart animation.<br><br>
   * - **NOTE:** If `0` or `null` is set, transition will be skipped. So, this makes initial rendering faster especially in case you have a lot of data.
   * - **NOTE:** In canvas mode, `transition.duration` is ignored. Canvas frames are redrawn synchronously. For canvas `flow()`, pass `duration` to the `flow()` call when an x-domain interpolation is required.
   * @name transition
   * @memberof Options
   * @type {object}
   * @property {object} [transition] transition object
   * @property {number} [transition.duration=250] duration in milliseconds
   * @example
   * transition: {
   *    duration: 500
   * }
   */
  transition_duration: 250,
  /**
   * Set plugins
   * @name plugins
   * @memberof Options
   * @type {Array}
   * @example
   *  plugins: [
   *    new bb.plugin.stanford({ ... }),
   *    new PluginA(),
   *    ...
   * ]
   */
  plugins: [],
  /**
   * Control the render timing
   * @name render
   * @memberof Options
   * @type {object}
   * @property {object} [render] render object
   * @property {boolean} [render.lazy=true] Make it not render at initialization.
   * - **NOTE**:
   *   - Enabled by default when bind element's visibility is hidden.
   *   - When set to `false`, will initialize the chart regardless the bind element's visibility state, but in this case chart can't be guaranteed to be rendered properly.
   * @property {boolean} [render.observe=true] Observe bind element's visibility(`display` or `visibility` inline css property or class value) & render when it is visible automatically (for IEs, only works IE11+). When set to **false**, call [`.flush()`](./Chart.html#flush) to render.
   * @property {"svg"|"canvas"} [render.mode="svg"] Select rendering backend. Available values are `"svg"` and `"canvas"`. In canvas mode, chart primitives are rendered to a single `<canvas>` instead of SVG nodes.
   * - **NOTE:** Canvas mode doesn't create per-shape, per-tick, grid, region and label SVG DOM nodes/classes. SVG CSS selectors that depend on those nodes, such as `.bb-target-data1 .bb-bar`, `.bb-bar-0` or `.bb-axis .tick text`, won't style canvas-drawn primitives. Use chart options, supported CSS theme probes or `canvas.theme` overrides.
   * - **NOTE:** Arc chart types (`pie`, `donut`, `gauge`, `polar` and `radar`) and funnel charts don't get meaningful rendering benefit from canvas mode. They are rendered as SVG only and `render.mode="canvas"` is ignored for those types.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.LazyRender)
   * @example
   *  render: {
   *    lazy: true,
   *    observe: true,
   *    mode: "svg"
   * }
   *
   * @example
   *  render: {
   *    mode: "canvas"
   * }
   *
   * @example
   * 	// <!-- render.lazy will detect visibility defined -->
   *  // (a) <div id='chart' class='hide'></div>
   *  // (b) <div id='chart' style='display:none'></div>
   *
   *  // render.lazy enabled by default when element is hidden
   *  var chart = bb.generate({ ... });
   *
   *  // chart will be rendered automatically when element's visibility changes
   *  // Note: works only for inlined css property or class attribute changes
   *  document.getElementById('chart').classList.remove('hide')  // (a)
   *  document.getElementById('chart').style.display = 'block';  // (b)
   *
   * @example
   * 	// chart won't be rendered and not observing bind element's visibility changes
   *  var chart = bb.generate({
   *     render: {
   *          lazy: true,
   *          observe: false
   *     }
   *  });
   *
   *  // call at any point when you want to render
   *  chart.flush();
   */
  render: {},
  render_mode: "svg",
  /**
   * Override canvas drawing style values read from supported SVG CSS probes.
   * Use this for canvas-specific styling that can't be represented by per-node SVG CSS selectors.
   * @name canvas
   * @memberof Options
   * @type {object}
   * @property {object} [canvas] Canvas options.
   * @property {object} [canvas.theme] Canvas theme override.
   * @property {object} [canvas.theme.selectors] Canvas theme overrides keyed by supported billboard.js SVG selectors. Use this to style canvas-rendered primitives with familiar CSS selectors and CSS property names.
   * - **NOTE:** `canvas.theme.selectors` keys are compatibility aliases for supported canvas primitives, not a full DOM/CSS selector engine. They don't match live SVG nodes 1:1 in canvas mode, and unsupported or per-data selectors such as `.bb-target-data1 .bb-bar` or `.bb-bar-0` are ignored. Use `canvas.theme` direct overrides or chart options for styles that need exact per-node behavior.
   * @see [Canvas theme selector reference](https://github.com/naver/billboard.js/blob/master/CANVAS_THEME_SELECTORS.md)
   * @example
   *  canvas: {
   *    theme: {
   *      selectors: {
   *        ".bb-axis .tick text": {
   *          fill: "#555",
   *          font: "12px sans-serif"
   *        },
   *        ".bb-grid line": {
   *          stroke: "#ddd",
   *          "stroke-width": 1,
   *          "stroke-dasharray": "2 2"
   *        },
   *        ".bb-bar": {
   *          stroke: "#fff",
   *          "stroke-width": 1
   *        }
   *      }
   *    }
   *  }
   */
  canvas_theme: {},
  /**
   * Show rectangles inside the chart.<br><br>
   * - **NOTE:**<br>
   *   - axis must be x, y or y2. start and end should be the value where regions start and end.
   *   - If not specified, the edge values will be used.
   *   - If timeseries x axis, date string, Date object and unixtime integer can be used.
   *   - If category x axis, category name can be used for start and end.
   *   - If class is set, the region element will have it as class.
   *
   * This option accept array of object with below values:
   * - `axis {string}`: 'x', 'y', or 'y2'
   * - `[start] {number|Date|string}`: Start position of the region. If not set, the start will be the edge of the chart.
   * - `[end] {number|Date|string}`: End position of the region. If not set, the end will be the edge of the chart.
   * - `[class] {string}`: Class value to apply to the region.
   * - `[label] {object}` Label text option.
   *   - `text {string}`: Text value.
   *   - `x {number}`: x Position.
   *   - `y {number}`: y Position.
   *   - `center {string}`: Align label at the center. Allowed values are 'x', 'y', 'xy'.
   *   - `color {string}`: Color string.
   *   - `rotated (boolean)`: Whether rotate label or not.
   * @name regions
   * @memberof Options
   * @type {Array}
   * @default []
   * @see [Demo: Regions](https://naver.github.io/billboard.js/demo/#Region.Region)
   * @see [Demo: Regions Timeseries](https://naver.github.io/billboard.js/demo/#Region.RegionWithTimeseries)
   * @see [Demo: Regions Label](https://naver.github.io/billboard.js/demo/#Region.RegionLabel)
   * @example
   *  regions: [
   *    {
   *      axis: "x",
   *      start: 1,
   *      end: 4,
   *      class: "region-1-4",
   *      opacity: 0.2,
   *      label: {
   *      	text: "Region Text",
   *      	x: 5,  // position relative of the initial x coordinate
   *      	y: 5,  // position relative of the initial y coordinate
   *      	center: "xy",  // center text label in both direction.
   *      	color: "red",  // color string
   *      	rotated: true  // make text to show in vertical or horizontal
   *      }
   *    }
   *  ]
   */
  regions: []
});

;// ./src/config/Options/common/title.ts
/* harmony default export */ var title = ({
  /**
   * Set title options
   * @name title
   * @memberof Options
   * @type {object}
   * @property {object} title Title object
   * @property {string} [title.text] Title text. If contains `\n`, it's used as line break allowing multiline title.
   * @property {number} [title.padding.top=0] Top padding value.
   * @property {number} [title.padding.right=0] Right padding value.
   * @property {number} [title.padding.bottom=0] Bottom padding value.
   * @property {number} [title.padding.left=0] Left padding value.
   * @property {string} [title.position=center] Available values are: 'center', 'right' and 'left'.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Title.MultilinedTitle)
   * @example
   *  title: {
   *      text: "Title Text",
   *
   *      // or Multiline title text
   *      text: "Main title text\nSub title text",
   *
   *      padding: {
   *          top: 10,
   *          right: 10,
   *          bottom: 10,
   *          left: 10
   *      },
   *      position: "center"
   *  }
   */
  title_text: void 0,
  title_padding: {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  },
  title_position: "center"
});

;// ./src/config/Options/common/tooltip.ts
/* harmony default export */ var tooltip = ({
  /**
   * Tooltip options
   * @name tooltip
   * @memberof Options
   * @type {object}
   * @property {object} tooltip Tooltip object
   * @property {boolean} [tooltip.show=true] Show or hide tooltip.
   * @property {boolean} [tooltip.doNotHide=false] Make tooltip keep showing not hiding on interaction.
   * @property {boolean} [tooltip.grouped=true] Set if tooltip is grouped or not for the data points.
   *   - **NOTE:** The overlapped data points will be displayed as grouped even if set false.
   * @property {boolean} [tooltip.linked=false] Set if tooltips on all visible charts with like x points are shown together when one is shown.
   * @property {string} [tooltip.linked.name=""] Groping name for linked tooltip.<br>If specified, linked tooltip will be groped interacting to be worked only with the same name.
   * @property {function} [tooltip.format.title] Set format for the title of tooltip.<br>
   *  Specified function receives x of the data point to show.
   * @property {function} [tooltip.format.name] Set format for the name of each data in tooltip.<br>
   *  Specified function receives name, ratio, id and index of the data point to show. ratio will be undefined if the chart is not donut/pie/gauge.
   * @property {function} [tooltip.format.value] Set format for the value of each data value in tooltip. If undefined returned, the row of that value will be skipped to be called.
   *  - Will pass following arguments to the given function:
   *    - `value {string}`: Value of the data point. If data row contains multiple or ranged(ex. candlestick, area range, etc.) value, formatter will be called as value length.
   *    - `ratio {number}`: Ratio of the data point in the `pie/donut/gauge` and `area/bar` when contains grouped data. Otherwise is `undefined`.
   *    - `id {string}`: id of the data point
   *    - `index {number}`: Index of the data point
   * @property {function} [tooltip.position] Set custom position function for the tooltip.<br>
   *  This option can be used to modify the tooltip position by returning object that has top and left.
   *  - Will pass following arguments to the given function:
   *    - `data {Array}`: Current selected data array object.
   *    - `width {number}`: Width of tooltip.
   *    - `height {number}`: Height of tooltip.
   *    - `element {SVGElement}`: Tooltip event bound element
   *    - `pos {object}`: Current position of the tooltip.
   * @property {function|object} [tooltip.contents] Set custom HTML for the tooltip.<br>
   *  If tooltip.grouped is true, data includes multiple data points.<br><br>
   *  Specified function receives `data` array and `defaultTitleFormat`, `defaultValueFormat` and `color` functions of the data point to show.
   *  - **Note:**
   *    - Only common HTML tags are allowed to prevent XSS attacks. If creating charts from user input, it is recommended to sanitize input values to avoid potential vulnerabilities.<br><br>
   *    - defaultTitleFormat:
   *      - if `axis.x.tick.format` option will be used if set.
   *      - otherwise, will return function based on tick format type(category, timeseries).
   *    - defaultValueFormat:
   * 	    - for Arc type (except gauge, radar), the function will return value from `(ratio * 100).toFixed(1)`.
   * 	    - for Axis based types, will be used `axis.[y|y2].tick.format` option value if is set.
   * 	    - otherwise, will parse value and return as number.
   * @property {string|HTMLElement} [tooltip.contents.bindto=undefined] Set CSS selector or element reference to bind tooltip.
   *  - **NOTE:** When is specified, will not be updating tooltip's position.
   * @property {string} [tooltip.contents.template=undefined] Set tooltip's template.
   *  - **NOTE:** Only common HTML tags are allowed to prevent XSS attacks. If creating charts from user input, it is recommended to sanitize input values to avoid potential vulnerabilities.<br><br>
   *  Within template, below syntax will be replaced using template-like syntax string:
   *    - **{{ ... }}**: the doubly curly brackets indicate loop block for data rows.
   *    - **{=CLASS_TOOLTIP}**: default tooltip class name `bb-tooltip`.
   *    - **{=CLASS_TOOLTIP_NAME}**: default tooltip data class name (ex. `bb-tooltip-name-data1`)
   *    - **{=TITLE}**: title value.
   *    - **{=COLOR}**: data color.
   *    - **{=NAME}**: data id value.
   *    - **{=VALUE}**: data value.
   *  - **NOTE:** While basic XSS sanitization is applied, if you're allowing user-provided chart options in a service exposed to other users, you should implement additional security measures to prevent sophisticated XSS attacks.
   * @property {object} [tooltip.contents.text=undefined] Set additional text content within data loop, using template syntax.
   *  - **NOTE:** It should contain `{ key: Array, ... }` value
   *    - 'key' name is used as substitution within template as '{=KEY}'
   *    - The value array length should match with the data length
   * @property {boolean} [tooltip.init.show=false] Show tooltip at the initialization.
   * @property {number} [tooltip.init.x=0] Set x Axis index(or index for Arc(donut, gauge, pie) types) to be shown at the initialization.
   * @property {object} [tooltip.init.position] Set the position of tooltip at the initialization.
   * @property {function} [tooltip.onshow] Set a callback that will be invoked before the tooltip is shown.
   * @property {function} [tooltip.onhide] Set a callback that will be invoked before the tooltip is hidden.
   * @property {function} [tooltip.onshown] Set a callback that will be invoked after the tooltip is shown
   * @property {function} [tooltip.onhidden] Set a callback that will be invoked after the tooltip is hidden.
   * @property {string|function|null} [tooltip.order=null] Set tooltip data display order.<br><br>
   *  **Available Values:**
   *  - `desc`: In descending data value order
   *  - `asc`: In ascending data value order
   *  - `null`: It keeps the data display order<br>
   *     **NOTE:** When `data.groups` is set, the order will follow as the stacked graph order.<br>
   *      If want to order as data bound, set any value rather than asc, desc or null. (ex. empty string "")
   *  - `function(data1, data2) { ... }`: [Array.sort compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters)
   * @see [Demo: Hide Tooltip](https://naver.github.io/billboard.js/demo/#Tooltip.HideTooltip)
   * @see [Demo: Tooltip Grouping](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipGrouping)
   * @see [Demo: Tooltip Format](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipFormat)
   * @see [Demo: Linked Tooltip](https://naver.github.io/billboard.js/demo/#Tooltip.LinkedTooltips)
   * @see [Demo: Tooltip Position](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipPosition)
   * @see [Demo: Tooltip Template](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipTemplate)
   * @example
   *  tooltip: {
   *      show: true,
   *      doNotHide: true,
   *      grouped: false,
   *      format: {
   *          title: function(x) { return "Data " + x; },
   *          name: function(name, ratio, id, index) { return name; },
   *
   *          // If data row contains multiple or ranged(ex. candlestick, area range, etc.) value,
   *          // formatter will be called as value length times.
   *          value: function(value, ratio, id, index) { return ratio; }
   *      },
   *      position: function(data, width, height, element, pos) {
   *          // data: [{x, index, id, name, value}, ...]
   *          // width: Tooltip width
   *          // height: Tooltip height
   *          // element: Tooltip event bound element
   *          // pos: {
   *          //   x: Current mouse event x position,
   *          //   y: Current mouse event y position,
   *          //   xAxis: Current x Axis position (the value is given for axis based chart type only)
   *          //   yAxis: Current y Axis position value or function(the value is given for axis based chart type only)
   *          // }
   *
   *          // yAxis will work differently per data lengths
   *          // - a) Single data: `yAxis` will return `number` value
   *          // - b) Multiple data: `yAxis` will return a function with property value
   *
   *          // a) Single data:
   *          // Get y coordinate
   *          pos.yAxis; // y axis coordinate value of current data point
   *
   *          // b) Multiple data:
   *          // Get y coordinate of value 500, where 'data1' scales(y or y2).
   *          // When 'data.axes' option is used, data can bound to different axes.
   *          // - when "data.axes={data1: 'y'}", will return y value from y axis scale.
   *          // - when "data.axes={data1: 'y2'}", will return y value from y2 axis scale.
   *          pos.yAxis(500, "data1"); // will return y coordinate value of data1
   *
   *          pos.yAxis(500); // get y coordinate with value of 500, using y axis scale
   *          pos.yAxis(500, null, "y2"); // get y coordinate with value of 500, using y2 axis scale
   *
   *          return {
   *            top: 0,
   *            left: 0
   *          }
   *      },
   *
   *      contents: function(d, defaultTitleFormat, defaultValueFormat, color) {
   *          return ... // formatted html as you want
   *      },
   *
   *       // specify tooltip contents using template
   *       // - example of HTML returned:
   *       // <ul class="bb-tooltip">
   *       //   <li class="bb-tooltip-name-data1"><span>250</span><br><span style="color:#00c73c">data1</span></li>
   *       //   <li class="bb-tooltip-name-data2"><span>50</span><br><span style="color:#fa7171">data2</span></li>
   *       // </ul>
   *       contents: {
   *      	bindto: "#tooltip",
   *      	template: '<ul class={=CLASS_TOOLTIP}>{{' +
   *      			'<li class="{=CLASS_TOOLTIP_NAME}"><span>{=VALUE}</span><br>' +
   *      			'<span style=color:{=COLOR}>{=NAME}</span></li>' +
   *      		'}}</ul>'
   *      }
   *
   *       // with additional text value
   *       // - example of HTML returned:
   *       // <ul class="bb-tooltip">
   *       //   <li class="bb-tooltip-name-data1"><span>250</span><br>comment1<span style="color:#00c73c">data1</span>text1</li>
   *       //   <li class="bb-tooltip-name-data2"><span>50</span><br>comment2<span style="color:#fa7171">data2</span>text2</li>
   *       // </ul>
   *       contents: {
   *      	bindto: "#tooltip",
   *      	text: {
   *      		// a) 'key' name is used as substitution within template as '{=KEY}'
   *      		// b) the length should match with the data length
   *      		VAR1: ["text1", "text2"],
   *      		VAR2: ["comment1", "comment2"],
   *      	},
   *      	template: '<ul class={=CLASS_TOOLTIP}>{{' +
   *      			'<li class="{=CLASS_TOOLTIP_NAME}"><span>{=VALUE}</span>{=VAR2}<br>' +
   *      			'<span style=color:{=COLOR}>{=NAME}</span>{=VAR1}</li>' +
   *      		'}}</ul>'
   *      }
   *
   *      // sort tooltip data value display in ascending order
   *      order: "asc",
   *
   *      // specifying sort function
   *      order: function(a, b) {
   *         // param data passed format
   *         {x: 5, value: 250, id: "data1", index: 5, name: "data1"}
   *           ...
   *      },
   *
   *      // show at the initialization
   *      init: {
   *          show: true,
   *          x: 2, // x Axis index (or index for Arc(donut, gauge, pie) types)
   *          position: {
   *              top: "150px",  // specify as number or as string with 'px' unit string
   *              left: 250  // specify as number or as string with 'px' unit string
   *          }
   *      },
   *
   *      // fires prior tooltip is shown
   *      onshow: function(selectedData) {
   *      	// current dataset selected
   *      	// ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
   *      	selectedData;
   *      },
   *
   *      // fires prior tooltip is hidden
   *      onhide: function(selectedData) {
   *      	// current dataset selected
   *      	// ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
   *      	selectedData;
   *      },
   *
   *      // fires after tooltip is shown
   *      onshown: function(selectedData) {
   *      	// current dataset selected
   *      	// ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
   *      	selectedData;
   *      },
   *
   *      // fires after tooltip is hidden
   *      onhidden: function(selectedData) {
   *      	// current dataset selected
   *      	// ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
   *      	selectedData;
   *      },
   *
   *      // Link any tooltips when multiple charts are on the screen where same x coordinates are available
   *      // Useful for timeseries correlation
   *      linked: true,
   *
   *      // Specify name to interact those with the same name only.
   *      linked: {
   *          name: "some-group"
   *      }
   *  }
   */
  tooltip_show: true,
  tooltip_doNotHide: false,
  tooltip_grouped: true,
  tooltip_format_title: void 0,
  tooltip_format_name: void 0,
  tooltip_format_value: void 0,
  tooltip_position: void 0,
  tooltip_contents: {},
  tooltip_init_show: false,
  tooltip_init_x: 0,
  tooltip_init_position: void 0,
  tooltip_linked: false,
  tooltip_linked_name: "",
  tooltip_onshow: () => {
  },
  tooltip_onhide: () => {
  },
  tooltip_onshown: () => {
  },
  tooltip_onhidden: () => {
  },
  tooltip_order: null
});

;// ./src/config/Options/data/data.ts
/* harmony default export */ var data = ({
  /**
   * Specify the key of x values in the data.<br><br>
   * We can show the data with non-index x values by this option. This option is required when the type of x axis is timeseries. If this option is set on a category axis, the values of the data on the key will be used for category names.
   * @name data․x
   * @memberof Options
   * @type {string}
   * @default undefined
   * @example
   * data: {
   *   x: "date"
   * }
   */
  data_x: void 0,
  /**
   * Converts data id value
   * @name data․idConverter
   * @memberof Options
   * @type {function}
   * @default function(id) { return id; }
   * @example
   * data: {
   *    idConverter: function(id) {
   *       // when id is 'data1', converts to be 'data2'
   *       // 'data2' should be given as the initial data value
   *       if (id === "data1") {
   *          return "data2";
   *       } else {
   *          return id;
   *       }
   *    }
   * }
   */
  data_idConverter: (id) => id,
  /**
   * Set custom data name.
   * If a name is set to `null`, the series is omitted from the legend.
   * @name data․names
   * @memberof Options
   * @type {object}
   * @default {}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataName)
   * @example
   * data: {
   *   names: {
   *     data1: "Data Name 1",
   *     data2: "Data Name 2"
   *   }
   * }
   */
  data_names: {},
  /**
   * Set custom data class.<br><br>
   * If this option is specified, the element g for the data has an additional class that has the prefix 'bb-target-' (eg. bb-target-additional-data1-class).
   * @name data․classes
   * @memberof Options
   * @type {object}
   * @default {}
   * @example
   * data: {
   *   classes: {
   *     data1: "additional-data1-class",
   *     data2: "additional-data2-class"
   *   }
   * }
   */
  data_classes: {},
  /**
   * Set chart type at once.<br><br>
   * If this option is specified, the type will be applied to every data. This setting can be overwritten by data.types.<br><br>
   * **Available Values:**
   * - area
   * - area-line-range
   * - area-spline
   * - area-spline-range
   * - area-step
   * - area-step-range
   * - bar
   * - bubble
   * - candlestick
   * - donut
   * - funnel
   * - gauge
   * - line
   * - pie
   * - polar
   * - radar
   * - scatter
   * - spline
   * - step
   * - treemap
   * @name data․type
   * @memberof Options
   * @type {string}
   * @default "line"<br>NOTE: When importing shapes by ESM, `line()` should be specified for type.
   * @example
   * data: {
   *    type: "bar"
   * }
   * @example
   * // Generate chart by importing ESM
   * // Import types to be used only, where this will make smaller bundle size.
   * import bb, {
   *   area,
   *   areaLineRange,
   *   areaSpline,
   *   areaSplineRange,
   *   areaStep,
   *   areaStepRange,
   *   bar,
   *   bubble,
   *   candlestick,
   *   donut,
   *   funnel,
   *   gauge,
   *   line,
   *   pie,
   *   polar,
   *   radar,
   *   scatter,
   *   spline,
   *   step,
   *   treemap
   * }
   *
   * bb.generate({
   *   ...,
   *   data: {
   *     type: bar()
   *   }
   * });
   */
  data_type: void 0,
  /**
   * Set chart type for each data.<br>
   * This setting overwrites data.type setting.
   * - **NOTE:** `radar` and `treemap` type can't be combined with other types.
   * @name data․types
   * @memberof Options
   * @type {object}
   * @default {}
   * @example
   * data: {
   *   types: {
   *     data1: "bar",
   *     data2: "spline"
   *   }
   * }
   * @example
   * // Generate chart by importing ESM
   * // Import types to be used only, where this will make smaller bundle size.
   * import bb, {
   *   area,
   *   areaLineRange,
   *   areaSpline,
   *   areaSplineRange,
   *   areaStep,
   *   areaStepRange,
   *   bar,
   *   bubble,
   *   candlestick,
   *   donut,
   *   funnel,
   *   gauge,
   *   line,
   *   pie,
   *   polar,
   *   radar,
   *   scatter,
   *   spline,
   *   step,
   *   treemap
   * }
   *
   * bb.generate({
   *   ...,
   *   data: {
   *     types: {
   *       data1: bar(),
   *       data1: spline()
   *     }
   *   }
   * });
   */
  data_types: {},
  /**
   *  This option changes the order of stacking data and pieces of pie/donut.
   *  - If `null` specified, it will be the order in which the data is loaded.
   *  - If a function is specified, it will be used as [Array.sort compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters)<br><br>
   *
   *  **Available Values:**
   *  - `desc`: In descending order
   *  - `asc`: In ascending order
   *  - `null`: It keeps the data load order
   *  - `function(data1, data2) { ... }`: Array.sort compareFunction
   *
   *  **NOTE**: order function only works for Axis based types & Arc types, except `Radar` type.
   * @name data․order
   * @memberof Options
   * @type {string|function|null}
   * @default desc
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataOrder)
   * @example
   * data: {
   *   // in descending order (default)
   *   order: "desc"
   *
   *   // in ascending order
   *   order: "asc"
   *
   *   // keeps data input order
   *   order: null
   *
   *   // specifying sort function
   *   order: function(a, b) {
   *       // param data passed format
   *       // {
   *       //   id: "data1", id_org: "data1", values: [
   *       //      {x: 5, value: 250, id: "data1", index: 5, name: "data1"},
   *       //       ...
   *       //   ]
   *       // }
   *
   *       const reducer = (p, c) => p + Math.abs(c.value);
   *       const aSum = a.values.reduce(reducer, 0);
   *       const bSum = b.values.reduce(reducer, 0);
   *
   *       // ascending order
   *       return aSum - bSum;
   *
   *       // descending order
   *       // return bSum - aSum;
   *   }
   * }
   */
  data_order: "desc",
  /**
   * Set groups for the data for stacking.
   * @name data․groups
   * @memberof Options
   * @type {Array}
   * @default []
   * @example
   * data: {
   *   groups: [
   *     ["data1", "data2"],
   *     ["data3"]
   *   ]
   * }
   */
  data_groups: [],
  /**
   * Set how zero value will be treated on groups.<br>
   * Possible values:
   * - `zero`: 0 will be positioned at the absolute axis zero point.
   * - `positive`: 0 will be positioned at the top of a stack.
   * - `negative`: 0 will be positioned at the bottom of a stack.
   * @name data․groupsZeroAs
   * @memberof Options
   * @type {string}
   * @default "positive"
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.Groups)
   * @example
   * data: {
   *   groupsZeroAs: "zero" // "positive" or "negative"
   * }
   */
  data_groupsZeroAs: "positive",
  /**
   * Set color converter function.<br><br>
   * This option should be a function and the specified function receives color (e.g. '#ff0000') and d that has data parameters like id, value, index, etc. And it must return a string that represents color (e.g. '#00ff00').
   * @name data․color
   * @memberof Options
   * @type {function}
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataColor)
   * @example
   * data: {
   *   color: function(color, d) { ... }
   * }
   */
  data_color: void 0,
  /**
   * Set color for each data.
   * @name data․colors
   * @memberof Options
   * @type {object}
   * @default {}
   * @example
   * data: {
   *   colors: {
   *     data1: "#ff0000",
   *     data2: function(d) {
   *        return "#000";
   *     }
   *     ...
   *   }
   * }
   */
  data_colors: {},
  /**
   * Set labels options
   * @name data․labels
   * @memberof Options
   * @type {object}
   * @property {object} data Data object
   * @property {boolean} [data.labels=false] Show or hide labels on each data point
   * @property {boolean} [data.labels.centered=false] Centerize labels on `bar` shape. (**NOTE:** works only for 'bar' type)
   * @property {function} [data.labels.format] Set formatter function for data labels.<br>
   * The formatter function receives 4 arguments such as `v, id, i, texts` and it **must return a string** (`\n` character will be used as line break) that will be shown as the label.<br><br>
   * The arguments are:<br>
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   *  - `texts` is an array of whole corresponding data series' text labels.<br><br>
   * Formatter function can be defined for each data by specifying as an object and D3 formatter function can be set (ex. d3.format('$'))
   * @property {string|object|function} [data.labels.backgroundColors] Set label text background colors.<br><br>
   * - **NOTE**: When a function is set, background colors can be specified one color per dataset.
   *   - Within the function, the last returned color for dataset will be used.
   *   - Only can control set or unset background color for each values.
   * @property {string|object|function} [data.labels.colors] Set label text colors.
   * @property {object|function} [data.labels.position] Set each dataset position, relative to the original.<br><br>
   * When a function is specified, it will receive 5 arguments such as `type, v, id, i, texts` and it must return a position number.<br><br>
   * The arguments are:<br>
   *  - `type` coordinate type string, which will be 'x' or 'y'.
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   *  - `texts` is an array of whole corresponding data series' text labels.<br><br>
   * @property {number} [data.labels.position.x=0] x coordinate position, relative to the original.
   * @property {number} [data.labels.position.y=0] y coordinate position, relative to the original.
   * @property {object} [data.labels.rotate] Rotate label text. Specify degree value in a range of `0 ~ 360`.
   * - **NOTE:** Depending on the rotate value, the text position needs to be adjusted manually(using `data.labels.position` option) to be shown nicely.
   * @property {boolean|object} [data.labels.border=false] Add border to data label text. NOTE: When set as `true`, styling isn't applied. Hence, you need to set it using `.bb-text-border` class.
   * @property {number|string|object} [data.labels.border.padding="3 5"] Border padding. Can be a single number, string or object with top, bottom, left, right properties.
   * @property {number} [data.labels.border.radius=10] Border radius value.
   * @property {number} [data.labels.border.strokeWidth=1] Border stroke width.
   * @property {string} [data.labels.border.stroke="#000"] Border stroke color.
   * @property {string} [data.labels.border.fill="none"] Border fill color.
   * @property {object|function} [data.labels.image] Set image to be displayed next to the label text.<br><br>
   * When a function is specified, it will receive 3 arguments such as `v, id, i` and it must return an image object with `url`, `width`, `height`, and optional `pos` properties.<br><br>
   * The arguments are:<br>
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   * @property {string} data.labels.image.url Image URL path. Can use placeholder `{=ID}` which will be replaced with the data ID.
   * @property {number} data.labels.image.width Image width in pixels.
   * @property {number} data.labels.image.height Image height in pixels.
   * @property {object} [data.labels.image.pos] Image position relative to the label text.
   * @property {number} [data.labels.image.pos.x=0] x coordinate position, relative to the original.
   * @property {number} [data.labels.image.pos.y=0] y coordinate position, relative to the original.
   * @memberof Options
   * @type {object}
   * @default {}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataLabel)
   * @see [Demo: label border](https://naver.github.io/billboard.js/demo/#Data.DataLabelBorder)
   * @see [Demo: label colors](https://naver.github.io/billboard.js/demo/#Data.DataLabelColors)
   * @see [Demo: label format](https://naver.github.io/billboard.js/demo/#Data.DataLabelFormat)
   * @see [Demo: label image](https://naver.github.io/billboard.js/demo/#Data.DataLabelImage)
   * @see [Demo: label multiline](https://naver.github.io/billboard.js/demo/#Data.DataLabelMultiline)
   * @see [Demo: label overlap](https://naver.github.io/billboard.js/demo/#Data.DataLabelOverlap)
   * @see [Demo: label position](https://naver.github.io/billboard.js/demo/#Data.DataLabelPosition)
   * @see [Demo: label rotate](https://naver.github.io/billboard.js/demo/#Data.DataLabelRotate)
   * @example
   * data: {
   *   labels: true,
   *
   *   // or set specific options
   *   labels: {
   *     format: function(v, id, i, texts) {
   *         ...
   *         // to multiline, return with '\n' character
   *         return "Line1\nLine2";
   *     },
   *
   *     // it's possible to set for each data
   *     format: {
   *         data1: function(v, id, i, texts) { ... },
   *         ...
   *     },
   *
   *     // align text to center of the 'bar' shape (works only for 'bar' type)
   *     centered: true,
   *
   *     // apply background color for label texts
   *     backgroundColors: "red",
   *
   *     // set different background colors per dataset
   *     backgroundColors: {
   *          data1: "green",
   *          data2: "yellow"
   *     },
   *
   *     // call back for label text background color
   *     backgroundColors: function(color, d) {
   *         // color: the default data label color string
   *         // data: ex) {x: 0, value: 200, id: "data3", index: 0}
   *         ....
   *         return d.value > 200 ? "cyan" : "red";
   *     },
   *
   *     // apply for all label texts
   *     colors: "red",
   *
   *     // set different colors per dataset
   *     // for not specified dataset, will have the default color value
   *     colors: {
   *        data1: "yellow",
   *        data3: "green"
   *     },
   *
   *     // call back for label text color
   *     colors: function(color, d) {
   *         // color: the default data label color string
   *         // data: ex) {x: 0, value: 200, id: "data3", index: 0}
   *         ....
   *         return d.value > 200 ? "cyan" : color;
   *     },
   *
   *     // return x, y coordinate position
   *     // apt to handle each text position manually
   *     position: function(type, v, id, i, texts) {
   *         ...
   *         return type == "x" ? 10 : 20;
   *     },
   *
   *     // set x, y coordinate position
   *     position: {
   *        x: -10,
   *        y: 10
   *     },
   *
   *     // or set x, y coordinate position by each dataset
   *     position: {
   *        data1: {x: 5, y: 5},
   *        data2: {x: 10, y: -20}
   *     },
   *
   * 	   // rotate degree for label text
   *     rotate: 90,
   *
   *     // add border to data label text
   *     // NOTE: When set as `true`, styling aren't applied. Hence, need to set using '.bb-text-border' class.
   *     // ex. ".bb-text-border { fill: red; stroke: #000; stroke-width: 2px; rx: 10px; ry: 10px; }"
   *     border: true,
   *
   *     // or set detailed border options
   *     border: {
   *        padding: 10,  // set all padding to 10
   *        padding: "5 10",  // set top and bottom padding to 5, left and right padding to 10
   *        padding: {  // specify each padding
   *           top: 3,
   *           bottom: 5,
   *           left: 10,
   *           right: 13
   *        },
   *        radius: 10,
   *        strokeWidth: 2,
   *        stroke: "#000",
   *        fill: "red"
   *     },
   *
   *     // set image to be displayed next to the label text
   *     image: {
   *        url: "./sample.svg",
   *
   *        // use placeholder to dynamically set image URL based on data ID
   *        url: "./images/{=ID}.svg",  // will be replaced to "./images/data1.svg", "./images/data2.svg", etc.
   *        width: 35,
   *        height: 35,
   *        pos: {
   *           x: 0,
   *           y: 0
   *        }
   *     },
   *
   *     // or use function to return image configuration dynamically
   *     image: function(v, id, i) {
   *        // v is the value of the data point where the label is shown.
   *        // id is the id of the data where the label is shown.
   *        // i is the index of the data series point where the label is shown.
   *
   *        // Return different images based on value
   *        if (v > 500) {
   *           return {
   *              url: "./high-value.svg",
   *              width: 40,
   *              height: 40,
   *              pos: { x: 0, y: 0 }
   *           };
   *        } else if (v > 100) {
   *           return {
   *              url: "./medium-value.svg",
   *              width: 30,
   *              height: 30,
   *              pos: { x: 0, y: 0 }
   *           };
   *        } else if(v < 5) {
   *        	// Return falsy value in case you don't want to show image
   *           return null;
   *        } else {
   *           return {
   *              url: "./low-value.svg",
   *              width: 20,
   *              height: 20,
   *              pos: { x: 0, y: 0 }
   *           };
   *        }
   *     }
   *   }
   * }
   */
  data_labels: {},
  data_labels_backgroundColors: void 0,
  data_labels_colors: void 0,
  data_labels_position: {},
  data_labels_imgUrl: void 0,
  /**
   * Hide each data when the chart appears.<br><br>
   * If true is specified, all of data will be hidden. If multiple ids are specified as an array, those will be hidden.
   * @name data․hide
   * @memberof Options
   * @type {boolean|Array}
   * @default false
   * @example
   * data: {
   *   // all of data will be hidden
   *   hide: true
   *
   *   // specified data will be hidden
   *   hide: ["data1", ...]
   * }
   */
  data_hide: false,
  /**
   * Filter values to be shown
   * The data value is the same as the returned by `.data()`.
   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
   * @name data․filter
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * data: {
   *   // filter for id value
   *   filter: function(v) {
   *      // v: [{id: "data1", id_org: "data1", values: [
   *      //      {x: 0, value: 130, id: "data2", index: 0}, ...]
   *      //    }, ...]
   *      return v.id !== "data1";
   *   }
   */
  data_filter: void 0,
  /**
   * Set a callback for click event on each data point.<br><br>
   * This callback will be called when each data point is clicked and will receive `d` and element as the arguments.
   * - `d` is the data clicked and element is the element clicked.
   * - `element` is the current interacting svg element.
   * - In this callback, `this` will be the Chart object.
   * @name data․onclick
   * @memberof Options
   * @type {function}
   * @default function() {}
   * @example
   * data: {
   *     onclick: function(d, element) {
   *        // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
   *        // element - <circle>
   *        ...
   *     }
   * }
   */
  data_onclick: () => {
  },
  /**
   * Set a callback for mouse/touch over event on each data point.<br><br>
   * This callback will be called when the mouse cursor or touch moves onto each data point and will receive `d` and `element` as the argument.
   * - `d` is the data where mouse cursor moves onto.
   * - `element` is the current interacting svg element.
   * - In this callback, `this` will be the Chart object.
   * @name data․onover
   * @memberof Options
   * @type {function}
   * @default function() {}
   * @example
   * data: {
   *     onover: function(d, element) {
   *        // d - ex) {x: 4, value: 150, id: "data1", index: 4}
   *        // element - <circle>
   *        ...
   *     }
   * }
   */
  data_onover: () => {
  },
  /**
   * Set a callback for mouse/touch out event on each data point.<br><br>
   * This callback will be called when the mouse cursor or touch moves out each data point and will receive `d` as the argument.
   * - `d` is the data where mouse cursor moves out.
   * - `element` is the current interacting svg element.
   * - In this callback, `this` will be the Chart object.
   * @name data․onout
   * @memberof Options
   * @type {function}
   * @default function() {}
   * @example
   * data: {
   *     onout: function(d, element) {
   *        // d - ex) {x: 4, value: 150, id: "data1", index: 4}
   *        // element - <circle>
   *        ...
   *     }
   * }
   */
  data_onout: () => {
  },
  /**
   * Set a callback for when data is shown.<br>
   * The callback will receive shown data ids in array.
   * @name data․onshown
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   *  data: {
   *    onshown: function(ids) {
   *      // ids - ["data1", "data2", ...]
   *      ...
   *    }
   *  }
   */
  data_onshown: void 0,
  /**
   * Set a callback for when data is hidden.<br>
   * The callback will receive hidden data ids in array.
   * @name data․onhidden
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   *  data: {
   *    onhidden: function(ids) {
   *      // ids - ["data1", "data2", ...]
   *      ...
   *    }
   *  }
   */
  data_onhidden: void 0,
  /**
   * Set a callback for minimum data
   * - **NOTE:** For 'area-line-range', 'area-step-range' and 'area-spline-range', `mid` data will be taken for the comparison
   * @name data․onmin
   * @memberof Options
   * @type {function}
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.OnMinMaxCallback)
   * @example
   *  onmin: function(data) {
   *    // data - ex) [{x: 3, value: 400, id: "data1", index: 3}, ... ]
   *    ...
   *  }
   */
  data_onmin: void 0,
  /**
   * Set a callback for maximum data
   * - **NOTE:** For 'area-line-range', 'area-step-range' and 'area-spline-range', `mid` data will be taken for the comparison
   * @name data․onmax
   * @memberof Options
   * @type {function}
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.OnMinMaxCallback)
   * @example
   *  onmax: function(data) {
   *    // data - ex) [{x: 3, value: 400, id: "data1", index: 3}, ... ]
   *    ...
   *  }
   */
  data_onmax: void 0,
  /**
   * Load a CSV or JSON file from a URL. NOTE that this will not work if loading via the "file://" protocol as most browsers will block XMLHTTPRequests.
   * @name data․url
   * @memberof Options
   * @type {string}
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.LoadData)
   * @example
   * data: {
   *     url: "/data/test.csv"
   * }
   */
  data_url: void 0,
  /**
   * XHR header value
   * - **NOTE:** Should be used with `data.url` option
   * @name data․headers
   * @memberof Options
   * @type {string}
   * @default undefined
   * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader
   * @example
   * data: {
   *     url: "/data/test.csv",
   *     headers: {
   *        "Content-Type": "text/xml",
   *        ...
   *     }
   * }
   */
  data_headers: void 0,
  /**
   * Parse a JSON object for data. See also data.keys.
   * @name data․json
   * @memberof Options
   * @type {Array}
   * @default undefined
   * @see [data․keys](#.data%25E2%2580%25A4keys)
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.JSONData)
   * @example
   * data: {
   *     json: [
   *       {name: "www.site1.com", upload: 200, download: 200, total: 400},
   *       {name: "www.site2.com", upload: 100, download: 300, total: 400},
   *       {name: "www.site3.com", upload: 300, download: 200, total: 500},
   *       {name: "www.site4.com", upload: 400, download: 100, total: 500}
   *     ],
   *     keys: {
   *       // case 1: specify 'x' key for category axis
   *       x: "name", // 'name' key will be used as category x axis values
   *       value: ["upload", "download"]
   *
   *       // case 2: without 'x' key for non-category axis
   *       value: ["upload", "download"]
   *     }
   * }
   */
  data_json: void 0,
  /**
   * Load data from a multidimensional array, with the first element containing the data names, the following containing related data in that order.
   * @name data․rows
   * @memberof Options
   * @type {Array}
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.RowOrientedData)
   * @example
   * data: {
   *   rows: [
   *     ["A", "B", "C"],
   *     [90, 120, 300],
   *     [40, 160, 240],
   *     [50, 200, 290],
   *     [120, 160, 230],
   *     [80, 130, 300],
   *     [90, 220, 320]
   *   ]
   * }
   *
   * // for 'bar' type, data can contain:
   * // - an array of [start, end] data following the order
   * data: {
   *   rows: [
   *      ["data1", "data2"],
   *      [[100, 150], 120],
   *      [[200, 300], 55],
   *      [[-400, 500], 60]
   *   ],
   *   type: "bar"
   * }
   *
   * // for 'range' types('area-line-range' or 'area-step-range' or 'area-spline-range'), data should contain:
   * // - an array of [high, mid, low] data following the order
   * // - or an object with 'high', 'mid' and 'low' key value
   * data: {
   *   rows: [
   *      ["data1", "data2"],
   *      [
   *        // or {high:150, mid: 140, low: 110}, 120
   *        [150, 140, 110], 120
   *      ],
   *      [[155, 130, 115], 55],
   *      [[160, 135, 120], 60]
   *   ],
   *   types: {
   *       data1: "area-line-range",
   *       data2: "line"
   *   }
   * }
   *
   * // for 'bubble' type, data can contain dimension value:
   * // - an array of [y, z] data following the order
   * // - or an object with 'y' and 'z' key value
   * // 'y' is for y axis coordination and 'z' is the bubble radius value
   * data: {
   *   rows: [
   *      ["data1", "data2"],
   *      [
   *        // or {y:10, z: 140}, 120
   *        [10, 140], 120
   *      ],
   *      [[100, 30], 55],
   *      [[50, 100], 60]
   *   ],
   *   types: {
   *       data1: "bubble",
   *       data2: "line"
   *   }
   * }
   *
   * // for 'candlestick' type, data should contain:
   * // - an array of [open, high, low, close, volume(optional)] data following the order
   * // - or an object with 'open', 'high', 'low', 'close' and 'value'(optional) key value
   * data: {
   *   rows: [
   *      ["data1", "data2"],
   * 		[
   * 			// open, high, low, close, volume (optional)
   * 			{open: 1300, high: 1369, low: 1200, close: 1339, volume: 100},
   * 			[1000, 1100, 850, 870]
   * 		],
   * 		[
   * 			{open: 1348, high: 1371, low: 1271, close: 1320},
   * 			[870, 1250, 830, 1200, 50]
   * 		]
   *   ],
   *   type: "candlestick"
   * }
   */
  data_rows: void 0,
  /**
   * Load data from a multidimensional array, with each element containing an array consisting of a datum name and associated data values.
   * @name data․columns
   * @memberof Options
   * @type {Array}
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.ColumnOrientedData)
   * @example
   * data: {
   *   columns: [
   *      ["data1", 30, 20, 50, 40, 60, 50],
   *      ["data2", 200, 130, 90, 240, 130, 220],
   *      ["data3", 300, 200, 160, 400, 250, 250]
   *   ]
   * }
   *
   * // for 'bar' type, data can contain:
   * // - an array of [start, end] data following the order
   * data: {
   *   columns: [
   *     ["data1", -100, 50, [100, 200], [200, 300]],
   *     ["data2", -200, 300, [-100, 100], [-50, -30]],
   *   ],
   *   type: "bar"
   * }
   *
   * // for 'range' types('area-line-range' or 'area-step-range' or 'area-spline-range'), data should contain:
   * // - an array of [high, mid, low] data following the order
   * // - or an object with 'high', 'mid' and 'low' key value
   * data: {
   *   columns: [
   *      ["data1",
   *          [150, 140, 110],  // or {high:150, mid: 140, low: 110}
   *          [150, 140, 110],
   *          [150, 140, 110]
   *      ]
   *   ],
   *   type: "area-line-range"
   * }
   *
   * // for 'bubble' type, data can contain dimension value:
   * // - an array of [y, z] data following the order
   * // - or an object with 'y' and 'z' key value
   * // 'y' is for y axis coordination and 'z' is the bubble radius value
   * data: {
   *   columns: [
   *      ["data1",
   *          [10, 140],  // or {y:10, z: 140}
   *          [100, 30],
   *          [50, 100]
   *      ]
   *   ],
   *   type: "bubble"
   * }
   *
   * // for 'candlestick' type, data should contain:
   * // - an array of [open, high, low, close, volume(optional)] data following the order
   * // - or an object with 'open', 'high', 'low', 'close' and 'value'(optional) key value
   * data: {
   *   columns: [
   *      ["data1",
   *          [1000, 1100, 850, 870, 100],  // or {open:1000, high: 1100, low: 870, volume: 100}
   *          [870, 1250, 830, 1200]  // 'volume' can be omitted
   *      ]
   *   ],
   *   type: "candlestick"
   * }
   */
  data_columns: void 0,
  /**
   * Used if loading JSON via data.url.
   * - **Available Values:**
   *   - json
   *   - csv
   *   - tsv
   * @name data․mimeType
   * @memberof Options
   * @type {string}
   * @default csv
   * @example
   * data: {
   *     mimeType: "json"
   * }
   */
  data_mimeType: "csv",
  /**
   * Choose which JSON object keys correspond to desired data.
   * - **NOTE:** Only for JSON object given as array.
   * @name data․keys
   * @memberof Options
   * @type {string}
   * @default undefined
   * @example
   * data: {
   *     json: [
   *       {name: "www.site1.com", upload: 200, download: 200, total: 400},
   *       {name: "www.site2.com", upload: 100, download: 300, total: 400},
   *       {name: "www.site3.com", upload: 300, download: 200, total: 500},
   *       {name: "www.site4.com", upload: 400, download: 100, total: 500}
   *     ],
   *     keys: {
   *       // case 1: specify 'x' key for category axis
   *       x: "name", // 'name' key will be used as category x axis values
   *       value: ["upload", "download"]
   *
   *       // case 2: without 'x' key for non-category axis
   *       value: ["upload", "download"]
   *     }
   * }
   */
  data_keys: void 0,
  /**
   * Set text label to be displayed when there's no data to show.
   * - ex. Toggling all visible data to not be shown, unloading all current data, etc.
   * @name data․empty․label․text
   * @memberof Options
   * @type {string}
   * @default ""
   * @example
   * data: {
   *   empty: {
   *     label: {
   *       text: "No Data"
   *     }
   *   }
   * }
   */
  data_empty_label_text: ""
});

;// ./src/config/Options/interaction/interaction.ts
/* harmony default export */ var interaction = ({
  /**
   * Interaction options
   * @name interaction
   * @memberof Options
   * @type {object}
   * @property {object} interaction Intersection object
   * @property {boolean} [interaction.enabled=true] Indicate if the chart should have interactions.<br>
   *     If `false` is set, all of interactions (showing/hiding tooltip, selection, mouse events, etc) will be disabled.
   * @property {boolean} [interaction.brighten=true] Make brighter for the selected area (ex. 'pie' type data selected area)
   * @property {boolean} [interaction.inputType.mouse=true] enable or disable mouse interaction
   * @property {boolean} [interaction.inputType.touch=true] enable or disable  touch interaction
   * @property {boolean|number} [interaction.inputType.touch.preventDefault=false] enable or disable to call event.preventDefault on touchstart & touchmove event. It's usually used to prevent document scrolling.<br>
   * - **NOTE**: When `true` is set, touch events are bound with [`{passive: false}`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners) option.
   * @property {boolean} [interaction.onout=true] Enable or disable "onout" event.<br>
   * 		When is disabled, defocus(hiding tooltip, focused gridline, etc.) event won't work.
   * @see [Demo: touch.preventDefault](https://naver.github.io/billboard.js/demo/#Interaction.PreventScrollOnTouch)
   * @example
   * interaction: {
   *    enabled: false,
   *    brighten: false,
   *    inputType: {
   *        mouse: true,
   *        touch: false
   *
   *        // or declare preventDefault explicitly.
   *        // In this case touch inputType is enabled by default
   *        touch: {
   *            preventDefault: true
   *
   *            // or threshold pixel value (pixel moved from touchstart to touchmove)
   *            preventDefault: 5
   *        }
   *    },
   *
   *    // disable "onout" event
   *    onout: false
   * }
   */
  interaction_enabled: true,
  interaction_brighten: true,
  interaction_inputType_mouse: true,
  interaction_inputType_touch: {},
  interaction_onout: true
});

;// ./src/config/Options/Options.ts
var Options_defProp = Object.defineProperty;
var Options_defNormalProp = (obj, key, value) => key in obj ? Options_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var Options_publicField = (obj, key, value) => Options_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);









const _Options = class _Options {
  static setOptions(options) {
    for (let i = 0; i < options.length; i++) {
      Object.assign(this.data, options[i]);
    }
  }
  constructor() {
    return deepClone(
      main,
      boost,
      data,
      color,
      interaction,
      legend,
      title,
      tooltip,
      _Options.data
    );
  }
};
Options_publicField(_Options, "data", {});
let Options = _Options;


;// ./src/config/Store/Element.ts
class Element {
  constructor() {
    const element = {
      chart: null,
      main: null,
      svg: null,
      axis: {
        // axes
        x: null,
        y: null,
        y2: null,
        subX: null,
        subY: null,
        subY2: null
      },
      axisTooltip: {
        x: null,
        y: null,
        y2: null
      },
      defs: null,
      tooltip: null,
      legend: null,
      title: null,
      subchart: {
        main: null,
        // $$.context
        bar: null,
        // $$.contextBar
        line: null,
        // $$.contextLine
        area: null
        // $$.contextArea
      },
      arcs: null,
      bar: null,
      // mainBar,
      candlestick: null,
      line: null,
      // mainLine,
      area: null,
      // mainArea,
      circle: null,
      // mainCircle,
      radar: null,
      text: null,
      // mainText,
      grid: {
        main: null,
        // grid (also focus)
        x: null,
        // xgrid,
        y: null
        // ygrid,
      },
      gridLines: {
        main: null,
        // gridLines
        x: null,
        // xgridLines,
        y: null
        // ygridLines
      },
      region: {
        main: null,
        // region
        list: null
        // mainRegion
      },
      eventRect: null,
      zoomResetBtn: null
      // drag zoom reset button
    };
    return element;
  }
}

;// ./src/config/Store/State.ts
class State {
  constructor() {
    return {
      // chart drawn area dimension, excluding axes
      width: 0,
      width2: 0,
      height: 0,
      height2: 0,
      margin: {
        top: 0,
        bottom: 0,
        left: 0,
        right: 0
      },
      margin2: {
        top: 0,
        bottom: 0,
        left: 0,
        right: 0
      },
      margin3: {
        top: 0,
        bottom: 0,
        left: 0,
        right: 0
      },
      arcWidth: 0,
      arcHeight: 0,
      xAxisHeight: 0,
      hasAxis: false,
      hasFunnel: false,
      hasRadar: false,
      hasTreemap: false,
      isCanvasMode: false,
      canvasShape: null,
      canvasFocusKey: null,
      canvasSubchartBrushDragging: false,
      canvasSubchartBrushMode: null,
      canvasSubchartBrushStart: null,
      canvasSubchartBrushOrigin: null,
      canvasSubchartBrushMoved: false,
      canvasFlowFrame: null,
      canvasFlowFinish: null,
      canvasFocusMainRedraw: false,
      // for data CSS rule index (used when boost.useCssRule is true)
      cssRule: {},
      // Data loading state (used in scale calculation)
      loading: void 0,
      // Zoom/subchart domain (different from current.domain which is for rendering)
      domain: void 0,
      subchartSourceTypes: void 0,
      current: {
        // current domain value. Assigned when is zoom is called
        domain: void 0,
        // chart whole dimension
        width: 0,
        height: 0,
        dataMax: 0,
        maxTickSize: {
          x: {
            width: 0,
            height: 0,
            ticks: [],
            clipPath: 0,
            domain: ""
          },
          y: { width: 0, height: 0, domain: "" },
          y2: { width: 0, height: 0, domain: "" }
        },
        // current used chart type list
        types: [],
        needle: void 0,
        // arc needle current value
        zoomDomain: null
        // zoomed domain value
      },
      // legend
      isLegendRight: false,
      isLegendInset: false,
      isLegendTop: false,
      isLegendLeft: false,
      legendStep: 0,
      legendItemWidth: 0,
      legendItemHeight: 0,
      legendHasRendered: false,
      canvasInlineStyle: {
        minHeight: ""
      },
      canvasSelection: /* @__PURE__ */ new Set(),
      canvasSelectionDragStart: null,
      canvasSelectionDragIncluded: /* @__PURE__ */ new Set(),
      canvasSelectionDragging: false,
      canvasSelectionDragMoved: false,
      canvasSelectionDragMoveHandler: null,
      canvasSelectionDragEndHandler: null,
      eventReceiver: {
        currentIdx: -1,
        // current event interaction index
        rect: {},
        // event rect's clientBoundingRect
        data: [],
        // event data bound of previoous eventRect
        coords: []
        // coordination value of previous eventRect
      },
      axis: {
        x: {
          padding: { left: 0, right: 0 },
          tickCount: 0
        }
      },
      rotatedPadding: {
        left: 30,
        right: 0,
        top: 5
      },
      withoutFadeIn: {},
      inputType: "",
      datetimeId: "",
      // clip id string
      clip: {
        id: "",
        idXAxis: "",
        idYAxis: "",
        idXAxisTickTexts: "",
        idGrid: "",
        idSubchart: "",
        // clipIdForSubchart
        path: "",
        pathXAxis: "",
        pathYAxis: "",
        pathXAxisTickTexts: "",
        pathGrid: ""
      },
      // state
      event: null,
      // event object
      dragStart: null,
      dragging: false,
      flowing: false,
      cancelClick: false,
      mouseover: false,
      rendered: false,
      transiting: false,
      redrawing: false,
      // if redraw() is on process
      resizing: false,
      // resize event called
      resizePreview: false,
      // rendered surface is stretched, pending an exact redraw
      resizeRedrawTime: 0,
      // ms the last resize redraw took, decides resize.live strategy
      // stretch instead of redrawing for the rest of this resize; null until decided
      resizeLiveScale: null,
      toggling: false,
      // legend toggle
      zooming: false,
      hasNegativeValue: false,
      hasPositiveValue: true,
      orgAreaOpacity: "0.2",
      orgConfig: {},
      // user original genration config
      // ID strings (Set for O(1) lookup — see isTargetToShow, classFocused, etc.)
      hiddenTargetIds: /* @__PURE__ */ new Set(),
      hiddenLegendIds: /* @__PURE__ */ new Set(),
      focusedTargetIds: /* @__PURE__ */ new Set(),
      defocusedTargetIds: /* @__PURE__ */ new Set(),
      // value for Arc
      radius: 0,
      innerRadius: 0,
      outerRadius: void 0,
      innerRadiusRatio: 0,
      gaugeArcWidth: 0,
      radiusExpanded: 0,
      // xgrid attribute
      xgridAttr: {
        x1: null,
        x2: null,
        y1: null,
        y2: null
      },
      // RAF batching for zoom/drag interactions
      pendingRaf: null,
      rafBatchQueue: [],
      // Dirty flags for selective redraw
      dirty: {
        data: false,
        // data changed (load/unload)
        visibility: false,
        // show/hide toggled
        size: false
        // dimensions changed
      },
      // Performance: generation counters for cache invalidation
      redrawGeneration: 0,
      // increments every redraw (for per-redraw caches)
      dataGeneration: 0,
      // increments on data/visibility changes (for data-dependent caches)
      // Performance: cached values for reuse within redraw cycle
      _targetsToShow: null,
      _cachedDrawShape: null,
      _canvasVisibleRangeCache: null,
      _canvasXDataTickCache: null,
      _canvasXTickValuesCache: null,
      _eventRectFingerprint: null,
      // Performance: throttle tooltip position updates on mousemove
      _lastTooltipMouse: null,
      // Performance: cached grid focus D3 selection
      _gridFocusEl: null,
      // Performance: generateClass() result cache (series IDs are fixed per chart)
      generateClassCache: /* @__PURE__ */ new Map()
    };
  }
}

;// ./src/config/Store/Store.ts


const Store_classes = {
  element: Element,
  state: State
};
class Store {
  constructor() {
    Object.keys(Store_classes).forEach((v) => {
      this[v] = new Store_classes[v]();
    });
  }
  getStore(name) {
    return this[name];
  }
}

;// ./src/module/Cache.ts
var Cache_defProp = Object.defineProperty;
var Cache_defNormalProp = (obj, key, value) => key in obj ? Cache_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var Cache_publicField = (obj, key, value) => Cache_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);

const KEY = {
  bubbleBaseLength: "$baseLength",
  bubbleMaxValue: "$bubbleMaxValue",
  colorPattern: "__colorPattern__",
  dataMinMax: "$dataMinMax",
  dataTotalSum: "$dataTotalSum",
  dataTotalPerIndex: "$totalPerIndex",
  visibleTotalPerIndex: "$visibleTotalPerIndex",
  domainMinMax: "$domainMinMax",
  filteredTargets: "$filteredTargets",
  svgLeft: "$svgLeft",
  valuesByX: "$valuesByX",
  legendItemTextBox: "legendItemTextBox",
  legendItemMap: "$legendItemMap",
  radarPoints: "$radarPoints",
  radarTextWidth: "$radarTextWidth",
  setOverOut: "setOverOut",
  callOverOutForTouch: "callOverOutForTouch",
  textRect: "textRect",
  shapeOffset: "$shapeOffset",
  maxTickSize: "$maxTickSize",
  maxDataCountTarget: "$maxDataCountTarget",
  valuesXIndexMap: "$valuesXIndexMap"
};
class Cache {
  constructor() {
    Cache_publicField(this, "cache", /* @__PURE__ */ new Map());
  }
  /**
   * Add cache
   * @param {string} key Cache key
   * @param {string|number|boolean|object|Array|function|null|undefined} value Value to be stored
   * @param {boolean} isDataType Weather the cache is data typed '{id:'data', id_org: 'data', values: [{x:0, index:0,...}, ...]}'
   * @returns {string|number|boolean|object|Array|function|null|undefined} Added data value
   * @private
   */
  add(key, value, isDataType = false) {
    const v = isDataType ? this.cloneTarget(value) : value;
    this.cache.set(key, v);
    return v;
  }
  /**
   * Remove cache
   * @param {string|Array} key Cache key
   * @private
   */
  remove(key) {
    const keys = isString(key) ? [key] : key;
    for (let i = 0; i < keys.length; i++) {
      this.cache.delete(keys[i]);
    }
  }
  /**
   * Get cahce
   * @param {string|Array} key Cache key
   * @param {boolean} isDataType Weather the cache is data typed '{id:'data', id_org: 'data', values: [{x:0, index:0,...}, ...]}'
   * @returns {string|number|boolean|object|Array|function|null} Cached value
   * @private
   */
  get(key, isDataType = false) {
    if (isDataType && Array.isArray(key)) {
      const targets = [];
      for (let i = 0, id; id = key[i]; i++) {
        if (this.cache.has(id)) {
          targets.push(this.cache.get(id));
        }
      }
      return targets;
    } else {
      return this.cache.has(key) ? this.cache.get(key) : null;
    }
  }
  /**
   * Check if cache key exists
   * @param {string} key Cache key
   * @returns {boolean} True if key exists in cache
   * @private
   */
  has(key) {
    return this.cache.has(key);
  }
  /**
   * Get all cache keys
   * @returns {string[]} Array of cache keys
   * @private
   */
  getKeys() {
    return Array.from(this.cache.keys());
  }
  /**
   * Reset cached data
   * @param {boolean} all true: reset all data, false: reset only '$' prefixed key data
   * @param {string[]} excludePrefixes Keys starting with any of these prefixes are preserved
   * @private
   */
  reset(all, excludePrefixes) {
    if (all) {
      this.cache.clear();
    } else {
      this.cache.forEach((_, x) => {
        if (/^\$/.test(x)) {
          if (!(excludePrefixes == null ? void 0 : excludePrefixes.some((prefix) => x.startsWith(prefix)))) {
            this.cache.delete(x);
          }
        }
      });
    }
  }
  /**
   * Clone data target object
   * @param {object} target Data object
   * @returns {object}
   * @private
   */
  cloneTarget(target) {
    return {
      id: target.id,
      id_org: target.id_org,
      values: target.values.map((d) => ({ x: d.x, value: d.value, id: d.id }))
    };
  }
}

;// ./src/module/error.ts




const MODULE_IMPORT_DOC = "https://github.com/naver/billboard.js/blob/master/MODULE_IMPORTS.md";
function checkModuleImport(ctx) {
  const $$ = ctx;
  const { config } = $$;
  let type = "";
  if (isEmpty(config.data_type || config.data_types) && !$$[TYPE_METHOD_NEEDED.LINE]) {
    type = "line";
  } else {
    for (const x in TYPE_METHOD_NEEDED) {
      const t = TYPE[x];
      if ($$.hasType(t) && !$$[TYPE_METHOD_NEEDED[x]]) {
        type = t;
        break;
      }
    }
  }
  type && logError(
    `Please, make sure if %c${camelize(type)}`,
    "module has been imported and specified correctly.",
    MODULE_IMPORT_DOC
  );
}
function checkApiModuleImport(apiName) {
  const moduleName = API_MODULE_NEEDED[apiName];
  moduleName && logError(
    `Please, make sure if %c${moduleName}`,
    "module has been imported and specified correctly.",
    MODULE_IMPORT_DOC
  );
}
function logError(head, tail, info) {
  var _a;
  const prefix = "[billboard.js]";
  const hasConsole = (_a = win.console) == null ? void 0 : _a.error;
  if (hasConsole) {
    const tailMsg = tail ? ["background:red;color:white;display:block;font-size:15px", tail] : [];
    console.error(
      `\u274C ${prefix} ${head}`,
      "background:red;color:white;display:block;font-size:15px",
      ...tailMsg
    );
    info && console.info("%c\u2139\uFE0F", "font-size:15px", info);
  }
  throw Error(`${prefix} ${head.replace(/\%c([a-z-]+)/i, "'$1' ")} ${tail != null ? tail : ""}`);
}

;// ./src/module/util/dom.ts




const RE_CSS_BB = /\s?(bb-)/g;
const RE_CSS_DOTS = /\.+/g;
function getCssSelector(s) {
  return s.replace(RE_CSS_BB, ".$1").replace(RE_CSS_DOTS, ".");
}
function _getRect(relativeViewport, node, forceEval = false) {
  const _ = (n) => n[relativeViewport ? "getBoundingClientRect" : "getBBox"]();
  const cacheKey = relativeViewport ? "rectClient" : "rectBBox";
  if (forceEval) {
    return _(node);
  } else {
    const needEvaluate = !(cacheKey in node) || node.hasAttribute("width") && node[cacheKey].width !== +(node.getAttribute("width") || 0);
    return needEvaluate ? node[cacheKey] = _(node) : node[cacheKey];
  }
}
function setTextValue(node, text, dy = [-1, 1], toMiddle = false) {
  if (!node || !isString(text)) {
    return;
  }
  if (text.indexOf("\n") === -1) {
    node.text(text);
  } else {
    const diff = [node.text(), text].map((v) => v.replace(/[\s\n]/g, ""));
    if (diff[0] !== diff[1]) {
      const multiline = text.split("\n");
      const len = toMiddle ? multiline.length - 1 : 1;
      node.html("");
      multiline.forEach((v, i) => {
        node.append("tspan").attr("x", 0).attr("dy", `${i === 0 ? dy[0] * len : dy[1]}em`).text(v);
      });
    }
  }
}
function getRectSegList(path) {
  const { x, y, width, height } = getBBox(path, true);
  return [
    { x, y: y + height },
    // seg0
    { x, y },
    // seg1
    { x: x + width, y },
    // seg2
    { x: x + width, y: y + height }
    // seg3
  ];
}
function getPathBox(path) {
  const { width, height } = getBoundingRect(path);
  const items = getRectSegList(path);
  const x = items[0].x;
  const y = Math.min(items[0].y, items[1].y);
  return {
    x,
    y,
    width,
    height
  };
}
function getPointer(event, element) {
  var _a;
  const touches = event && ((_a = event.touches || event.sourceEvent && event.sourceEvent.touches) == null ? void 0 : _a[0]);
  let pointer = [0, 0];
  try {
    pointer = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.pointer)(touches || event, element);
  } catch (e) {
  }
  return pointer.map((v) => isNaN(v) ? 0 : v);
}
function getBoundingRect(node, forceEval = false) {
  return _getRect(true, node, forceEval);
}
function getBBox(node, forceEval = false) {
  return _getRect(false, node, forceEval);
}
function addCssRules(style, selector, prop) {
  const { rootSelector = "", sheet } = style;
  const rule = `${rootSelector} ${getCssSelector(selector)} {${prop.join(";")}}`;
  return sheet[sheet.insertRule ? "insertRule" : "addRule"](
    rule,
    sheet.cssRules.length
  );
}
function getCssRules(styleSheets) {
  let rules = [];
  styleSheets.forEach((sheet) => {
    var _a;
    try {
      if (sheet.cssRules && sheet.cssRules.length) {
        rules = rules.concat(toArray(sheet.cssRules));
      }
    } catch (e) {
      (_a = win.console) == null ? void 0 : _a.warn(`Error while reading rules from ${sheet.href}: ${String(e)}`);
    }
  });
  return rules;
}
function getScrollPosition(node) {
  var _a, _b, _c, _d, _e, _f;
  return {
    x: ((_b = (_a = win.pageXOffset) != null ? _a : win.scrollX) != null ? _b : 0) + ((_c = node.scrollLeft) != null ? _c : 0),
    y: ((_e = (_d = win.pageYOffset) != null ? _d : win.scrollY) != null ? _e : 0) + ((_f = node.scrollTop) != null ? _f : 0)
  };
}
function getTransformCTM(node, x = 0, y = 0, inverse = true) {
  const point = new DOMPoint(x, y);
  const screen = node.getScreenCTM();
  const res = point.matrixTransform(
    inverse ? screen == null ? void 0 : screen.inverse() : screen
  );
  if (inverse === false) {
    const rect = getBoundingRect(node);
    res.x -= rect.x;
    res.y -= rect.y;
  }
  return res;
}
function getTranslation(node) {
  const transform = node ? node.transform : null;
  const baseVal = transform && transform.baseVal;
  return baseVal && baseVal.numberOfItems ? baseVal.getItem(0).matrix : { a: 0, b: 0, c: 0, d: 0, e: 0, f: 0 };
}
function getElementPos(element, type) {
  var _a;
  const attr = (_a = element == null ? void 0 : element.getAttribute) == null ? void 0 : _a.call(element, type);
  if (attr) {
    return parseFloat(attr);
  }
  const matrix = getTranslation(element);
  return type === "x" ? matrix.e : matrix.f;
}
function hasViewBox(svg) {
  const attr = svg.attr("viewBox");
  return attr ? attr.trim().split(/[\s,]+/).length === 4 : false;
}
function hasStyle(node, condition, all = false) {
  const isD3Node = !!node.node;
  let has = false;
  for (const [key, value] of Object.entries(condition)) {
    has = isD3Node ? node.style(key) === value : node.style[key] === value;
    if (all ? !has : has) {
      break;
    }
  }
  return has;
}
function isTabVisible() {
  var _a, _b;
  return ((_a = browser_doc) == null ? void 0 : _a.hidden) === false || ((_b = browser_doc) == null ? void 0 : _b.visibilityState) === "visible";
}
function convertInputType(mouse, touch) {
  const { DocumentTouch, matchMedia, navigator } = win;
  const hasPointerCoarse = matchMedia == null ? void 0 : matchMedia("(pointer:coarse)").matches;
  let hasTouch = false;
  if (touch) {
    if (navigator && "maxTouchPoints" in navigator) {
      hasTouch = navigator.maxTouchPoints > 0;
    } else if ("ontouchmove" in win || DocumentTouch && browser_doc instanceof DocumentTouch) {
      hasTouch = true;
    } else {
      if (hasPointerCoarse) {
        hasTouch = true;
      } else {
        const UA = navigator.userAgent;
        hasTouch = /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) || /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA);
      }
    }
  }
  const hasMouse = mouse && !hasPointerCoarse && (matchMedia == null ? void 0 : matchMedia("(pointer:fine)").matches);
  return hasMouse && "mouse" || hasTouch && "touch" || "mouse";
}
function scheduleRAFUpdate(rafState, callback) {
  if (rafState.pendingRaf !== null) {
    win.cancelAnimationFrame(rafState.pendingRaf);
    rafState.pendingRaf = win.requestAnimationFrame(() => {
      rafState.pendingRaf = null;
      callback();
    });
  } else {
    rafState.pendingRaf = win.requestAnimationFrame(() => {
      rafState.pendingRaf = null;
    });
    callback();
  }
}
const emulateEvent = {
  mouse: (() => {
    const getParams = () => ({
      bubbles: false,
      cancelable: false,
      screenX: 0,
      screenY: 0,
      clientX: 0,
      clientY: 0
    });
    try {
      new MouseEvent("t");
      return (el, eventType, params = getParams()) => {
        el.dispatchEvent(new MouseEvent(eventType, params));
      };
    } catch (e) {
      return (el, eventType, params = getParams()) => {
        const mouseEvent = browser_doc.createEvent("MouseEvent");
        mouseEvent.initMouseEvent(
          eventType,
          params.bubbles,
          params.cancelable,
          win,
          0,
          // the event's mouse click count
          params.screenX,
          params.screenY,
          params.clientX,
          params.clientY,
          false,
          false,
          false,
          false,
          0,
          null
        );
        el.dispatchEvent(mouseEvent);
      };
    }
  })(),
  touch: (el, eventType, params) => {
    const touchObj = new Touch(mergeObj({
      identifier: Date.now(),
      target: el,
      radiusX: 2.5,
      radiusY: 2.5,
      rotationAngle: 10,
      force: 0.5
    }, params));
    el.dispatchEvent(new TouchEvent(eventType, {
      cancelable: true,
      bubbles: true,
      shiftKey: true,
      touches: [touchObj],
      targetTouches: [],
      changedTouches: [touchObj]
    }));
  }
};


;// ./src/module/generator.ts


const { setTimeout: generator_setTimeout, clearTimeout: generator_clearTimeout } = win;
function generateResize(option, live) {
  const fn = [];
  let timeout;
  let rafId = null;
  const callResizeFn = function() {
    callResizeFn.clear();
    if (live && rafId === null) {
      rafId = requestAnimationFrame(() => {
        rafId = null;
        live();
      });
    }
    if (option === false) {
      timeout = requestIdleCallback(() => {
        timeout = null;
        fn.forEach((f) => f());
      }, { timeout: 200 });
    } else {
      timeout = generator_setTimeout(() => {
        timeout = null;
        fn.forEach((f) => f());
      }, isNumber(option) ? option : 200);
    }
  };
  callResizeFn.clear = () => {
    if (timeout) {
      (option === false ? cancelIdleCallback : generator_clearTimeout)(timeout);
      timeout = null;
    }
  };
  callResizeFn.clearLive = () => {
    if (rafId !== null) {
      cancelAnimationFrame(rafId);
      rafId = null;
    }
  };
  callResizeFn.add = (f) => fn.push(f);
  callResizeFn.remove = (f) => {
    const index = fn.indexOf(f);
    index !== -1 && fn.splice(index, 1);
  };
  return callResizeFn;
}
function generateWait() {
  let transitionsToWait = [];
  const f = function(selection, callback) {
    function loop() {
      var _a;
      let done = 0;
      for (let i = 0, t; t = transitionsToWait[i]; i++) {
        if (t === true || ((_a = t.empty) == null ? void 0 : _a.call(t))) {
          done++;
          continue;
        }
        if (isTabVisible() === false) {
          done = transitionsToWait.length;
          break;
        }
        try {
          t.transition();
        } catch (e) {
          done++;
        }
      }
      return done === transitionsToWait.length;
    }
    runUntil(() => {
      callback == null ? void 0 : callback();
    }, loop);
  };
  f.add = function(t) {
    isArray(t) ? transitionsToWait = transitionsToWait.concat(t) : transitionsToWait.push(t);
  };
  return f;
}

;// ./src/module/worker.ts

const cache = {};
const disabledKeys = /* @__PURE__ */ new Set();
const verifiedOps = /* @__PURE__ */ new Map();
const DEFAULT_WORKER_TIMEOUT = 5e3;
const VERIFY_SAMPLE_SIZE = 3;
let messageId = 0;
function getWorkerSrc() {
  try {
    return "var bbWorker=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){let t=[];return e.forEach(function(e,n){let r=e[0];e.forEach(function(e,i){if(i>0){if(t[i-1]===void 0&&(t[i-1]={}),e===void 0)throw Error(`Source data is missing a component at (${n}, ${i})!`);t[i-1][r]=e}})}),t}function n(e){let t=e[0],n=[];return e.forEach(function(e,r){if(r>0){let i={};e.forEach(function(e,n){if(e===void 0)throw Error(`Source data is missing a component at (${r}, ${n})!`);i[t[n]]=e}),n.push(i)}}),n}function r(e,r){let i=[],a,o;if(Array.isArray(e)){let t=function(e,t){if(e[t]!==void 0)return e[t];let n=t.replace(/\\[(\\w+)\\]/g,`.$1`).replace(/^\\./,``).split(`.`),r=e;return n.some(function(e){return!(r=r&&typeof r==`object`&&e in r?r[e]:void 0)}),r};a=r.x?r.value.concat(r.x):r.value,i.push(a),e.forEach(function(e){let n=a.map(function(n){let r=t(e,n);return r===void 0&&(r=null),r});i.push(n)}),o=n(i)}else Object.keys(e).forEach(function(t){let n=[].concat(e[t]);n.unshift?.(t),i.push(n)}),o=t(i);return o}let i={columns:t,json:r,rows:n},a=self;function o({data:e}){let{args:t,id:n,op:r}=e;try{let e=i[r];if(!e)throw Error(`Unknown worker op: ${r}`);a.postMessage({id:n,result:e(...t)})}catch(e){a.postMessage({id:n,error:e&&(e.message||e.name)||String(e)})}}return typeof window>`u`&&(a.onmessage=o),e.handleMessage=o,e.ops=i,e})({});";
  } catch (e) {
    return "";
  }
}
function getWorkerAPI() {
  const { Blob, Worker, URL } = win;
  return Worker && Blob && (URL == null ? void 0 : URL.createObjectURL) && (URL == null ? void 0 : URL.revokeObjectURL) ? { Blob, Worker, URL } : null;
}
function getWorkerConstructor() {
  return win.Worker || null;
}
function normalizeWorkerOptions(options) {
  var _a, _b;
  return typeof options === "number" ? { timeout: options, workerUrl: "" } : {
    timeout: (_a = options == null ? void 0 : options.timeout) != null ? _a : DEFAULT_WORKER_TIMEOUT,
    workerUrl: (_b = options == null ? void 0 : options.workerUrl) != null ? _b : ""
  };
}
function releaseWorker(key, disable = false) {
  var _a, _b;
  const cached = cache[key];
  if (disable) {
    disabledKeys.add(key);
  }
  if (cached) {
    (_a = cached.worker) == null ? void 0 : _a.terminate();
    cached.revoke && ((_b = getWorkerAPI()) == null ? void 0 : _b.URL.revokeObjectURL(cached.src));
    delete cache[key];
  }
  for (const verified of verifiedOps.keys()) {
    if (verified.startsWith(`${key}:`)) {
      verifiedOps.delete(verified);
    }
  }
}
function isSameResult(actual, expected) {
  if (actual === expected) {
    return true;
  }
  try {
    return JSON.stringify(actual) === JSON.stringify(expected);
  } catch (e) {
    return true;
  }
}
function getVerifySample(args) {
  const [data, ...rest] = args;
  if (!Array.isArray(data)) {
    return args;
  }
  return [
    data.slice(0, VERIFY_SAMPLE_SIZE).map(
      (entry) => (
        // +1: a column/row entry leads with its name, which the values follow
        Array.isArray(entry) ? entry.slice(0, VERIFY_SAMPLE_SIZE + 1) : entry
      )
    ),
    ...rest
  ];
}
function request(worker, op, args, timeout) {
  const id = ++messageId;
  let settled = false;
  let cleanup;
  const promise = new Promise((resolve, reject) => {
    const settle = (fn, value) => {
      if (!settled) {
        settled = true;
        cleanup();
        fn(value);
      }
    };
    const handler = function(e) {
      var _a;
      if (((_a = e.data) == null ? void 0 : _a.id) === id) {
        e.data.error ? settle(reject, new Error(e.data.error)) : settle(resolve, e.data.result);
      }
    };
    const errorHandler = function() {
      settle(reject, new Error("worker error"));
    };
    const timer = setTimeout(() => settle(reject, new Error("worker timeout")), timeout);
    cleanup = () => {
      clearTimeout(timer);
      worker.removeEventListener("message", handler);
      worker.removeEventListener("error", errorHandler);
    };
    worker.addEventListener("message", handler);
    worker.addEventListener("error", errorHandler);
  });
  try {
    worker.postMessage({ args, id, op });
  } catch (error) {
    settled = true;
    cleanup();
    throw error;
  }
  return promise;
}
function startVerify(worker, verifyKey, op, fn, args, timeout) {
  const sample = getVerifySample(args);
  const check = request(worker, op, sample, timeout).then((result) => isSameResult(result, fn(...sample)), () => false).then((matched) => {
    matched ? verifiedOps.set(verifyKey, true) : verifiedOps.delete(verifyKey);
    return matched;
  });
  verifiedOps.set(verifyKey, check);
  return check;
}
function getOrCreateWorkerResources(op, workerUrl = "") {
  const hasWorker = !!getWorkerConstructor();
  const api = workerUrl ? null : getWorkerAPI();
  const src = workerUrl ? "" : getWorkerSrc();
  const key = workerUrl || "blob";
  if (!hasWorker || !workerUrl && (!api || !src) || disabledKeys.has(key)) {
    return null;
  }
  if (!(key in cache)) {
    try {
      if (workerUrl) {
        cache[key] = {
          revoke: false,
          src: workerUrl,
          worker: null
        };
      } else if (api) {
        const blob = new api.Blob([src], {
          type: "text/javascript"
        });
        cache[key] = {
          revoke: true,
          src: api.URL.createObjectURL(blob),
          worker: null
        };
      }
    } catch (e) {
      return null;
    }
  }
  return { key, src: cache[key].src };
}
function getWorker(key, src) {
  const cached = cache[key];
  const Worker = getWorkerConstructor();
  if (!cached || !Worker || disabledKeys.has(key)) {
    return null;
  }
  if (!cached.worker) {
    try {
      cached.worker = new Worker(src);
    } catch (e) {
      releaseWorker(key, true);
      return null;
    }
  }
  return cached.worker;
}
function runWorker(useWorker = true, op, fn, callback, options) {
  const { timeout, workerUrl } = normalizeWorkerOptions(options);
  const runSync = function(...args) {
    const res = fn(...args);
    callback(res);
  };
  let runFn = runSync;
  if (useWorker) {
    const workerResources = getOrCreateWorkerResources(op, workerUrl);
    const worker = workerResources ? getWorker(workerResources.key, workerResources.src) : null;
    if (worker && workerResources) {
      const { key } = workerResources;
      runFn = function(...args) {
        var _a;
        const fallback = () => {
          releaseWorker(key, true);
          runFn = runSync;
          runSync(...args);
        };
        try {
          const verifyKey = `${key}:${op}`;
          const verified = (_a = verifiedOps.get(verifyKey)) != null ? _a : startVerify(worker, verifyKey, op, fn, args, timeout);
          request(worker, op, args, timeout).then((result) => {
            if (verified === true) {
              callback(result);
            } else {
              verified.then((matched) => matched ? callback(result) : fallback());
            }
          }, fallback);
        } catch (e) {
          fallback();
        }
      };
    }
  }
  return runFn;
}
function cleanupWorkers() {
  const api = getWorkerAPI();
  for (const key in cache) {
    const cached = cache[key];
    if (cached.worker) {
      cached.worker.terminate();
    }
    if (cached.src) {
      cached.revoke && (api == null ? void 0 : api.URL.revokeObjectURL(cached.src));
    }
    delete cache[key];
  }
  disabledKeys.clear();
  verifiedOps.clear();
}

;// ./src/module/dsv.ts
const QUOTE = 34;
const NEWLINE = 10;
const RETURN = 13;
function dsv(delimiter) {
  const delimiterCode = delimiter.charCodeAt(0);
  function parseRows(text, callback) {
    const rows = [];
    let len = text.length;
    let pos = 0;
    let rowNum = 0;
    let eof = len <= 0;
    let eol = false;
    text.charCodeAt(0) === 65279 && pos++;
    text.charCodeAt(len - 1) === NEWLINE && --len;
    text.charCodeAt(len - 1) === RETURN && --len;
    function token() {
      if (eof) {
        return null;
      }
      if (eol) {
        eol = false;
        return null;
      }
      const start = pos;
      let c, end;
      if (text.charCodeAt(start) === QUOTE) {
        while (++pos < len) {
          if (text.charCodeAt(pos) === QUOTE) {
            if (text.charCodeAt(pos + 1) !== QUOTE) {
              break;
            }
            pos++;
          }
        }
        if ((end = pos++) >= len) {
          eof = true;
        } else if ((c = text.charCodeAt(pos++)) === NEWLINE) {
          eol = true;
        } else if (c === RETURN) {
          eol = true;
          text.charCodeAt(pos) === NEWLINE && ++pos;
        }
        return text.slice(start + 1, end).replace(/""/g, '"');
      }
      while (pos < len) {
        if ((c = text.charCodeAt(end = pos++)) === NEWLINE) {
          eol = true;
        } else if (c === RETURN) {
          eol = true;
          text.charCodeAt(pos) === NEWLINE && ++pos;
        } else if (c !== delimiterCode) {
          continue;
        }
        return text.slice(start, end);
      }
      eof = true;
      return text.slice(start, len);
    }
    let t;
    while ((t = token()) !== null) {
      const row = [];
      while (t !== null) {
        row.push(t);
        t = token();
      }
      if (callback) {
        const result = callback(row, rowNum++);
        result != null && rows.push(result);
      } else {
        rows.push(row);
      }
    }
    return rows;
  }
  function parse(text, callback) {
    let columns = [];
    return parseRows(text, (row, i) => {
      var _a;
      if (i === 0) {
        columns = row;
        return null;
      }
      const obj = {};
      for (let j = 0; j < columns.length; j++) {
        obj[columns[j]] = (_a = row[j]) != null ? _a : "";
      }
      return callback ? callback(obj, i - 1, columns) : obj;
    });
  }
  return { parse, parseRows };
}
const csv = dsv(",");
const tsv = dsv("	");
const csvParse = csv.parse;
const csvParseRows = csv.parseRows;
const tsvParse = tsv.parse;
const tsvParseRows = tsv.parseRows;

;// ./src/ChartInternal/data/convert.helper.ts


function columns(columns2) {
  const newRows = [];
  columns2.forEach(function(col, i) {
    const key = col[0];
    col.forEach(function(v, j) {
      if (j > 0) {
        if (typeof newRows[j - 1] === "undefined") {
          newRows[j - 1] = {};
        }
        if (typeof v === "undefined") {
          throw new Error(`Source data is missing a component at (${i}, ${j})!`);
        }
        newRows[j - 1][key] = v;
      }
    });
  });
  return newRows;
}
function rows(rows2) {
  const keys = rows2[0];
  const newRows = [];
  rows2.forEach(function(row, i) {
    if (i > 0) {
      const newRow = {};
      row.forEach(function(v, j) {
        if (typeof v === "undefined") {
          throw new Error(`Source data is missing a component at (${i}, ${j})!`);
        }
        newRow[keys[j]] = v;
      });
      newRows.push(newRow);
    }
  });
  return newRows;
}
function json(json2, keysParam) {
  const newRows = [];
  let targetKeys;
  let data;
  if (Array.isArray(json2)) {
    const findValueInJson = function(object, path) {
      if (object[path] !== void 0) {
        return object[path];
      }
      const convertedPath = path.replace(/\[(\w+)\]/g, ".$1");
      const pathArray = convertedPath.replace(/^\./, "").split(".");
      let target = object;
      pathArray.some(function(k) {
        return !(target = target && typeof target === "object" && k in target ? target[k] : void 0);
      });
      return target;
    };
    if (keysParam.x) {
      targetKeys = keysParam.value.concat(keysParam.x);
    } else {
      targetKeys = keysParam.value;
    }
    newRows.push(targetKeys);
    json2.forEach(function(o) {
      const newRow = targetKeys.map(function(key) {
        let v = findValueInJson(o, key);
        if (typeof v === "undefined") {
          v = null;
        }
        return v;
      });
      newRows.push(newRow);
    });
    data = rows(newRows);
  } else {
    Object.keys(json2).forEach(function(key) {
      var _a;
      const tmp = [].concat(json2[key]);
      (_a = tmp.unshift) == null ? void 0 : _a.call(tmp, key);
      newRows.push(tmp);
    });
    data = columns(newRows);
  }
  return data;
}
function url(url2, mimeType = "csv", headers, keys, done) {
  const req = new XMLHttpRequest();
  const converter = { csv: convert_helper_csv, tsv: convert_helper_tsv, json };
  req.open("GET", url2);
  if (headers) {
    Object.keys(headers).forEach(function(key) {
      req.setRequestHeader(key, headers[key]);
    });
  }
  req.onreadystatechange = function() {
    if (req.readyState === 4) {
      if (req.status === 200) {
        const response = req.responseText;
        response && done.call(this, converter[mimeType](
          mimeType === "json" ? JSON.parse(response) : response,
          keys
        ));
      } else {
        throw new Error(`${url2}: Something went wrong loading!`);
      }
    }
  };
  req.send();
}
function convertCsvTsvToData(parser, xsv) {
  const rows2 = parser.rows(xsv);
  let d;
  if (rows2.length === 1) {
    d = [{}];
    rows2[0].forEach((id) => {
      d[0][id] = null;
    });
  } else {
    d = parser.parse(xsv);
  }
  return d;
}
function convert_helper_csv(xsv) {
  return convertCsvTsvToData({
    rows: csvParseRows,
    parse: csvParse
  }, xsv);
}
function convert_helper_tsv(tsv2) {
  return convertCsvTsvToData({
    rows: tsvParseRows,
    parse: tsvParse
  }, tsv2);
}

;// ./src/ChartInternal/data/convert.ts



const WORKER_CELL_THRESHOLD = 5e3;
function _getCellCount(data) {
  var _a, _b;
  const first = data[0];
  if (isArray(first)) {
    let count = 0;
    for (let i = 0, len = data.length; i < len; i++) {
      count += (_b = (_a = data[i]) == null ? void 0 : _a.length) != null ? _b : 0;
    }
    return count;
  }
  return data.length * Object.keys(first != null ? first : {}).length;
}
function _getDataKeyForJson(keysParam, config) {
  const keys = keysParam || (config == null ? void 0 : config.data_keys);
  if (keys == null ? void 0 : keys.x) {
    config.data_x = keys.x;
  }
  return keys;
}
function _setXS(ids, data, params) {
  const $$ = this;
  const { config } = $$;
  let xsData;
  ids.forEach((id) => {
    const xKey = $$.getXKey(id);
    if (params.customX || params.timeSeries) {
      if (params.xs.indexOf(xKey) >= 0) {
        xsData = (params.appendXs && $$.data.xs[id] || []).concat(
          data.map((d, i) => {
            const rawX = d[xKey];
            return isValue(rawX) ? $$.generateTargetX(rawX, id, i) : false;
          }).filter((v) => v !== false)
        );
      } else if (config.data_x) {
        xsData = this.getOtherTargetXs();
      } else if (notEmpty(config.data_xs)) {
        xsData = $$.getXValuesOfXKey(xKey, $$.data.targets);
      }
    } else {
      xsData = data.map((d, i) => i);
    }
    if (xsData) {
      $$.data.xs[id] = xsData;
    } else {
      throw new Error(`x is not defined for id = "${id}".`);
    }
  });
}
/* harmony default export */ var convert = ({
  /**
   * Convert data according its type
   * @param {object} args data object
   * @param {function} [callback] callback for url(XHR) type loading
   * @private
   */
  convertData(args, callback) {
    const { config } = this;
    const useWorker = (d) => {
      if (!(d == null ? void 0 : d.length) || isEmpty(d[0])) {
        return false;
      }
      return config.boost_useWorker === "auto" ? _getCellCount(d) >= WORKER_CELL_THRESHOLD : !!config.boost_useWorker;
    };
    const workerOptions = config.boost_workerUrl ? {
      workerUrl: config.boost_workerUrl
    } : void 0;
    let data = args;
    if (args.bindto) {
      data = {};
      ["url", "mimeType", "headers", "keys", "json", "rows", "columns"].forEach((v) => {
        const key = `data_${v}`;
        if (key in args) {
          data[v] = args[key];
        }
      });
    }
    if (data.url && callback) {
      url(
        data.url,
        data.mimeType,
        data.headers,
        _getDataKeyForJson(data.keys, config),
        callback
      );
    } else if (data.json) {
      runWorker(useWorker(data.json), "json", json, callback, workerOptions)(
        data.json,
        _getDataKeyForJson(data.keys, config)
      );
    } else if (data.rows) {
      runWorker(useWorker(data.rows), "rows", rows, callback, workerOptions)(data.rows);
    } else if (data.columns) {
      runWorker(useWorker(data.columns), "columns", columns, callback, workerOptions)(
        data.columns
      );
    } else if (args.bindto) {
      throw Error("url or json or rows or columns is required.");
    }
  },
  /**
   * Convert data to targets
   * @param {object[]} data Data to convert
   * @param {boolean} appendXs Whether to append xs
   * @returns {IData[]} Converted targets
   * @private
   */
  convertDataToTargets(data, appendXs) {
    const $$ = this;
    const { axis, config, state } = $$;
    const chartType = config.data_type;
    const dataKeys = Object.keys(data[0] || {});
    const { ids, xs } = dataKeys.length ? dataKeys.reduce((acc, key) => {
      if ($$.isX.call($$, key)) {
        acc.xs.push(key);
      } else {
        acc.ids.push(key);
      }
      return acc;
    }, { ids: [], xs: [] }) : { ids: [], xs: [] };
    const params = {
      appendXs,
      xs,
      categorized: axis == null ? void 0 : axis.isCategorized(),
      timeSeries: axis == null ? void 0 : axis.isTimeSeries(),
      customX: axis == null ? void 0 : axis.isCustomX()
    };
    _setXS.bind($$)(ids, data, params);
    const categoryIndexMap = params.customX && params.categorized && config.axis_x_categories.length ? new Map(config.axis_x_categories.map((cat, i) => [cat, i])) : null;
    const idConverter = config.data_idConverter.bind($$.api);
    const targets = ids.map((id, index) => {
      const convertedId = idConverter(id);
      const xKey = $$.getXKey(id);
      const isCategory = params.customX && params.categorized;
      const hasCategory = isCategory && index === 0 && (() => {
        const categorySet = toSet(config.axis_x_categories);
        return data.every((v) => categorySet.has(v[xKey]));
      })();
      const isDataAppend = data.__append__;
      const xIndex = xKey === null && isDataAppend ? $$.api.data.values(id).length : 0;
      return {
        id: convertedId,
        id_org: id,
        values: data.map((d, i) => {
          var _a;
          const rawX = d[xKey];
          let value = d[id];
          let x;
          value = value !== null && !isNaN(value) && !isObject(value) ? +value : isArray(value) || isObject(value) ? value : null;
          if ((isCategory || state.hasRadar) && index === 0 && !isUndefined(rawX)) {
            if (!hasCategory && i === 0 && !isDataAppend) {
              config.axis_x_categories = [];
              if (categoryIndexMap) {
                categoryIndexMap.clear();
              }
            }
            const rawXStr = String(rawX);
            x = (_a = categoryIndexMap == null ? void 0 : categoryIndexMap.get(rawXStr)) != null ? _a : -1;
            if (x === -1) {
              x = config.axis_x_categories.length;
              config.axis_x_categories.push(rawX);
              categoryIndexMap == null ? void 0 : categoryIndexMap.set(rawXStr, x);
            }
          } else {
            x = $$.generateTargetX(rawX, id, xIndex + i);
          }
          if (isUndefined(value) || $$.data.xs[id].length <= i) {
            x = void 0;
          }
          return {
            x,
            value,
            id: convertedId,
            index: -1
          };
        }).filter((v) => isDefined(v.x))
      };
    });
    targets.forEach((t) => {
      var _a;
      if (config.data_xSort) {
        t.values = t.values.sort((v1, v2) => {
          const x1 = v1.x || v1.x === 0 ? v1.x : Infinity;
          const x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
          return x1 - x2;
        });
      }
      t.values.forEach((v, i) => v.index = i);
      (_a = $$.data.xs[t.id]) == null ? void 0 : _a.sort((v1, v2) => v1 - v2);
    });
    state.hasNegativeValue = targets.some(
      (t) => t.values.some((v) => v.value !== null && v.value < 0)
    );
    state.hasPositiveValue = targets.some(
      (t) => t.values.some((v) => v.value !== null && v.value > 0)
    );
    if (chartType && $$.isValidChartType(chartType)) {
      const targetIds = $$.mapToIds(targets).filter(
        (id) => !(id in config.data_types) || !$$.isValidChartType(config.data_types[id])
      );
      $$.setTargetType(targetIds, chartType);
    }
    targets.forEach((d) => $$.cache.add(d.id_org, d, true));
    return targets;
  }
});

;// ./src/ChartInternal/data/data.ts





const rangedDataKeyIndex = {
  areaRange: { high: 0, mid: 1, low: 2 },
  candlestick: { open: 0, high: 1, low: 2, close: 3, volume: 4 }
};
function normalizeTargetIds(targetIds) {
  return isArray(targetIds) ? targetIds : [targetIds];
}
/* harmony default export */ var data_data = ({
  isX(key) {
    const $$ = this;
    const { config } = $$;
    const dataKey = config.data_x && key === config.data_x;
    const existValue = notEmpty(config.data_xs) && hasValue(config.data_xs, key);
    return dataKey || existValue;
  },
  isStackNormalized() {
    const { config } = this;
    return !!((config.data_stack_normalize === true || isObjectType(config.data_stack_normalize)) && config.data_groups.length);
  },
  /**
   * Check if stack normalization should be applied per group
   * @returns {boolean}
   * @private
   */
  isStackNormalizedPerGroup() {
    var _a;
    const { config } = this;
    return !!(isObjectType(config.data_stack_normalize) && ((_a = config.data_stack_normalize) == null ? void 0 : _a.perGroup) && config.data_groups.length);
  },
  /**
   * Check if given id is grouped data or has grouped data
   * @param {string} id Data id value
   * @returns {boolean} is grouped data or has grouped data
   * @private
   */
  isGrouped(id) {
    const groups = this.config.data_groups;
    return id ? groups.some((v) => v.indexOf(id) >= 0 && v.length > 1) : groups.length > 0;
  },
  /**
   * Check if the given axis has any grouped data
   * @param {string} axisId Axis ID (e.g., "y", "y2")
   * @returns {boolean} true if axis has grouped data
   * @private
   */
  hasAxisGroupedData(axisId) {
    const $$ = this;
    const { axis } = $$;
    const targets = $$.data.targets;
    const axisDataIds = targets.filter((t) => axis.getId(t.id) === axisId).map((t) => t.id);
    return axisDataIds.some((id) => $$.isGrouped(id));
  },
  getXKey(id) {
    const $$ = this;
    const { config } = $$;
    return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
  },
  getXValuesOfXKey(key, targets) {
    const $$ = this;
    const ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
    let xValues;
    ids.forEach((id) => {
      if ($$.getXKey(id) === key) {
        xValues = $$.data.xs[id];
      }
    });
    return xValues;
  },
  /**
   * Get index number based on given x Axis value
   * @param {Date|number|string} x x Axis to be compared
   * @param {Array} basedX x Axis list to be based on
   * @returns {number} index number
   * @private
   */
  getIndexByX(x, basedX) {
    const $$ = this;
    return basedX ? basedX.indexOf(isString(x) ? x : +x) : ($$.filterByX($$.data.targets, x)[0] || { index: null }).index;
  },
  getXValue(id, i) {
    const $$ = this;
    return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
  },
  getOtherTargetXs() {
    const $$ = this;
    const idsForX = Object.keys($$.data.xs);
    return idsForX.length ? $$.data.xs[idsForX[0]] : null;
  },
  getOtherTargetX(index) {
    const xs = this.getOtherTargetXs();
    return xs && index < xs.length ? xs[index] : null;
  },
  addXs(xs) {
    const $$ = this;
    const { config } = $$;
    Object.keys(xs).forEach((id) => {
      config.data_xs[id] = xs[id];
    });
  },
  /**
   * Determine if x axis is multiple
   * @returns {boolean} true: multiple, false: single
   * @private
   */
  isMultipleX() {
    return !this.config.axis_x_forceAsSingle && (notEmpty(this.config.data_xs) || this.hasType("bubble") || this.hasType("scatter"));
  },
  addName(data) {
    const $$ = this;
    const { config } = $$;
    let name;
    if (data) {
      name = config.data_names[data.id];
      data.name = name !== void 0 ? name : data.id;
    }
    return data;
  },
  /**
   * Get all values on given index
   * @param {number} index Index
   * @param {boolean} filterNull Filter nullish value
   * @returns {Array}
   * @private
   */
  getAllValuesOnIndex(index, filterNull = false) {
    const $$ = this;
    let value = $$.filterTargetsToShow($$.data.targets).map((t) => $$.addName($$.getValueOnIndex(t.values, index)));
    if (filterNull) {
      value = value.filter((v) => v && "value" in v && isValue(v.value));
    }
    return value;
  },
  getValueOnIndex(values, index) {
    var _a;
    if (((_a = values[index]) == null ? void 0 : _a.index) === index) {
      return values[index];
    }
    const valueOnIndex = values.filter((v) => v.index === index);
    return valueOnIndex.length ? valueOnIndex[0] : null;
  },
  updateTargetX(targets, x) {
    const $$ = this;
    targets.forEach((t) => {
      t.values.forEach((v, i) => {
        v.x = $$.generateTargetX(x[i], t.id, i);
      });
      $$.data.xs[t.id] = x;
    });
  },
  updateTargetXs(targets, xs) {
    const $$ = this;
    targets.forEach((t) => {
      xs[t.id] && $$.updateTargetX([t], xs[t.id]);
    });
  },
  generateTargetX(rawX, id, index) {
    const $$ = this;
    const { axis } = $$;
    let x = (axis == null ? void 0 : axis.isCategorized()) ? index : rawX || index;
    if (axis == null ? void 0 : axis.isTimeSeries()) {
      const fn = parseDate.bind($$);
      x = rawX ? fn(rawX) : fn($$.getXValue(id, index));
    } else if ((axis == null ? void 0 : axis.isCustomX()) && !(axis == null ? void 0 : axis.isCategorized())) {
      x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
    }
    return x;
  },
  updateXs(values) {
    if (values.length) {
      this.axis.xs = values.map((v) => v.x);
    }
  },
  getPrevX(i) {
    const x = this.axis.xs[i - 1];
    return isDefined(x) ? x : null;
  },
  getNextX(i) {
    const x = this.axis.xs[i + 1];
    return isDefined(x) ? x : null;
  },
  /**
   * Get base value isAreaRangeType
   * @param {object} data Data object
   * @returns {number}
   * @private
   */
  getBaseValue(data) {
    const $$ = this;
    const { hasAxis } = $$.state;
    let { value } = data;
    if (value && hasAxis) {
      if ($$.isAreaRangeType(data)) {
        value = $$.getRangedData(data, "mid");
      } else if ($$.isBubbleZType(data)) {
        value = $$.getBubbleZData(value, "y");
      }
    }
    return value;
  },
  /**
   * Get min/max value from the data
   * @private
   * @param {Array} data array data to be evaluated
   * @returns {{min: {number}, max: {number}}}
   */
  getMinMaxValue(data) {
    const getBaseValue = this.getBaseValue.bind(this);
    let min = Infinity;
    let max = -Infinity;
    const targets = data || this.data.targets.map((t) => t.values);
    for (let i = 0; i < targets.length; i++) {
      const v = targets[i];
      for (let j = 0; j < v.length; j++) {
        const val = getBaseValue(v[j]);
        if (isNumber(val)) {
          if (val < min) min = val;
          if (val > max) max = val;
        }
      }
    }
    return { min, max };
  },
  /**
   * Get the min/max data
   * @private
   * @returns {{min: Array, max: Array}}
   */
  getMinMaxData() {
    const $$ = this;
    const cacheKey = KEY.dataMinMax;
    let minMaxData = $$.cache.get(cacheKey);
    if (!minMaxData) {
      const data = $$.data.targets.map((t) => t.values);
      const minMax = $$.getMinMaxValue(data);
      const min = [];
      const max = [];
      const { min: minVal, max: maxVal } = minMax;
      data.forEach((v) => {
        const minData = $$.getFilteredDataByValue(v, minVal);
        const maxData = $$.getFilteredDataByValue(v, maxVal);
        if (minData.length) {
          for (let i = 0; i < minData.length; i++) {
            min.push(minData[i]);
          }
        }
        if (maxData.length) {
          for (let i = 0; i < maxData.length; i++) {
            max.push(maxData[i]);
          }
        }
      });
      $$.cache.add(cacheKey, minMaxData = { min, max });
    }
    return minMaxData;
  },
  /**
   * Get sum of data per index
   * @param {string} targetId Target ID to get total for (only for normalized stack per group)
   * @private
   * @returns {Array}
   */
  getTotalPerIndex(targetId) {
    const $$ = this;
    const { config } = $$;
    const cacheKey = targetId ? `${KEY.dataTotalPerIndex}-${targetId}` : KEY.dataTotalPerIndex;
    const cached = $$.cache.get(cacheKey);
    let sum = (cached == null ? void 0 : cached.generation) === $$.state.dataGeneration ? cached.value : null;
    if (($$.config.data_groups.length || $$.isStackNormalized()) && !sum) {
      sum = [];
      let { targets } = $$.data;
      if ($$.isStackNormalizedPerGroup() && targetId) {
        const group = config.data_groups.find((g) => g.indexOf(targetId) >= 0);
        if (group) {
          targets = targets.filter((t) => group.indexOf(t.id) >= 0);
        } else {
          return null;
        }
      }
      targets.forEach((row) => {
        row.values.forEach((v, i) => {
          if (!sum[i]) {
            sum[i] = 0;
          }
          sum[i] += isNumber(v.value) ? v.value : 0;
        });
      });
      $$.cache.add(cacheKey, { generation: $$.state.dataGeneration, value: sum });
    }
    return sum;
  },
  /**
   * Get per-index totals excluding hidden series, cached until data or visibility changes.
   * @param {string} targetId Target ID for per-group normalization
   * @returns {Array|null} Visible totals, or null for an ungrouped target
   * @private
   */
  getVisibleTotalPerIndex(targetId) {
    const $$ = this;
    const { api, config, state, cache } = $$;
    let cached = cache.get(KEY.visibleTotalPerIndex);
    if (!cached || cached.generation !== state.dataGeneration) {
      cached = cache.add(KEY.visibleTotalPerIndex, {
        generation: state.dataGeneration,
        values: /* @__PURE__ */ new Map()
      });
    }
    if (cached.values.has(targetId)) {
      return cached.values.get(targetId);
    }
    const dataValues = api.data.values.bind(api);
    const { hiddenTargetIds } = state;
    let total = $$.getTotalPerIndex(targetId);
    if (total === null) {
      cached.values.set(targetId, total);
      return total;
    }
    if (hiddenTargetIds.size) {
      let hiddenIds = [...hiddenTargetIds];
      if (targetId) {
        const group = config.data_groups.find((g) => g.indexOf(targetId) >= 0);
        if (group) {
          hiddenIds = hiddenIds.filter((id) => group.indexOf(id) >= 0);
        }
      }
      if (hiddenIds.length) {
        let hiddenSum = dataValues(hiddenIds, false);
        if (hiddenSum.length) {
          hiddenSum = hiddenSum.reduce((acc, curr) => acc.map((v, i) => (isNumber(v) ? v : 0) + curr[i]));
          total = total.map((v, i) => v - hiddenSum[i]);
        }
      }
    }
    cached.values.set(targetId, total);
    return total;
  },
  /**
   * Get total data sum
   * @param {boolean} subtractHidden Subtract hidden data from total
   * @returns {number}
   * @private
   */
  getTotalDataSum(subtractHidden) {
    const $$ = this;
    const cacheKey = KEY.dataTotalSum;
    let total = $$.cache.get(cacheKey);
    if (!isNumber(total)) {
      total = $$.data.targets.reduce((acc, t) => {
        return acc + t.values.reduce((sum, v) => {
          var _a;
          return sum + ((_a = v.value) != null ? _a : 0);
        }, 0);
      }, 0);
      $$.cache.add(cacheKey, total);
    }
    if (subtractHidden) {
      total -= $$.getHiddenTotalDataSum();
    }
    return total;
  },
  /**
   * Get total hidden data sum
   * @returns {number}
   * @private
   */
  getHiddenTotalDataSum() {
    const $$ = this;
    const { api, state: { hiddenTargetIds } } = $$;
    let total = 0;
    if (hiddenTargetIds.size) {
      total = api.data.values.bind(api)([...hiddenTargetIds]).reduce((p, c) => p + c, 0);
    }
    return total;
  },
  /**
   * Get filtered data by value
   * @param {object} data Data
   * @param {number} value Value to be filtered
   * @returns {Array} filtered array data
   * @private
   */
  getFilteredDataByValue(data, value) {
    return data.filter((t) => this.getBaseValue(t) === value);
  },
  /**
   * Return the max length of the data
   * @returns {number} max data length
   * @private
   */
  getMaxDataCount() {
    const { targets } = this.data;
    let max = 0;
    for (let i = 0; i < targets.length; i++) {
      if (targets[i].values.length > max) {
        max = targets[i].values.length;
      }
    }
    return max;
  },
  getMaxDataCountTarget() {
    const $$ = this;
    const { cache, state } = $$;
    const cached = cache.get(KEY.maxDataCountTarget);
    if (cached && cached.generation === state.dataGeneration) {
      return cached.value;
    }
    let target = $$.filterTargetsToShow() || [];
    const length = target.length;
    const isInverted = $$.config.axis_x_inverted;
    if (length > 1) {
      const allX = [];
      for (let i = 0; i < target.length; i++) {
        const values = target[i].values;
        for (let j = 0; j < values.length; j++) {
          allX.push(values[j].x);
        }
      }
      target = allX;
      target = sortValue(getUnique(target)).map((x, index, array) => ({
        x,
        index: isInverted ? array.length - index - 1 : index
      }));
    } else if (length) {
      target = target[0].values.concat();
    }
    cache.add(KEY.maxDataCountTarget, { value: target, generation: state.dataGeneration });
    return target;
  },
  mapToIds(targets) {
    return targets.map((d) => d.id);
  },
  mapToTargetIds(ids) {
    const $$ = this;
    return ids ? isArray(ids) ? ids.concat() : [ids] : $$.mapToIds($$.data.targets);
  },
  hasTarget(targets, id) {
    const ids = this.mapToIds(targets);
    for (let i = 0, val; val = ids[i]; i++) {
      if (val === id) {
        return true;
      }
    }
    return false;
  },
  isTargetToShow(targetId) {
    return !this.state.hiddenTargetIds.has(targetId);
  },
  isLegendToShow(targetId) {
    return !this.state.hiddenLegendIds.has(targetId);
  },
  getTargetsToShow() {
    var _a;
    const { state } = this;
    return (_a = state._targetsToShow) != null ? _a : this.filterTargetsToShow();
  },
  filterTargetsToShow(targets) {
    const $$ = this;
    if (!targets) {
      const { cache, data, state } = $$;
      const cacheKey = KEY.filteredTargets;
      const cached = cache.get(cacheKey);
      if (cached && cached.generation === state.dataGeneration) {
        return cached.value;
      }
      const filtered = data.targets.filter((t) => $$.isTargetToShow(t.id));
      cache.add(cacheKey, { value: filtered, generation: state.dataGeneration });
      return filtered;
    }
    return targets.filter((t) => $$.isTargetToShow(t.id));
  },
  mapTargetsToUniqueXs(targets) {
    const $$ = this;
    const { axis } = $$;
    let xs = [];
    if (targets == null ? void 0 : targets.length) {
      xs = getUnique(
        mergeArray(targets.map((t) => t.values.map((v) => +v.x)))
      );
      xs = (axis == null ? void 0 : axis.isTimeSeries()) ? xs.map((x) => /* @__PURE__ */ new Date(+x)) : xs.map(Number);
    }
    return sortValue(xs);
  },
  /**
   * Add to thetarget Ids
   * @param {string} type State's prop name
   * @param {Array|string} targetIds Target ids array
   * @private
   */
  addTargetIds(type, targetIds) {
    const { state } = this;
    normalizeTargetIds(targetIds).forEach((v) => state[type].add(v));
  },
  /**
   * Remove from the state target Ids
   * @param {string} type State's prop name
   * @param {Array|string} targetIds Target ids array
   * @private
   */
  removeTargetIds(type, targetIds) {
    const { state } = this;
    normalizeTargetIds(targetIds).forEach((v) => state[type].delete(v));
  },
  addHiddenTargetIds(targetIds) {
    this.addTargetIds("hiddenTargetIds", targetIds);
    this.cache.remove(KEY.visibleTotalPerIndex);
  },
  removeHiddenTargetIds(targetIds) {
    this.removeTargetIds("hiddenTargetIds", targetIds);
    this.cache.remove(KEY.visibleTotalPerIndex);
  },
  addHiddenLegendIds(targetIds) {
    this.addTargetIds("hiddenLegendIds", targetIds);
  },
  removeHiddenLegendIds(targetIds) {
    this.removeTargetIds("hiddenLegendIds", targetIds);
  },
  getValuesAsIdKeyed(targets) {
    const $$ = this;
    const { hasAxis } = $$.state;
    const ys = {};
    const isMultipleX = $$.isMultipleX();
    let xIndexMap = null;
    if (isMultipleX) {
      const cached = $$.cache.get(KEY.valuesXIndexMap);
      if (cached && cached.generation === $$.state.dataGeneration) {
        xIndexMap = cached.value;
      } else {
        const xs = $$.mapTargetsToUniqueXs($$.data.targets).map((v) => isString(v) ? v : +v);
        xIndexMap = new Map(xs.map((x, i) => [x, i]));
        $$.cache.add(KEY.valuesXIndexMap, {
          value: xIndexMap,
          generation: $$.state.dataGeneration
        });
      }
    }
    targets.forEach((t) => {
      const data = [];
      t.values.filter(({ value }) => isValue(value) || value === null).forEach((v) => {
        let { value } = v;
        if (value !== null && $$.isCandlestickType(v)) {
          value = isArray(value) ? value.slice(0, 4) : [value.open, value.high, value.low, value.close];
        }
        if (isArray(value)) {
          data.push(...value);
        } else if (isObject(value) && "high" in value) {
          data.push(...Object.values(value));
        } else if ($$.isBubbleZType(v)) {
          data.push(hasAxis && $$.getBubbleZData(value, "y"));
        } else {
          if (isMultipleX && xIndexMap) {
            const xKey = isString(v.x) ? v.x : +v.x;
            const index = xIndexMap.get(xKey);
            if (index !== void 0) {
              data[index] = value;
            }
          } else {
            data.push(value);
          }
        }
      });
      ys[t.id] = data;
    });
    return ys;
  },
  hasMultiTargets() {
    return this.filterTargetsToShow().length > 1;
  },
  /**
   * Sort targets data
   * Note: For stacked bar, will sort from the total sum of data series, not for each stacked bar
   * @param {Array} targetsValue Target value
   * @returns {Array}
   * @private
   */
  orderTargets(targetsValue) {
    const $$ = this;
    const targets = targetsValue.slice();
    const fn = $$.getSortCompareFn();
    fn && targets.sort(fn);
    return targets;
  },
  /**
   * Get data.order compare function
   * @param {boolean} isReversed for Arc & Treemap type sort order needs to be reversed
   * @returns {function} compare function
   * @private
   */
  getSortCompareFn(isReversed = false) {
    const $$ = this;
    const { config } = $$;
    const order = config.data_order;
    const orderAsc = /asc/i.test(order);
    const orderDesc = /desc/i.test(order);
    let fn;
    if (orderAsc || orderDesc) {
      const reducer = (p, c) => p + Math.abs(c.value);
      const sum = (v) => isNumber(v) ? v : "values" in v ? v.values.reduce(reducer, 0) : v.value;
      fn = (t1, t2) => {
        const t1Sum = sum(t1);
        const t2Sum = sum(t2);
        return isReversed ? orderAsc ? t1Sum - t2Sum : t2Sum - t1Sum : orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
      };
    } else if (isFunction(order)) {
      fn = order.bind($$.api);
    }
    return fn || null;
  },
  filterByX(targets, x) {
    return this.getValuesByX(targets).get(this.getXCacheKey(x)) || [];
  },
  filterNullish(data) {
    const filter = (v) => isValue(v.value);
    return data ? data.filter(
      (v) => "value" in v ? filter(v) : v.values.some(filter)
    ) : data;
  },
  filterRemoveNull(data) {
    return data.filter((d) => isValue(this.getBaseValue(d)));
  },
  filterByXDomain(targets, xDomain) {
    return targets.map((t) => ({
      id: t.id,
      id_org: t.id_org,
      values: t.values.filter((v) => xDomain[0] <= v.x && v.x <= xDomain[1])
    }));
  },
  hasDataLabel() {
    const dataLabels = this.config.data_labels;
    return isBoolean(dataLabels) && dataLabels || isObjectType(dataLabels) && notEmpty(dataLabels);
  },
  /**
   * Determine if has null value
   * @param {Array} targets Data array to be evaluated
   * @returns {boolean}
   * @private
   */
  hasNullDataValue(targets) {
    return targets.some(({ value }) => value === null);
  },
  /**
   * Get data index from the event coodinates
   * @param {Event} event Event object
   * @returns {number}
   * @private
   */
  getDataIndexFromEvent(event) {
    const $$ = this;
    const {
      $el,
      config,
      state: { hasRadar, inputType, eventReceiver: { coords, rect } }
    } = $$;
    let index;
    if (hasRadar) {
      let target = event.target;
      if (/tspan/i.test(target.tagName)) {
        target = target.parentNode;
      }
      const d = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
      index = d && Object.keys(d).length === 1 ? d.index : void 0;
    } else {
      const isRotated = config.axis_rotated;
      const scrollPos = getScrollPosition($el.chart.node());
      const e = inputType === "touch" && event.changedTouches ? event.changedTouches[0] : event;
      let point = isRotated ? e.clientY + scrollPos.y : e.clientX + scrollPos.x;
      if (hasViewBox($el.svg)) {
        const pos = [point, 0];
        isRotated && pos.reverse();
        point = getTransformCTM($el.eventRect.node(), ...pos)[isRotated ? "y" : "x"];
      } else {
        point -= isRotated ? rect.top : rect.left;
      }
      index = findIndex(
        coords,
        point,
        0,
        coords.length - 1,
        isRotated
      );
    }
    return index;
  },
  getDataLabelLength(min, max, key) {
    var _a, _b, _c;
    const $$ = this;
    const paddingCoef = 1.3;
    const values = [min, max].map((v) => $$.dataLabelFormat()(v));
    if ($$.config.render_mode === "canvas" && !$$.$el.svg) {
      const chart = (_b = (_a = $$.$el.chart) == null ? void 0 : _a.node) == null ? void 0 : _b.call(_a);
      const doc = chart == null ? void 0 : chart.ownerDocument;
      const svg = doc == null ? void 0 : doc.createElementNS("http://www.w3.org/2000/svg", "svg");
      if (chart && svg) {
        const texts = values.map((value) => {
          const text = doc.createElementNS("http://www.w3.org/2000/svg", "text");
          text.textContent = value;
          svg.appendChild(text);
          return text;
        });
        svg.style.cssText = "position:absolute;visibility:hidden;left:-10000px;top:-10000px;";
        chart.appendChild(svg);
        const lengths = texts.map((text) => text.getBoundingClientRect()[key] * paddingCoef);
        svg.remove();
        return lengths;
      }
    }
    return ((_c = $$.getTextRect(
      values
    )) == null ? void 0 : _c.map((rect) => rect[key] * paddingCoef)) || [0, 0];
  },
  isNoneArc(d) {
    return this.hasTarget(this.data.targets, d.id);
  },
  isArc(d) {
    return "data" in d && this.hasTarget(this.data.targets, d.data.id);
  },
  findSameXOfValues(values, index) {
    const targetX = values[index].x;
    const sames = [];
    let i;
    for (i = index - 1; i >= 0; i--) {
      if (targetX !== values[i].x) {
        break;
      }
      sames.push(values[i]);
    }
    for (i = index; i < values.length; i++) {
      if (targetX !== values[i].x) {
        break;
      }
      sames.push(values[i]);
    }
    return sames;
  },
  /**
   * Get normalized x value cache key.
   * @param {Date|number|string} x X value
   * @returns {number|string} Cache key value
   * @private
   */
  getXCacheKey(x) {
    return isString(x) ? x : +x;
  },
  /**
   * Get data rows grouped by x value.
   * @param {Array} targets Data targets
   * @returns {Map} X-value keyed data rows
   * @private
   */
  getValuesByX(targets) {
    const $$ = this;
    const { cache, state } = $$;
    const targetKey = targets.map((t) => {
      const { values } = t;
      const first = values[0];
      const last = values[values.length - 1];
      return `${t.id}:${values.length}:${first ? $$.getXCacheKey(first.x) : ""}:${last ? $$.getXCacheKey(last.x) : ""}`;
    }).join("|");
    const cached = cache.get(KEY.valuesByX);
    if (cached && cached.generation === state.dataGeneration && cached.targetKey === targetKey) {
      return cached.value;
    }
    const valueMap = /* @__PURE__ */ new Map();
    for (let i = 0; i < targets.length; i++) {
      const values = targets[i].values;
      for (let j = 0; j < values.length; j++) {
        const v = values[j];
        const x = $$.getXCacheKey(v.x);
        const rows = valueMap.get(x);
        rows ? rows.push(v) : valueMap.set(x, [v]);
      }
    }
    cache.add(KEY.valuesByX, {
      generation: state.dataGeneration,
      targetKey,
      value: valueMap
    });
    return valueMap;
  },
  /**
   * Get candidate values near the current pointer position.
   * @param {Array} values Data values
   * @param {Array} pos Pointer position
   * @param {boolean} useSortedIndex Whether values are sorted target values
   * @returns {Array} Candidate values
   * @private
   */
  getClosestCandidates(values, pos, useSortedIndex = true) {
    const $$ = this;
    const { config, scale } = $$;
    const len = values.length;
    const first = values[0];
    if (!useSortedIndex || len < 200 || !first || !config.data_xSort) {
      return values;
    }
    const isBar = $$.isBarType(first.id);
    const isCandle = $$.isCandlestickType(first.id);
    const sensitivity = config.point_sensitivity;
    if (!(isBar || isCandle) && !isNumber(sensitivity)) {
      return values;
    }
    const xScale = scale.zoom || scale.x;
    const pointerX = pos[+config.axis_rotated];
    const isAscending = xScale(values[0].x) <= xScale(values[len - 1].x);
    let start = 0;
    let end = len - 1;
    while (start < end) {
      const mid = start + end >> 1;
      const x = xScale(values[mid].x);
      if (isAscending ? x < pointerX : x > pointerX) {
        start = mid + 1;
      } else {
        end = mid;
      }
    }
    const candidates = [];
    const visited = /* @__PURE__ */ new Set();
    const add = (index) => {
      if (index >= 0 && index < len && !visited.has(index)) {
        visited.add(index);
        candidates.push(values[index]);
      }
    };
    const addSameX = (index) => {
      if (index < 0 || index >= len) {
        return;
      }
      const x = $$.getXCacheKey(values[index].x);
      let i = index;
      while (i >= 0 && $$.getXCacheKey(values[i].x) === x) {
        add(i--);
      }
      i = index + 1;
      while (i < len && $$.getXCacheKey(values[i].x) === x) {
        add(i++);
      }
    };
    if (isBar || isCandle) {
      for (let i = start - 2; i <= start + 2; i++) {
        addSameX(i);
      }
    } else {
      const maxDx = sensitivity;
      const scan = (index, direction) => {
        for (let i = index; i >= 0 && i < len; i += direction) {
          const v = values[i];
          if (Math.abs(xScale(v.x) - pointerX) > maxDx) {
            break;
          }
          add(i);
        }
      };
      scan(start, 1);
      scan(start - 1, -1);
    }
    return candidates;
  },
  findClosestFromTargets(targets, pos) {
    const $$ = this;
    const candidates = [];
    for (let i = 0; i < targets.length; i++) {
      const closest = $$.findClosest(targets[i].values, pos);
      closest && candidates.push(closest);
    }
    return $$.findClosest(candidates, pos, false);
  },
  findClosest(values, pos, useSortedIndex = true) {
    const $$ = this;
    const { $el: { main } } = $$;
    const data = $$.getClosestCandidates(values, pos, useSortedIndex);
    let minDist;
    let closest;
    for (let i = 0; i < data.length; i++) {
      const v = data[i];
      if (!v || !isValue(v.value)) {
        continue;
      }
      const isBar = $$.isBarType(v.id);
      const isCandle = $$.isCandlestickType(v.id);
      if (isBar || isCandle) {
        const selector = isBar ? `.${$BAR.chartBar}.${$COMMON.target}${$$.getTargetSelectorSuffix(v.id)} .${$BAR.bar}-${v.index}` : `.${$CANDLESTICK.chartCandlestick}.${$COMMON.target}${$$.getTargetSelectorSuffix(v.id)} .${$CANDLESTICK.candlestick}-${v.index} path`;
        if (!closest && $$.isWithinBar(main.select(selector).node())) {
          closest = v;
        }
      } else {
        const d = $$.dist(v, pos);
        const sensitivity = $$.getPointSensitivity(v);
        if (d < sensitivity && (minDist === void 0 || d < minDist)) {
          minDist = d;
          closest = v;
        }
      }
    }
    return closest;
  },
  dist(data, pos) {
    const $$ = this;
    const { config: { axis_rotated: isRotated }, scale } = $$;
    const xIndex = +isRotated;
    const yIndex = +!isRotated;
    const y = $$.circleY(data, data.index);
    const x = (scale.zoom || scale.x)(data.x);
    const dx = x - pos[xIndex];
    const dy = y - pos[yIndex];
    return Math.sqrt(dx * dx + dy * dy);
  },
  /**
   * Convert data for step type
   * @param {Array} values Object data values
   * @returns {Array}
   * @private
   */
  convertValuesToStep(values) {
    const $$ = this;
    const { axis, config } = $$;
    const stepType = config.line_step_type;
    const isCategorized = axis ? axis.isCategorized() : false;
    const converted = isArray(values) ? values.concat() : [values];
    if (!(isCategorized || /step\-(after|before)/.test(stepType))) {
      return values;
    }
    if (converted.length) {
      const head = converted[0];
      const tail = converted[converted.length - 1];
      const { id } = head;
      let { x } = head;
      converted.unshift({ x: --x, value: head.value, id });
      isCategorized && stepType === "step-after" && converted.unshift({ x: x - 1, value: head.value, id });
      x = tail.x;
      converted.push({ x: ++x, value: tail.value, id });
      isCategorized && stepType === "step-before" && converted.push({ x: x + 1, value: tail.value, id });
    }
    return converted;
  },
  convertValuesToRange(values) {
    const converted = isArray(values) ? values.concat() : [values];
    const ranges = [];
    converted.forEach((range) => {
      const { x, id } = range;
      ranges.push({
        x,
        id,
        value: range.value[0]
      });
      ranges.push({
        x,
        id,
        value: range.value[2]
      });
    });
    return ranges;
  },
  updateDataAttributes(name, attrs) {
    const $$ = this;
    const { config } = $$;
    const current = config[`data_${name}`];
    if (isUndefined(attrs)) {
      return current;
    }
    Object.keys(attrs).forEach((id) => {
      current[id] = attrs[id];
    });
    $$.redraw({ withLegend: true });
    return current;
  },
  getRangedData(d, key = "", type = "areaRange") {
    var _a, _b;
    const value = d == null ? void 0 : d.value;
    if (isArray(value)) {
      if (type === "bar") {
        return value.reduce((a, c) => c - a);
      } else {
        const index = (_b = (_a = rangedDataKeyIndex[type]) == null ? void 0 : _a[key]) != null ? _b : -1;
        return index >= 0 ? value[index] : void 0;
      }
    } else if (value && key) {
      return value[key];
    }
    return value;
  },
  /**
   * Set ratio for grouped data
   * @param {Array} data Data array
   * @private
   */
  setRatioForGroupedData(data) {
    const $$ = this;
    const { config } = $$;
    if (config.data_groups.length && data.some((d) => $$.isGrouped(d.id))) {
      const setter = (d) => $$.getRatio("index", d, true);
      data.forEach((v) => {
        "values" in v ? v.values.forEach(setter) : setter(v);
      });
    }
  },
  /**
   * Get ratio value
   * @param {string} type Ratio for given type
   * @param {object} d Data value object
   * @param {boolean} asPercent Convert the return as percent or not
   * @returns {number} Ratio value
   * @private
   */
  getRatio(type, d, asPercent = false) {
    const $$ = this;
    const { config, state } = $$;
    const api = $$.api;
    let ratio = 0;
    if (d && api.data.shown().length) {
      ratio = d.ratio || d.value;
      if (type === "arc") {
        if ($$.pie.padAngle()()) {
          ratio = d.value / $$.getTotalDataSum(true);
        } else {
          const gaugeArcLength = config.gauge_fullCircle ? $$.getArcLength() : $$.getStartingAngle() * -2;
          const arcLength = $$.hasType("gauge") ? gaugeArcLength : Math.PI * 2;
          ratio = (d.endAngle - d.startAngle) / arcLength;
        }
      } else if (type === "index") {
        const total = $$.getVisibleTotalPerIndex(
          $$.isStackNormalizedPerGroup() ? d.id : void 0
        );
        if (total === null) {
          return ratio;
        }
        const divisor = total[d.index];
        d.ratio = isNumber(d.value) && total && divisor ? d.value / divisor : 0;
        ratio = d.ratio;
      } else if (type === "radar") {
        ratio = parseFloat(String(Math.max(d.value, 0))) / state.current.dataMax * config.radar_size_ratio;
      } else if (type === "bar") {
        const yScale = $$.getYScaleById.bind($$)(d.id);
        const max = yScale.domain().reduce((a, c) => c - a);
        ratio = max === 0 ? 0 : Math.abs(
          $$.getRangedData(d, null, type) / max
        );
      } else if (type === "treemap") {
        ratio /= $$.getTotalDataSum(true);
      }
    }
    return asPercent && ratio ? ratio * 100 : ratio;
  },
  /**
   * Sort data index to be aligned with x axis.
   * @param {Array} tickValues Tick array values
   * @private
   */
  updateDataIndexByX(tickValues) {
    const $$ = this;
    const tickValueMap = tickValues.reduce((out, tick, index) => {
      out[Number(tick.x)] = index;
      return out;
    }, {});
    $$.data.targets.forEach((t) => {
      t.values.forEach((value, valueIndex) => {
        let index = tickValueMap[Number(value.x)];
        if (index === void 0) {
          index = valueIndex;
        }
        value.index = index;
      });
    });
  },
  /**
   * Determine if bubble has dimension data
   * @param {object|Array} d data value
   * @returns {boolean}
   * @private
   */
  isBubbleZType(d) {
    const $$ = this;
    return $$.isBubbleType(d) && (isObject(d.value) && ("z" in d.value || "y" in d.value) || isArray(d.value) && d.value.length >= 2);
  },
  /**
   * Determine if bar has ranged data
   * @param {Array} d data value
   * @returns {boolean}
   * @private
   */
  isBarRangeType(d) {
    var _a;
    const $$ = this;
    const { value } = d;
    return $$.isBarType(d) && !((_a = $$.isSubchartSourceTypeOf) == null ? void 0 : _a.call($$, d, TYPE.CANDLESTICK)) && isArray(value) && value.length >= 2 && value.every(isNumber);
  },
  /**
   * Get data object by id
   * @param {string} id data id
   * @returns {object}
   * @private
   */
  getDataById(id) {
    var _a;
    const d = this.cache.get(id) || this.api.data(id);
    return (_a = d == null ? void 0 : d[0]) != null ? _a : d;
  }
});

;// ./src/ChartInternal/data/load.ts



function callDone(fn, resizeAfter = false) {
  const $$ = this;
  const { api } = $$;
  resizeAfter && $$.api.flush(true);
  fn == null ? void 0 : fn.call(api);
}
/* harmony default export */ var load = ({
  load(rawTargets, args) {
    const $$ = this;
    const { axis, data, org, scale } = $$;
    const { append } = args;
    const zoomState = {
      domain: null,
      currentDomain: null,
      x: null
    };
    let targets = rawTargets;
    if (targets) {
      if (args.filter) {
        targets = targets.filter(args.filter);
      }
      if (args.type || args.types) {
        targets.forEach((t) => {
          var _a;
          const type = ((_a = args.types) == null ? void 0 : _a[t.id]) || args.type;
          $$.setTargetType(t.id, type);
        });
      }
      const incoming = new Map(targets.map((t) => [t.id, t]));
      data.targets.forEach((d) => {
        const t = incoming.get(d.id);
        if (t) {
          if (append) {
            const values = t.values;
            for (let j = 0; j < values.length; j++) {
              d.values.push(values[j]);
            }
          } else {
            d.values = t.values;
          }
          incoming.delete(d.id);
        }
      });
      incoming.forEach((t) => data.targets.push(t));
    }
    if ($$.state.isCanvasMode) {
      $$.redraw({
        withUpdateOrgXDomain: true,
        withUpdateXDomain: true,
        withLegend: true
      });
      $$.updateTypesElements();
      callDone.call($$, args.done, args.resizeAfter);
      return;
    }
    $$.updateTargets(data.targets);
    if (scale.zoom) {
      zoomState.x = axis.isCategorized() ? scale.x.orgScale() : (org.xScale || scale.x).copy();
      zoomState.domain = $$.getXDomain(data.targets);
      zoomState.x.domain(zoomState.domain);
      zoomState.currentDomain = $$.zoom.getDomain();
      if (!$$.withinRange(zoomState.currentDomain, void 0, zoomState.domain)) {
        scale.x.domain(zoomState.domain);
        scale.zoom = null;
        $$.$el.eventRect.property("__zoom", null);
      }
    }
    $$.redraw({
      withUpdateOrgXDomain: true,
      withUpdateXDomain: true,
      withLegend: true
    });
    if (scale.zoom) {
      org.xDomain = zoomState.domain;
      org.xScale = zoomState.x;
      if (axis.isCategorized()) {
        zoomState.currentDomain = $$.getZoomDomainValue(zoomState.currentDomain);
        org.xDomain = $$.getZoomDomainValue(org.xDomain);
        org.xScale = zoomState.x.domain(org.xDomain);
      }
      $$.updateCurrentZoomTransform(zoomState.x, zoomState.currentDomain);
    } else if (org.xScale) {
      org.xScale.domain(org.xDomain);
    }
    $$.updateTypesElements();
    callDone.call($$, args.done, args.resizeAfter);
  },
  loadFromArgs(args) {
    const $$ = this;
    if (!$$.config) {
      return;
    }
    $$.cache.reset(false, [
      KEY.filteredTargets,
      KEY.maxDataCountTarget,
      KEY.valuesXIndexMap,
      KEY.maxTickSize
    ]);
    $$.convertData(args, (d) => {
      const data = args.data || d;
      args.append && (data.__append__ = true);
      data && $$.load($$.convertDataToTargets.call($$, data), args);
    });
  },
  unload(rawTargetIds, customDoneCb) {
    var _a;
    const $$ = this;
    const { state, $el, $T } = $$;
    const hasLegendDefsPoint = !!((_a = $$.hasLegendDefsPoint) == null ? void 0 : _a.call($$));
    let done = customDoneCb;
    let targetIds = rawTargetIds;
    $$.cache.reset(false, [
      KEY.filteredTargets,
      KEY.maxDataCountTarget,
      KEY.valuesXIndexMap,
      KEY.maxTickSize
    ]);
    if (!done) {
      done = () => {
      };
    }
    targetIds = targetIds.filter((id) => $$.hasTarget($$.data.targets, id));
    if (targetIds.length === 0) {
      done();
      return;
    }
    const unloadIds = new Set(targetIds);
    if (state.isCanvasMode) {
      targetIds.forEach((id) => {
        state.withoutFadeIn[id] = false;
      });
      $$.data.targets = $$.data.targets.filter((t) => !unloadIds.has(t.id));
      $$.removeHiddenTargetIds(targetIds);
      $$.removeHiddenLegendIds(targetIds);
      $$.updateTypesElements();
      done();
      return;
    }
    targetIds.forEach((id) => {
      var _a2;
      const suffixId = $$.getTargetSelectorSuffix(id);
      state.withoutFadeIn[id] = false;
      if ($el.legend) {
        $el.legend.selectAll(`.${$LEGEND.legendItem}${suffixId}`).remove();
      }
      hasLegendDefsPoint && ((_a2 = $el.defs) == null ? void 0 : _a2.select(`#${$$.getDefsPointId(suffixId)}`).remove());
    });
    $$.data.targets = $$.data.targets.filter((t) => !unloadIds.has(t.id));
    state.hasFunnel && $$.updateFunnel($$.data.targets);
    state.hasTreemap && $$.updateTargetsForTreemap($$.data.targets);
    $$.updateTypesElements();
    const targets = $el.svg.selectAll(targetIds.map((id) => $$.selectorTarget(id)));
    $T(targets).style("opacity", "0").remove().call(endall, done);
  }
});

// EXTERNAL MODULE: external {"commonjs":"d3-drag","commonjs2":"d3-drag","amd":"d3-drag","root":"d3"}
var external_commonjs_d3_drag_commonjs2_d3_drag_amd_d3_drag_root_d3_ = __webpack_require__(6);
;// ./src/ChartInternal/interactions/interaction.ts





/* harmony default export */ var interactions_interaction = ({
  /**
   * Expand data shape/point
   * @param {number} index Index number
   * @param {string} id Data id
   * @param {boolean} reset Reset expand state
   * @private
   */
  setExpand(index, id, reset) {
    const $$ = this;
    const { config, $el: { circle } } = $$;
    circle && config.point_focus_expand_enabled && $$.expandCircles(index, id, reset);
    $$.expandBarTypeShapes(true, index, id, reset);
  },
  /**
   * Expand/Unexpand bar type shapes
   * @param {boolean} expand Expand or unexpand
   * @param {number} i Shape index
   * @param {string} id Data id
   * @param {boolean} reset Reset expand style
   * @private
   */
  expandBarTypeShapes(expand = true, i, id, reset) {
    const $$ = this;
    ["bar", "candlestick"].filter((v) => $$.$el[v]).forEach((v) => {
      reset && $$.$el[v].classed($COMMON.EXPANDED, false);
      $$.getShapeByIndex(v, i, id).classed($COMMON.EXPANDED, expand);
    });
  },
  /**
   * Handle data.onover/out callback options
   * @param {boolean} isOver Over or not
   * @param {number|object} d data object
   * @private
   */
  setOverOut(isOver, d) {
    const $$ = this;
    const { config, state: { hasFunnel, hasRadar, hasTreemap }, $el: { main } } = $$;
    const isArcishData = isObject(d);
    if (isArcishData || d !== -1) {
      const callback = config[isOver ? "data_onover" : "data_onout"].bind($$.api);
      config.color_onover && $$.setOverColor(isOver, d, isArcishData);
      if (isArcishData) {
        const suffix = $$.getTargetSelectorSuffix(d.id);
        const selector = hasFunnel || hasTreemap ? `${$COMMON.target + suffix} .${$SHAPE.shape}` : $ARC.arc + suffix;
        callback(d, main.select(`.${selector}`).node());
      } else if (!config.tooltip_grouped) {
        const last = $$.cache.get(KEY.setOverOut) || [];
        const shapesAtIndex = main.selectAll(`.${$SHAPE.shape}-${d}`).filter(function(d2) {
          return $$.isWithinShape(this, d2);
        });
        const shape = shapesAtIndex.filter(function() {
          return last.every((v) => v !== this);
        });
        if (!isOver || shapesAtIndex.empty() || last.length === shape.size() && shape.nodes().every((v, i) => v !== last[i])) {
          while (last.length) {
            const target = last.pop();
            config.data_onout.bind($$.api)((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum(), target);
          }
        }
        shape.each(function() {
          if (isOver) {
            callback((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).datum(), this);
            last.push(this);
          }
        });
        $$.cache.add(KEY.setOverOut, last);
      } else {
        if (isOver) {
          hasRadar && $$.isPointFocusOnly() ? $$.showCircleFocus($$.getAllValuesOnIndex(d, true)) : $$.setExpand(d, null, true);
        }
        !$$.isMultipleX() && main.selectAll(`.${$SHAPE.shape}-${d}`).each(function(d2) {
          callback(d2, this);
        });
      }
    }
  },
  /**
   * Call data.onover/out callback for touch event
   * @param {number|object} d target index or data object for Arc type
   * @private
   */
  callOverOutForTouch(d) {
    const $$ = this;
    const last = $$.cache.get(KEY.callOverOutForTouch);
    if (isObject(d) && last ? d.id !== last.id : d !== last) {
      (last || isNumber(last)) && $$.setOverOut(false, last);
      (d || isNumber(d)) && $$.setOverOut(true, d);
      $$.cache.add(KEY.callOverOutForTouch, d);
    }
  },
  /**
   * Return draggable selection function
   * @returns {function}
   * @private
   */
  getDraggableSelection() {
    const $$ = this;
    const { config, state } = $$;
    return config.interaction_enabled && config.data_selection_draggable && $$.drag ? (0,external_commonjs_d3_drag_commonjs2_d3_drag_amd_d3_drag_root_d3_.drag)().on("drag", function(event) {
      state.event = event;
      $$.drag(getPointer(event, this));
    }).on("start", function(event) {
      state.event = event;
      $$.dragstart(getPointer(event, this));
    }).on("end", (event) => {
      state.event = event;
      $$.dragend();
    }) : () => {
    };
  },
  /**
   * Dispatch a mouse event.
   * @private
   * @param {string} type event type
   * @param {number} index Index of eventRect
   * @param {Array} mouse x and y coordinate value
   */
  dispatchEvent(type, index, mouse) {
    var _a, _b, _c;
    const $$ = this;
    const {
      config,
      state: {
        eventReceiver,
        hasAxis,
        hasFunnel,
        hasRadar,
        hasTreemap
      },
      $el: { eventRect, funnel, radar, svg, treemap }
    } = $$;
    let element = (_c = (_b = (hasFunnel || hasTreemap) && eventReceiver.rect || hasRadar && radar.axes.select(`.${$AXIS.axis}-${index} text`) || (eventRect || ((_a = $$.getArcElementByIdOrIndex) == null ? void 0 : _a.call($$, index)))) == null ? void 0 : _b.node) == null ? void 0 : _c.call(_b);
    if (element) {
      const isMultipleX = $$.isMultipleX();
      const isRotated = config.axis_rotated;
      let { width, left, top } = getBoundingRect(element);
      if (hasAxis && !hasRadar && !isMultipleX) {
        const coords = eventReceiver.coords[index];
        if (coords) {
          width = coords.w;
          left += coords.x;
          top += coords.y;
        } else {
          width = 0;
          left = 0;
          top = 0;
        }
      }
      let x = left + (mouse ? mouse[0] : 0) + (isMultipleX || isRotated ? 0 : width / 2);
      let y = top + (mouse ? mouse[1] : 0) + (isRotated ? 4 : 0);
      if (hasViewBox(svg) && $$.$el.eventRect) {
        const ctm = getTransformCTM($$.$el.eventRect.node(), x, y, false);
        x = ctm.x;
        y = ctm.y;
      }
      const params = {
        screenX: x,
        screenY: y,
        clientX: x,
        clientY: y,
        bubbles: hasRadar
        // radar type needs to bubble up event
      };
      if (hasFunnel || hasTreemap) {
        element = (funnel != null ? funnel : treemap).node();
      }
      emulateEvent[/^(mouse|click)/.test(type) ? "mouse" : "touch"](
        element,
        type,
        params
      );
    }
  },
  setDragStatus(isDragging) {
    this.state.dragging = isDragging;
  },
  /**
   * Unbind zoom events
   * @private
   */
  unbindZoomEvent() {
    const $$ = this;
    const { $el: { canvas, eventRect, svg, zoomResetBtn } } = $$;
    eventRect == null ? void 0 : eventRect.on(".zoom wheel.zoom .drag", null);
    canvas == null ? void 0 : canvas.on(".zoom wheel.zoom .drag", null);
    svg == null ? void 0 : svg.on("wheel", null);
    zoomResetBtn == null ? void 0 : zoomResetBtn.on("click", null).style("display", "none");
  },
  /**
   * Unbind all attached events
   * @private
   */
  unbindAllEvents() {
    var _a;
    const $$ = this;
    const { $el: { arcs, eventRect, legend, region, svg, treemap }, brush } = $$;
    const list = [
      "wheel",
      "click",
      "mouseover",
      "mousemove",
      "mouseout",
      "touchstart",
      "touchmove",
      "touchend",
      "touchstart.eventRect",
      "touchmove.eventRect",
      "touchend.eventRect",
      ".brush",
      ".drag",
      ".zoom",
      "wheel.zoom",
      "dblclick.zoom"
    ].join(" ");
    [
      svg,
      eventRect,
      region == null ? void 0 : region.list,
      brush == null ? void 0 : brush.getSelection(),
      arcs == null ? void 0 : arcs.selectAll("path"),
      legend == null ? void 0 : legend.selectAll("g"),
      treemap
    ].forEach((v) => v == null ? void 0 : v.on(list, null));
    (_a = $$.unbindZoomEvent) == null ? void 0 : _a.call($$);
  }
});

;// ./src/ChartInternal/internals/category.ts
/* harmony default export */ var category = ({
  /**
   * Category Name
   * @param {number} i Index number
   * @returns {string} category Name
   * @private
   */
  categoryName(i) {
    var _a;
    const { axis_x_categories } = this.config;
    return (_a = axis_x_categories == null ? void 0 : axis_x_categories[i]) != null ? _a : i;
  }
});

;// ./src/ChartInternal/internals/class.ts

const RE_SELECTOR_SUFFIX = /[\x00-\x20\x7F-\xA0\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g;
/* harmony default export */ var internals_class = ({
  generateClass(prefix, targetId) {
    const cache = this.state.generateClassCache;
    const key = `${prefix}\0${targetId}`;
    let cls = cache.get(key);
    if (!cls) {
      cls = ` ${prefix} ${prefix + this.getTargetSelectorSuffix(targetId)}`;
      cache.set(key, cls);
    }
    return cls;
  },
  /**
   * Get class string
   * @param {string} type Shape type
   * @param {boolean} withShape Get with shape prefix
   * @returns {string} Class string
   * @private
   */
  getClass(type, withShape) {
    const isPlural = /s$/.test(type);
    const useIdKey = /^(area|arc|line|funnel|treemap)s?$/.test(type);
    const key = isPlural ? "id" : "index";
    return (d) => {
      const data = d.data || d;
      const result = (withShape ? this.generateClass(config_classes[isPlural ? "shapes" : "shape"], data[key]) : "") + this.generateClass(config_classes[type], data[useIdKey ? "id" : key]);
      return result.trim();
    };
  },
  /**
   * Get chart class string
   * @param {string} type Shape type
   * @returns {string} Class string
   * @private
   */
  getChartClass(type) {
    return (d) => config_classes[`chart${type}`] + this.classTarget((d.data ? d.data : d).id);
  },
  generateExtraLineClass() {
    const $$ = this;
    const classes = $$.config.line_classes || [];
    const ids = [];
    return function(d) {
      var _a;
      const id = d.id || ((_a = d.data) == null ? void 0 : _a.id) || d;
      if (ids.indexOf(id) < 0) {
        ids.push(id);
      }
      return classes[ids.indexOf(id) % classes.length];
    };
  },
  classRegion(d, i) {
    return `${this.generateClass(config_classes.region, i)} ${"class" in d ? d.class : ""}`;
  },
  classTarget(id) {
    const additionalClassSuffix = this.config.data_classes[id];
    let additionalClass = "";
    if (additionalClassSuffix) {
      additionalClass = ` ${config_classes.target}-${additionalClassSuffix}`;
    }
    return this.generateClass(config_classes.target, id) + additionalClass;
  },
  classFocus(d) {
    return this.classFocused(d) + this.classDefocused(d);
  },
  classFocused(d) {
    return ` ${this.state.focusedTargetIds.has(d.id) ? config_classes.focused : ""}`;
  },
  classDefocused(d) {
    return ` ${this.state.defocusedTargetIds.has(d.id) ? config_classes.defocused : ""}`;
  },
  getTargetSelectorSuffix(targetId) {
    const targetStr = targetId || targetId === 0 ? `-${targetId}` : "";
    return targetStr.replace(RE_SELECTOR_SUFFIX, "-");
  },
  selectorTarget(id, prefix = "", postfix = "") {
    const target = this.getTargetSelectorSuffix(id);
    return `${prefix}.${config_classes.target + target} ${postfix}, ${prefix}.${config_classes.circles + target} ${postfix}`;
  },
  selectorTargets(idsValue, prefix) {
    const ids = idsValue || [];
    return ids.length ? ids.map((id) => this.selectorTarget(id, prefix)) : null;
  },
  selectorLegend(id) {
    return `.${config_classes.legendItem + this.getTargetSelectorSuffix(id)}`;
  },
  selectorLegends(ids) {
    return (ids == null ? void 0 : ids.length) ? ids.map((id) => this.selectorLegend(id)) : null;
  }
});

;// ./src/ChartInternal/internals/color.ts





const _colorizePattern = (pattern, color, id) => {
  const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(pattern.cloneNode(true));
  node.attr("id", id).insert("rect", ":first-child").attr("width", node.attr("width")).attr("height", node.attr("height")).style("fill", color);
  return {
    id,
    node: node.node()
  };
};
function _getColorFromCss(element) {
  const cacheKey = KEY.colorPattern;
  const { body } = browser_doc;
  let pattern = body[cacheKey];
  if (!pattern) {
    const delimiter = ";";
    const content = element.classed($COLOR.colorPattern, true).style("background-image");
    element.classed($COLOR.colorPattern, false);
    if (content.indexOf(delimiter) > -1) {
      pattern = content.replace(/url[^#]*|["'()]|(\s|%20)/g, "").split(delimiter).map((v) => v.trim().replace(/[\"'\s]/g, "")).filter(Boolean);
      body[cacheKey] = pattern;
    }
  }
  return pattern;
}
const schemeCategory10 = [
  "#1f77b4",
  "#ff7f0e",
  "#2ca02c",
  "#d62728",
  "#9467bd",
  "#8c564b",
  "#e377c2",
  "#7f7f7f",
  "#bcbd22",
  "#17becf"
];
/* harmony default export */ var internals_color = ({
  generateColor() {
    const $$ = this;
    const { $el, config } = $$;
    const ids = [];
    const hasGradient = config.area_linearGradient || config.bar_linearGradient || config.point_radialGradient;
    let pattern = notEmpty(config.color_pattern) ? config.color_pattern : [..._getColorFromCss($el.chart) || schemeCategory10];
    const originalColorPattern = pattern;
    if (isFunction(config.color_tiles)) {
      const tiles = config.color_tiles.bind($$.api)();
      const colorizedPatterns = pattern.map((p, index) => {
        const color = p.replace(/[#\(\)\s,]/g, "");
        const id = `${$$.state.datetimeId}-pattern-${color}-${index}`;
        return _colorizePattern(tiles[index % tiles.length], p, id);
      });
      pattern = colorizedPatterns.map((p) => `url(#${p.id})`);
      $$.patterns = colorizedPatterns;
    }
    return function(d) {
      var _a;
      const colors = config.data_colors;
      const callback = config.data_color;
      const id = d.id || ((_a = d.data) == null ? void 0 : _a.id) || d;
      const isLine = $$.isTypeOf(id, ["line", "spline", "step"]) || !config.data_types[id];
      let color;
      if (isFunction(colors[id])) {
        color = colors[id].bind($$.api)(d);
      } else if (colors[id]) {
        color = colors[id];
      } else {
        let idx = ids.indexOf(id);
        if (idx < 0) {
          ids.push(id);
          idx = ids.length - 1;
        }
        color = isLine ? originalColorPattern[idx % originalColorPattern.length] : pattern[idx % pattern.length];
        colors[id] = color;
      }
      color = isFunction(callback) ? callback.call($$.api, color, d) : color;
      if (hasGradient && $el.defs) {
        const stop = $$.$el.defs.selectAll(
          `[id$='-gradient${$$.getTargetSelectorSuffix(id)}'] stop`
        );
        let hasSameColor;
        stop.each(function(d2, i) {
          hasSameColor = i === 0 ? this.style.stopColor : this.style.stopColor === hasSameColor;
        });
        hasSameColor === true && stop.attr("stop-color", color);
      }
      return color;
    };
  },
  generateLevelColor() {
    const $$ = this;
    const { config } = $$;
    const colors = config.color_pattern;
    const threshold = config.color_threshold;
    const asValue = threshold.unit === "value";
    const max = threshold.max || 100;
    const values = threshold.values && threshold.values.length ? threshold.values : [];
    return notEmpty(threshold) ? function(value) {
      const v = asValue ? value : value * 100 / max;
      let color = colors[colors.length - 1];
      for (let i = 0, l = values.length; i < l; i++) {
        if (v <= values[i]) {
          color = colors[i];
          break;
        }
      }
      return color;
    } : null;
  },
  /**
   * Append data backgound color filter definition
   * @param {string|object|function} color Color string, object, or function
   * @param {object} attr filter attribute
   * @private
   */
  generateTextBGColorFilter(color, attr = {
    x: 0,
    y: 0,
    width: 1,
    height: 1
  }) {
    const $$ = this;
    const { $el: { defs }, state } = $$;
    if (color) {
      let ids = [];
      if (isString(color)) {
        ids.push("");
      } else if (isObject(color)) {
        ids = Object.keys(color);
      } else if (isFunction(color)) {
        ids = $$.mapToTargetIds();
      }
      ids.forEach((v) => {
        const id = `${state.datetimeId}-labels-bg${$$.getTargetSelectorSuffix(v)}${isString(color) ? $$.getTargetSelectorSuffix(color) : ""}`;
        const colorValue = sanitize(v === "" ? color : (color == null ? void 0 : color[v]) || "");
        if (defs.select(`#${id}`).empty()) {
          const filter = defs.append("filter").attr("x", attr.x).attr("y", attr.y).attr("width", attr.width).attr("height", attr.height).attr("id", id);
          filter.append("feFlood").attr("flood-color", colorValue);
          filter.append("feComposite").attr("in", "SourceGraphic");
        }
      });
    }
  },
  /**
   * Get data gradient color url
   * @param {string} id Data id
   * @returns {string}
   * @private
   */
  getGradienColortUrl(id) {
    return `url(#${this.state.datetimeId}-gradient${this.getTargetSelectorSuffix(id)})`;
  },
  /**
   * Update linear/radial gradient definition
   * - linear: area & bar only
   * - radial: type which has data points only
   * @private
   */
  updateLinearGradient() {
    const $$ = this;
    const { config, data: { targets }, state: { datetimeId }, $el: { defs } } = $$;
    targets.forEach((d) => {
      const id = `${datetimeId}-gradient${$$.getTargetSelectorSuffix(d.id)}`;
      const radialGradient = $$.hasPointType() && config.point_radialGradient;
      const supportedType = $$.isAreaType(d) && "area" || $$.isBarType(d) && "bar";
      if ((radialGradient || supportedType) && defs.select(`#${id}`).empty()) {
        const color = $$.color(d);
        const gradient = {
          defs: null,
          stops: []
        };
        if (radialGradient) {
          const {
            cx = 0.3,
            cy = 0.3,
            r = 0.7,
            stops = [[0.1, color, 0], [0.9, color, 1]]
          } = radialGradient;
          gradient.stops = stops;
          gradient.defs = defs.append("radialGradient").attr("id", `${id}`).attr("cx", cx).attr("cy", cy).attr("r", r);
        } else {
          const isRotated = config.axis_rotated;
          const {
            x = isRotated ? [1, 0] : [0, 0],
            y = isRotated ? [0, 0] : [0, 1],
            stops = [[0, color, 1], [1, color, 0]]
          } = config[`${supportedType}_linearGradient`];
          gradient.stops = stops;
          gradient.defs = defs.append("linearGradient").attr("id", `${id}`).attr("x1", x[0]).attr("x2", x[1]).attr("y1", y[0]).attr("y2", y[1]);
        }
        gradient.stops.forEach((v) => {
          const [offset, stopColor, stopOpacity] = v;
          const colorValue = isFunction(stopColor) ? stopColor.bind($$.api)(d.id) : stopColor;
          gradient.defs && gradient.defs.append("stop").attr("offset", offset).attr("stop-color", colorValue || color).attr("stop-opacity", stopOpacity);
        });
      }
    });
  },
  /**
   * Set the data over color.
   * When is out, will restate in its previous color value
   * @param {boolean} isOver true: set overed color, false: restore
   * @param {number|object} d target index or data object for Arc type
   * @private
   */
  setOverColor(isOver, d) {
    const $$ = this;
    const { config, $el: { main } } = $$;
    const onover = config.color_onover;
    let color = isOver ? onover : $$.color;
    if (isObject(color)) {
      color = ({ id }) => id in onover ? onover[id] : $$.color(id);
    } else if (isString(color)) {
      color = () => onover;
    } else if (isFunction(onover)) {
      color = color.bind($$.api);
    }
    main.selectAll(
      isObject(d) ? (
        // when is Arc type
        `.${$ARC.arc}${$$.getTargetSelectorSuffix(d.id)}`
      ) : `.${$SHAPE.shape}-${d}`
    ).style("fill", color);
  }
});

// EXTERNAL MODULE: external {"commonjs":"d3-brush","commonjs2":"d3-brush","amd":"d3-brush","root":"d3"}
var external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_ = __webpack_require__(7);
;// ./src/module/util/brush.ts

function getBrushSelection(ctx) {
  const { event, $el } = ctx;
  const main = $el.subchart.main || $el.main;
  let selection;
  if (event && event.type === "brush") {
    selection = event.selection;
  } else if (main && (selection = main.select(".bb-brush").node())) {
    selection = (0,external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_.brushSelection)(selection);
  }
  return selection;
}
function brushEmpty(ctx) {
  const selection = getBrushSelection(ctx);
  if (selection) {
    return selection[0] === selection[1];
  }
  return true;
}


;// ./src/ChartInternal/internals/domain.ts



function getTargetDomainCacheKey($$, targets) {
  return targets.map((target) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i;
    const { values } = target;
    const first = values[0];
    const last = values[values.length - 1];
    const firstX = first ? (_b = (_a = $$.getXCacheKey) == null ? void 0 : _a.call($$, first.x)) != null ? _b : first.x : "";
    const lastX = last ? (_d = (_c = $$.getXCacheKey) == null ? void 0 : _c.call($$, last.x)) != null ? _d : last.x : "";
    const targetType = (_f = (_e = $$.getTargetType) == null ? void 0 : _e.call($$, target)) != null ? _f : "";
    const sourceType = (_i = (_h = (_g = $$.state) == null ? void 0 : _g.subchartSourceTypes) == null ? void 0 : _h[target.id]) != null ? _i : "";
    return `${target.id}:${targetType}:${sourceType}:${values.length}:${firstX}:${lastX}`;
  }).join("|");
}
function canCacheTargetDomain($$, targets) {
  var _a;
  const sourceTargets = (_a = $$.data) == null ? void 0 : _a.targets;
  if (!sourceTargets) {
    return false;
  }
  for (let i = 0; i < targets.length; i++) {
    const target = targets[i];
    const source = sourceTargets.find((v) => v.id === target.id);
    if (!source || source.values !== target.values) {
      return false;
    }
  }
  return true;
}
function updateMinMax(minMax, value) {
  if (!notEmpty(value)) {
    return;
  }
  if (minMax.min === void 0 || value < minMax.min) {
    minMax.min = value;
  }
  if (minMax.max === void 0 || value > minMax.max) {
    minMax.max = value;
  }
}
function updateMinMaxFromValues(minMax, values) {
  for (let i = 0; i < values.length; i++) {
    updateMinMax(minMax, values[i]);
  }
}
function getTargetValueMinMax($$, targets) {
  var _a, _b, _c, _d;
  const minMax = { min: void 0, max: void 0 };
  const hasAxis = $$.state.hasAxis;
  for (let i = 0; i < targets.length; i++) {
    const target = targets[i];
    const isCandlestick = (_a = $$.isCandlestickType) == null ? void 0 : _a.call($$, target);
    const isSubchartCandlestick = !isCandlestick && !!((_b = $$.isSubchartSourceTypeOf) == null ? void 0 : _b.call($$, target, TYPE.CANDLESTICK));
    const { values } = target;
    for (let j = 0; j < values.length; j++) {
      const row = values[j];
      let value = row.value;
      if (!(isValue(value) || value === null)) {
        continue;
      }
      const subchartCandlestickValue = isSubchartCandlestick ? (_c = $$.getSubchartCandlestickShapeValue) == null ? void 0 : _c.call($$, row, true) : void 0;
      if (isNumber(subchartCandlestickValue)) {
        value = subchartCandlestickValue;
      } else if (value !== null && (isCandlestick || isSubchartCandlestick)) {
        value = Array.isArray(value) ? value.slice(0, 4) : [value.open, value.high, value.low, value.close];
      }
      if (Array.isArray(value)) {
        updateMinMaxFromValues(minMax, value);
      } else if (isObject(value) && "high" in value) {
        updateMinMaxFromValues(minMax, Object.values(value));
      } else if ((_d = $$.isBubbleZType) == null ? void 0 : _d.call($$, row)) {
        updateMinMax(minMax, hasAxis && $$.getBubbleZData(value, "y"));
      } else {
        updateMinMax(minMax, value);
      }
    }
  }
  return [minMax.min, minMax.max];
}
function getTargetXMinMax(targets, type) {
  let result;
  for (let i = 0; i < targets.length; i++) {
    const { values } = targets[i];
    for (let j = 0; j < values.length; j++) {
      const { x } = values[j];
      if (notEmpty(x) && (result === void 0 || (type === "min" ? x < result : x > result))) {
        result = x;
      }
    }
  }
  return result;
}
/* harmony default export */ var domain = ({
  /**
   * Get both min and max Y domain values in a single pass.
   * Avoids calling getValuesAsIdKeyed twice.
   * @param {Array} targets Target data
   * @returns {Array.<number|Date|undefined>} [min, max]
   * @private
   */
  getYDomainMinMaxBoth(targets) {
    const $$ = this;
    const { axis, cache, config, state } = $$;
    const canCache = canCacheTargetDomain($$, targets);
    const cacheKey = canCache ? `${KEY.domainMinMax}_y_${getTargetDomainCacheKey($$, targets)}` : null;
    const cached = cacheKey && cache.get(cacheKey);
    if (cached && cached.generation === state.dataGeneration) {
      return cached.value;
    }
    const dataGroups = config.data_groups;
    const ids = $$.mapToIds(targets);
    const idsSet = toSet(ids);
    let result;
    if (dataGroups.length > 0) {
      const rawYs = $$.getValuesAsIdKeyed(targets);
      const hasNegative = targets.some((t) => t.values.some((v) => v.value < 0));
      const hasPositive = targets.some((t) => t.values.some((v) => v.value > 0));
      const axisIdMap = new Map(ids.map((id) => [id, axis.getId(id)]));
      const ysMin = {};
      const ysMax = {};
      for (const key in rawYs) {
        ysMin[key] = rawYs[key].slice();
        ysMax[key] = rawYs[key].slice();
      }
      dataGroups.forEach((groupIds) => {
        const idsInGroup = groupIds.filter((v) => idsSet.has(v));
        if (idsInGroup.length) {
          const baseId = idsInGroup[0];
          const baseAxisId = axisIdMap.get(baseId);
          if (ysMin[baseId] && hasNegative) {
            ysMin[baseId] = ysMin[baseId].map((v) => v < 0 ? v : 0);
          }
          if (ysMax[baseId] && hasPositive) {
            ysMax[baseId] = ysMax[baseId].map((v) => v > 0 ? v : 0);
          }
          idsInGroup.filter((v, i) => i > 0).forEach((id) => {
            if (ysMin[id]) {
              const axisId = axisIdMap.get(id);
              ysMin[id].forEach((v, i) => {
                const val = +v;
                if (axisId === baseAxisId && !(hasNegative && val > 0)) {
                  ysMin[baseId][i] += val;
                }
              });
            }
            if (ysMax[id]) {
              const axisId = axisIdMap.get(id);
              ysMax[id].forEach((v, i) => {
                const val = +v;
                if (axisId === baseAxisId && !(hasPositive && val < 0)) {
                  ysMax[baseId][i] += val;
                }
              });
            }
          });
        }
      });
      const minVals = [];
      const maxVals = [];
      for (const key in ysMin) {
        minVals.push(getMinMax("min", ysMin[key]));
        maxVals.push(getMinMax("max", ysMax[key]));
      }
      result = [
        getMinMax("min", minVals),
        getMinMax("max", maxVals)
      ];
    } else {
      result = getTargetValueMinMax($$, targets);
    }
    if (cacheKey) {
      cache.add(cacheKey, {
        generation: state.dataGeneration,
        value: result
      });
    }
    return result;
  },
  /**
   * Check if hidden targets bound to the given axis id
   * @param {string} id ID to be checked
   * @returns {boolean}
   * @private
   */
  isHiddenTargetWithYDomain(id) {
    const $$ = this;
    for (const v of $$.state.hiddenTargetIds) {
      if ($$.axis.getId(v) === id) return true;
    }
    return false;
  },
  getYDomain(targets, axisId, xDomain) {
    const $$ = this;
    const { axis, config, scale } = $$;
    const pfx = `axis_${axisId}`;
    if ($$.isStackNormalized()) {
      const axisDataIds = targets.filter((t) => axis.getId(t.id) === axisId).map((t) => t.id);
      const hasGroupedData = axisDataIds.some((id) => $$.isGrouped(id));
      if (hasGroupedData) {
        return [0, 100];
      }
    }
    const isLog = (scale == null ? void 0 : scale[axisId]) && scale[axisId].type === "log";
    const targetsByAxisId = targets.filter((t) => axis.getId(t.id) === axisId);
    const yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId;
    if (yTargets.length === 0) {
      if ($$.isHiddenTargetWithYDomain(axisId)) {
        return scale[axisId].domain();
      } else {
        return axisId === "y2" ? scale.y.domain() : (
          // When all data bounds to y2, y Axis domain is called prior y2.
          // So, it needs to call to get y2 domain here
          $$.getYDomain(targets, "y2", xDomain)
        );
      }
    }
    const yMin = config[`${pfx}_min`];
    const yMax = config[`${pfx}_max`];
    const center = config[`${pfx}_center`];
    const isInverted = config[`${pfx}_inverted`];
    const showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated;
    const showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
    const [yDomainMinVal, yDomainMaxVal] = $$.getYDomainMinMaxBoth(yTargets);
    let yDomainMin = yDomainMinVal;
    let yDomainMax = yDomainMaxVal;
    let isZeroBased = [TYPE.BAR, TYPE.BUBBLE, TYPE.SCATTER, ...TYPE_BY_CATEGORY.Line].some((v) => {
      const type = v.indexOf("area") > -1 ? "area" : v;
      return $$.hasType(v, yTargets, true) && config[`${type}_zerobased`];
    });
    yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? yDomainMin <= yMax ? yDomainMin : yMax - 10 : yDomainMin;
    yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? yMin <= yDomainMax ? yDomainMax : yMin + 10 : yDomainMax;
    if (isNaN(yDomainMin)) {
      yDomainMin = 0;
    }
    if (isNaN(yDomainMax)) {
      yDomainMax = yDomainMin;
    }
    if (yDomainMin === yDomainMax) {
      yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
    }
    const isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
    const isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
    if (isValue(yMin) && isAllPositive || isValue(yMax) && isAllNegative) {
      isZeroBased = false;
    }
    if (isZeroBased) {
      isAllPositive && (yDomainMin = 0);
      isAllNegative && (yDomainMax = 0);
    }
    const domainLength = Math.abs(yDomainMax - yDomainMin);
    let padding = { top: domainLength * 0.1, bottom: domainLength * 0.1 };
    if (isDefined(center)) {
      const yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
      yDomainMax = center + yDomainAbs;
      yDomainMin = center - yDomainAbs;
    }
    if (showHorizontalDataLabel) {
      const diff = diffDomain(scale.y.range());
      const ratio = $$.getDataLabelLength(yDomainMin, yDomainMax, "width").map((v) => {
        const result = v / diff;
        return isFinite(result) ? result : 0;
      });
      ["bottom", "top"].forEach((v, i) => {
        padding[v] += domainLength * (ratio[i] / (1 - ratio[0] - ratio[1]));
      });
    } else if (showVerticalDataLabel) {
      const lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, "height");
      ["bottom", "top"].forEach((v, i) => {
        padding[v] += $$.convertPixelToScale("y", lengths[i], domainLength);
      });
    }
    padding = $$.getResettedPadding(padding);
    const p = config[`${pfx}_padding`];
    if (notEmpty(p)) {
      ["bottom", "top"].forEach((v) => {
        padding[v] = axis.getPadding(p, v, padding[v], domainLength);
      });
    }
    if (isZeroBased) {
      isAllPositive && (padding.bottom = yDomainMin);
      isAllNegative && (padding.top = -yDomainMax);
    }
    const domain = isLog ? [yDomainMin, yDomainMax].map((v) => v < 0 ? 0 : v) : [yDomainMin - padding.bottom, yDomainMax + padding.top];
    return isInverted ? domain.reverse() : domain;
  },
  getXDomainMinMax(targets, type) {
    var _a;
    const $$ = this;
    const { cache, state } = $$;
    const configValue = $$.config[`axis_x_${type}`];
    const canCache = canCacheTargetDomain($$, targets);
    const cacheKey = canCache ? `${KEY.domainMinMax}_x_${type}_${getTargetDomainCacheKey($$, targets)}` : null;
    const cached = cacheKey && cache.get(cacheKey);
    let dataValue = (cached == null ? void 0 : cached.generation) === state.dataGeneration ? cached.value : void 0;
    if (dataValue === void 0) {
      dataValue = getTargetXMinMax(targets, type);
      cacheKey && cache.add(cacheKey, {
        generation: state.dataGeneration,
        value: dataValue
      });
    }
    let value = isObject(configValue) ? configValue.value : configValue;
    value = isDefined(value) && ((_a = $$.axis) == null ? void 0 : _a.isTimeSeries()) ? parseDate.bind(this)(value) : value;
    if (isObject(configValue) && configValue.fit && (type === "min" && value < dataValue || type === "max" && value > dataValue)) {
      value = void 0;
    }
    return isDefined(value) ? value : dataValue;
  },
  /**
   * Get x Axis padding
   * @param {Array} domain x Axis domain
   * @param {number} tickCount Tick count
   * @returns {object} Padding object values with 'left' & 'right' key
   * @private
   */
  getXDomainPadding(domain, tickCount) {
    const $$ = this;
    const { axis, config } = $$;
    const padding = config.axis_x_padding;
    const isTimeSeriesTickCount = axis.isTimeSeries() && tickCount;
    const diff = diffDomain(domain);
    let defaultValue;
    if (axis.isCategorized() || isTimeSeriesTickCount) {
      defaultValue = 0;
    } else if ($$.hasType("bar")) {
      const maxDataCount = $$.getMaxDataCount();
      defaultValue = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : 0.5;
    } else {
      defaultValue = $$.getResettedPadding(diff * 0.01);
    }
    let { left = defaultValue, right = defaultValue } = isNumber(padding) ? { left: padding, right: padding } : padding;
    if (padding.unit === "px") {
      const domainLength = Math.abs(diff + diff * 0.2);
      left = axis.getPadding(padding, "left", defaultValue, domainLength);
      right = axis.getPadding(padding, "right", defaultValue, domainLength);
    } else {
      const range = diff + left + right;
      if (isTimeSeriesTickCount && range) {
        const relativeTickWidth = diff / tickCount / range;
        left = left / range / relativeTickWidth;
        right = right / range / relativeTickWidth;
      }
    }
    return { left, right };
  },
  /**
   * Get x Axis domain
   * @param {Array} targets targets
   * @returns {Array} x Axis domain
   * @private
   */
  getXDomain(targets) {
    const $$ = this;
    const { axis, config, scale: { x } } = $$;
    const isInverted = config.axis_x_inverted;
    const domain = [
      $$.getXDomainMinMax(targets, "min"),
      $$.getXDomainMinMax(targets, "max")
    ];
    let [min = 0, max = 0] = domain;
    if (x.type !== "log") {
      const isCategorized = axis.isCategorized();
      const isTimeSeries = axis.isTimeSeries();
      const padding = $$.getXDomainPadding(domain);
      let [firstX, lastX] = domain;
      if (firstX - lastX === 0 && !isCategorized) {
        if (isTimeSeries) {
          firstX = new Date(firstX.getTime() * 0.5);
          lastX = new Date(lastX.getTime() * 1.5);
        } else {
          firstX = firstX === 0 ? 1 : firstX * 0.5;
          lastX = lastX === 0 ? -1 : lastX * 1.5;
        }
      }
      if (firstX || firstX === 0) {
        min = isTimeSeries ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
      }
      if (lastX || lastX === 0) {
        max = isTimeSeries ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
      }
    }
    return isInverted ? [max, min] : [min, max];
  },
  updateXDomain(targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
    var _a;
    const $$ = this;
    const { config, org, scale: { x, subX } } = $$;
    const zoomEnabled = config.zoom_enabled;
    if (withUpdateOrgXDomain) {
      x.domain(domain || sortValue($$.getXDomain(targets), !config.axis_x_inverted));
      org.xDomain = x.domain();
      subX.domain(x.domain());
      (_a = $$.brush) == null ? void 0 : _a.scale(subX);
    }
    if (withUpdateXDomain) {
      const domainValue = domain || (!$$.brush || brushEmpty($$)) ? org.xDomain : getBrushSelection($$).map(subX.invert);
      x.domain(domainValue);
    }
    if (withUpdateOrgXDomain || withUpdateXDomain) {
      zoomEnabled && $$.zoom.updateScaleExtent();
    }
    withTrim && x.domain($$.trimXDomain(x.orgDomain()));
    return x.domain();
  },
  /**
   * Trim x domain when given domain surpasses the range
   * @param {Array} domain Domain value
   * @returns {Array} Trimed domain if given domain is out of range
   * @private
   */
  trimXDomain(domain) {
    const $$ = this;
    const isInverted = $$.config.axis_x_inverted;
    const zoomDomain = $$.getZoomDomain();
    const [min, max] = zoomDomain;
    if (isInverted ? domain[0] >= min : domain[0] <= min) {
      domain[1] = +domain[1] + (min - domain[0]);
      domain[0] = min;
    }
    if (isInverted ? domain[1] <= max : domain[1] >= max) {
      domain[0] = +domain[0] - (domain[1] - max);
      domain[1] = max;
    }
    return domain;
  },
  /**
   * Get subchart/zoom domain
   * @param {string} type "subX" or "zoom"
   * @param {boolean} getCurrent Get current domain if true
   * @returns {Array} zoom domain
   * @private
   */
  getZoomDomain(type = "zoom", getCurrent = false) {
    const $$ = this;
    const { config, scale, org } = $$;
    let [min, max] = getCurrent && scale[type] ? scale[type].domain() : org.xDomain;
    if (type === "zoom") {
      if (isDefined(config.zoom_x_min)) {
        min = getMinMax("min", [min, config.zoom_x_min]);
      }
      if (isDefined(config.zoom_x_max)) {
        max = getMinMax("max", [max, config.zoom_x_max]);
      }
    }
    return [min, max];
  },
  /**
   * Return zoom domain from given domain
   * - 'category' type need to add offset to original value
   * @param {Array} domainValue domain value
   * @returns {Array} Zoom domain
   * @private
   */
  getZoomDomainValue(domainValue) {
    const $$ = this;
    const { config, axis } = $$;
    if (axis.isCategorized() && Array.isArray(domainValue)) {
      const isInverted = config.axis_x_inverted;
      const domain = domainValue.map(
        (v, i) => Number(v) + (i === 0 ? +isInverted : +!isInverted)
      );
      return domain;
    }
    return domainValue;
  },
  /**
   * Converts pixels to axis' scale values
   * @param {string} type Axis type
   * @param {number} pixels Pixels
   * @param {number} domainLength Domain length
   * @returns {number}
   * @private
   */
  convertPixelToScale(type, pixels, domainLength) {
    const $$ = this;
    const { config, state } = $$;
    const isRotated = config.axis_rotated;
    let length;
    if (type === "x") {
      length = isRotated ? "height" : "width";
    } else {
      length = isRotated ? "width" : "height";
    }
    return domainLength * (pixels / state[length]);
  },
  /**
   * Check if the given domain is within subchart/zoom range
   * @param {Array} domain Target domain value
   * @param {Array} current Current subchart/zoom domain value
   * @param {Array} range subchart/zoom range value
   * @returns {boolean}
   * @private
   */
  withinRange(domain, current = [0, 0], range) {
    const $$ = this;
    const isInverted = $$.config.axis_x_inverted;
    const [min, max] = range;
    if (Array.isArray(domain)) {
      const lo = isInverted ? domain[1] : domain[0];
      const hi = isInverted ? domain[0] : domain[1];
      if (lo < hi) {
        return domain.every(
          (v, i) => (i === 0 ? isInverted ? +v <= min : +v >= min : isInverted ? +v >= max : +v <= max) && !domain.every((v2, i2) => v2 === current[i2])
        );
      }
    }
    return false;
  }
});

;// ./src/ChartInternal/internals/format.ts

function _getFormat($$, typeValue, v) {
  const { config } = $$;
  const type = `axis_${typeValue}_tick_format`;
  const format = config[type] ? config[type] : $$.defaultValueFormat;
  return format.call($$.api, v);
}
/* harmony default export */ var format = ({
  yFormat(v) {
    return _getFormat(this, "y", v);
  },
  y2Format(v) {
    return _getFormat(this, "y2", v);
  },
  /**
   * Get default value format function
   * @returns {function} formatter function
   * @private
   */
  getDefaultValueFormat() {
    const $$ = this;
    const { defaultArcValueFormat, yFormat, y2Format } = $$;
    const hasArc = $$.hasArcType(null, ["gauge", "polar", "radar"]);
    return function(v, ratio, id) {
      const format = hasArc ? defaultArcValueFormat : $$.axis && $$.axis.getId(id) === "y2" ? y2Format : yFormat;
      return format.call($$, v, ratio);
    };
  },
  defaultValueFormat(v) {
    return isArray(v) ? v.join("~") : isValue(v) ? +v : "";
  },
  defaultArcValueFormat(v, ratio) {
    return `${(ratio * 100).toFixed(1)}%`;
  },
  defaultPolarValueFormat(v) {
    return `${v}`;
  },
  dataLabelFormat(targetId) {
    const $$ = this;
    const dataLabels = $$.config.data_labels;
    const defaultFormat = (v) => {
      const delimiter = "~";
      let res = v;
      if (isArray(v)) {
        res = v.join(delimiter);
      } else if (isObject(v)) {
        res = Object.values(v).join(delimiter);
      }
      return res;
    };
    let format = defaultFormat;
    if (isFunction(dataLabels.format)) {
      format = dataLabels.format;
    } else if (isObjectType(dataLabels.format)) {
      if (dataLabels.format[targetId]) {
        format = dataLabels.format[targetId] === true ? defaultFormat : dataLabels.format[targetId];
      } else {
        format = () => "";
      }
    }
    return format.bind($$.api);
  }
});

;// ./src/ChartInternal/internals/legend.ts





const LEGEND_TOUCH_TAP_THRESHOLD = 10;
const LEGEND_TOUCH_CLICK_TIMEOUT = 750;
function _getLegendColor(id) {
  const $$ = this;
  const data = $$.getDataById(id);
  const color = $$.levelColor ? $$.levelColor(data.values[0].value) : $$.color(data);
  return color;
}
function _getFormattedText(id, formatted = true) {
  var _a;
  const { config } = this;
  let text = (_a = config.data_names[id]) != null ? _a : id;
  if (formatted && isFunction(config.legend_format)) {
    text = config.legend_format(text, id !== text ? id : void 0);
  }
  return text;
}
function _buildLegendItemMap($$, legendItems) {
  var _a;
  if (!legendItems || legendItems.empty()) {
    return;
  }
  const allItems = (_a = $$.$el.legend) == null ? void 0 : _a.selectAll(`.${$LEGEND.legendItem}`);
  if (allItems && !allItems.empty()) {
    legendItems = allItems;
  }
  const items = [];
  legendItems.each(function(id) {
    items.push({ id, node: this });
  });
  const itemMap = toMap(
    items,
    (item) => item.id,
    (item) => item.node
  );
  $$.cache.add(KEY.legendItemMap, itemMap);
}
function _getLegendTouchPoint(event) {
  var _a, _b;
  return ((_a = event.changedTouches) == null ? void 0 : _a[0]) || ((_b = event.touches) == null ? void 0 : _b[0]);
}
function _setLegendTouchStart($$, id, event) {
  const touch = _getLegendTouchPoint(event);
  $$.state.legendTouch = touch ? {
    id,
    x: touch.clientX,
    y: touch.clientY,
    moved: false
  } : null;
}
function _updateLegendTouchMove($$, event) {
  const start = $$.state.legendTouch;
  const touch = start && _getLegendTouchPoint(event);
  if (touch) {
    start.moved = start.moved || Math.abs(touch.clientX - start.x) > LEGEND_TOUCH_TAP_THRESHOLD || Math.abs(touch.clientY - start.y) > LEGEND_TOUCH_TAP_THRESHOLD;
  }
}
function _isLegendTouchTap($$, id, event) {
  _updateLegendTouchMove($$, event);
  const start = $$.state.legendTouch;
  $$.state.legendTouch = null;
  return !!start && start.id === id && !start.moved;
}
function _markLegendTouchClick($$, id) {
  $$.state.legendLastTouchClickId = id;
  $$.state.legendLastTouchClickTime = Date.now();
}
function _isDuplicateLegendTouchClick($$, id) {
  const { state } = $$;
  const duplicate = state.legendLastTouchClickId === id && Date.now() - (state.legendLastTouchClickTime || 0) < LEGEND_TOUCH_CLICK_TIMEOUT;
  if (duplicate) {
    state.legendLastTouchClickId = null;
    state.legendLastTouchClickTime = 0;
  }
  return duplicate;
}
function _getLegendTouchOption($$) {
  var _a;
  const preventDefault = (_a = $$.config.interaction_inputType_touch) == null ? void 0 : _a.preventDefault;
  const isPrevented = isBoolean(preventDefault) && preventDefault || false;
  const preventThreshold = !isNaN(preventDefault) && preventDefault || null;
  return {
    passive: !isPrevented && preventThreshold === null
  };
}
/* harmony default export */ var internals_legend = ({
  /**
   * Initialize the legend.
   * @private
   */
  initLegend() {
    var _a;
    const $$ = this;
    const { config, $el } = $$;
    $$.legendItemTextBox = {};
    $$.state.legendHasRendered = false;
    if ($$.state.isCanvasMode) {
      if (config.legend_show) {
        (_a = $$.updateHtmlLegend) == null ? void 0 : _a.call($$);
      } else {
        $$.state.hiddenLegendIds = new Set($$.mapToIds($$.data.targets));
      }
      return;
    }
    if (config.legend_show) {
      if (!config.legend_contents_bindto) {
        $el.legend = $$.$el.svg.append("g").classed($LEGEND.legend, true).attr("transform", $$.getTranslate("legend"));
      }
      $$.updateLegend();
    } else {
      $$.state.hiddenLegendIds = new Set($$.mapToIds($$.data.targets));
    }
  },
  /**
   * Update legend element
   * @param {Array} targetIds ID's of target
   * @param {object} options withTransform : Whether to use the transform property / withTransitionForTransform: Whether transition is used when using the transform property / withTransition : whether or not to transition.
   * @param {object} transitions Return value of the generateTransitions
   * @private
   */
  updateLegend(targetIds, options, transitions) {
    var _a;
    const $$ = this;
    const { config, state, scale, $el } = $$;
    const optionz = options || {
      withTransform: false,
      withTransitionForTransform: false,
      withTransition: false
    };
    optionz.withTransition = getOption(optionz, "withTransition", true);
    optionz.withTransitionForTransform = getOption(optionz, "withTransitionForTransform", true);
    if (config.legend_contents_bindto && config.legend_contents_template) {
      $$.updateLegendTemplate();
    } else if (!state.hasTreemap) {
      $$.updateLegendElement(
        targetIds || $$.mapToIds($$.data.targets),
        optionz
      );
    }
    (_a = $el.legend) == null ? void 0 : _a.selectAll(`.${$LEGEND.legendItem}`).classed($LEGEND.legendItemHidden, function(id) {
      const hide = !$$.isTargetToShow(id);
      if (hide) {
        this.style.opacity = null;
      }
      return hide;
    });
    $$.updateScales(false, !scale.zoom);
    $$.updateSvgSize();
    $$.transformAll(optionz.withTransitionForTransform, transitions);
    state.legendHasRendered = true;
  },
  /**
   * Update legend using template option
   * @private
   */
  updateLegendTemplate() {
    const $$ = this;
    const { config, $el } = $$;
    const wrapper = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(config.legend_contents_bindto);
    const template = config.legend_contents_template;
    if (!wrapper.empty()) {
      const targets = $$.mapToIds($$.data.targets);
      const ids = [];
      let html = "";
      targets.forEach((v) => {
        const content = isFunction(template) ? sanitize(template.call($$.api, v, $$.color(v), $$.api.data(v)[0].values)) : tplProcess(template, {
          COLOR: $$.color(v),
          TITLE: v
        });
        if (content) {
          ids.push(v);
          html += content;
        }
      });
      const legendItem = wrapper.html(html).selectAll(function() {
        return this.childNodes;
      }).data(ids);
      $$.setLegendItem(legendItem);
      $el.legend = wrapper;
    }
  },
  /**
   * Update the size of the legend.
   * @param {Obejct} size Size object
   * @private
   */
  updateSizeForLegend(size) {
    const $$ = this;
    const {
      config,
      state: {
        isLegendTop,
        isLegendLeft,
        isLegendRight,
        isLegendInset,
        current
      }
    } = $$;
    const { width, height } = size;
    const insetLegendPosition = {
      top: isLegendTop ? $$.getCurrentPaddingByDirection("top") + config.legend_inset_y + 5.5 : current.height - height - $$.getCurrentPaddingByDirection("bottom") - config.legend_inset_y,
      left: isLegendLeft ? $$.getCurrentPaddingByDirection("left") + config.legend_inset_x + 0.5 : current.width - width - $$.getCurrentPaddingByDirection("right") - config.legend_inset_x + 0.5
    };
    $$.state.margin3 = {
      top: isLegendRight ? 0 : isLegendInset ? insetLegendPosition.top : current.height - height,
      right: NaN,
      bottom: 0,
      left: isLegendRight ? current.width - width : isLegendInset ? insetLegendPosition.left : 0
    };
  },
  /**
   * Transform Legend
   * @param {boolean} withTransition whether or not to transition.
   * @private
   */
  transformLegend(withTransition) {
    const $$ = this;
    const { $el: { legend }, $T } = $$;
    $T(legend, withTransition).attr("transform", $$.getTranslate("legend"));
  },
  /**
   * Update legend item color
   * @param {string} id Corresponding data ID value
   * @param {string} color Color value
   * @private
   */
  updateLegendItemColor(id, color) {
    const $$ = this;
    const { legend } = $$.$el;
    if (legend) {
      const legendItem = $$.getLegendItemById(id);
      if (legendItem) {
        (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(legendItem).select("line").style("stroke", color);
      }
    }
  },
  /**
   * Get the width of the legend
   * @returns {number} width
   * @private
   */
  getLegendWidth() {
    const $$ = this;
    const { current: { width }, isLegendRight, isLegendInset, legendItemWidth, legendStep } = $$.state;
    return $$.config.legend_show ? isLegendRight || isLegendInset ? legendItemWidth * (legendStep + 1) : width : 0;
  },
  /**
   * Get the height of the legend
   * @returns {number} height
   * @private
   */
  getLegendHeight() {
    var _a;
    const $$ = this;
    const { current, isLegendRight, legendItemHeight, legendStep } = $$.state;
    const isFitPadding = ((_a = $$.config.padding) == null ? void 0 : _a.mode) === "fit";
    const minHeight = isFitPadding ? 10 : 20;
    const height = $$.config.legend_show ? isLegendRight ? current.height : Math.max(minHeight, legendItemHeight) * (legendStep + 1) : 0;
    return height;
  },
  /**
   * Get the opacity of the legend that is unfocused
   * @param {d3.selection} legendItem Legend item node
   * @returns {string|null} opacity
   * @private
   */
  opacityForUnfocusedLegend(legendItem) {
    return legendItem.classed($LEGEND.legendItemHidden) ? null : "0.3";
  },
  /**
   * Toggles the focus of the legend
   * @param {Array} targetIds ID's of target
   * @param {boolean} focus whether or not to focus.
   * @private
   */
  toggleFocusLegend(targetIds, focus) {
    const $$ = this;
    const { $el: { legend }, $T } = $$;
    const targetIdz = $$.mapToTargetIds(targetIds);
    legend && $T(legend.selectAll(`.${$LEGEND.legendItem}`).filter((id) => targetIdz.indexOf(id) >= 0).classed($FOCUS.legendItemFocused, focus)).style("opacity", function() {
      return focus ? null : $$.opacityForUnfocusedLegend.call($$, (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this));
    });
  },
  /**
   * Revert the legend to its default state
   * @private
   */
  revertLegend() {
    const $$ = this;
    const { $el: { legend }, $T } = $$;
    legend && $T(legend.selectAll(`.${$LEGEND.legendItem}`).classed($FOCUS.legendItemFocused, false)).style("opacity", null);
  },
  /**
   * Shows the legend
   * @param {Array} targetIds ID's of target
   * @private
   */
  showLegend(targetIds) {
    const $$ = this;
    const { config, $el, $T } = $$;
    if (!config.legend_show) {
      config.legend_show = true;
      $el.legend ? $el.legend.style("visibility", null) : $$.initLegend();
      !$$.state.legendHasRendered && $$.updateLegend();
    }
    $$.removeHiddenLegendIds(targetIds);
    $T(
      $el.legend.selectAll($$.selectorLegends(targetIds)).style("visibility", null)
    ).style("opacity", null);
  },
  /**
   * Hide the legend
   * @param {Array} targetIds ID's of target
   * @private
   */
  hideLegend(targetIds) {
    const $$ = this;
    const { config, $el: { legend } } = $$;
    if (config.legend_show && isEmpty(targetIds)) {
      config.legend_show = false;
      legend == null ? void 0 : legend.style("visibility", "hidden");
    }
    $$.addHiddenLegendIds(targetIds);
    legend == null ? void 0 : legend.selectAll($$.selectorLegends(targetIds)).style("opacity", "0").style("visibility", "hidden");
  },
  /**
   * Get legend item textbox dimension
   * @param {string} id Data ID
   * @param {HTMLElement|d3.selection} textElement Text node element
   * @returns {object} Bounding rect
   * @private
   */
  getLegendItemTextBox(id, textElement) {
    const $$ = this;
    const { cache, state } = $$;
    let data;
    const cacheKey = KEY.legendItemTextBox;
    if (id) {
      data = !state.redrawing && cache.get(cacheKey) || {};
      if (!data[id]) {
        data[id] = $$.getTextRect(textElement, $LEGEND.legendItem);
        cache.add(cacheKey, data);
      }
      data = data[id];
    }
    return data;
  },
  /**
   * Set legend item style & bind events
   * @param {d3.selection} item Item node
   * @private
   */
  setLegendItem(item) {
    const $$ = this;
    const { $el, api, config, state } = $$;
    const isTouch = state.inputType === "touch";
    const hasGauge = $$.hasType("gauge");
    const useCssRule = config.boost_useCssRule;
    const interaction = config.legend_item_interaction;
    const eventType = interaction.dblclick ? "dblclick" : "click";
    const hasClickInteraction = interaction || isFunction(config.legend_item_onclick);
    const touchOption = isTouch ? _getLegendTouchOption($$) : void 0;
    const handleLegendToggle = function(event, id) {
      var _a;
      if (!callFn(config.legend_item_onclick, api, id, !state.hiddenTargetIds.has(id))) {
        const { altKey, type } = event;
        const selected = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        if (type === "dblclick" || altKey) {
          if (state.hiddenTargetIds.size && !selected.classed($LEGEND.legendItemHidden)) {
            api.show();
          } else {
            api.hide();
            api.show(id);
          }
        } else {
          api.toggle(id);
          selected.classed($FOCUS.legendItemFocused, false);
        }
      }
      if (isTouch) {
        $$.hideTooltip();
        (_a = $$.hideGridFocus) == null ? void 0 : _a.call($$, true);
      }
    };
    item.attr("class", function(id) {
      const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      const itemClass = !node.empty() && node.attr("class") || "";
      return itemClass + $$.generateClass($LEGEND.legendItem, id);
    }).style("visibility", (id) => $$.isLegendToShow(id) ? null : "hidden");
    if (config.interaction_enabled) {
      if (useCssRule) {
        [
          [`.${$LEGEND.legendItem}`, "cursor:pointer"],
          [`.${$LEGEND.legendItem} text`, "pointer-events:none"],
          [`.${$LEGEND.legendItemPoint} text`, "pointer-events:none"],
          [`.${$LEGEND.legendItemTile}`, "pointer-events:none"],
          [`.${$LEGEND.legendItemEvent}`, "fill-opacity:0"]
        ].forEach((v) => {
          const [selector, props] = v;
          $$.setCssRule(false, selector, [props])($el.legend);
        });
      }
      item.on(eventType, hasClickInteraction ? function(event, id) {
        if (isTouch && event.type === "click" && _isDuplicateLegendTouchClick($$, id)) {
          return;
        }
        handleLegendToggle.call(this, event, id);
      } : null);
      isTouch && eventType === "click" && hasClickInteraction && item.on("touchstart", function(event, id) {
        _setLegendTouchStart($$, id, event);
      }, touchOption).on("touchmove", (event) => {
        _updateLegendTouchMove($$, event);
      }, touchOption).on("touchend", function(event, id) {
        if (_isLegendTouchTap($$, id, event)) {
          _markLegendTouchClick($$, id);
          handleLegendToggle.call(this, event, id);
        }
      }, touchOption);
      !isTouch && item.on("mouseout", interaction || isFunction(config.legend_item_onout) ? function(event, id) {
        if (!callFn(
          config.legend_item_onout,
          api,
          id,
          !state.hiddenTargetIds.has(id)
        )) {
          (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused, false);
          if (hasGauge) {
            $$.undoMarkOverlapped($$, `.${$GAUGE.gaugeValue}`);
          }
          $$.api.revert();
        }
      } : null).on("mouseover", interaction || isFunction(config.legend_item_onover) ? function(event, id) {
        if (!callFn(
          config.legend_item_onover,
          api,
          id,
          !state.hiddenTargetIds.has(id)
        )) {
          (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused, true);
          if (hasGauge) {
            $$.markOverlapped(id, $$, `.${$GAUGE.gaugeValue}`);
          }
          if (!state.transiting && $$.isTargetToShow(id)) {
            api.focus(id);
          }
        }
      } : null);
      !item.empty() && item.on("click mouseout mouseover") && item.style("cursor", $$.getStylePropValue("pointer"));
    }
    _buildLegendItemMap($$, item);
  },
  /**
   * Get legend item node by ID using cached Map for O(1) lookup
   * Falls back to D3 selection if map is not available
   * @param {string} id Data ID
   * @returns {HTMLElement | null} Legend item node
   * @private
   */
  getLegendItemById(id) {
    var _a;
    const $$ = this;
    const itemMap = $$.cache.get(KEY.legendItemMap);
    if (itemMap && itemMap instanceof Map) {
      return itemMap.get(id) || null;
    }
    const item = (_a = $$.$el.legend) == null ? void 0 : _a.selectAll(`.${$LEGEND.legendItem}`).filter((d) => d === id);
    return (item == null ? void 0 : item.node()) || null;
  },
  /**
   * Update the legend
   * @param {Array} targetIds ID's of target
   * @param {object} options withTransform : Whether to use the transform property / withTransitionForTransform: Whether transition is used when using the transform property / withTransition : whether or not to transition.
   * @private
   */
  updateLegendElement(targetIds, options) {
    const $$ = this;
    const { config, state, $el: { legend }, $T } = $$;
    const legendType = config.legend_item_tile_type;
    const isRectangle = legendType !== "circle";
    const legendItemR = config.legend_item_tile_r;
    const itemTileSize = {
      width: isRectangle ? config.legend_item_tile_width : legendItemR * 2,
      height: isRectangle ? config.legend_item_tile_height : legendItemR * 2
    };
    const dimension = {
      padding: {
        top: 4,
        right: 10
      },
      max: {
        width: 0,
        height: 0
      },
      posMin: 10,
      step: 0,
      tileWidth: itemTileSize.width + 5,
      totalLength: 0
    };
    const sizes = {
      offsets: {},
      widths: {},
      heights: {},
      margins: [0],
      steps: {}
    };
    let xForLegend;
    let yForLegend;
    let background;
    const targetIdz = targetIds.filter((id) => !isDefined(config.data_names[id]) || config.data_names[id] !== null);
    const withTransition = options.withTransition;
    const isLegendRightOrInset = state.isLegendRight || state.isLegendInset;
    const getFormattedText = _getFormattedText.bind($$);
    const updatePositions = $$.getUpdateLegendPositions(
      targetIdz,
      dimension,
      sizes,
      isLegendRightOrInset
    );
    if (state.isLegendInset) {
      dimension.step = config.legend_inset_step ? config.legend_inset_step : targetIdz.length;
      state.legendStep = dimension.step;
    }
    if (state.isLegendRight) {
      xForLegend = (id) => dimension.max.width * sizes.steps[id];
      yForLegend = (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
    } else if (state.isLegendInset) {
      xForLegend = (id) => dimension.max.width * sizes.steps[id] + 10;
      yForLegend = (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
    } else {
      xForLegend = (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
      yForLegend = (id) => dimension.max.height * sizes.steps[id];
    }
    const posFn = {
      xText: (id, i) => xForLegend(id, i) + 4 + itemTileSize.width,
      xRect: (id, i) => xForLegend(id, i),
      x1Tile: (id, i) => xForLegend(id, i) - 2,
      x2Tile: (id, i) => xForLegend(id, i) - 2 + itemTileSize.width,
      yText: (id, i) => yForLegend(id, i) + 9,
      yRect: (id, i) => yForLegend(id, i) - 5,
      yTile: (id, i) => yForLegend(id, i) + 4
    };
    $$.generateLegendItem(
      targetIdz,
      itemTileSize,
      updatePositions,
      posFn,
      isLegendRightOrInset,
      getFormattedText
    );
    background = legend.select(`.${$LEGEND.legendBackground} rect`);
    if (state.isLegendInset && dimension.max.width > 0 && background.size() === 0) {
      background = legend.insert("g", `.${$LEGEND.legendItem}`).attr("class", $LEGEND.legendBackground).append("rect");
    }
    if (config.legend_tooltip) {
      legend.selectAll("title").data(targetIdz).text((id) => getFormattedText(id, false));
    }
    const texts = legend.selectAll("text").data(targetIdz).text((id) => getFormattedText(id)).each(function(id, i) {
      updatePositions(this, id, i);
    });
    $T(texts, withTransition).attr("x", posFn.xText).attr("y", posFn.yText);
    const rects = legend.selectAll(`rect.${$LEGEND.legendItemEvent}`).data(targetIdz);
    $T(rects, withTransition).attr("width", (id) => sizes.widths[id]).attr("height", (id) => sizes.heights[id]).attr("x", posFn.xRect).attr("y", posFn.yRect);
    $$.updateLegendItemPos(targetIdz, withTransition, posFn);
    if (background) {
      $T(background, withTransition).attr("height", $$.getLegendHeight() - 12).attr("width", dimension.max.width * (dimension.step + 1) + 10);
    }
    state.legendItemWidth = dimension.max.width;
    state.legendItemHeight = dimension.max.height;
    state.legendStep = dimension.step;
  },
  /**
   * Get position update function
   * @param {Array} targetIdz Data ids
   * @param {object} dimension Dimension object
   * @param {object} sizes Size object
   * @param {boolean} isLegendRightOrInset Whether legend is right or inset
   * @returns {function} Update position function
   * @private
   */
  getUpdateLegendPositions(targetIdz, dimension, sizes, isLegendRightOrInset) {
    const $$ = this;
    const { config, state } = $$;
    return function(textElement, id, index) {
      const reset = index === 0;
      const isLast = index === targetIdz.length - 1;
      const box = $$.getLegendItemTextBox(id, textElement);
      const itemWidth = box.width + dimension.tileWidth + (isLast && !isLegendRightOrInset ? 0 : dimension.padding.right) + config.legend_padding;
      const itemHeight = box.height + dimension.padding.top;
      const itemLength = isLegendRightOrInset ? itemHeight : itemWidth;
      const areaLength = isLegendRightOrInset ? $$.getLegendHeight() : $$.getLegendWidth();
      let margin;
      const updateValues = function(id2, withoutStep) {
        if (!withoutStep) {
          margin = (areaLength - dimension.totalLength - itemLength) / 2;
          if (margin < dimension.posMin) {
            margin = (areaLength - itemLength) / 2;
            dimension.totalLength = 0;
            dimension.step++;
          }
        }
        sizes.steps[id2] = dimension.step;
        sizes.margins[dimension.step] = state.isLegendInset ? 10 : margin;
        sizes.offsets[id2] = dimension.totalLength;
        dimension.totalLength += itemLength;
      };
      if (reset) {
        dimension.totalLength = 0;
        dimension.step = 0;
        dimension.max.width = 0;
        dimension.max.height = 0;
      }
      if (config.legend_show && !$$.isLegendToShow(id)) {
        sizes.widths[id] = 0;
        sizes.heights[id] = 0;
        sizes.steps[id] = 0;
        sizes.offsets[id] = 0;
        return;
      }
      sizes.widths[id] = itemWidth;
      sizes.heights[id] = itemHeight;
      if (!dimension.max.width || itemWidth >= dimension.max.width) {
        dimension.max.width = itemWidth;
      }
      if (!dimension.max.height || itemHeight >= dimension.max.height) {
        dimension.max.height = itemHeight;
      }
      const maxLength = isLegendRightOrInset ? dimension.max.height : dimension.max.width;
      if (config.legend_equally) {
        for (const id2 in sizes.widths) sizes.widths[id2] = dimension.max.width;
        for (const id2 in sizes.heights) sizes.heights[id2] = dimension.max.height;
        margin = (areaLength - maxLength * targetIdz.length) / 2;
        if (margin < dimension.posMin) {
          dimension.totalLength = 0;
          dimension.step = 0;
          targetIdz.forEach((id2) => updateValues(id2));
        } else {
          updateValues(id, true);
        }
      } else {
        updateValues(id);
      }
    };
  },
  /**
   * Generate legend item elements
   * @param {Array} targetIdz Data ids
   * @param {object} itemTileSize Item tile size {width, height}
   * @param {function} updatePositions Update position function
   * @param {object} posFn Position functions
   * @param {boolean} isLegendRightOrInset Whether legend is right or inset
   * @param {function} getFormattedText Bound text formatter function
   * @private
   */
  generateLegendItem(targetIdz, itemTileSize, updatePositions, posFn, isLegendRightOrInset, getFormattedText) {
    const $$ = this;
    const { config, state, $el: { legend } } = $$;
    const usePoint = config.legend_usePoint;
    const legendItemR = config.legend_item_tile_r;
    const legendType = config.legend_item_tile_type;
    const isRectangle = legendType !== "circle";
    const pos = -200;
    const l = legend.selectAll(`.${$LEGEND.legendItem}`).data(targetIdz).enter().append("g");
    $$.setLegendItem(l);
    if (config.legend_tooltip) {
      l.append("title").text((id) => id);
    }
    l.append("text").text((id) => getFormattedText(id)).each(function(id, i) {
      updatePositions(this, id, i);
    }).style("pointer-events", $$.getStylePropValue("none")).attr("x", isLegendRightOrInset ? posFn.xText : pos).attr("y", isLegendRightOrInset ? pos : posFn.yText);
    l.append("rect").attr("class", $LEGEND.legendItemEvent).style("fill-opacity", $$.getStylePropValue("0")).attr("x", isLegendRightOrInset ? posFn.xRect : pos).attr("y", isLegendRightOrInset ? pos : posFn.yRect);
    if (usePoint) {
      const ids = [];
      const pattern = $$.getValidPointPattern();
      l.append((d) => {
        ids.indexOf(d) === -1 && ids.push(d);
        let point = pattern[ids.indexOf(d) % pattern.length];
        if (point === "rectangle") {
          point = "rect";
        }
        return browser_doc.createElementNS(
          external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.svg,
          "hasValidPointType" in $$ && $$.hasValidPointType(point) ? point : "use"
        );
      }).attr("class", $LEGEND.legendItemPoint).style("fill", _getLegendColor.bind($$)).style("pointer-events", $$.getStylePropValue("none")).attr("href", (data, idx, selection) => {
        const node = selection[idx];
        const nodeName = node.nodeName.toLowerCase();
        const id = $$.getTargetSelectorSuffix(data);
        return nodeName === "use" ? `#${state.datetimeId}-point${id}` : void 0;
      });
    } else {
      l.append(isRectangle ? "line" : legendType).attr("class", $LEGEND.legendItemTile).style("stroke", _getLegendColor.bind($$)).style("pointer-events", $$.getStylePropValue("none")).call((selection) => {
        if (legendType === "circle") {
          selection.attr("r", legendItemR).style("fill", _getLegendColor.bind($$)).attr("cx", isLegendRightOrInset ? posFn.x2Tile : pos).attr("cy", isLegendRightOrInset ? pos : posFn.yTile);
        } else if (isRectangle) {
          selection.attr("stroke-width", itemTileSize.height).attr("x1", isLegendRightOrInset ? posFn.x1Tile : pos).attr("y1", isLegendRightOrInset ? pos : posFn.yTile).attr("x2", isLegendRightOrInset ? posFn.x2Tile : pos).attr("y2", isLegendRightOrInset ? pos : posFn.yTile);
        }
      });
    }
  },
  /**
   * Update legend item position
   * @param {Array} targetIdz Data ids
   * @param {boolean} withTransition Whether or not to apply transition
   * @param {object} posFn Position functions
   * @private
   */
  updateLegendItemPos(targetIdz, withTransition, posFn) {
    const $$ = this;
    const { config, $el: { legend }, $T } = $$;
    const usePoint = config.legend_usePoint;
    const legendType = config.legend_item_tile_type;
    const isRectangle = legendType !== "circle";
    if (usePoint) {
      const tiles = legend.selectAll(`.${$LEGEND.legendItemPoint}`).data(targetIdz);
      const isRectangleTile = config.legend_item_tile_type !== "circle";
      const tileWidth = isRectangleTile ? config.legend_item_tile_width : config.legend_item_tile_r * 2;
      const tileHeight = isRectangleTile ? config.legend_item_tile_height : config.legend_item_tile_r * 2;
      const iconWidth = tileWidth * 0.75;
      const iconHeight = tileHeight * 0.75;
      const customScaleX = tileWidth / 8;
      const customScaleY = tileHeight / 8;
      $T(tiles, withTransition).each(function() {
        const nodeName = this.nodeName.toLowerCase();
        let x = "x";
        let y = "y";
        let radius = null;
        let width = null;
        let height = null;
        if (nodeName === "circle") {
          x = "cx";
          y = "cy";
          radius = Math.min(iconWidth, iconHeight) / 2;
        } else if (nodeName === "rect") {
          width = iconWidth;
          height = iconHeight;
        }
        const tile = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).attr("transform", null).attr("x", null).attr("y", null).attr("cx", null).attr("cy", null).attr("r", radius).attr("width", width).attr("height", height);
        if (nodeName === "use") {
          tile.attr("transform", (d) => `translate(${posFn.x1Tile(d)} ${posFn.yTile(d) - tileHeight / 2}) scale(${customScaleX} ${customScaleY})`);
        } else {
          tile.attr(x, (d) => posFn.x1Tile(d) + (tileWidth - (width || 0)) / 2).attr(y, (d) => posFn.yTile(d) - (height || 0) / 2);
        }
      });
    } else {
      const tiles = legend.selectAll(`.${$LEGEND.legendItemTile}`).data(targetIdz);
      $T(tiles, withTransition).style("stroke", _getLegendColor.bind($$)).call((selection) => {
        if (legendType === "circle") {
          selection.attr("cx", (d) => {
            const x2 = posFn.x2Tile(d);
            return x2 - (x2 - posFn.x1Tile(d)) / 2;
          }).attr("cy", posFn.yTile);
        } else if (isRectangle) {
          selection.attr("x1", posFn.x1Tile).attr("y1", posFn.yTile).attr("x2", posFn.x2Tile).attr("y2", posFn.yTile);
        }
      });
    }
  }
});

// EXTERNAL MODULE: external {"commonjs":"d3-transition","commonjs2":"d3-transition","amd":"d3-transition","root":"d3"}
var external_commonjs_d3_transition_commonjs2_d3_transition_amd_d3_transition_root_d3_ = __webpack_require__(8);
;// ./src/ChartInternal/internals/redraw.ts





/* harmony default export */ var redraw = ({
  redraw(options = {}) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
    const $$ = this;
    const { config, state, $el } = $$;
    const { main, treemap } = $el;
    state.redrawing = true;
    state.redrawGeneration++;
    if (state.dirty.data || state.dirty.visibility || options.initializing) {
      state.dataGeneration++;
    }
    if (options.initializing || state.dirty.size || state.dirty.data || !state.rendered) {
      $$.cache.remove([KEY.svgLeft]);
    }
    const targetsToShow = $$.filterTargetsToShow($$.data.targets);
    state._targetsToShow = targetsToShow;
    const dirtySnapshot = {
      data: state.dirty.data,
      visibility: state.dirty.visibility,
      size: state.dirty.size
    };
    state.dirty.data = false;
    state.dirty.visibility = false;
    state.dirty.size = false;
    const { flow, initializing } = options;
    const wth = $$.getWithOption(options);
    const duration = wth.Transition ? config.transition_duration : 0;
    const durationForExit = wth.TransitionForExit ? duration : 0;
    const durationForAxis = wth.TransitionForAxis ? duration : 0;
    const transitions = (_a = $$.axis) == null ? void 0 : _a.generateTransitions(durationForAxis);
    const needShapeUpdate = dirtySnapshot.data || dirtySnapshot.visibility || initializing;
    if (state.isCanvasMode) {
      $$.setContainerSize();
      (_b = $$.updateHtmlLegend) == null ? void 0 : _b.call($$);
    }
    $$.updateSizes(initializing);
    if (state.isCanvasMode) {
      const zoomScale = $$.scale.zoom;
      const zoomDomain = zoomScale == null ? void 0 : zoomScale.domain();
      zoomScale && ($$.scale.zoom = null);
      $$.updateScales(initializing, wth.UpdateXDomain);
      if (zoomScale) {
        zoomScale.range($$.scale.x.range());
        zoomDomain && zoomScale.domain(zoomDomain);
        $$.scale.zoom = $$.getCustomizedXScale(zoomScale);
        $$.axis.x.scale($$.scale.zoom);
        $$.scale.x.domain(config.zoom_rescale ? zoomDomain : $$.org.xDomain);
        $$.scale.subX.domain($$.org.xDomain);
      }
      state.hasAxis && $$.axis.syncAxisDomains(targetsToShow, wth, flow);
      state.hasAxis && ((_c = $$.applyCanvasSubchartDomain) == null ? void 0 : _c.call($$));
      const shape = needShapeUpdate ? $$.getDrawShape() : state._cachedDrawShape || $$.getDrawShape();
      if (needShapeUpdate) {
        state._cachedDrawShape = shape;
      }
      if (config.legend_show && $el.legend && !(config.legend_contents_bindto && config.legend_contents_template)) {
        (_d = $$.positionHtmlLegend) == null ? void 0 : _d.call($$);
      }
      (_e = $$.resizeCanvas) == null ? void 0 : _e.call($$);
      state.canvasFocusKey = null;
      $$.renderCanvasFrame(shape, null, true);
      initializing && $$.updateTypesElements();
      $$.callPluginHook("$redraw", options, 0);
      state.redrawing = false;
      state._targetsToShow = null;
      state._cachedDrawShape = null;
      $$.mapToIds($$.data.targets).forEach((id) => {
        state.withoutFadeIn[id] = true;
      });
      callFn(config.onrendered, $$.api);
      return;
    }
    if (wth.Legend && config.legend_show) {
      options.withTransition = !!duration;
      !treemap && $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
    } else if (wth.Dimension) {
      $$.updateDimension(true);
    }
    config.data_empty_label_text && main.select(`text.${$TEXT.text}.${$COMMON.empty}`).attr("x", state.width / 2).attr("y", state.height / 2).text(config.data_empty_label_text).style("display", targetsToShow.length ? "none" : null);
    (_f = $$.redrawTitle) == null ? void 0 : _f.call($$);
    if (state.hasAxis) {
      $$.axis.redrawAxis(targetsToShow, wth, transitions, flow, initializing);
      ((_g = $$.hasGrid) == null ? void 0 : _g.call($$)) && $$.updateGrid();
      config.regions.length && ((_h = $$.updateRegion) == null ? void 0 : _h.call($$));
      ["bar", "candlestick", "line", "area"].forEach((v) => {
        const name = capitalize(v);
        if (/^(line|area)$/.test(v) && $$.hasTypeOf(name) || $$.hasType(v)) {
          if (needShapeUpdate) {
            $$[`update${name}`](wth.TransitionForExit);
          }
        }
      });
      $el.text && main.selectAll(`.${$SELECT.selectedCircles}`).filter($$.isBarType.bind($$)).selectAll("circle").remove();
      if (config.interaction_enabled && !flow && wth.EventRect) {
        $$.redrawEventRect();
        (_i = $$.bindZoomEvent) == null ? void 0 : _i.call($$);
      }
    } else {
      $el.arcs && $$.redrawArc(duration, durationForExit, wth.Transform);
      $el.radar && $$.redrawRadar();
      $el.polar && $$.redrawPolar();
      $el.funnel && $$.redrawFunnel();
      treemap && $$.updateTreemap(durationForExit);
    }
    if (!state.resizing && !treemap && ($$.hasPointType() || state.hasRadar)) {
      if (needShapeUpdate) {
        $$.updateCircle();
      }
    } else if ((_j = $$.hasLegendDefsPoint) == null ? void 0 : _j.call($$)) {
      $$.data.targets.forEach($$.point("create", this));
    }
    if ($$.hasDataLabel() && !$$.hasArcType(null, ["radar"])) {
      if (needShapeUpdate) {
        $$.updateText();
      }
    }
    initializing && $$.updateTypesElements();
    $$.generateRedrawList(targetsToShow, flow, duration, wth.Subchart, needShapeUpdate);
    $$.updateTooltipOnRedraw();
    $$.callPluginHook("$redraw", options, duration);
  },
  /**
   * Generate redraw list
   * @param {object} targets targets data to be shown
   * @param {object} flow flow object
   * @param {number} duration duration value
   * @param {boolean} withSubchart whether or not to show subchart
   * @param {boolean} needShapeRegen whether to regenerate draw shape
   * @private
   */
  generateRedrawList(targets, flow, duration, withSubchart, needShapeRegen = true) {
    const $$ = this;
    const { config, state } = $$;
    const shape = needShapeRegen ? $$.getDrawShape() : state._cachedDrawShape || $$.getDrawShape();
    if (needShapeRegen) {
      state._cachedDrawShape = shape;
    }
    if (state.hasAxis) {
      config.subchart_show && $$.redrawSubchart(withSubchart, duration, shape);
    }
    const flowFn = flow && $$.generateFlow({
      targets,
      flow,
      duration: flow.duration,
      shape,
      xv: $$.xv.bind($$)
    });
    const withTransition = (duration || flowFn) && isTabVisible();
    const redrawList = $$.getRedrawList(shape, flow, flowFn, withTransition);
    const afterRedraw = () => {
      flowFn && flowFn();
      state.redrawing = false;
      state._targetsToShow = null;
      state._cachedDrawShape = null;
      callFn(config.onrendered, $$.api);
    };
    if (withTransition && redrawList.length) {
      const waitForDraw = generateWait();
      (0,external_commonjs_d3_transition_commonjs2_d3_transition_amd_d3_transition_root_d3_.transition)().duration(duration).each(() => {
        redrawList.flatMap((t1) => t1).forEach((t) => waitForDraw.add(t));
      }).call(waitForDraw, afterRedraw);
    } else if (!state.transiting) {
      afterRedraw();
    }
    $$.mapToIds($$.data.targets).forEach((id) => {
      state.withoutFadeIn[id] = true;
    });
  },
  getRedrawList(shape, flow, flowFn, withTransition) {
    const $$ = this;
    const { config, state: { hasAxis, hasRadar, hasTreemap }, $el: { grid } } = $$;
    const { cx, cy, xForText, yForText } = shape.pos;
    const list = [];
    if (hasAxis) {
      if ($$.redrawGrid && (config.grid_x_lines.length || config.grid_y_lines.length)) {
        list.push($$.redrawGrid(withTransition));
      }
      if ($$.redrawRegion && config.regions.length) {
        list.push($$.redrawRegion(withTransition));
      }
      for (const v in shape.type) {
        const name = capitalize(v);
        const drawFn = shape.type[v];
        if (/^(area|line)$/.test(v) && $$.hasTypeOf(name) || $$.hasType(v)) {
          list.push($$[`redraw${name}`](drawFn, withTransition));
        }
      }
      !flow && grid.main && $$.updateGridFocus && list.push($$.updateGridFocus());
    }
    if (!$$.hasArcType() || hasRadar) {
      notEmpty(config.data_labels) && config.data_labels !== false && list.push($$.redrawText(xForText, yForText, flow, withTransition));
    }
    if (($$.hasPointType() || hasRadar) && !$$.isPointFocusOnly()) {
      $$.redrawCircle && list.push($$.redrawCircle(cx, cy, withTransition, flowFn));
    }
    if (hasTreemap) {
      list.push($$.redrawTreemap(withTransition));
    }
    return list;
  },
  updateAndRedraw(options = {}) {
    const $$ = this;
    const { config, state } = $$;
    let transitions;
    options.withTransition = getOption(options, "withTransition", true);
    options.withTransform = getOption(options, "withTransform", false);
    options.withLegend = getOption(options, "withLegend", false);
    options.withUpdateXDomain = true;
    options.withUpdateOrgXDomain = true;
    options.withTransitionForExit = false;
    options.withTransitionForTransform = getOption(
      options,
      "withTransitionForTransform",
      options.withTransition
    );
    if (!(options.withLegend && config.legend_show)) {
      if (state.hasAxis) {
        transitions = $$.axis.generateTransitions(
          options.withTransitionForAxis ? config.transition_duration : 0
        );
      }
      $$.updateScales();
      $$.updateSvgSize();
      $$.transformAll(options.withTransitionForTransform, transitions);
    }
    $$.redraw(options);
  }
});

;// ./src/ChartInternal/internals/size.ts




/* harmony default export */ var size = ({
  /**
   * Update container size
   * @private
   */
  setContainerSize() {
    const $$ = this;
    const { state } = $$;
    state.current.width = $$.getCurrentWidth();
    state.current.height = $$.getCurrentHeight();
  },
  getCurrentWidth() {
    const $$ = this;
    return $$.config.size_width || $$.getParentRectValue("width");
  },
  getCurrentHeight() {
    var _a, _b;
    const $$ = this;
    const { config, state, $el } = $$;
    let h = config.size_height;
    if (!h) {
      const chartNode = state.isCanvasMode ? (_a = $el.chart) == null ? void 0 : _a.node() : null;
      const minHeight = chartNode == null ? void 0 : chartNode.style.minHeight;
      minHeight && (chartNode.style.minHeight = "");
      h = $$.getParentHeight();
      minHeight && (chartNode.style.minHeight = minHeight);
      const surface = chartNode ? parseFloat((_b = $$.canvasEngine) == null ? void 0 : _b.canvas.style.height) || 0 : 0;
      const reserve = state.current.height - surface;
      if (reserve > 0 && Math.round(h) === Math.round(surface)) {
        h += reserve;
      }
    }
    return h > 0 ? h : 320 / ($$.hasType("gauge") && !config.gauge_fullCircle ? 2 : 1);
  },
  /**
   * Get the parent rect element's size
   * @param {string} key property/attribute name
   * @returns {number}
   * @private
   */
  getParentRectValue(key) {
    const offsetName = `offset${capitalize(key)}`;
    let parent = this.$el.chart.node();
    let v = 0;
    while (v < 30 && parent && parent.tagName !== "BODY") {
      try {
        v = getBoundingRect(parent, true)[key];
      } catch (e) {
        if (offsetName in parent) {
          v = parent[offsetName];
        }
      }
      parent = parent.parentNode;
    }
    const bodySize = browser_doc.body[offsetName];
    v > bodySize && (v = bodySize);
    return v;
  },
  getParentHeight() {
    const h = this.$el.chart.style("height");
    let height = 0;
    if (h) {
      height = /px$/.test(h) ? parseInt(h, 10) : this.getParentRectValue("height");
    }
    return height;
  },
  getSvgLeft(withoutRecompute) {
    var _a, _b, _c;
    const $$ = this;
    const { cache, config, state: { hasAxis }, $el } = $$;
    if (withoutRecompute) {
      const cached = cache.get(KEY.svgLeft);
      if (cached !== null) {
        return cached;
      }
    }
    const isRotated = config.axis_rotated;
    const hasLeftAxisRect = isRotated || !isRotated && !config.axis_y_inner;
    const leftAxisClass = isRotated ? $AXIS.axisX : $AXIS.axisY;
    const leftAxis = $el.main.select(`.${leftAxisClass}`).node();
    const leftLabel = hasAxis && config[`axis_${isRotated ? "x" : "y"}_label`];
    const needLabelRect = hasAxis && (isString(leftLabel) || isString(leftLabel.text) || /^inner-/.test(leftLabel == null ? void 0 : leftLabel.position));
    const label = needLabelRect ? $el.main.select(`.${leftAxisClass}-label`) : null;
    const labelNode = label && !label.empty() ? label.node() : null;
    const forceEval = !withoutRecompute;
    const rects = {
      label: labelNode ? getBoundingRect(labelNode, forceEval) : null,
      leftAxis: leftAxis && hasLeftAxisRect ? getBoundingRect(leftAxis, forceEval) : null,
      chart: getBoundingRect($el.chart.node(), forceEval)
    };
    const labelWidth = (_b = (_a = rects.label) == null ? void 0 : _a.left) != null ? _b : 0;
    const svgRect = (_c = rects.leftAxis) != null ? _c : { right: 0 };
    const chartRectLeft = rects.chart.left + labelWidth;
    const hasArc = $$.hasArcType();
    const svgLeft = svgRect.right - chartRectLeft - (hasArc ? 0 : $$.getCurrentPaddingByDirection("left", withoutRecompute));
    const result = svgLeft > 0 ? svgLeft : 0;
    cache.add(KEY.svgLeft, result);
    return result;
  },
  /**
   * Stretch the rendered surface to the container's current size, without redrawing.
   * Gives an immediate size feedback while the delayed resize is pending.
   * The drawn content keeps its previous geometry until the redraw takes place.
   * @private
   */
  previewResize() {
    var _a, _b, _c;
    const $$ = this;
    const { state, $el } = $$;
    const { current } = state;
    const width = $$.getCurrentWidth();
    const height = $$.getCurrentHeight();
    if (!width || !height || !current.width || !current.height || width === current.width && height === current.height) {
      return;
    }
    if (state.isCanvasMode) {
      const canvas = (_a = $$.canvasEngine) == null ? void 0 : _a.canvas;
      if (!canvas) {
        return;
      }
      $el.chart.style("min-height", `${height}px`);
      canvas.style.width = `${width}px`;
      canvas.style.height = `${Math.max(0, height - ((_c = (_b = $$.getCanvasBottomLegendHeight) == null ? void 0 : _b.call($$)) != null ? _c : 0))}px`;
    } else if ($el.svg) {
      $el.svg.attr("viewBox", `0 0 ${current.width} ${current.height}`).attr("preserveAspectRatio", "none").attr("width", width).attr("height", height);
    } else {
      return;
    }
    state.resizePreview = true;
  },
  /**
   * Drop the stretched state set by previewResize(), to render on exact pixels again.
   * @private
   */
  clearResizePreview() {
    const $$ = this;
    const { config, state, $el } = $$;
    if (!state.resizePreview) {
      return;
    }
    state.resizePreview = false;
    if (!state.isCanvasMode && $el.svg && config.resize_auto !== "viewBox") {
      $el.svg.attr("viewBox", null).attr("preserveAspectRatio", null);
    }
  },
  updateDimension(withoutAxis) {
    var _a, _b;
    const $$ = this;
    const { config, state: { hasAxis, isCanvasMode }, $el } = $$;
    if (hasAxis && !withoutAxis && $$.axis.x && config.axis_rotated) {
      (_a = $$.axis.subX) == null ? void 0 : _a.create($el.axis.subX);
    }
    $$.updateScales(withoutAxis);
    if (isCanvasMode) {
      (_b = $$.resizeCanvas) == null ? void 0 : _b.call($$);
      return;
    }
    $$.updateSvgSize();
    $$.transformAll(false);
  },
  updateSvgSize() {
    var _a;
    const $$ = this;
    const { config, state: { clip, current, hasAxis, width, height }, $el: { svg } } = $$;
    if (!svg) {
      (_a = $$.resizeCanvas) == null ? void 0 : _a.call($$);
      return;
    }
    $$.clearResizePreview();
    if (config.resize_auto === "viewBox") {
      svg.attr("viewBox", `0 0 ${current.width} ${current.height}`);
    } else {
      svg.attr("width", current.width).attr("height", current.height);
    }
    if (hasAxis) {
      const brush = svg.select(`.${$SUBCHART.brush} .overlay`);
      const brushSize = { width: 0, height: 0 };
      if (brush.size()) {
        brushSize.width = +brush.attr("width");
        brushSize.height = +brush.attr("height");
      }
      svg.selectAll([`#${clip.id}`, `#${clip.idGrid}`]).select("rect").attr("width", width).attr("height", height);
      svg.select(`#${clip.idXAxis}`).select("rect").call($$.setXAxisClipPath.bind($$));
      svg.select(`#${clip.idYAxis}`).select("rect").call($$.setYAxisClipPath.bind($$));
      clip.idSubchart && svg.select(`#${clip.idSubchart}`).select("rect").attr("width", width).attr("height", brushSize.height);
    }
  },
  /**
   * Get padding by the direction.
   * @param {string} type "top" | "bottom" | "left" | "right"
   * @param {boolean} [withoutRecompute=false] If set true, do not recompute the padding value.
   * @param {boolean} [withXAxisTickTextOverflow=false] If set true, calculate x axis tick text overflow.
   * @returns {number} padding value
   * @private
   */
  getCurrentPaddingByDirection(type, withoutRecompute = false, withXAxisTickTextOverflow = false) {
    var _a;
    const $$ = this;
    const { config, $el, state: { hasAxis, isCanvasMode } } = $$;
    const isRotated = config.axis_rotated;
    const isFitPadding = ((_a = config.padding) == null ? void 0 : _a.mode) === "fit";
    const paddingOption = isNumber(config[`padding_${type}`]) ? config[`padding_${type}`] : void 0;
    const axisId = hasAxis ? {
      top: isRotated ? "y2" : null,
      bottom: isRotated ? "y" : "x",
      left: isRotated ? "x" : "y",
      right: isRotated ? null : "y2"
    }[type] : null;
    const isLeftRight = /^(left|right)$/.test(type);
    const isAxisInner = axisId && config[`axis_${axisId}_inner`];
    const isAxisShow = axisId && config[`axis_${axisId}_show`];
    const axesLen = axisId ? config[`axis_${axisId}_axes`].length : 0;
    let axisSize = axisId ? isLeftRight ? $$.getAxisWidthByAxisId(axisId, withoutRecompute) : $$.getHorizontalAxisHeight(axisId) : 0;
    const defaultPadding = 20;
    let gap = 0;
    if (!isFitPadding && isLeftRight) {
      axisSize = ceil10(axisSize);
    }
    let padding = hasAxis && isLeftRight && (isAxisInner || isUndefined(paddingOption) && !isAxisShow) ? 0 : isFitPadding ? (isAxisShow ? axisSize : 0) + (paddingOption != null ? paddingOption : 0) : isUndefined(paddingOption) ? axisSize : paddingOption;
    if (isLeftRight && hasAxis) {
      if (axisId && (isFitPadding || isAxisInner) && config[`axis_${axisId}_label`].text) {
        padding += $$.axis.getAxisLabelPosition(axisId).isOuter ? defaultPadding : 0;
      }
      if (type === "right") {
        padding += isRotated ? !isFitPadding && isUndefined(paddingOption) ? 10 : 2 : !isAxisShow || isAxisInner ? isFitPadding ? 2 : 1 : 0;
        padding += withXAxisTickTextOverflow ? $$.axis.getXAxisTickTextY2Overflow(defaultPadding) : 0;
      } else if (type === "left" && isRotated && isUndefined(paddingOption)) {
        padding = !config.axis_x_show ? 1 : isFitPadding ? axisSize : Math.max(axisSize, 40);
      }
    } else {
      if (type === "top") {
        if ($el.title && $el.title.node() || isCanvasMode && config.title_text) {
          padding += $$.getTitlePadding();
        }
        gap = isRotated && !isAxisInner ? axesLen : 0;
      } else if (type === "bottom" && hasAxis && isRotated && !isAxisShow) {
        padding += 1;
      }
    }
    return padding + axisSize * axesLen - gap;
  },
  getCurrentPadding(withXAxisTickTextOverflow = false) {
    const $$ = this;
    const [top, bottom, left, right] = ["top", "bottom", "left", "right"].map((v) => $$.getCurrentPaddingByDirection(v, null, withXAxisTickTextOverflow));
    return { top, bottom, left, right };
  },
  /**
   * Get resetted padding values when 'padding=false' option is set
   * https://github.com/naver/billboard.js/issues/2367
   * @param {number|object} v Padding values to be resetted
   * @returns {number|object} Padding value
   * @private
   */
  getResettedPadding(v) {
    const $$ = this;
    const { config } = $$;
    const isNum = isNumber(v);
    let p = isNum ? 0 : {};
    if (config.padding === false) {
      !isNum && Object.keys(v).forEach((key) => {
        p[key] = !isEmpty(config.data_labels) && config.data_labels !== false && key === "top" ? v[key] : 0;
      });
    } else {
      p = v;
    }
    return p;
  },
  /**
   * Update size values
   * @param {boolean} isInit If is called at initialization
   * @private
   */
  updateSizes(isInit) {
    var _a, _b, _c, _d, _e;
    const $$ = this;
    const { config, state, $el: { legend } } = $$;
    const isRotated = config.axis_rotated;
    const isNonAxis = $$.hasArcType() || state.hasFunnel || state.hasTreemap;
    const isFitPadding = ((_a = config.padding) == null ? void 0 : _a.mode) === "fit";
    !isInit && $$.setContainerSize();
    const legendWidth = legend ? $$.getLegendWidth() : 0;
    const legendHeight = legend ? $$.getLegendHeight() : 0;
    const currLegend = {
      width: legendWidth,
      height: legendHeight
    };
    if (!isNonAxis && config.axis_x_show && config.axis_x_tick_autorotate) {
      $$.updateXAxisTickClip();
    }
    const legendSize = {
      right: config.legend_show && state.isLegendRight ? legendWidth + (isFitPadding ? 0 : 20) : 0,
      bottom: !config.legend_show || state.isLegendRight || state.isLegendInset ? 0 : legendHeight
    };
    const xAxisHeight = isRotated || isNonAxis ? 0 : $$.getHorizontalAxisHeight("x");
    const subchartXAxisHeight = config.subchart_axis_x_show && config.subchart_axis_x_tick_text_show ? xAxisHeight : 30;
    const subchartHeight = config.subchart_show && !isNonAxis ? config.subchart_size_height + subchartXAxisHeight : 0;
    const gaugeHeight = $$.hasType("gauge") && config.arc_needle_show && !config.gauge_fullCircle && !config.gauge_label_show ? 10 : 0;
    const padding = $$.getCurrentPadding(true);
    state.margin = !isNonAxis && isRotated ? {
      top: padding.top,
      right: isNonAxis ? 0 : padding.right + legendSize.right,
      bottom: legendSize.bottom + padding.bottom,
      left: subchartHeight + (isNonAxis ? 0 : padding.left)
    } : {
      top: (isFitPadding ? 0 : 4) + padding.top,
      // for top tick text
      right: isNonAxis ? 0 : padding.right + legendSize.right,
      bottom: gaugeHeight + subchartHeight + legendSize.bottom + padding.bottom,
      left: isNonAxis ? 0 : padding.left
    };
    state.margin = $$.getResettedPadding(state.margin);
    state.margin2 = isRotated ? {
      top: state.margin.top,
      right: NaN,
      bottom: 20 + legendSize.bottom,
      left: $$.state.rotatedPadding.left
    } : {
      top: state.current.height - subchartHeight - legendSize.bottom,
      right: NaN,
      bottom: subchartXAxisHeight + legendSize.bottom,
      left: state.margin.left
    };
    state.margin3 = {
      top: 0,
      right: NaN,
      bottom: 0,
      left: 0
    };
    (_b = $$.updateSizeForLegend) == null ? void 0 : _b.call($$, currLegend);
    state.width = state.current.width - state.margin.left - state.margin.right;
    state.height = state.current.height - state.margin.top - state.margin.bottom;
    if (state.width < 0) {
      state.width = 0;
    }
    if (state.height < 0) {
      state.height = 0;
    }
    state.width2 = isRotated ? state.margin.left - state.rotatedPadding.left - state.rotatedPadding.right : state.width;
    state.height2 = isRotated ? state.height : state.current.height - state.margin2.top - state.margin2.bottom;
    if (state.width2 < 0) {
      state.width2 = 0;
    }
    if (state.height2 < 0) {
      state.height2 = 0;
    }
    if ($$.hasArcType()) {
      const hasGauge = $$.hasType("gauge");
      const isLegendRight = config.legend_show && state.isLegendRight;
      const textWidth = (_c = state.hasRadar && $$.cache.get(KEY.radarTextWidth)) != null ? _c : 0;
      state.arcWidth = state.width - (isLegendRight ? currLegend.width + 10 : 0) - textWidth;
      state.arcHeight = state.height - (isLegendRight && !hasGauge ? 0 : 10);
      if ((_d = config.arc_rangeText_values) == null ? void 0 : _d.length) {
        if (hasGauge) {
          state.arcWidth -= 25;
          state.arcHeight -= 10;
          state.margin.left += 10;
        } else {
          state.arcHeight -= 20;
          state.margin.top += 10;
        }
      }
      if (hasGauge && !config.gauge_fullCircle) {
        state.arcHeight += state.height - $$.getPaddingBottomForGauge();
      }
      (_e = $$.updateRadius) == null ? void 0 : _e.call($$);
    }
    if (state.isLegendRight && isNonAxis) {
      state.margin3.left = state.arcWidth / 2 + state.radiusExpanded * 1.1;
    }
  }
});

;// ./src/ChartInternal/internals/style.ts


/* harmony default export */ var style = ({
  /**
   * Add props color css rule to given selector
   * @param {boolean} withShape Set shpes' prefix class
   * @param {string} selector CSS selector
   * @param {Array} props CSS props list
   * @param {function} propsFn Function to retrieve value or determine for props
   * @returns {function}
   * @private
   */
  setCssRule(withShape, selector, props, propsFn) {
    const $$ = this;
    const { config, state: { cssRule, style } } = $$;
    return config.boost_useCssRule ? (selection) => {
      selection.each((d) => {
        const res = propsFn && (propsFn == null ? void 0 : propsFn.call($$, d));
        const shapeSelector = `${withShape ? `.${$SHAPE.shapes + $$.getTargetSelectorSuffix(d.id)}` : ""}${selector}`;
        selector in cssRule && style.sheet.deleteRule(cssRule[shapeSelector]);
        $$.state.cssRule[shapeSelector] = addCssRules(
          style,
          shapeSelector,
          props.filter(Boolean).map((v) => isString(res) && v.indexOf(":") === -1 ? `${v}: ${res}` : v || "")
        );
      });
    } : () => {
    };
  },
  /**
   * Get style prop value
   * @param {function|string} v Value
   * @returns {string|null}
   * @private
   */
  getStylePropValue(v) {
    const { config: { boost_useCssRule: useCssRule } } = this;
    return useCssRule ? null : isFunction(v) ? v.bind(this) : v;
  }
});

;// ./src/ChartInternal/internals/text.util.ts



function getRotateAnchor(angle) {
  let anchor = "middle";
  if (angle > 0 && angle <= 170) {
    anchor = "end";
  } else if (angle > 190 && angle <= 360) {
    anchor = "start";
  }
  return anchor;
}
function setRotatePos(d, pos, anchor, isRotated, isInverted) {
  var _a;
  const $$ = this;
  const { value } = d;
  const isCandlestickType = $$.isCandlestickType(d);
  const isNegative = isNumber(value) && value < 0 || isCandlestickType && !((_a = $$.getCandlestickData(d)) == null ? void 0 : _a._isUp);
  let { x, y } = pos;
  const gap = 4;
  const doubleGap = gap * 2;
  if (isRotated) {
    if (anchor === "start") {
      x += isNegative ? 0 : doubleGap;
      y += gap;
    } else if (anchor === "middle") {
      x += doubleGap;
      y -= doubleGap;
    } else if (anchor === "end") {
      isNegative && (x -= doubleGap);
      y += gap;
    }
  } else {
    if (anchor === "start") {
      x += gap;
      isNegative && (y += doubleGap * 2);
    } else if (anchor === "middle") {
      y -= doubleGap;
    } else if (anchor === "end") {
      x -= gap;
      isNegative && (y += doubleGap * 2);
    }
    if (isInverted) {
      y += isNegative ? -17 : isCandlestickType ? 13 : 7;
    }
  }
  return { x, y };
}
function getTextPos(d, type) {
  var _a;
  const position = this.config.data_labels_position;
  const { id, index, value } = d;
  return (_a = isFunction(position) ? position.bind(this.api)(type, value, id, index, this.$el.text) : (id in position ? position[id] : position)[type]) != null ? _a : 0;
}
function updateTextBorder(text, pos, rectClass) {
  var _a, _b;
  const $$ = this;
  const { config, $T } = $$;
  const isRotated = config.axis_rotated;
  const {
    border: {
      padding = "3 5",
      radius = 10,
      stroke = "#000",
      strokeWidth = 1,
      fill = "none"
    }
  } = config.data_labels;
  const borderPadding = parseShorthand(padding);
  const applyStyle = config.data_labels.border !== true;
  const textRect = getBBox(text);
  let borderRect = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(text.previousElementSibling);
  if (borderRect.empty() || ((_a = borderRect.node()) == null ? void 0 : _a.tagName) !== "rect" || !((_b = borderRect.attr("class")) == null ? void 0 : _b.includes(rectClass))) {
    borderRect = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(text.parentNode).insert("rect", () => text).attr("class", `${$TEXT.textBorderRect} ${rectClass}`).attr(
      "width",
      textRect.width + (applyStyle ? borderPadding.left + borderPadding.right : 0)
    ).attr(
      "height",
      textRect.height + (applyStyle ? borderPadding.top + borderPadding.bottom : 0)
    );
    if (applyStyle) {
      borderRect.style("fill", fill).style("stroke", stroke).style("stroke-width", `${strokeWidth}px`).attr("rx", radius).attr("ry", radius);
    }
  }
  $T(borderRect).attr(
    "x",
    pos.x - (applyStyle ? borderPadding.left : 0) - (isRotated ? 0 : textRect.width / 2)
  ).attr("y", pos.y - (applyStyle ? borderPadding.top : 0) - textRect.height / 4 * 3.2);
}
function meetsLabelThreshold(ratio = 0, type) {
  const $$ = this;
  const { config } = $$;
  const threshold = config[`${type}_label_threshold`] || 0;
  return ratio >= threshold;
}
function updateTextImage() {
  const $$ = this;
  const { $el: { text }, config } = $$;
  const isArc = $$.state.arcWidth;
  if (isArc ? $$.getArcLabelConfig("image") : config.data_labels.image) {
    text.filter(function() {
      const prev = this.previousElementSibling;
      if (prev) {
        return prev.tagName !== "image" || !prev.classList.contains($TEXT.textLabelImage);
      }
      return true;
    }).each(function(d) {
      var _a, _b, _c, _d;
      const image = getDataLabelImgUrl.call($$, d);
      if (!image) {
        return;
      }
      const { url, width, height, pos } = image;
      if (url) {
        const parentNode = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this.parentNode);
        parentNode == null ? void 0 : parentNode.insert(
          "image",
          `${(_b = (_a = this.getAttribute("class")) == null ? void 0 : _a.replace(/(?:^(.)|\s)/g, ".$1")) != null ? _b : "text"}`
        ).style("opacity", "0").attr("href", (d2) => tplProcess(url, {
          ID: "id" in d2 ? d2.id : d2.data.id
        })).attr("class", $TEXT.textLabelImage).style("pointer-events", "none").attr("width", width).attr("height", height).attr("transform", pos ? `translate(${(_c = pos.x) != null ? _c : 0} ${(_d = pos.y) != null ? _d : 0})` : null);
      }
    });
  }
}
function getDataLabelImgUrl(d) {
  var _a;
  const $$ = this;
  const { config, state } = $$;
  const image = state.arcWidth ? $$.getArcLabelConfig("image") : config.data_labels.image;
  if (isFunction(image)) {
    return (_a = image.call($$.api, d.value, d.id, d.index)) != null ? _a : {
      url: "",
      width: 0,
      height: 0,
      pos: { x: 0, y: 0 }
    };
  } else if (image) {
    const { url = "", width = 0, height = 0, pos } = image;
    return {
      url,
      width,
      height,
      pos
    };
  }
  return null;
}
function updateTextImagePos(textNode, pos, textRect) {
  var _a;
  const $$ = this;
  const { config, state: { arcWidth, hasTreemap } } = $$;
  const isRotated = config.axis_rotated;
  const image = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(textNode.previousElementSibling);
  const isShown = (textNode2) => {
    var _a2;
    const isShown2 = textNode2.style.opacity !== "0" && textNode2.style.fillOpacity !== "0";
    return (arcWidth ? textNode2.textContent : isShown2) && ((_a2 = this.previousElementSibling) == null ? void 0 : _a2.tagName) !== "image";
  };
  if (!image.empty() && ((_a = image.node()) == null ? void 0 : _a.tagName) === "image") {
    const textDimension = textRect || getBoundingRect(textNode);
    const w = +image.attr("width") / 2;
    const h = +image.attr("height") / 2;
    let x = pos.x - w;
    let y = pos.y - h - textDimension.height / 2;
    if (isRotated) {
      pos.x += w;
    } else {
      if (hasTreemap) {
        x = -w;
        y = -(h * 2 + textDimension.height);
      }
      if (!($$.hasType("pie") || $$.hasType("polar"))) {
        pos.y += h;
      }
    }
    $$.$T(image).style("opacity", isShown(textNode) ? null : "0").attr("x", x).attr("y", y);
  }
}
function batchGetBBox(elements) {
  return toMap(
    elements,
    (element) => element,
    (element) => getBBox(element, true)
  );
}


;// ./src/ChartInternal/internals/text.ts





/* harmony default export */ var internals_text = ({
  opacityForText(d) {
    const $$ = this;
    return $$.isBarType(d) && !meetsLabelThreshold.call($$, Math.abs($$.getRatio("bar", d)), "bar") ? "0" : $$.hasDataLabel() ? null : "0";
  },
  /**
   * Initializes the text
   * @private
   */
  initText() {
    const { $el } = this;
    $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $TEXT.chartTexts).style("pointer-events", $el.funnel || $el.treemap ? "none" : null);
  },
  /**
   * Update chartText
   * @param {object} targets $$.data.targets
   * @private
   */
  updateTargetsForText(targets) {
    const $$ = this;
    const classChartText = $$.getChartClass("Text");
    const classTexts = $$.getClass("texts", "id");
    const classFocus = $$.classFocus.bind($$);
    const mainTextUpdate = $$.$el.main.select(`.${$TEXT.chartTexts}`).selectAll(`.${$TEXT.chartText}`).data($$.filterNullish(targets)).attr("class", (d) => `${classChartText(d)}${classFocus(d)}`.trim());
    const mainTextEnter = mainTextUpdate.enter().append("g").style("opacity", "0").attr("class", classChartText).call(
      $$.setCssRule(
        true,
        ` .${$TEXT.text}`,
        ["fill", "pointer-events:none"],
        $$.updateTextColor
      )
    );
    mainTextEnter.append("g").attr("class", classTexts);
  },
  /**
   * Update text
   * @private
   */
  updateText() {
    const $$ = this;
    const { $el, $T, config, axis } = $$;
    const classText = $$.getClass("text", "index");
    const labelsCentered = config.data_labels.centered;
    const text = $el.main.selectAll(`.${$TEXT.texts}`).selectAll(`.${$TEXT.text}`).data($$.labelishData.bind($$));
    $T(text.exit()).style("fill-opacity", "0").remove();
    $el.text = text.enter().append("text").merge(text).attr("class", classText).attr("text-anchor", (d) => {
      const isInverted = config[`axis_${axis == null ? void 0 : axis.getId(d.id)}_inverted`];
      let isEndAnchor = isInverted ? d.value > 0 : d.value < 0;
      if ($$.isCandlestickType(d)) {
        const data = $$.getCandlestickData(d);
        isEndAnchor = !(data == null ? void 0 : data._isUp);
      } else if ($$.isTreemapType(d)) {
        return labelsCentered ? "middle" : "start";
      }
      return config.axis_rotated ? isEndAnchor ? "end" : "start" : "middle";
    }).style("fill", $$.getStylePropValue($$.updateTextColor)).style("fill-opacity", "0").each(function(d, i, texts) {
      const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      let { value } = d;
      if ($$.isBubbleZType(d)) {
        value = $$.getBubbleZData(value, "z");
      } else if ($$.isCandlestickType(d)) {
        const data = $$.getCandlestickData(d);
        if (data) {
          value = data.close;
        }
      }
      value = $$.isTreemapType(d) ? $$.treemapDataLabelFormat(d)(node) : $$.dataLabelFormat(d.id)(value, d.id, d.index, texts);
      if (isNumber(value)) {
        this.textContent = value;
      } else {
        setTextValue(node, value, void 0, true);
      }
    });
    updateTextImage.call($$);
  },
  updateTextColor(d) {
    const $$ = this;
    const { config } = $$;
    const labelColors = config.data_labels_colors;
    const defaultColor = $$.isArcType(d) && !$$.isRadarType(d) || $$.isFunnelType(d) || $$.isTreemapType(d) ? null : $$.color(d);
    let color;
    if (isString(labelColors)) {
      color = labelColors;
    } else if (isObject(labelColors)) {
      const { id } = d.data || d;
      color = labelColors[id];
    } else if (isFunction(labelColors)) {
      color = labelColors.bind($$.api)(defaultColor, d);
    }
    if ($$.isCandlestickType(d) && !isFunction(labelColors)) {
      const value = $$.getCandlestickData(d);
      if (!(value == null ? void 0 : value._isUp)) {
        const downColor = config.candlestick_color_down;
        color = isObject(downColor) ? downColor[d.id] : downColor;
      }
    }
    return color || defaultColor;
  },
  /**
   * Update data label text background color
   * @param {object} d Data object
   * @param {object|string|function} option option object
   * @returns {string|null}
   * @private
   */
  updateTextBGColor(d, option) {
    const $$ = this;
    const { $el: { defs } } = $$;
    let color = "";
    if (option) {
      const id = isString(option) ? "" : $$.getTargetSelectorSuffix("id" in d ? d.id : d.data.id);
      const filter = defs.select(["filter[id*='labels-bg", "']"].join(id));
      if (filter.size()) {
        color = `url(#${filter.attr("id")})`;
      }
      if (isFunction(option)) {
        $$.generateTextBGColorFilter(option);
        const defaultColor = $$.color(d);
        const bgColor = option.bind($$.api)(defaultColor, d);
        if (bgColor) {
          filter.select("feFlood").attr("flood-color", bgColor);
        } else {
          color = "";
        }
      }
    }
    return color || null;
  },
  /**
   * Redraw chartText
   * @param {function} getX Positioning function for x
   * @param {function} getY Positioning function for y
   * @param {boolean} forFlow Weather is flow
   * @param {boolean} withTransition transition is enabled
   * @returns {Array}
   * @private
   */
  redrawText(getX, getY, forFlow, withTransition) {
    const $$ = this;
    const { $T, axis, config, state: { hasTreemap } } = $$;
    const t = getRandom(true);
    const isRotated = config.axis_rotated;
    const angle = config.data_labels.rotate;
    const anchorString = getRotateAnchor(angle);
    const rotateString = angle ? `rotate(${angle})` : "";
    const text = $$.$el.text.style("fill", $$.getStylePropValue($$.updateTextColor)).attr(
      "filter",
      (d) => $$.updateTextBGColor.bind($$)(d, config.data_labels_backgroundColors)
    ).style("fill-opacity", forFlow ? 0 : $$.opacityForText.bind($$));
    const dimensions = /* @__PURE__ */ new Map();
    const elementsToMeasure = [];
    text.each(function(d) {
      const element = this;
      dimensions.set(element, { rect: getBoundingRect(element) });
      if (config.data_labels.centered && ($$.isBarType(d) || $$.isTreemapType(d))) {
        elementsToMeasure.push(element);
      }
    });
    if (elementsToMeasure.length > 0) {
      batchGetBBox(elementsToMeasure).forEach((bbox, element) => {
        const dimension = dimensions.get(element);
        dimension && (dimension.bbox = bbox);
      });
    }
    text.each(function(d, i) {
      const labelDimension = dimensions.get(this);
      const node = $T(
        hasTreemap && this.childElementCount ? this.parentNode : this,
        !!(withTransition && (this.getAttribute("x") || this.getAttribute("transform"))),
        t
      );
      const isInverted = config[`axis_${axis == null ? void 0 : axis.getId(d.id)}_inverted`];
      let pos = {
        x: getX.call(this, d, i, labelDimension),
        y: getY.call(this, d, i, labelDimension)
      };
      if (angle) {
        pos = setRotatePos.bind($$)(d, pos, anchorString, isRotated, isInverted);
        node.attr("text-anchor", anchorString);
      }
      updateTextImagePos.call($$, this, pos, labelDimension == null ? void 0 : labelDimension.rect);
      if (this.childElementCount || angle) {
        node.attr("transform", `translate(${pos.x} ${pos.y}) ${rotateString}`);
      } else {
        node.attr("x", pos.x).attr("y", pos.y);
      }
      config.data_labels.border && updateTextBorder.call($$, node.node(), pos, `${$TEXT.textBorderRect}-${i}`);
    });
    return true;
  },
  /**
   * Gets the getBoundingClientRect value of the element
   * @param {HTMLElement|d3.selection|Array} source Target element
   * @param {string} className Class name
   * @returns {object} value of element.getBoundingClientRect()
   * @private
   */
  getTextRect(source, className) {
    var _a, _b;
    const $$ = this;
    let cacheKey;
    let base;
    let text;
    if (Array.isArray(source)) {
      cacheKey = `${KEY.textRect}-${source.join("_")}`;
    } else {
      base = (_b = (_a = source.node) == null ? void 0 : _a.call(source)) != null ? _b : source;
      if (!/text/i.test(base.tagName)) {
        base = base.querySelector("text");
      }
      text = base.textContent;
      cacheKey = `${KEY.textRect}-${text.replace(/\W/g, "_")}`;
    }
    const rect = $$.cache.get(cacheKey) || [];
    if (rect.length === 0) {
      ($$.$el.svg || $$.$el.chart.select("svg")).selectAll(`.${$COMMON.dummy}`).data(text ? [text] : source).enter().append("text").style("visibility", "hidden").style("font", base ? (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(base).style("font") : null).classed(className || $COMMON.dummy, true).text((d) => d).each(function(v, i) {
        rect[i] = getBoundingRect(this);
      }).remove();
      $$.cache.add(cacheKey, rect);
    }
    return rect.length > 1 ? rect : rect[0];
  },
  /**
   * Gets the x or y coordinate of the text
   * @param {object} indices Indices values
   * @param {boolean} forX whether or not to x
   * @returns {function} coordinates
   * @private
   */
  generateXYForText(indices, forX) {
    const $$ = this;
    const { state: { hasRadar, hasFunnel, hasTreemap } } = $$;
    const types = Object.keys(indices);
    const points = {};
    const getter = forX ? $$.getXForText : $$.getYForText;
    hasFunnel && types.push("funnel");
    hasRadar && types.push("radar");
    hasTreemap && types.push("treemap");
    types.forEach((v) => {
      points[v] = $$[`generateGet${capitalize(v)}Points`](indices[v], false);
    });
    return function(d, i, labelDimension) {
      const type = $$.isAreaType(d) && "area" || $$.isBarType(d) && "bar" || $$.isCandlestickType(d) && "candlestick" || $$.isFunnelType(d) && "funnel" || $$.isRadarType(d) && "radar" || $$.isTreemapType(d) && "treemap" || "line";
      return getter.call($$, points[type](d, i), d, this, labelDimension);
    };
  },
  /**
   * Get centerized text position for bar type data.label.text
   * @param {object} d Data object
   * @param {Array} points Data points position
   * @param {HTMLElement} textElement Data label text element
   * @param {string} type 'x' or 'y'
   * @param {object} labelDimension Optional cached label dimensions
   * @returns {number} Position value
   * @private
   */
  getCenteredTextPos(d, points, textElement, type, labelDimension) {
    const $$ = this;
    const { config } = $$;
    const isRotated = config.axis_rotated;
    const isBarType = $$.isBarType(d);
    const isTreemapType = $$.isTreemapType(d);
    if (config.data_labels.centered && (isBarType || isTreemapType)) {
      const rect = (labelDimension == null ? void 0 : labelDimension.bbox) || getBBox(textElement);
      if (isBarType) {
        const isPositive = $$.getRangedData(d, null, "bar") >= 0;
        if (isRotated) {
          const w = (isPositive ? points[1][1] - points[0][1] : points[0][1] - points[1][1]) / 2 + rect.width / 2;
          return isPositive ? -w - 3 : w + 2;
        } else {
          const h = (isPositive ? points[0][1] - points[1][1] : points[1][1] - points[0][1]) / 2 + rect.height / 2;
          return isPositive ? h : -h - 2;
        }
      } else if (isTreemapType) {
        return type === "x" ? (points[1][0] - points[0][0]) / 2 : (
          // X: Move to horizontal center of rect
          (points[1][1] - points[0][1]) / 2 - rect.y - rect.height / 2
        );
      }
    }
    return 0;
  },
  /**
   * Gets the x coordinate of the text
   * @param {object} points Data points position
   * @param {object} d Data object
   * @param {HTMLElement} textElement Data label text element
   * @param {object} labelDimension Optional cached label dimensions
   * @returns {number} x coordinate
   * @private
   */
  getXForText(points, d, textElement, labelDimension) {
    var _a, _b, _c;
    const $$ = this;
    const { config } = $$;
    const isRotated = config.axis_rotated;
    const isFunnelType = $$.isFunnelType(d);
    const isTreemapType = $$.isTreemapType(d);
    let xPos = points ? points[0][0] : 0;
    if ($$.isCandlestickType(d)) {
      if (isRotated) {
        xPos = ((_a = $$.getCandlestickData(d)) == null ? void 0 : _a._isUp) ? points[2][2] + 4 : points[2][1] - 4;
      } else {
        xPos += (points[1][0] - xPos) / 2;
      }
    } else if (isFunnelType) {
      if (points) {
        xPos = (_c = (_b = points[2]) == null ? void 0 : _b[0]) != null ? _c : xPos;
      } else {
        return getElementPos(textElement, "x");
      }
    } else if (isTreemapType) {
      xPos += config.data_labels.centered ? 0 : 5;
    } else {
      if (isRotated) {
        const isInverted = config[`axis_${$$.axis.getId(d.id)}_inverted`];
        const padding = $$.isBarType(d) ? 4 : 6;
        const value = d.value;
        xPos = points[2][1];
        xPos += padding * ((isInverted ? value > 0 : value < 0) ? -1 : 1);
      } else {
        xPos = $$.hasType("bar") ? (points[2][0] + points[0][0]) / 2 : xPos;
      }
    }
    if (isRotated || isTreemapType || isFunnelType) {
      xPos += $$.getCenteredTextPos(d, points, textElement, "x", labelDimension);
    }
    return xPos + getTextPos.call(this, d, "x");
  },
  /**
   * Gets the y coordinate of the text
   * @param {object} points Data points position
   * @param {object} d Data object
   * @param {HTMLElement} textElement Data label text element
   * @param {object} labelDimension Optional cached label dimensions
   * @returns {number} y coordinate
   * @private
   */
  getYForText(points, d, textElement, labelDimension) {
    var _a, _b;
    const $$ = this;
    const { axis, config, state } = $$;
    const isRotated = config.axis_rotated;
    const isInverted = config[`axis_${axis == null ? void 0 : axis.getId(d.id)}_inverted`];
    const isBarType = $$.isBarType(d);
    const isFunnelType = $$.isFunnelType(d);
    const isTreemapType = $$.isTreemapType(d);
    const r = config.point_r;
    const rect = (labelDimension == null ? void 0 : labelDimension.rect) || getBoundingRect(textElement);
    let { value } = d;
    let baseY = 3;
    let yPos;
    if ($$.isCandlestickType(d)) {
      value = $$.getCandlestickData(d);
      if (isRotated) {
        yPos = points[0][0];
        yPos += (points[1][0] - yPos) / 2 + baseY;
      } else {
        yPos = value && value._isUp ? points[2][2] - baseY : points[2][1] + baseY * 4;
        if (isInverted) {
          yPos += 15 * (value._isUp ? 1 : -1);
        }
      }
    } else if (isFunnelType) {
      if (points) {
        yPos = ((_b = (_a = points[2]) == null ? void 0 : _a[1]) != null ? _b : points[0][1]) + rect.height / 2 - 3;
      } else {
        return getElementPos(textElement, "y");
      }
    } else if (isTreemapType) {
      yPos = points[0][1] + (config.data_labels.centered ? 0 : rect.height + 5);
    } else {
      if (isRotated) {
        yPos = (points[0][0] + points[2][0] + rect.height * 0.6) / 2;
      } else {
        yPos = points[2][1];
        if (isNumber(r) && r > 5 && ($$.isLineType(d) || $$.isScatterType(d))) {
          baseY += config.point_r / 2.3;
        }
        if (value < 0 || value === 0 && !state.hasPositiveValue && state.hasNegativeValue) {
          yPos += isInverted ? isBarType ? -3 : -5 : rect.height + (isBarType ? -baseY : baseY);
        } else {
          let diff = -baseY * 2;
          if (isBarType) {
            diff = -baseY;
          } else if ($$.isBubbleType(d)) {
            diff = baseY;
          }
          if (isInverted) {
            diff = isBarType ? 10 : 15;
          }
          yPos += diff;
        }
      }
    }
    if (!isRotated || isTreemapType) {
      yPos += $$.getCenteredTextPos(d, points, textElement, "y", labelDimension);
    }
    return yPos + getTextPos.call(this, d, "y");
  },
  /**
   * Calculate if two or more text nodes are overlapping
   * Mark overlapping text nodes with "text-overlapping" class
   * @param {string} id Axis id
   * @param {ChartInternal} $$ ChartInternal context
   * @param {string} selector Selector string
   * @private
   */
  markOverlapped(id, $$, selector) {
    const textNodes = $$.$el.arcs.selectAll(selector);
    const filteredTextNodes = textNodes.filter((node) => node.data.id !== id);
    const textNode = textNodes.filter((node) => node.data.id === id);
    const translate = getTranslation(textNode.node());
    const calcHypo = (x, y) => Math.sqrt(x * x + y * y);
    if (!textNode.node()) {
      return;
    }
    const fontSize = parseInt(textNode.style("font-size"), 10);
    const overlapStates = [];
    filteredTextNodes.each(function() {
      const coordinate = getTranslation(this);
      const nodeForWidth = calcHypo(translate.e, translate.f) > calcHypo(coordinate.e, coordinate.f) ? textNode : (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      const overlapsX = Math.ceil(Math.abs(translate.e - coordinate.e)) < Math.ceil(nodeForWidth.node().getComputedTextLength());
      const overlapsY = Math.ceil(Math.abs(translate.f - coordinate.f)) < fontSize;
      overlapStates.push({
        node: this,
        overlaps: overlapsX && overlapsY
      });
    });
    overlapStates.forEach(({ node, overlaps }) => {
      (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(node).classed($TEXT.TextOverlapping, overlaps);
    });
  },
  /**
   * Calculate if two or more text nodes are overlapping
   * Remove "text-overlapping" class on selected text nodes
   * @param {ChartInternal} $$ ChartInternal context
   * @param {string} selector Selector string
   * @private
   */
  undoMarkOverlapped($$, selector) {
    $$.$el.arcs.selectAll(selector).each(function() {
      (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.selectAll)([this, this.previousSibling]).classed($TEXT.TextOverlapping, false);
    });
  }
});

;// ./src/ChartInternal/internals/title.ts


function _getTextXPos(pos = "left", width) {
  const isNum = isNumber(width);
  if (pos.includes("center")) {
    return isNum ? width / 2 : "middle";
  }
  if (pos.includes("right")) {
    return isNum ? width : "end";
  }
  return isNum ? 0 : "start";
}
function _getCanvasTitleHeight($$) {
  var _a, _b, _c, _d, _e, _f, _g, _h;
  const { config, $el } = $$;
  const font = ((_c = (_b = (_a = $$.canvasTheme) == null ? void 0 : _a.style) == null ? void 0 : _b.title) == null ? void 0 : _c.font) || ((_f = (_e = (_d = $$.canvasTheme) == null ? void 0 : _d.style) == null ? void 0 : _e.label) == null ? void 0 : _f.font) || "14px sans-serif";
  const chart = (_h = (_g = $el.chart) == null ? void 0 : _g.node) == null ? void 0 : _h.call(_g);
  const doc = chart == null ? void 0 : chart.ownerDocument;
  if (chart && doc && config.title_text) {
    const svg = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
    const text = doc.createElementNS("http://www.w3.org/2000/svg", "text");
    svg.style.cssText = "position:absolute;visibility:hidden;left:-10000px;top:-10000px;";
    text.setAttribute("class", $TEXT.title);
    text.style.font = font;
    text.textContent = String(config.title_text);
    svg.appendChild(text);
    chart.appendChild(svg);
    const height = getBoundingRect(text).height;
    svg.remove();
    if (height) {
      return height;
    }
  }
  return config.title_text ? parseFloat(font) || 14 : 0;
}
/* harmony default export */ var internals_title = ({
  /**
   * Initializes the title
   * @private
   */
  initTitle() {
    const $$ = this;
    const { config, $el } = $$;
    if (config.title_text) {
      $el.title = $el.svg.append("g");
      const text = $el.title.append("text").style("text-anchor", _getTextXPos(config.title_position)).attr("class", $TEXT.title);
      setTextValue(text, config.title_text, [0.3, 1.5]);
    }
  },
  /**
   * Redraw title
   * @private
   */
  redrawTitle() {
    const $$ = this;
    const { config, state: { current }, $el: { title } } = $$;
    if (title) {
      const x = _getTextXPos(config.title_position, current.width);
      const y = (config.title_padding.top || 0) + $$.getTextRect($$.$el.title, $TEXT.title).height;
      title.attr("transform", `translate(${x}, ${y})`);
    }
  },
  /**
   * Get canvas title height using the same SVG text measurement as title padding.
   * @returns {number} Title height
   * @private
   */
  getCanvasTitleHeight() {
    return _getCanvasTitleHeight(this);
  },
  /**
   * Get title padding
   * @returns {number} padding value
   * @private
   */
  getTitlePadding() {
    const $$ = this;
    const { $el: { title }, config, state } = $$;
    const paddingTop = config.title_padding.top || 0;
    const paddingBottom = config.title_padding.bottom || 0;
    if (state.isCanvasMode && config.title_text) {
      return paddingTop + $$.getCanvasTitleHeight() + paddingBottom;
    }
    if (!(title == null ? void 0 : title.node())) {
      return paddingTop + paddingBottom;
    }
    const titleNode = title.node();
    const translateY = getElementPos(titleNode, "y");
    if (translateY) {
      const bbox = getBBox(titleNode);
      return translateY + bbox.y + bbox.height + paddingBottom;
    }
    return paddingTop + $$.getTextRect(title, $TEXT.title).height + paddingBottom;
  }
});

;// ./src/ChartInternal/internals/tooltip.ts




const RE_WHITESPACE = /(\r?\n|\t)/g;
const RE_TOOLTIP_TPL = /{{(.*)}}/;
/* harmony default export */ var internals_tooltip = ({
  /**
   * Initializes the tooltip
   * @private
   */
  initTooltip() {
    const $$ = this;
    const { config, $el } = $$;
    $el.tooltip = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(config.tooltip_contents.bindto);
    if ($el.tooltip.empty()) {
      $el.tooltip = $el.chart.append("div").attr("class", $TOOLTIP.tooltipContainer).style("position", "absolute").style("pointer-events", "none").style("display", "none");
    }
    $$.bindTooltipResizePos();
  },
  /**
   * Show tooltip at initialization.
   * Is called only when tooltip.init.show=true option is set
   * @private
   */
  initShowTooltip() {
    var _a;
    const $$ = this;
    const { config, $el, state: { hasAxis, hasRadar } } = $$;
    if (config.tooltip_init_show) {
      const isArc = !(hasAxis || hasRadar);
      if (((_a = $$.axis) == null ? void 0 : _a.isTimeSeries()) && isString(config.tooltip_init_x)) {
        config.tooltip_init_x = parseDate.call($$, config.tooltip_init_x);
      }
      $$.api.tooltip.show({
        data: {
          [isArc ? "index" : "x"]: config.tooltip_init_x
        }
      });
      const position = config.tooltip_init_position;
      if (!config.tooltip_contents.bindto && !isEmpty(position)) {
        const { top = 0, left = 50 } = position;
        $el.tooltip.style("top", isString(top) ? top : `${top}px`).style("left", isString(left) ? left : `${left}px`).style("display", null);
      }
    }
  },
  /**
   * Get the tooltip HTML string
   * @param  {Array} args Arguments
   * @returns {string} Formatted HTML string
   * @private
   */
  getTooltipHTML(...args) {
    const $$ = this;
    const { api, config } = $$;
    return sanitize(
      isFunction(config.tooltip_contents) ? config.tooltip_contents.bind(api)(...args) : $$.getTooltipContent(...args)
    );
  },
  /**
   * Returns the tooltip content(HTML string)
   * @param {object} d data
   * @param {function} defaultTitleFormat Default title format
   * @param {function} defaultValueFormat Default format for each data value in the tooltip.
   * @param {function} color Color function
   * @returns {string} html
   * @private
   */
  getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) {
    var _a;
    const $$ = this;
    const { api, config, state, $el } = $$;
    const titleFn = config.tooltip_format_title;
    const nameFn = config.tooltip_format_name;
    const valueFn = config.tooltip_format_value;
    const titleFormat = isFunction(titleFn) ? titleFn.bind(api) : defaultTitleFormat;
    const nameFormat = isFunction(nameFn) ? nameFn.bind(api) : ((name) => name);
    const boundValueFn = isFunction(valueFn) ? valueFn.bind(api) : null;
    const valueFormat = (v, ratio, id, index) => {
      let fn = boundValueFn;
      if (!fn) {
        if (state.hasTreemap || $$.isStackNormalized() && (!$$.isStackNormalizedPerGroup() || $$.isGrouped(id))) {
          fn = (v2, ratio2) => `${(ratio2 * 100).toFixed(2)}%`;
        } else {
          fn = defaultValueFormat;
        }
      }
      return fn(v, ratio, id, index);
    };
    const order = config.tooltip_order;
    const getRowValue = (row2) => $$.axis && $$.isBubbleZType(row2) ? $$.getBubbleZData(row2.value, "z") : $$.getBaseValue(row2);
    const getBgColor = $$.levelColor ? (row2) => $$.levelColor(row2.value) : (row2) => color(row2);
    const contents = config.tooltip_contents;
    const tplStr = contents.template;
    const targetIds = $$.mapToTargetIds();
    if (order === null && config.data_groups.length) {
      const ids = $$.orderTargets($$.data.targets).map((i2) => i2.id).reverse();
      d.sort((a, b) => {
        let v1 = a ? a.value : null;
        let v2 = b ? b.value : null;
        if (v1 > 0 && v2 > 0) {
          v1 = a.id ? ids.indexOf(a.id) : null;
          v2 = b.id ? ids.indexOf(b.id) : null;
        }
        return v1 - v2;
      });
    } else if (/^(asc|desc)$/.test(order)) {
      const isAscending = order === "asc";
      d.sort((a, b) => {
        const v1 = a ? getRowValue(a) : null;
        const v2 = b ? getRowValue(b) : null;
        return isAscending ? v1 - v2 : v2 - v1;
      });
    } else if (isFunction(order)) {
      d.sort(order.bind(api));
    }
    const tpl = $$.getTooltipContentTemplate(tplStr);
    const len = d.length;
    let text;
    let row;
    let param;
    let value;
    let i;
    for (i = 0; i < len; i++) {
      row = d[i];
      const rowValue = row && getRowValue(row);
      if (!row || !(rowValue || rowValue === 0)) {
        continue;
      }
      if (isUndefined(text)) {
        const title = (state.hasAxis || state.hasRadar) && titleFormat(row.x);
        text = tplProcess(tpl[0], {
          CLASS_TOOLTIP: $TOOLTIP.tooltip,
          TITLE: isValue(title) ? tplStr ? title : `<tr><th colspan="2">${title}</th></tr>` : ""
        });
      }
      if (!row.ratio && $el.arcs) {
        param = ["arc", $$.$el.arcs.select(`path.${$ARC.arc}-${row.id}`).data()[0]];
        row.ratio = $$.getRatio(...param);
      }
      param = [row.ratio, row.id, row.index];
      if ($$.isAreaRangeType(row)) {
        const [high, low] = ["high", "low"].map(
          (v) => valueFormat($$.getRangedData(row, v), ...param)
        );
        const mid = valueFormat(getRowValue(row), ...param);
        value = `<b>Mid:</b> ${mid} <b>High:</b> ${high} <b>Low:</b> ${low}`;
      } else if ($$.isCandlestickType(row)) {
        const [open, high, low, close, volume] = ["open", "high", "low", "close", "volume"].map((v) => {
          const value2 = $$.getRangedData(row, v, "candlestick");
          return value2 ? valueFormat(
            $$.getRangedData(row, v, "candlestick"),
            ...param
          ) : void 0;
        });
        value = `<b>Open:</b> ${open} <b>High:</b> ${high} <b>Low:</b> ${low} <b>Close:</b> ${close}${volume ? ` <b>Volume:</b> ${volume}` : ""}`;
      } else if ($$.isBarRangeType(row)) {
        const { value: rangeValue, id, index } = row;
        value = `${valueFormat(rangeValue, void 0, id, index)}`;
      } else {
        value = valueFormat(getRowValue(row), ...param);
      }
      if (value !== void 0) {
        if (row.name === null) {
          continue;
        }
        const name = nameFormat((_a = row.name) != null ? _a : row.id, ...param);
        const color2 = getBgColor(row);
        const contentValue = {
          CLASS_TOOLTIP_NAME: $TOOLTIP.tooltipName + $$.getTargetSelectorSuffix(row.id),
          COLOR: tplStr || !$$.patterns ? color2 : `<svg><rect style="fill:${color2}" width="10" height="10"></rect></svg>`,
          NAME: name,
          VALUE: value
        };
        if (tplStr && isObject(contents.text)) {
          const index = targetIds.indexOf(row.id);
          Object.keys(contents.text).forEach((key) => {
            contentValue[key] = contents.text[key][index];
          });
        }
        text += tplProcess(tpl[1], contentValue);
      }
    }
    return `${text}</table>`;
  },
  /**
   * Get the content template string
   * @param {string} tplStr Tempalte string
   * @returns {Array} Template string
   * @private
   */
  getTooltipContentTemplate(tplStr) {
    return (tplStr || `<table class="{=CLASS_TOOLTIP}"><tbody>
				{=TITLE}
				{{<tr class="{=CLASS_TOOLTIP_NAME}">
					<td class="name">${this.patterns ? `{=COLOR}` : `<span style="background-color:{=COLOR}"></span>`}{=NAME}</td>
					<td class="value">{=VALUE}</td>
				</tr>}}
			</tbody></table>`).replace(RE_WHITESPACE, "").split(RE_TOOLTIP_TPL);
  },
  /**
   * Update tooltip position coordinate
   * @param {object} dataToShow Data object
   * @param {SVGElement} eventTarget Event element
   * @private
   */
  setTooltipPosition(dataToShow, eventTarget) {
    var _a, _b;
    const $$ = this;
    const { config, scale, state, $el: { eventRect, tooltip, svg } } = $$;
    const { bindto } = config.tooltip_contents;
    const isRotated = config.axis_rotated;
    const datum = tooltip == null ? void 0 : tooltip.datum();
    if (!bindto && datum) {
      const data = dataToShow != null ? dataToShow : datum.data;
      const [x, y] = getPointer(state.event, eventTarget != null ? eventTarget : eventRect == null ? void 0 : eventRect.node());
      const currPos = { x, y };
      if (state.hasAxis && scale.x && datum && "x" in datum) {
        const getYPos = (value = 0, id, axisId = "y") => {
          var _a2;
          const scaleFn = scale[id ? (_a2 = $$.axis) == null ? void 0 : _a2.getId(id) : axisId];
          return scaleFn ? scaleFn(value) + (isRotated ? state.margin.left : state.margin.top) : 0;
        };
        currPos.xAxis = scale.x(datum.x) + // add margin only when user specified tooltip.position function
        (config.tooltip_position ? isRotated ? state.margin.top : state.margin.left : 0);
        if (data.length === 1) {
          currPos.yAxis = getYPos(data[0].value, data[0].id);
        } else {
          currPos.yAxis = getYPos;
        }
      }
      const { width = 0, height = 0 } = datum;
      const pos = (_b = (_a = config.tooltip_position) == null ? void 0 : _a.bind($$.api)(
        data,
        width,
        height,
        eventRect == null ? void 0 : eventRect.node(),
        currPos
      )) != null ? _b : svg && hasViewBox(svg) ? $$.getTooltipPositionViewBox.bind($$)(width, height, currPos) : $$.getTooltipPosition.bind($$)(width, height, currPos);
      ["top", "left"].forEach((v) => {
        const value = pos[v];
        tooltip.style(v, `${value}px`);
        if (v === "left" && !datum.xPosInPercent) {
          datum.xPosInPercent = value / state.current.width * 100;
        }
      });
    }
  },
  /**
   * Get tooltip position when svg has vieBox attribute
   * @param {number} tWidth Tooltip width value
   * @param {number} tHeight Tooltip height value
   * @param {object} currPos Current event position value from SVG coordinate
   * @returns {object} top, left value
   */
  getTooltipPositionViewBox(tWidth, tHeight, currPos) {
    var _a, _b;
    const $$ = this;
    const { $el: { eventRect, svg }, config, state } = $$;
    const isRotated = config.axis_rotated;
    const hasArcType = $$.hasArcType() || state.hasFunnel || state.hasTreemap;
    const target = (_b = (_a = hasArcType ? svg : eventRect) == null ? void 0 : _a.node()) != null ? _b : state.event.target;
    let { x, y } = currPos;
    if (state.hasAxis) {
      x = isRotated ? x : currPos.xAxis;
      y = isRotated ? currPos.xAxis : y;
    }
    const ctm = getTransformCTM(target, x, y, false);
    const rect = getBoundingRect(target);
    const size = getTransformCTM(target, 20, 0, false).x;
    let top = ctm.y;
    let left = ctm.x + tWidth / 2 + size;
    if (hasArcType) {
      if (state.hasFunnel || state.hasTreemap || state.hasRadar) {
        left -= tWidth / 2 + size;
        top += tHeight;
      } else {
        top += rect.height / 2;
        left += rect.width / 2 - (tWidth - size);
      }
    }
    if (left + tWidth > rect.width) {
      left = rect.width - tWidth - size;
    }
    if (top + tHeight > rect.height) {
      top -= tHeight * 2;
    }
    return {
      top,
      left
    };
  },
  /**
   * Returns the position of the tooltip
   * @param {string} tWidth Width value of tooltip element
   * @param {string} tHeight Height value of tooltip element
   * @param {object} currPos Current mouse position
   * @returns {object} top, left value
   * @private
   */
  getTooltipPosition(tWidth, tHeight, currPos) {
    var _a, _b, _c;
    const $$ = this;
    const { config, scale, state } = $$;
    const { width, height, current, hasFunnel, hasRadar, hasTreemap, isLegendRight, inputType } = state;
    const hasGauge = $$.hasType("gauge") && !config.gauge_fullCircle;
    const isRotated = config.axis_rotated;
    const hasArcType = $$.hasArcType();
    const svgLeft = state.isCanvasMode ? 0 : $$.getSvgLeft(true);
    let chartRight = svgLeft + current.width - $$.getCurrentPaddingByDirection("right");
    const size = 20;
    let { x, y } = currPos;
    if (hasRadar) {
      x += x >= width / 2 ? 15 : -(tWidth + 15);
      y += 15;
    } else if (hasArcType) {
      const notTouch = inputType !== "touch";
      if (notTouch) {
        let titlePadding = (_b = (_a = $$.getTitlePadding) == null ? void 0 : _a.call($$)) != null ? _b : 0;
        if (titlePadding && hasGauge && ((_c = config.arc_rangeText_values) == null ? void 0 : _c.length)) {
          titlePadding += 10;
        }
        x += (width - (isLegendRight ? $$.getLegendWidth() : 0)) / 2;
        y += (hasGauge ? height : height / 2 + tHeight) + titlePadding;
      }
    } else if (hasFunnel || hasTreemap) {
      y += tHeight;
    } else {
      const padding = {
        top: $$.getCurrentPaddingByDirection("top", true),
        left: $$.getCurrentPaddingByDirection("left", true)
      };
      if (isRotated) {
        x += svgLeft + padding.left + size;
        y = padding.top + currPos.xAxis + size;
        chartRight -= svgLeft;
      } else {
        x = svgLeft + padding.left + size + (scale.zoom ? x : currPos.xAxis);
        y += padding.top - 5;
      }
    }
    if (x + tWidth + 15 > chartRight) {
      x -= tWidth + (hasFunnel || hasTreemap || hasArcType ? 0 : isRotated ? size * 2 : 38);
    }
    if (y + tHeight > current.height) {
      const gap = hasTreemap ? tHeight + 10 : 30;
      y -= hasGauge ? tHeight * 1.5 : tHeight + gap;
    }
    const pos = { top: y, left: x };
    if (pos.top < 0) pos.top = 0;
    if (pos.left < 0) pos.left = 0;
    return pos;
  },
  /**
   * Show the tooltip
   * @param {object} selectedData Data object
   * @param {SVGElement} eventTarget Event element
   * @private
   */
  showTooltip(selectedData, eventTarget) {
    const $$ = this;
    const { config, $el: { tooltip } } = $$;
    if (!tooltip || !config.tooltip_show) {
      return;
    }
    let dataToShow = null;
    let dataToShowCount = 0;
    let dataStr = `${$$.data.targets.length}:`;
    let firstData;
    for (let i = 0; i < selectedData.length; i++) {
      const d = selectedData[i];
      i > 0 && (dataStr += ",");
      dataStr += `${d == null ? void 0 : d.index}|${d == null ? void 0 : d.id}|${d == null ? void 0 : d.value}`;
      !firstData && d && (firstData = d);
      if (d && isValue($$.getBaseValue(d))) {
        dataToShowCount++;
        dataToShow == null ? void 0 : dataToShow.push(d);
      } else if (!dataToShow) {
        dataToShow = selectedData.slice(0, i);
      }
    }
    if (dataToShowCount === 0 || !firstData) {
      return;
    }
    const datum = tooltip.datum();
    let positionData = dataToShow;
    if (!datum || datum.current !== dataStr) {
      const { index, x } = firstData;
      if (!positionData) {
        positionData = selectedData.slice();
      }
      callFn(config.tooltip_onshow, $$.api, selectedData);
      tooltip.html($$.getTooltipHTML(
        selectedData,
        // data
        $$.axis ? $$.axis.getXAxisTickFormat() : $$.categoryName.bind($$),
        // defaultTitleFormat
        $$.getDefaultValueFormat(),
        // defaultValueFormat
        $$.color
        // color
      )).style("display", null).style("visibility", null);
      tooltip.datum({
        index,
        x,
        current: dataStr,
        data: selectedData,
        width: tooltip.property("offsetWidth"),
        height: tooltip.property("offsetHeight")
      });
      callFn(config.tooltip_onshown, $$.api, selectedData);
      $$._handleLinkedCharts(true, index);
    }
    $$.setTooltipPosition(positionData || selectedData, eventTarget);
  },
  /**
   * Adjust tooltip position on resize event
   * @private
   */
  bindTooltipResizePos() {
    const $$ = this;
    const { resizeFunction, state, $el: { tooltip } } = $$;
    resizeFunction.add(() => {
      if (tooltip.style("display") === "block") {
        const { current } = state;
        const { width, xPosInPercent } = tooltip.datum();
        let value = current.width / 100 * xPosInPercent;
        const diff = current.width - (value + width);
        if (diff < 0) {
          value += diff;
        }
        tooltip.style("left", `${value}px`);
      }
    });
  },
  /**
   * Hide the tooltip
   * @param {boolean} force Force to hide
   * @private
   */
  hideTooltip(force) {
    var _a;
    const $$ = this;
    const { api, config, $el: { tooltip } } = $$;
    if (tooltip && tooltip.style("display") !== "none" && (!config.tooltip_doNotHide || force)) {
      const selectedData = (_a = tooltip.datum().data) != null ? _a : [];
      callFn(config.tooltip_onhide, api, selectedData);
      tooltip.style("display", "none").datum(null);
      callFn(config.tooltip_onhidden, api, selectedData);
    }
  },
  /**
   * Toggle display for linked chart instances
   * @param {boolean} show true: show, false: hide
   * @param {number} index x Axis index
   * @private
   */
  _handleLinkedCharts(show, index) {
    const $$ = this;
    const { charts, config, state: { event } } = $$;
    if ((event == null ? void 0 : event.isTrusted) && config.tooltip_linked && charts.length > 1) {
      const linkedName = config.tooltip_linked_name;
      charts.filter((c) => c !== $$.api).forEach((c) => {
        var _a, _b;
        const { config: config2, $el, state } = c.internal;
        const isLinked = config2.tooltip_linked;
        const name = config2.tooltip_linked_name;
        const isInDom = browser_doc.body.contains($el.chart.node());
        if (isLinked && linkedName === name && isInDom) {
          const data = $el.tooltip.data()[0];
          const isNotSameIndex = index !== (data == null ? void 0 : data.index);
          try {
            if (show && isNotSameIndex && state.isCanvasMode) {
              (_b = (_a = c.internal).showCanvasLinkedTooltip) == null ? void 0 : _b.call(_a, index);
            } else {
              c.tooltip[show && isNotSameIndex ? "show" : "hide"]({ index });
            }
          } catch (e) {
          }
        }
      });
    }
  },
  /**
   * Update tooltip content on redraw
   * - In a situation where tooltip is displayed and data load happens, it should reflect loaded data to tooltip
   * @param {d3Selection} context Event rect element
   * @param {number} index Data index
   * @private
   */
  updateTooltipOnRedraw(context, index) {
    var _a;
    const $$ = this;
    const {
      config,
      $el: { eventRect, svg, tooltip },
      state: { event, hasAxis, hasRadar, hasTreemap }
    } = $$;
    if ($$.state.isCanvasMode) {
      return;
    }
    if ((tooltip == null ? void 0 : tooltip.style("display")) === "block" && event) {
      const rect = context != null ? context : (_a = hasRadar ? svg : eventRect) == null ? void 0 : _a.node();
      if (hasAxis || hasRadar) {
        if ($$.isMultipleX()) {
          $$.selectRectForMultipleXs(rect, false);
        } else {
          const idx = index != null ? index : $$.getDataIndexFromEvent(event);
          if (index === -1) {
            $$.api.tooltip.hide();
          } else {
            $$.selectRectForSingle(rect, idx);
            $$.setExpand(idx, null, true);
          }
        }
      } else {
        const { clientX, clientY } = event;
        setTimeout(() => {
          let target = [clientX, clientY].every(Number.isFinite) && browser_doc.elementFromPoint(clientX, clientY);
          const data = target && (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
          if (data) {
            const d = $$.hasArcType() ? $$.convertToArcData($$.updateAngle(data)) : data == null ? void 0 : data.data;
            hasTreemap && (target = svg.node());
            d && $$.showTooltip([d], target);
          } else {
            $$.api.tooltip.hide();
          }
        }, config.transition_duration);
      }
    }
  }
});

;// ./src/ChartInternal/internals/transform.ts


/* harmony default export */ var transform = ({
  getTranslate(target, index = 0) {
    var _a;
    const $$ = this;
    const { config, state } = $$;
    const isRotated = config.axis_rotated;
    let padding = 0;
    let x;
    let y;
    if (index && /^(x|y2?)$/.test(target)) {
      padding = $$.getAxisSize(target) * index;
    }
    if (target === "main") {
      x = asHalfPixel(state.margin.left);
      y = asHalfPixel(state.margin.top);
    } else if (target === "context") {
      x = asHalfPixel(state.margin2.left);
      y = asHalfPixel(state.margin2.top);
    } else if (target === "legend") {
      x = state.margin3.left;
      y = state.margin3.top;
    } else if (target === "x") {
      x = isRotated ? -padding : 0;
      y = isRotated ? 0 : state.height + padding;
    } else if (target === "y") {
      x = isRotated ? 0 : -padding;
      y = isRotated ? state.height + padding : 0;
    } else if (target === "y2") {
      x = isRotated ? 0 : state.width + padding;
      y = isRotated ? -padding - 1 : 0;
    } else if (target === "subX") {
      x = 0;
      y = isRotated ? 0 : state.height2;
    } else if (target === "subY") {
      x = 0;
      y = isRotated ? state.height2 : 0;
    } else if (target === "subY2") {
      x = isRotated ? 0 : state.width2;
      y = isRotated ? -1 : 0;
    } else if (target === "arc") {
      x = state.arcWidth / 2;
      y = state.arcHeight / 2;
      if ((_a = config.arc_rangeText_values) == null ? void 0 : _a.length) {
        y += 5 + ($$.hasType("gauge") && config.title_text ? 10 : 0);
      }
    } else if (target === "polar") {
      x = state.arcWidth / 2;
      y = state.arcHeight / 2;
    } else if (target === "radar") {
      const [width, height] = $$.getRadarSize();
      x = state.width / 2 - width;
      y = state.height / 2 - height;
    }
    return `translate(${x}, ${y})`;
  },
  transformMain(withTransition, transitions) {
    const $$ = this;
    const { $el: { main }, $T } = $$;
    const xAxis = (transitions == null ? void 0 : transitions.axisX) ? transitions.axisX : $T(main.select(`.${$AXIS.axisX}`), withTransition);
    const yAxis = (transitions == null ? void 0 : transitions.axisY) ? transitions.axisY : $T(main.select(`.${$AXIS.axisY}`), withTransition);
    const y2Axis = (transitions == null ? void 0 : transitions.axisY2) ? transitions.axisY2 : $T(main.select(`.${$AXIS.axisY2}`), withTransition);
    $T(main, withTransition).attr("transform", $$.getTranslate("main"));
    xAxis.attr("transform", $$.getTranslate("x"));
    yAxis.attr("transform", $$.getTranslate("y"));
    y2Axis.attr("transform", $$.getTranslate("y2"));
    main.select(`.${$ARC.chartArcs}`).attr("transform", $$.getTranslate("arc"));
  },
  transformAll(withTransition, transitions) {
    const $$ = this;
    const { config, state: { hasAxis, hasFunnel, hasTreemap, isCanvasMode }, $el } = $$;
    if (isCanvasMode) {
      return;
    }
    !hasFunnel && !hasTreemap && $$.transformMain(withTransition, transitions);
    hasAxis && config.subchart_show && $$.transformContext(withTransition, transitions);
    $el.legend && $$.transformLegend(withTransition);
  }
});

;// ./src/ChartInternal/internals/type.ts


const INTERPOLATION_TYPES = /* @__PURE__ */ new Set([
  "basis",
  "basis-closed",
  "basis-open",
  "bundle",
  "cardinal",
  "cardinal-closed",
  "cardinal-open",
  "catmull-rom",
  "catmull-rom-closed",
  "catmull-rom-open",
  "linear",
  "linear-closed",
  "monotone-x",
  "monotone-y",
  "natural"
]);
/* harmony default export */ var type = ({
  /**
   * Check if the given chart type is valid
   * @param {string} type Chart type string
   * @returns {boolean}
   * @private
   */
  isValidChartType(type) {
    return !!(type && Object.values(TYPE).indexOf(type) > -1);
  },
  /**
   * Get the chart type to use for the subchart target.
   * subchart.types > subchart.type > data.types > data.type > line
   * @param {object|string} d Target data or id
   * @returns {string}
   * @private
   */
  getSubchartTargetType(d) {
    const $$ = this;
    const { config } = $$;
    const id = isString(d) ? d : d == null ? void 0 : d.id;
    const subchartTypes = config.subchart_types || {};
    const subchartType = config.subchart_type;
    const dataTypes = config.data_types || {};
    const targetSubchartType = id && subchartTypes[id];
    if (targetSubchartType && $$.isValidChartType(targetSubchartType)) {
      return targetSubchartType;
    } else if (subchartType && $$.isValidChartType(subchartType)) {
      return subchartType;
    }
    return id && dataTypes[id] || config.data_type || TYPE.LINE;
  },
  /**
   * Get the regular chart type configured for the target.
   * @param {object|string} d Target data or id
   * @returns {string}
   * @private
   */
  getTargetType(d) {
    var _a;
    const { config } = this;
    const id = isString(d) ? d : d == null ? void 0 : d.id;
    return id && ((_a = config.data_types) == null ? void 0 : _a[id]) || config.data_type || TYPE.LINE;
  },
  /**
   * Get the target's original chart type while subchart.type context is active.
   * @param {object|string} d Target data or id
   * @returns {string}
   * @private
   */
  getSubchartSourceTargetType(d) {
    const { state } = this;
    const id = isString(d) ? d : d == null ? void 0 : d.id;
    const sourceTypes = state.subchartSourceTypes;
    return id && (sourceTypes == null ? void 0 : sourceTypes[id]) || this.getTargetType(d);
  },
  /**
   * Check whether a target had the given source type before subchart.type remapping.
   * @param {object|string} d Target data or id
   * @param {string|Array} type chart type
   * @returns {boolean}
   * @private
   */
  isSubchartSourceTypeOf(d, type) {
    const sourceType = this.getSubchartSourceTargetType(d);
    return isArray(type) ? type.indexOf(sourceType) >= 0 : sourceType === type;
  },
  /**
   * Run a callback while regular type helpers resolve using subchart.type/types.
   * @param {function(): unknown} callback Callback to run
   * @returns {unknown} Callback return value
   * @private
   */
  withSubchartTypeContext(callback) {
    const $$ = this;
    const { config, data, state } = $$;
    const dataType = config.data_type;
    const dataTypes = config.data_types;
    const currentTypes = state.current.types;
    const sourceTypes = state.subchartSourceTypes;
    const subchartTypes = {};
    const subchartSourceTypes = {};
    const subchartType = config.subchart_type;
    $$.mapToIds(data.targets).forEach((id) => {
      subchartSourceTypes[id] = $$.getTargetType(id);
      subchartTypes[id] = $$.getSubchartTargetType(id);
    });
    config.data_type = subchartType && $$.isValidChartType(subchartType) ? subchartType : dataType;
    config.data_types = subchartTypes;
    state.current.types = [];
    state.subchartSourceTypes = subchartSourceTypes;
    try {
      return callback();
    } finally {
      config.data_type = dataType;
      config.data_types = dataTypes;
      state.current.types = currentTypes;
      state.subchartSourceTypes = sourceTypes;
    }
  },
  setTargetType(targetIds, type) {
    const $$ = this;
    const { config, state: { withoutFadeIn } } = $$;
    $$.mapToTargetIds(targetIds).forEach((id) => {
      withoutFadeIn[id] = type === config.data_types[id];
      config.data_types[id] = type;
    });
    if (!targetIds) {
      config.data_type = type;
    }
  },
  /**
   * Updte current used chart types
   * @private
   */
  updateTypesElements() {
    const $$ = this;
    const { state: { current } } = $$;
    Object.keys(TYPE).forEach((v) => {
      const t = TYPE[v];
      const has = $$.hasType(t, null, true);
      const idx = current.types.indexOf(t);
      if (idx === -1 && has) {
        current.types.push(t);
      } else if (idx > -1 && !has) {
        current.types.splice(idx, 1);
      }
    });
    $$.setChartElements();
  },
  /**
   * Check if given chart types exists
   * @param {string} type Chart type
   * @param {Array} targetsValue Data array
   * @param {boolean} checkFromData Force to check type cotains from data targets
   * @returns {boolean}
   * @private
   */
  hasType(type, targetsValue, checkFromData = false) {
    var _a;
    const $$ = this;
    const { config, state: { current } } = $$;
    const types = config.data_types;
    const targets = targetsValue || $$.data.targets;
    if (!checkFromData && ((_a = current.types) == null ? void 0 : _a.indexOf(type)) > -1) {
      return true;
    } else if (targets == null ? void 0 : targets.length) {
      return targets.some((target) => {
        const t = types[target.id];
        return t === type || !t && type === "line";
      });
    } else if (Object.keys(types).length) {
      return Object.values(types).some((t) => t === type);
    }
    return config.data_type === type;
  },
  /**
   * Check if contains given chart types
   * @param {string} type Type key
   * @param {object} targets Target data
   * @param {Array} exclude Excluded types
   * @returns {boolean}
   * @private
   */
  hasTypeOf(type, targets, exclude = []) {
    if (type in TYPE_BY_CATEGORY) {
      return !TYPE_BY_CATEGORY[type].filter((v) => exclude.indexOf(v) === -1).every((v) => !this.hasType(v, targets));
    }
    return false;
  },
  /**
   * Check if given data is certain chart type
   * @param {object} d Data object
   * @param {string|Array} type chart type
   * @returns {boolean}
   * @private
   */
  isTypeOf(d, type) {
    const id = isString(d) ? d : d.id;
    const dataType = this.config && this.getTargetType(id);
    return isArray(type) ? type.indexOf(dataType) >= 0 : dataType === type;
  },
  hasPointType() {
    const $$ = this;
    return $$.hasTypeOf("Line") || $$.hasType("bubble") || $$.hasType("scatter");
  },
  /**
   * Check if contains arc types chart
   * @param {object} targets Target data
   * @param {Array} exclude Excluded types
   * @returns {boolean}
   * @private
   */
  hasArcType(targets, exclude) {
    return this.hasTypeOf("Arc", targets, exclude);
  },
  hasMultiArcGauge() {
    return this.hasType("gauge") && this.config.gauge_type === "multi";
  },
  isLineType(d) {
    const id = isString(d) ? d : d.id;
    return !this.config.data_types[id] || this.isTypeOf(id, TYPE_BY_CATEGORY.Line);
  },
  isStepType(d) {
    return this.isTypeOf(d, TYPE_BY_CATEGORY.Step);
  },
  isSplineType(d) {
    return this.isTypeOf(d, TYPE_BY_CATEGORY.Spline);
  },
  isAreaType(d) {
    return this.isTypeOf(d, TYPE_BY_CATEGORY.Area);
  },
  isAreaRangeType(d) {
    return this.isTypeOf(d, TYPE_BY_CATEGORY.AreaRange);
  },
  isBarType(d) {
    return this.isTypeOf(d, "bar");
  },
  isBubbleType(d) {
    return this.isTypeOf(d, "bubble");
  },
  isCandlestickType(d) {
    return this.isTypeOf(d, "candlestick");
  },
  isScatterType(d) {
    return this.isTypeOf(d, "scatter");
  },
  isTreemapType(d) {
    return this.isTypeOf(d, "treemap");
  },
  isPieType(d) {
    return this.isTypeOf(d, "pie");
  },
  isFunnelType(d) {
    return this.isTypeOf(d, "funnel");
  },
  isGaugeType(d) {
    return this.isTypeOf(d, "gauge");
  },
  isDonutType(d) {
    return this.isTypeOf(d, "donut");
  },
  isPolarType(d) {
    return this.isTypeOf(d, "polar");
  },
  isRadarType(d) {
    return this.isTypeOf(d, "radar");
  },
  isArcType(d) {
    return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d) || this.isPolarType(d) || this.isRadarType(d);
  },
  // determine if is 'circle' data point
  isCirclePoint(node) {
    const { config } = this;
    const pattern = config.point_pattern;
    const isCircle = (node == null ? void 0 : node.tagName) === "circle" || config.point_type === "circle" && (!pattern || isArray(pattern) && pattern.length === 0);
    return isCircle;
  },
  lineData(d) {
    return this.isLineType(d) ? [d] : [];
  },
  arcData(d) {
    return this.isArcType(d.data) ? [d] : [];
  },
  /**
   * Get data adapt for data label showing
   * @param {object} d Data object
   * @returns {Array}
   * @private
   */
  labelishData(d) {
    return this.isBarType(d) || this.isLineType(d) || this.isScatterType(d) || this.isBubbleType(d) || this.isCandlestickType(d) || this.isFunnelType(d) || this.isRadarType(d) || this.isTreemapType(d) ? d.values.filter((v) => isNumber(v.value) || Boolean(v.value)) : [];
  },
  barLineBubbleData(d) {
    return this.isBarType(d) || this.isLineType(d) || this.isBubbleType(d) ? d.values : [];
  },
  isInterpolationType(type) {
    return INTERPOLATION_TYPES.has(type);
  }
});

;// ./src/ChartInternal/shape/shape.ts






const CURVE_MAP = {
  basis: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBasis,
  "basis-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBasisClosed,
  "basis-open": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBasisOpen,
  bundle: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBundle,
  cardinal: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCardinal,
  "cardinal-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCardinalClosed,
  "cardinal-open": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCardinalOpen,
  "catmull-rom": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCatmullRom,
  "catmull-rom-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCatmullRomClosed,
  "catmull-rom-open": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCatmullRomOpen,
  "monotone-x": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveMonotoneX,
  "monotone-y": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveMonotoneY,
  natural: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveNatural,
  "linear-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveLinearClosed,
  linear: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveLinear,
  step: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveStep,
  "step-after": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveStepAfter,
  "step-before": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveStepBefore
};
function isLinePointGroupType($$, d) {
  var _a, _b;
  return $$.isLineType(d) || ((_a = $$.isScatterType) == null ? void 0 : _a.call($$, d)) || ((_b = $$.isBubbleType) == null ? void 0 : _b.call($$, d));
}
function getLinePointGroupTypeFilter($$) {
  return (d) => isLinePointGroupType($$, d);
}
function getShapeOffsetValue($$, d, isSub) {
  var _a, _b, _c;
  const subchartCandlestickValue = isSub ? getSubchartCandlestickShapeValue($$, d, isSub) : void 0;
  if (isNumber(subchartCandlestickValue)) {
    return subchartCandlestickValue;
  }
  if ((_a = $$.isCandlestickType) == null ? void 0 : _a.call($$, d)) {
    return (_c = (_b = $$.getCandlestickData) == null ? void 0 : _b.call($$, d)) == null ? void 0 : _c.close;
  }
  return $$.getBaseValue(d);
}
function getSubchartCandlestickShapeValue($$, d, isSub) {
  var _a, _b, _c;
  if (!isSub || ((_a = $$.isCandlestickType) == null ? void 0 : _a.call($$, d)) || !((_b = $$.isSubchartSourceTypeOf) == null ? void 0 : _b.call($$, d, TYPE.CANDLESTICK))) {
    return void 0;
  }
  const value = (_c = $$.getCandlestickData) == null ? void 0 : _c.call($$, d);
  if (!value) {
    return void 0;
  }
  if ($$.isBarType(d)) {
    return isNumber(value.open) && isNumber(value.close) ? value._isUp ? value.close : value.open : void 0;
  }
  return isNumber(value.close) ? value.close : void 0;
}
function isSubchartCandlestickBarValue($$, d, isSub) {
  const value = getSubchartCandlestickShapeValue($$, d, isSub);
  return isNumber(value) && $$.isBarType(d);
}
function getSubchartCandlestickBarColor($$, d, isSub) {
  var _a;
  if (!isSubchartCandlestickBarValue($$, d, isSub)) {
    return null;
  }
  const value = (_a = $$.getCandlestickData) == null ? void 0 : _a.call($$, d);
  if (value == null ? void 0 : value._isUp) {
    return $$.color(d);
  }
  const downColor = $$.config.candlestick_color_down;
  const color = downColor && typeof downColor === "object" ? downColor[d.id] : downColor;
  return color || $$.color(d);
}
function _getGroupedDataPointsFn(d) {
  var _a, _b;
  const $$ = this;
  let fn;
  if (isLinePointGroupType($$, d)) {
    const typeFilter = getLinePointGroupTypeFilter($$);
    fn = $$.generateGetLinePoints($$.getShapeIndices(typeFilter), false, typeFilter);
  } else if ($$.isBarType(d)) {
    fn = $$.generateGetBarPoints($$.getShapeIndices($$.isBarType));
  } else if ((_a = $$.isCandlestickType) == null ? void 0 : _a.call($$, d)) {
    fn = (_b = $$.generateGetCandlestickPoints) == null ? void 0 : _b.call($$, $$.getShapeIndices($$.isCandlestickType));
  }
  return fn;
}
function getShapeColorWithGradient(d, configKey, colorFn) {
  return this.config[configKey] ? this.getGradienColortUrl(d.id) : colorFn(d);
}
function initShapeElement(config) {
  const { $el } = this;
  const { elKey, className, cssRules, position } = config;
  const container = $el.main.select(`.${config_classes.chart}`);
  $el[elKey] = position === "first" ? container.insert("g", ":first-child") : container.append("g");
  $el[elKey].attr("class", className);
  if (cssRules == null ? void 0 : cssRules.length) {
    $el[elKey].call(this.setCssRule(false, `.${className}`, cssRules));
  }
}
function updateTargetsForShape(targets, config) {
  const $$ = this;
  const { $el } = $$;
  const { type, elKey, containerClass, itemClass, initFn, withFocus = true, withStyles = true } = config;
  if (!$el[elKey]) {
    initFn.call($$);
  }
  const classChart = $$.getChartClass(type);
  const classFocus = withFocus ? $$.classFocus.bind($$) : () => "";
  const mainUpdate = $el.main.select(`.${containerClass}`).selectAll(`.${itemClass}`).data($$.filterNullish(targets)).attr("class", (d) => classChart(d) + classFocus(d));
  const mainEnter = mainUpdate.enter().append("g").attr("class", classChart);
  if (withStyles) {
    mainEnter.style("opacity", "0").style("pointer-events", $$.getStylePropValue("none"));
  }
  return mainEnter;
}
/* harmony default export */ var shape = ({
  /**
   * Get the shape draw function
   * @returns {object}
   * @private
   */
  getDrawShape() {
    const $$ = this;
    const isRotated = $$.config.axis_rotated;
    const { hasRadar, hasTreemap } = $$.state;
    const shape = { type: {}, indices: {}, pos: {} };
    !hasTreemap && ["bar", "candlestick", "line", "area"].forEach((v) => {
      const name = capitalize(v);
      if ($$.hasType(v) || $$.hasTypeOf(name) || v === "line" && ($$.hasType("bubble") || $$.hasType("scatter"))) {
        const indices = $$.getShapeIndices($$[`is${name}Type`]);
        const drawFn = $$[`generateDraw${name}`];
        shape.indices[v] = indices;
        shape.type[v] = drawFn ? drawFn.bind($$)(indices, false) : void 0;
      }
    });
    if (!$$.hasArcType() || hasRadar || hasTreemap) {
      let cx;
      let cy;
      let xForText;
      let yForText;
      if (!hasTreemap) {
        cx = hasRadar ? $$.radarCircleX : isRotated ? $$.circleY : $$.circleX;
        cy = hasRadar ? $$.radarCircleY : isRotated ? $$.circleX : $$.circleY;
      }
      if (hasTreemap && $$.state.isCanvasMode) {
        xForText = yForText = function() {
        };
      } else {
        xForText = $$.generateXYForText(shape.indices, true);
        yForText = $$.generateXYForText(shape.indices, false);
      }
      shape.pos = {
        xForText,
        yForText,
        cx: (cx || function() {
        }).bind($$),
        cy: (cy || function() {
        }).bind($$)
      };
    }
    return shape;
  },
  /**
   * Get shape's indices according it's position within each axis tick.
   *
   * From the below example, indices will be:
   * ==> {data1: 0, data2: 0, data3: 1, data4: 1, __max__: 1}
   *
   * 	data1 data3   data1 data3
   * 	data2 data4   data2 data4
   * 	-------------------------
   * 		 0             1
   * @param {function} typeFilter Chart type filter function
   * @returns {object} Indices object with its position
   */
  getShapeIndices(typeFilter) {
    const $$ = this;
    const { config } = $$;
    const xs = config.data_xs;
    const hasXs = notEmpty(xs);
    const indices = {};
    let i = hasXs ? {} : 0;
    if (hasXs) {
      getUnique(Object.keys(xs).map((v) => xs[v])).forEach((v) => {
        i[v] = 0;
        indices[v] = {};
      });
    }
    $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach((d) => {
      var _a;
      const xKey = d.id in xs ? xs[d.id] : "";
      const ind = xKey ? indices[xKey] : indices;
      for (let j = 0, groups; groups = config.data_groups[j]; j++) {
        if (groups.indexOf(d.id) < 0) {
          continue;
        }
        for (let k = 0, key; key = groups[k]; k++) {
          if (key in ind) {
            ind[d.id] = ind[key];
            break;
          }
          if (d.id !== key && xKey) {
            ind[key] = (_a = ind[d.id]) != null ? _a : i[xKey];
          }
        }
      }
      if (isUndefined(ind[d.id])) {
        ind[d.id] = xKey ? i[xKey]++ : i++;
        ind.__max__ = (xKey ? i[xKey] : i) - 1;
      }
    });
    return indices;
  },
  /**
   * Get indices value based on data ID value
   * @param {object} indices Indices object
   * @param {object} d Data row
   * @param {string} caller Caller function name (Used only for 'sparkline' plugin)
   * @returns {object} Indices object
   * @private
   */
  getIndices(indices, d, caller) {
    const $$ = this;
    const { data_xs: xs, bar_indices_removeNull: removeNull } = $$.config;
    const { id, index } = d;
    if ($$.isBarType(id) && removeNull) {
      const ind = {};
      $$.getAllValuesOnIndex(index, true).forEach((v, i) => {
        ind[v.id] = i;
        ind.__max__ = i;
      });
      return ind;
    }
    return notEmpty(xs) ? indices[xs[id]] : indices;
  },
  /**
   * Get indices max number
   * @param {object} indices Indices object
   * @returns {number} Max number
   * @private
   */
  getIndicesMax(indices) {
    if (!notEmpty(this.config.data_xs)) {
      return indices.__max__;
    }
    let total = 0;
    for (const key in indices) {
      total += indices[key].__max__ || 0;
    }
    return total;
  },
  getShapeX(offset, indices, isSub) {
    const $$ = this;
    const { config, scale } = $$;
    const currScale = isSub ? scale.subX : scale.zoom || scale.x;
    const barOverlap = config.bar_overlap;
    const barPadding = config.bar_padding;
    const sum = (p, c) => p + c;
    const halfWidth = isObjectType(offset) && (offset._$total.length ? offset._$total.reduce(sum) / 2 : 0);
    const prefixSums = [];
    if (halfWidth && isObjectType(offset) && offset._$total.length) {
      let acc = 0;
      for (const v of offset._$total) {
        acc += v;
        prefixSums.push(acc);
      }
    }
    return (d) => {
      var _a;
      const ind = $$.getIndices(indices, d, "getShapeX");
      const index = d.id in ind ? ind[d.id] : 0;
      const targetsNum = (ind.__max__ || 0) + 1;
      let x = 0;
      if (notEmpty(d.x)) {
        const xPos = currScale(d.x, true);
        if (halfWidth) {
          const offsetWidth = offset[d.id] || offset._$width;
          x = barOverlap ? xPos - offsetWidth / 2 : xPos - offsetWidth + ((_a = prefixSums[index]) != null ? _a : offset._$total.slice(0, index + 1).reduce(sum)) - halfWidth;
        } else {
          x = xPos - (isNumber(offset) ? offset : offset._$width) * (targetsNum / 2 - (barOverlap ? 1 : index));
        }
      }
      if (offset && x && targetsNum > 1 && barPadding) {
        if (index) {
          x += barPadding * index;
        }
        if (targetsNum > 2) {
          x -= (targetsNum - 1) * barPadding / 2;
        } else if (targetsNum === 2) {
          x -= barPadding / 2;
        }
      }
      return x;
    };
  },
  getShapeY(isSub) {
    const $$ = this;
    const isStackNormalized = $$.isStackNormalized();
    return (d) => {
      let { value } = d;
      const subchartCandlestickValue = isSub ? getSubchartCandlestickShapeValue($$, d, isSub) : void 0;
      if (isNumber(d)) {
        value = d;
      } else if (isNumber(subchartCandlestickValue)) {
        value = subchartCandlestickValue;
      } else if ($$.isAreaRangeType(d)) {
        value = $$.getBaseValue(d, "mid");
      } else if (isStackNormalized) {
        value = $$.getRatio("index", d, true);
      } else if ($$.isBubbleZType(d)) {
        value = $$.getBubbleZData(d.value, "y");
      } else if ($$.isBarRangeType(d)) {
        value = value[1];
      }
      return $$.getYScaleById(d.id, isSub)(value);
    };
  },
  /**
   * Get shape based y Axis min value
   * @param {string} id Data id
   * @param {boolean} isSub Whether to use subchart scale
   * @returns {number}
   * @private
   */
  getShapeYMin(id, isSub = false) {
    const $$ = this;
    const axisId = $$.axis.getId(id);
    const scale = $$.getYScaleById(id, isSub);
    const [yMin] = scale.domain();
    const inverted = $$.config[`axis_${axisId}_inverted`];
    return !$$.isGrouped(id) && !inverted && yMin > 0 ? yMin : 0;
  },
  /**
   * Get Shape's offset data
   * @param {function} typeFilter Type filter function
   * @param {boolean} isSub Whether coordinates are for the subchart
   * @returns {object}
   * @private
   */
  getShapeOffsetData(typeFilter, isSub) {
    const $$ = this;
    const targets = $$.orderTargets(
      $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))
    );
    const dataGeneration = $$.state.dataGeneration;
    const targetIds = targets.map((t) => t.id).join("_");
    const cacheKey = `${KEY.shapeOffset}_${isSub ? "sub" : "main"}_${targetIds}`;
    const cachedData = $$.cache.get(cacheKey);
    if ((cachedData == null ? void 0 : cachedData.generation) === dataGeneration) {
      return cachedData;
    }
    const isStackNormalized = $$.isStackNormalized();
    const shapeOffsetTargets = targets.map((target) => {
      let rowValues = target.values;
      const values = {};
      if ($$.isStepType(target)) {
        rowValues = $$.convertValuesToStep(rowValues);
      }
      const rowValueMapByXValue = rowValues.reduce((out, d) => {
        const key = Number(d.x);
        const value = getShapeOffsetValue($$, d, isSub);
        out[key] = d;
        values[key] = isStackNormalized ? $$.getRatio("index", d, true) : value;
        return out;
      }, {});
      return {
        id: target.id,
        rowValues,
        rowValueMapByXValue,
        values
      };
    });
    const indexMapByTargetId = targets.reduce((out, { id }, index) => {
      out[id] = index;
      return out;
    }, {});
    const result = { generation: dataGeneration, indexMapByTargetId, shapeOffsetTargets };
    $$.cache.add(cacheKey, result);
    return result;
  },
  getShapeOffset(typeFilter, indices, isSub) {
    const $$ = this;
    const { shapeOffsetTargets, indexMapByTargetId } = $$.getShapeOffsetData(
      typeFilter,
      isSub
    );
    const groupsZeroAs = $$.config.data_groupsZeroAs;
    let sameGroupByTargetId = null;
    if (!$$.config.bar_indices_removeNull) {
      sameGroupByTargetId = /* @__PURE__ */ new Map();
      for (const target of shapeOffsetTargets) {
        const ind = $$.getIndices(indices, { id: target.id, index: 0 });
        sameGroupByTargetId.set(
          target.id,
          shapeOffsetTargets.filter(
            (t) => t.id !== target.id && ind[t.id] === ind[target.id]
          )
        );
      }
    }
    return (d, idx) => {
      var _a;
      const { id, value, x } = d;
      const baseValue = getShapeOffsetValue($$, d, isSub);
      const ind = $$.getIndices(indices, d);
      const scale = $$.getYScaleById(id, isSub);
      if ($$.isBarRangeType(d)) {
        return scale(value[0]);
      }
      const dataXAsNumber = Number(x);
      const y0 = scale(groupsZeroAs === "zero" ? 0 : $$.getShapeYMin(id, isSub));
      let offset = y0;
      const sameGroupTargets = (_a = sameGroupByTargetId == null ? void 0 : sameGroupByTargetId.get(id)) != null ? _a : shapeOffsetTargets.filter((t) => t.id !== id && ind[t.id] === ind[id]);
      for (const t of sameGroupTargets) {
        const {
          id: tid,
          rowValueMapByXValue,
          rowValues,
          values: tvalues
        } = t;
        if (indexMapByTargetId[tid] < indexMapByTargetId[id]) {
          const rValue = tvalues[dataXAsNumber];
          let row = rowValues[idx];
          if (!row || Number(row.x) !== dataXAsNumber) {
            row = rowValueMapByXValue[dataXAsNumber];
          }
          const rowValue = row && getShapeOffsetValue($$, row, isSub);
          if (isNumber(rowValue) && isNumber(baseValue) && rowValue * baseValue >= 0 && isNumber(rValue)) {
            const addOffset = baseValue === 0 ? groupsZeroAs === "positive" && rValue > 0 || groupsZeroAs === "negative" && rValue < 0 : true;
            if (addOffset) {
              offset += scale(rValue) - y0;
            }
          }
        }
      }
      return offset;
    };
  },
  /**
   * Generate line coordinate points from shared geometry.
   * @param {object} lineIndices Data order within x axis
   * @param {boolean} isSub Whether the coordinates are for subchart
   * @param {function} typeFilter Type filter for offset targets
   * @returns {function} Line point generator
   * @private
   */
  generateGetLinePoints(lineIndices, isSub, typeFilter) {
    const $$ = this;
    const { config } = $$;
    const x = $$.getShapeX(0, lineIndices, isSub);
    const y = $$.getShapeY(isSub);
    const lineOffset = $$.getShapeOffset(typeFilter || $$.isLineType, lineIndices, isSub);
    const yScale = $$.getYScaleById.bind($$);
    const y0Cache = /* @__PURE__ */ new Map();
    return (d, i) => {
      let y0 = y0Cache.get(d.id);
      if (y0 === void 0) {
        y0 = yScale.call($$, d.id, isSub)($$.getShapeYMin(d.id, isSub));
        y0Cache.set(d.id, y0);
      }
      const offset = lineOffset(d, i) || y0;
      const posX = x(d);
      let posY = y(d);
      if (config.axis_rotated && (d.value > 0 && posY < y0 || d.value < 0 && y0 < posY)) {
        posY = y0;
      }
      const point = [posX, posY - (y0 - offset)];
      return [
        point,
        point,
        point,
        point
      ];
    };
  },
  /**
   * Generate area coordinate points from shared geometry.
   * @param {object} areaIndices Data order within x axis
   * @param {boolean} isSub Whether the coordinates are for subchart
   * @returns {function} Area point generator
   * @private
   */
  generateGetAreaPoints(areaIndices, isSub) {
    const $$ = this;
    const { config } = $$;
    const x = $$.getShapeX(0, areaIndices, isSub);
    const y = $$.getShapeY(!!isSub);
    const areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, isSub);
    const yScale = $$.getYScaleById.bind($$);
    const y0Cache = /* @__PURE__ */ new Map();
    return function(d, i) {
      let y0 = y0Cache.get(d.id);
      if (y0 === void 0) {
        y0 = yScale.call($$, d.id, isSub)($$.getShapeYMin(d.id, isSub));
        y0Cache.set(d.id, y0);
      }
      const offset = areaOffset(d, i) || y0;
      const posX = x(d);
      const value = d.value;
      let posY = y(d);
      if (config.axis_rotated && (value > 0 && posY < y0 || value < 0 && y0 < posY)) {
        posY = y0;
      }
      return [
        [posX, offset],
        [posX, posY - (y0 - offset)],
        [posX, posY - (y0 - offset)],
        [posX, offset]
      ];
    };
  },
  /**
   * Generate bar coordinate points from shared geometry.
   * @param {object} barIndices Data order within x axis
   * @param {boolean} isSub Whether the coordinates are for subchart
   * @returns {function} Bar point generator
   * @private
   */
  generateGetBarPoints(barIndices, isSub) {
    const $$ = this;
    const { config } = $$;
    const axis = isSub ? $$.axis.subX : $$.axis.x;
    const barTargetsNum = $$.getIndicesMax(barIndices) + 1;
    const barW = $$.getBarW("bar", axis, barTargetsNum);
    const barX = $$.getShapeX(barW, barIndices, !!isSub);
    const barY = $$.getShapeY(!!isSub);
    const barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub);
    const yScale = $$.getYScaleById.bind($$);
    const idCache = /* @__PURE__ */ new Map();
    return (d, i) => {
      const { id } = d;
      let idInfo = idCache.get(id);
      if (!idInfo) {
        idInfo = {
          y0: yScale.call($$, id, isSub)($$.getShapeYMin(id, isSub)),
          isInverted: config[`axis_${$$.axis.getId(id)}_inverted`]
        };
        idCache.set(id, idInfo);
      }
      const { y0, isInverted } = idInfo;
      const offset = barOffset(d, i) || y0;
      const width = isNumber(barW) ? barW : barW[d.id] || barW._$width;
      const value = d.value;
      const posX = barX(d);
      let posY = barY(d);
      if (config.axis_rotated && !isInverted && (value > 0 && posY < y0 || value < 0 && y0 < posY)) {
        posY = y0;
      }
      if (!$$.isBarRangeType(d)) {
        posY -= y0 - offset;
      }
      const startPosX = posX + width;
      return [
        [posX, offset],
        [posX, posY],
        [startPosX, posY],
        [startPosX, offset]
      ];
    };
  },
  /**
   * Get data's y coordinate
   * @param {object} d Target data
   * @param {number} i Index number
   * @returns {number} y coordinate
   * @private
   */
  circleY(d, i) {
    const $$ = this;
    const id = d.id;
    let points;
    if ($$.isGrouped(id)) {
      points = _getGroupedDataPointsFn.bind($$)(d);
    }
    return points ? points(d, i)[0][1] : $$.getYScaleById(id)($$.getBaseValue(d));
  },
  /**
   * Get data point x coordinate.
   * @param {object} d Data row
   * @returns {number|null} X coordinate
   * @private
   */
  circleX(d) {
    return this.xx(d);
  },
  /**
   * Generate data point y coordinate accessor.
   * @param {boolean} isSub Whether the coordinates are for subchart
   * @returns {function} Y coordinate accessor
   * @private
   */
  updateCircleY(isSub = false) {
    const $$ = this;
    const typeFilter = getLinePointGroupTypeFilter($$);
    const getPoints = $$.generateGetLinePoints(
      $$.getShapeIndices(typeFilter),
      isSub,
      typeFilter
    );
    const y = $$.getShapeY(isSub);
    return (d, i) => {
      const id = d.id;
      return $$.isGrouped(id) && isLinePointGroupType($$, d) ? getPoints(d, i)[0][1] : y(d);
    };
  },
  /**
   * Get candlestick data projected for alternate subchart shapes.
   * @param {object} d Data row
   * @param {boolean} isSub Whether coordinates are for the subchart
   * @returns {number|undefined} Projected value
   * @private
   */
  getSubchartCandlestickShapeValue(d, isSub) {
    return getSubchartCandlestickShapeValue(this, d, isSub);
  },
  /**
   * Check whether the row should be drawn as a candlestick-derived subchart bar.
   * @param {object} d Data row
   * @param {boolean} isSub Whether coordinates are for the subchart
   * @returns {boolean}
   * @private
   */
  isSubchartCandlestickBarValue(d, isSub) {
    return isSubchartCandlestickBarValue(this, d, isSub);
  },
  /**
   * Get subchart bar color projected from candlestick up/down state.
   * @param {object} d Data row
   * @param {boolean} isSub Whether coordinates are for the subchart
   * @returns {string|null} Bar color
   * @private
   */
  getSubchartCandlestickBarColor(d, isSub) {
    return getSubchartCandlestickBarColor(this, d, isSub);
  },
  /**
   * Get point radius.
   * @param {object} d Data row
   * @returns {number} Point radius
   * @private
   */
  pointR(d) {
    const $$ = this;
    const { config } = $$;
    const pointR = config.point_r;
    let r = pointR;
    if ($$.isBubbleType(d)) {
      r = $$.getBubbleR(d);
    } else if (isFunction(pointR)) {
      r = pointR.bind($$.api)(d);
    }
    d.r = r;
    return r;
  },
  /**
   * Get focused point radius.
   * @param {object} d Data row
   * @returns {number} Focused point radius
   * @private
   */
  pointExpandedR(d) {
    const $$ = this;
    const { config } = $$;
    const scale = $$.isBubbleType(d) ? 1.15 : 1.75;
    return config.point_focus_expand_enabled ? config.point_focus_expand_r || $$.pointR(d) * scale : $$.pointR(d);
  },
  /**
   * Get selected point radius.
   * @param {object} d Data row
   * @returns {number} Selected point radius
   * @private
   */
  pointSelectR(d) {
    const $$ = this;
    const selectR = $$.config.point_select_r;
    return isFunction(selectR) ? selectR(d) : selectR || $$.pointR(d) * 4;
  },
  /**
   * Check if point.focus.only option can be applied.
   * @returns {boolean} Whether focus-only point rendering is active
   * @private
   */
  isPointFocusOnly() {
    const $$ = this;
    return $$.config.point_focus_only && !$$.hasType("bubble") && !$$.hasType("scatter") && !$$.hasArcType(null, ["radar"]);
  },
  /**
   * Get data point sensitivity radius.
   * @param {object} d Data point
   * @returns {number} Sensitivity radius
   * @private
   */
  getPointSensitivity(d) {
    const $$ = this;
    let sensitivity = $$.config.point_sensitivity;
    if (!d) {
      return sensitivity;
    } else if (isFunction(sensitivity)) {
      sensitivity = sensitivity.call($$.api, d);
    } else if (sensitivity === "radius") {
      sensitivity = d.r;
    }
    return sensitivity;
  },
  getBarW(type, axis, targetsNum) {
    var _a, _b, _c, _d, _e;
    const $$ = this;
    const { config, org, scale, state } = $$;
    const maxDataCount = $$.getMaxDataCount();
    const isGrouped = type === "bar" && ((_a = config.data_groups) == null ? void 0 : _a.length);
    const configName = `${type}_width`;
    const { k } = (_c = (_b = $$.getZoomTransform) == null ? void 0 : _b.call($$)) != null ? _c : { k: 1 };
    const xMinMax = [
      (_d = config.axis_x_min) != null ? _d : org.xDomain[0],
      (_e = config.axis_x_max) != null ? _e : org.xDomain[1]
    ].map((v) => $$.axis.isTimeSeries() ? parseDate.call($$, v) : Number(v));
    let tickInterval = axis.tickInterval(maxDataCount);
    if (scale.zoom && !$$.axis.isCategorized() && k > 1) {
      const isSameMinMax = xMinMax.every((v, i) => v === org.xDomain[i]);
      tickInterval = org.xDomain.map((v, i) => {
        const value = isSameMinMax ? v : v - Math.abs(xMinMax[i]);
        return scale.zoom(value);
      }).reduce((a, c) => Math.abs(a) + c) / maxDataCount;
    }
    const getWidth = (id) => {
      const width = id ? config[configName][id] : config[configName];
      const ratio = id ? width.ratio : config[`${configName}_ratio`];
      const max = id ? width.max : config[`${configName}_max`];
      const w = isNumber(width) ? width : isFunction(width) ? width.call($$, state.width, targetsNum, maxDataCount) : targetsNum ? tickInterval * ratio / targetsNum : 0;
      return max && w > max ? max : w;
    };
    let result = getWidth();
    if (!isGrouped && isObjectType(config[configName])) {
      result = { _$width: result, _$total: [] };
      $$.getTargetsToShow().forEach((v) => {
        if (config[configName][v.id]) {
          result[v.id] = getWidth(v.id);
          result._$total.push(result[v.id] || result._$width);
        }
      });
    }
    return result;
  },
  /**
   * Get shape element
   * @param {string} shapeName Shape string
   * @param {number} i Index number
   * @param {string} id Data series id
   * @returns {d3Selection}
   * @private
   */
  getShapeByIndex(shapeName, i, id) {
    const $$ = this;
    const { $el } = $$;
    const suffix = isValue(i) ? `-${i}` : ``;
    let shape = $el[shapeName];
    if (shape && !shape.empty()) {
      shape = shape.filter((d) => id ? d.id === id : true).filter((d) => isValue(i) ? d.index === i : true);
    } else {
      shape = (id ? $el.main.selectAll(
        `.${config_classes[`${shapeName}s`]}${$$.getTargetSelectorSuffix(id)}`
      ) : $el.main).selectAll(`.${config_classes[shapeName]}${suffix}`);
    }
    return shape;
  },
  isWithinShape(that, d) {
    var _a;
    const $$ = this;
    const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(that);
    let isWithin;
    if (!$$.isTargetToShow(d.id)) {
      isWithin = false;
    } else if ((_a = $$.hasValidPointType) == null ? void 0 : _a.call($$, that.nodeName)) {
      isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScaleById(d.id)($$.getBaseValue(d))) : $$.isWithinCircle(
        that,
        $$.isBubbleType(d) ? $$.pointSelectR(d) * 1.5 : 0
      );
    } else if (that.nodeName === "path") {
      isWithin = shape.classed(config_classes.bar) ? $$.isWithinBar(that) : true;
    }
    return isWithin;
  },
  getInterpolate(d) {
    const $$ = this;
    const interpolation = $$.getInterpolateType(d);
    return CURVE_MAP[interpolation];
  },
  /**
   * Get curve generator for line-like shapes.
   * @param {object} d Data target
   * @returns {function} Curve generator
   * @private
   */
  getCurve(d) {
    const $$ = this;
    const isRotatedStepType = $$.config.axis_rotated && $$.isStepType(d);
    return isRotatedStepType ? (context) => {
      const step = $$.getInterpolate(d)(context);
      step.orgPoint = step.point;
      step.pointRotated = function(x, y) {
        this._point === 1 && (this._point = 2);
        const y1 = this._y * (1 - this._t) + y * this._t;
        this._context.lineTo(this._x, y1);
        this._context.lineTo(x, y1);
        this._x = x;
        this._y = y;
      };
      step.point = function(x, y) {
        this._point === 0 ? this.orgPoint(x, y) : this.pointRotated(x, y);
      };
      return step;
    } : $$.getInterpolate(d);
  },
  getInterpolateType(d) {
    const $$ = this;
    const { config } = $$;
    const type = config.spline_interpolation_type;
    const interpolation = $$.isInterpolationType(type) ? type : "cardinal";
    return $$.isSplineType(d) ? interpolation : $$.isStepType(d) ? config.line_step_type : "linear";
  },
  isWithinBar(that) {
    const mouse = getPointer(this.state.event, that);
    const list = getRectSegList(that);
    const [seg0, seg1, seg2] = list;
    const x = Math.min(seg0.x, seg1.x);
    const y = Math.min(seg0.y, seg1.y);
    const offset = this.config.bar_sensitivity;
    const width = Math.abs(seg2.x - seg1.x);
    const height = Math.abs(seg0.y - seg1.y);
    const sx = x - offset;
    const ex = x + width + offset;
    const sy = y + height + offset;
    const ey = y - offset;
    const isWithin = sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
    return isWithin;
  }
});

;// ./src/ChartInternal/ChartInternal.ts
var ChartInternal_defProp = Object.defineProperty;
var ChartInternal_defNormalProp = (obj, key, value) => key in obj ? ChartInternal_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var ChartInternal_publicField = (obj, key, value) => ChartInternal_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);































function getTime() {
  var _a, _b, _c;
  return (_c = (_b = (_a = win.performance) == null ? void 0 : _a.now) == null ? void 0 : _b.call(_a)) != null ? _c : Date.now();
}
function getUnsupportedCanvasRenderType($$) {
  if ($$.hasArcType()) {
    return "arc charts";
  }
  if ($$.hasType("funnel")) {
    return "funnel chart";
  }
  return null;
}
function fallbackUnsupportedCanvasRenderMode($$) {
  var _a, _b;
  const { config } = $$;
  const unsupportedType = config.render_mode === "canvas" ? getUnsupportedCanvasRenderType($$) : null;
  if (!unsupportedType) {
    return;
  }
  (_b = (_a = win.console) == null ? void 0 : _a.warn) == null ? void 0 : _b.call(
    _a,
    `[billboard.js] render.mode='canvas' is ignored for ${unsupportedType}; falling back to SVG.`
  );
  config.render_mode = "svg";
}
class ChartInternal {
  constructor(api) {
    ChartInternal_publicField(this, "api");
    // API interface
    ChartInternal_publicField(this, "config");
    // config object
    ChartInternal_publicField(this, "cache");
    // cache instance
    ChartInternal_publicField(this, "$el");
    // elements
    ChartInternal_publicField(this, "state");
    // state variables
    ChartInternal_publicField(this, "charts");
    // all Chart instances array within page (equivalent of 'bb.instances')
    // data object
    ChartInternal_publicField(this, "data", {
      xs: {},
      targets: []
    });
    // Axis
    ChartInternal_publicField(this, "axis");
    // Axis
    // scales
    ChartInternal_publicField(this, "scale", {
      x: null,
      y: null,
      y2: null,
      subX: null,
      subY: null,
      subY2: null,
      zoom: null
    });
    // original values
    ChartInternal_publicField(this, "org", {
      xScale: null,
      xDomain: null
    });
    // formatter function
    ChartInternal_publicField(this, "color");
    ChartInternal_publicField(this, "patterns");
    ChartInternal_publicField(this, "levelColor");
    ChartInternal_publicField(this, "point");
    ChartInternal_publicField(this, "brush");
    // format function
    ChartInternal_publicField(this, "format", {
      extraLineClasses: null,
      xAxisTick: null,
      dataTime: null,
      // dataTimeFormat
      defaultAxisTime: null,
      // defaultAxisTimeFormat
      axisTime: null
      // axisTimeFormat
    });
    const $$ = this;
    $$.api = api;
    $$.config = new Options();
    $$.cache = new Cache();
    const store = new Store();
    $$.$el = store.getStore("element");
    $$.state = store.getStore("state");
    $$.$T = $$.$T.bind($$);
  }
  /**
   * Get the selection based on transition config
   * @param {SVGElement|d3Selection} selection Target selection
   * @param {boolean} force Force transition
   * @param {string} name Transition name
   * @returns {d3Selection}
   * @private
   */
  $T(selection, force, name) {
    const { config, state } = this;
    const duration = config.transition_duration;
    const subchart = config.subchart_show;
    let t = selection;
    if (t) {
      if ("tagName" in t) {
        t = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(t);
      }
      const transit = (force !== false && duration || force) && (!state.zooming || state.dragging) && !state.resizing && state.rendered && !subchart;
      t = transit ? t.transition(name).duration(duration) : t;
    }
    return t;
  }
  beforeInit() {
    const $$ = this;
    $$.callPluginHook("$beforeInit");
    callFn($$.config.onbeforeinit, $$.api);
  }
  afterInit() {
    const $$ = this;
    $$.callPluginHook("$afterInit");
    callFn($$.config.onafterinit, $$.api);
  }
  init() {
    const $$ = this;
    const { config, state, $el } = $$;
    const { boost_useCssRule, bindto } = config;
    checkModuleImport($$);
    fallbackUnsupportedCanvasRenderMode($$);
    const hasArcType = $$.hasArcType();
    state.hasRadar = !state.hasAxis && $$.hasType("radar");
    state.hasFunnel = !state.hasAxis && $$.hasType("funnel");
    state.hasTreemap = !state.hasAxis && $$.hasType("treemap");
    state.hasAxis = !hasArcType && !state.hasFunnel && !state.hasTreemap;
    state.datetimeId = `bb-${+/* @__PURE__ */ new Date() * getRandom()}`;
    if (boost_useCssRule) {
      const styleEl = browser_doc.createElement("style");
      styleEl.type = "text/css";
      browser_doc.head.appendChild(styleEl);
      state.style = {
        rootSelector: `.${state.datetimeId}`,
        sheet: styleEl.sheet
      };
      $el.style = styleEl;
    }
    const bindConfig = {
      element: bindto,
      classname: "bb"
    };
    if (isObject(bindto)) {
      bindConfig.element = bindto.element || "#chart";
      bindConfig.classname = bindto.classname || bindConfig.classname;
    }
    $el.chart = isFunction(bindConfig.element.node) ? bindto.element : (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(bindConfig.element || []);
    if ($el.chart.empty()) {
      $el.chart = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(browser_doc.body.appendChild(browser_doc.createElement("div")));
    }
    $el.chart.html("").classed(bindConfig.classname, true).classed(state.datetimeId, boost_useCssRule).style("position", "relative");
    $$.initParams();
    $$.initToRender();
  }
  /**
   * Initialize the rendering process
   * @param {boolean} forced Force to render process
   * @private
   */
  initToRender(forced) {
    const $$ = this;
    const { config, state, $el: { chart } } = $$;
    const isHidden = () => hasStyle(chart, { display: "none", visibility: "hidden" });
    const isLazy = config.render.lazy === false ? false : config.render.lazy || isHidden();
    const MutationObserver = win.MutationObserver;
    if (isLazy && MutationObserver && config.render.observe !== false && !forced) {
      new MutationObserver((mutation, observer) => {
        if (!isHidden()) {
          observer.disconnect();
          !state.rendered && $$.initToRender(true);
        }
      }).observe(chart.node(), {
        attributes: true,
        attributeFilter: ["class", "style"]
      });
    }
    if (!isLazy || forced) {
      $$.convertData(config, (res) => {
        $$.initWithData(res);
        $$.afterInit();
      });
    }
  }
  initParams() {
    var _a, _b;
    const $$ = this;
    const { config, format: format2, state } = $$;
    if (config.render_mode === "canvas") {
      (_a = $$.prepareCanvasConfig) == null ? void 0 : _a.call($$);
    }
    $$.color = $$.generateColor();
    $$.levelColor = $$.generateLevelColor();
    if (config.padding === false) {
      config.axis_x_show = false;
      config.axis_y_show = false;
      config.axis_y2_show = false;
      config.subchart_show = false;
    }
    if (config.render_mode !== "canvas" && ($$.hasPointType() || ((_b = $$.hasLegendDefsPoint) == null ? void 0 : _b.call($$)))) {
      $$.point = $$.generatePoint();
    }
    if (state.hasAxis) {
      $$.initClip();
      format2.extraLineClasses = $$.generateExtraLineClass();
      format2.dataTime = config.data_xLocaltime ? external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_.timeParse : external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_.utcParse;
      format2.axisTime = config.axis_x_localtime ? external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_.timeFormat : external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_.utcFormat;
      const isDragZoom = config.zoom_enabled && config.zoom_type === "drag";
      format2.defaultAxisTime = (d) => {
        const { x, zoom } = $$.scale;
        const isZoomed = isDragZoom ? zoom : zoom && x.orgDomain().toString() !== zoom.domain().toString();
        const specifier = d.getMilliseconds() && ".%L" || d.getSeconds() && ".:%S" || d.getMinutes() && "%I:%M" || d.getHours() && "%I %p" || d.getDate() !== 1 && "%b %d" || isZoomed && d.getDate() === 1 && "%b'%y" || d.getMonth() && "%-m/%-d" || "%Y";
        return format2.axisTime(specifier)(d);
      };
    }
    const { legend_position, legend_inset_anchor, axis_rotated } = config;
    state.isLegendRight = legend_position === "right";
    state.isLegendInset = legend_position === "inset";
    state.isLegendTop = legend_inset_anchor === "top-left" || legend_inset_anchor === "top-right";
    state.isLegendLeft = legend_inset_anchor === "top-left" || legend_inset_anchor === "bottom-left";
    state.rotatedPadding.top = $$.getResettedPadding(state.rotatedPadding.top);
    state.rotatedPadding.right = axis_rotated && !config.axis_x_show ? 0 : 30;
    state.inputType = convertInputType(
      config.interaction_inputType_mouse,
      config.interaction_inputType_touch
    );
  }
  initWithData(data2) {
    var _a, _b, _c, _d, _e, _f;
    const $$ = this;
    const { config, scale: scale2, state, $el, org } = $$;
    const { hasAxis, hasFunnel, hasTreemap } = state;
    const hasInteraction = config.interaction_enabled;
    const hasPolar = $$.hasType("polar");
    const labelsBGColor = config.data_labels_backgroundColors;
    if (hasAxis) {
      $$.axis = $$.getAxisInstance();
      config.zoom_enabled && $$.initZoom();
    }
    $$.data.xs = {};
    $$.data.targets = $$.convertDataToTargets(data2);
    if (config.data_filter) {
      $$.data.targets = $$.data.targets.filter(config.data_filter.bind($$.api));
    }
    if (config.data_hide) {
      $$.addHiddenTargetIds(
        config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide
      );
    }
    if (config.legend_hide) {
      $$.addHiddenLegendIds(
        config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide
      );
    }
    $$.updateSizes();
    $$.updateScales(true);
    if (hasAxis) {
      const { x, y, y2, subX, subY, subY2 } = scale2;
      if (x) {
        x.domain(sortValue($$.getXDomain($$.data.targets), !config.axis_x_inverted));
        subX.domain(x.domain());
        org.xDomain = x.domain();
      }
      if (y) {
        y.domain($$.getYDomain($$.data.targets, "y"));
        subY.domain(y.domain());
      }
      if (y2) {
        y2.domain($$.getYDomain($$.data.targets, "y2"));
        subY2 && subY2.domain(y2.domain());
      }
    }
    if (config.render_mode === "canvas") {
      if (!$$.initCanvas) {
        throw Error(
          "[billboard.js] Please import and call canvas() to use render.mode='canvas'."
        );
      }
      $$.bindResize();
      $$.initCanvas();
      config.tooltip_show && $$.initTooltip();
      $$.callPluginHook("$init");
      callFn(config.oninit, $$.api);
      $$.redraw({
        withTransition: false,
        withTransform: true,
        withUpdateXDomain: true,
        withUpdateOrgXDomain: true,
        withTransitionForAxis: false,
        initializing: true
      });
      if (config.data_onmin || config.data_onmax) {
        const minMax = $$.getMinMaxData();
        callFn(config.data_onmin, $$.api, minMax.min);
        callFn(config.data_onmax, $$.api, minMax.max);
      }
      state.rendered = true;
      return;
    }
    $el.svg = $el.chart.append("svg").style("overflow", "hidden").style("display", "block");
    if (hasInteraction && state.inputType) {
      const isTouch = state.inputType === "touch";
      const { onclick, onover, onout } = config;
      const preventDefault = (_a = config.interaction_inputType_touch) == null ? void 0 : _a.preventDefault;
      const isPrevented = isBoolean(preventDefault) && preventDefault || false;
      const preventThreshold = !isNaN(preventDefault) && preventDefault || null;
      const touchOption = isTouch ? {
        passive: !isPrevented && preventThreshold === null
      } : void 0;
      $el.svg.on("click", (onclick == null ? void 0 : onclick.bind($$.api)) || null).on(
        isTouch ? "touchstart" : "mouseenter",
        (onover == null ? void 0 : onover.bind($$.api)) || null,
        touchOption
      ).on(isTouch ? "touchend" : "mouseleave", (onout == null ? void 0 : onout.bind($$.api)) || null);
    }
    config.svg_classname && $el.svg.attr("class", config.svg_classname);
    const hasColorPatterns = isFunction(config.color_tiles) && $$.patterns;
    if (hasAxis || hasColorPatterns || hasPolar || hasTreemap || labelsBGColor || ((_b = $$.hasLegendDefsPoint) == null ? void 0 : _b.call($$))) {
      $el.defs = $el.svg.append("defs");
      if (hasAxis) {
        ["id", "idXAxis", "idYAxis", "idGrid"].forEach((v) => {
          $$.appendClip($el.defs, state.clip[v]);
        });
      }
      $$.generateTextBGColorFilter(labelsBGColor);
      if (hasColorPatterns) {
        $$.patterns.forEach((p) => $el.defs.append(() => p.node));
      }
    }
    $$.updateSvgSize();
    $$.bindResize();
    const main = $el.svg.append("g").classed($COMMON.main, true).attr("transform", hasFunnel || hasTreemap ? null : $$.getTranslate("main"));
    $el.main = main;
    config.subchart_show && $$.initSubchart();
    config.tooltip_show && $$.initTooltip();
    config.title_text && $$.initTitle();
    !hasTreemap && config.legend_show && $$.initLegend();
    if (config.data_empty_label_text) {
      main.append("text").attr("class", `${$TEXT.text} ${$COMMON.empty}`).attr("text-anchor", "middle").attr("dominant-baseline", "middle");
    }
    if (hasAxis) {
      config.regions.length && ((_c = $$.initRegion) == null ? void 0 : _c.call($$));
      !config.clipPath && $$.axis.init();
    }
    main.append("g").classed($COMMON.chart, true).attr("clip-path", hasAxis ? state.clip.path : null);
    $$.callPluginHook("$init");
    $$.initChartElements();
    if (hasAxis) {
      hasInteraction && ((_d = $$.initEventRect) == null ? void 0 : _d.call($$));
      (_e = $$.initGrid) == null ? void 0 : _e.call($$);
      config.clipPath && ((_f = $$.axis) == null ? void 0 : _f.init());
    }
    $$.updateTargets($$.data.targets);
    $$.updateDimension();
    callFn(config.oninit, $$.api);
    $$.setBackground();
    $$.redraw({
      withTransition: false,
      withTransform: true,
      withUpdateXDomain: true,
      withUpdateOrgXDomain: true,
      withTransitionForAxis: false,
      initializing: true
    });
    if (config.data_onmin || config.data_onmax) {
      const minMax = $$.getMinMaxData();
      callFn(config.data_onmin, $$.api, minMax.min);
      callFn(config.data_onmax, $$.api, minMax.max);
    }
    config.tooltip_show && $$.initShowTooltip();
    state.rendered = true;
  }
  /**
   * Initialize chart elements
   * @private
   */
  initChartElements() {
    const $$ = this;
    const { hasAxis, hasRadar, hasTreemap } = $$.state;
    const types = [];
    if (hasAxis) {
      const shapes = ["bar", "bubble", "candlestick", "line"];
      if ($$.config.bar_front) {
        shapes.push(shapes.shift());
      }
      for (const shape2 of shapes) {
        const name = capitalize(shape2);
        if (shape2 === "line" && $$.hasTypeOf(name) || $$.hasType(shape2)) {
          types.push(name);
        }
      }
    } else if (hasTreemap) {
      types.push("Treemap");
    } else if ($$.hasType("funnel")) {
      types.push("Funnel");
    } else {
      const hasPolar = $$.hasType("polar");
      const hasGauge = $$.hasType("gauge");
      if (!hasRadar) {
        types.push("Arc", "Pie");
      }
      if (hasGauge) {
        types.push("Gauge");
      } else if (hasRadar) {
        types.push("Radar");
      } else if (hasPolar) {
        types.push("Polar");
      }
    }
    for (const type of types) {
      $$[`init${type}`]();
    }
    if (notEmpty($$.config.data_labels) && !$$.hasArcType(null, ["radar"])) {
      $$.initText();
    }
  }
  /**
   * Set chart elements
   * @private
   */
  setChartElements() {
    const $$ = this;
    const {
      $el: {
        chart,
        svg,
        defs,
        main,
        tooltip: tooltip2,
        legend: legend2,
        title: title2,
        canvas,
        eventOverlay,
        grid,
        needle,
        arcs: arc,
        circle: circles,
        bar: bars,
        candlestick,
        line: lines,
        area: areas,
        text: texts
      }
    } = $$;
    $$.api.$ = {
      chart,
      svg,
      canvas,
      eventOverlay,
      defs,
      main,
      tooltip: tooltip2,
      legend: legend2,
      title: title2,
      grid,
      arc,
      circles,
      bar: { bars },
      candlestick,
      line: { lines, areas },
      needle,
      text: { texts }
    };
  }
  /**
   * Set background element/image
   * @private
   */
  setBackground() {
    const $$ = this;
    const { config: { background: bg }, state, $el: { svg } } = $$;
    if (notEmpty(bg)) {
      const element = svg.select("g").insert(bg.imgUrl ? "image" : "rect", ":first-child");
      if (bg.imgUrl) {
        element.attr("href", bg.imgUrl);
      } else if (bg.color) {
        element.style("fill", bg.color).attr("clip-path", state.clip.path);
      }
      element.attr("class", bg.class || null).attr("width", "100%").attr("height", "100%");
    }
  }
  /**
   * Update targeted element with given data
   * @param {object} targets Data object formatted as 'target'
   * @private
   */
  updateTargets(targets) {
    var _a, _b;
    const $$ = this;
    const { hasAxis, hasFunnel, hasRadar, hasTreemap } = $$.state;
    const helper = (type) => $$[`updateTargetsFor${type}`](
      targets.filter($$[`is${type}Type`].bind($$))
    );
    $$.updateTargetsForText(targets);
    if (hasAxis) {
      const shapes = ["bar", "candlestick", "line"];
      for (const shape2 of shapes) {
        const name = capitalize(shape2);
        if (shape2 === "line" && $$.hasTypeOf(name) || $$.hasType(shape2)) {
          helper(name);
        }
      }
      (_a = $$.updateTargetsForSubchart) == null ? void 0 : _a.call($$, targets);
    } else if ($$.hasArcType(targets)) {
      let type = "Arc";
      if (hasRadar) {
        type = "Radar";
      } else if ($$.hasType("polar")) {
        type = "Polar";
      }
      helper(type);
    } else if (hasFunnel) {
      helper("Funnel");
    } else if (hasTreemap) {
      helper("Treemap");
    }
    const hasPointType = $$.hasType("bubble") || $$.hasType("scatter");
    if (hasPointType) {
      (_b = $$.updateTargetForCircle) == null ? void 0 : _b.call($$);
    }
    $$.filterTargetsToShowAtInit(hasPointType);
  }
  /**
   * Display targeted elements at initialization
   * @param {boolean} hasPointType whether has point type(bubble, scatter) or not
   * @private
   */
  filterTargetsToShowAtInit(hasPointType = false) {
    const $$ = this;
    const { $el: { svg }, $T } = $$;
    let selector = `.${$COMMON.target}`;
    if (hasPointType) {
      selector += `, .${$CIRCLE.chartCircles} > .${$CIRCLE.circles}`;
    }
    $T(svg.selectAll(selector).filter((d) => $$.isTargetToShow(d.id))).style("opacity", null);
  }
  getWithOption(options) {
    const withOptions = {
      Dimension: true,
      EventRect: true,
      Legend: false,
      Subchart: true,
      Transform: false,
      Transition: true,
      TrimXDomain: true,
      UpdateXAxis: "UpdateXDomain",
      UpdateXDomain: false,
      UpdateOrgXDomain: false,
      TransitionForExit: "Transition",
      TransitionForAxis: "Transition",
      Y: true
    };
    for (const [key, defVal] of Object.entries(withOptions)) {
      const value = isString(defVal) ? withOptions[defVal] : defVal;
      withOptions[key] = getOption(options, `with${key}`, value);
    }
    return withOptions;
  }
  initialOpacity(d) {
    const $$ = this;
    const { withoutFadeIn } = $$.state;
    return $$.getBaseValue(d) !== null && withoutFadeIn[d.id] ? null : "0";
  }
  bindResize() {
    var _a, _b;
    const $$ = this;
    const { $el, config, state } = $$;
    const { resize_auto, resize_live } = config;
    const isAutoResize = /^(true|parent)$/.test(resize_auto);
    const list = [];
    const redrawOnResize = () => {
      var _a2;
      const prevWidth = state.current.width;
      const prevHeight = state.current.height;
      $$.setContainerSize();
      if (!state.resizePreview && prevWidth === state.current.width && prevHeight === state.current.height) {
        return false;
      }
      state.resizing = true;
      state.dirty.size = true;
      if (config.legend_show) {
        $$.updateSizes();
        state.isCanvasMode ? (_a2 = $$.updateHtmlLegend) == null ? void 0 : _a2.call($$) : $$.updateLegend();
      }
      $$.api.flush(false);
      return true;
    };
    const liveResize = () => {
      if (state.resizeLiveScale === null) {
        state.resizeLiveScale = state.resizeRedrawTime > RESIZE_FRAME_BUDGET;
      }
      if (state.resizeLiveScale) {
        $$.previewResize();
        return;
      }
      const start = getTime();
      if (redrawOnResize()) {
        state.resizeRedrawTime = getTime() - start;
        state.resizeLiveScale = state.resizeRedrawTime > RESIZE_FRAME_BUDGET;
      }
    };
    const resizeFunction = generateResize(
      config.resize_timer,
      isAutoResize && resize_live ? liveResize : void 0
    );
    list.push(() => callFn(config.onresize, $$.api));
    isAutoResize && list.push(redrawOnResize);
    list.push(() => {
      callFn(config.onresized, $$.api);
      state.resizing = false;
      state.resizeLiveScale = null;
    });
    list.forEach((v) => resizeFunction.add(v));
    $$.resizeFunction = resizeFunction;
    if (resize_auto === "parent" && win.ResizeObserver) {
      ($$.resizeFunction.resizeObserver = new win.ResizeObserver(
        $$.resizeFunction.bind($$)
      )).observe($el.chart.node().parentNode);
    } else {
      if (resize_auto === "parent") {
        (_b = (_a = win.console) == null ? void 0 : _a.warn) == null ? void 0 : _b.call(
          _a,
          "[billboard.js] resize.auto='parent' requires ResizeObserver; falling back to window resize."
        );
      }
      win.addEventListener("resize", $$.resizeFunction);
    }
  }
  /**
   * Call plugin hook
   * @param {string} phase The lifecycle phase
   * @param {Array} args Arguments
   * @private
   */
  callPluginHook(phase, ...args) {
    this.config.plugins.forEach((v) => {
      if (phase === "$beforeInit") {
        v.$$ = this;
        this.api.plugins.push(v);
      }
      v[phase](...args);
    });
  }
}
extend(ChartInternal.prototype, [
  // common
  convert,
  data_data,
  load,
  category,
  internals_class,
  internals_color,
  domain,
  interactions_interaction,
  format,
  internals_legend,
  redraw,
  scale,
  shape,
  size,
  style,
  internals_text,
  internals_title,
  internals_tooltip,
  transform,
  type
]);

;// ./src/config/resolver/canvas.ts















const CANVAS_SELECTABLE_TYPE_FILTERS = [
  isCanvasPointType,
  isCanvasBarType,
  isCanvasCandlestickType,
  isCanvasTreemapType
];
const CANVAS_LEGEND_TOUCH_TAP_THRESHOLD = 10;
const CANVAS_LEGEND_TOUCH_CLICK_TIMEOUT = 750;
const CANVAS_SUBCHART_HANDLE_SIZE = 6;
const CANVAS_SUBCHART_CLICK_TOLERANCE = 2;
const CANVAS_FLOW_ANIMATION_MAX_VALUES = 1e5;
const CANVAS_HTML_ATTR_ESCAPE = {
  "&": "&amp;",
  "<": "&lt;",
  ">": "&gt;",
  '"': "&quot;",
  "'": "&#39;"
};
const canvasSelectionDragRows = /* @__PURE__ */ new WeakMap();
function warn(message) {
  var _a, _b;
  (_b = (_a = win.console) == null ? void 0 : _a.warn) == null ? void 0 : _b.call(_a, `[billboard.js] ${message}`);
}
function getLegendText($$, id) {
  var _a;
  const { config } = $$;
  const text = (_a = config.data_names[id]) != null ? _a : id;
  return isFunction(config.legend_format) ? config.legend_format(text, id !== text ? id : void 0) : text;
}
function escapeHtmlAttr(value) {
  return `${value}`.replace(/[&<>"']/g, (char) => CANVAS_HTML_ATTR_ESCAPE[char]);
}
function getCanvasLegendPointPattern($$, id) {
  var _a, _b;
  const { config } = $$;
  const targetIds = ((_a = $$.mapToIds) == null ? void 0 : _a.call($$, $$.data.targets)) || [];
  const pattern = ((_b = $$.getValidPointPattern) == null ? void 0 : _b.call($$)) || (Array.isArray(config.point_pattern) && config.point_pattern.length ? config.point_pattern : [config.point_type]);
  const index = Math.max(0, targetIds.indexOf(id));
  return pattern[index % pattern.length] || "circle";
}
function getCanvasLegendPointIcon($$, id) {
  const color = escapeHtmlAttr($$.color(id));
  const pattern = getCanvasLegendPointPattern($$, id);
  const svgAttrs = 'viewBox="0 0 8 8" aria-hidden="true" focusable="false" style="display:block;width:100%;height:100%;overflow:visible;pointer-events:none"';
  const paintAttrs = `fill="${color}" stroke="${color}"`;
  if (/^rect(angle)?$/i.test(pattern)) {
    return `<svg ${svgAttrs}><rect x="1" y="1" width="6" height="6" ${paintAttrs}></rect></svg>`;
  }
  if (!pattern || /^circle$/i.test(pattern)) {
    return `<svg ${svgAttrs}><circle cx="4" cy="4" r="3" ${paintAttrs}></circle></svg>`;
  }
  return `<svg ${svgAttrs}><g ${paintAttrs}>${sanitize(pattern)}</g></svg>`;
}
function updateCanvasLegendItemMap($$, item) {
  const itemMap = /* @__PURE__ */ new Map();
  item.each(function(id) {
    itemMap.set(id, this);
  });
  $$.cache.add(KEY.legendItemMap, itemMap);
}
function setCanvasHtmlLegendItem($$, item) {
  const { config } = $$;
  item.attr("class", function(id) {
    const current = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).attr("class") || "";
    const next = `${current} ${$$.generateClass($LEGEND.legendItem, id)}`;
    return Array.from(new Set(next.trim().split(/\s+/).filter(Boolean))).join(" ");
  }).style("visibility", (id) => $$.isLegendToShow(id) ? null : "hidden").classed($LEGEND.legendItemHidden, (id) => !$$.isTargetToShow(id)).classed($CANVAS.legendItemInteractive, !!config.interaction_enabled);
  updateCanvasLegendItemMap($$, item);
}
function setCanvasHtmlLegendFocus($$, id) {
  var _a;
  const { legend } = $$.$el;
  const targetIds = ((_a = $$.mapToTargetIds) == null ? void 0 : _a.call($$, [id])) || [id];
  legend == null ? void 0 : legend.selectAll(`.${$LEGEND.legendItem}`).classed($FOCUS.legendItemFocused, (d) => targetIds.indexOf(d) >= 0).style("opacity", function(d) {
    return targetIds.indexOf(d) >= 0 ? null : $$.opacityForUnfocusedLegend.call($$, (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this));
  });
}
function revertCanvasHtmlLegendFocus($$) {
  const { legend } = $$.$el;
  legend == null ? void 0 : legend.selectAll(`.${$LEGEND.legendItem}`).classed($FOCUS.legendItemFocused, false).style("opacity", null);
}
function setCanvasLegendTargetFocus($$, id) {
  var _a, _b, _c;
  const { state } = $$;
  const targetIds = ((_a = $$.mapToTargetIds) == null ? void 0 : _a.call($$, [id])) || [id];
  const focusedIds = targetIds.filter($$.isTargetToShow, $$);
  const focusedSet = new Set(focusedIds);
  const defocusedIds = (((_b = $$.mapToTargetIds) == null ? void 0 : _b.call($$)) || []).filter((targetId) => !focusedSet.has(targetId) && $$.isTargetToShow(targetId));
  state.focusedTargetIds = focusedSet;
  state.defocusedTargetIds = new Set(defocusedIds);
  (_c = $$.renderCanvasFrame) == null ? void 0 : _c.call($$, void 0, null, false);
}
function revertCanvasLegendTargetFocus($$) {
  var _a, _b, _c;
  const { state } = $$;
  const changed = !!((_a = state.focusedTargetIds) == null ? void 0 : _a.size) || !!((_b = state.defocusedTargetIds) == null ? void 0 : _b.size);
  state.focusedTargetIds = /* @__PURE__ */ new Set();
  state.defocusedTargetIds = /* @__PURE__ */ new Set();
  changed && ((_c = $$.renderCanvasFrame) == null ? void 0 : _c.call($$, void 0, null, false));
}
function getCanvasLegendTouchPoint(event) {
  var _a, _b;
  return ((_a = event.changedTouches) == null ? void 0 : _a[0]) || ((_b = event.touches) == null ? void 0 : _b[0]);
}
function setCanvasLegendTouchStart($$, id, event) {
  const touch = getCanvasLegendTouchPoint(event);
  $$.state.canvasLegendTouch = touch ? {
    id,
    x: touch.clientX,
    y: touch.clientY,
    moved: false
  } : null;
}
function updateCanvasLegendTouchMove($$, event) {
  const start = $$.state.canvasLegendTouch;
  const touch = start && getCanvasLegendTouchPoint(event);
  if (touch) {
    start.moved = start.moved || Math.abs(touch.clientX - start.x) > CANVAS_LEGEND_TOUCH_TAP_THRESHOLD || Math.abs(touch.clientY - start.y) > CANVAS_LEGEND_TOUCH_TAP_THRESHOLD;
  }
}
function isCanvasLegendTouchTap($$, id, event) {
  updateCanvasLegendTouchMove($$, event);
  const start = $$.state.canvasLegendTouch;
  $$.state.canvasLegendTouch = null;
  return !!start && start.id === id && !start.moved;
}
function markCanvasLegendTouchClick($$, id) {
  $$.state.canvasLegendLastTouchClickId = id;
  $$.state.canvasLegendLastTouchClickTime = Date.now();
}
function isDuplicateCanvasLegendTouchClick($$, id) {
  const { state } = $$;
  const duplicate = state.canvasLegendLastTouchClickId === id && Date.now() - (state.canvasLegendLastTouchClickTime || 0) < CANVAS_LEGEND_TOUCH_CLICK_TIMEOUT;
  if (duplicate) {
    state.canvasLegendLastTouchClickId = null;
    state.canvasLegendLastTouchClickTime = 0;
  }
  return duplicate;
}
function bindCanvasHtmlLegendInteractions($$, item) {
  const { api, config, state } = $$;
  item.on("click dblclick mouseover mouseout touchstart touchmove touchend", null);
  if (!config.interaction_enabled) {
    return;
  }
  const interaction = config.legend_item_interaction;
  const eventType = typeof interaction === "object" && (interaction == null ? void 0 : interaction.dblclick) ? "dblclick" : "click";
  const isTouch = state.inputType === "touch";
  const hasClickInteraction = interaction || isFunction(config.legend_item_onclick);
  const touchOption = isTouch ? getCanvasTouchListenerOption(config) : void 0;
  const handleCanvasLegendToggle = function(event, id) {
    var _a;
    if (!callFn(config.legend_item_onclick, api, id, !state.hiddenTargetIds.has(id))) {
      const selected = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      if (event.type === "dblclick" || event.altKey) {
        if (state.hiddenTargetIds.size && !selected.classed($LEGEND.legendItemHidden)) {
          api.show();
        } else {
          api.hide();
          api.show(id);
        }
      } else {
        api.toggle(id);
        selected.classed($FOCUS.legendItemFocused, false);
      }
      revertCanvasLegendTargetFocus($$);
    }
    isTouch && ((_a = $$.hideTooltip) == null ? void 0 : _a.call($$));
  };
  item.on(eventType, hasClickInteraction ? function(event, id) {
    if (isTouch && event.type === "click" && isDuplicateCanvasLegendTouchClick($$, id)) {
      return;
    }
    handleCanvasLegendToggle.call(this, event, id);
  } : null);
  isTouch && eventType === "click" && hasClickInteraction && item.on("touchstart", function(event, id) {
    setCanvasLegendTouchStart($$, id, event);
  }, touchOption).on("touchmove", (event) => {
    updateCanvasLegendTouchMove($$, event);
  }, touchOption).on("touchend", function(event, id) {
    if (isCanvasLegendTouchTap($$, id, event)) {
      markCanvasLegendTouchClick($$, id);
      handleCanvasLegendToggle.call(this, event, id);
    }
  }, touchOption);
  !isTouch && item.on("mouseover", interaction || isFunction(config.legend_item_onover) ? function(event, id) {
    if (!callFn(config.legend_item_onover, api, id, !state.hiddenTargetIds.has(id))) {
      if (!state.transiting && $$.isTargetToShow(id)) {
        setCanvasHtmlLegendFocus($$, id);
        setCanvasLegendTargetFocus($$, id);
      }
    }
  } : null).on("mouseout", interaction || isFunction(config.legend_item_onout) ? function(event, id) {
    if (!callFn(config.legend_item_onout, api, id, !state.hiddenTargetIds.has(id))) {
      revertCanvasHtmlLegendFocus($$);
      revertCanvasLegendTargetFocus($$);
    }
  } : null);
}
function measureSvgLegendText($$, text) {
  var _a, _b;
  const chart = (_b = (_a = $$.$el.chart) == null ? void 0 : _a.node) == null ? void 0 : _b.call(_a);
  const doc = chart == null ? void 0 : chart.ownerDocument;
  if (!chart || !doc) {
    return null;
  }
  const svg = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
  const group = doc.createElementNS("http://www.w3.org/2000/svg", "g");
  const textElement = doc.createElementNS("http://www.w3.org/2000/svg", "text");
  svg.style.cssText = "position:absolute;visibility:hidden;left:-10000px;top:-10000px;";
  group.setAttribute("class", $LEGEND.legendItem);
  textElement.textContent = text;
  group.appendChild(textElement);
  svg.appendChild(group);
  chart.appendChild(svg);
  const rect = getBoundingRect(textElement);
  svg.remove();
  return rect;
}
function isSupportedCanvasXType(type) {
  return /^(indexed|category|log|timeseries)$/.test(type);
}
function isSupportedCanvasYType(type) {
  return /^(indexed|log|timeseries)$/.test(type);
}
function getCanvasEventClientPoint(event) {
  var _a, _b;
  const touchEvent = event;
  const touch = ((_a = touchEvent.changedTouches) == null ? void 0 : _a[0]) || ((_b = touchEvent.touches) == null ? void 0 : _b[0]);
  return touch || ("clientX" in event ? event : null);
}
function getCanvasEventDatum($$, event, shapeOnly = false) {
  var _a, _b;
  const point = getCanvasEventPoint($$, event);
  return point ? shapeOnly ? (_b = (_a = $$.hitDetector).findNearestShape) == null ? void 0 : _b.call(_a, point[0], point[1]) : $$.hitDetector.findNearest(point[0], point[1]) : null;
}
function isCanvasXIndexHoverArea($$, point) {
  var _a;
  const { config, state } = $$;
  const { height, margin, width, xAxisHeight } = state;
  const [x, y] = point;
  const left = margin.left;
  const right = margin.left + width;
  const top = margin.top;
  const bottom = margin.top + height;
  const axisBand = config.axis_x_show ? Math.max(xAxisHeight || 0, 24) : 0;
  if (((_a = $$.isMultipleX) == null ? void 0 : _a.call($$)) || state.hasTreemap) {
    return false;
  }
  return config.axis_rotated ? y >= top && y <= bottom && x >= left - axisBand && x <= right : x >= left && x <= right && y >= top && y <= bottom + axisBand;
}
function isCanvasAxisTooltipArea($$, point) {
  const { state: { height, margin, width } } = $$;
  const [x, y] = point;
  return x >= margin.left && x <= margin.left + width && y >= margin.top && y <= margin.top + height;
}
function getCanvasHoverDatumFromPoint($$, point) {
  var _a, _b;
  return $$.hitDetector.findNearest(point[0], point[1]) || (isCanvasXIndexHoverArea($$, point) ? (_b = (_a = $$.hitDetector).findNearestIndexByCoord) == null ? void 0 : _b.call(_a, point[0], point[1]) : null);
}
function getCanvasTooltipData($$, d) {
  var _a;
  const { config, state } = $$;
  const targetsToShow = $$.filterTargetsToShow($$.data.targets);
  const pointBased = isCanvasPointBasedInteraction($$, d);
  const sameXData = config.tooltip_grouped && !state.hasTreemap && !pointBased ? (_a = $$.filterByX) == null ? void 0 : _a.call($$, targetsToShow, d.x) : null;
  return (state.hasTreemap ? [d] : pointBased ? [d] : config.tooltip_grouped ? (sameXData == null ? void 0 : sameXData.length) ? sameXData : targetsToShow.map((target) => target.values[d.index]).filter(Boolean) : [d]).map((v) => {
    var _a2;
    return ((_a2 = $$.addName) == null ? void 0 : _a2.call($$, v)) || v;
  });
}
function getCanvasFocusData($$, d, selectedData) {
  var _a, _b;
  return ((_a = $$.isMultipleX) == null ? void 0 : _a.call($$)) && !isCanvasPointBasedInteraction($$, d) ? [((_b = $$.addName) == null ? void 0 : _b.call($$, d)) || d] : selectedData;
}
function getCanvasEventPoint($$, event) {
  const point = getCanvasEventClientPoint(event);
  if (!point) {
    return null;
  }
  const canvas2 = $$.$el.canvas.node();
  const rect = getBoundingRect(canvas2, true);
  return [point.clientX - rect.left, point.clientY - rect.top];
}
function normalizeCanvasSubchartDomain($$, domain) {
  var _a, _b;
  if (!Array.isArray(domain) || domain.length < 2) {
    return null;
  }
  const values = domain.slice(0, 2);
  return ((_b = (_a = $$.axis) == null ? void 0 : _a.isTimeSeries) == null ? void 0 : _b.call(_a)) ? values.map((value) => parseDate.call($$, value)) : values;
}
function getCanvasSubchartRect($$) {
  const { config, state } = $$;
  if (!config.subchart_show || !state.hasAxis || state.width2 <= 0 || state.height2 <= 0) {
    return null;
  }
  return {
    x: state.margin2.left,
    y: state.margin2.top,
    w: state.width2,
    h: state.height2
  };
}
function isCanvasSubchartPoint($$, point) {
  const rect = getCanvasSubchartRect($$);
  return !!rect && point[0] >= rect.x && point[0] <= rect.x + rect.w && point[1] >= rect.y && point[1] <= rect.y + rect.h;
}
function getCanvasMainPointFromSubchart($$, point) {
  const { config, state } = $$;
  const rect = getCanvasSubchartRect($$);
  if (config.subchart_brush_enabled !== false || !rect || !isCanvasSubchartPoint($$, point)) {
    return null;
  }
  const mainCoord = getMainCoordFromSubchartCoord(
    $$,
    config.axis_rotated ? point[1] - rect.y : point[0] - rect.x
  );
  if (mainCoord === null) {
    return null;
  }
  return config.axis_rotated ? [state.margin.left + state.width / 2, state.margin.top + mainCoord] : [state.margin.left + mainCoord, state.margin.top + state.height / 2];
}
function getCanvasSubchartBrushExtent($$) {
  var _a, _b;
  const rect = getCanvasSubchartRect($$);
  const axisLength = rect ? $$.config.axis_rotated ? rect.h : rect.w : 0;
  const extent = (_b = (_a = $$.axis) == null ? void 0 : _a.getExtent) == null ? void 0 : _b.call(_a);
  const values = Array.isArray(extent) ? extent.slice(0, 2) : [];
  if (values.length === 2 && values.every(Number.isFinite)) {
    const start = Math.max(0, Math.min(axisLength, values[0]));
    const end = Math.max(0, Math.min(axisLength, values[1]));
    return [Math.min(start, end), Math.max(start, end)];
  }
  return [0, axisLength];
}
function getCanvasSubchartBrushCoord($$, event, clampToExtent = false) {
  const point = getCanvasEventPoint($$, event);
  const rect = point && getCanvasSubchartRect($$);
  if (!point || !rect || !isCanvasSubchartPoint($$, point)) {
    return null;
  }
  const raw = $$.config.axis_rotated ? point[1] - rect.y : point[0] - rect.x;
  const [min, max] = getCanvasSubchartBrushExtent($$);
  if (!clampToExtent && (raw < min || raw > max)) {
    return null;
  }
  return Math.max(min, Math.min(max, raw));
}
function getCanvasSubchartDomainFromCoords($$, start, end) {
  const coordStart = Math.min(start, end);
  const coordEnd = Math.max(start, end);
  return [
    $$.scale.subX.invert(coordStart),
    $$.scale.subX.invert(coordEnd)
  ];
}
function getCanvasSubchartBrushSelection($$) {
  const { scale, state } = $$;
  const domain = state.domain;
  if (!(domain == null ? void 0 : domain.length) || !scale.subX) {
    return null;
  }
  const rect = getCanvasSubchartRect($$);
  const p0 = scale.subX(domain[0]);
  const p1 = scale.subX(domain[1]);
  if (!rect || !Number.isFinite(p0) || !Number.isFinite(p1)) {
    return null;
  }
  const [min, max] = getCanvasSubchartBrushExtent($$);
  return [
    Math.max(min, Math.min(max, Math.min(p0, p1))),
    Math.max(min, Math.min(max, Math.max(p0, p1)))
  ];
}
function getCanvasSubchartBrushMode($$, coord) {
  const selection = getCanvasSubchartBrushSelection($$);
  if (!selection) {
    return "select";
  }
  const [start, end] = selection;
  if (Math.abs(coord - start) <= CANVAS_SUBCHART_HANDLE_SIZE) {
    return "resize-start";
  }
  if (Math.abs(coord - end) <= CANVAS_SUBCHART_HANDLE_SIZE) {
    return "resize-end";
  }
  return coord > start && coord < end ? "move" : "select";
}
function clampCanvasSubchartSelection($$, start, end) {
  const [min, max] = getCanvasSubchartBrushExtent($$);
  return [
    Math.max(min, Math.min(max, start)),
    Math.max(min, Math.min(max, end))
  ];
}
function getCanvasSubchartCursor($$, mode) {
  if (/^resize/.test(mode)) {
    return $$.config.axis_rotated ? "ns-resize" : "ew-resize";
  }
  return mode === "move" ? "move" : "crosshair";
}
function getCanvasDataKey(d) {
  return d ? `${d.id}:${d.index}` : null;
}
function getCanvasSelectionDragDelta($$, dataRows) {
  const previousKeys = $$.state.canvasSelectionDragIncluded;
  const previousRows = canvasSelectionDragRows.get($$) || /* @__PURE__ */ new Map();
  const currentRows = /* @__PURE__ */ new Map();
  const included = /* @__PURE__ */ new Set();
  const rows = [];
  dataRows.filter((d) => isCanvasSelectableData($$, d)).forEach((d) => {
    const key = getCanvasDataKey(d);
    if (key) {
      included.add(key);
      !currentRows.has(key) && currentRows.set(key, d);
    }
  });
  currentRows.forEach((d, key) => {
    !previousKeys.has(key) && rows.push(d);
  });
  previousRows.forEach((d, key) => {
    !included.has(key) && rows.push(d);
  });
  canvasSelectionDragRows.set($$, currentRows);
  return { included, rows };
}
function getCanvasSelectionIds(ids) {
  return ids ? Array.isArray(ids) ? ids : [ids] : null;
}
function isCanvasSelectableData($$, d) {
  return d && hasCanvasDrawableValue($$, d) && isCanvasTargetSupported($$, d, CANVAS_SELECTABLE_TYPE_FILTERS) && CANVAS_SELECTABLE_TYPE_FILTERS.some((filter) => filter($$, d)) && $$.config.data_selection_isselectable.bind($$.api)(d);
}
function eachCanvasSelectableData($$, callback) {
  $$.filterTargetsToShow($$.data.targets).filter((target) => isCanvasTargetSupported($$, target, CANVAS_SELECTABLE_TYPE_FILTERS)).forEach((target) => {
    target.values.forEach((d) => {
      isCanvasSelectableData($$, d) && callback(d);
    });
  });
}
function isCanvasPointBasedInteraction($$, d) {
  return !($$.config.axis_x_forceAsSingle && $$.config.tooltip_grouped) && (isCanvasScatterType($$, d) || isCanvasBubbleType($$, d));
}
function isCanvasTouchEnabled(config) {
  return config.interaction_inputType_touch !== false;
}
function getCanvasTouchListenerOption(config) {
  var _a;
  const preventDefault = (_a = config.interaction_inputType_touch) == null ? void 0 : _a.preventDefault;
  const isPrevented = isBoolean(preventDefault) && preventDefault || false;
  const preventThreshold = !isNaN(preventDefault) && preventDefault || null;
  return {
    passive: !isPrevented && preventThreshold === null
  };
}
function getCanvasTouchPreventer(config) {
  var _a;
  const preventDefault = (_a = config.interaction_inputType_touch) == null ? void 0 : _a.preventDefault;
  const isPrevented = isBoolean(preventDefault) && preventDefault || false;
  const preventThreshold = !isNaN(preventDefault) && preventDefault || null;
  let startPx;
  return (event) => {
    var _a2, _b;
    const touch = ((_a2 = event.changedTouches) == null ? void 0 : _a2[0]) || ((_b = event.touches) == null ? void 0 : _b[0]);
    if (!touch) {
      return;
    }
    const currentXY = touch[`client${config.axis_rotated ? "Y" : "X"}`];
    if (event.type === "touchstart") {
      if (isPrevented) {
        event.preventDefault();
      } else if (preventThreshold !== null) {
        startPx = currentXY;
      }
    } else if (event.type === "touchmove" && (isPrevented || startPx === true || preventThreshold !== null && Math.abs(startPx - currentXY) >= preventThreshold)) {
      startPx = true;
      event.preventDefault();
    }
  };
}
function shouldHandleCanvasPointerEvent($$, event) {
  return event.pointerType !== "mouse" && $$.state.inputType !== "touch";
}
function isDuplicateCanvasInputClick($$, d) {
  const { state } = $$;
  const key = getCanvasDataKey(d);
  const duplicate = key && state.canvasLastInputClickKey === key && Date.now() - (state.canvasLastInputClickTime || 0) < 750;
  if (duplicate) {
    state.canvasLastInputClickKey = null;
    state.canvasLastInputClickTime = 0;
  }
  return Boolean(duplicate);
}
function markCanvasInputClick($$, d) {
  $$.state.canvasLastInputClickKey = getCanvasDataKey(d);
  $$.state.canvasLastInputClickTime = Date.now();
}
function getCanvasAnimationTime() {
  var _a, _b, _c;
  return (_c = (_b = (_a = win.performance) == null ? void 0 : _a.now) == null ? void 0 : _b.call(_a)) != null ? _c : Date.now();
}
function isCanvasFlowDomain(domain, isLog = false) {
  return Array.isArray(domain) && domain.length >= 2 && domain.every((v) => Number.isFinite(+v) && (!isLog || +v > 0));
}
function interpolateCanvasFlowDomain(start, end, ratio, isLog = false) {
  return start.slice(0, 2).map((value, index) => {
    const next = isLog ? Math.exp(Math.log(+value) + (Math.log(+end[index]) - Math.log(+value)) * ratio) : +value + (+end[index] - +value) * ratio;
    return value instanceof Date || end[index] instanceof Date ? new Date(next) : next;
  });
}
function getCanvasFlowValueCount($$) {
  return $$.data.targets.reduce((sum, target) => sum + target.values.length, 0);
}
function syncCanvasFlowYDomains($$) {
  const { scale } = $$;
  const targetsToShow = $$.filterTargetsToShow($$.data.targets);
  ["y", "y2"].forEach((key) => {
    var _a;
    (_a = scale[key]) == null ? void 0 : _a.domain($$.getYDomain(targetsToShow, key));
  });
  $$.withSubchartTypeContext(() => {
    var _a, _b;
    (_a = scale.subY) == null ? void 0 : _a.domain($$.getYDomain(targetsToShow, "y"));
    (_b = scale.subY2) == null ? void 0 : _b.domain($$.getYDomain(targetsToShow, "y2"));
  });
}
const canvasInternal = {
  /**
   * Normalize unsupported options before initializing canvas mode.
   * @private
   */
  prepareCanvasConfig() {
    var _a, _b;
    const { config, state } = this;
    this.warnUnsupportedCanvasOptions();
    if (((_a = state.orgConfig) == null ? void 0 : _a.transition) && Object.prototype.hasOwnProperty.call(state.orgConfig.transition, "duration") && state.orgConfig.transition.duration) {
      warn("canvas mode: transition.duration is ignored; canvas redraws synchronously.");
    }
    config.transition_duration = 0;
    if (!isSupportedCanvasXType(config.axis_x_type)) {
      config.axis_x_type = "indexed";
    }
    if (!isSupportedCanvasYType(config.axis_y_type)) {
      config.axis_y_type = "indexed";
    }
    if (!isSupportedCanvasYType(config.axis_y2_type)) {
      config.axis_y2_type = "indexed";
    }
    if ((_b = this.hasType) == null ? void 0 : _b.call(this, "bubble")) {
      config.point_show = true;
      config.point_type = "circle";
    }
  },
  /**
   * Apply the current canvas subchart selection to the main x domain.
   * @private
   */
  applyCanvasSubchartDomain() {
    const $$ = this;
    const { axis, config, scale, state } = $$;
    if (!config.subchart_show || !state.hasAxis || !scale.subX) {
      return;
    }
    if (!state.rendered && !state.domain && config.subchart_init_range) {
      state.domain = normalizeCanvasSubchartDomain($$, config.subchart_init_range);
    }
    const domain = normalizeCanvasSubchartDomain($$, state.domain);
    if (!domain || !$$.withinRange(domain, $$.getZoomDomain("subX", true), $$.getZoomDomain("subX"))) {
      return;
    }
    state.domain = domain;
    scale.x.domain(domain);
    axis.x.scale(scale.x);
  },
  /**
   * Set the canvas subchart selection domain and redraw the main chart.
   * @param {Array} domain Domain range
   * @param {boolean} redraw Whether to redraw immediately
   * @param {boolean} callCallback Whether to call subchart.onbrush
   * @returns {Array|undefined} Applied domain range
   * @private
   */
  setCanvasSubchartDomain(domain, redraw = true, callCallback = false) {
    const $$ = this;
    const { config, scale, state } = $$;
    const nextDomain = normalizeCanvasSubchartDomain($$, domain);
    if (!config.subchart_show || !nextDomain || !$$.withinRange(nextDomain, $$.getZoomDomain("subX", true), $$.getZoomDomain("subX"))) {
      return void 0;
    }
    state.domain = nextDomain;
    scale.zoom = null;
    if (redraw) {
      $$.redraw({
        withTransition: false,
        withY: config.zoom_rescale,
        withSubchart: false,
        withEventRect: false,
        withDimension: false
      });
    }
    callCallback && config.subchart_onbrush.bind($$.api)(state.domain);
    return state.domain;
  },
  /**
   * Clear the canvas subchart brush selection and restore the full x domain.
   * @param {boolean} redraw Whether to redraw immediately
   * @param {boolean} callCallback Whether to call subchart.onbrush
   * @private
   */
  clearCanvasSubchartDomain(redraw = true, callCallback = false) {
    var _a;
    const $$ = this;
    const { axis, config, org, scale, state } = $$;
    if (!config.subchart_show) {
      return;
    }
    state.domain = void 0;
    scale.zoom = null;
    if ((_a = org.xDomain) == null ? void 0 : _a.length) {
      scale.x.domain(org.xDomain);
      axis.x.scale(scale.x);
    }
    if (redraw) {
      $$.redraw({
        withTransition: false,
        withUpdateXDomain: true,
        withUpdateOrgXDomain: false,
        withY: config.zoom_rescale,
        withSubchart: false,
        withEventRect: false,
        withDimension: false
      });
    }
    callCallback && config.subchart_onbrush.bind($$.api)(scale.x.orgDomain());
  },
  /**
   * Finish a pending canvas flow animation before accepting another flow mutation.
   * @private
   */
  flushCanvasFlow() {
    var _a, _b;
    const { state } = this;
    if (!state.canvasFlowFinish) {
      return;
    }
    state.canvasFlowFrame !== null && ((_b = (_a = win).cancelAnimationFrame) == null ? void 0 : _b.call(_a, state.canvasFlowFrame));
    state.canvasFlowFrame = null;
    state.canvasFlowFinish();
  },
  /**
   * Animate canvas flow by interpolating the x domain, then commit the final data window.
   * @param {object} flow Flow metadata
   * @returns {boolean} Whether animation was started
   * @private
   */
  animateCanvasFlow(flow) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
    const $$ = this;
    const { axis, data, org, scale, state } = $$;
    const { done = () => {
    }, duration, length, orgDataCount } = flow;
    const requestFrame = (_a = win.requestAnimationFrame) == null ? void 0 : _a.bind(win);
    const isLog = !!((_b = axis.isLog) == null ? void 0 : _b.call(axis, "x"));
    if (!requestFrame || !duration || !length || !orgDataCount || getCanvasFlowValueCount($$) > CANVAS_FLOW_ANIMATION_MAX_VALUES) {
      return false;
    }
    const startDomain = scale.x.domain().slice(0, 2);
    const startOrgDomain = (_d = (_c = org.xDomain) == null ? void 0 : _c.slice) == null ? void 0 : _d.call(_c);
    const startSubXDomain = (_h = (_f = (_e = scale.subX) == null ? void 0 : _e.domain) == null ? void 0 : (_g = _f.call(_e)).slice) == null ? void 0 : _h.call(_g);
    if (!isCanvasFlowDomain(startDomain, isLog)) {
      return false;
    }
    const removed = data.targets.map((target) => target.values.splice(0, length));
    $$.updateXDomain($$.filterTargetsToShow(data.targets), true, true);
    const endDomain = scale.x.domain().slice(0, 2);
    const endOrgDomain = (_j = (_i = org.xDomain) == null ? void 0 : _i.slice) == null ? void 0 : _j.call(_i);
    data.targets.forEach((target, index) => {
      target.values.unshift(...removed[index]);
    });
    if (!isCanvasFlowDomain(endDomain, isLog)) {
      startOrgDomain && (org.xDomain = startOrgDomain);
      scale.x.domain(startDomain);
      startSubXDomain && scale.subX.domain(startSubXDomain);
      axis.x.scale(scale.x);
      return false;
    }
    syncCanvasFlowYDomains($$);
    let finished = false;
    const started = getCanvasAnimationTime();
    const finish = () => {
      var _a2, _b2;
      if (finished) {
        return;
      }
      finished = true;
      data.targets.forEach((target) => {
        target.values.splice(0, length);
      });
      endOrgDomain && (org.xDomain = endOrgDomain);
      scale.x.domain(endDomain);
      (_b2 = (_a2 = scale.subX) == null ? void 0 : _a2.domain) == null ? void 0 : _b2.call(_a2, endOrgDomain != null ? endOrgDomain : endDomain);
      axis.x.scale(scale.x);
      state.dirty.data = true;
      state._eventRectFingerprint = null;
      state.canvasShape = null;
      state._cachedDrawShape = null;
      $$.redraw({
        withLegend: true,
        withTransition: false,
        withTrimXDomain: false,
        withUpdateOrgXDomain: true,
        withUpdateXAxis: true,
        withUpdateXDomain: true
      });
      $$.updateTypesElements();
      state.canvasFlowFrame = null;
      state.canvasFlowFinish = null;
      state.flowing = false;
      done.call($$.api);
    };
    const render = (timestamp) => {
      const ratio = Math.min(1, Math.max(0, (timestamp - started) / duration));
      const domain = interpolateCanvasFlowDomain(startDomain, endDomain, ratio, isLog);
      scale.x.domain(domain);
      axis.x.scale(scale.x);
      state.canvasShape = null;
      state._cachedDrawShape = null;
      state._canvasVisibleRangeCache = null;
      state._canvasXTickValuesCache = null;
      $$.renderCanvasFrame(void 0, null, false);
      if (ratio < 1) {
        state.canvasFlowFrame = requestFrame(render);
      } else {
        finish();
      }
    };
    startOrgDomain && (org.xDomain = startOrgDomain);
    scale.x.domain(startDomain);
    startSubXDomain && scale.subX.domain(startSubXDomain);
    axis.x.scale(scale.x);
    state.flowing = true;
    state.cancelClick = true;
    (_k = $$.hideTooltip) == null ? void 0 : _k.call($$);
    state.canvasFlowFinish = finish;
    state.canvasFlowFrame = requestFrame(render);
    return true;
  },
  /**
   * Initialize canvas renderers, theme, hit detector and event bindings.
   * @private
   */
  initCanvas() {
    var _a;
    const $$ = this;
    const { config, state, $el } = $$;
    const container = $el.chart.node();
    state.isCanvasMode = true;
    state.canvasInlineStyle.minHeight = container.style.minHeight;
    if (win.getComputedStyle(container).position === "static") {
      $el.chart.style("position", "relative");
    }
    $el.chart.style("min-height", `${state.current.height}px`);
    $$.canvasEngine = new CanvasEngine();
    $$.canvasEngine.init(container, state.current.width, $$.getCanvasSurfaceHeight());
    $el.canvas = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)($$.canvasEngine.canvas);
    $$.canvasTheme = new CanvasTheme();
    $$.canvasTheme.load(container, config.canvas_theme);
    $$.canvasAxisRenderer = new CanvasAxisRenderer($$.canvasEngine, $$.canvasTheme);
    $$.canvasRenderer = new CanvasRenderer($$.canvasEngine, $$.canvasTheme);
    $$.hitDetector = new HitDetector();
    $$.bindCanvasEvents();
    config.zoom_enabled && ((_a = $$.bindZoomEvent) == null ? void 0 : _a.call($$));
  },
  /**
   * Warn about options that canvas mode does not support yet.
   * @private
   */
  warnUnsupportedCanvasOptions() {
    var _a, _b, _c, _d;
    const { config } = this;
    const unsupported = [
      [
        !isSupportedCanvasXType(config.axis_x_type),
        "axis.x.type other than indexed/category/log/timeseries"
      ],
      [
        !isSupportedCanvasYType(config.axis_y_type),
        "axis.y.type other than indexed/log/timeseries"
      ],
      [
        !isSupportedCanvasYType(config.axis_y2_type),
        "axis.y2.type other than indexed/log/timeseries"
      ],
      [config.boost_useCssRule, "boost.useCssRule"],
      [(_a = this.hasArcType) == null ? void 0 : _a.call(this), "arc charts"],
      [(_b = this.hasType) == null ? void 0 : _b.call(this, "radar"), "radar chart"],
      [(_c = this.hasType) == null ? void 0 : _c.call(this, "polar"), "polar chart"],
      [(_d = this.hasType) == null ? void 0 : _d.call(this, "funnel"), "funnel chart"]
    ];
    unsupported.forEach(([condition, name]) => {
      condition && warn(`canvas mode: ${name} is not yet supported.`);
    });
  },
  /**
   * Bind pointer and click handlers to the canvas surface.
   * @private
   */
  bindCanvasEvents() {
    const $$ = this;
    const { config, state, $el } = $$;
    const canvas2 = $el.canvas.node();
    const preventTouchEvent = getCanvasTouchPreventer(config);
    const touchOption = getCanvasTouchListenerOption(config);
    canvas2.addEventListener("mousemove", $$.onCanvasMouseMove.bind($$));
    canvas2.addEventListener("mouseenter", (event) => {
      var _a;
      state.event = event;
      (_a = config.onover) == null ? void 0 : _a.bind($$.api)(event);
    });
    canvas2.addEventListener("mouseout", $$.onCanvasMouseOut.bind($$));
    canvas2.addEventListener("mouseleave", (event) => {
      var _a;
      state.event = event;
      (_a = config.onout) == null ? void 0 : _a.bind($$.api)(event);
    });
    canvas2.addEventListener("mousedown", (event) => {
      var _a;
      if ((_a = $$.onCanvasSubchartBrushStart) == null ? void 0 : _a.call($$, event)) {
        return;
      }
      $$.onCanvasSelectionDragStart(event);
    });
    canvas2.addEventListener("click", $$.onCanvasClick.bind($$));
    canvas2.addEventListener("pointerdown", $$.onCanvasPointerDown.bind($$));
    canvas2.addEventListener("pointerenter", $$.onCanvasPointerEnter.bind($$));
    canvas2.addEventListener("pointermove", $$.onCanvasPointerMove.bind($$));
    canvas2.addEventListener("pointerup", $$.onCanvasPointerUp.bind($$));
    canvas2.addEventListener("pointerleave", $$.onCanvasPointerOut.bind($$));
    canvas2.addEventListener("pointercancel", $$.onCanvasPointerCancel.bind($$));
    if (isCanvasTouchEnabled(config)) {
      canvas2.addEventListener("touchstart", (event) => {
        preventTouchEvent(event);
        $$.onCanvasTouchStart(event);
      }, touchOption);
      canvas2.addEventListener("touchmove", (event) => {
        preventTouchEvent(event);
        $$.onCanvasTouchMove(event);
      }, touchOption);
      canvas2.addEventListener("touchend", $$.onCanvasTouchEnd.bind($$), touchOption);
      canvas2.addEventListener("touchcancel", $$.onCanvasTouchCancel.bind($$), touchOption);
    }
  },
  /**
   * Render and update the HTML legend used by canvas mode.
   * @private
   */
  updateHtmlLegend() {
    var _a, _b;
    const $$ = this;
    const { config, state, $el } = $$;
    const chart = $el.chart.node();
    if (!config.legend_show || state.hasTreemap) {
      if (state.hasTreemap) {
        (_a = $el.legend) == null ? void 0 : _a.remove();
        $el.legend = null;
      } else {
        (_b = $el.legend) == null ? void 0 : _b.style("visibility", "hidden");
      }
      state.legendItemWidth = 0;
      state.legendItemHeight = 0;
      state.legendStep = 0;
      return;
    }
    const targetIds = $$.mapToIds($$.data.targets).filter((id) => config.data_names[id] !== null);
    if (config.legend_contents_bindto && config.legend_contents_template) {
      if ($$.updateHtmlLegendTemplate(targetIds)) {
        state.legendItemWidth = 0;
        state.legendItemHeight = 0;
        state.legendStep = 0;
        state.legendHasRendered = true;
      } else {
        state.legendItemWidth = 0;
        state.legendItemHeight = 0;
        state.legendStep = 0;
      }
      return;
    }
    if (!$el.legend) {
      $el.legend = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(chart).append("div").classed($LEGEND.legend, true).classed($CANVAS.legend, true);
    }
    $el.legend.style("visibility", null);
    const legendItems = $el.legend.selectAll(`button.${$LEGEND.legendItem}`).data(targetIds, (id) => id);
    legendItems.exit().remove();
    const enter = legendItems.enter().append("button").attr("type", "button").attr("data-id", (id) => id);
    enter.append("span").classed($LEGEND.legendItemTile, true);
    enter.append("span").classed($CANVAS.legendItemTitle, true);
    const item = enter.merge(legendItems).attr("class", (id) => $$.generateClass($LEGEND.legendItem, id).trim());
    setCanvasHtmlLegendItem($$, item);
    item.select(`.${$LEGEND.legendItemTile}`).classed(
      $CANVAS.legendItemTileCircle,
      !config.legend_usePoint && config.legend_item_tile_type === "circle"
    ).style("background-color", (id) => config.legend_usePoint ? null : $$.color(id)).html((id) => config.legend_usePoint ? getCanvasLegendPointIcon($$, id) : "");
    item.select(`.${$CANVAS.legendItemTitle}`).text((id) => getLegendText($$, id));
    if (config.legend_tooltip) {
      item.attr("title", (id) => getLegendText($$, id));
    }
    bindCanvasHtmlLegendInteractions($$, item);
    $$.updateHtmlLegendSize(targetIds);
    $$.positionHtmlLegend();
    state.legendHasRendered = true;
  },
  /**
   * Render canvas mode legend into custom HTML template container.
   * @param {Array} targetIds Legend target ids
   * @returns {boolean} Whether template legend was rendered
   * @private
   */
  updateHtmlLegendTemplate(targetIds) {
    const $$ = this;
    const { api, config, $el } = $$;
    const wrapper = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(config.legend_contents_bindto);
    const template = config.legend_contents_template;
    const ids = [];
    let html = "";
    if (wrapper.empty()) {
      return false;
    }
    targetIds.forEach((id) => {
      const content = isFunction(template) ? sanitize(template.call(api, id, $$.color(id), api.data(id)[0].values)) : tplProcess(template, {
        COLOR: $$.color(id),
        TITLE: id
      });
      if (content) {
        ids.push(id);
        html += content;
      }
    });
    const legendItem = wrapper.html(html).classed($LEGEND.legend, true).classed($CANVAS.legend, false).style("visibility", null).selectAll(function() {
      return this.children;
    }).data(ids);
    setCanvasHtmlLegendItem($$, legendItem);
    bindCanvasHtmlLegendInteractions($$, legendItem);
    $el.legend = wrapper;
    return true;
  },
  /**
   * Measure HTML legend items and update legend layout state.
   * @param {Array} targetIds Visible legend target ids
   * @private
   */
  updateHtmlLegendSize(targetIds) {
    const $$ = this;
    const { config, state, $el } = $$;
    const itemSizes = [];
    const itemLayouts = {};
    let maxWidth = 0;
    let maxHeight = 0;
    let legendStep = 0;
    const useTemplateLegend = config.legend_contents_bindto && config.legend_contents_template;
    if (useTemplateLegend) {
      $el.legend.selectAll(`.${$LEGEND.legendItem}`).each(function(id) {
        const rect = getBoundingRect(this, true);
        const text = `${getLegendText($$, id)}`;
        const fallbackWidth = Math.max(32, text.length * 7 + 24);
        const fallbackHeight = 20;
        const width = Math.ceil(rect.width || fallbackWidth);
        const height = Math.ceil(rect.height || fallbackHeight);
        itemSizes.push(width);
        maxWidth = Math.max(maxWidth, width);
        maxHeight = Math.max(maxHeight, height);
      });
    } else if (targetIds.length) {
      const isRightOrInset = state.isLegendRight || state.isLegendInset;
      const isRectangle = config.legend_item_tile_type !== "circle";
      const itemTileSize = {
        width: isRectangle ? config.legend_item_tile_width : config.legend_item_tile_r * 2,
        height: isRectangle ? config.legend_item_tile_height : config.legend_item_tile_r * 2
      };
      const dimension = {
        padding: {
          top: 4,
          right: 10
        },
        max: {
          width: 0,
          height: 0
        },
        posMin: 10,
        step: 0,
        tileWidth: itemTileSize.width + 5,
        totalLength: 0
      };
      const sizes = {
        offsets: {},
        widths: {},
        heights: {},
        margins: [0],
        steps: {}
      };
      const measured = targetIds.map((id, index) => {
        const text = `${getLegendText($$, id)}`;
        const rect = measureSvgLegendText($$, text);
        const fallbackWidth = Math.max(32, text.length * 7);
        const fallbackHeight = 12;
        const isLast = index === targetIds.length - 1;
        const hidden = config.legend_show && !$$.isLegendToShow(id);
        const width = hidden ? 0 : ((rect == null ? void 0 : rect.width) || fallbackWidth) + dimension.tileWidth + (isLast && !isRightOrInset ? 0 : dimension.padding.right) + config.legend_padding;
        const height = hidden ? 0 : ((rect == null ? void 0 : rect.height) || fallbackHeight) + dimension.padding.top;
        dimension.max.width = Math.max(dimension.max.width, width);
        dimension.max.height = Math.max(dimension.max.height, height);
        return {
          id,
          hidden,
          width,
          height
        };
      });
      const areaLength = isRightOrInset ? $$.getLegendHeight() : $$.getLegendWidth();
      const updateValues = (id, itemLength, withoutStep = false) => {
        let margin;
        if (!withoutStep) {
          margin = (areaLength - dimension.totalLength - itemLength) / 2;
          if (margin < dimension.posMin) {
            margin = (areaLength - itemLength) / 2;
            dimension.totalLength = 0;
            dimension.step++;
          }
        }
        sizes.steps[id] = dimension.step;
        sizes.margins[dimension.step] = state.isLegendInset ? 10 : margin;
        sizes.offsets[id] = dimension.totalLength;
        dimension.totalLength += itemLength;
      };
      if (state.isLegendInset) {
        dimension.step = config.legend_inset_step ? config.legend_inset_step : targetIds.length;
        state.legendStep = dimension.step;
      }
      measured.forEach(({ id, hidden, width, height }) => {
        const itemWidth = config.legend_equally && !hidden ? dimension.max.width : width;
        const itemHeight = config.legend_equally && !hidden ? dimension.max.height : height;
        const itemLength = isRightOrInset ? itemHeight : itemWidth;
        sizes.widths[id] = itemWidth;
        sizes.heights[id] = itemHeight;
        itemSizes.push(itemWidth);
        maxWidth = Math.max(maxWidth, itemWidth);
        maxHeight = Math.max(maxHeight, itemHeight);
        if (hidden) {
          sizes.steps[id] = 0;
          sizes.offsets[id] = 0;
          return;
        }
        updateValues(id, itemLength);
      });
      const xForLegend = state.isLegendRight ? (id) => dimension.max.width * sizes.steps[id] : state.isLegendInset ? (id) => dimension.max.width * sizes.steps[id] + 10 : (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
      const yForLegend = state.isLegendRight || state.isLegendInset ? (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id] : (id) => dimension.max.height * sizes.steps[id];
      const titleX = 4 + itemTileSize.width;
      const tileCenterY = 9;
      measured.forEach(({ id, hidden }) => {
        const x = hidden ? 0 : xForLegend(id);
        const y = hidden ? 0 : yForLegend(id);
        itemLayouts[id] = {
          item: {
            x,
            y: y - 5,
            width: sizes.widths[id],
            height: sizes.heights[id]
          },
          title: {
            x: titleX,
            y: 0,
            height: sizes.heights[id]
          },
          tile: {
            x: -2,
            y: tileCenterY - itemTileSize.height / 2,
            width: itemTileSize.width,
            height: itemTileSize.height
          }
        };
      });
      legendStep = dimension.step;
    }
    if (!targetIds.length) {
      state.legendItemWidth = 0;
      state.legendItemHeight = 0;
      state.legendStep = 0;
      return;
    }
    if (useTemplateLegend) {
      const availableWidth = Math.max(1, state.current.width);
      const rowGap = 10;
      let rows = 1;
      let rowWidth = 0;
      itemSizes.forEach((width) => {
        if (rowWidth && rowWidth + rowGap + width > availableWidth) {
          rows++;
          rowWidth = width;
        } else {
          rowWidth += (rowWidth ? rowGap : 0) + width;
        }
      });
      state.legendStep = Math.max(0, rows - 1);
    } else {
      state.legendStep = legendStep;
    }
    state.legendItemWidth = maxWidth;
    state.legendItemHeight = Math.max(12, maxHeight);
    if (!useTemplateLegend) {
      $el.legend.selectAll(`button.${$LEGEND.legendItem}`).each(function(id) {
        const layout = itemLayouts[id];
        const item = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        if (!layout) {
          return;
        }
        item.style("left", `${layout.item.x}px`).style("top", `${layout.item.y}px`).style("width", `${layout.item.width}px`).style("height", `${layout.item.height}px`);
        item.select(`.${$CANVAS.legendItemTitle}`).style("left", `${layout.title.x}px`).style("top", `${layout.title.y}px`).style("height", `${layout.title.height}px`).style("line-height", `${layout.title.height}px`);
        item.select(`.${$LEGEND.legendItemTile}`).style("left", `${layout.tile.x}px`).style("top", `${layout.tile.y}px`).style("width", `${layout.tile.width}px`).style("height", `${layout.tile.height}px`);
      });
    }
  },
  /**
   * Get bottom legend block height separated from the canvas drawing surface.
   * @returns {number} Legend block height
   * @private
   */
  getCanvasBottomLegendHeight() {
    var _a;
    const $$ = this;
    const { config, state, $el } = $$;
    if (!config.legend_show || state.isLegendRight || state.isLegendInset || state.hasTreemap || !$el.legend || !state.legendItemHeight) {
      return 0;
    }
    const rectHeight = getBoundingRect($el.legend.node(), true).height;
    const rowHeight = state.legendItemHeight * (state.legendStep + 1);
    return Math.ceil(Math.max(((_a = $$.getLegendHeight) == null ? void 0 : _a.call($$)) || 0, rectHeight || rowHeight));
  },
  /**
   * Get canvas drawing surface height excluding separately rendered bottom legend DOM.
   * @returns {number} Canvas drawing surface height
   * @private
   */
  getCanvasSurfaceHeight() {
    const $$ = this;
    return Math.max(0, $$.state.current.height - $$.getCanvasBottomLegendHeight());
  },
  /**
   * Position the HTML legend around or inside the canvas chart.
   * @private
   */
  positionHtmlLegend() {
    var _a;
    const $$ = this;
    const { config, state, $el } = $$;
    const legend = $el.legend;
    legend.classed($CANVAS.legendBottom, !state.isLegendRight && !state.isLegendInset).classed($CANVAS.legendRight, state.isLegendRight).classed($CANVAS.legendInset, state.isLegendInset).style("top", null).style("right", null).style("bottom", null).style("left", null).style("width", null).style("height", null).style("min-height", null);
    if (state.isLegendRight) {
      legend.style("top", `${state.margin3.top}px`).style("right", "0").style("bottom", `${state.margin3.bottom}px`).style("width", `${Math.max(0, $$.getLegendWidth())}px`);
    } else if (!state.isLegendInset) {
      const legendHeight = ((_a = $$.getLegendHeight) == null ? void 0 : _a.call($$)) || 0;
      legend.style("top", `${Math.max(0, state.current.height - legendHeight)}px`).style("right", "0").style("bottom", "auto").style("left", "0");
    } else if (state.isLegendInset) {
      const isTop = state.isLegendTop;
      const isLeft = state.isLegendLeft;
      legend.style(isTop ? "top" : "bottom", `${config.legend_inset_y}px`).style(isLeft ? "left" : "right", `${config.legend_inset_x}px`).style(
        "width",
        `${Math.max(0, state.legendItemWidth * (state.legendStep + 1) + 20)}px`
      );
    }
  },
  /**
   * Get selected canvas data rows.
   * @param {string} targetId Target id
   * @returns {Array} Selected rows
   * @private
   */
  getCanvasSelectedData(targetId) {
    const $$ = this;
    const selected = $$.state.canvasSelection;
    const data = [];
    if (!$$.config.data_selection_enabled || !(selected == null ? void 0 : selected.size)) {
      return data;
    }
    eachCanvasSelectableData($$, (d) => {
      (!targetId || d.id === targetId) && selected.has(getCanvasDataKey(d)) && data.push(d);
    });
    return data;
  },
  /**
   * Select or unselect canvas data rows.
   * @param {boolean} isSelection Whether to select
   * @param {string|Array} ids Target ids
   * @param {Array} indices Target indices
   * @param {boolean} resetOther Whether to reset unrelated selections
   * @private
   */
  setCanvasSelection(isSelection = false, ids, indices, resetOther) {
    var _a;
    const $$ = this;
    const { config, state } = $$;
    const selected = state.canvasSelection;
    const selectionGrouped = config.data_selection_grouped;
    let targetIds = getCanvasSelectionIds(ids);
    let changed = false;
    const singleSelection = isSelection && !config.data_selection_multiple;
    let resetDone = !singleSelection;
    if (!config.data_selection_enabled) {
      return;
    }
    if (singleSelection) {
      indices = (indices == null ? void 0 : indices.length) ? [indices[0]] : [0];
      if (!selectionGrouped) {
        if (targetIds) {
          targetIds = targetIds.slice(0, 1);
        } else {
          const [firstTarget] = $$.filterTargetsToShow($$.data.targets);
          targetIds = firstTarget ? [firstTarget.id] : [];
        }
      }
    }
    eachCanvasSelectableData($$, (d) => {
      const key = getCanvasDataKey(d);
      const isTargetId = selectionGrouped || !targetIds || targetIds.indexOf(d.id) >= 0;
      const isTargetIndex = !indices || indices.indexOf(d.index) >= 0;
      const isSelected = selected.has(key);
      if (isSelection) {
        if (isTargetId && isTargetIndex && (!isSelected || singleSelection)) {
          if (!resetDone) {
            $$.setCanvasSelection(false);
            resetDone = true;
          }
          if (selected.has(key)) {
            return;
          }
          selected.add(key);
          callFn(config.data_onselected, $$.api, d, $$.canvasEngine.canvas);
          changed = true;
        } else if ((!singleSelection || resetDone) && resetOther && isSelected) {
          selected.delete(key);
          callFn(config.data_onunselected, $$.api, d, $$.canvasEngine.canvas);
          changed = true;
        }
      } else if (isTargetId && isTargetIndex && isSelected) {
        selected.delete(key);
        callFn(config.data_onunselected, $$.api, d, $$.canvasEngine.canvas);
        changed = true;
      }
    });
    changed && ((_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false));
  },
  /**
   * Toggle canvas data selection from a click.
   * @param {Array} dataRows Data rows to toggle
   * @private
   */
  toggleCanvasSelection(dataRows) {
    var _a;
    const $$ = this;
    const { config, state } = $$;
    const selected = state.canvasSelection;
    let changed = false;
    if (!config.data_selection_enabled) {
      return;
    }
    dataRows.filter((d) => isCanvasSelectableData($$, d)).forEach((d) => {
      const key = getCanvasDataKey(d);
      const isSelected = selected.has(key);
      if (!config.data_selection_multiple) {
        eachCanvasSelectableData($$, (selectedData) => {
          const selectedKey = getCanvasDataKey(selectedData);
          const shouldReset = config.data_selection_grouped ? selectedData.id === d.id : selectedKey !== key;
          if (shouldReset && selected.has(selectedKey)) {
            selected.delete(selectedKey);
            callFn(
              config.data_onunselected,
              $$.api,
              selectedData,
              $$.canvasEngine.canvas
            );
            changed = true;
          }
        });
      }
      if (isSelected && selected.has(key)) {
        selected.delete(key);
        callFn(config.data_onunselected, $$.api, d, $$.canvasEngine.canvas);
      } else {
        selected.add(key);
        callFn(config.data_onselected, $$.api, d, $$.canvasEngine.canvas);
      }
      changed = true;
    });
    changed && ((_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false));
  },
  /**
   * Check whether canvas draggable selection can start.
   * @param {MouseEvent|TouchEvent} event Input event
   * @returns {boolean} Whether drag selection can start
   * @private
   */
  canStartCanvasSelectionDrag(event) {
    const $$ = this;
    const { config } = $$;
    const mouse = event;
    return Boolean(
      config.interaction_enabled && config.data_selection_enabled && config.data_selection_draggable && config.data_selection_multiple && !config.zoom_enabled && (mouse.button === void 0 || mouse.button === 0)
    );
  },
  /**
   * Get the selected data rows inside the current canvas drag rectangle.
   * @param {object} rect Canvas rectangle
   * @returns {Array} Included rows
   * @private
   */
  getCanvasSelectionDragData(rect) {
    const $$ = this;
    const { config } = $$;
    const data = $$.hitDetector.findInRect(rect, config.data_selection_grouped);
    if (!config.data_selection_grouped) {
      return data;
    }
    const indices = new Set(data.map((d) => d.index));
    return $$.filterTargetsToShow($$.data.targets).flatMap((target) => target.values.filter((d) => indices.has(d.index)));
  },
  /**
   * Start canvas draggable selection.
   * @param {MouseEvent|TouchEvent} event Input event
   * @returns {boolean} Whether drag started
   * @private
   */
  startCanvasSelectionDrag(event) {
    var _a, _b;
    const $$ = this;
    const { state } = $$;
    const point = getCanvasEventPoint($$, event);
    if (!point || !$$.canStartCanvasSelectionDrag(event)) {
      return false;
    }
    state.dragStart = point;
    state.canvasSelectionDragStart = point;
    state.canvasSelectionDragIncluded = /* @__PURE__ */ new Set();
    state.canvasSelectionDragging = true;
    state.canvasSelectionDragMoved = false;
    canvasSelectionDragRows.set($$, /* @__PURE__ */ new Map());
    $$.setDragStatus(true);
    (_a = $$.hideTooltip) == null ? void 0 : _a.call($$);
    (_b = event.preventDefault) == null ? void 0 : _b.call(event);
    return true;
  },
  /**
   * Update canvas draggable selection.
   * @param {MouseEvent|TouchEvent} event Input event
   * @returns {boolean} Whether drag was handled
   * @private
   */
  updateCanvasSelectionDrag(event) {
    var _a;
    const $$ = this;
    const { config, state } = $$;
    const start = state.canvasSelectionDragStart;
    const point = getCanvasEventPoint($$, event);
    if (!state.canvasSelectionDragging || !start || !point) {
      return false;
    }
    const [sx, sy] = start;
    const [mx, my] = point;
    const minX = Math.min(sx, mx);
    const maxX = Math.max(sx, mx);
    const minY = config.data_selection_grouped ? state.margin.top : Math.min(sy, my);
    const maxY = config.data_selection_grouped ? state.margin.top + state.height : Math.max(sy, my);
    const rect = {
      x: minX,
      y: minY,
      w: maxX - minX,
      h: maxY - minY
    };
    const moved = Math.abs(mx - sx) > 4 || Math.abs(my - sy) > 4;
    state.canvasSelectionDragMoved = state.canvasSelectionDragMoved || moved;
    if (moved) {
      const { included, rows } = getCanvasSelectionDragDelta(
        $$,
        $$.getCanvasSelectionDragData(rect)
      );
      rows.length && $$.toggleCanvasSelection(rows);
      state.canvasSelectionDragIncluded = included;
      state.cancelClick = true;
    }
    $$.renderCanvasSelectionDrag(rect);
    (_a = event.preventDefault) == null ? void 0 : _a.call(event);
    return true;
  },
  /**
   * End canvas draggable selection.
   * @param {MouseEvent|TouchEvent} event Input event
   * @returns {boolean} Whether drag ended
   * @private
   */
  endCanvasSelectionDrag(event) {
    var _a;
    const $$ = this;
    const { state } = $$;
    if (!state.canvasSelectionDragging) {
      return false;
    }
    $$.updateCanvasSelectionDrag(event);
    state.cancelClick = state.cancelClick || state.canvasSelectionDragMoved;
    state.dragStart = null;
    state.canvasSelectionDragStart = null;
    state.canvasSelectionDragIncluded = /* @__PURE__ */ new Set();
    state.canvasSelectionDragging = false;
    state.canvasSelectionDragMoved = false;
    canvasSelectionDragRows.delete($$);
    $$.setDragStatus(false);
    $$.clearCanvasFocus();
    (_a = event.preventDefault) == null ? void 0 : _a.call(event);
    return true;
  },
  /**
   * Dispatch canvas data.onout callback for the current hovered row.
   * @param {HTMLCanvasElement} canvas Canvas element
   * @private
   */
  dispatchCanvasDataOut(canvas2) {
    const $$ = this;
    const { config, state } = $$;
    const d = state.canvasDataHover;
    if (!d) {
      return;
    }
    state.canvasDataHover = null;
    state.canvasDataHoverKey = null;
    config.interaction_enabled && callFn(config.data_onout, $$.api, d, canvas2);
  },
  /**
   * Dispatch canvas data.onover callback when the hovered row changes.
   * @param {object} d Data row
   * @param {HTMLCanvasElement} canvas Canvas element
   * @private
   */
  dispatchCanvasDataOver(d, canvas2) {
    const $$ = this;
    const { config, state } = $$;
    const key = getCanvasDataKey(d);
    if (state.canvasDataHoverKey === key) {
      return;
    }
    $$.dispatchCanvasDataOut(canvas2);
    state.canvasDataHover = d;
    state.canvasDataHoverKey = key;
    config.interaction_enabled && d && callFn(config.data_onover, $$.api, d, canvas2);
  },
  /**
   * Dispatch canvas data.onclick callback for a pointer position.
   * @param {Event} event Input event
   * @param {boolean} markInputClick Whether to suppress following compatibility click
   * @returns {object|null} Clicked data row
   * @private
   */
  dispatchCanvasDataClick(event, markInputClick = false) {
    var _a;
    const $$ = this;
    const { config, $el } = $$;
    const canvas2 = $el.canvas.node();
    const d = getCanvasEventDatum($$, event, true);
    if (!d || isDuplicateCanvasInputClick($$, d)) {
      return d;
    }
    if (config.interaction_enabled) {
      const dataRows = config.data_selection_grouped ? $$.filterTargetsToShow($$.data.targets).map((target) => target.values[d.index]).filter(Boolean) : [d];
      (_a = $$.toggleCanvasSelection) == null ? void 0 : _a.call($$, dataRows);
      dataRows.forEach((row) => callFn(config.data_onclick, $$.api, row, canvas2));
      markInputClick && markCanvasInputClick($$, d);
    }
    return d;
  },
  /**
   * Update canvas subchart brush domain from an input event.
   * @param {Event} event Input event
   * @returns {boolean} Whether the brush was updated
   * @private
   */
  updateCanvasSubchartBrush(event) {
    var _a, _b;
    const $$ = this;
    const { config, state } = $$;
    const start = state.canvasSubchartBrushStart;
    const origin = state.canvasSubchartBrushOrigin;
    const mode = state.canvasSubchartBrushMode;
    const coord = getCanvasSubchartBrushCoord($$, event, true);
    if (config.subchart_brush_enabled === false || !state.canvasSubchartBrushDragging || start === null || coord === null || !mode) {
      return false;
    }
    const delta = coord - start;
    if (Math.abs(delta) > CANVAS_SUBCHART_CLICK_TOLERANCE) {
      state.canvasSubchartBrushMoved = true;
    }
    if (!state.canvasSubchartBrushMoved) {
      (_a = event.preventDefault) == null ? void 0 : _a.call(event);
      return true;
    }
    let selection;
    if (mode === "move" && origin) {
      const [extentStart, extentEnd] = getCanvasSubchartBrushExtent($$);
      const size = origin[1] - origin[0];
      let nextStart = origin[0] + delta;
      let nextEnd = origin[1] + delta;
      if (nextStart < extentStart) {
        nextEnd += extentStart - nextStart;
        nextStart = extentStart;
      }
      if (nextEnd > extentEnd) {
        nextStart -= nextEnd - extentEnd;
        nextEnd = extentEnd;
      }
      selection = [
        Math.max(extentStart, Math.min(extentEnd - size, nextStart)),
        Math.min(extentEnd, Math.max(extentStart + size, nextEnd))
      ];
    } else if (mode === "resize-start" && origin) {
      selection = clampCanvasSubchartSelection($$, coord, origin[1]);
    } else if (mode === "resize-end" && origin) {
      selection = clampCanvasSubchartSelection($$, origin[0], coord);
    } else {
      selection = clampCanvasSubchartSelection($$, start, coord);
    }
    const domain = getCanvasSubchartDomainFromCoords($$, selection[0], selection[1]);
    $$.setCanvasSubchartDomain(domain, true);
    state.cancelClick = true;
    (_b = event.preventDefault) == null ? void 0 : _b.call(event);
    return true;
  },
  /**
   * Update cursor while hovering over the canvas subchart brush area.
   * @param {Event} event Input event
   * @returns {boolean} Whether the pointer is over the subchart
   * @private
   */
  updateCanvasSubchartCursor(event) {
    const $$ = this;
    const canvas2 = $$.$el.canvas.node();
    if ($$.config.subchart_brush_enabled === false) {
      canvas2.style.cursor = "";
      return false;
    }
    const coord = getCanvasSubchartBrushCoord($$, event);
    if (coord === null) {
      canvas2.style.cursor = "";
      return false;
    }
    const mode = getCanvasSubchartBrushMode($$, coord);
    canvas2.style.cursor = getCanvasSubchartCursor($$, mode);
    return true;
  },
  /**
   * Start a canvas subchart brush gesture.
   * @param {Event} event Mouse, pointer or touch event
   * @returns {boolean} Whether brushing started
   * @private
   */
  startCanvasSubchartBrush(event) {
    var _a;
    const $$ = this;
    const { state } = $$;
    if ($$.config.subchart_brush_enabled === false) {
      return false;
    }
    const coord = getCanvasSubchartBrushCoord($$, event);
    if (coord === null) {
      return false;
    }
    const mode = getCanvasSubchartBrushMode($$, coord);
    state.event = event;
    state.canvasSubchartBrushDragging = true;
    state.canvasSubchartBrushMode = mode;
    state.canvasSubchartBrushStart = coord;
    state.canvasSubchartBrushOrigin = getCanvasSubchartBrushSelection($$);
    state.canvasSubchartBrushMoved = false;
    state.cancelClick = true;
    $$.setDragStatus(true);
    (_a = event.preventDefault) == null ? void 0 : _a.call(event);
    return true;
  },
  /**
   * End a canvas subchart brush gesture.
   * @param {Event} event Mouse, pointer or touch event
   * @returns {boolean} Whether brushing ended
   * @private
   */
  endCanvasSubchartBrush(event) {
    var _a, _b, _c;
    const $$ = this;
    const { state } = $$;
    if (!state.canvasSubchartBrushDragging) {
      return false;
    }
    $$.updateCanvasSubchartBrush(event);
    const shouldClear = state.canvasSubchartBrushMode === "select" && !state.canvasSubchartBrushMoved;
    const shouldCallback = state.canvasSubchartBrushMoved || shouldClear;
    if (shouldClear) {
      (_a = $$.clearCanvasSubchartDomain) == null ? void 0 : _a.call($$, true, true);
    } else if (shouldCallback) {
      $$.config.subchart_onbrush.bind($$.api)((_b = state.domain) != null ? _b : $$.scale.x.orgDomain());
    }
    state.canvasSubchartBrushDragging = false;
    state.canvasSubchartBrushMode = null;
    state.canvasSubchartBrushStart = null;
    state.canvasSubchartBrushOrigin = null;
    state.canvasSubchartBrushMoved = false;
    $$.setDragStatus(false);
    (_c = event.preventDefault) == null ? void 0 : _c.call(event);
    return true;
  },
  /**
   * Cancel a canvas subchart brush gesture without applying callbacks.
   * @param {Event} event Mouse, pointer or touch event
   * @returns {boolean} Whether brushing was cancelled
   * @private
   */
  cancelCanvasSubchartBrush(event) {
    var _a;
    const $$ = this;
    const { state } = $$;
    if (!state.canvasSubchartBrushDragging) {
      return false;
    }
    state.canvasSubchartBrushDragging = false;
    state.canvasSubchartBrushMode = null;
    state.canvasSubchartBrushStart = null;
    state.canvasSubchartBrushOrigin = null;
    state.canvasSubchartBrushMoved = false;
    $$.setDragStatus(false);
    (_a = event.preventDefault) == null ? void 0 : _a.call(event);
    return true;
  },
  /**
   * Start mouse-driven canvas subchart brushing.
   * @param {MouseEvent} event Mouse event
   * @returns {boolean} Whether brushing started
   * @private
   */
  onCanvasSubchartBrushStart(event) {
    const $$ = this;
    if (!$$.startCanvasSubchartBrush(event)) {
      return false;
    }
    const move = (event2) => {
      $$.updateCanvasSubchartBrush(event2);
    };
    const end = (event2) => {
      $$.endCanvasSubchartBrush(event2);
      win.removeEventListener("mousemove", move);
      win.removeEventListener("mouseup", end);
    };
    win.addEventListener("mousemove", move);
    win.addEventListener("mouseup", end);
    return true;
  },
  /**
   * Handle canvas click and dispatch shape-level data onclick.
   * @param {MouseEvent} event Mouse click event
   * @private
   */
  onCanvasClick(event) {
    var _a;
    const $$ = this;
    const { config, state } = $$;
    state.event = event;
    if (state.flowing || state.cancelClick) {
      state.cancelClick = false;
      return;
    }
    $$.dispatchCanvasDataClick(event);
    (_a = config.onclick) == null ? void 0 : _a.bind($$.api)(event);
  },
  /**
   * Start mouse-driven canvas draggable selection.
   * @param {MouseEvent} event Mouse event
   * @private
   */
  onCanvasSelectionDragStart(event) {
    const $$ = this;
    const { state } = $$;
    if (!$$.startCanvasSelectionDrag(event)) {
      return;
    }
    const move = (event2) => {
      $$.updateCanvasSelectionDrag(event2);
    };
    const end = (event2) => {
      $$.endCanvasSelectionDrag(event2);
      win.removeEventListener("mousemove", move);
      win.removeEventListener("mouseup", end);
      state.canvasSelectionDragMoveHandler = null;
      state.canvasSelectionDragEndHandler = null;
    };
    state.canvasSelectionDragMoveHandler = move;
    state.canvasSelectionDragEndHandler = end;
    win.addEventListener("mousemove", move);
    win.addEventListener("mouseup", end);
  },
  /**
   * Start non-mouse pointer-driven canvas subchart brushing.
   * @param {PointerEvent} event Pointer event
   * @private
   */
  onCanvasPointerDown(event) {
    var _a;
    if (!shouldHandleCanvasPointerEvent(this, event)) {
      return;
    }
    const $$ = this;
    const canvas2 = $$.$el.canvas.node();
    if (!$$.startCanvasSubchartBrush(event)) {
      return;
    }
    const pointerId = event.pointerId;
    const matchesPointer = (event2) => event2.pointerId === pointerId;
    const move = (event2) => {
      matchesPointer(event2) && $$.updateCanvasSubchartBrush(event2);
    };
    const end = (event2) => {
      if (matchesPointer(event2)) {
        $$.endCanvasSubchartBrush(event2);
        cleanup();
      }
    };
    const cancel = (event2) => {
      if (matchesPointer(event2)) {
        $$.cancelCanvasSubchartBrush(event2);
        cleanup();
      }
    };
    function cleanup() {
      var _a2;
      win.removeEventListener("pointermove", move);
      win.removeEventListener("pointerup", end);
      win.removeEventListener("pointercancel", cancel);
      try {
        (_a2 = canvas2.releasePointerCapture) == null ? void 0 : _a2.call(canvas2, pointerId);
      } catch (e) {
      }
    }
    try {
      (_a = canvas2.setPointerCapture) == null ? void 0 : _a.call(canvas2, pointerId);
    } catch (e) {
    }
    win.addEventListener("pointermove", move);
    win.addEventListener("pointerup", end);
    win.addEventListener("pointercancel", cancel);
  },
  /**
   * Handle non-mouse pointer entering the canvas.
   * @param {PointerEvent} event Pointer event
   * @private
   */
  onCanvasPointerEnter(event) {
    var _a;
    if (!shouldHandleCanvasPointerEvent(this, event)) {
      return;
    }
    this.state.event = event;
    (_a = this.config.onover) == null ? void 0 : _a.bind(this.api)(event);
  },
  /**
   * Handle non-mouse pointer movement over the canvas.
   * @param {PointerEvent} event Pointer event
   * @private
   */
  onCanvasPointerMove(event) {
    if (!shouldHandleCanvasPointerEvent(this, event)) {
      return;
    }
    if (this.updateCanvasSubchartBrush(event)) {
      return;
    }
    this.onCanvasMouseMove(event);
  },
  /**
   * Handle non-mouse pointer click.
   * @param {PointerEvent} event Pointer event
   * @private
   */
  onCanvasPointerUp(event) {
    var _a;
    if (!shouldHandleCanvasPointerEvent(this, event)) {
      return;
    }
    this.state.event = event;
    if (this.endCanvasSubchartBrush(event)) {
      (_a = this.config.onout) == null ? void 0 : _a.bind(this.api)(event);
      return;
    }
    this.dispatchCanvasDataClick(event, true);
    this.dispatchCanvasDataOut(this.$el.canvas.node());
  },
  /**
   * Handle non-mouse pointer leaving the canvas.
   * @param {PointerEvent} event Pointer event
   * @private
   */
  onCanvasPointerOut(event) {
    var _a;
    if (!shouldHandleCanvasPointerEvent(this, event)) {
      return;
    }
    if (this.state.canvasSubchartBrushDragging) {
      return;
    }
    this.state.event = event;
    this.onCanvasMouseOut();
    (_a = this.config.onout) == null ? void 0 : _a.bind(this.api)(event);
  },
  /**
   * Handle non-mouse pointer cancellation.
   * @param {PointerEvent} event Pointer event
   * @private
   */
  onCanvasPointerCancel(event) {
    var _a;
    if (!shouldHandleCanvasPointerEvent(this, event)) {
      return;
    }
    this.state.event = event;
    if (this.cancelCanvasSubchartBrush(event)) {
      (_a = this.config.onout) == null ? void 0 : _a.bind(this.api)(event);
      return;
    }
    this.onCanvasPointerOut(event);
  },
  /**
   * Handle touch start over the canvas.
   * @param {TouchEvent} event Touch event
   * @private
   */
  onCanvasTouchStart(event) {
    var _a;
    if (event.touches.length > 1) {
      return;
    }
    this.state.event = event;
    if (this.startCanvasSubchartBrush(event)) {
      return;
    }
    if (this.startCanvasSelectionDrag(event)) {
      return;
    }
    (_a = this.config.onover) == null ? void 0 : _a.bind(this.api)(event);
    this.onCanvasMouseMove(event);
  },
  /**
   * Handle touch move over the canvas.
   * @param {TouchEvent} event Touch event
   * @private
   */
  onCanvasTouchMove(event) {
    if (event.touches.length > 1) {
      return;
    }
    if (this.updateCanvasSubchartBrush(event)) {
      return;
    }
    if (this.updateCanvasSelectionDrag(event)) {
      return;
    }
    this.onCanvasMouseMove(event);
  },
  /**
   * Handle touch end over the canvas.
   * @param {TouchEvent} event Touch event
   * @private
   */
  onCanvasTouchEnd(event) {
    var _a, _b, _c;
    this.state.event = event;
    if (this.endCanvasSubchartBrush(event)) {
      (_a = this.config.onout) == null ? void 0 : _a.bind(this.api)(event);
      return;
    }
    if (this.endCanvasSelectionDrag(event)) {
      (_b = this.config.onout) == null ? void 0 : _b.bind(this.api)(event);
      return;
    }
    this.dispatchCanvasDataClick(event, true);
    this.dispatchCanvasDataOut(this.$el.canvas.node());
    (_c = this.config.onout) == null ? void 0 : _c.bind(this.api)(event);
  },
  /**
   * Handle touch cancellation.
   * @param {TouchEvent} event Touch event
   * @private
   */
  onCanvasTouchCancel(event) {
    var _a;
    this.state.event = event;
    this.cancelCanvasSubchartBrush(event);
    this.endCanvasSelectionDrag(event);
    this.onCanvasMouseOut();
    (_a = this.config.onout) == null ? void 0 : _a.bind(this.api)(event);
  },
  /**
   * Update canvas focus state and tooltip on pointer movement.
   * @param {Event} event Mouse, pointer or touch move event
   * @private
   */
  onCanvasMouseMove(event) {
    var _a, _b, _c, _d, _e;
    const $$ = this;
    const { config, state, $el } = $$;
    const canvas2 = $el.canvas.node();
    state.event = event;
    if (state.flowing) {
      return;
    }
    if (state.canvasSelectionDragging) {
      return;
    }
    if ((_a = $$.updateCanvasSubchartCursor) == null ? void 0 : _a.call($$, event)) {
      $$.dispatchCanvasDataOut(canvas2);
      if (state.canvasFocusKey) {
        state.canvasFocusKey = null;
        $$.clearCanvasFocus();
      }
      (_b = $$.hideTooltip) == null ? void 0 : _b.call($$);
      return;
    }
    const rawPoint = getCanvasEventPoint($$, event);
    const point = rawPoint && (getCanvasMainPointFromSubchart($$, rawPoint) || rawPoint);
    const d = point ? getCanvasHoverDatumFromPoint($$, point) : null;
    if (!d) {
      $$.dispatchCanvasDataOut(canvas2);
      if (state.canvasFocusKey) {
        state.canvasFocusKey = null;
        $$.clearCanvasFocus();
      }
      if (rawPoint && config.axis_tooltip && isCanvasAxisTooltipArea($$, rawPoint)) {
        $$.renderCanvasAxisTooltip(rawPoint);
        (_c = $$.hideTooltip) == null ? void 0 : _c.call($$);
        return;
      }
      (_d = $$.hideTooltip) == null ? void 0 : _d.call($$);
      return;
    }
    $$.dispatchCanvasDataOver(d, canvas2);
    const selectedData = getCanvasTooltipData($$, d);
    const focusData = getCanvasFocusData($$, d, selectedData);
    const focusKey = focusData.map((v) => `${v.id}:${v.index}`).join("|");
    if (state.canvasFocusKey !== focusKey || config.axis_tooltip) {
      state.canvasFocusKey = focusKey;
      $$.renderCanvasFocus(focusData, point);
    }
    (_e = $$.showTooltip) == null ? void 0 : _e.call($$, selectedData, canvas2);
  },
  /**
   * Clear focus and tooltip state when the pointer leaves the canvas.
   * @private
   */
  onCanvasMouseOut() {
    var _a;
    const canvas2 = this.$el.canvas.node();
    canvas2.style.cursor = "";
    this.dispatchCanvasDataOut(canvas2);
    if (this.state.canvasFocusKey) {
      this.state.canvasFocusKey = null;
      this.clearCanvasFocus();
    } else if (this.config.axis_tooltip) {
      this.clearCanvasFocus();
    }
    (_a = this.hideTooltip) == null ? void 0 : _a.call(this);
  },
  /**
   * Show canvas tooltip from linked tooltip propagation.
   * @param {number} index Data index
   * @returns {boolean} Whether linked tooltip was shown
   * @private
   */
  showCanvasLinkedTooltip(index) {
    var _a, _b, _c, _d;
    const $$ = this;
    const { $el, state } = $$;
    const canvas2 = (_a = $el.canvas) == null ? void 0 : _a.node();
    const targetsToShow = $$.filterTargetsToShow($$.data.targets);
    const d = targetsToShow.map((target) => target.values[index]).find(Boolean);
    if (!canvas2 || !d) {
      (_b = $$.hideTooltip) == null ? void 0 : _b.call($$);
      return false;
    }
    const selectedData = getCanvasTooltipData($$, d);
    const focus = selectedData.find((v) => v && hasCanvasDrawableValue($$, v)) || selectedData[0];
    if (!selectedData.length || !focus) {
      (_c = $$.hideTooltip) == null ? void 0 : _c.call($$);
      return false;
    }
    const { left, top } = getBoundingRect(canvas2, true);
    const point = getRenderDataPoint($$, focus);
    const eventPoint = [
      state.margin.left + point.x,
      state.margin.top + point.y
    ];
    state.event = {
      clientX: left + eventPoint[0],
      clientY: top + eventPoint[1],
      currentTarget: canvas2,
      target: canvas2
    };
    state.canvasFocusKey = selectedData.map((v) => `${v.id}:${v.index}`).join("|");
    $$.renderCanvasFocus(selectedData, eventPoint);
    (_d = $$.showTooltip) == null ? void 0 : _d.call($$, selectedData, canvas2);
    return true;
  },
  /**
   * Draw drag-zoom brush overlay on the cached canvas frame.
   * @param {number} start Start coordinate
   * @param {number} end End coordinate
   * @private
   */
  renderCanvasZoomBrush(start, end) {
    const $$ = this;
    $$.canvasEngine.withOverlay((ctx) => {
      $$.canvasRenderer.withContext(ctx, () => {
        $$.canvasRenderer.drawZoomBrush($$, start, end);
      });
    });
  },
  /**
   * Clear drag-zoom brush overlay.
   * @private
   */
  clearCanvasZoomBrush() {
    this.canvasEngine.clearOverlay();
  },
  /**
   * Draw selection drag overlay on the cached canvas frame.
   * @param {object} rect Selection rectangle
   * @private
   */
  renderCanvasSelectionDrag(rect) {
    const $$ = this;
    $$.canvasEngine.withOverlay((ctx) => {
      $$.canvasRenderer.withContext(ctx, () => {
        $$.canvasRenderer.drawSelectionDragArea($$, rect);
      });
    });
  },
  /**
   * Draw a complete canvas frame and optionally rebuild hit indexes.
   * @param {object} shape Cached draw shape object
   * @param {Array} focusData Focused data rows
   * @param {boolean} rebuildHit Whether to rebuild hit indexes
   * @private
   */
  renderCanvasFrame(shape, focusData, rebuildHit = false) {
    const $$ = this;
    const { state } = $$;
    const drawShape = shape || state.canvasShape || $$.getDrawShape();
    state.canvasShape = drawShape;
    state._canvasVisibleRangeCache = null;
    state._canvasXTickValuesCache = null;
    $$.canvasEngine.beginFrame(state.current.width, $$.getCanvasSurfaceHeight());
    try {
      $$.canvasRenderer.drawBackground($$);
      $$.canvasAxisRenderer.drawTitle($$);
      state.hasAxis && $$.canvasAxisRenderer.draw($$);
      $$.canvasRenderer.draw($$, drawShape);
      state.hasAxis && $$.config.grid_lines_front && $$.canvasAxisRenderer.drawGridLines($$);
      $$.canvasRenderer.drawSubchart($$, drawShape);
      state.hasAxis && $$.canvasAxisRenderer.drawSubXAxis($$);
      state.hasAxis && $$.canvasAxisRenderer.drawSubYAxes($$);
      $$.canvasRenderer.drawEmptyLabel($$);
      rebuildHit && $$.hitDetector.rebuild($$, drawShape);
    } finally {
      $$.canvasEngine.endFrame();
    }
    $$.canvasEngine.clearOverlay();
    state.canvasFocusMainRedraw = false;
    focusData && $$.renderCanvasFocus(focusData);
  },
  /**
   * Restore the cached frame and draw focus overlays.
   * @param {Array} focusData Focused data rows
   * @param {Array} point Canvas-local pointer coordinate
   * @private
   */
  renderCanvasFocus(focusData, point) {
    var _a, _b;
    const $$ = this;
    const { state } = $$;
    const withMainRedraw = (_b = (_a = $$.canvasRenderer).hasExpandedShapeFocus) == null ? void 0 : _b.call(_a, $$, focusData);
    if (withMainRedraw) {
      const drawShape = state.canvasShape || $$.getDrawShape();
      $$.canvasEngine.beginFrame(state.current.width, $$.getCanvasSurfaceHeight());
      try {
        $$.canvasRenderer.drawBackground($$);
        $$.canvasAxisRenderer.drawTitle($$);
        state.hasAxis && $$.canvasAxisRenderer.draw($$);
        $$.canvasRenderer.draw($$, drawShape, focusData);
        state.hasAxis && $$.config.grid_lines_front && $$.canvasAxisRenderer.drawGridLines($$);
        $$.canvasRenderer.drawSubchart($$, drawShape);
        state.hasAxis && $$.canvasAxisRenderer.drawSubXAxis($$);
        state.hasAxis && $$.canvasAxisRenderer.drawSubYAxes($$);
        $$.canvasRenderer.drawEmptyLabel($$);
      } finally {
        $$.canvasEngine.endFrame();
      }
    }
    state.canvasFocusMainRedraw = !!withMainRedraw;
    $$.canvasEngine.withOverlay((ctx) => {
      $$.canvasRenderer.withContext(ctx, () => {
        $$.canvasRenderer.drawFocus($$, focusData);
      });
      $$.canvasAxisRenderer.withContext(ctx, () => {
        $$.canvasAxisRenderer.drawFocusedXAxisTick($$, focusData);
        point && $$.canvasAxisRenderer.drawAxisTooltip($$, point);
      });
    });
  },
  /**
   * Draw only the canvas axis tooltip overlay.
   * @param {Array} point Canvas-local pointer coordinate
   * @private
   */
  renderCanvasAxisTooltip(point) {
    const $$ = this;
    $$.canvasEngine.withOverlay((ctx) => {
      $$.canvasAxisRenderer.withContext(ctx, () => {
        $$.canvasAxisRenderer.drawAxisTooltip($$, point);
      });
    });
  },
  /**
   * Restore the cached canvas frame without focus overlays.
   * @private
   */
  clearCanvasFocus() {
    var _a;
    const $$ = this;
    if ($$.state.canvasFocusMainRedraw) {
      $$.state.canvasFocusMainRedraw = false;
      $$.renderCanvasFrame(void 0, null, false);
    } else {
      (_a = $$.canvasEngine) == null ? void 0 : _a.clearOverlay();
    }
  },
  /**
   * Resize canvas surfaces and reload canvas theme values.
   * @private
   */
  resizeCanvas() {
    var _a, _b;
    const $$ = this;
    const { config, state, $el } = $$;
    const container = $el.chart.node();
    $$.clearResizePreview();
    $el.chart.style("min-height", `${state.current.height}px`);
    (_a = $$.canvasEngine) == null ? void 0 : _a.resize(state.current.width, $$.getCanvasSurfaceHeight());
    (_b = $$.canvasTheme) == null ? void 0 : _b.reload(container, config.canvas_theme);
  }
};
let canvas = () => {
  extend(ChartInternal.prototype, canvasInternal);
  return (canvas = () => "canvas")();
};

;// ./src/Chart/api/category.ts

/* harmony default export */ var api_category = ({
  /**
   * Set specified category name on category axis.
   * @function category
   * @instance
   * @memberof Chart
   * @param {number} i index of category to be changed
   * @param {string} category category value to be changed
   * @returns {string}
   * @example
   * chart.category(2, "Category 3");
   */
  category(i, category) {
    const $$ = this.internal;
    const { config } = $$;
    if (arguments.length > 1) {
      config.axis_x_categories[i] = category;
      $$.state.dirty.data = true;
      $$.redraw();
    }
    return config.axis_x_categories[i];
  },
  /**
   * Set or get category names on category axis.
   * @function categories
   * @instance
   * @memberof Chart
   * @param {Array} categories This must be an array that includes category names in string. If category names are included in the date by data.x option, this is not required.
   * @returns {Array}
   * @example
   * chart.categories([
   *      "Category 1", "Category 2", ...
   * ]);
   */
  categories(categories) {
    const $$ = this.internal;
    const { config } = $$;
    if (!categories || !Array.isArray(categories)) {
      const cat = config.axis_x_categories;
      return isEmpty(cat) ? Object.values($$.data.xs)[0] : cat;
    }
    config.axis_x_categories = categories;
    $$.state.dirty.data = true;
    $$.redraw();
    return config.axis_x_categories;
  }
});

;// ./src/config/config.ts

function loadConfig(config) {
  const thisConfig = this.config;
  let target;
  let keys;
  let read;
  const find = () => {
    const key = keys.shift();
    if (key && target && isObjectType(target) && key in target) {
      target = target[key];
      return find();
    } else if (!key) {
      return target;
    }
    return void 0;
  };
  Object.keys(thisConfig).forEach((key) => {
    target = config;
    keys = key.split("_");
    read = find();
    if (isDefined(read)) {
      thisConfig[key] = read;
    }
  });
  if (this.api) {
    this.state.orgConfig = config;
  }
}

;// ./src/Chart/api/chart.ts



/* harmony default export */ var chart = ({
  /**
   * Resize the chart.
   * @function resize
   * @instance
   * @memberof Chart
   * @param {object} size This argument should include width and height in pixels.
   * @param {number} [size.width] width value
   * @param {number} [size.height] height value
   * @example
   * // Resize to 640x480
   * chart.resize({
   *    width: 640,
   *    height: 480
   * });
   */
  resize(size) {
    const $$ = this.internal;
    const { config, state } = $$;
    if (state.rendered) {
      config.size_width = size ? size.width : null;
      config.size_height = size ? size.height : null;
      state.resizing = true;
      state.dirty.size = true;
      this.flush(false);
      $$.resizeFunction();
    }
  },
  /**
   * Force to redraw.
   * - **NOTE:** When zoom/subchart is used, the zoomed state will be reset.
   * @function flush
   * @instance
   * @memberof Chart
   * @param {boolean} [soft] For soft redraw.
   * @example
   * chart.flush();
   *
   * // for soft redraw
   * chart.flush(true);
   */
  flush(soft) {
    var _a, _b;
    const $$ = this.internal;
    const { state, $el: { zoomResetBtn } } = $$;
    if (state.rendered) {
      if (state.resizing) {
        (_a = $$.brush) == null ? void 0 : _a.updateResize();
      } else {
        (_b = $$.axis) == null ? void 0 : _b.setOrient();
      }
      zoomResetBtn == null ? void 0 : zoomResetBtn.style("display", "none");
      if ($$.scale.zoom) {
        state.current.zoomDomain = $$.scale.zoom.domain();
      }
      $$.scale.zoom = null;
      if (!state.resizing) {
        state.dirty.data = true;
      }
      soft ? $$.redraw({
        withTransform: true,
        withUpdateXDomain: true,
        withUpdateOrgXDomain: true,
        withLegend: true
      }) : $$.updateAndRedraw({
        withLegend: true,
        withTransition: false,
        withTransitionForTransform: false
      });
      if (!state.resizing && $$.brush) {
        $$.brush.getSelection().call($$.brush.move);
        $$.unselectRect();
      }
      if (state.current.zoomDomain) {
        $$.api.zoom(state.current.zoomDomain);
        state.current.zoomDomain = null;
      }
    } else {
      $$.initToRender(true);
    }
  },
  /**
   * Reset the chart object and remove element and events completely.
   * @function destroy
   * @instance
   * @memberof Chart
   * @returns {null}
   * @example
   * chart.destroy();
   */
  destroy() {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
    const $$ = this.internal;
    const { state, $el: { chart, style, svg } } = $$;
    if (notEmpty($$)) {
      $$.callPluginHook("$willDestroy");
      (_a = $$.cache) == null ? void 0 : _a.remove(["setOverOut", "callOverOutForTouch"]);
      $$.charts.splice($$.charts.indexOf(this), 1);
      $$.charts.length === 0 && cleanupWorkers();
      $$.unbindAllEvents();
      svg == null ? void 0 : svg.select("*").interrupt();
      state.canvasFlowFrame !== null && ((_c = (_b = win).cancelAnimationFrame) == null ? void 0 : _c.call(_b, state.canvasFlowFrame));
      state.canvasFlowFrame = null;
      state.canvasFlowFinish = null;
      state.pendingRaf !== null && ((_e = (_d = win).cancelAnimationFrame) == null ? void 0 : _e.call(_d, state.pendingRaf));
      state.pendingRaf = null;
      (_f = $$.canvasRenderer) == null ? void 0 : _f.destroy();
      (_g = $$.canvasEngine) == null ? void 0 : _g.destroy();
      (_h = $$.resizeFunction) == null ? void 0 : _h.clear();
      (_j = (_i = $$.resizeFunction) == null ? void 0 : _i.clearLive) == null ? void 0 : _j.call(_i);
      (_l = (_k = $$.resizeFunction) == null ? void 0 : _k.resizeObserver) == null ? void 0 : _l.disconnect();
      $$.resizeFunction && win.removeEventListener("resize", $$.resizeFunction);
      chart.classed("bb", false).style("position", null);
      if (state.isCanvasMode) {
        chart.style("min-height", state.canvasInlineStyle.minHeight || null);
      }
      chart.selectChildren().remove();
      style && style.parentNode.removeChild(style);
      Object.keys(this).forEach((key) => {
        key === "internal" && Object.keys($$).forEach((k) => {
          $$[k] = null;
        });
        this[key] = null;
        delete this[key];
      });
      for (const key in this) {
        this[key] = () => {
        };
      }
    }
    return null;
  },
  /**
   * Get or set config option value.
   * - **NOTE**
   *  - The option key name must be specified as the last level.
   *  - When no argument is given, it will return all specified generation options object only. (will exclude any other options not specified at the initialization)
   * @function config
   * @instance
   * @memberof Chart
   * @param {string} name The option key name.
   * @param {string|number|boolean|object|Array} [value] The value accepted for indicated option.
   * @param {boolean} [redraw] Set to redraw with the new option changes.
   * - **NOTE:** Doesn't guarantee to work in all circumstances. It can be applied for limited options only.
   * @returns {string|number|boolean|object|Array} The option value or all options object
   * @example
   *
   * // Getter
   * chart.config("gauge.max");
   *
   * // Getter specified with top level key name will not work.
   * // The option key name must be specified as the last level.
   * // chart.config("gauge"); // will not work
   *
   * // without any arguments, it returns generation config object
   * chart.config();  // {data: { ... }, axis: { ... }, ...}
   *
   * // Setter
   * chart.config("gauge.max", 100);
   *
   * // Setter specified with top level key name will not work.
   * // The option key name must be specified as the last level.
   * // chart.config("gauge", {min: 10, max: 20}); // will not work
   *
   * // Setter & redraw with the new option
   * chart.config("gauge.max", 100, true);
   */
  config(name, value, redraw) {
    const $$ = this.internal;
    const { config, state } = $$;
    const key = name == null ? void 0 : name.replace(/\./g, "_");
    let res;
    if (name && key in config) {
      if (isDefined(value)) {
        config[key] = value;
        res = value;
        redraw && this.flush();
      } else {
        res = config[key];
      }
    } else if (arguments.length === 0 || isEmpty(name)) {
      res = state.orgConfig;
    }
    return res;
  }
});

;// ./src/Chart/api/color.ts
/* harmony default export */ var api_color = ({
  /**
   * Get the color
   * @function color
   * @instance
   * @memberof Chart
   * @param {string} id id to get the color
   * @returns {string}
   * @example
   * chart.color("data1");
   */
  color(id) {
    return this.internal.color(id);
  }
});

;// ./src/Chart/api/data.ts

const api_data_data = function(targetIds) {
  const { targets } = this.internal.data;
  if (!isUndefined(targetIds)) {
    const ids = isArray(targetIds) ? targetIds : [targetIds];
    return targets.filter((t) => ids.some((v) => v === t.id));
  }
  return targets;
};
extend(api_data_data, {
  /**
   * Get data shown in the chart.
   * @function data․shown
   * @instance
   * @memberof Chart
   * @param {string|Array} targetIds If this argument is given, this API filters the data with specified target ids. If this argument is not given, all shown data will be returned.
   * @returns {Array} Data objects
   * @example
   * // Get shown data by filtering to include only data1 data
   * chart.data.shown("data1");
   * // --> [{id: "data1", id_org: "data1", values: Array(6)}, ...]
   *
   * // Get shown data by filtering to include data1 and data2 data
   * chart.data.shown(["data1", "data2"]);
   *
   * // Get all shown data
   * chart.data.shown();
   */
  shown: function(targetIds) {
    return this.internal.filterTargetsToShow(this.data(targetIds));
  },
  /**
   * Get values of the data loaded in the chart.
   * @function data․values
   * @instance
   * @memberof Chart
   * @param {string|Array|null} targetIds This API returns the values of specified target. If this argument is not given, null will be returned
   * @param {boolean} [flat=true] Get flatten values
   * @returns {Array} Data values
   * @example
   * // Get data1 values
   * chart.data.values("data1");
   * // --> [10, 20, 30, 40]
   */
  values: function(targetIds, flat = true) {
    let values = null;
    if (targetIds) {
      const targets = this.data(targetIds);
      if (isArray(targets)) {
        values = [];
        targets.forEach((v) => {
          if (flat) {
            v.values.forEach((d) => values.push(d.value));
          } else {
            values.push(v.values.map((d) => d.value));
          }
        });
      }
    }
    return values;
  },
  /**
   * Get and set names of the data loaded in the chart.
   * @function data․names
   * @instance
   * @memberof Chart
   * @param {object} names If this argument is given, the names of data will be updated. If not given, the current names will be returned. The format of this argument is the same as [data.names](./Options.html#.data%25E2%2580%25A4names).
   * @returns {object} Corresponding names according its key value, if specified names values.
   * @example
   * // Get current names
   * chart.data.names();
   * // --> {data1: "test1", data2: "test2"}
   *
   * // Update names
   * chart.data.names({
   *  data1: "New Name 1",
   *  data2: "New Name 2"
   * });
   */
  names: function(names) {
    const $$ = this.internal;
    return $$.updateDataAttributes("names", names);
  },
  /**
   * Get and set colors of the data loaded in the chart.
   * - **NOTE:** If gradient option is set, the color update will affect only gradient stops have the same color.
   * @function data․colors
   * @instance
   * @memberof Chart
   * @param {object} colors If this argument is given, the colors of data will be updated. If not given, the current colors will be returned. The format of this argument is the same as [data.colors](./Options.html#.data%25E2%2580%25A4colors).
   * @returns {object} Corresponding data color value according its key value.
   * @example
   * // Get current colors
   * chart.data.colors();
   * // --> {data1: "#00c73c", data2: "#fa7171"}
   *
   * // Update colors
   * chart.data.colors({
   *  data1: "#FFFFFF",
   *  data2: "#000000"
   * });
   */
  colors: function(colors) {
    return this.internal.updateDataAttributes("colors", colors);
  },
  /**
   * Get and set axes of the data loaded in the chart.
   * - **NOTE:** If all data is related to one of the axes, the domain of axis without related data will be replaced by the domain from the axis with related data
   * @function data․axes
   * @instance
   * @memberof Chart
   * @param {object} axes If this argument is given, the axes of data will be updated. If not given, the current axes will be returned. The format of this argument is the same as
   * @returns {object} Corresponding axes value for data, if specified axes value.
   * @example
   * // Get current axes
   * chart.data.axes();
   * // --> {data1: "y"}
   *
   * // Update axes
   * chart.data.axes({
   *  data1: "y",
   *  data2: "y2"
   * });
   */
  axes: function(axes) {
    return this.internal.updateDataAttributes("axes", axes);
  },
  /**
   * Get the minimum data value bound to the chart
   * @function data․min
   * @instance
   * @memberof Chart
   * @returns {Array} Data objects
   * @example
   * // Get current axes
   * chart.data.min();
   * // --> [{x: 0, value: 30, id: "data1", index: 0}, ...]
   */
  min: function() {
    return this.internal.getMinMaxData().min;
  },
  /**
   * Get the maximum data value bound to the chart
   * @function data․max
   * @instance
   * @memberof Chart
   * @returns {Array} Data objects
   * @example
   * // Get current axes
   * chart.data.max();
   * // --> [{x: 3, value: 400, id: "data1", index: 3}, ...]
   */
  max: function() {
    return this.internal.getMinMaxData().max;
  }
});
/* harmony default export */ var api_data = ({ data: api_data_data });

;// ./src/Chart/api/focus.ts


/* harmony default export */ var api_focus = ({
  /**
   * This API highlights specified targets and fade out the others.<br><br>
   * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be highlighted.
   * @function focus
   * @instance
   * @memberof Chart
   * @param {string|Array} targetIdsValue Target ids to be highlighted.
   * @example
   *  // data1 will be highlighted and the others will be faded out
   *  chart.focus("data1");
   *
   * // data1 and data2 will be highlighted and the others will be faded out
   * chart.focus(["data1", "data2"]);
   *
   * // all targets will be highlighted
   * chart.focus();
   */
  focus(targetIdsValue) {
    var _a;
    const $$ = this.internal;
    const { state } = $$;
    const targetIds = $$.mapToTargetIds(targetIdsValue);
    if (state.isCanvasMode) {
      const focusedIds = targetIds.filter($$.isTargetToShow, $$);
      const focusedSet = new Set(focusedIds);
      const defocusedIds = $$.mapToTargetIds().filter((id) => !focusedSet.has(id) && $$.isTargetToShow(id));
      $$.revertLegend();
      $$.toggleFocusLegend(defocusedIds, false);
      $$.toggleFocusLegend(focusedIds, true);
      state.focusedTargetIds = focusedSet;
      state.defocusedTargetIds = new Set(defocusedIds);
      (_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false);
      return;
    }
    const candidates = $$.$el.svg.selectAll(
      $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
    );
    this.revert();
    this.defocus();
    candidates.classed($FOCUS.focused, true).classed($FOCUS.defocused, false);
    if ($$.hasArcType() && !state.hasRadar) {
      $$.expandArc(targetIds);
      $$.hasType("gauge") && $$.markOverlapped(targetIdsValue, $$, `.${$GAUGE.gaugeValue}`);
    }
    $$.toggleFocusLegend(targetIds, true);
    state.focusedTargetIds = new Set(targetIds);
    targetIds.forEach((id) => state.defocusedTargetIds.delete(id));
  },
  /**
   * This API fades out specified targets and reverts the others.<br><br>
   * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be faded out.
   * @function defocus
   * @instance
   * @memberof Chart
   * @param {string|Array} targetIdsValue Target ids to be faded out.
   * @example
   * // data1 will be faded out and the others will be reverted.
   * chart.defocus("data1");
   *
   * // data1 and data2 will be faded out and the others will be reverted.
   * chart.defocus(["data1", "data2"]);
   *
   * // all targets will be faded out.
   * chart.defocus();
   */
  defocus(targetIdsValue) {
    var _a;
    const $$ = this.internal;
    const { state } = $$;
    const targetIds = $$.mapToTargetIds(targetIdsValue);
    if (state.isCanvasMode) {
      const defocusedIds = targetIds.filter($$.isTargetToShow, $$);
      $$.toggleFocusLegend(defocusedIds, false);
      defocusedIds.forEach((id) => state.focusedTargetIds.delete(id));
      state.defocusedTargetIds = new Set(defocusedIds);
      (_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false);
      return;
    }
    const candidates = $$.$el.svg.selectAll(
      $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
    );
    candidates.classed($FOCUS.focused, false).classed($FOCUS.defocused, true);
    if ($$.hasArcType(null, ["polar"])) {
      $$.unexpandArc(targetIds);
      $$.hasType("gauge") && $$.undoMarkOverlapped($$, `.${$GAUGE.gaugeValue}`);
    }
    $$.toggleFocusLegend(targetIds, false);
    targetIds.forEach((id) => state.focusedTargetIds.delete(id));
    state.defocusedTargetIds = new Set(targetIds);
  },
  /**
   * Revert focused or defocused state to initial state.<br><br>
   * You can specify multiple targets by giving an array that includes id as string. If no argument is given, all of targets will be reverted.
   * @function revert
   * @instance
   * @memberof Chart
   * @param {string|Array} targetIdsValue Target ids to be reverted
   * @example
   * // 'data1' will be reverted.
   * chart.revert("data1");
   *
   * // 'data1' and 'data2' will be reverted.
   * chart.revert(["data1", "data2"]);
   *
   * // all targets will be reverted.
   * chart.revert();
   */
  revert(targetIdsValue) {
    var _a, _b, _c;
    const $$ = this.internal;
    const { config, state, $el } = $$;
    const targetIds = $$.mapToTargetIds(targetIdsValue);
    const resetLegend = () => {
      if (config.legend_show) {
        $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
        $el.legend.selectAll($$.selectorLegends(targetIds)).filter(function() {
          return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused);
        }).classed($FOCUS.legendItemFocused, false);
      }
    };
    if (state.isCanvasMode) {
      const changed = !!((_a = state.focusedTargetIds) == null ? void 0 : _a.size) || !!((_b = state.defocusedTargetIds) == null ? void 0 : _b.size);
      resetLegend();
      state.focusedTargetIds = /* @__PURE__ */ new Set();
      state.defocusedTargetIds = /* @__PURE__ */ new Set();
      changed && ((_c = $$.renderCanvasFrame) == null ? void 0 : _c.call($$, void 0, null, false));
      return;
    }
    const candidates = $el.svg.selectAll($$.selectorTargets(targetIds));
    candidates.classed($FOCUS.focused, false).classed($FOCUS.defocused, false);
    $$.hasArcType(null, ["polar"]) && $$.unexpandArc(targetIds);
    resetLegend();
    state.focusedTargetIds = /* @__PURE__ */ new Set();
    state.defocusedTargetIds = /* @__PURE__ */ new Set();
  }
});

;// ./src/Chart/api/legend.ts
const legend_legend = {
  /**
   * Show legend for each target.
   * - **NOTE:** Legend APIs aren't supported for `treemap` type.
   * @function legend․show
   * @instance
   * @memberof Chart
   * @param {string|Array} targetIds
   * - If targetIds is given, specified target's legend will be shown.
   * - If only one target is the candidate, String can be passed.
   * - If no argument is given, all of target's legend will be shown.
   * @example
   * // Show legend for data1.
   * chart.legend.show("data1");
   *
   * // Show legend for data1 and data2.
   * chart.legend.show(["data1", "data2"]);
   *
   * // Show all legend.
   * chart.legend.show();
   */
  show: function(targetIds) {
    const $$ = this.internal;
    $$.showLegend($$.mapToTargetIds(targetIds));
    $$.updateAndRedraw({ withLegend: true });
  },
  /**
   * Hide legend for each target.
   * @function legend․hide
   * @instance
   * @memberof Chart
   * @param {string|Array} targetIds
   * - If targetIds is given, specified target's legend will be hidden.
   * - If only one target is the candidate, String can be passed.
   * - If no argument is given, all of target's legend will be hidden.
   * @example
   * // Hide legend for data1.
   * chart.legend.hide("data1");
   *
   * // Hide legend for data1 and data2.
   * chart.legend.hide(["data1", "data2"]);
   *
   * // Hide all legend.
   * chart.legend.hide();
   */
  hide: function(targetIds) {
    const $$ = this.internal;
    $$.hideLegend($$.mapToTargetIds(targetIds));
    $$.updateAndRedraw({ withLegend: true });
  }
};
/* harmony default export */ var api_legend = ({ legend: legend_legend });

;// ./src/Chart/api/load.ts



/* harmony default export */ var api_load = ({
  /**
   * Load data to the chart.<br><br>
   * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be toggles.
   * - <b>Note:</b>
   *   - unload should be used if some data needs to be unloaded simultaneously.
   *     If you call unload API soon after/before load instead of unload param, chart will not be rendered properly because of cancel of animation.<br>
   *   - done will be called after data loaded, but it's not after rendering.
   *     It's because rendering will finish after some transition and there is some time lag between loading and rendering
   * @function load
   * @instance
   * @memberof Chart
   * @param {object} args The object can consist with following members:<br>
   *
   *    | Key | Type | Description |
   *    | --- | --- | --- |
   *    | columns | Array | The `columns` data will be loaded. If data that has the same target id is given, the chart will be updated. Otherwise, new target will be added |
   *    | json | Array | The `json` data will be loaded. If data that has the same target id is given, the chart will be updated. Otherwise, new target will be added |
   *    | rows | Array | The `rows` data will be loaded. If data that has the same target id is given, the chart will be updated. Otherwise, new target will be added |
   *    | url | string | The data from `url` will be loaded. If data that has the same target id is given, the chart will be updated. Otherwise, new target will be added |
   *    | &nbsp; | | |
   *    | append | boolean | Load data appending it to the current dataseries.<br>If the existing chart has`x` value, should provide with corresponding `x` value for newly loaded data.  |
   *    | axes | Object | The axes specified by data.axes will be updated. axes must be Object that has target id as keys. |
   *    | categories | Array | The categories specified by axis.x.categories or data.x will be updated. categories must be Array. |
   *    | classes | Object | The classes specified by data.classes will be updated. classes must be Object that has target id as keys. |
   *    | colors | Object | The colors specified by data.colors will be updated. colors must be Object that has target id as keys. |
   *    | data | Object | Data objects to be loaded. Checkout the example. |
   *    | done | Function | The specified function will be called after data loaded.|
   *    | headers | string |  Set request header if loading via `data.url`.<br>@see [data․headers](Options.html#.data%25E2%2580%25A4headers) |
   *    | keys | Object |  Choose which JSON objects keys correspond to desired data.<br>**NOTE:** Only for JSON object given as array.<br>@see [data․keys](Options.html#.data%25E2%2580%25A4keys) |
   *    | mimeType | string |  Set 'json' if loading JSON via url.<br>@see [data․mimeType](Options.html#.data%25E2%2580%25A4mimeType) |
   *    | names | Object | Same as data.names() |
   *    | regions | Object | The regions specified by data.regions will be updated. regions must be Object that has target id as keys. |
   *    | resizeAfter | boolean | Resize after the load. Default value is `false`.<br>- This option won't call `onresize` neither `onresized`.<br>- When set to 'true', will call `.flush(true)` at the end of load. |
   *    | type | string | The type of targets will be updated. |
   *    | types | Object | The types of targets will be updated. |
   *    | unload | Array | Specify the data will be unloaded before loading new data. If true given, all of data will be unloaded. If target ids given as String or Array, specified targets will be unloaded. If absent or false given, unload will not occur. |
   *    | xs | string | Same as data.xs option  |
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataFromURL)
   * @example
   * // Load data1 and unload data2 and data3
   * chart.load({
   *     columns: [
   *        ["data1", 100, 200, 150, ...],
   *        ...
   *    ],
   *    unload: ["data2", "data3"],
   *    url: "...",
   *    done: function() { ... }
   *    resizeAfter: true  // will resize after load
   * });
   * @example
   * const chart = bb.generate({
   *   data: {
   *     columns: [
   *       ["data1", 20, 30, 40]
   *     ]
   *   }
   * });
   *
   * chart.load({
   *    columns: [
   *        // with 'append' option, the 'data1' will have `[20,30,40,50,60]`.
   *        ["data1", 50, 60]
   *    ],
   *    append: true
   * });
   * @example
   * const chart = bb.generate({
   *   data: {
   *     x: "x",
   *     xFormat: "%Y-%m-%dT%H:%M:%S",
   *     columns: [
   *       ["x", "2021-01-03T03:00:00", "2021-01-04T12:00:00", "2021-01-05T21:00:00"],
   *       ["data1", 36, 30, 24]
   *     ]
   *   },
   *   axis: {
   *     x: {
   *       type: "timeseries"
   *     }
   *   }
   * };
   *
   * chart.load({
   *   columns: [
   *     // when existing chart has `x` value, should provide corresponding 'x' value.
   *     // with 'append' option, the 'data1' will have `[36,30,24,37]`.
   *     ["x", "2021-02-01T08:00:00"],
   *     ["data1", 37]
   *   ],
   *   append: true
   * });
   * @example
   * // myAPI.json
   * // {
   * //   "data1": [220, 240, 270, 250, 280],
   * //   "data2": [180, 150, 300, 70, 120]
   * // }
   *
   * chart.load({
   *     url: './data/myAPI.json',
   *     mimeType: "json",
   *
   *     // set request header if is needed
   *     headers: {
   *       "Content-Type": "text/json"
   *     }
   * });
   * @example
   * chart.load({
   *     data: [
   *       // equivalent as: columns: [["data1", 30, 200, 100]]
   *       {"data1": 30}, {"data1": 200}, {"data1": 100}
   *
   *       // or
   *       // equivalent as: columns: [["data1", 10, 20], ["data2", 13, 30]]
   *       // {"data1": 10, "data2": 13}, {"data1": 20, "data2": 30}}
   *     ]
   * });
   * @example
   * chart.load({
   *     json: [
   *          {name: "www.site1.com", upload: 800, download: 500, total: 400},
   *     ],
   *     keys: {
   *         x: "name",
   *         value: ["upload", "download"]
   *     }
   * });
   * @example
   * chart.load({
   *   json: {
   *       data1:[30, 20, 50, 40, 60, 50],
   *       data2:[200, 130, 90, 240, 130, 220],
   *   }
   * });
   */
  load(args) {
    const $$ = this.internal;
    const { config } = $$;
    $$.state.dirty.data = true;
    $$.state._eventRectFingerprint = null;
    args.xs && $$.addXs(args.xs);
    "names" in args && this.data.names(args.names);
    "classes" in args && Object.keys(args.classes).forEach((id) => {
      config.data_classes[id] = args.classes[id];
    });
    if ("categories" in args && $$.axis.isCategorized()) {
      config.axis_x_categories = args.categories;
    }
    "axes" in args && Object.keys(args.axes).forEach((id) => {
      config.data_axes[id] = args.axes[id];
    });
    "colors" in args && Object.keys(args.colors).forEach((id) => {
      config.data_colors[id] = args.colors[id];
    });
    "regions" in args && (config.data_regions = args.regions || {});
    const hasDataToLoad = ["data", "columns", "rows", "json", "url"].some((key) => key in args);
    const hasUnload = "unload" in args && args.unload !== false;
    if ("regions" in args && !hasDataToLoad && !hasUnload) {
      $$.redraw({
        withUpdateOrgXDomain: true,
        withUpdateXDomain: true,
        withLegend: true
      });
      callDone.call($$, args.done, args.resizeAfter);
      return;
    }
    if (hasUnload) {
      const unloadIds = $$.mapToTargetIds(args.unload === true ? null : args.unload);
      $$.unload(unloadIds, () => {
        if (!$$.config || !$$.cache) {
          return;
        }
        $$.cache.remove(unloadIds);
        requestIdleCallback(() => $$.loadFromArgs(args));
      });
    } else {
      $$.loadFromArgs(args);
    }
  },
  /**
   * Unload data to the chart.<br><br>
   * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be toggles.
   * - <b>Note:</b>
   * If you call load API soon after/before unload, unload param of load should be used. Otherwise chart will not be rendered properly because of cancel of animation.<br>
   * `done` will be called after data loaded, but it's not after rendering. It's because rendering will finish after some transition and there is some time lag between loading and rendering.
   * @function unload
   * @instance
   * @memberof Chart
   * @param {object} argsValue
   *  | key | Type | Description |
   *  | --- | --- | --- |
   *  | ids | String &vert; Array | Target id data to be unloaded. If not given, all data will be unloaded. |
   *  | done | Function | Callback after data is unloaded. |
   *  | resizeAfter | boolean | Resize after the unload. Default value is `false`.<br>- This option won't call `onresize` neither `onresized`.<br>- When set to 'true', will call `.flush(true)` at the end of unload. |
   * @example
   *  // Unload data2 and data3
   *  chart.unload({
   *    ids: ["data2", "data3"],
   *    done: function() {
   *       // called after the unloaded
   *    },
   *    resizeAfter: true  // will resize after unload
   *  });
   */
  unload(argsValue) {
    const $$ = this.internal;
    let args = argsValue || {};
    isEmpty(args) && this.tooltip.hide();
    if (isArray(args)) {
      args = { ids: args };
    } else if (isString(args)) {
      args = { ids: [args] };
    }
    const ids = $$.mapToTargetIds(args.ids);
    $$.state.dirty.data = true;
    $$.state._eventRectFingerprint = null;
    $$.unload(ids, () => {
      if (!$$.config || !$$.cache) {
        return;
      }
      $$.redraw({
        withUpdateOrgXDomain: true,
        withUpdateXDomain: true,
        withLegend: true
      });
      $$.cache.remove(ids);
      callDone.call($$, args.done, args.resizeAfter);
    });
  }
});

;// ./src/Chart/api/show.ts

function showHide(show, targetIdsValue, options, skipRedraw = false) {
  var _a;
  const $$ = this.internal;
  const targetIds = $$.mapToTargetIds(targetIdsValue);
  const targetIdSet = new Set(targetIds);
  const hiddenIds = [...$$.state.hiddenTargetIds].filter((v) => targetIdSet.has(v));
  $$.state.toggling = true;
  $$.state.dirty.visibility = true;
  $$[`${show ? "remove" : "add"}HiddenTargetIds`](targetIds);
  if ($$.state.isCanvasMode) {
    if (show && hiddenIds.length) {
      callFn($$.config.data_onshown, this, hiddenIds);
    } else if (!show && hiddenIds.length === 0) {
      callFn((_a = $$.config) == null ? void 0 : _a.data_onhidden, this, targetIds);
    }
    if (!skipRedraw) {
      $$.redraw({
        withUpdateOrgXDomain: true,
        withUpdateXDomain: true,
        withLegend: true
      });
    }
    $$.state.toggling = false;
    return;
  }
  const targets = $$.$el.svg.selectAll($$.selectorTargets(targetIds));
  const opacity = show ? null : "0";
  if (show && hiddenIds.length) {
    targets.style("display", null);
    callFn($$.config.data_onshown, this, hiddenIds);
  }
  $$.$T(targets).style("opacity", opacity, "important").call(endall, () => {
    var _a2;
    if (!show && hiddenIds.length === 0) {
      targets.style("display", "none");
      callFn((_a2 = $$.config) == null ? void 0 : _a2.data_onhidden, this, targetIds);
    }
    targets.style("opacity", opacity);
  });
  options.withLegend && $$[`${show ? "show" : "hide"}Legend`](targetIds);
  if (!skipRedraw) {
    $$.redraw({
      withUpdateOrgXDomain: true,
      withUpdateXDomain: true,
      withLegend: true
    });
  }
  $$.state.toggling = false;
}
/* harmony default export */ var show = ({
  /**
   * Show data series on chart
   * @function show
   * @instance
   * @memberof Chart
   * @param {string|Array} [targetIdsValue] The target id value.
   * @param {object} [options] The object can consist with following members:<br>
   *
   *    | Key | Type | default | Description |
   *    | --- | --- | --- | --- |
   *    | withLegend | boolean | false | whether or not display legend |
   *
   * @example
   * // show 'data1'
   * chart.show("data1");
   *
   * // show 'data1' and 'data3'
   * chart.show(["data1", "data3"]);
   */
  show(targetIdsValue, options = {}) {
    showHide.call(this, true, targetIdsValue, options);
  },
  /**
   * Hide data series from chart
   * @function hide
   * @instance
   * @memberof Chart
   * @param {string|Array} [targetIdsValue] The target id value.
   * @param {object} [options] The object can consist with following members:<br>
   *
   *    | Key | Type | default | Description |
   *    | --- | --- | --- | --- |
   *    | withLegend | boolean | false | whether or not display legend |
   *
   * @example
   * // hide 'data1'
   * chart.hide("data1");
   *
   * // hide 'data1' and 'data3'
   * chart.hide(["data1", "data3"]);
   */
  hide(targetIdsValue, options = {}) {
    showHide.call(this, false, targetIdsValue, options);
  },
  /**
   * Toggle data series on chart. When target data is hidden, it will show. If is shown, it will hide in vice versa.
   * @function toggle
   * @instance
   * @memberof Chart
   * @param {string|Array} [targetIds] The target id value.
   * @param {object} [options] The object can consist with following members:<br>
   *
   *    | Key | Type | default | Description |
   *    | --- | --- | --- | --- |
   *    | withLegend | boolean | false | whether or not display legend |
   *
   * @example
   * // toggle 'data1'
   * chart.toggle("data1");
   *
   * // toggle 'data1' and 'data3'
   * chart.toggle(["data1", "data3"]);
   */
  toggle(targetIds, options = {}) {
    const $$ = this.internal;
    const targets = { show: [], hide: [] };
    $$.mapToTargetIds(targetIds).forEach((id) => targets[$$.isTargetToShow(id) ? "hide" : "show"].push(id));
    if (targets.show.length && targets.hide.length) {
      showHide.call(this, true, targets.show, options, true);
      showHide.call(this, false, targets.hide, options);
    } else {
      targets.show.length && this.show(targets.show, options);
      targets.hide.length && this.hide(targets.hide, options);
    }
  }
});

;// ./src/Chart/api/tooltip.ts


const tooltip_tooltip = {
  /**
   * Show tooltip
   * @function tooltip․show
   * @instance
   * @memberof Chart
   * @param {object} args The object can consist with following members:<br>
   *
   *    | Key | Type | Description |
   *    | --- | --- | --- |
   *    | index | Number | Determine focus by index |
   *    | x | Number &vert; Date | Determine focus by x Axis index |
   *    | mouse | Array | Determine x and y coordinate value relative the targeted '.bb-event-rect' x Axis.<br>It should be used along with `data`, `index` or `x` value. The default value is set as `[0,0]` |
   *    | data | Object | When [data.xs](Options.html#.data%25E2%2580%25A4xs) option is used or [tooltip.grouped](Options.html#.tooltip) set to 'false', `should be used giving this param`.<br><br>**Key:**<br>- x {number &verbar; Date}: x Axis value<br>- index {number}: x Axis index (useless for data.xs)<br>- id {string}: data id<br>- value {number}: The corresponding value for tooltip. |
   *
   * @example
   *  // show the 2nd x Axis coordinate tooltip
   *  // for Arc(gauge, donut & pie) and radar type, approach showing tooltip by using "index" number.
   *  chart.tooltip.show({
   *    index: 1
   *  });
   *
   *  // show tooltip for the 3rd x Axis in x:50 and y:100 coordinate of '.bb-event-rect' of the x Axis.
   *  chart.tooltip.show({
   *    x: 2,
   *    mouse: [50, 100]
   *  });
   *
   *  // show tooltip for timeseries x axis
   *  chart.tooltip.show({
   *    x: new Date("2018-01-02 00:00")
   *  });
   *
   *  // treemap type can be shown by using "id" only.
   *  chart.tooltip.show({
   *    data: {
   *        id: "data1"  // data id
   *    }
   *  });
   *
   *  // for Arc types, specify 'id' or 'index'
   *  chart.tooltip.show({ data: { id: "data2" }});
   *  chart.tooltip.show({ data: { index: 2 }});
   *
   *  // when data.xs is used
   *  chart.tooltip.show({
   *    data: {
   *        x: 3,  // x Axis value
   *        id: "data1",  // data id
   *        value: 500  // data value
   *    }
   *  });
   *
   *  // when data.xs isn't used, but tooltip.grouped=false is set
   *  chart.tooltip.show({
   *    data: {
   *        index: 3,  // or 'x' key value
   *        id: "data1",  // data id
   *        value: 500  // data value
   *    }
   *  });
   */
  show: function(args) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
    const $$ = this.internal;
    const { $el, config, state: { eventReceiver, hasFunnel, hasTreemap, inputType } } = $$;
    let index;
    let mouse;
    if (args.mouse) {
      mouse = args.mouse;
    }
    if (args.data) {
      const { data } = args;
      const y = (_a = $$.getYScaleById(data.id)) == null ? void 0 : _a(data.value);
      if ((hasFunnel || hasTreemap) && data.id) {
        const selector = $$.selectorTarget(data.id, void 0, `.${$SHAPE.shape}`);
        eventReceiver.rect = $el.main.select(selector);
      } else if ($$.isMultipleX()) {
        mouse = [$$.xx(data), y];
      } else {
        if (!config.tooltip_grouped) {
          mouse = [0, y];
        }
        index = (_c = data.index) != null ? _c : $$.hasArcType() && data.id ? (_b = $$.getArcElementByIdOrIndex(data.id)) == null ? void 0 : _b.datum().index : $$.getIndexByX(data.x);
      }
    } else if (isDefined(args.x)) {
      index = $$.getIndexByX(args.x);
    } else if (isDefined(args.index)) {
      index = args.index;
    }
    if ($$.state.isCanvasMode) {
      const targets = ((_d = $$.filterTargetsToShow) == null ? void 0 : _d.call($$)) || $$.data.targets;
      const selectedData = ((_e = args.data) == null ? void 0 : _e.id) && !config.tooltip_grouped ? targets.filter((target) => target.id === args.data.id).map((target) => target.values[index != null ? index : args.data.index]).filter(Boolean) : targets.map((target) => target.values[index]).filter(Boolean);
      const canvas = (_g = (_f = $el.canvas) == null ? void 0 : _f.node) == null ? void 0 : _g.call(_f);
      const shape = $$.state.canvasShape || ((_h = $$.getDrawShape) == null ? void 0 : _h.call($$));
      const first = selectedData[0];
      const point = mouse || (first && ((_i = shape == null ? void 0 : shape.pos) == null ? void 0 : _i.cx) && ((_j = shape == null ? void 0 : shape.pos) == null ? void 0 : _j.cy) ? [
        $$.state.margin.left + shape.pos.cx(first),
        $$.state.margin.top + shape.pos.cy(first)
      ] : void 0);
      if (!selectedData.length || !canvas) {
        return;
      }
      $$.state.canvasFocusKey = selectedData.map((v) => `${v.id}:${v.index}`).join("|");
      (_k = $$.renderCanvasFocus) == null ? void 0 : _k.call($$, selectedData, point);
      (_l = $$.showTooltip) == null ? void 0 : _l.call($$, selectedData, canvas);
      return;
    }
    (inputType === "mouse" ? ["mouseover", "mousemove"] : ["touchstart"]).forEach((eventName) => {
      $$.dispatchEvent(eventName, index, mouse);
    });
  },
  /**
   * Hide tooltip
   * @function tooltip․hide
   * @instance
   * @memberof Chart
   */
  hide: function() {
    var _a, _b, _c, _d, _e;
    const $$ = this.internal;
    const { state: { inputType, isCanvasMode }, $el: { tooltip: tooltip2 } } = $$;
    const data = tooltip2 == null ? void 0 : tooltip2.datum();
    if (isCanvasMode) {
      $$.state.canvasFocusKey = null;
      $$.hideTooltip(true);
      (_a = $$.clearCanvasFocus) == null ? void 0 : _a.call($$);
      return;
    }
    if ((_b = data == null ? void 0 : data.data) == null ? void 0 : _b[0]) {
      const { index } = data.data[0];
      (inputType === "mouse" ? ["mouseout"] : ["touchend"]).forEach((eventName) => {
        $$.dispatchEvent(eventName, index);
      });
    }
    inputType === "touch" && $$.callOverOutForTouch();
    $$.hideTooltip(true);
    (_c = $$.hideGridFocus) == null ? void 0 : _c.call($$);
    (_d = $$.unexpandCircles) == null ? void 0 : _d.call($$);
    (_e = $$.expandBarTypeShapes) == null ? void 0 : _e.call($$, false);
  }
};
/* harmony default export */ var api_tooltip = ({ tooltip: tooltip_tooltip });

;// ./src/Chart/Chart.ts
var Chart_defProp = Object.defineProperty;
var Chart_defNormalProp = (obj, key, value) => key in obj ? Chart_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var Chart_publicField = (obj, key, value) => Chart_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);











class Chart {
  constructor(options) {
    Chart_publicField(this, "plugins", []);
    Chart_publicField(this, "internal");
    const $$ = new ChartInternal(this);
    this.internal = $$;
    (function bindThis(fn, target, argThis) {
      Object.keys(fn).forEach((key) => {
        const isFunc = isFunction(fn[key]);
        const isChild = target !== argThis;
        const isNotNil = notEmpty(fn[key]);
        const hasChild = isNotNil && Object.keys(fn[key]).length > 0;
        if (isFunc && (!isChild && hasChild || isChild)) {
          target[key] = fn[key].bind(argThis);
        } else if (isNotNil && !isFunc) {
          target[key] = {};
        } else {
          target[key] = fn[key];
        }
        hasChild && bindThis(fn[key], target[key], argThis);
      });
    })(Chart.prototype, this, this);
    loadConfig.call($$, options);
    $$.beforeInit();
    $$.init();
  }
}
extend(Chart.prototype, [
  chart,
  api_color,
  api_data,
  api_focus,
  api_legend,
  api_load,
  show,
  api_tooltip
]);

;// ./src/config/resolver/category.ts


let category_category = () => {
  Chart.prototype.category = api_category.category;
  Chart.prototype.categories = api_category.categories;
  return (category_category = () => ({}))();
};

;// ./src/Chart/api/export.ts



const b64EncodeUnicode = (str) => {
  var _a, _b;
  return (_b = (_a = win).btoa) == null ? void 0 : _b.call(
    _a,
    encodeURIComponent(str).replace(
      /%([0-9A-F]{2})/g,
      (match, p) => String.fromCharCode(Number(`0x${p}`))
    )
  );
};
function nodeToSvgDataUrl(node, option, orgSize) {
  const { width, height } = option || orgSize;
  const serializer = new XMLSerializer();
  const clone = node.cloneNode(true);
  const cssText = getCssRules(toArray(browser_doc.styleSheets)).filter((r) => r.cssText).map((r) => r.cssText);
  clone.setAttribute("xmlns", external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.xhtml);
  clone.style.margin = "0";
  clone.style.padding = "0";
  if (option.preserveFontStyle) {
    clone.querySelectorAll("text").forEach((t) => {
      t.innerHTML = "";
    });
  }
  const nodeXml = serializer.serializeToString(clone);
  const style = browser_doc.createElement("style");
  style.appendChild(browser_doc.createTextNode(cssText.join("\n")));
  const styleXml = serializer.serializeToString(style);
  const dataStr = `<svg xmlns="${external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.svg}" width="${width}" height="${height}" 
		viewBox="0 0 ${orgSize.width} ${orgSize.height}" 
		preserveAspectRatio="${(option == null ? void 0 : option.preserveAspectRatio) === false ? "none" : "xMinYMid meet"}">
			<foreignObject width="100%" height="100%">
				${styleXml}
				${nodeXml.replace(/(url\()[^#]+/g, "$1")}
			</foreignObject></svg>`;
  return `data:image/svg+xml;base64,${b64EncodeUnicode(dataStr)}`;
}
function getCoords(elem, svgOffset) {
  const { top, left } = svgOffset;
  const { x, y } = getBBox(elem, true);
  const { a, b, c, d, e, f } = elem.getScreenCTM();
  const { width, height } = getBoundingRect(elem, true);
  return {
    x: a * x + c * y + e - left,
    y: b * x + d * y + f - top + (height - Math.round(height / 4)),
    width,
    height
  };
}
function getGlyph(svg) {
  const { left, top } = getBoundingRect(svg);
  const filterFn = (t) => t.textContent || t.childElementCount;
  const glyph = [];
  toArray(svg.querySelectorAll("text")).filter(filterFn).forEach((t) => {
    const getStyleFn = (ts) => {
      const { fill, fontFamily, fontSize, textAnchor, transform } = win.getComputedStyle(
        ts
      );
      const { x, y, width, height } = getCoords(ts, { left, top });
      return {
        [ts.textContent]: {
          x,
          y,
          width,
          height,
          fill,
          fontFamily,
          fontSize,
          textAnchor,
          transform
        }
      };
    };
    if (t.childElementCount > 1) {
      toArray(t.querySelectorAll("tspan")).filter(filterFn).forEach((ts) => {
        glyph.push(getStyleFn(ts));
      });
    } else {
      glyph.push(getStyleFn(t));
    }
  });
  return glyph;
}
function renderText(ctx, glyph) {
  glyph.forEach((g) => {
    Object.keys(g).forEach((key) => {
      const { x, y, width, height, fill, fontFamily, fontSize, transform } = g[key];
      ctx.save();
      ctx.font = `${fontSize} ${fontFamily}`;
      ctx.fillStyle = fill;
      if (transform === "none") {
        ctx.fillText(key, x, y);
      } else {
        const args = transform.replace(/(matrix|\(|\))/g, "").split(",");
        if (args.splice(4).every((v) => +v === 0)) {
          args.push(x + width - width / 4);
          args.push(y - height + height / 3);
        } else {
          args.push(x);
          args.push(y);
        }
        ctx.transform(...args);
        ctx.fillText(key, 0, 0);
      }
      ctx.restore();
    });
  });
}
function canvasToDataUrl(source, option, orgSize) {
  const { width, height } = option || orgSize;
  const canvas = browser_doc.createElement("canvas");
  const ctx = canvas.getContext("2d");
  canvas.width = width;
  canvas.height = height;
  if (ctx) {
    const x = 0;
    let y = 0;
    let w = width;
    let h = height;
    if ((option == null ? void 0 : option.preserveAspectRatio) !== false) {
      const scale = Math.min(width / orgSize.width, height / orgSize.height);
      w = orgSize.width * scale;
      h = orgSize.height * scale;
      y = (height - h) / 2;
    }
    ctx.drawImage(source, 0, 0, source.width, source.height, x, y, w, h);
  }
  return canvas.toDataURL(option.mimeType);
}
/* harmony default export */ var api_export = ({
  /**
   * Export chart as an image.
   * - **NOTE:**
   *   - IE11 and below not work properly due to the lack of the feature(<a href="https://msdn.microsoft.com/en-us/library/hh834675(v=vs.85).aspx">foreignObject</a>) support
   *   - Every style applied to the chart & the basic CSS file(ex. billboard.css) should be at same domain as API call context to get correct styled export image.
   * @function export
   * @instance
   * @memberof Chart
   * @param {object} option Export option
   * @param {string} [option.mimeType="image/png"] The desired output image format. (ex. 'image/png' for png, 'image/jpeg' for jpeg format)
   * @param {number} [option.width={currentWidth}] width
   * @param {number} [option.height={currentHeigth}] height
   * @param {boolean} [option.preserveAspectRatio=true] Preserve aspect ratio on given size
   * @param {boolean} [option.preserveFontStyle=false] Preserve font style(font-family).<br>
   * **NOTE:**
   *   - This option is useful when outlink web font style's `font-family` are applied to chart's text element.
   *   - Text element's position(especially "transformed") can't be preserved correctly according the page's layout condition.
   *   - If need to preserve accurate text position, embed the web font data within to the page and set `preserveFontStyle=false`.
   *     - Checkout the embed example: <a href="https://stackblitz.com/edit/zfbya9-8nf9nn?file=index.html">https://stackblitz.com/edit/zfbya9-8nf9nn?file=index.html</a>
   * @param {function(string): void} [callback] The callback to be invoked when export is ready.
   * @returns {string} dataURI
   * @example
   *  chart.export();
   *  // --> "data:image/svg+xml;base64,PHN..."
   *
   *  // Initialize the download automatically
   *  chart.export({mimeType: "image/png"}, dataUrl => {
   *     const link = document.createElement("a");
   *
   *     link.download = `${Date.now()}.png`;
   *     link.href = dataUrl;
   *     link.innerHTML = "Download chart as image";
   *
   *     document.body.appendChild(link);
   *  });
   *
   *  // Resize the exported image
   *  chart.export(
   *    {
   *      width: 800,
   *      height: 600,
   *      preserveAspectRatio: false,
   *      preserveFontStyle: false,
   *      mimeType: "image/png"
   *    },
   *    dataUrl => { ... }
   *  );
   */
  export(option, callback) {
    var _a;
    const $$ = this.internal;
    const { state, $el: { chart, svg } } = $$;
    const canvas = (_a = $$.canvasEngine) == null ? void 0 : _a.canvas;
    const canvasRect = state.isCanvasMode && canvas ? getBoundingRect(canvas, true) : null;
    const { width, height } = canvasRect && canvasRect.width && canvasRect.height ? {
      width: canvasRect.width,
      height: canvasRect.height
    } : state.current;
    const opt = mergeObj(/* @__PURE__ */ Object.create(null), {
      width,
      height,
      preserveAspectRatio: true,
      preserveFontStyle: false,
      mimeType: "image/png"
    }, option);
    if (state.isCanvasMode && canvas) {
      const dataUrl = canvasToDataUrl(canvas, opt, { width, height });
      callback == null ? void 0 : callback.bind(this)(dataUrl);
      return dataUrl;
    }
    const svgDataUrl = nodeToSvgDataUrl(chart.node(), opt, { width, height });
    const glyph = opt.preserveFontStyle ? getGlyph(svg.node()) : [];
    if (callback && isFunction(callback)) {
      const img = new Image();
      img.crossOrigin = "Anonymous";
      img.onload = () => {
        const canvas2 = browser_doc.createElement("canvas");
        const ctx = canvas2.getContext("2d");
        canvas2.width = opt.width || width;
        canvas2.height = opt.height || height;
        ctx.drawImage(img, 0, 0);
        if (glyph.length) {
          renderText(ctx, glyph);
          glyph.length = 0;
        }
        callback.bind(this)(canvas2.toDataURL(opt.mimeType));
      };
      img.src = svgDataUrl;
    }
    return svgDataUrl;
  }
});

;// ./src/config/resolver/export.ts


let exportApi = () => {
  Chart.prototype.export = api_export.export;
  return (exportApi = () => ({}))();
};

;// ./src/Chart/api/flow.ts

/* harmony default export */ var flow = ({
  /**
   * Flow data to the chart.<br><br>
   * By this API, you can append new data points to the chart.
   * @function flow
   * @instance
   * @memberof Chart
   * @param {object} args The object can consist with following members:<br>
   *
   *    | Key | Type | Description |
   *    | --- | --- | --- |
   *    | json | Object | Data as JSON format (@see [data․json](Options.html#.data%25E2%2580%25A4json)) |
   *    | rows | Array | Data in array as row format (@see [data․rows](Options.html#.data%25E2%2580%25A4json)) |
   *    | columns | Array | Data in array as column format (@see [data․columns](Options.html#.data%25E2%2580%25A4columns)) |
   *    | to | String | The lower x edge will move to that point. If not given, the lower x edge will move by the number of given data points |
   *    | length | Number | The lower x edge will move by the number of this argument |
   *    | duration | Number | The duration of the transition will be specified value. If not given, transition.duration will be used as default |
   *    | done | Function | The specified function will be called when flow ends |
   *
   * - **NOTE:**
   *   - If json, rows and columns given, the data will be loaded.
   *   - If data that has the same target id is given, the chart will be appended.
   *   - Otherwise, new target will be added. One of these is required when calling.
   *   - If json specified, keys is required as well as data.json.
   * 	 - If tab isn't visible(by evaluating `document.hidden`), will not be executed to prevent unnecessary work.
   * @example
   * // 2 data points will be appended to the tail and popped from the head.
   * // After that, 4 data points will be appended and no data points will be poppoed.
   * chart.flow({
   *  columns: [
   *    ["x", "2018-01-11", "2018-01-21"],
   *    ["data1", 500, 200],
   *    ["data2", 100, 300],
   *    ["data3", 200, 120]
   *  ],
   *  to: "2013-01-11",
   *  done: function () {
   *    chart.flow({
   *      columns: [
   *        ["x", "2018-02-11", "2018-02-12", "2018-02-13", "2018-02-14"],
   *        ["data1", 200, 300, 100, 250],
   *        ["data2", 100, 90, 40, 120],
   *        ["data3", 100, 100, 300, 500]
   *      ],
   *      length: 2,
   *      duration: 1500
   *    });
   *  }
   * });
   */
  flow(args) {
    const $$ = this.internal;
    let data;
    if (args.json || args.rows || args.columns) {
      $$.convertData(args, (res) => {
        data = res;
        _();
      });
    }
    function _() {
      var _a, _b, _c;
      let domain;
      let length = 0;
      let tail = 0;
      let diff;
      let to;
      if ($$.state.redrawing || !data || !isTabVisible()) {
        return;
      }
      (_a = $$.flushCanvasFlow) == null ? void 0 : _a.call($$);
      const notfoundIds = [];
      const orgDataCount = $$.getMaxDataCount();
      const targets = $$.convertDataToTargets(data, true);
      const isTimeSeries = $$.axis.isTimeSeries();
      $$.data.targets.forEach((t) => {
        let found = false;
        for (let i = 0; i < targets.length; i++) {
          if (t.id === targets[i].id) {
            found = true;
            if (t.values[t.values.length - 1]) {
              tail = t.values[t.values.length - 1].index + 1;
            }
            const values = targets[i].values;
            length = values.length;
            for (let j = 0; j < length; j++) {
              values[j].index = tail + j;
              if (!isTimeSeries) {
                values[j].x = tail + j;
              }
              t.values.push(values[j]);
            }
            targets.splice(i, 1);
            break;
          }
        }
        !found && notfoundIds.push(t.id);
      });
      $$.data.targets.forEach((t) => {
        for (let i = 0; i < notfoundIds.length; i++) {
          if (t.id === notfoundIds[i]) {
            if (!t.values[t.values.length - 1]) {
              continue;
            }
            tail = t.values[t.values.length - 1].index + 1;
            for (let j = 0; j < length; j++) {
              t.values.push({
                id: t.id,
                index: tail + j,
                x: isTimeSeries ? $$.getOtherTargetX(tail + j) : tail + j,
                value: null
              });
            }
          }
        }
      });
      if ($$.data.targets.length) {
        targets.forEach((t) => {
          const firstIndex = $$.data.targets[0].values[0].index;
          const values = t.values;
          const valueLength = values.length;
          const missingLength = Math.max(tail - firstIndex, 0);
          if (missingLength) {
            values.length = valueLength + missingLength;
            for (let i = valueLength - 1; i >= 0; i--) {
              values[i + missingLength] = values[i];
            }
            for (let i = 0; i < missingLength; i++) {
              const index = firstIndex + i;
              values[i] = {
                id: t.id,
                index,
                x: isTimeSeries ? $$.getOtherTargetX(index) : index,
                value: null
              };
            }
          }
          for (let i = missingLength; i < values.length; i++) {
            const v = values[i];
            v.index += tail;
            if (!isTimeSeries) {
              v.x += tail;
            }
          }
        });
      }
      for (let i = 0; i < targets.length; i++) {
        $$.data.targets.push(targets[i]);
      }
      const baseTarget = $$.data.targets[0];
      const baseValue = baseTarget.values[0];
      if (isDefined(args.to)) {
        length = 0;
        to = isTimeSeries ? parseDate.call($$, args.to) : args.to;
        baseTarget.values.forEach((v) => {
          v.x < to && length++;
        });
      } else if (isDefined(args.length)) {
        length = args.length;
      }
      if (!orgDataCount) {
        if (isTimeSeries) {
          diff = baseTarget.values.length > 1 ? baseTarget.values[baseTarget.values.length - 1].x - baseValue.x : baseValue.x - $$.getXDomain($$.data.targets)[0];
        } else {
          diff = 1;
        }
        domain = [baseValue.x - diff, baseValue.x];
      } else if (orgDataCount === 1 && isTimeSeries) {
        diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
        domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
      }
      domain && $$.updateXDomain(null, true, true, false, domain);
      if ($$.state.isCanvasMode) {
        const duration = isValue(args.duration) ? args.duration : $$.config.transition_duration;
        const animated = (_b = $$.animateCanvasFlow) == null ? void 0 : _b.call($$, {
          done: args.done,
          duration,
          length,
          orgDataCount
        });
        if (animated) {
          return;
        }
        if (length && orgDataCount) {
          $$.data.targets.forEach((d) => {
            d.values.splice(0, length);
          });
        }
        $$.state.dirty.data = true;
        $$.state._eventRectFingerprint = null;
        $$.redraw({
          withLegend: true,
          withTransition: false,
          withTrimXDomain: false,
          withUpdateOrgXDomain: true,
          withUpdateXAxis: true,
          withUpdateXDomain: true
        });
        $$.updateTypesElements();
        (_c = args.done) == null ? void 0 : _c.call($$.api);
        return;
      }
      $$.updateTargets($$.data.targets);
      $$.state.dirty.data = true;
      $$.state._eventRectFingerprint = null;
      $$.redraw({
        flow: {
          index: baseValue.index,
          length,
          duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
          done: args.done,
          orgDataCount
        },
        withLegend: true,
        withTransition: orgDataCount > 1,
        withTrimXDomain: false,
        withUpdateXAxis: true
      });
    }
  }
});

;// ./src/ChartInternal/interactions/flow.ts



/* harmony default export */ var interactions_flow = ({
  /**
   * Generate flow
   * @param {object} args option object
   * @returns {function}
   * @private
   */
  generateFlow(args) {
    const $$ = this;
    const { data, state, $el } = $$;
    return function() {
      var _a;
      const flowLength = args.flow.length;
      state.flowing = true;
      data.targets.forEach((d) => {
        d.values.splice(0, flowLength);
      });
      state.dataGeneration++;
      if ($$.updateXGrid) {
        $$.updateXGrid(true);
      }
      const elements = {};
      [
        "axis.x",
        "grid.x",
        "gridLines.x",
        "region.list",
        "text",
        "bar",
        "line",
        "area",
        "circle"
      ].forEach((v) => {
        const name = v.split(".");
        let node = $el[name[0]];
        if (node && name.length > 1) {
          node = node[name[1]];
        }
        if (node == null ? void 0 : node.size()) {
          elements[v] = node;
        }
      });
      (_a = $$.hideGridFocus) == null ? void 0 : _a.call($$);
      $$.setFlowList(elements, args);
    };
  },
  /**
   * Set flow list
   * @param {object} elements Target elements
   * @param {object} args option object
   * @private
   */
  setFlowList(elements, args) {
    const $$ = this;
    const { flow, targets } = args;
    const {
      duration = args.duration,
      index: flowIndex,
      length: flowLength,
      orgDataCount
    } = flow;
    const transform = $$.getFlowTransform(targets, orgDataCount, flowIndex, flowLength);
    const wait = generateWait();
    let n;
    wait.add(Object.keys(elements).map((v) => {
      n = elements[v].transition().ease((t) => +t).duration(duration);
      if (v === "axis.x") {
        n = n.call((g) => {
          $$.axis.x.setTransition(g).create(g);
        });
      } else if (v === "region.list") {
        n = n.filter($$.isRegionOnX).attr("transform", transform);
      } else {
        n = n.attr("transform", transform);
      }
      return n;
    }));
    n.call(wait, () => {
      $$.cleanUpFlow(elements, args);
    });
  },
  /**
   * Clean up flow
   * @param {object} elements Target elements
   * @param {object} args option object
   * @private
   */
  cleanUpFlow(elements, args) {
    const $$ = this;
    const { config, state, $el: { svg } } = $$;
    const isRotated = config.axis_rotated;
    const { flow, shape, xv } = args;
    const { cx, cy, xForText, yForText } = shape.pos;
    const {
      done = () => {
      },
      length: flowLength
    } = flow;
    if (flowLength) {
      ["circle", "text", "shape", "eventRect"].forEach((v) => {
        const target = [];
        for (let i = 0; i < flowLength; i++) {
          target.push(`.${config_classes[v]}-${i}`);
        }
        svg.selectAll(`.${config_classes[`${v}s`]}`).selectAll(target).remove();
      });
      svg.select(`.${config_classes.xgrid}`).remove();
    }
    Object.keys(elements).forEach((v) => {
      const n = elements[v];
      if (v !== "axis.x") {
        n.attr("transform", null);
      }
      if (v === "grid.x") {
        n.attr(state.xgridAttr);
      } else if (v === "gridLines.x") {
        n.attr("x1", isRotated ? 0 : xv).attr("x2", isRotated ? state.width : xv);
        n.select("text").attr("x", isRotated ? state.width : 0).attr("y", xv);
      } else if (/^(area|bar|line)$/.test(v)) {
        n.attr("d", shape.type[v]);
      } else if (v === "text") {
        n.attr("x", xForText).attr("y", yForText).style("fill-opacity", $$.opacityForText.bind($$));
      } else if (v === "circle") {
        if ($$.isCirclePoint()) {
          n.attr("cx", cx).attr("cy", cy);
        } else {
          const xFunc = (d) => cx(d) - config.point_r;
          const yFunc = (d) => cy(d) - config.point_r;
          n.attr("x", xFunc).attr("y", yFunc);
        }
      } else if (v === "region.list") {
        n.select("rect").filter($$.isRegionOnX).attr("x", $$.regionX.bind($$)).attr("width", $$.regionWidth.bind($$));
      }
    });
    config.interaction_enabled && $$.redrawEventRect();
    done.call($$.api);
    state.flowing = false;
  },
  /**
   * Get flow transform value
   * @param {object} targets target
   * @param {number} orgDataCount original data count
   * @param {number} flowIndex flow index
   * @param {number} flowLength flow length
   * @returns {string}
   * @private
   */
  getFlowTransform(targets, orgDataCount, flowIndex, flowLength) {
    const $$ = this;
    const { data, scale: { x } } = $$;
    const dataValues = data.targets[0].values;
    let flowStart = $$.getValueOnIndex(dataValues, flowIndex);
    let flowEnd = $$.getValueOnIndex(dataValues, flowIndex + flowLength);
    let translateX;
    const orgDomain = x.domain();
    const domain = $$.updateXDomain(targets, true, true);
    if (!orgDataCount) {
      if (dataValues.length !== 1) {
        translateX = x(orgDomain[0]) - x(domain[0]);
      } else {
        if ($$.axis.isTimeSeries()) {
          flowStart = $$.getValueOnIndex(dataValues, 0);
          flowEnd = $$.getValueOnIndex(dataValues, dataValues.length - 1);
          translateX = x(flowStart.x) - x(flowEnd.x);
        } else {
          translateX = diffDomain(domain) / 2;
        }
      }
    } else if (orgDataCount === 1 || (flowStart == null ? void 0 : flowStart.x) === (flowEnd == null ? void 0 : flowEnd.x)) {
      translateX = x(orgDomain[0]) - x(domain[0]);
    } else {
      translateX = $$.axis.isTimeSeries() ? x(orgDomain[0]) - x(domain[0]) : x((flowStart == null ? void 0 : flowStart.x) || 0) - x(flowEnd.x);
    }
    const scaleX = diffDomain(orgDomain) / diffDomain(domain);
    return `translate(${translateX},0) scale(${scaleX},1)`;
  }
});

;// ./src/config/resolver/flow.ts





let flow_flow = () => {
  extend(ChartInternal.prototype, interactions_flow);
  Chart.prototype.flow = flow.flow;
  return (flow_flow = () => ({}))();
};

;// ./src/Chart/api/grid.ts

function toGrids(grids) {
  return Array.isArray(grids) ? grids : [grids];
}
function redrawCanvasGrid($$) {
  var _a;
  $$.state.canvasShape = null;
  (_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false);
}
function grid(grids, axisId) {
  const $$ = this.internal;
  const { config } = $$;
  const withTransition = config.transition_duration && isTabVisible();
  const gridPropLines = `grid_${axisId}_lines`;
  if (!grids) {
    return config[gridPropLines];
  }
  config[gridPropLines] = toGrids(grids);
  if ($$.state.isCanvasMode) {
    redrawCanvasGrid($$);
    return config[gridPropLines];
  }
  $$.updateGrid();
  $$.redrawGrid(withTransition);
  return config[gridPropLines];
}
function add(grids, axisId) {
  const gridPropLines = `grid_${axisId}_lines`;
  return grid.bind(this)(
    this.internal.config[gridPropLines].concat(grids ? toGrids(grids) : []),
    axisId
  );
}
function remove(grids, isXAxis) {
  var _a;
  const $$ = this.internal;
  if ($$.state.isCanvasMode) {
    const toRemove = ((_a = $$.getGridFilterToRemove) == null ? void 0 : _a.call($$, grids)) || (() => true);
    const gridLines = `grid_${isXAxis ? "x" : "y"}_lines`;
    $$.config[gridLines] = $$.config[gridLines].filter((line) => !toRemove(line));
    redrawCanvasGrid($$);
    return;
  }
  $$.removeGridLines(grids, isXAxis);
}
const xgrids = function(grids) {
  return grid.bind(this)(grids, "x");
};
extend(xgrids, {
  /**
   * Add x grid lines.<br>
   * This API adds new x grid lines instead of replacing like xgrids.
   * @function xgrids․add
   * @instance
   * @memberof Chart
   * @param {Array|object} grids New x grid lines will be added. The format of this argument is the same as grid.x.lines and it's possible to give an Object if only one line will be added.
   * @returns {Array}
   * @example
   *  // Add a new x grid line
   * chart.xgrids.add(
   *   {value: 4, text: "Label 4"}
   * );
   *
   * // Add new x grid lines
   * chart.xgrids.add([
   *   {value: 2, text: "Label 2"},
   *   {value: 4, text: "Label 4"}
   * ]);
   */
  add(grids) {
    return add.bind(this)(grids, "x");
  },
  /**
   * Remove x grid lines.<br>
   * This API removes x grid lines.
   * @function xgrids․remove
   * @instance
   * @memberof Chart
   * @param {object} grids This argument should include value or class. If value is given, the x grid lines that have specified x value will be removed. If class is given, the x grid lines that have specified class will be removed. If args is not given, all of x grid lines will be removed.
   * @param {number} [grids.value] target value
   * @param {string} [grids.class] target class
   * @returns {void}
   * @example
   * // x grid line on x = 2 will be removed
   * chart.xgrids.remove({value: 2});
   *
   * // x grid lines that have 'grid-A' will be removed
   * chart.xgrids.remove({
   *   class: "grid-A"
   * });
   *
   * // all of x grid lines will be removed
   * chart.xgrids.remove();
   */
  remove(grids) {
    return remove.bind(this)(grids, true);
  }
});
const ygrids = function(grids) {
  return grid.bind(this)(grids, "y");
};
extend(ygrids, {
  /**
   * Add y grid lines.<br>
   * This API adds new y grid lines instead of replacing like ygrids.
   * @function ygrids․add
   * @instance
   * @memberof Chart
   * @param {Array|object} grids New y grid lines will be added. The format of this argument is the same as grid.y.lines and it's possible to give an Object if only one line will be added.
   * @returns {object}
   * @example
   *  // Add a new x grid line
   * chart.ygrids.add(
   *   {value: 400, text: "Label 4"}
   * );
   *
   * // Add new x grid lines
   * chart.ygrids.add([
   *   {value: 200, text: "Label 2"},
   *   {value: 400, text: "Label 4"}
   * ]);
   */
  add(grids) {
    return add.bind(this)(grids, "y");
  },
  /**
   * Remove y grid lines.<br>
   * This API removes x grid lines.
   * @function ygrids․remove
   * @instance
   * @memberof Chart
   * @param {object} grids This argument should include value or class. If value is given, the y grid lines that have specified y value will be removed. If class is given, the y grid lines that have specified class will be removed. If args is not given, all of y grid lines will be removed.
   * @param {number} [grids.value] target value
   * @param {string} [grids.class] target class
   * @returns {void}
   * @example
   * // y grid line on y = 200 will be removed
   * chart.ygrids.remove({value: 200});
   *
   * // y grid lines that have 'grid-A' will be removed
   * chart.ygrids.remove({
   *   class: "grid-A"
   * });
   *
   * // all of y grid lines will be removed
   * chart.ygrids.remove();
   */
  remove(grids) {
    return remove.bind(this)(grids, false);
  }
});
/* harmony default export */ var api_grid = ({ xgrids, ygrids });

;// ./src/ChartInternal/internals/grid.ts




const GRID_FOCUS_SELECTOR = `line.${$FOCUS.xgridFocus}:not(.${$FOCUS.xgridFocusContinuous}), line.${$FOCUS.ygridFocus}`;
const _getGridTextAnchor = (d) => isValue(d.position) || "end";
const _getGridTextDx = (d) => d.position === "start" ? 4 : d.position === "middle" ? 0 : -4;
function _getGridFocusEl($$) {
  var _a;
  const { state, $el: { main } } = $$;
  const cached = state._gridFocusEl;
  const mainNode = main.node();
  const cachedNodes = ((_a = cached == null ? void 0 : cached.nodes) == null ? void 0 : _a.call(cached)) || [];
  return cachedNodes.length && cachedNodes.every((node) => mainNode == null ? void 0 : mainNode.contains(node)) ? cached : state._gridFocusEl = main.selectAll(GRID_FOCUS_SELECTOR);
}
function _hideContinuousGridFocus($$) {
  $$.$el.main.select(`line.${$FOCUS.xgridFocusContinuous}`).style("visibility", "hidden");
}
function _getGridTextX(isX, width, height) {
  return (d) => {
    let x = isX ? 0 : width;
    if (d.position === "start") {
      x = isX ? -height : 0;
    } else if (d.position === "middle") {
      x = (isX ? -height : width) / 2;
    }
    return x;
  };
}
function _smoothLines(el, type) {
  if (type === "grid") {
    el.each(function() {
      const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      ["x1", "x2", "y1", "y2"].forEach((v) => g.attr(v, +g.attr(v)));
    });
  }
}
/* harmony default export */ var internals_grid = ({
  hasGrid() {
    const { config } = this;
    return ["x", "y"].some((v) => config[`grid_${v}_show`] || config[`grid_${v}_lines`].length);
  },
  initGrid() {
    const $$ = this;
    $$.hasGrid() && $$.initGridLines();
    $$.initFocusGrid();
  },
  initGridLines() {
    const $$ = this;
    const { config, state: { clip }, $el } = $$;
    if (config.grid_x_lines.length || config.grid_y_lines.length) {
      $el.gridLines.main = $el.main.insert(
        "g",
        `.${$COMMON.chart}${config.grid_lines_front ? " + *" : ""}`
      ).attr("clip-path", clip.pathGrid).attr("class", `${$GRID.grid} ${$GRID.gridLines}`);
      $el.gridLines.main.append("g").attr("class", $GRID.xgridLines);
      $el.gridLines.main.append("g").attr("class", $GRID.ygridLines);
      $el.gridLines.x = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.selectAll)([]);
    }
  },
  updateXGrid(withoutUpdate) {
    const $$ = this;
    const { config, scale, state, $el: { main, grid } } = $$;
    const isRotated = config.axis_rotated;
    const xgridData = $$.generateGridData(config.grid_x_type, scale.x);
    const tickOffset = $$.axis.isCategorized() ? $$.axis.x.tickOffset() : 0;
    const pos = (d) => (scale.zoom || scale.x)(d) + tickOffset * (isRotated ? -1 : 1);
    state.xgridAttr = isRotated ? {
      x1: 0,
      x2: state.width,
      y1: pos,
      y2: pos
    } : {
      x1: pos,
      x2: pos,
      y1: 0,
      y2: state.height
    };
    grid.x = main.select(`.${$GRID.xgrids}`).selectAll(`.${$GRID.xgrid}`).data(xgridData);
    grid.x.exit().remove();
    grid.x = grid.x.enter().append("line").attr("class", $GRID.xgrid).merge(grid.x);
    if (!withoutUpdate) {
      grid.x.each(function() {
        const grid2 = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        Object.keys(state.xgridAttr).forEach((id) => {
          grid2.attr(id, state.xgridAttr[id]);
        });
        grid2.style("opacity", () => +grid2.attr(isRotated ? "y1" : "x1") === (isRotated ? state.height : 0) ? "0" : null);
      });
    }
  },
  updateYGrid() {
    const $$ = this;
    const { axis, config, scale, state, $el: { grid, main } } = $$;
    const isRotated = config.axis_rotated;
    const pos = (d) => scale.y(d);
    const generated = axis.y.getGeneratedTicks(config.grid_y_ticks);
    const gridValues = (generated == null ? void 0 : generated.length) ? generated : $$.scale.y.ticks(config.grid_y_ticks);
    grid.y = main.select(`.${$GRID.ygrids}`).selectAll(`.${$GRID.ygrid}`).data(gridValues);
    grid.y.exit().remove();
    grid.y = grid.y.enter().append("line").attr("class", $GRID.ygrid).merge(grid.y);
    grid.y.attr("x1", isRotated ? pos : 0).attr("x2", isRotated ? pos : state.width).attr("y1", isRotated ? 0 : pos).attr("y2", isRotated ? state.height : pos);
    _smoothLines(grid.y, "grid");
  },
  updateGrid() {
    const $$ = this;
    const { $el: { grid, gridLines } } = $$;
    !gridLines.main && $$.initGridLines();
    grid.main.style("visibility", $$.hasArcType() ? "hidden" : null);
    $$.hideGridFocus();
    $$.updateGridLines("x");
    $$.updateGridLines("y");
  },
  /**
   * Update Grid lines
   * @param {string} type x | y
   * @private
   */
  updateGridLines(type) {
    const $$ = this;
    const { config, $el: { gridLines, main }, $T } = $$;
    const isRotated = config.axis_rotated;
    const isX = type === "x";
    config[`grid_${type}_show`] && $$[`update${type.toUpperCase()}Grid`]();
    let lines = main.select(`.${$GRID[`${type}gridLines`]}`).selectAll(`.${$GRID[`${type}gridLine`]}`).data(config[`grid_${type}_lines`]);
    $T(lines.exit()).style("opacity", "0").remove();
    const gridLine = lines.enter().append("g");
    gridLine.append("line").style("opacity", "0");
    lines = gridLine.merge(lines);
    lines.each(function(d) {
      const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      if (g.select("text").empty() && d.text) {
        g.append("text").style("opacity", "0");
      }
    });
    $T(lines.attr("class", (d) => `${$GRID[`${type}gridLine`]} ${d.class || ""}`.trim()).select("text").attr("text-anchor", _getGridTextAnchor).attr(
      "transform",
      () => isX ? isRotated ? null : "rotate(-90)" : isRotated ? "rotate(-90)" : null
    ).attr("dx", _getGridTextDx).attr("dy", -5)).text(function(d) {
      var _a;
      return (_a = d.text) != null ? _a : this.remove();
    });
    gridLines[type] = lines;
  },
  redrawGrid(withTransition) {
    const $$ = this;
    const {
      config: { axis_rotated: isRotated },
      state: { width, height },
      $el: { gridLines },
      $T
    } = $$;
    const xv = $$.xv.bind($$);
    const yv = $$.yv.bind($$);
    let xLines = gridLines.x.select("line");
    let xTexts = gridLines.x.select("text");
    let yLines = gridLines.y.select("line");
    let yTexts = gridLines.y.select("text");
    xLines = $T(xLines, withTransition).attr("x1", isRotated ? 0 : xv).attr("x2", isRotated ? width : xv).attr("y1", isRotated ? xv : 0).attr("y2", isRotated ? xv : height);
    xTexts = $T(xTexts, withTransition).attr("x", _getGridTextX(!isRotated, width, height)).attr("y", xv);
    yLines = $T(yLines, withTransition).attr("x1", isRotated ? yv : 0).attr("x2", isRotated ? yv : width).attr("y1", isRotated ? 0 : yv).attr("y2", isRotated ? height : yv);
    yTexts = $T(yTexts, withTransition).attr("x", _getGridTextX(isRotated, width, height)).attr("y", yv);
    return [
      xLines.style("opacity", null),
      xTexts.style("opacity", null),
      yLines.style("opacity", null),
      yTexts.style("opacity", null)
    ];
  },
  initFocusGrid() {
    const $$ = this;
    const { config, state, state: { clip }, $el } = $$;
    state._gridFocusEl = null;
    const isFront = config.grid_front;
    const className = `.${isFront && $el.gridLines.main ? $GRID.gridLines : $COMMON.chart}${isFront ? " + *" : ""}`;
    const grid = $el.main.insert("g", className).attr("clip-path", clip.pathGrid).attr("class", $GRID.grid);
    $el.grid.main = grid;
    config.grid_x_show && grid.append("g").attr("class", $GRID.xgrids);
    config.grid_y_show && grid.append("g").attr("class", $GRID.ygrids);
    if (config.axis_tooltip) {
      const axis = grid.append("g").attr("class", "bb-axis-tooltip");
      axis.append("line").attr("class", "bb-axis-tooltip-x");
      axis.append("line").attr("class", "bb-axis-tooltip-y");
    }
    if (config.interaction_enabled && config.grid_focus_show && !config.axis_tooltip) {
      grid.append("g").attr("class", $FOCUS.xgridFocus).append("line").attr("class", $FOCUS.xgridFocus);
      if (config.grid_focus_y && !config.tooltip_grouped) {
        grid.append("g").attr("class", $FOCUS.ygridFocus).append("line").attr("class", $FOCUS.ygridFocus);
      }
      config.subchart_grid_focus_continuous && config.subchart_grid_focus !== false && $el.main.insert("g", className).attr("class", $FOCUS.xgridFocusContinuous).append("line").attr("class", `${$FOCUS.xgridFocus} ${$FOCUS.xgridFocusContinuous}`).style("visibility", "hidden");
    }
  },
  showAxisGridFocus() {
    var _a, _b;
    const $$ = this;
    const { config, format, state: { event, width, height } } = $$;
    const isRotated = config.axis_rotated;
    const [x, y] = getPointer(event, (_a = $$.$el.eventRect) == null ? void 0 : _a.node());
    const pos = { x, y };
    for (const [axis, node] of Object.entries($$.$el.axisTooltip)) {
      const attr = axis === "x" && !isRotated || axis !== "x" && isRotated ? "x" : "y";
      const value = pos[attr];
      let scaleText = (_b = $$.scale[axis]) == null ? void 0 : _b.invert(value);
      if (scaleText) {
        scaleText = axis === "x" && $$.axis.isTimeSeries() ? format.xAxisTick(scaleText) : scaleText == null ? void 0 : scaleText.toFixed(2);
        node == null ? void 0 : node.attr(attr, value).text(scaleText);
      }
    }
    $$.$el.main.selectAll(
      `line.bb-axis-tooltip-x, line.bb-axis-tooltip-y`
    ).style("visibility", null).each(function(d, i) {
      const line = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      if (i === 0) {
        line.attr("x1", x).attr("x2", x).attr("y1", i ? 0 : height).attr("y2", i ? height : 0);
      } else {
        line.attr("x1", i ? 0 : width).attr("x2", i ? width : 0).attr("y1", y).attr("y2", y);
      }
    });
  },
  hideAxisGridFocus() {
    const $$ = this;
    $$.$el.main.selectAll(
      `line.${$AXIS.axisTooltipX}, line.${$AXIS.axisTooltipY}`
    ).style("visibility", "hidden");
    Object.values($$.$el.axisTooltip).forEach((v) => v == null ? void 0 : v.style("display", "none"));
  },
  /**
   * Show grid focus line
   * @param {Array} data Selected data
   * @private
   */
  showGridFocus(data) {
    var _a;
    const $$ = this;
    const { config, state: { width, height } } = $$;
    const isRotated = config.axis_rotated;
    const focusEl = _getGridFocusEl($$);
    const dataToShow = (data || [focusEl.datum()]).filter(
      (d) => d && isValue($$.getBaseValue(d))
    );
    if (!config.tooltip_show || dataToShow.length === 0 || !config.axis_x_forceAsSingle && $$.hasType("bubble") || $$.hasArcType()) {
      return;
    }
    const isEdge = config.grid_focus_edge && !config.tooltip_grouped;
    const xx = $$.xx.bind($$);
    focusEl.style("visibility", null).data(dataToShow.concat(dataToShow)).each(function(d) {
      const el = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      const pos = {
        x: xx(d),
        y: $$.getYScaleById(d.id)(d.value)
      };
      let xy;
      if (el.classed($FOCUS.xgridFocus)) {
        xy = isRotated ? [
          null,
          // x1
          pos.x,
          // y1
          isEdge ? pos.y : width,
          // x2
          pos.x
          // y2
        ] : [
          pos.x,
          isEdge ? pos.y : null,
          pos.x,
          height
        ];
      } else {
        const isY2 = $$.axis.getId(d.id) === "y2";
        xy = isRotated ? [
          pos.y,
          // x1
          isEdge && !isY2 ? pos.x : null,
          // y1
          pos.y,
          // x2
          isEdge && isY2 ? pos.x : height
          // y2
        ] : [
          isEdge && isY2 ? pos.x : null,
          pos.y,
          isEdge && !isY2 ? pos.x : width,
          pos.y
        ];
      }
      ["x1", "y1", "x2", "y2"].forEach((v, i) => el.attr(v, xy[i]));
    });
    _smoothLines(focusEl, "grid");
    (_a = $$.showCircleFocus) == null ? void 0 : _a.call($$, data);
  },
  hideGridFocus(force = false) {
    var _a;
    const $$ = this;
    const { state: { inputType, resizing } } = $$;
    if (force || inputType === "mouse" || !resizing) {
      const focusEl = _getGridFocusEl($$);
      focusEl.style("visibility", "hidden");
      _hideContinuousGridFocus($$);
      (_a = $$.hideCircleFocus) == null ? void 0 : _a.call($$);
    }
  },
  updateGridFocus() {
    var _a;
    const $$ = this;
    const { state: { inputType, width, height, resizing }, $el: { grid } } = $$;
    const xgridFocus = grid.main.select(`line.${$FOCUS.xgridFocus}`);
    if (inputType === "touch") {
      if (xgridFocus.empty()) {
        resizing && ((_a = $$.showCircleFocus) == null ? void 0 : _a.call($$));
      } else {
        $$.showGridFocus();
      }
    } else {
      const isRotated = $$.config.axis_rotated;
      xgridFocus.attr("x1", isRotated ? 0 : -10).attr("x2", isRotated ? width : -10).attr("y1", isRotated ? -10 : 0).attr("y2", isRotated ? -10 : height);
      _hideContinuousGridFocus($$);
    }
    return true;
  },
  generateGridData(type, scale) {
    const $$ = this;
    const tickNum = $$.$el.main.select(`.${$AXIS.axisX}`).selectAll(".tick").size();
    let gridData = [];
    if (type === "year") {
      const xDomain = $$.getXDomain($$.data.targets);
      const [firstYear, lastYear] = xDomain.map((v) => v.getFullYear());
      for (let i = firstYear; i <= lastYear; i++) {
        gridData.push(/* @__PURE__ */ new Date(`${i}-01-01 00:00:00`));
      }
    } else {
      gridData = scale.ticks(AXIS_DEFAULT_TICK_COUNT);
      if (gridData.length > tickNum) {
        gridData = gridData.filter((d) => String(d).indexOf(".") < 0);
      }
    }
    return gridData;
  },
  getGridFilterToRemove(params) {
    return params ? (line) => {
      let found = false;
      (isArray(params) ? params.concat() : [params]).forEach((param) => {
        if ("value" in param && line.value === param.value || "class" in param && line.class === param.class) {
          found = true;
        }
      });
      return found;
    } : () => true;
  },
  removeGridLines(params, forX) {
    const $$ = this;
    const { config, $T } = $$;
    const toRemove = $$.getGridFilterToRemove(params);
    const toShow = (line) => !toRemove(line);
    const classLines = forX ? $GRID.xgridLines : $GRID.ygridLines;
    const classLine = forX ? $GRID.xgridLine : $GRID.ygridLine;
    $T($$.$el.main.select(`.${classLines}`).selectAll(`.${classLine}`).filter(toRemove)).style("opacity", "0").remove();
    const gridLines = `grid_${forX ? "x" : "y"}_lines`;
    config[gridLines] = config[gridLines].filter(toShow);
  }
});

;// ./src/config/Options/common/grid.ts
/* harmony default export */ var common_grid = ({
  /**
   * Set related options
   * @name grid
   * @memberof Options
   * @type {object}
   * @property {boolean} [front=false] Set 'grid & focus lines' to be positioned over grid lines and chart elements.
   * @property {object} x Grid x object
   * @property {boolean} [x.show=false] Show grids along x axis.
   * @property {Array} [x.lines=[]] Show additional grid lines along x axis.<br>
   *  This option accepts array including object that has value, text, position and class. text, position and class are optional. For position, start, middle and end (default) are available.
   *  If x axis is category axis, value can be category name. If x axis is timeseries axis, value can be date string, Date object and unixtime integer.
   * @property {object} y Grid y object
   * @property {boolean} [y.show=false] Show grids along x axis.
   * @property {Array} [y.lines=[]] Show additional grid lines along y axis.<br>
   *  This option accepts array including object that has value, text, position and class.
   * @property {number} [y.ticks=undefined] Number of y grids to be shown.
   * @property {object} focus Grid focus object
   * @property {boolean} [focus.edge=false] Show edged focus grid line.<br>**NOTE:** Available when [`tooltip.grouped=false`](#.tooltip) option is set.
   * @property {boolean} [focus.show=true] Show grid line when focus.
   * @property {boolean} [focus.y=false] Show y coordinate focus grid line.<br>**NOTE:** Available when [`tooltip.grouped=false`](#.tooltip) option is set.
   * @property {object} lines Grid lines object
   * @property {boolean} [lines.front=true] Set grid lines to be positioned over chart elements.
   * @default undefined
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Grid.GridLines)
   * @see [Demo: X Grid Lines](https://naver.github.io/billboard.js/demo/#Grid.OptionalXGridLines)
   * @see [Demo: Y Grid Lines](https://naver.github.io/billboard.js/demo/#Grid.OptionalYGridLines)
   * @example
   * grid: {
   *   x: {
   *     show: true,
   *     lines: [
   *       {value: 2, text: "Label on 2"},
   *       {value: 5, text: "Label on 5", class: "label-5"},
   *       {value: 6, text: "Label on 6", position: "start"}
   *     ]
   *   },
   *   y: {
   *     show: true,
   *     lines: [
   *       {value: 100, text: "Label on 100"},
   *       {value: 200, text: "Label on 200", class: "label-200"},
   *       {value: 300, text: "Label on 300", position: 'middle'}
   *     ],
   *     ticks: 5
   *   },
   *   front: true,
   *   focus: {
   *      show: false,
   *
   *      // Below options are available when 'tooltip.grouped=false' option is set
   *      edge: true,
   *      y: true
   *   },
   *   lines: {
   *      front: false
   *   }
   * }
   */
  grid_x_show: false,
  grid_x_type: "tick",
  grid_x_lines: [],
  grid_y_show: false,
  grid_y_lines: [],
  grid_y_ticks: void 0,
  grid_focus_edge: false,
  grid_focus_show: true,
  grid_focus_y: false,
  grid_front: false,
  grid_lines_front: true
});

;// ./src/config/resolver/grid.ts







let grid_grid = () => {
  extend(ChartInternal.prototype, internals_grid);
  Chart.prototype.xgrids = api_grid.xgrids;
  Chart.prototype.ygrids = api_grid.ygrids;
  Options.setOptions([common_grid]);
  return (grid_grid = () => ({}))();
};

;// ./src/Chart/api/selection.ts



function setSelectionForFocusOnly(isSelection, ids, indices, resetOther) {
  const $$ = this;
  const { config, $el: { main } } = $$;
  const selectionGrouped = config.data_selection_grouped;
  const isSelectable = config.data_selection_isselectable.bind($$.api);
  const targetIds = isDefined(ids) ? [].concat(ids) : null;
  const singleSelection = isSelection && !config.data_selection_multiple;
  let resetDone = !singleSelection;
  const unselect = (circle, d, index) => {
    $$.unselectPoint(circle, d, index);
    circle.interrupt().remove();
  };
  $$.getTargetsToShow().forEach((target) => {
    const { id } = target;
    const isTargetId = selectionGrouped || !targetIds || targetIds.indexOf(id) >= 0;
    const selectedCircles = main.select(
      `.${$SELECT.selectedCircles}${$$.getTargetSelectorSuffix(id)}`
    );
    target.values.forEach((d) => {
      const { index } = d;
      const isTargetIndex = !indices || indices.indexOf(index) >= 0;
      const circle = selectedCircles.selectAll(`.${$SELECT.selectedCircle}-${index}`);
      const isSelected = !circle.empty();
      if (isSelection) {
        if (isTargetId && isTargetIndex && isSelectable(d) && (!isSelected || singleSelection)) {
          if (!resetDone) {
            setSelectionForFocusOnly.call($$, false);
            resetDone = true;
          }
          $$.selectPoint(null, d, index);
        } else if ((!singleSelection || resetDone) && isDefined(resetOther) && resetOther && isSelected) {
          unselect(circle, d, index);
        }
      } else if (isTargetId && isTargetIndex && isSelected) {
        unselect(circle, d, index);
      }
    });
  });
}
function setSelection(isSelection = false, ids, indices, resetOther) {
  var _a;
  const $$ = this;
  const { config, $el: { main } } = $$;
  const selectionGrouped = config.data_selection_grouped;
  const isSelectable = config.data_selection_isselectable.bind($$.api);
  const singleSelection = isSelection && !config.data_selection_multiple;
  let resetDone = !singleSelection;
  if (!config.data_selection_enabled) {
    return;
  }
  if (singleSelection) {
    indices = (indices == null ? void 0 : indices.length) ? [indices[0]] : [0];
    if (!selectionGrouped) {
      const targetIds = isDefined(ids) ? [].concat(ids) : $$.getTargetsToShow().map((t) => t.id);
      ids = targetIds.slice(0, 1);
    }
  }
  if ((_a = $$.isPointFocusOnly) == null ? void 0 : _a.call($$)) {
    setSelectionForFocusOnly.call($$, isSelection, ids, indices, resetOther);
    return;
  }
  main.selectAll(`.${$SHAPE.shapes}`).selectAll(`.${$SHAPE.shape}`).each(function(d) {
    const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
    const { id, index } = d.data ? d.data : d;
    const isTargetId = selectionGrouped || !ids || ids.indexOf(id) >= 0;
    const isTargetIndex = !indices || indices.indexOf(index) >= 0;
    if (shape.classed($LINE.line) || shape.classed($AREA.area)) {
      return;
    }
    const toggle = $$.getToggle(this, d).bind($$);
    const isSelected = shape.classed($SELECT.SELECTED);
    if (isSelection) {
      if (isTargetId && isTargetIndex && isSelectable(d) && (!isSelected || singleSelection)) {
        if (!resetDone) {
          setSelection.call($$, false);
          resetDone = true;
        }
        !shape.classed($SELECT.SELECTED) && toggle(true, shape.classed($SELECT.SELECTED, true), d, index);
      } else if ((!singleSelection || resetDone) && isDefined(resetOther) && resetOther && isSelected) {
        toggle(false, shape.classed($SELECT.SELECTED, false), d, index);
      }
    } else {
      if (isTargetId && isTargetIndex && isSelectable(d) && isSelected) {
        toggle(false, shape.classed($SELECT.SELECTED, false), d, index);
      }
    }
  });
}
/* harmony default export */ var selection = ({
  /**
   * Get selected data points.<br><br>
   * By this API, you can get selected data points information. To use this API, data.selection.enabled needs to be set true.
   * @function selected
   * @instance
   * @memberof Chart
   * @param {string} [targetId] You can filter the result by giving target id that you want to get. If not given, all of data points will be returned.
   * @returns {Array} dataPoint Array of the data points.<br>ex.) `[{x: 1, value: 200, id: "data1", index: 1, name: "data1"}, ...]`
   * @example
   *  // all selected data points will be returned.
   *  chart.selected();
   *  // --> ex.) [{x: 1, value: 200, id: "data1", index: 1, name: "data1"}, ... ]
   *
   *  // all selected data points of data1 will be returned.
   *  chart.selected("data1");
   */
  selected(targetId) {
    var _a, _b;
    const $$ = this.internal;
    const dataPoint = [];
    if ($$.state.isCanvasMode) {
      return ((_a = $$.getCanvasSelectedData) == null ? void 0 : _a.call($$, targetId)) || dataPoint;
    }
    if ((_b = $$.isPointFocusOnly) == null ? void 0 : _b.call($$)) {
      $$.$el.main.selectAll(`.${$SELECT.selectedCircles + $$.getTargetSelectorSuffix(targetId)}`).selectAll(`.${$SELECT.selectedCircle}`).each((d) => dataPoint.push(d));
      return dataPoint;
    }
    $$.$el.main.selectAll(`.${$SHAPE.shapes + $$.getTargetSelectorSuffix(targetId)}`).selectAll(`.${$SHAPE.shape}`).filter(function() {
      return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($SELECT.SELECTED);
    }).each((d) => dataPoint.push(d));
    return dataPoint;
  },
  /**
   * Set data points to be selected. ([`data.selection.enabled`](Options.html#.data%25E2%2580%25A4selection%25E2%2580%25A4enabled) option should be set true to use this method)
   * @function select
   * @instance
   * @memberof Chart
   * @param {string|Array} [ids] id value to get selected.
   * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.
   * @param {boolean} [resetOther] Unselect already selected.
   * @example
   *  // select all data points
   *  chart.select();
   *
   *  // select all from 'data2'
   *  chart.select("data2");
   *
   *  // select all from 'data1' and 'data2'
   *  chart.select(["data1", "data2"]);
   *
   *  // select from 'data1', indices 2 and unselect others selected
   *  chart.select("data1", [2], true);
   *
   *  // select from 'data1', indices 0, 3 and 5
   *  chart.select("data1", [0, 3, 5]);
   */
  select(ids, indices, resetOther) {
    var _a;
    const $$ = this.internal;
    if ($$.state.isCanvasMode) {
      (_a = $$.setCanvasSelection) == null ? void 0 : _a.call($$, true, ids, indices, resetOther);
      return;
    }
    setSelection.bind($$)(true, ids, indices, resetOther);
  },
  /**
   * Set data points to be un-selected.
   * @function unselect
   * @instance
   * @memberof Chart
   * @param {string|Array} [ids] id value to be unselected.
   * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.
   * @example
   *  // unselect all data points
   *  chart.unselect();
   *
   *  // unselect all from 'data1'
   *  chart.unselect("data1");
   *
   *  // unselect from 'data1', indices 2
   *  chart.unselect("data1", [2]);
   */
  unselect(ids, indices) {
    var _a;
    const $$ = this.internal;
    if ($$.state.isCanvasMode) {
      (_a = $$.setCanvasSelection) == null ? void 0 : _a.call($$, false, ids, indices);
      return;
    }
    setSelection.bind($$)(false, ids, indices);
  }
});

;// ./src/ChartInternal/interactions/drag.ts



/* harmony default export */ var drag = ({
  /**
   * Called when dragging.
   * Data points can be selected.
   * @private
   * @param {object} mouse Object
   */
  drag(mouse) {
    const $$ = this;
    const { config, state, $el: { main } } = $$;
    const isSelectionGrouped = config.data_selection_grouped;
    const isSelectable = config.interaction_enabled && config.data_selection_isselectable;
    if ($$.hasArcType() || !config.data_selection_enabled || // do nothing if not selectable
    config.zoom_enabled && !$$.zoom.altDomain || // skip if zoomable because of conflict drag behavior
    !config.data_selection_multiple) {
      return;
    }
    const [sx, sy] = state.dragStart || [0, 0];
    const [mx, my] = mouse;
    const minX = Math.min(sx, mx);
    const maxX = Math.max(sx, mx);
    const minY = isSelectionGrouped ? state.margin.top : Math.min(sy, my);
    const maxY = isSelectionGrouped ? state.height : Math.max(sy, my);
    const executeDrag = () => {
      if (!$$ || !$$.$el || !$$.$el.main) {
        return;
      }
      main.select(`.${$DRAG.dragarea}`).attr("x", minX).attr("y", minY).attr("width", maxX - minX).attr("height", maxY - minY);
      main.selectAll(`.${$SHAPE.shapes}`).selectAll(`.${$SHAPE.shape}`).filter((d) => isSelectable == null ? void 0 : isSelectable.bind($$.api)(d)).each(function(d, i) {
        const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        const isSelected = shape.classed($SELECT.SELECTED);
        const isIncluded = shape.classed($DRAG.INCLUDED);
        let isWithin;
        let toggle;
        if (shape.classed($CIRCLE.circle)) {
          const x = +shape.attr("cx");
          const y = +shape.attr("cy");
          toggle = $$.togglePoint;
          isWithin = minX < x && x < maxX && minY < y && y < maxY;
        } else if (shape.classed($BAR.bar)) {
          const { x, y, width, height } = getPathBox(this);
          toggle = $$.togglePath;
          isWithin = !(maxX < x || x + width < minX) && !(maxY < y || y + height < minY);
        } else {
          return;
        }
        if (isWithin ^ isIncluded) {
          shape.classed($DRAG.INCLUDED, !isIncluded);
          shape.classed($SELECT.SELECTED, !isSelected);
          toggle.call($$, !isSelected, shape, d, i);
        }
      });
    };
    scheduleRAFUpdate($$.state, executeDrag);
  },
  /**
   * Called when the drag starts.
   * Adds and Shows the drag area.
   * @private
   * @param {object} mouse Object
   */
  dragstart(mouse) {
    const $$ = this;
    const { config, state, $el: { main } } = $$;
    if ($$.hasArcType() || !config.data_selection_enabled) {
      return;
    }
    state.dragStart = mouse;
    main.select(`.${$COMMON.chart}`).append("rect").attr("class", $DRAG.dragarea).style("opacity", "0.1");
    $$.setDragStatus(true);
  },
  /**
   * Called when the drag finishes.
   * Removes the drag area.
   * @private
   */
  dragend() {
    const $$ = this;
    const { config, $el: { main }, $T } = $$;
    if ($$.hasArcType() || !config.data_selection_enabled) {
      return;
    }
    $T(main.select(`.${$DRAG.dragarea}`)).style("opacity", "0").remove();
    main.selectAll(`.${$SHAPE.shape}`).classed($DRAG.INCLUDED, false);
    $$.setDragStatus(false);
  }
});

;// ./src/ChartInternal/internals/selection.ts
var selection_defProp = Object.defineProperty;
var selection_defProps = Object.defineProperties;
var selection_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var selection_getOwnPropSymbols = Object.getOwnPropertySymbols;
var selection_hasOwnProp = Object.prototype.hasOwnProperty;
var selection_propIsEnum = Object.prototype.propertyIsEnumerable;
var selection_defNormalProp = (obj, key, value) => key in obj ? selection_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var selection_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (selection_hasOwnProp.call(b, prop))
      selection_defNormalProp(a, prop, b[prop]);
  if (selection_getOwnPropSymbols)
    for (var prop of selection_getOwnPropSymbols(b)) {
      if (selection_propIsEnum.call(b, prop))
        selection_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var selection_spreadProps = (a, b) => selection_defProps(a, selection_getOwnPropDescs(b));




/* harmony default export */ var internals_selection = (selection_spreadProps(selection_spreadValues({}, drag), {
  /**
   * Select a point
   * @param {object} target Target point
   * @param {object} d Data object
   * @param {number} i Index number
   * @private
   */
  selectPoint(target, d, i) {
    const $$ = this;
    const { config, $el: { main }, $T } = $$;
    const isRotated = config.axis_rotated;
    const cx = (isRotated ? $$.circleY : $$.circleX).bind($$);
    const cy = (isRotated ? $$.circleX : $$.circleY).bind($$);
    const r = $$.pointSelectR.bind($$);
    callFn(config.data_onselected, $$.api, d, target == null ? void 0 : target.node());
    $T(main.select(`.${$SELECT.selectedCircles}${$$.getTargetSelectorSuffix(d.id)}`).selectAll(`.${$SELECT.selectedCircle}-${i}`).data([d]).enter().append("circle").attr("class", () => $$.generateClass($SELECT.selectedCircle, i)).attr("cx", cx).attr("cy", cy).attr("stroke", $$.color).attr("r", (d2) => $$.pointSelectR(d2) * 1.4)).attr("r", r);
  },
  /**
   * Unelect a point
   * @param {object} target Target point
   * @param {object} d Data object
   * @param {number} i Index number
   * @private
   */
  unselectPoint(target, d, i) {
    const $$ = this;
    const { config, $el: { main }, $T } = $$;
    callFn(config.data_onunselected, $$.api, d, target == null ? void 0 : target.node());
    $T(main.select(`.${$SELECT.selectedCircles}${$$.getTargetSelectorSuffix(d.id)}`).selectAll(`.${$SELECT.selectedCircle}-${i}`)).attr("r", 0).remove();
  },
  /**
   * Toggles the selection of points
   * @param {boolean} selected whether or not to select.
   * @param {object} target Target object
   * @param {object} d Data object
   * @param {number} i Index number
   * @private
   */
  togglePoint(selected, target, d, i) {
    const method = `${selected ? "" : "un"}selectPoint`;
    this[method](target, d, i);
  },
  /**
   * Select a path
   * @param {object} target Target path
   * @param {object} d Data object
   * @private
   */
  selectPath(target, d) {
    const $$ = this;
    const { config } = $$;
    callFn(config.data_onselected, $$.api, d, target.node());
    if (config.interaction_brighten) {
      target.style("filter", "brightness(1.25)");
    }
  },
  /**
   * Unelect a path
   * @private
   * @param {object} target Target path
   * @param {object} d Data object
   */
  unselectPath(target, d) {
    const $$ = this;
    const { config } = $$;
    callFn(config.data_onunselected, $$.api, d, target.node());
    if (config.interaction_brighten) {
      target.style("filter", null);
    }
  },
  /**
   * Toggles the selection of lines
   * @param {boolean} selected whether or not to select.
   * @param {object} target Target object
   * @param {object} d Data object
   * @param {number} i Index number
   * @private
   */
  togglePath(selected, target, d, i) {
    this[`${selected ? "" : "un"}selectPath`](target, d, i);
  },
  /**
   * Returns the toggle method of the target
   * @param {object} that shape
   * @param {object} d Data object
   * @returns {function} toggle method
   * @private
   */
  getToggle(that, d) {
    const $$ = this;
    return that.nodeName === "path" ? $$.togglePath : $$.isStepType(d) ? () => {
    } : (
      // circle is hidden in step chart, so treat as within the click area
      $$.togglePoint
    );
  },
  /**
   * Toggles the selection of shapes
   * @param {object} that shape
   * @param {object} d Data object
   * @param {number} i Index number
   * @private
   */
  toggleShape(that, d, i) {
    var _a;
    const $$ = this;
    const { config, $el: { main } } = $$;
    if (config.data_selection_enabled && config.data_selection_isselectable.bind($$.api)(d)) {
      const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(that);
      const isSelected = shape.classed($SELECT.SELECTED);
      const toggle = $$.getToggle(that, d).bind($$);
      let toggledShape;
      if (!config.data_selection_multiple) {
        const focusOnly = (_a = $$.isPointFocusOnly) == null ? void 0 : _a.call($$);
        let selector = `.${focusOnly ? $SELECT.selectedCircles : $SHAPE.shapes}`;
        if (config.data_selection_grouped) {
          selector += $$.getTargetSelectorSuffix(d.id);
        }
        main.selectAll(selector).selectAll(
          focusOnly ? `.${$SELECT.selectedCircle}` : `.${$SHAPE.shape}.${$SELECT.SELECTED}`
        ).classed($SELECT.SELECTED, false).each(function(d2) {
          const shape2 = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
          toggledShape = shape2;
          toggle(false, shape2, d2, d2.index);
        });
      }
      if (!toggledShape || toggledShape.node() !== shape.node()) {
        shape.classed($SELECT.SELECTED, !isSelected);
        toggle(!isSelected, shape, d, i);
      }
    }
  }
}));

;// ./src/config/Options/data/selection.ts
/* harmony default export */ var data_selection = ({
  /**
   * Set data selection enabled<br><br>
   * If this option is set true, we can select the data points and get/set its state of selection by API (e.g. select, unselect, selected).
   *  - **NOTE:** for ESM imports, needs to import 'selection' exports and instantiate it by calling `selection()`.
   *    - `enabled: selection()`
   * @name data․selection․enabled
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataSelection)
   * @example
   * data: {
   *    selection: {
   *       enabled: true
   *    }
   * }
   * @example
   * // importing ESM
   * import bb, {selection} from "billboard.js";
   *
   * data: {
   *    selection: {
   *       enabled: selection(),
   *       ...
   *    }
   * }
   */
  data_selection_enabled: false,
  /**
   * Set grouped selection enabled.<br><br>
   * If this option set true, multiple data points that have same x value will be selected by one selection.
   * @name data․selection․grouped
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * data: {
   *    selection: {
   *       grouped: true
   *    }
   * }
   */
  data_selection_grouped: false,
  /**
   * Set a callback for each data point to determine if it's selectable or not.<br><br>
   * The callback will receive d as an argument and it has some parameters like id, value, index. This callback should return boolean.
   * @name data․selection․isselectable
   * @memberof Options
   * @type {function}
   * @default function() { return true; }
   * @example
   * data: {
   *    selection: {
   *       isselectable: function(d) { ... }
   *    }
   * }
   */
  data_selection_isselectable: () => true,
  /**
   * Set multiple data points selection enabled.<br><br>
   * If this option set true, multiple data points can have the selected state at the same time. If false set, only one data point can have the selected state and the others will be unselected when the new data point is selected.
   * @name data․selection․multiple
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * data: {
   *    selection: {
   *       multiple: false
   *    }
   * }
   */
  data_selection_multiple: true,
  /**
   * Enable to select data points by dragging.
   * If this option set true, data points can be selected by dragging.
   * - **NOTE:** If this option set true, scrolling on the chart will be disabled because dragging event will handle the event.
   * @name data․selection․draggable
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * data: {
   *    selection: {
   *       draggable: true
   *   }
   * }
   */
  data_selection_draggable: false,
  /**
   * Set a callback for on data selection.
   * @name data․onselected
   * @memberof Options
   * @type {function}
   * @default function() {}
   * @example
   * data: {
   *     onselected: function(d, element) {
   *        // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
   *        // element - <circle>
   *        ...
   *    }
   * }
   */
  data_onselected: () => {
  },
  /**
   * Set a callback for on data un-selection.
   * @name data․onunselected
   * @memberof Options
   * @type {function}
   * @default function() {}
   * @example
   * data: {
   *     onunselected: function(d, element) {
   *        // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
   *        // element - <circle>
   *        ...
   *    }
   * }
   */
  data_onunselected: () => {
  }
});

;// ./src/config/resolver/interaction/selection.ts







let selectionModule = () => {
  extend(ChartInternal.prototype, internals_selection);
  extend(Chart.prototype, selection);
  Options.setOptions([data_selection]);
  return (selectionModule = () => true)();
};

;// ./src/Chart/api/subchart.ts


const subchart = function(domainValue) {
  var _a, _b;
  const $$ = this.internal;
  const { axis, brush, config, scale: { x, subX }, state } = $$;
  let domain;
  if (state.isCanvasMode) {
    if (config.subchart_show) {
      domain = domainValue;
      if (Array.isArray(domain)) {
        domain = axis.isTimeSeries() ? domain.map((x2) => parseDate.bind($$)(x2)) : domain;
        domain = $$.setCanvasSubchartDomain(domain) || state.domain;
      } else {
        domain = (_a = state.domain) != null ? _a : x.orgDomain();
      }
    }
    return domain;
  }
  if (config.subchart_show) {
    domain = domainValue;
    if (Array.isArray(domain)) {
      if (axis.isTimeSeries()) {
        domain = domain.map((x2) => parseDate.bind($$)(x2));
      }
      const isWithinRange = $$.withinRange(
        domain,
        $$.getZoomDomain("subX", true),
        $$.getZoomDomain("subX")
      );
      if (isWithinRange) {
        state.domain = domain.slice();
        brush.move(
          brush.getSelection(),
          domain.map(subX)
        );
      }
    } else {
      domain = (_b = state.domain) != null ? _b : x.orgDomain();
    }
  }
  return domain;
};
extend(subchart, {
  /**
   * Show subchart
   * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
   * @function subchart․show
   * @instance
   * @memberof Chart
   * @example
   * // for ESM imports, needs to import 'subchart' and must be instantiated first to enable subchart's API.
   * import {subchart} from "billboard.js";
   *
   * const chart = bb.generate({
   *   ...
   *   subchart: {
   *      // need to be instantiated by calling 'subchart()'
   *      enabled: subchart()
   *
   *      // in case don't want subchart to be shown at initialization, instantiate with '!subchart()'
   *      enabled: !subchart()
   *   }
   * });
   *
   * chart.subchart.show();
   */
  show() {
    var _a, _b, _c;
    const $$ = this.internal;
    const { $el: { subchart: subchart2 }, config } = $$;
    const show = config.subchart_show;
    if (!show) {
      if ($$.state.isCanvasMode) {
        (_a = $$.unbindZoomEvent) == null ? void 0 : _a.call($$);
        config.subchart_show = true;
        this.resize();
        return;
      }
      $$.unbindZoomEvent();
      config.subchart_show = !show;
      !subchart2.main && $$.initSubchart();
      let $target = subchart2.main.selectAll(`.${$COMMON.target}`);
      if ($$.data.targets.length !== $target.size()) {
        $$.updateSizes();
        $$.updateTargetsForSubchart($$.data.targets);
        $target = (_b = subchart2.main) == null ? void 0 : _b.selectAll(`.${$COMMON.target}`);
      }
      $target == null ? void 0 : $target.style("opacity", null);
      (_c = subchart2.main) == null ? void 0 : _c.style("display", null);
      this.resize();
    }
  },
  /**
   * Hide generated subchart
   * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
   * @function subchart․hide
   * @instance
   * @memberof Chart
   * @example
   *  chart.subchart.hide();
   */
  hide() {
    var _a;
    const $$ = this.internal;
    const { $el: { subchart: { main } }, config } = $$;
    if ($$.state.isCanvasMode) {
      if (config.subchart_show) {
        config.subchart_show = false;
        this.resize();
        (_a = $$.bindZoomEvent) == null ? void 0 : _a.call($$);
      }
      return;
    }
    if (config.subchart_show && (main == null ? void 0 : main.style("display")) !== "none") {
      config.subchart_show = false;
      main.style("display", "none");
      this.resize();
    }
  },
  /**
   * Toggle the visibility of subchart
   * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
   * @function subchart․toggle
   * @instance
   * @memberof Chart
   * @example
   * // When subchart is hidden, will be shown
   * // When subchart is shown, will be hidden
   * chart.subchart.toggle();
   */
  toggle() {
    const $$ = this.internal;
    const { config } = $$;
    this.subchart[config.subchart_show ? "hide" : "show"]();
  },
  /**
   * Reset subchart selection
   * @function subchart․reset
   * @instance
   * @memberof Chart
   * @example
   * // Reset subchart selection
   * chart.subchart.reset();
   */
  reset() {
    var _a;
    const $$ = this.internal;
    const { brush } = $$;
    if ($$.state.isCanvasMode) {
      (_a = $$.clearCanvasSubchartDomain) == null ? void 0 : _a.call($$, true, false);
      return;
    }
    brush.clear(brush.getSelection());
  }
});
/* harmony default export */ var api_subchart = ({
  subchart
});

;// ./src/ChartInternal/interactions/subchart.ts







const SUBCHART_TYPES = ["bar", "line", "bubble", "candlestick", "scatter"];
const FOCUS_GRID_STYLE_PROPS = [
  "opacity",
  "stroke",
  "stroke-dasharray",
  "stroke-dashoffset",
  "stroke-linecap",
  "stroke-linejoin",
  "stroke-miterlimit",
  "stroke-opacity",
  "stroke-width"
];
function syncSubchartGridFocusStyle($$, line) {
  var _a, _b;
  const source = (_b = (_a = $$.$el.grid) == null ? void 0 : _a.main) == null ? void 0 : _b.select(`line.${config_classes.xgridFocus}`).node();
  if (!source || !win.getComputedStyle) {
    return;
  }
  const style = win.getComputedStyle(source);
  FOCUS_GRID_STYLE_PROPS.forEach((prop) => {
    const value = style.getPropertyValue(prop);
    value && line.style(prop, value);
  });
}
function getFiniteAttr(value, fallback) {
  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : fallback;
}
function showContinuousSubchartGridFocus($$) {
  var _a, _b;
  if (!isContinuousGridFocusEnabled($$)) {
    return false;
  }
  const { config, state, $el } = $$;
  const mainLine = (_b = (_a = $el.grid) == null ? void 0 : _a.main) == null ? void 0 : _b.select(
    `line.${config_classes.xgridFocus}:not(.${config_classes.xgridFocusContinuous})`
  );
  const line = $el.main.select(`line.${config_classes.xgridFocusContinuous}`);
  if (!(mainLine == null ? void 0 : mainLine.node()) || !line.node()) {
    return false;
  }
  const x2 = state.margin2.left - state.margin.left + state.width2;
  const y2 = state.margin2.top - state.margin.top + state.height2;
  syncSubchartGridFocusStyle($$, line);
  config.axis_rotated ? line.attr("x1", getFiniteAttr(mainLine.attr("x1"), 0)).attr("x2", x2).attr("y1", getFiniteAttr(mainLine.attr("y1"), -10)).attr("y2", getFiniteAttr(mainLine.attr("y2"), -10)) : line.attr("x1", getFiniteAttr(mainLine.attr("x1"), -10)).attr("x2", getFiniteAttr(mainLine.attr("x2"), -10)).attr("y1", getFiniteAttr(mainLine.attr("y1"), 0)).attr("y2", y2);
  line.style("visibility", null);
  mainLine.style("visibility", "hidden");
  return true;
}
function hideContinuousSubchartGridFocus($$) {
  var _a;
  (_a = $$.$el.main) == null ? void 0 : _a.select(`line.${config_classes.xgridFocusContinuous}`).style("visibility", "hidden");
}
function getMainPointFromSubchartEvent($$, event, context) {
  const { config, state } = $$;
  const [x, y] = getPointer(event, context);
  const mainCoord = getMainCoordFromSubchartCoord($$, config.axis_rotated ? y : x);
  if (mainCoord === null) {
    return null;
  }
  return config.axis_rotated ? [state.width / 2, mainCoord] : [mainCoord, state.height / 2];
}
function dispatchSubchartEvent($$, type, event, context) {
  var _a, _b;
  const mainEventRect = (_b = (_a = $$.$el.eventRect) == null ? void 0 : _a.node) == null ? void 0 : _b.call(_a);
  if (!mainEventRect) {
    return;
  }
  const point = getMainPointFromSubchartEvent($$, event, context) || [0, 0];
  const rect = getBoundingRect(mainEventRect, true);
  const clientX = rect.left + point[0];
  const clientY = rect.top + point[1];
  const params = {
    bubbles: true,
    cancelable: true,
    screenX: clientX,
    screenY: clientY,
    clientX,
    clientY
  };
  /^touch/.test(type) ? emulateEvent.touch(mainEventRect, type, params) : emulateEvent.mouse(mainEventRect, type, params);
}
/* harmony default export */ var interactions_subchart = ({
  /**
   * Whether subchart brush interaction is enabled.
   * @returns {boolean}
   * @private
   */
  isSubchartBrushEnabled() {
    const { config } = this;
    return config.subchart_show && config.subchart_brush_enabled !== false;
  },
  /**
   * Bind event rect handlers for subchart hover interactions.
   * @param {d3Selection} eventRect Subchart event rect selection
   * @private
   */
  bindSubchartEventRect(eventRect) {
    const $$ = this;
    const { config, state } = $$;
    eventRect.on("mouseover mousemove mouseout touchstart touchmove touchend", null);
    if (!config.interaction_enabled) {
      return;
    }
    if (state.inputType === "mouse") {
      eventRect.on("mouseover mousemove", function(event) {
        if ($$.isSubchartBrushEnabled()) {
          return;
        }
        dispatchSubchartEvent($$, event.type, event, this);
      }).on("mouseout", function(event) {
        if ($$.isSubchartBrushEnabled()) {
          return;
        }
        dispatchSubchartEvent($$, "mouseout", event, this);
      });
    } else if (state.inputType === "touch") {
      eventRect.on("touchstart touchmove touchend", function(event) {
        var _a;
        if ($$.isSubchartBrushEnabled() || ((_a = event.touches) == null ? void 0 : _a.length) > 1) {
          return;
        }
        dispatchSubchartEvent($$, event.type, event, this);
      });
    }
  },
  /**
   * Initialize the brush.
   * @private
   */
  initBrush() {
    const $$ = this;
    const { config, scale, $el: { subchart }, state } = $$;
    const isRotated = config.axis_rotated;
    const height = config.subchart_size_height;
    let lastDomain;
    let lastSelection;
    let timeout;
    $$.brush = (isRotated ? (0,external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_.brushY)() : (0,external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_.brushX)()).handleSize(5);
    $$.brush.on("start brush end", (event) => {
      const { selection, sourceEvent, target, type } = event;
      if (type === "start") {
        $$.state.inputType === "touch" && $$.hideTooltip();
        lastSelection = sourceEvent ? selection : null;
      }
      if (/(start|brush)/.test(type)) {
        type === "brush" && sourceEvent && state.domain && (lastSelection == null ? void 0 : lastSelection.forEach((v, i) => {
          if (v !== selection[i]) {
            state.domain[i] = scale.x.orgDomain()[i];
          }
        }));
        $$.redrawForBrush(type !== "start");
      }
      if (type === "end") {
        lastDomain = scale.x.orgDomain();
      }
      if (target == null ? void 0 : target.handle) {
        if (selection === null) {
          $$.brush.handle.attr("display", "none");
        } else {
          $$.brush.handle.attr("display", null).attr("transform", (d, i) => {
            const pos = [selection[i], height / 2];
            return `translate(${isRotated ? pos.reverse() : pos})`;
          });
        }
      }
    });
    $$.brush.updateResize = function() {
      timeout && clearTimeout(timeout);
      timeout = setTimeout(() => {
        const selection = this.getSelection();
        lastDomain && (0,external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_.brushSelection)(selection.node()) && this.move(selection, lastDomain.map(scale.subX.orgScale()));
      }, 0);
    };
    $$.brush.update = function() {
      var _a;
      const extent = this.extent()();
      if (extent[1].filter((v) => isNaN(v)).length === 0) {
        (_a = subchart.main) == null ? void 0 : _a.select(`.${config_classes.brush}`).call(this);
      }
      return this;
    };
    $$.brush.scale = function(scale2) {
      const h = config.subchart_size_height;
      let extent = $$.axis.getExtent();
      if (!extent && scale2.range) {
        extent = [[0, 0], [scale2.range()[1], h]];
      } else if (isArray(extent)) {
        extent = extent.map((v, i) => [v, i > 0 ? h : i]);
      }
      isRotated && extent[1].reverse();
      this.extent(extent);
      this.update();
    };
    $$.brush.getSelection = () => (
      // @ts-ignore
      subchart.main ? subchart.main.select(`.${config_classes.brush}`) : (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)([])
    );
  },
  /**
   * Initialize the subchart.
   * @private
   */
  initSubchart() {
    const $$ = this;
    const { config, state: { clip, hasAxis }, $el: { defs, svg, subchart, axis } } = $$;
    if (!hasAxis) {
      return;
    }
    const visibility = config.subchart_show ? null : "hidden";
    const clipId = `${clip.id}-subchart`;
    const clipPath = $$.getClipPath(clipId);
    clip.idSubchart = clipId;
    $$.appendClip(defs, clipId);
    $$.initBrush();
    subchart.main = svg.append("g").classed(config_classes.subchart, true).attr("transform", $$.getTranslate("context"));
    const { main } = subchart;
    main.style("visibility", visibility);
    main.append("g").attr("clip-path", clipPath).attr("class", config_classes.chart);
    $$.withSubchartTypeContext(() => {
      SUBCHART_TYPES.forEach((v) => {
        const type = capitalize(/^(bubble|scatter)$/.test(v) ? "circle" : v);
        if ($$.hasType(v) || $$.hasTypeOf(type)) {
          const chart = main.select(`.${config_classes.chart}`);
          const chartClassName = config_classes[`chart${type}s`];
          if (chart.select(`.${chartClassName}`).empty()) {
            chart.append("g").attr("class", chartClassName);
          }
        }
      });
    });
    const brush = main.append("g").attr("clip-path", clipPath).attr("class", config_classes.brush).style("pointer-events", $$.isSubchartBrushEnabled() ? null : "none").call($$.brush);
    config.subchart_showHandle && $$.addBrushHandle(brush);
    subchart.eventRect = main.append("g").attr("clip-path", clipPath).attr("class", `${config_classes.eventRects} ${config_classes.eventRects}-subchart`).style("fill-opacity", "0").style("pointer-events", $$.isSubchartBrushEnabled() ? "none" : "all").append("rect").attr("class", `${config_classes.eventRect} ${config_classes.eventRect}-subchart`).attr("width", $$.state.width2).attr("height", $$.state.height2);
    $$.bindSubchartEventRect(subchart.eventRect);
    main.append("g").attr("clip-path", clipPath).attr("class", config_classes.xgridFocus).append("line").attr("class", config_classes.xgridFocus).style("visibility", "hidden");
    axis.subX = main.append("g").attr("class", config_classes.axisX).attr("transform", $$.getTranslate("subX")).attr("clip-path", config.axis_rotated ? "" : clip.pathXAxis).style("visibility", config.subchart_axis_x_show ? visibility : "hidden");
    axis.subY = main.append("g").attr("class", config_classes.axisY).attr("transform", $$.getTranslate("subY")).style("visibility", config.subchart_axis_y_show ? visibility : "hidden");
    axis.subY2 = main.append("g").attr("class", config_classes.axisY2).attr("transform", $$.getTranslate("subY2")).style("visibility", config.subchart_axis_y2_show ? visibility : "hidden");
  },
  /**
   * Add brush handle
   * Enabled when: subchart.showHandle=true
   * @param {d3Selection} brush Brush selection
   * @private
   */
  addBrushHandle(brush) {
    const $$ = this;
    const { config } = $$;
    const isRotated = config.axis_rotated;
    const initRange = config.subchart_init_range;
    const customHandleClass = "handle--custom";
    const path = SUBCHART_BRUSH_HANDLE_PATH[isRotated ? "y" : "x"];
    $$.brush.handle = brush.selectAll(`.${customHandleClass}`).data(isRotated ? [{ type: "n" }, { type: "s" }] : [{ type: "w" }, { type: "e" }]).enter().append("path").attr("class", customHandleClass).attr("cursor", `${isRotated ? "ns" : "ew"}-resize`).attr("d", (d) => path[/[se]/.test(d.type) ? "end" : "start"]).attr("display", initRange ? null : "none");
  },
  /**
   * Update sub chart
   * @param {object} targets $$.data.targets
   * @private
   */
  updateTargetsForSubchart(targets) {
    var _a;
    const $$ = this;
    const { config, state, $el: { subchart: { main } } } = $$;
    if (config.subchart_show) {
      $$.withSubchartTypeContext(() => {
        SUBCHART_TYPES.filter((v) => $$.hasType(v) || $$.hasTypeOf(capitalize(v))).forEach((v) => {
          const isPointType = /^(bubble|scatter)$/.test(v);
          const name = capitalize(isPointType ? "circle" : v);
          const chartClass = $$.getChartClass(name, true);
          const shapeClass = $$.getClass(isPointType ? "circles" : `${v}s`, true);
          const shapeChart = main.select(`.${config_classes[`chart${`${name}s`}`]}`);
          if (isPointType) {
            const circle = shapeChart.selectAll(`.${config_classes.circles}`).data(targets.filter($$[`is${capitalize(v)}Type`].bind($$))).attr("class", shapeClass);
            circle.exit().remove();
            circle.enter().append("g").attr("class", shapeClass);
          } else {
            const shapeUpdate = shapeChart.selectAll(`.${config_classes[`chart${name}`]}`).attr("class", chartClass).data(targets.filter($$[`is${name}Type`].bind($$)));
            const shapeEnter = shapeUpdate.enter().append("g").style("opacity", "0").attr("class", chartClass).append("g").attr("class", shapeClass);
            shapeUpdate.exit().remove();
            v === "line" && $$.hasTypeOf("Area") && shapeEnter.append("g").attr("class", $$.getClass("areas", true));
          }
        });
      });
      main.selectAll(`.${config_classes.brush} rect`).attr(
        config.axis_rotated ? "width" : "height",
        config.axis_rotated ? state.width2 : state.height2
      );
      (_a = $$.$el.subchart.eventRect) == null ? void 0 : _a.attr("width", state.width2).attr("height", state.height2).style("pointer-events", $$.isSubchartBrushEnabled() ? "none" : "all");
    }
  },
  /**
   * Update subchart y domains using subchart type options.
   * @param {object} targets Targets to show
   * @private
   */
  updateSubchartYDomain(targets) {
    var _a, _b;
    const $$ = this;
    const { scale } = $$;
    const targetsToShow = targets || $$.filterTargetsToShow($$.data.targets);
    (_a = scale.subY) == null ? void 0 : _a.domain($$.getYDomain(targetsToShow, "y"));
    (_b = scale.subY2) == null ? void 0 : _b.domain($$.getYDomain(targetsToShow, "y2"));
  },
  /**
   * Redraw subchart.
   * @private
   * @param {boolean} withSubchart whether or not to show subchart
   * @param {number} duration duration
   */
  redrawSubchart(withSubchart, duration) {
    var _a, _b, _c, _d;
    const $$ = this;
    const { config, $el: { subchart: { main } }, state } = $$;
    const withTransition = !!duration;
    main.style("visibility", config.subchart_show ? null : "hidden");
    main.select(`.${config_classes.brush}`).style("pointer-events", $$.isSubchartBrushEnabled() ? null : "none");
    (_a = $$.$el.subchart.eventRect) == null ? void 0 : _a.style("pointer-events", $$.isSubchartBrushEnabled() ? "none" : "all");
    (_b = $$.$el.axis.subY) == null ? void 0 : _b.style("visibility", config.subchart_axis_y_show ? null : "hidden");
    (_c = $$.$el.axis.subY2) == null ? void 0 : _c.style("visibility", config.subchart_axis_y2_show ? null : "hidden");
    if (config.subchart_show) {
      if (((_d = state.event) == null ? void 0 : _d.type) === "zoom") {
        $$.brush.update();
      }
      if (withSubchart) {
        const initRange = config.subchart_init_range;
        !brushEmpty($$) && $$.brush.update();
        $$.withSubchartTypeContext(() => {
          const targetsToShow = state._targetsToShow || $$.filterTargetsToShow($$.data.targets);
          $$.updateSubchartYDomain(targetsToShow);
          const subchartShape = $$.getDrawShape();
          Object.keys(subchartShape.type).forEach((v) => {
            const name = capitalize(v);
            const drawFn = $$[`generateDraw${name}`](subchartShape.indices[v], true);
            $$[`update${name}`](withTransition, true);
            $$[`redraw${name}`](drawFn, withTransition, true);
          });
          if ($$.hasType("bubble") || $$.hasType("scatter")) {
            const { cx } = subchartShape.pos;
            const cy = $$.updateCircleY(true);
            $$.updateCircle(true);
            $$.redrawCircle(cx, cy, withTransition, void 0, true);
          }
        });
        if (!state.rendered && initRange) {
          state.domain = initRange;
          $$.brush.move(
            $$.brush.getSelection(),
            initRange.map($$.scale.x)
          );
        }
      }
    }
  },
  /**
   * Show a focus grid line on subchart following main chart focus.
   * @param {Array} data Selected data
   * @private
   */
  showSubchartGridFocus(data) {
    const $$ = this;
    const { config, state, $el: { subchart: { main } } } = $$;
    if (!main || !config.subchart_show || $$.isSubchartBrushEnabled() || config.grid_focus_show === false || config.subchart_grid_focus === false || !config.tooltip_show || config.axis_tooltip) {
      return;
    }
    const focusData = Array.isArray(data) ? data : [data];
    const focus = focusData.find((d) => d && $$.getBaseValue(d) != null);
    if (!focus) {
      $$.hideSubchartGridFocus();
      return;
    }
    const pos = $$.scale.subX(focus.x);
    if (!Number.isFinite(pos)) {
      $$.hideSubchartGridFocus();
      return;
    }
    const line = main.select(`g.${config_classes.xgridFocus} line.${config_classes.xgridFocus}`);
    if (showContinuousSubchartGridFocus($$)) {
      line.style("visibility", "hidden");
      return;
    }
    syncSubchartGridFocusStyle($$, line);
    config.axis_rotated ? line.attr("x1", 0).attr("x2", state.width2).attr("y1", pos).attr("y2", pos) : line.attr("x1", pos).attr("x2", pos).attr("y1", 0).attr("y2", state.height2);
    line.style("visibility", null);
  },
  /**
   * Hide subchart focus grid line.
   * @private
   */
  hideSubchartGridFocus() {
    var _a;
    hideContinuousSubchartGridFocus(this);
    (_a = this.$el.subchart.main) == null ? void 0 : _a.select(`g.${config_classes.xgridFocus} line.${config_classes.xgridFocus}`).style("visibility", "hidden");
  },
  /**
   * Redraw the brush.
   * @param {boolean} [callCallbck=true] Call 'onbrush' callback or not.
   * @private
   */
  redrawForBrush(callCallbck = true) {
    var _a;
    const $$ = this;
    const {
      config: {
        subchart_onbrush: onBrush,
        zoom_rescale: withY
      },
      scale,
      state
    } = $$;
    $$.redraw({
      withTransition: false,
      withY,
      withSubchart: false,
      withUpdateXDomain: true,
      withDimension: false
    });
    callCallbck && state.rendered && onBrush.bind($$.api)((_a = state.domain) != null ? _a : scale.x.orgDomain());
  },
  /**
   * Transform context
   * @param {boolean} withTransition indicates transition is enabled
   * @param {object} transitions The return value of the generateTransitions method of Axis.
   * @private
   */
  transformContext(withTransition, transitions) {
    const $$ = this;
    const { $el: { subchart }, $T } = $$;
    const subXAxis = (transitions == null ? void 0 : transitions.axisSubX) ? transitions.axisSubX : $T(subchart.main.select(`.${config_classes.axisX}`), withTransition);
    const subYAxis = (transitions == null ? void 0 : transitions.axisSubY) ? transitions.axisSubY : $T(subchart.main.select(`.${config_classes.axisY}`), withTransition);
    const subY2Axis = (transitions == null ? void 0 : transitions.axisSubY2) ? transitions.axisSubY2 : $T(subchart.main.select(`.${config_classes.axisY2}`), withTransition);
    subchart.main.attr("transform", $$.getTranslate("context"));
    subXAxis.attr("transform", $$.getTranslate("subX"));
    subYAxis.attr("transform", $$.getTranslate("subY"));
    subY2Axis.attr("transform", $$.getTranslate("subY2"));
  }
});

;// ./src/config/Options/interaction/subchart.ts
/* harmony default export */ var interaction_subchart = ({
  /**
   * Set subchart options.
   * - **NOTE:** Not supported for non-Axis based(pie, donut, gauge, radar) types.
   * @name subchart
   * @memberof Options
   * @type {object}
   * @property {object} subchart Subchart object
   * @property {boolean} [subchart.show=false] Show sub chart on the bottom of the chart.
   *  - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
   *    - `show: subchart()`
   * @property {string} [subchart.type] Set chart type for the subchart. Defaults to data.type.
   * @property {object} [subchart.types] Set chart type for each data in the subchart. Defaults to data.types.
   * @property {boolean} [subchart.brush.enabled=true] Enable subchart brush interaction.
   * @property {boolean} [subchart.showHandle=false] Show sub chart's handle.
   * @property {boolean|object} [subchart.grid.focus=true] Show x focus grid line in subchart when subchart brush is disabled.
   * @property {boolean} [subchart.grid.focus.continuous=false] Render x focus grid line as one continuous line across main chart and subchart when subchart brush is disabled.
   * @property {boolean} [subchart.axis.x.show=true] Show or hide x axis.
   * @property {boolean} [subchart.axis.x.tick.show=true] Show or hide x axis tick line.
   * @property {number} [subchart.axis.x.tick.count] Set the number of x axis ticks.
   * @property {Array|function} [subchart.axis.x.tick.values] Set x axis tick values manually.
   * @property {boolean|object} [subchart.axis.x.tick.culling] Setting for culling x axis ticks.
   * @property {number} [subchart.axis.x.tick.culling.max] The number of x axis tick texts will be adjusted to less than this value.
   * @property {boolean} [subchart.axis.x.tick.culling.lines=true] Control x axis tick line visibility within culling option.
   * @property {boolean} [subchart.axis.x.tick.culling.reverse=false] Control x axis culling start point to be reversed.
   * @property {boolean} [subchart.axis.x.tick.outer] Show or hide x axis outer tick.
   * @property {function|string} [subchart.axis.x.tick.format] Use custom format for x axis ticks - see [axis.x.tick.format](#.axis․x․tick․format) for details.
   * @property {boolean} [subchart.axis.x.tick.text.show=true] Show or hide x axis tick text.
   * @property {boolean} [subchart.axis.y.show=false] Show or hide y axis.
   * @property {boolean} [subchart.axis.y.tick.show=true] Show or hide y axis tick line.
   * @property {number} [subchart.axis.y.tick.count] Set the number of y axis ticks.
   * @property {Array|function} [subchart.axis.y.tick.values] Set y axis tick values manually.
   * @property {boolean|object} [subchart.axis.y.tick.culling] Setting for culling y axis ticks.
   * @property {number} [subchart.axis.y.tick.culling.max] The number of y axis tick texts will be adjusted to less than this value.
   * @property {boolean} [subchart.axis.y.tick.culling.lines=true] Control y axis tick line visibility within culling option.
   * @property {boolean} [subchart.axis.y.tick.culling.reverse=false] Control y axis culling start point to be reversed.
   * @property {boolean} [subchart.axis.y.tick.outer] Show or hide y axis outer tick.
   * @property {function|string} [subchart.axis.y.tick.format] Use custom format for y axis ticks - see [axis.y.tick.format](#.axis․y․tick․format) for details.
   * @property {boolean} [subchart.axis.y.tick.text.show=true] Show or hide y axis tick text.
   * @property {boolean} [subchart.axis.y2.show=false] Show or hide y2 axis.
   * @property {boolean} [subchart.axis.y2.tick.show=true] Show or hide y2 axis tick line.
   * @property {number} [subchart.axis.y2.tick.count] Set the number of y2 axis ticks.
   * @property {Array|function} [subchart.axis.y2.tick.values] Set y2 axis tick values manually.
   * @property {boolean|object} [subchart.axis.y2.tick.culling] Setting for culling y2 axis ticks.
   * @property {number} [subchart.axis.y2.tick.culling.max] The number of y2 axis tick texts will be adjusted to less than this value.
   * @property {boolean} [subchart.axis.y2.tick.culling.lines=true] Control y2 axis tick line visibility within culling option.
   * @property {boolean} [subchart.axis.y2.tick.culling.reverse=false] Control y2 axis culling start point to be reversed.
   * @property {boolean} [subchart.axis.y2.tick.outer] Show or hide y2 axis outer tick.
   * @property {function|string} [subchart.axis.y2.tick.format] Use custom format for y2 axis ticks - see [axis.y2.tick.format](#.axis․y2․tick․format) for details.
   * @property {boolean} [subchart.axis.y2.tick.text.show=true] Show or hide y2 axis tick text.
   * @property {Array} [subchart.init.range] Set initial selection domain range.
   * @property {number} [subchart.size.height] Change the height of the subchart.
   * @property {function} [subchart.onbrush] Set callback for brush event.<br>
   *  Specified function receives the current zoomed x domain.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Interaction.SubChart)
   * @example
   *  subchart: {
   *      show: true,
   *      showHandle: true,
   *
   *      // render the overview with a different chart type than the main chart
   *      type: "bar",
   *
   *      // override the type per data series
   *      types: {
   *      	data2: "area"
   *      },
   *      size: {
   *          height: 20
   *      },
   *      brush: {
   *      	// disable brush(zoom) interaction, rendering the subchart as a static overview
   *      	enabled: false
   *      },
   *      grid: {
   *      	// set false to hide focus grid line in subchart
   *      	// focus: false,
   *      	focus: {
   *      		// NOTE: works only when 'brush.enabled=false'
   *      		continuous: true
   *      	}
   *      },
   *      init: {
   *          // specify initial range domain selection
   *          range: [1, 2]
   *      },
   *      axis: {
   *      	x: {
   *      	  show: true,
   *      	    tick: {
   *      	      show: true,
   *      	      format: (x) => d3Format(".1f")(x)
   *      	      text: {
   *      	        show: false
   *      	      }
   *      	    }
   *      	},
   *      	y: {
   *      	  show: true,
   *      	    tick: {
   *      	      count: 3
   *      	    }
   *      	}
   *      },
   *      onbrush: function(domain) { ... }
   *  }
   * @example
   * // importing ESM
   * import bb, {subchart} from "billboard.js";
   *
   * subchart: {
   *      show: subchart(),
   *      ...
   * }
   */
  subchart_show: false,
  subchart_type: void 0,
  subchart_types: {},
  subchart_brush_enabled: true,
  subchart_showHandle: false,
  subchart_size_height: 60,
  subchart_grid_focus: true,
  subchart_grid_focus_continuous: false,
  subchart_axis_x_show: true,
  subchart_axis_x_tick_show: true,
  subchart_axis_x_tick_count: void 0,
  subchart_axis_x_tick_values: void 0,
  subchart_axis_x_tick_culling: void 0,
  subchart_axis_x_tick_culling_max: void 0,
  subchart_axis_x_tick_culling_lines: void 0,
  subchart_axis_x_tick_culling_reverse: void 0,
  subchart_axis_x_tick_outer: void 0,
  subchart_axis_x_tick_format: void 0,
  subchart_axis_x_tick_text_show: true,
  subchart_axis_y_show: false,
  subchart_axis_y_tick_show: true,
  subchart_axis_y_tick_count: void 0,
  subchart_axis_y_tick_values: void 0,
  subchart_axis_y_tick_culling: void 0,
  subchart_axis_y_tick_culling_max: void 0,
  subchart_axis_y_tick_culling_lines: void 0,
  subchart_axis_y_tick_culling_reverse: void 0,
  subchart_axis_y_tick_outer: void 0,
  subchart_axis_y_tick_format: void 0,
  subchart_axis_y_tick_text_show: true,
  subchart_axis_y2_show: false,
  subchart_axis_y2_tick_show: true,
  subchart_axis_y2_tick_count: void 0,
  subchart_axis_y2_tick_values: void 0,
  subchart_axis_y2_tick_culling: void 0,
  subchart_axis_y2_tick_culling_max: void 0,
  subchart_axis_y2_tick_culling_lines: void 0,
  subchart_axis_y2_tick_culling_reverse: void 0,
  subchart_axis_y2_tick_outer: void 0,
  subchart_axis_y2_tick_format: void 0,
  subchart_axis_y2_tick_text_show: true,
  subchart_init_range: void 0,
  subchart_onbrush: () => {
  }
});

;// ./src/config/resolver/interaction/subchart.ts







let subchartModule = () => {
  extend(ChartInternal.prototype, interactions_subchart);
  extend(Chart.prototype, api_subchart);
  Options.setOptions([interaction_subchart]);
  return (subchartModule = () => true)();
};

// EXTERNAL MODULE: external {"commonjs":"d3-zoom","commonjs2":"d3-zoom","amd":"d3-zoom","root":"d3"}
var external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_ = __webpack_require__(9);
;// ./src/Chart/api/zoom.ts


const zoom = function(domainValue) {
  var _a, _b;
  const $$ = this.internal;
  const { axis, config, org, scale, state } = $$;
  let domain;
  if (!axis) {
    return void 0;
  }
  const isCategorized = axis.isCategorized();
  if (config.zoom_enabled) {
    domain = domainValue;
    if (Array.isArray(domain)) {
      if (axis.isTimeSeries()) {
        domain = domain.map((x) => parseDate.bind($$)(x));
      }
      const isWithinRange = $$.withinRange(
        domain,
        $$.getZoomDomain("zoom", true),
        $$.getZoomDomain("zoom")
      );
      if (isWithinRange) {
        state.domain = domain.slice();
        domain = $$.getZoomDomainValue(domain);
        $$.api.tooltip.hide();
        if (config.subchart_show) {
          if (state.isCanvasMode) {
            (_a = $$.setCanvasSubchartDomain) == null ? void 0 : _a.call($$, domain, true, false);
          } else {
            const x = scale.zoom || scale.x;
            $$.brush.getSelection().call($$.brush.move, domain.map(x));
          }
        } else {
          const x = isCategorized ? scale.x.orgScale() : org.xScale || scale.x;
          $$.updateCurrentZoomTransform(x, domain);
        }
        $$.setZoomResetButton();
      }
    } else {
      domain = $$.zoom.getDomain();
    }
  }
  return (_b = state.domain) != null ? _b : domain;
};
extend(zoom, {
  /**
   * Enable and disable zooming.
   * @function zoom․enable
   * @instance
   * @memberof Chart
   * @param {string|boolean} enabled Possible string values are "wheel" or "drag". If enabled is true, "wheel" will be used. If false is given, zooming will be disabled.<br>When set to false, the current zooming status will be reset.
   * @example
   *  // Enable zooming using the mouse wheel
   *  chart.zoom.enable(true);
   *  // Or
   *  chart.zoom.enable("wheel");
   *
   *  // Enable zooming by dragging
   *  chart.zoom.enable("drag");
   *
   *  // Disable zooming
   *  chart.zoom.enable(false);
   */
  enable(enabled) {
    var _a;
    const $$ = this.internal;
    const { axis, config } = $$;
    if (!axis) {
      config.zoom_enabled = false;
      return;
    }
    if (/^(drag|wheel)$/.test(enabled)) {
      config.zoom_type = enabled;
    }
    config.zoom_enabled = !!enabled;
    if (!$$.zoom) {
      $$.initZoom();
    } else if (enabled === false) {
      $$.bindZoomEvent(false);
    }
    if (enabled !== false) {
      config.zoom_type === "drag" && !$$.zoomBehaviour && ((_a = $$.initZoomBehaviour) == null ? void 0 : _a.call($$));
      $$.bindZoomEvent();
    }
    $$.updateAndRedraw();
  },
  /**
   * Set or get x Axis maximum zoom range value
   * @function zoom․max
   * @instance
   * @memberof Chart
   * @param {number} [max] maximum value to set for zoom
   * @returns {number} zoom max value
   * @example
   *  // Set maximum range value
   *  chart.zoom.max(20);
   */
  max(max) {
    const $$ = this.internal;
    const { config, org: { xDomain } } = $$;
    if (max === 0 || max) {
      config.zoom_x_max = getMinMax("max", [xDomain[1], max]);
    }
    return config.zoom_x_max;
  },
  /**
   * Set or get x Axis minimum zoom range value
   * @function zoom․min
   * @instance
   * @memberof Chart
   * @param {number} [min] minimum value to set for zoom
   * @returns {number} zoom min value
   * @example
   *  // Set minimum range value
   *  chart.zoom.min(-1);
   */
  min(min) {
    const $$ = this.internal;
    const { config, org: { xDomain } } = $$;
    if (min === 0 || min) {
      config.zoom_x_min = getMinMax("min", [xDomain[0], min]);
    }
    return config.zoom_x_min;
  },
  /**
   * Set zoom range
   * @function zoom․range
   * @instance
   * @memberof Chart
   * @param {object} [range] zoom range
   * @returns {object} zoom range value
   * {
   *   min: 0,
   *   max: 100
   * }
   * @example
   *  chart.zoom.range({
   *      min: 10,
   *      max: 100
   *  });
   */
  range(range) {
    const zoom2 = this.zoom;
    if (isObject(range)) {
      const { min, max } = range;
      isDefined(min) && zoom2.min(min);
      isDefined(max) && zoom2.max(max);
    }
    return {
      min: zoom2.min(),
      max: zoom2.max()
    };
  }
});
/* harmony default export */ var api_zoom = ({
  zoom,
  /**
   * Unzoom zoomed area
   * - **NOTE:** Calling .unzoom() will not trigger zoom events.
   * @function unzoom
   * @instance
   * @memberof Chart
   * @example
   *  chart.unzoom();
   */
  unzoom() {
    var _a;
    const $$ = this.internal;
    const { config, $el: { canvas, eventRect, zoomResetBtn }, scale: { zoom: zoom2 }, state } = $$;
    const target = state.isCanvasMode ? canvas : eventRect;
    if (zoom2 || state.isCanvasMode && config.subchart_show && state.domain) {
      config.subchart_show ? state.isCanvasMode ? (_a = $$.clearCanvasSubchartDomain) == null ? void 0 : _a.call($$, true, false) : $$.brush.getSelection().call($$.brush.move, null) : $$.zoom.updateTransformScale(external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity);
      $$.updateZoom(true);
      zoomResetBtn == null ? void 0 : zoomResetBtn.style("display", "none");
      if ((target == null ? void 0 : target.node()) && (0,external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomTransform)(target.node()) !== external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity) {
        $$.zoom.transform(target, external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity);
      }
      state.domain = void 0;
    }
  }
});

;// ./src/ChartInternal/interactions/zoom.ts





function getZoomTarget($$) {
  return $$.state.isCanvasMode ? $$.$el.canvas : $$.$el.eventRect;
}
function toPlotZoomTransform($$, transform) {
  if (!$$.state.isCanvasMode) {
    return transform;
  }
  const { margin } = $$.state;
  return external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity.translate(
    transform.x + (transform.k - 1) * margin.left,
    transform.y + (transform.k - 1) * margin.top
  ).scale(transform.k);
}
function toCanvasZoomTransform($$, transform) {
  if (!$$.state.isCanvasMode) {
    return transform;
  }
  const { margin } = $$.state;
  return external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity.translate(
    transform.x - (transform.k - 1) * margin.left,
    transform.y - (transform.k - 1) * margin.top
  ).scale(transform.k);
}
function getZoomDragPointer($$, event, element) {
  const pointer = getPointer(event, element);
  if ($$.state.isCanvasMode) {
    const { margin } = $$.state;
    pointer[0] -= margin.left;
    pointer[1] -= margin.top;
  }
  return pointer;
}
/* harmony default export */ var interactions_zoom = ({
  /**
   * Initialize zoom.
   * @private
   */
  initZoom() {
    const $$ = this;
    $$.scale.zoom = null;
    $$.generateZoom();
    $$.config.zoom_type === "drag" && $$.initZoomBehaviour();
  },
  /**
   * Bind zoom event
   * @param {boolean} bind Weather bind or unbound
   * @private
   */
  bindZoomEvent(bind = true) {
    const $$ = this;
    const { config } = $$;
    const zoomEnabled = config.zoom_enabled;
    if (zoomEnabled && bind) {
      !config.subchart_show && $$.bindZoomOnEventRect();
    } else if (bind === false) {
      $$.api.unzoom();
      $$.unbindZoomEvent();
    }
  },
  /**
   * Generate zoom
   * @private
   */
  generateZoom() {
    const $$ = this;
    const { config, org, scale } = $$;
    const zoom = (0,external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoom)().duration(0).on("start", $$.onZoomStart.bind($$)).on("zoom", $$.onZoom.bind($$)).on("end", $$.onZoomEnd.bind($$));
    zoom.orgScaleExtent = () => {
      const extent = config.zoom_extent || [1, 10];
      return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];
    };
    zoom.updateScaleExtent = function() {
      const ratio = diffDomain($$.scale.x.orgDomain()) / diffDomain($$.getZoomDomain());
      const extent = this.orgScaleExtent();
      this.scaleExtent([extent[0] * ratio, extent[1] * ratio]);
      return this;
    };
    zoom.updateTransformScale = (transform, correctTransform) => {
      var _a, _b;
      const isRotated = config.axis_rotated;
      const transformForScale = toPlotZoomTransform($$, transform);
      (_a = org.xScale) == null ? void 0 : _a.range(scale.x.range());
      const newScale = transformForScale[isRotated ? "rescaleY" : "rescaleX"](org.xScale || scale.x);
      if (newScale.domain().some((v) => /(Invalid Date|NaN)/.test(v.toString()))) {
        return;
      }
      const domain = $$.trimXDomain(newScale.domain());
      const rescale = config.zoom_rescale;
      newScale.domain(domain, org.xDomain);
      if (correctTransform) {
        const t = newScale(scale.x.domain()[0]);
        const tX = isRotated ? transformForScale.x : t;
        const tY = isRotated ? t : transformForScale.y;
        const targetTransform = toCanvasZoomTransform(
          $$,
          external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity.translate(tX, tY).scale(transform.k)
        );
        (_b = getZoomTarget($$)) == null ? void 0 : _b.property("__zoom", targetTransform);
      }
      scale.zoom = $$.getCustomizedXScale(newScale);
      $$.axis.x.scale(scale.zoom);
      if (rescale) {
        !org.xScale && (org.xScale = scale.x.copy());
        scale.x.domain(domain);
      } else if (org.xScale) {
        scale.x.domain(org.xScale.domain());
        org.xScale = null;
      }
    };
    zoom.getDomain = () => {
      const domain = scale[scale.zoom ? "zoom" : "subX"].domain();
      const isCategorized = $$.axis.isCategorized();
      if (isCategorized) {
        domain[1] -= 2;
      }
      return domain;
    };
    $$.zoom = zoom;
  },
  /**
   * 'start' event listener
   * @param {object} event Event object
   * @private
   */
  onZoomStart(event) {
    const $$ = this;
    const { sourceEvent } = event;
    if (sourceEvent) {
      $$.zoom.startEvent = sourceEvent;
      $$.state.zooming = true;
      callFn($$.config.zoom_onzoomstart, $$.api, event);
    }
  },
  /**
   * 'zoom' event listener
   * @param {object} event Event object
   * @private
   */
  onZoom(event) {
    const $$ = this;
    const { config, scale, state, org } = $$;
    const { sourceEvent } = event;
    const isUnZoom = (event == null ? void 0 : event.transform) === external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity;
    if (!config.zoom_enabled || $$.filterTargetsToShow($$.data.targets).length === 0 || !scale.zoom && (sourceEvent == null ? void 0 : sourceEvent.type.indexOf("touch")) > -1 && (sourceEvent == null ? void 0 : sourceEvent.touches.length) === 1) {
      return;
    }
    if (event.sourceEvent) {
      state.zooming = true;
      state.domain = void 0;
    }
    const isMousemove = (sourceEvent == null ? void 0 : sourceEvent.type) === "mousemove";
    const isZoomOut = (sourceEvent == null ? void 0 : sourceEvent.wheelDelta) < 0;
    const { transform } = event;
    if (!isMousemove && isZoomOut && scale.x.domain().every((v, i) => v !== org.xDomain[i])) {
      scale.x.domain(org.xDomain);
    }
    $$.zoom.updateTransformScale(transform, config.zoom_type === "wheel" && sourceEvent);
    const doTransition = config.transition_duration > 0 && !config.subchart_show && (state.dragging || isUnZoom || !event.sourceEvent);
    const useRAF = sourceEvent && isMousemove && config.zoom_type !== "wheel";
    const executeRedraw = () => {
      var _a;
      if (!$$.config) {
        return;
      }
      $$.redraw({
        withTransition: doTransition,
        withY: config.zoom_rescale,
        withSubchart: false,
        withEventRect: false,
        withDimension: false
      });
      $$.state.cancelClick = isMousemove;
      !isUnZoom && callFn(
        config.zoom_onzoom,
        $$.api,
        (_a = $$.state.domain) != null ? _a : $$.zoom.getDomain()
      );
    };
    useRAF ? scheduleRAFUpdate($$.state, executeRedraw) : executeRedraw();
  },
  /**
   * 'end' event listener
   * @param {object} event Event object
   * @private
   */
  onZoomEnd(event) {
    var _a, _b;
    const $$ = this;
    const { config, state } = $$;
    const zoom = $$.zoom;
    if (!zoom) {
      return;
    }
    let { startEvent } = zoom;
    let e = event == null ? void 0 : event.sourceEvent;
    const isUnZoom = (event == null ? void 0 : event.transform) === external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity;
    if ((startEvent == null ? void 0 : startEvent.type.indexOf("touch")) > -1) {
      startEvent = startEvent.changedTouches[0];
      e = (_a = e == null ? void 0 : e.changedTouches) == null ? void 0 : _a[0];
    }
    if (config.zoom_type === "drag" && (e && startEvent.clientX === e.clientX && startEvent.clientY === e.clientY)) {
      return;
    }
    state.zooming = false;
    !state.isCanvasMode && $$.redrawEventRect();
    $$.updateZoom();
    !isUnZoom && (e || state.dragging) && callFn(
      config.zoom_onzoomend,
      $$.api,
      (_b = $$.state.domain) != null ? _b : $$.zoom.getDomain()
    );
  },
  /**
   * Update zoom
   * @param {boolean} force Force unzoom
   * @private
   */
  updateZoom(force) {
    const $$ = this;
    const { subX, x, zoom } = $$.scale;
    if (zoom) {
      const zoomDomain = zoom.domain();
      const xDomain = subX.domain();
      const delta = 0.015;
      const isfullyShown = $$.config.axis_x_inverted ? (zoomDomain[0] >= xDomain[0] || zoomDomain[0] + delta >= xDomain[0]) && (xDomain[1] >= zoomDomain[1] || xDomain[1] >= zoomDomain[1] + delta) : (zoomDomain[0] <= xDomain[0] || zoomDomain[0] - delta <= xDomain[0]) && (xDomain[1] <= zoomDomain[1] || xDomain[1] <= zoomDomain[1] - delta);
      if (force || isfullyShown) {
        $$.axis.x.scale(subX);
        x.domain(subX.orgDomain());
        $$.scale.zoom = null;
      }
    }
  },
  /**
   * Set zoom transform to event rect
   * @param {function} x x Axis scale function
   * @param {Array} domain Domain value to be set
   * @private
   */
  updateCurrentZoomTransform(x, domain) {
    var _a;
    const $$ = this;
    const { config } = $$;
    const isRotated = config.axis_rotated;
    const translate = [-x(domain[0]), 0];
    const transform = external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity.scale(x.range()[1] / (x(domain[1]) - x(domain[0]))).translate(
      ...isRotated ? translate.reverse() : translate
    );
    (_a = getZoomTarget($$)) == null ? void 0 : _a.call($$.zoom.transform, toCanvasZoomTransform($$, transform));
  },
  /**
   * Attach zoom event on <rect>
   * @private
   */
  bindZoomOnEventRect() {
    var _a, _b;
    const $$ = this;
    const { config, $el: { svg } } = $$;
    const target = getZoomTarget($$);
    const behaviour = config.zoom_type === "drag" ? $$.zoomBehaviour : $$.zoom;
    $$.state.isCanvasMode && ((_a = behaviour == null ? void 0 : behaviour.touchable) == null ? void 0 : _a.call(behaviour, () => config.interaction_inputType_touch !== false));
    if (!$$.state.isCanvasMode && win.GestureEvent && /^((?!chrome|android|mobile).)*safari/i.test((_b = win.navigator) == null ? void 0 : _b.userAgent)) {
      svg.on("wheel", () => {
      });
    }
    target == null ? void 0 : target.call(behaviour).on("dblclick.zoom", null);
  },
  /**
   * Initialize the drag behaviour used for zooming.
   * @private
   */
  initZoomBehaviour() {
    const $$ = this;
    const { config, state } = $$;
    const isRotated = config.axis_rotated;
    let start = 0;
    let end = 0;
    let zoomRect;
    let extent;
    const prop = {
      axis: isRotated ? "y" : "x",
      attr: isRotated ? "height" : "width",
      index: isRotated ? 1 : 0
    };
    const clampPointer = (v) => {
      const [lo, hi] = extent != null ? extent : [0, isRotated ? state.height : state.width];
      return Math.min(Math.max(v, lo), hi);
    };
    $$.zoomBehaviour = (0,external_commonjs_d3_drag_commonjs2_d3_drag_amd_d3_drag_root_d3_.drag)().touchable(() => !state.isCanvasMode || config.interaction_inputType_touch !== false).clickDistance(4).on("start", function(event) {
      var _a;
      extent = $$.scale.zoom ? null : $$.axis.getExtent();
      state.event = event;
      $$.setDragStatus(true);
      $$.unselectRect();
      if (!state.isCanvasMode && !zoomRect) {
        zoomRect = $$.$el.main.append("rect").attr("clip-path", state.clip.path).attr("class", $ZOOM.zoomBrush).attr("width", isRotated ? state.width : 0).attr("height", isRotated ? 0 : state.height);
      }
      zoomRect == null ? void 0 : zoomRect.attr(
        isRotated ? "width" : "height",
        isRotated ? state.width : state.height
      );
      start = clampPointer(getZoomDragPointer($$, event, this)[prop.index]);
      end = start;
      state.isCanvasMode ? (_a = $$.renderCanvasZoomBrush) == null ? void 0 : _a.call($$, start, end) : zoomRect.attr(prop.axis, start).attr(prop.attr, 0);
      $$.onZoomStart(event);
    }).on("drag", function(event) {
      var _a;
      end = clampPointer(getZoomDragPointer($$, event, this)[prop.index]);
      state.isCanvasMode ? (_a = $$.renderCanvasZoomBrush) == null ? void 0 : _a.call($$, start, end) : zoomRect.attr(prop.axis, Math.min(start, end)).attr(prop.attr, Math.abs(end - start));
    }).on("end", (event) => {
      var _a;
      const scale = $$.scale.zoom || $$.scale.x;
      state.event = event;
      end = clampPointer(end);
      state.isCanvasMode ? (_a = $$.clearCanvasZoomBrush) == null ? void 0 : _a.call($$) : zoomRect.attr(prop.axis, 0).attr(prop.attr, 0);
      if (start > end) {
        [start, end] = [end, start];
      }
      if (start < 0) {
        end += Math.abs(start);
        start = 0;
      }
      if (start !== end) {
        $$.api.zoom([start, end].map((v) => scale.invert(v)));
      }
      $$.setDragStatus(false);
    });
  },
  setZoomResetButton() {
    const $$ = this;
    const { config, $el } = $$;
    const resetButton = config.zoom_resetButton;
    if (resetButton && config.zoom_type === "drag") {
      if (!$el.zoomResetBtn) {
        $el.zoomResetBtn = $$.$el.chart.append("div").classed($COMMON.button, true).append("span").on("click", function() {
          isFunction(resetButton.onclick) && resetButton.onclick.bind($$.api)(this);
          $$.api.unzoom();
        }).classed($ZOOM.buttonZoomReset, true).text(resetButton.text || "Reset Zoom");
      } else {
        $el.zoomResetBtn.style("display", null);
      }
    }
  },
  getZoomTransform() {
    const $$ = this;
    const target = getZoomTarget($$);
    const node = target == null ? void 0 : target.node();
    return node ? toPlotZoomTransform($$, (0,external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomTransform)(node)) : { k: 1 };
  }
});

;// ./src/config/Options/interaction/zoom.ts
/* harmony default export */ var interaction_zoom = ({
  /**
   * Set zoom options
   * @name zoom
   * @memberof Options
   * @type {object}
   * @property {object} zoom Zoom object
   * @property {boolean} [zoom.enabled=false] Enable zooming.
   *  - **NOTE:** for ESM imports, needs to import 'zoom' exports and instantiate it by calling `zoom()`.
   *    - `enabled: zoom()`
   * @property {string} [zoom.type='wheel'] Set zoom interaction type.
   *  - **Available types:**
   *    - wheel
   *    - drag
   * @property {boolean} [zoom.rescale=false] Enable to rescale after zooming.<br>
   *  If true set, y domain will be updated according to the zoomed region.
   * @property {Array} [zoom.extent=[1, 10]] Change zoom extent.
   * @property {number|Date} [zoom.x.min] Set x Axis minimum zoom range
   * @property {number|Date} [zoom.x.max] Set x Axis maximum zoom range
   * @property {function} [zoom.onzoomstart=undefined] Set callback that is called when zooming starts.<br>
   *  Specified function receives the zoom event.
   * @property {function} [zoom.onzoom=undefined] Set callback that is called when the chart is zooming.<br>
   *  Specified function receives the zoomed domain.
   * @property {function} [zoom.onzoomend=undefined] Set callback that is called when zooming ends.<br>
   *  Specified function receives the zoomed domain.
   * @property {boolean|object} [zoom.resetButton=true] Set to display zoom reset button for 'drag' type zoom
   * @property {function} [zoom.resetButton.onclick] Set callback when clicks the reset button. The callback will receive reset button element reference as argument.
   * @property {string} [zoom.resetButton.text='Reset Zoom'] Text value for zoom reset button.
   * @see [Demo:zoom](https://naver.github.io/billboard.js/demo/#Interaction.Zoom)
   * @see [Demo:drag zoom](https://naver.github.io/billboard.js/demo/#Interaction.DragZoom)
   * @example
   *  zoom: {
   *      enabled: true,
   *      type: "drag",
   *      rescale: true,
   *      extent: [1, 100]  // enable more zooming
   *      x: {
   *          min: -1,  // set min range
   *          max: 10  // set max range
   *      },
   *      onzoomstart: function(event) { ... },
   *      onzoom: function(domain) { ... },
   *      onzoomend: function(domain) { ... },
   *
   *      // show reset button when is zoomed-in
   *      resetButton: true,
   *
   *      resetButton: {
   *          // onclick callback when reset button is clicked
   *          onclick: function(button) {
   *            button; // Reset button element reference
   *            ...
   *          },
   *
   *          // customized text value for reset zoom button
   *          text: "Unzoom"
   *      }
   *  }
   * @example
   * // importing ESM
   * import bb, {zoom} from "billboard.js";
   *
   * zoom: {
   *      enabled: zoom(),
   *      ...
   * }
   */
  zoom_enabled: false,
  zoom_type: "wheel",
  zoom_extent: void 0,
  zoom_rescale: false,
  zoom_onzoom: void 0,
  zoom_onzoomstart: void 0,
  zoom_onzoomend: void 0,
  zoom_resetButton: true,
  zoom_x_min: void 0,
  zoom_x_max: void 0
});

;// ./src/config/resolver/interaction/zoom.ts







let zoomModule = () => {
  extend(ChartInternal.prototype, interactions_zoom);
  extend(Chart.prototype, api_zoom);
  Options.setOptions([interaction_zoom]);
  return (zoomModule = () => true)();
};

;// ./src/config/resolver/interaction/index.ts




;// ./src/Chart/api/regions.ts


function redrawCanvasRegions($$) {
  var _a;
  $$.state.canvasShape = null;
  (_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false);
}
function regionsFn(regions2, isAdd = false) {
  const $$ = this.internal;
  const { config } = $$;
  const withTransition = config.transition_duration && isTabVisible();
  if (!regions2) {
    return config.regions;
  }
  config.regions = isAdd ? config.regions.concat(regions2) : regions2;
  if ($$.state.isCanvasMode) {
    redrawCanvasRegions($$);
    return config.regions;
  }
  $$.updateRegion();
  $$.redrawRegion(withTransition);
  return config.regions;
}
const regions = function(regions2) {
  return regionsFn.bind(this)(regions2);
};
extend(regions, {
  /**
   * Add new region.<br><br>
   * This API adds new region instead of replacing like regions.
   * @function regions․add
   * @instance
   * @memberof Chart
   * @param {Array|object} regions New region will be added. The format of this argument is the same as [regions](./Options.html#.regions) and it's possible to give an Object if only one region will be added.
   * @returns {Array} regions
   * @example
   * // Add a new region
   * chart.regions.add(
   *    {
   *      axis: "x", start: 5, class: "regionX",
   *      label: {
   *      	text: "Region Text",
   *      	color: "red"  // color string
   *      }
   *    }
   * );
   *
   * // Add new regions
   * chart.regions.add([
   *    {axis: "x", start: 5, class: "regionX"},
   *    {
   *      axis: "y", end: 50, class: "regionY",
   *      label: {
   *      	text: "Region Text",
   *      	x: 5,  // position relative of the initial x coordinate
   *      	y: 5,  // position relative of the initial y coordinate
   *      	color: "red",  // color string
   *      	rotated: true  // make text to show in vertical or horizontal
   *      }
   *    }
   * ]);
   */
  add: function(regions2) {
    return regionsFn.bind(this)(regions2, true);
  },
  /**
   * Remove regions.<br><br>
   * This API removes regions.
   * @function regions․remove
   * @instance
   * @memberof Chart
   * @param {object} optionsValue This argument should include classes. If classes is given, the regions that have one of the specified classes will be removed. If args is not given, all of regions will be removed.
   * @returns {Array} regions Removed regions
   * @example
   * // regions that have 'region-A' or 'region-B' will be removed.
   * chart.regions.remove({
   *   classes: [
   *     "region-A", "region-B"
   *   ]
   * });
   *
   * // all of regions will be removed.
   * chart.regions.remove();
   */
  remove: function(optionsValue) {
    const $$ = this.internal;
    const { config, $T } = $$;
    const options = optionsValue || {};
    const classes = getOption(options, "classes", [$REGION.region]);
    let regions2 = config.regions;
    if ($$.state.isCanvasMode) {
      if (Object.keys(options).length) {
        regions2 = regions2.filter((region) => {
          let found = false;
          if (!region.class) {
            return true;
          }
          region.class.split(" ").forEach((c) => {
            if (classes.indexOf(c) >= 0) {
              found = true;
            }
          });
          return !found;
        });
        config.regions = regions2;
      } else {
        config.regions = [];
      }
      redrawCanvasRegions($$);
      return config.regions;
    }
    const regionNodes = $$.$el.main.select(`.${$REGION.regions}`).selectAll(classes.map((c) => `.${c}`));
    $T(regionNodes).style("opacity", "0").remove();
    if (Object.keys(options).length) {
      regions2 = regions2.filter((region) => {
        let found = false;
        if (!region.class) {
          return true;
        }
        region.class.split(" ").forEach((c) => {
          if (classes.indexOf(c) >= 0) {
            found = true;
          }
        });
        return !found;
      });
      config.regions = regions2;
    } else {
      config.regions = [];
    }
    return regions2;
  }
});
/* harmony default export */ var api_regions = ({ regions });

;// ./src/ChartInternal/internals/region.ts



/* harmony default export */ var region = ({
  initRegion() {
    const $$ = this;
    const { $el } = $$;
    $el.region.main = $el.main.insert("g", ":first-child").attr("clip-path", $$.state.clip.path).attr("class", $REGION.regions);
  },
  updateRegion() {
    const $$ = this;
    const { config, $el: { region }, $T } = $$;
    if (!region.main) {
      $$.initRegion();
    }
    region.main.style("visibility", $$.hasArcType() ? "hidden" : null);
    const regions = region.main.selectAll(`.${$REGION.region}`).data(config.regions);
    $T(regions.exit()).style("opacity", "0").remove();
    const regionsEnter = regions.enter().append("g");
    regionsEnter.append("rect").style("fill-opacity", "0");
    region.list = regionsEnter.merge(regions).attr("class", $$.classRegion.bind($$));
    region.list.each(function(d) {
      var _a;
      const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      if (g.select("text").empty() && ((_a = d.label) == null ? void 0 : _a.text)) {
        (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).append("text").style("opacity", "0");
      }
    });
  },
  redrawRegion(withTransition) {
    const $$ = this;
    const { $el: { region }, $T } = $$;
    const regionX = $$.regionX.bind($$);
    const regionY = $$.regionY.bind($$);
    const attr = ["width", "height"];
    let regions = region.list.select("rect");
    let label = region.list.selectAll("text");
    regions = $T(regions, withTransition).attr("x", regionX).attr("y", regionY).attr("width", $$.regionWidth.bind($$)).attr("height", $$.regionHeight.bind($$));
    label = $T(label, withTransition).text((d) => {
      var _a;
      return (_a = d.label) == null ? void 0 : _a.text;
    }).attr("transform", ({ label: label2 }) => label2.rotated ? ` rotate(-90)` : null).attr("transform", function(d) {
      var _a;
      const { x = 0, y = 0, center = false, rotated = false } = (_a = d.label) != null ? _a : {};
      const rect = this.previousElementSibling;
      const pos = { x: 0, y: 0 };
      if (isString(center)) {
        ["x", "y"].forEach((v, i) => {
          if (center.indexOf(v) > -1) {
            pos[v] = (+rect.getAttribute(attr[i]) - getBoundingRect(this)[attr[i]]) / 2;
          }
        });
      }
      return `translate(${regionX(d) + pos.x + x}, ${regionY(d) + pos.y + y})${rotated ? ` rotate(-90)` : ``}`;
    }).attr("text-anchor", ({ label: label2 }) => (label2 == null ? void 0 : label2.rotated) ? "end" : null).attr("dy", "1em").style("fill", ({ label: label2 }) => {
      var _a;
      return (_a = label2 == null ? void 0 : label2.color) != null ? _a : null;
    });
    return [
      regions.style("fill-opacity", (d) => isValue(d.opacity) ? d.opacity : null).on("end", function() {
        (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this.parentNode).selectAll("rect:not([x])").remove();
      }),
      label.style("opacity", null)
    ];
  },
  regionX(d) {
    return this.getRegionSize("x", d);
  },
  regionY(d) {
    return this.getRegionSize("y", d);
  },
  regionWidth(d) {
    return this.getRegionSize("width", d);
  },
  regionHeight(d) {
    return this.getRegionSize("height", d);
  },
  /**
   * Get Region size according start/end position
   * @param {string} type Type string
   * @param {ojbect} d Data object
   * @returns {number}
   * @private
   */
  getRegionSize(type, d) {
    const $$ = this;
    const { config, scale, state } = $$;
    const isRotated = config.axis_rotated;
    const isAxisType = /(x|y|y2)/.test(type);
    const isType = isAxisType ? type === "x" : type === "width";
    const start = !isAxisType && $$[isType ? "regionX" : "regionY"](d);
    let key = isAxisType ? "start" : "end";
    let pos = isAxisType ? 0 : state[type];
    let currScale;
    if (d.axis === "y" || d.axis === "y2") {
      if (!isAxisType && !isType) {
        key = "start";
      } else if (isAxisType && !isType) {
        key = "end";
      }
      if ((isType ? isRotated : !isRotated) && key in d) {
        currScale = scale[d.axis];
      }
    } else if ((isType ? !isRotated : isRotated) && key in d) {
      currScale = scale.zoom || scale.x;
    }
    if (currScale) {
      let offset = 0;
      pos = d[key];
      if ($$.axis.isTimeSeries(d.axis)) {
        pos = parseDate.call($$, pos);
      } else if (/(x|width)/.test(type) && $$.axis.isCategorized() && isNaN(pos)) {
        pos = config.axis_x_categories.indexOf(pos);
        offset = $$.axis.x.tickOffset() * (key === "start" ? -1 : 1);
      }
      pos = currScale(pos) + offset;
    }
    return isAxisType ? pos : pos < start ? 0 : pos - start;
  },
  isRegionOnX(d) {
    return !d.axis || d.axis === "x";
  }
});

;// ./src/config/resolver/regions.ts





let regions_regions = () => {
  extend(ChartInternal.prototype, region);
  Chart.prototype.regions = api_regions.regions;
  return (regions_regions = () => ({}))();
};

;// ./src/ChartInternal/shape/area.ts





/* harmony default export */ var shape_area = ({
  initArea(mainLine) {
    const $$ = this;
    const { config } = $$;
    mainLine.insert("g", `.${config.area_front ? $CIRCLE.circles : $LINE.lines}`).attr("class", $$.getClass("areas", true));
  },
  /**
   * Update area color
   * @param {object} d Data object
   * @returns {string} Color string
   * @private
   */
  updateAreaColor(d) {
    const $$ = this;
    return getShapeColorWithGradient.call($$, d, "area_linearGradient", $$.color);
  },
  /**
   * Generate/Update elements
   * @param {boolean} withTransition Transition for exit elements
   * @param {boolean} isSub Subchart draw
   * @private
   */
  updateArea(withTransition, isSub = false) {
    const $$ = this;
    if ($$.state.isCanvasMode) {
      return;
    }
    const { config, state, $el, $T } = $$;
    const $root = isSub ? $el.subchart : $el;
    config.area_linearGradient && $$.updateLinearGradient();
    const area = $root.main.selectAll(`.${$AREA.areas}`).selectAll(`.${$AREA.area}`).data($$.lineData.bind($$));
    $T(area.exit(), withTransition).style("opacity", "0").remove();
    $root.area = area.enter().append("path").attr("class", $$.getClass("area", true)).style("fill", $$.updateAreaColor.bind($$)).style("opacity", function() {
      state.orgAreaOpacity = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).style("opacity");
      return "0";
    }).merge(area);
    area.style("opacity", state.orgAreaOpacity);
    $$.setRatioForGroupedData($root.area.data());
  },
  /**
   * Redraw function
   * @param {function} drawFn Retuned functino from .generateDrawCandlestick()
   * @param {boolean} withTransition With or without transition
   * @param {boolean} isSub Subchart draw
   * @returns {Array}
   */
  redrawArea(drawFn, withTransition, isSub = false) {
    const $$ = this;
    if ($$.state.isCanvasMode) {
      return [];
    }
    const { area } = isSub ? this.$el.subchart : this.$el;
    const { orgAreaOpacity } = $$.state;
    return [
      $$.$T(area, withTransition, getRandom()).attr("d", drawFn).style("fill", $$.updateAreaColor.bind($$)).style(
        "opacity",
        (d) => String($$.isAreaRangeType(d) ? orgAreaOpacity / 1.75 : orgAreaOpacity)
      )
    ];
  },
  /**
   * Generate area path data
   * @param {object} areaIndices Indices
   * @param {boolean} isSub Weather is sub axis
   * @returns {function}
   * @private
   */
  generateDrawArea(areaIndices, isSub) {
    const $$ = this;
    return generateDrawAreaPath($$, areaIndices, isSub);
  }
});

;// ./src/config/Options/shape/area.ts
/* harmony default export */ var Options_shape_area = ({
  /**
   * Set area options
   * @name area
   * @memberof Options
   * @type {object}
   * @property {object} area Area object
   * @property {boolean} [area.above=false] Set background area `above` the data chart line.
   * @property {boolean} [area.below=false] Set background area `below` the data chart line.
   *  - **NOTE**: Can't be used along with `above` option. When above & below options are set to true, `above` will be prioritized.
   * @property {boolean} [area.front=true] Set area node to be positioned over line node.
   * @property {boolean|object} [area.linearGradient=false] Set the linear gradient on area.<br><br>
   * Or customize by giving below object value:
   *  - x {Array}: `x1`, `x2` value (default: `[0, 0]`)
   *  - y {Array}: `y1`, `y2` value (default: `[0, 1]`)
   *  - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.
   *    - (default: `[[0, $DATA_COLOR, 1], [1, $DATA_COLOR, 0]]`)
   * @property {boolean} [area.zerobased=true] Set if min or max value will be 0 on area chart.
   * @see [MDN's &lt;linearGradient>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient), [&lt;stop>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/stop)
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.AreaChart)
   * @see [Demo: above](https://naver.github.io/billboard.js/demo/#AreaChartOptions.Above)
   * @see [Demo: below](https://naver.github.io/billboard.js/demo/#AreaChartOptions.Below)
   * @see [Demo: linearGradient](https://naver.github.io/billboard.js/demo/#AreaChartOptions.LinearGradient)
   * @example
   *  area: {
   *      above: true,
   *      below: false,
   *      zerobased: false,
   *
   *      // <g class='bb-areas'> will be positioned behind the line <g class='bb-lines'> in stacking order
   *      front: false,
   *
   *      // will generate following linearGradient:
   *      // for more info: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
   *      // <linearGradient x1="0" x2="0" y1="0" y2="1">
   *      //    <stop offset="0" stop-color="$DATA_COLOR" stop-opacity="1"></stop>
   *      //    <stop offset="1" stop-color="$DATA_COLOR" stop-opacity="0"></stop>
   *      // </linearGradient>
   *      linearGradient: true,
   *
   *      // Or customized gradient
   *      linearGradient: {
   *      	x: [0, 0],  // x1, x2 attributes
   *      	y: [0, 0],  // y1, y2 attributes
   *      	stops: [
   *      	  // offset, stop-color, stop-opacity
   *      	  [0, "#7cb5ec", 1],
   *
   *      	  // setting 'null' for stop-color, will set its original data color
   *      	  [0.5, null, 0],
   *
   *      	  // setting 'function' for stop-color, will pass data id as argument.
   *      	  // It should return color string or null value
   *      	  [1, function(id) { return id === "data1" ? "red" : "blue"; }, 0],
   *      	]
   *      }
   *  }
   */
  area_above: false,
  area_below: false,
  area_front: true,
  area_linearGradient: false,
  area_zerobased: true
});

;// ./src/config/Options/shape/spline.ts
/* harmony default export */ var spline = ({
  /**
   * Set spline options
   * - **Available interpolation type values:**
   *  - basis (d3.curveBasis)
   *  - basis-closed (d3.curveBasisClosed)
   *  - basis-open (d3.curveBasisOpen)
   *  - bundle (d3.curveBundle)
   *  - cardinal (d3.curveCardinal)
   *  - cardinal-closed (d3.curveCardinalClosed)
   *  - cardinal-open (d3.curveCardinalOpen)
   *  - catmull-rom (d3.curveCatmullRom)
   *  - catmull-rom-closed (d3.curveCatmullRomClosed)
   *  - catmull-rom-open (d3.curveCatmullRomOpen)
   *  - monotone-x (d3.curveMonotoneX)
   *  - monotone-y (d3.curveMonotoneY)
   *  - natural (d3.curveNatural)
   *  - linear-closed (d3.curveLinearClosed)
   *  - linear (d3.curveLinear)
   *  - step (d3.curveStep)
   *  - step-after (d3.curveStepAfter)
   *  - step-before (d3.curveStepBefore)
   * @name spline
   * @memberof Options
   * @type {object}
   * @property {object} spline Spline object
   * @property {object} spline.interpolation Spline interpolation object
   * @property {string} [spline.interpolation.type="cardinal"] Interpolation type
   * @see [Interpolation (d3 v4)](http://bl.ocks.org/emmasaunders/c25a147970def2b02d8c7c2719dc7502)
   * @example
   *  spline: {
   *      interpolation: {
   *          type: "cardinal"
   *      }
   *  }
   */
  spline_interpolation_type: "cardinal"
});

;// ./src/ChartInternal/shape/core/point.ts



function _hasValidPointDrawMethods(point) {
  return isObjectType(point) && isFunction(point.create) && isFunction(point.update);
}
function _insertPointInfoDefs(point, id) {
  var _a;
  const $$ = this;
  const copyAttr = (from, target) => {
    const attribs = from.attributes;
    for (let i = 0, name; name = attribs[i]; i++) {
      name = name.name;
      target.setAttribute(name, from.getAttribute(name));
    }
  };
  const doc = new DOMParser().parseFromString(sanitize(point), "image/svg+xml");
  const node = doc.documentElement;
  const clone = browser_doc.createElementNS(external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.svg, node.nodeName.toLowerCase());
  clone.id = id;
  clone.style.fill = "inherit";
  clone.style.stroke = "inherit";
  copyAttr(node, clone);
  if ((_a = node.childNodes) == null ? void 0 : _a.length) {
    const parent = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(clone);
    if ("innerHTML" in clone) {
      parent.html(sanitize(node.innerHTML));
    } else {
      toArray(node.childNodes).forEach((v) => {
        copyAttr(v, parent.append(v.tagName).node());
      });
    }
  }
  $$.$el.defs.node().appendChild(clone);
}
/* harmony default export */ var point = ({
  /**
   * Check if point type option is valid
   * @param {string} type point type
   * @returns {boolean}
   * @private
   */
  hasValidPointType(type) {
    return /^(circle|rect(angle)?|polygon|ellipse|use)$/i.test(type || this.config.point_type);
  },
  /**
   * Check if pattern point is set to be used on legend
   * @returns {boolean}
   * @private
   */
  hasLegendDefsPoint() {
    var _a;
    const { config } = this;
    return config.legend_show && ((_a = config.point_pattern) == null ? void 0 : _a.length) && config.legend_usePoint;
  },
  getDefsPointId(id) {
    const { state: { datetimeId } } = this;
    return `${datetimeId}-point${id}`;
  },
  /**
   * Get validated point pattern array
   * @returns {Array} Array of point types
   * @private
   */
  getValidPointPattern() {
    const { config } = this;
    const validPointType = /^(circle|rect(angle)?)$/i.test(config.point_type) ? config.point_type : "circle";
    return notEmpty(config.point_pattern) ? config.point_pattern : [validPointType];
  },
  /**
   * Get generate point function
   * @returns {function}
   * @private
   */
  generatePoint() {
    const $$ = this;
    const { $el, config } = $$;
    const ids = [];
    const pattern = $$.getValidPointPattern();
    return function(method, context, ...args) {
      return function(d) {
        var _a, _b, _c, _d;
        const id = $$.getTargetSelectorSuffix(d.id || ((_a = d.data) == null ? void 0 : _a.id) || d);
        const element = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        ids.indexOf(id) < 0 && ids.push(id);
        let point = pattern[ids.indexOf(id) % pattern.length];
        if ($$.hasValidPointType(point)) {
          point = $$[point];
        } else if (!_hasValidPointDrawMethods(point || config.point_type)) {
          const pointId = $$.getDefsPointId(id);
          const defsPoint = $el.defs.select(`#${pointId}`);
          if (defsPoint.size() < 1) {
            _insertPointInfoDefs.call($$, point, pointId);
          }
          if (method === "create") {
            return (_b = $$.custom) == null ? void 0 : _b.create.bind(context)(element, pointId, ...args);
          } else if (method === "update") {
            return (_c = $$.custom) == null ? void 0 : _c.update.bind(context)(element, ...args);
          }
        }
        return (_d = point[method]) == null ? void 0 : _d.bind(context)(element, ...args);
      };
    };
  }
});

;// ./src/ChartInternal/shape/line.ts






function _getStrokeDashArray(start, end, pattern, isLastX = false) {
  const dash = start ? [start, 0] : pattern;
  for (let i = start ? start : pattern.reduce((a, c) => a + c); i <= end; ) {
    pattern.forEach((v) => {
      if (i + v <= end) {
        dash.push(v);
      }
      i += v;
    });
  }
  dash.length % 2 !== 0 && dash.push(isLastX ? pattern[1] : 0);
  return {
    dash: dash.join(" "),
    length: dash.reduce((a, b) => a + b, 0)
  };
}
/* harmony default export */ var line = ({
  initLine() {
    initShapeElement.call(this, {
      elKey: "line",
      className: $LINE.chartLines,
      cssRules: ["pointer-events:none"]
    });
  },
  updateTargetsForLine(t) {
    const $$ = this;
    const { $el: { area, main } } = $$;
    const classLines = $$.getClass("lines", true);
    const targets = t.filter((d) => !($$.isScatterType(d) || $$.isBubbleType(d)));
    const mainLineEnter = updateTargetsForShape.call($$, targets, {
      type: "Line",
      elKey: "line",
      containerClass: $LINE.chartLines,
      itemClass: $LINE.chartLine,
      initFn: $$.initLine
    });
    mainLineEnter.append("g").attr("class", classLines);
    if ($$.hasTypeOf("Area")) {
      const mainLineUpdate = main.select(`.${$LINE.chartLines}`).selectAll(`.${$LINE.chartLine}`);
      const mainLine = (!area && mainLineEnter.empty() ? mainLineUpdate : mainLineEnter).filter($$.isAreaType.bind($$));
      $$.initArea(mainLine);
    }
    $$.updateTargetForCircle(targets, mainLineEnter);
  },
  /**
   * Generate/Update elements
   * @param {boolean} withTransition Transition for exit elements
   * @param {boolean} isSub Subchart draw
   * @private
   */
  updateLine(withTransition, isSub = false) {
    const $$ = this;
    if ($$.state.isCanvasMode) {
      return;
    }
    const { format: { extraLineClasses }, $el, $T } = $$;
    const $root = isSub ? $el.subchart : $el;
    const line = $root.main.selectAll(`.${$LINE.lines}`).selectAll(`.${$LINE.line}`).data($$.lineData.bind($$));
    $T(line.exit(), withTransition).style("opacity", "0").remove();
    $root.line = line.enter().append("path").attr("class", (d) => `${$$.getClass("line", true)(d)} ${extraLineClasses(d) || ""}`).style("stroke", $$.color).merge(line).style("opacity", $$.initialOpacity.bind($$)).attr("transform", null);
  },
  /**
   * Redraw function
   * @param {function} drawFn Retuned functino from .generateDrawCandlestick()
   * @param {boolean} withTransition With or without transition
   * @param {boolean} isSub Subchart draw
   * @returns {Array}
   * @private
   */
  redrawLine(drawFn, withTransition, isSub = false) {
    const $$ = this;
    if ($$.state.isCanvasMode) {
      return [];
    }
    const { $el, $T } = $$;
    const { line } = isSub ? $el.subchart : $el;
    return [
      $T(line, withTransition, getRandom()).attr("d", drawFn).style("stroke", this.color).style("opacity", null)
    ];
  },
  generateDrawLine(lineIndices, isSub) {
    const $$ = this;
    return generateDrawLinePath($$, lineIndices, isSub);
  },
  /**
   * Set regions dasharray and get path
   * @param {Array} d Data object
   * @param {function} x x scale function
   * @param {function} y y scale function
   * @param {object} _regions regions to be set
   * @returns {stirng} Path string
   * @private
   */
  lineWithRegions(d, x, y, _regions) {
    const $$ = this;
    const { config } = $$;
    const isRotated = config.axis_rotated;
    const isTimeSeries = $$.axis.isTimeSeries();
    const dasharray = "2 2";
    const regions = normalizeDataRegions($$, d, _regions);
    const hasNullDataValue = $$.hasNullDataValue(d);
    let xp;
    let yp;
    let diff;
    let diffx2;
    const xValue = isRotated ? (dt) => y(dt.value) : (dt) => x(dt.x);
    const yValue = isRotated ? (dt) => x(dt.x) : (dt) => y(dt.value);
    const generateM = (points) => `M${points[0][0]},${points[0][1]}L${points[1][0]},${points[1][1]}`;
    const sWithRegion = isTimeSeries ? (d0, d1, k, timeseriesDiff) => {
      const x0 = d0.x.getTime();
      const xDiff = d1.x - d0.x;
      const xv0 = new Date(x0 + xDiff * k);
      const xv1 = new Date(x0 + xDiff * (k + timeseriesDiff));
      const points = isRotated ? [[y(yp(k)), x(xv0)], [y(yp(k + diff)), x(xv1)]] : [[x(xv0), y(yp(k))], [x(xv1), y(yp(k + diff))]];
      return generateM(points);
    } : (d0, d1, k, otherDiff) => {
      const x0 = x(d1.x, !isRotated);
      const y0 = y(d1.value, isRotated);
      const gap = k + otherDiff;
      const xValue2 = x(xp(k), !isRotated);
      const yValue2 = y(yp(k), isRotated);
      let xDiff = x(xp(gap), !isRotated);
      let yDiff = y(yp(gap), isRotated);
      if (xDiff > x0) {
        xDiff = x0;
      }
      if (d0.value > d1.value && (isRotated ? yDiff < y0 : yDiff > y0)) {
        yDiff = y0;
      }
      const points = [
        [xValue2, yValue2],
        [xDiff, yDiff]
      ];
      isRotated && points.forEach((v) => v.reverse());
      return generateM(points);
    };
    const axisType = { x: $$.axis.getAxisType("x"), y: $$.axis.getAxisType("y") };
    let path = "";
    if (!d.length) {
      return path;
    }
    const target = $$.$el.line.filter(({ id }) => id === d[0].id);
    const tempNode = target.clone().style("display", "none");
    const getLength = (node, path2) => node.attr("d", path2).node().getTotalLength();
    const dashArray = {
      dash: [],
      lastLength: 0
    };
    let isLastX = false;
    for (let i = 0, data; data = d[i]; i++) {
      const prevData = d[i - 1];
      const hasPrevData = prevData && isValue(prevData.value);
      let style = $$.isWithinRegions(data.x, regions);
      if (!isValue(data.value)) {
        continue;
      }
      if (isUndefined(regions) || !style || !hasPrevData) {
        path += `${i && hasPrevData ? "L" : "M"}${xValue(data)},${yValue(data)}`;
      } else if (hasPrevData) {
        style = ((style == null ? void 0 : style.dasharray) || dasharray).split(" ").map(Number);
        xp = getScale(axisType.x, prevData.x, data.x);
        yp = getScale(axisType.y, prevData.value, data.value);
        if (hasNullDataValue) {
          const dx = x(data.x) - x(prevData.x);
          const dy = y(data.value) - y(prevData.value);
          const dd = Math.sqrt(dx * dx + dy * dy);
          diff = style[0] / dd;
          diffx2 = diff * style[1];
          for (let j = diff; j <= 1; j += diffx2) {
            path += sWithRegion(prevData, data, j, diff);
            if (j + diffx2 >= 1) {
              path += sWithRegion(prevData, data, 1, 0);
            }
          }
        } else {
          let points;
          isLastX = data.x === d[d.length - 1].x;
          if (isTimeSeries) {
            const x0 = +prevData.x;
            const xv0 = new Date(x0);
            const xv1 = new Date(x0 + (+data.x - x0));
            points = [
              [x(xv0), y(yp(0))],
              // M
              [x(xv1), y(yp(1))]
              // L
            ];
          } else {
            points = [
              [x(xp(0)), y(yp(0))],
              // M
              [x(xp(1)), y(yp(1))]
              // L
            ];
          }
          isRotated && points.forEach((v) => v.reverse());
          const startLength = getLength(tempNode, path);
          const endLength = getLength(tempNode, path += `L${points[1].join(",")}`);
          const strokeDashArray = _getStrokeDashArray(
            startLength - dashArray.lastLength,
            endLength - dashArray.lastLength,
            style,
            isLastX
          );
          dashArray.lastLength += strokeDashArray.length;
          dashArray.dash.push(strokeDashArray.dash);
        }
      }
    }
    if (dashArray.dash.length) {
      !isLastX && dashArray.dash.push(getLength(tempNode, path));
      target.attr("stroke-dasharray", dashArray.dash.join(" "));
    }
    tempNode.remove();
    return path;
  },
  isWithinRegions(withinX, withinRegions) {
    return getDataRegionStyle(withinX, withinRegions);
  },
  isWithinStep(that, y) {
    return Math.abs(y - getPointer(this.state.event, that)[1]) < 30;
  },
  shouldDrawPointsForLine(d) {
    const linePoint = this.config.line_point;
    return linePoint === true || isArray(linePoint) && linePoint.indexOf(d.id) !== -1;
  }
});

;// ./src/ChartInternal/shape/point.ts



const getTransitionName = () => getRandom();
const pointBBoxCache = /* @__PURE__ */ new WeakMap();
function getPointBBox(node) {
  const attrHeight = node.getAttribute("height");
  const attrWidth = node.getAttribute("width");
  const href = node.getAttribute("href") || node.getAttribute("xlink:href");
  const cached = pointBBoxCache.get(node);
  if (cached && cached.attrHeight === attrHeight && cached.attrWidth === attrWidth && cached.href === href) {
    return cached;
  }
  const { width, height } = getBBox(node);
  const bbox = { attrHeight, attrWidth, height, href, width };
  pointBBoxCache.set(node, bbox);
  return bbox;
}
/* harmony default export */ var shape_point = ({
  initialOpacityForCircle(d) {
    const { config, state: { withoutFadeIn } } = this;
    let opacity = config.point_opacity;
    if (isUndefined(opacity)) {
      opacity = this.getBaseValue(d) !== null && withoutFadeIn[d.id] ? this.opacityForCircle(d) : "0";
    }
    return opacity;
  },
  opacityForCircle(d) {
    var _a;
    const { config } = this;
    let opacity = config.point_opacity;
    if (isUndefined(opacity)) {
      opacity = config.point_show && !((_a = this.isPointFocusOnly) == null ? void 0 : _a.call(this)) ? null : "0";
      opacity = isValue(this.getBaseValue(d)) ? this.isBubbleType(d) || this.isScatterType(d) ? "0.5" : opacity : "0";
    }
    return opacity;
  },
  initCircle() {
    const $$ = this;
    const { $el: { main } } = $$;
    !$$.point && ($$.point = $$.generatePoint());
    if (($$.hasType("bubble") || $$.hasType("scatter")) && main.select(`.${$COMMON.chart} > .${$CIRCLE.chartCircles}`).empty()) {
      main.select(`.${$COMMON.chart}`).append("g").attr("class", $CIRCLE.chartCircles);
    }
  },
  updateTargetForCircle(targetsValue, enterNodeValue) {
    const $$ = this;
    const { config, data, $el } = $$;
    const selectionEnabled = config.interaction_enabled && config.data_selection_enabled;
    const isSelectable = selectionEnabled && config.data_selection_isselectable;
    const classCircles = $$.getClass("circles", true);
    if (!config.point_show) {
      return;
    }
    $$.initCircle();
    let targets = targetsValue;
    let enterNode = enterNodeValue;
    if (!targets) {
      targets = $$.filterNullish(data.targets).filter((d) => this.isScatterType(d) || this.isBubbleType(d));
      const mainCircle = $el.main.select(`.${$CIRCLE.chartCircles}`).style("pointer-events", "none").selectAll(`.${$CIRCLE.circles}`).data(targets);
      mainCircle.exit().remove();
      enterNode = mainCircle.enter();
    }
    selectionEnabled && enterNode.append("g").attr("class", (d) => $$.generateClass($SELECT.selectedCircles, d.id));
    enterNode.append("g").attr("class", classCircles).call((selection) => {
      $$.setCssRule(true, `.${$CIRCLE.circles}`, ["cursor:pointer"], isSelectable)(
        selection
      );
      $$.setCssRule(true, ` .${$CIRCLE.circle}`, ["fill", "stroke"], $$.color)(selection);
    }).style("opacity", function() {
      const parent = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this.parentNode);
      return parent.classed($CIRCLE.chartCircles) ? "0" : null;
    });
    selectionEnabled && targets.forEach((t) => {
      $el.main.selectAll(`.${$SELECT.selectedCircles}${$$.getTargetSelectorSuffix(t.id)}`).selectAll(`${$SELECT.selectedCircle}`).each((d) => {
        d.value = t.values[d.index].value;
      });
    });
  },
  updateCircle(isSub = false) {
    const $$ = this;
    const { config, state, $el } = $$;
    const focusOnly = $$.isPointFocusOnly();
    const $root = isSub ? $el.subchart : $el;
    if (config.point_show && !state.toggling) {
      config.point_radialGradient && $$.updateLinearGradient();
      const circles = $root.main.selectAll(`.${$CIRCLE.circles}`).selectAll(`.${$CIRCLE.circle}`).data((d) => {
        const data = $$.isLineType(d) && $$.shouldDrawPointsForLine(d) || $$.isBubbleType(d) || $$.isRadarType(d) || $$.isScatterType(d) ? focusOnly ? [d.values[0]] : d.values : [];
        return $$.filterNullish(data);
      });
      circles.exit().remove();
      const pointR = $$.pointR.bind($$);
      const updateCircleColor = $$.generateUpdateCircleColor();
      const initialOpacityForCircle = $$.initialOpacityForCircle.bind($$);
      circles.enter().filter(Boolean).append($$.point("create", this, pointR, updateCircleColor));
      $root.circle = $root.main.selectAll(`.${$CIRCLE.circles} .${$CIRCLE.circle}`).style("stroke", $$.getStylePropValue($$.color)).style("opacity", initialOpacityForCircle);
    }
  },
  /**
   * Generate circle color accessor, hoisting the bound color function
   * to be created once per call (not per datum)
   * @returns {function} Color accessor
   * @private
   */
  generateUpdateCircleColor() {
    const $$ = this;
    const fn = $$.getStylePropValue($$.color);
    return (d) => $$.config.point_radialGradient ? $$.getGradienColortUrl(d.id) : fn ? fn(d) : null;
  },
  /**
   * Update circle color
   * @param {object} d Data object
   * @returns {string} Color string
   * @private
   */
  updateCircleColor(d) {
    return this.generateUpdateCircleColor()(d);
  },
  redrawCircle(cx, cy, withTransition, flow, isSub = false) {
    const $$ = this;
    const { state: { rendered }, $el, $T } = $$;
    const $root = isSub ? $el.subchart : $el;
    const selectedCircles = $root.main.selectAll(`.${$SELECT.selectedCircle}`);
    if (!$$.config.point_show) {
      return [];
    }
    const posAttr = $$.isCirclePoint() ? "c" : "";
    const t = getRandom();
    const opacityStyleFn = $$.opacityForCircle.bind($$);
    const updateCircleColor = $$.generateUpdateCircleColor();
    if ($$.isCirclePoint()) {
      const sel = $root.circle;
      if ($$.hasType("bubble")) {
        sel.attr("r", $$.pointR.bind($$));
      }
      if (withTransition) {
        flow && sel.attr("cx", cx);
        $T(sel.filter(function() {
          return !!this.getAttribute("cx");
        }), true, `${t}-pos`).attr("cx", cx).attr("cy", cy).style("fill", updateCircleColor);
        sel.filter(function() {
          return !this.getAttribute("cx");
        }).attr("cx", cx).attr("cy", cy).style("fill", updateCircleColor);
      } else {
        sel.attr("cx", cx).attr("cy", cy).style("fill", updateCircleColor);
      }
      const result = $T(sel, withTransition || !rendered, t).style("opacity", opacityStyleFn);
      return [
        [result],
        $T(selectedCircles, withTransition).attr("cx", cx).attr("cy", cy)
      ];
    }
    const fn = $$.point(
      "update",
      $$,
      cx,
      cy,
      updateCircleColor,
      withTransition,
      flow,
      selectedCircles
    );
    const mainCircles = [];
    $root.circle.each(function(d) {
      let result = fn.bind(this)(d);
      result = $T(result, withTransition || !rendered, t).style("opacity", opacityStyleFn);
      mainCircles.push(result);
    });
    return [
      mainCircles,
      $T(selectedCircles, withTransition).attr(`${posAttr}x`, cx).attr(`${posAttr}y`, cy)
    ];
  },
  /**
   * Show focused data point circle
   * @param {object} d Selected data
   * @private
   */
  showCircleFocus(d) {
    const $$ = this;
    const { state: { hasRadar, resizing, toggling, transiting }, $el } = $$;
    let { circle } = $el;
    if (transiting === false && circle && $$.isPointFocusOnly()) {
      const cx = (hasRadar ? $$.radarCircleX : $$.circleX).bind($$);
      const cy = (hasRadar ? $$.radarCircleY : $$.circleY).bind($$);
      const withTransition = toggling || isUndefined(d);
      const fn = $$.point(
        "update",
        $$,
        cx,
        cy,
        $$.getStylePropValue($$.color),
        resizing ? false : withTransition
      );
      if (d) {
        circle = circle.filter(function(t) {
          var _a;
          const data = (_a = d.filter) == null ? void 0 : _a.call(d, (v) => v.id === t.id);
          return data.length ? (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).datum(data[0]) : false;
        });
      }
      circle.attr("class", this.updatePointClass.bind(this)).style("opacity", null).each(function(d2) {
        const { id, index, value } = d2;
        let visibility = "hidden";
        if (isValue(value)) {
          fn.bind(this)(d2);
          $$.expandCircles(index, id);
          visibility = "";
        }
        this.style.visibility = visibility;
      });
    }
  },
  /**
   * Hide focused data point circle
   * @private
   */
  hideCircleFocus() {
    const $$ = this;
    const { $el: { circle } } = $$;
    if ($$.isPointFocusOnly() && circle) {
      $$.unexpandCircles();
      circle.style("visibility", "hidden");
    }
  },
  expandCircles(i, id, reset) {
    const $$ = this;
    const r = $$.pointExpandedR.bind($$);
    reset && $$.unexpandCircles();
    const circles = $$.getShapeByIndex("circle", i, id).classed($COMMON.EXPANDED, true);
    const scale = r(circles) / $$.config.point_r;
    const ratio = 1 - scale;
    if ($$.isCirclePoint()) {
      circles.attr("r", r);
    } else {
      circles.each(function() {
        const point = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        if (this.tagName === "circle") {
          point.attr("r", r);
        } else {
          const { width, height } = getPointBBox(this);
          const x = ratio * (+point.attr("x") + width / 2);
          const y = ratio * (+point.attr("y") + height / 2);
          point.attr("transform", `translate(${x} ${y}) scale(${scale})`);
        }
      });
    }
  },
  unexpandCircles(i) {
    const $$ = this;
    const r = $$.pointR.bind($$);
    const circles = $$.getShapeByIndex("circle", i).filter(function() {
      return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($COMMON.EXPANDED);
    }).classed($COMMON.EXPANDED, false);
    circles.attr("r", r);
    if (!$$.isCirclePoint()) {
      const scale = r(circles) / $$.config.point_r;
      circles.attr("transform", scale !== 1 ? `scale(${scale})` : null);
    }
  },
  isWithinCircle(node, r) {
    const { state } = this;
    const mouse = getPointer(state.event, node);
    const element = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(node);
    const prefix = this.isCirclePoint(node) ? "c" : "";
    const pointSensitivity = this.getPointSensitivity(element == null ? void 0 : element.datum());
    let cx = +element.attr(`${prefix}x`);
    let cy = +element.attr(`${prefix}y`);
    if (!(cx || cy) && node.nodeType === 1) {
      const { x, y } = getBoundingRect(node);
      cx = x;
      cy = y;
    }
    const dx = cx - mouse[0];
    const dy = cy - mouse[1];
    return Math.sqrt(dx * dx + dy * dy) < (r || pointSensitivity);
  },
  updatePointClass(d) {
    const $$ = this;
    const { circle } = $$.$el;
    let pointClass = false;
    if (isObject(d) || circle) {
      pointClass = d === true ? circle.each(function(d2) {
        let className = $$.getClass("circle", true)(d2);
        if (this.getAttribute("class").indexOf($COMMON.EXPANDED) > -1) {
          className += ` ${$COMMON.EXPANDED}`;
        }
        this.setAttribute("class", className);
      }) : $$.getClass("circle", true)(d);
    }
    return pointClass;
  },
  custom: {
    create(element, id, fillStyleFn) {
      return element.append("use").attr("xlink:href", `#${id}`).attr("class", this.updatePointClass.bind(this)).style("fill", fillStyleFn).node();
    },
    update(element, xPosFn, yPosFn, fillStyleFn, withTransition, flow, selectedCircles) {
      const $$ = this;
      const { width, height } = getPointBBox(element.node());
      const xPosFn2 = (d) => isValue(d.value) ? xPosFn(d) - width / 2 : 0;
      const yPosFn2 = (d) => isValue(d.value) ? yPosFn(d) - height / 2 : 0;
      let mainCircles = element;
      if (withTransition) {
        flow && mainCircles.attr("x", xPosFn2);
        mainCircles = $$.$T(mainCircles, withTransition, getTransitionName());
        selectedCircles && $$.$T(selectedCircles, withTransition, getTransitionName());
      }
      return mainCircles.attr("x", xPosFn2).attr("y", yPosFn2).style("fill", fillStyleFn);
    }
  },
  // 'circle' data point
  circle: {
    create(element, sizeFn, fillStyleFn) {
      return element.append("circle").attr("class", this.updatePointClass.bind(this)).attr("r", sizeFn).style("fill", fillStyleFn).node();
    },
    update(element, xPosFn, yPosFn, fillStyleFn, withTransition, flow, selectedCircles) {
      const $$ = this;
      let mainCircles = element;
      if ($$.hasType("bubble")) {
        mainCircles.attr("r", $$.pointR.bind($$));
      }
      if (withTransition) {
        flow && mainCircles.attr("cx", xPosFn);
        if (mainCircles.attr("cx")) {
          mainCircles = $$.$T(mainCircles, withTransition, getTransitionName());
        }
        selectedCircles && $$.$T(selectedCircles, withTransition, getTransitionName());
      }
      return mainCircles.attr("cx", xPosFn).attr("cy", yPosFn).style("fill", fillStyleFn);
    }
  },
  // 'rectangle' data point
  rectangle: {
    create(element, sizeFn, fillStyleFn) {
      const rectSizeFn = (d) => sizeFn(d) * 2;
      return element.append("rect").attr("class", this.updatePointClass.bind(this)).attr("width", rectSizeFn).attr("height", rectSizeFn).style("fill", fillStyleFn).node();
    },
    update(element, xPosFn, yPosFn, fillStyleFn, withTransition, flow, selectedCircles) {
      const $$ = this;
      const r = $$.config.point_r;
      const rectXPosFn = (d) => xPosFn(d) - r;
      const rectYPosFn = (d) => yPosFn(d) - r;
      let mainCircles = element;
      if (withTransition) {
        flow && mainCircles.attr("x", rectXPosFn);
        mainCircles = $$.$T(mainCircles, withTransition, getTransitionName());
        selectedCircles && $$.$T(selectedCircles, withTransition, getTransitionName());
      }
      return mainCircles.attr("x", rectXPosFn).attr("y", rectYPosFn).style("fill", fillStyleFn);
    }
  }
});

;// ./src/config/Options/common/point.ts
/* harmony default export */ var common_point = ({
  /**
   * Set point options
   * @name point
   * @memberof Options
   * @type {object}
   * @property {object} point Point object
   * @property {boolean} [point.show=true] Whether to show each point in line.
   * @property {number|function} [point.r=2.5] The radius size of each point.
   *  - **NOTE:** Disabled for 'bubble' type
   * @property {boolean|object} [point.radialGradient=false] Set the radial gradient on point.<br><br>
   * Or customize by giving below object value:
   *  - cx {number}: `cx` value (default: `0.3`)
   *  - cy {number}: `cy` value (default: `0.3`)
   *  - r {number}: `r` value (default: `0.7`)
   *  - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.
   *    - (default: `[[0.1, $DATA_COLOR, 1], [0.9, $DATA_COLOR, 0]]`)
   * @property {boolean} [point.focus.expand.enabled=true] Whether to expand each point on focus.
   * @property {number} [point.focus.expand.r=point.r*1.75] The radius size of each point on focus.
   *  - **NOTE:** For 'bubble' type, the default is `bubbleSize*1.15`
   * @property {boolean} [point.focus.only=false] Show point only when is focused.
   * @property {number|null} [point.opacity=undefined] Set point opacity value.
   * - **NOTE:**
   * 	- `null` will make to not set inline 'opacity' css prop.
   * 	- when no value(or undefined) is set, it defaults to set opacity value according its chart types.
   * @property {number|string|function} [point.sensitivity=10] The sensitivity value for interaction boundary.
   * - **Available Values:**
   *   - {number}: Absolute sensitivity value which is the distance from the data point in pixel.
   *   - "radius": sensitivity based on point's radius
   *   - Function: callback for each point to determine the sensitivity<br>
   *    	```js
   *   	sensitivity: function(d) {
   * 	  // ex. of argument d:
   * 	  // ==> {x: 2, value: 55, id: 'data3', index: 2, r: 19.820624179302296}
   *
   * 	  // returning d.r, will make sensitivity same as point's radius value.
   *  	  return d.r;
   * 	}
   * 	```
   * @property {number} [point.select.r=point.r*4] The radius size of each point on selected.
   * @property {string} [point.type="circle"] The type of point to be drawn
   * - **NOTE:**
   *   - If chart has 'bubble' type, only circle can be used.
   *   - For IE, non circle point expansions are not supported due to lack of transform support.
   * - **Available Values:**
   *   - circle
   *   - rectangle
   * @property {Array} [point.pattern=[]] The type of point or svg shape as string, to be drawn for each line
   * - **NOTE:**
   *   - This is an `experimental` feature and can have some unexpected behaviors.
   *   - If chart has 'bubble' type, only circle can be used.
   *   - For IE, non circle point expansions are not supported due to lack of transform support.
   *   - Only common SVG tags are allowed to prevent XSS attacks. If creating charts from user input, it is recommended to sanitize input values to avoid potential vulnerabilities.
   * - **Available Values:**
   *   - circle
   *   - rectangle
   *   - svg shape tag interpreted as string<br>
   *     (ex. `<polygon points='2.5 0 0 5 5 5'></polygon>`)
   * @see [Demo: point type](https://naver.github.io/billboard.js/demo/#Point.RectanglePoints)
   * @see [Demo: point focus only](https://naver.github.io/billboard.js/demo/#Point.FocusOnly)
   * @see [Demo: point radialGradient](https://naver.github.io/billboard.js/demo/#Point.RadialGradientPoint)
   * @see [Demo: point sensitivity](https://naver.github.io/billboard.js/demo/#Point.PointSensitivity)
   * @example
   *  point: {
   *      show: false,
   *      r: 5,
   *
   *      // or customize the radius
   *      r: function(d) {
   *          ...
   *          return r;
   *      },
   *
   *      // will generate following radialGradient:
   *      // for more info: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/radialGradient
   *      // <radualGradient cx="0.3" cy="0.3" r="0.7">
   *      //    <stop offset="0.1" stop-color="$DATA_COLOR" stop-opacity="1"></stop>
   *      //    <stop offset="0.9" stop-color="$DATA_COLOR" stop-opacity="0"></stop>
   *      // </radialrGradient>
   *      radialGradient: true,
   *
   *      // Or customized gradient
   *      radialGradient: {
   *      	cx: 0.3,  // cx attributes
   *      	cy: 0.5,  // cy attributes
   *      	r: 0.7,  // r attributes
   *      	stops: [
   *      	  // offset, stop-color, stop-opacity
   *      	  [0, "#7cb5ec", 1],
   *
   *      	  // setting 'null' for stop-color, will set its original data color
   *      	  [0.5, null, 0],
   *
   *      	  // setting 'function' for stop-color, will pass data id as argument.
   *      	  // It should return color string or null value
   *      	  [1, function(id) { return id === "data1" ? "red" : "blue"; }, 0],
   *      	]
   *      },
   *
   *      focus: {
   *          expand: {
   *              enabled: true,
   *              r: 1
   *          },
   *          only: true
   *      },
   *
   *      // do not set inline 'opacity' css prop setting
   *      opacity: null,
   *
   *      // set every data point's opacity value
   *      opacity: 0.7,
   *
   *      select: {
   *          r: 3
   *      },
   *
   *      // having lower value, means how closer to be for interaction
   *      sensitivity: 3,
   *
   *      // sensitivity based on point's radius
   *      sensitivity: "radius",
   *
   *      // callback for each point to determine the sensitivity
   *      sensitivity: function(d) {
   * 	// ex. of argument d:
   * 	// ==> {x: 2, value: 55, id: 'data3', index: 2, r: 19.820624179302296}
   *
   * 	// returning d.r, will make sensitivity same as point's radius value.
   * 	return d.r;
   *      }
   *
   *      // valid values are "circle" or "rectangle"
   *      type: "rectangle",
   *
   *      // or indicate as pattern
   *      pattern: [
   *        "circle",
   *        "rectangle",
   *        "<polygon points='0 6 4 0 -4 0'></polygon>"
   *     ],
   *  }
   */
  point_show: true,
  point_r: 2.5,
  point_radialGradient: false,
  point_sensitivity: 10,
  point_focus_expand_enabled: true,
  point_focus_expand_r: void 0,
  point_focus_only: false,
  point_opacity: void 0,
  point_pattern: [],
  point_select_r: void 0,
  point_type: "circle"
});

;// ./src/config/Options/shape/line.ts
/* harmony default export */ var shape_line = ({
  /**
   * Set line options
   * @name line
   * @memberof Options
   * @type {object}
   * @property {object} line Line object
   * @property {boolean} [line.connectNull=false] Set if null data point will be connected or not.<br>
   *  If true set, the region of null data will be connected without any data point. If false set, the region of null data will not be connected and get empty.
   * @property {Array}   [line.classes=undefined] If set, used to set a css class on each line.
   * @property {boolean} [line.step.type=step] Change step type for step chart.<br>
   * **Available values:**
   * - step
   * - step-before
   * - step-after
   * @property {boolean} [line.step.tooltipMatch=false] Set to `true` for `step-before` and `step-after` types to have cursor/tooltip match to hovered step's point instead of nearest point.
   * @property {boolean|Array} [line.point=true] Set to false to not draw points on linecharts. Or pass an array of line ids to draw points for.
   * @property {boolean} [line.zerobased=false] Set if min or max value will be 0 on line chart.
   * @example
   *  line: {
   *      connectNull: true,
   *      classes: [
   *          "line-class1",
   *          "line-class2"
   *      ],
   *      step: {
   *          type: "step-after",
   *
   *          // to have cursor/tooltip match to hovered step's point instead of nearest point.
   *          tooltipMatch: true
   *      },
   *
   *      // hide all data points ('point.show=false' also has similar effect)
   *      point: false,
   *
   *      // show data points for only indicated data
   *      point: [
   *          "data1", "data3"
   *      ],
   *
   *      zerobased: false
   *  }
   */
  line_connectNull: false,
  line_step_type: "step",
  line_step_tooltipMatch: false,
  line_zerobased: false,
  line_classes: void 0,
  line_point: true
});

;// ./src/Chart/api/axis.ts

function setMinMax($$, type, value) {
  const { config } = $$;
  const helper = (key, value2) => {
    const v = isNumber(value2) ? value2 : value2 === false ? void 0 : null;
    if (v !== null) {
      config[`axis_${key}_${type}`] = v;
    }
  };
  if (isDefined(value)) {
    if (isObjectType(value)) {
      Object.keys(value).forEach((key) => {
        helper(key, value[key]);
      });
    } else if (isNumber(value) || value === false) {
      ["y", "y2"].forEach((key) => {
        helper(key, value);
      });
    }
    $$.state.dirty.data = true;
    $$.redraw({
      withUpdateOrgXDomain: true,
      withUpdateXDomain: true
    });
  }
}
function axis_getMinMax($$, type) {
  const { config } = $$;
  return {
    x: config[`axis_x_${type}`],
    y: config[`axis_y_${type}`],
    y2: config[`axis_y2_${type}`]
  };
}
const axis = {
  /**
   * Get and set axis labels.
   * - **NOTE:** Only applicable for chart types which has x and y axes.
   * @function axis․labels
   * @instance
   * @memberof Chart
   * @param {object} labels specified axis' label to be updated.
   * @param {string} [labels.x] x Axis string
   * @param {string} [labels.y] y Axis string
   * @param {string} [labels.y2] y2 Axis string
   * @returns {object|undefined} axis labels text object
   * @example
   * // Update axis' label
   * chart.axis.labels({
   *   x: "New X Axis Label",
   *   y: "New Y Axis Label",
   *   y2: "New Y2 Axis Label"
   * });
   *
   * chart.axis.labels();
   * // --> {
   * //  x: "New X Axis Label",
   * //  y: "New Y Axis Label",
   * //  y2: "New Y2 Axis Label"
   * // }
   */
  labels: function(labels) {
    var _a;
    const $$ = this.internal;
    let labelText;
    if (labels) {
      Object.keys(labels).forEach((axisId) => {
        $$.axis.setLabelText(axisId, labels[axisId]);
      });
      if ($$.state.isCanvasMode) {
        (_a = $$.renderCanvasFrame) == null ? void 0 : _a.call($$, void 0, null, false);
      } else {
        $$.axis.updateLabels();
      }
    }
    ["x", "y", "y2"].forEach((v) => {
      const text = $$.axis.getLabelText(v);
      if (text) {
        !labelText && (labelText = {});
        labelText[v] = text;
      }
    });
    return labelText;
  },
  /**
   * Get and set axis min value.
   * - **NOTE:** Only applicable for chart types which has x and y axes.
   * @function axis․min
   * @instance
   * @memberof Chart
   * @param {object} min If min is given, specified axis' min value will be updated.<br>
   *   If no argument is given, the min values set on generating option for each axis will be returned.
   *   If not set any min values on generation, it will return `undefined`.<br>
   *   To unset specific axis max, set `false` to each of them.
   * @returns {object|undefined}
   * @example
   * // Update axis' min
   * chart.axis.min({
   *   x: -10,
   *   y: 1000,
   *   y2: 100
   * });
   *
   * // To unset specific axis min, set false to each of them.
   * chart.axis.min({
   *   x: false,
   *   y: false,
   *   y2: false
   * });
   *
   * // shorthand (only affects y and y2 axis)
   * chart.axis.min(-50);
   * chart.axis.min(false);
   */
  min: function(min) {
    const $$ = this.internal;
    return isValue(min) || min === false ? setMinMax($$, "min", min) : axis_getMinMax($$, "min");
  },
  /**
   * Get and set axis max value.
   * - **NOTE:** Only applicable for chart types which has x and y axes.
   * @function axis․max
   * @instance
   * @memberof Chart
   * @param {object} max If max is given, specified axis' max value will be updated.<br>
   *   If no argument is given, the max values set on generating option for each axis will be returned.
   *   If not set any max values on generation, it will return `undefined`.<br>
   *   To unset specific axis max, set `false` to each of them.
   * @returns {object|undefined}
   * @example
   * // Update axis' label
   * chart.axis.max({
   *    x: 100,
   *    y: 1000,
   *    y2: 10000
   * });
   *
   * // To unset specific axis max, set false to each of them.
   * chart.axis.max({
   *   x: false,
   *   y: false,
   *   y2: false
   * });
   *
   * // shorthand (only affects y and y2 axis)
   * chart.axis.max(10);
   * chart.axis.max(false);
   */
  max: function(max) {
    const $$ = this.internal;
    return isValue(max) || max === false ? setMinMax($$, "max", max) : axis_getMinMax($$, "max");
  },
  /**
   * Get and set axis min and max value.
   * - **NOTE:** Only applicable for chart types which has x and y axes.
   * @function axis․range
   * @instance
   * @memberof Chart
   * @param {object} range If range is given, specified axis' min and max value will be updated.
   *   If no argument is given, the current min and max values for each axis will be returned.<br>
   *   To unset specific axis max, set `false` to each of them.
   * @returns {object|undefined}
   * @example
   * // Update axis' label
   * chart.axis.range({
   *   min: {
   *     x: -10,
   *     y: -1000,
   *     y2: -10000
   *   },
   *   max: {
   *     x: 100,
   *     y: 1000,
   *     y2: 10000
   *   },
   * });
   *
   * // To unset specific axis max, set false to each of them.
   * chart.axis.range({
   *   min: {
   *     x: false,
   *     y: false,
   *     y2: false
   *   },
   *   max: {
   *     x: false,
   *     y: false,
   *     y2: false
   *   },
   * });
   *
   * // shorthand (only affects y and y2 axis)
   * chart.axis.range({ min: -50, max: 1000 });
   * chart.axis.range({ min: false, max: false });
   */
  range: function(range) {
    const { axis: axis2 } = this;
    if (arguments.length) {
      const { min, max } = range;
      isDefined(max) && axis2.max(max);
      isDefined(min) && axis2.min(min);
    } else {
      return {
        max: axis2.max(),
        min: axis2.min()
      };
    }
    return void 0;
  }
};
/* harmony default export */ var api_axis = ({ axis });

;// ./src/Chart/api/group.ts

/* harmony default export */ var group = ({
  /**
   * Update groups for the targets.
   * @function groups
   * @instance
   * @memberof Chart
   * @param {Array} groups This argument needs to be an Array that includes one or more Array that includes target ids to be grouped.
   * @returns {Array} Grouped data names array
   * @example
   *  // data1 and data2 will be a new group.
   *  chart.groups([
   *     ["data1", "data2"]
   *  ]);
   */
  groups(groups) {
    const $$ = this.internal;
    const { config } = $$;
    if (isUndefined(groups)) {
      return config.data_groups;
    }
    config.data_groups = groups;
    $$.state.dirty.data = true;
    $$.redraw();
    return config.data_groups;
  }
});

;// ./src/Chart/api/x.ts

/* harmony default export */ var x = ({
  /**
   * Get and set x values for the chart.
   * @function x
   * @instance
   * @memberof Chart
   * @param {Array} x If x is given, x values of every target will be updated. If no argument is given, current x values will be returned as an Object whose keys are the target ids.
   * @returns {object} xs
   * @example
   *  // Get current x values
   *  chart.x();
   *
   *  // Update x values for all targets
   *  chart.x([100, 200, 300, 400, ...]);
   */
  x(x) {
    const $$ = this.internal;
    const { axis, data } = $$;
    const isCategorized = axis.isCustomX() && axis.isCategorized();
    if (isArray(x)) {
      if (isCategorized) {
        this.categories(x);
      } else {
        $$.updateTargetX(data.targets, x);
        $$.state.dirty.data = true;
        $$.redraw({
          withUpdateOrgXDomain: true,
          withUpdateXDomain: true
        });
      }
    }
    return isCategorized ? this.categories() : data.xs;
  },
  /**
   * Get and set x values for the chart.
   * @function xs
   * @instance
   * @memberof Chart
   * @param {Array} xs If xs is given, specified target's x values will be updated. If no argument is given, current x values will be returned as an Object whose keys are the target ids.
   * @returns {object} xs
   * @example
   *  // Get current x values
   *  chart.xs();
   *
   *  // Update x values for all targets
   *  chart.xs({
   *    data1: [10, 20, 30, 40, ...],
   *    data2: [100, 200, 300, 400, ...]
   *  });
   */
  xs(xs) {
    const $$ = this.internal;
    if (isObject(xs)) {
      $$.updateTargetXs($$.data.targets, xs);
      $$.state.dirty.data = true;
      $$.redraw({
        withUpdateOrgXDomain: true,
        withUpdateXDomain: true
      });
    }
    return $$.data.xs;
  }
});

;// ./src/ChartInternal/Axis/AxisRendererHelper.ts
var AxisRendererHelper_defProp = Object.defineProperty;
var AxisRendererHelper_defNormalProp = (obj, key, value) => key in obj ? AxisRendererHelper_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var AxisRendererHelper_publicField = (obj, key, value) => AxisRendererHelper_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);


class AxisRendererHelper {
  constructor(owner) {
    AxisRendererHelper_publicField(this, "owner");
    AxisRendererHelper_publicField(this, "config");
    AxisRendererHelper_publicField(this, "scale");
    AxisRendererHelper_publicField(this, "charSize", {});
    const scale = getScale();
    const { config, params } = owner;
    this.owner = owner;
    this.config = config;
    this.scale = scale;
    if (config.noTransition || !params.config.transition_duration) {
      config.withoutTransition = true;
    }
    config.range = this.scaleExtent((params.orgXScale || scale).range());
  }
  /**
   * Compute a character dimension
   * @param {string} orient Axis orientation
   * @param {d3.selection} text SVG text selection
   * @param {boolean} memoize memoize the calculated size
   * @returns {{w: number, h: number}}
   * @private
   */
  getSizeFor1Char(orient, text, memoize = true) {
    const size = {
      w: 5.5,
      h: 11.5
    };
    if (this.charSize[orient] && memoize) {
      return this.charSize[orient];
    }
    !text.empty() && text.text("0").call((el) => {
      try {
        const { width, height } = getBBox(el.node(), true);
        if (width && height) {
          size.w = width;
          size.h = height;
        }
      } finally {
        el.text("");
      }
    });
    this.charSize[orient] = size;
    return size;
  }
  /**
   * Get tick transform setter function
   * @param {string} id Axis id
   * @returns {function(d3Selection, d3Scale): void} transform setter function
   * @private
   */
  getTickTransformSetter(id) {
    const { config } = this;
    const fn = id === "x" ? (value) => `translate(${value + config.tickOffset},0)` : (value) => `translate(0,${value})`;
    return (selection, scale) => {
      selection.attr("transform", (d) => {
        const x = scale(d);
        return isValue(d) ? fn(x) : null;
      });
    };
  }
  scaleExtent(domain) {
    const start = domain[0];
    const stop = domain[domain.length - 1];
    return start < stop ? [start, stop] : [stop, start];
  }
  generateTicks(scale, isYAxes) {
    const { tickStepSize } = this.owner.params;
    const [start, end] = scale.domain();
    let ticks = [];
    if (isYAxes && tickStepSize) {
      let interval = Math.round(start);
      while (interval <= end) {
        ticks.push(interval);
        interval += tickStepSize;
      }
    } else if (scale.ticks) {
      const { tickArguments } = this.config;
      if (scale.type === "log" && !tickArguments) {
        const s = getScale("_log").domain([start > 0 ? start : 1, end]).range(scale.range());
        ticks = s.ticks();
        for (let cnt = end.toFixed().length; ticks.length > 15; cnt--) {
          ticks = s.ticks(cnt);
        }
        ticks.splice(0, 1, start);
        ticks.splice(ticks.length - 1, 1, end);
      } else {
        ticks = scale.ticks(...this.config.tickArguments || []);
      }
    }
    return ticks;
  }
  copyScale() {
    const newScale = this.scale.copy();
    if (!newScale.domain().length) {
      newScale.domain(this.scale.domain());
    }
    newScale.type = this.scale.type;
    return newScale;
  }
  textFormatted(v) {
    const tickFormat = this.config.tickFormat;
    const value = /\d+\.\d+0{5,}\d$/.test(v) ? +String(v).replace(/0+\d$/, "") : v;
    const formatted = tickFormat ? tickFormat(value) : value;
    return isDefined(formatted) ? formatted : "";
  }
  transitionise(selection) {
    const { config } = this;
    let transitionSelection = selection;
    if (config.withoutTransition) {
      transitionSelection = selection.interrupt();
    } else if (config.transition || !this.owner.params.noTransition) {
      try {
        transitionSelection = selection.transition(config.transition);
      } catch (e) {
      }
    }
    return transitionSelection;
  }
}

;// ./src/ChartInternal/Axis/AxisRenderer.ts
var AxisRenderer_defProp = Object.defineProperty;
var AxisRenderer_defNormalProp = (obj, key, value) => key in obj ? AxisRenderer_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var AxisRenderer_publicField = (obj, key, value) => AxisRenderer_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);





function getBaseAxisId(id) {
  return id === "subX" ? "x" : id === "subY" ? "y" : id === "subY2" ? "y2" : id;
}
function getAxisOptionPrefix(id) {
  const type = getBaseAxisId(id);
  return /^sub/.test(id) ? `subchart_axis_${type}` : `axis_${type}`;
}
class AxisRenderer {
  constructor(params = {}) {
    AxisRenderer_publicField(this, "helper");
    AxisRenderer_publicField(this, "config");
    AxisRenderer_publicField(this, "params");
    AxisRenderer_publicField(this, "g");
    AxisRenderer_publicField(this, "generatedTicks", []);
    const config = {
      innerTickSize: AXIS_TICK_SIZE,
      outerTickSize: params.outerTick ? AXIS_TICK_SIZE : 0,
      orient: "bottom",
      range: [],
      tickArguments: null,
      tickCentered: null,
      tickCulling: true,
      tickFormat: null,
      tickLength: AXIS_TICK_LENGTH,
      tickOffset: 0,
      tickPadding: AXIS_TICK_PADDING,
      tickValues: null,
      transition: null,
      noTransition: params.noTransition
    };
    config.tickLength = Math.max(config.innerTickSize, 0) + config.tickPadding;
    this.config = config;
    this.params = params;
    this.helper = new AxisRendererHelper(this);
  }
  canReuseTickTextOnResize(isLeftRight) {
    const { config, params } = this;
    const { config: chartConfig, id, owner } = params;
    const isX = /^(x|subX)$/.test(id);
    const type = getBaseAxisId(id);
    const customTickFormat = /^sub/.test(id) ? chartConfig[`subchart_axis_${type}_tick_format`] || chartConfig[`axis_${type}_tick_format`] : chartConfig[`axis_${type}_tick_format`];
    const categoryAutoWrap = params.tickMultiline && params.isCategory && !isLeftRight && !(params.tickWidth > 0);
    return !!(owner.state.resizing && !owner.state.flowing && !isFunction(chartConfig.axis_evalTextSize) && !customTickFormat && !params.tickTitle && !(isX && chartConfig.axis_x_tick_autorotate) && !categoryAutoWrap && config.withoutTransition);
  }
  canReuseTickNodesOnResize(tickNodes, ticks, isLeftRight, tickShow) {
    if (tickShow.tick || !tickShow.text || !this.canReuseTickTextOnResize(isLeftRight) || tickNodes.size() !== ticks.length) {
      return false;
    }
    const nodes = tickNodes.nodes();
    for (let i = 0; i < ticks.length; i++) {
      const current = nodes[i].__data__;
      const next = ticks[i];
      if (current instanceof Date || next instanceof Date) {
        if (+current !== +next) {
          return false;
        }
      } else if (current !== next) {
        return false;
      }
    }
    return true;
  }
  /**
   * Create axis element
   * @param {d3.selection} g Axis selection
   * @private
   */
  create(g) {
    const ctx = this;
    const { config, helper, params } = ctx;
    const { scale } = helper;
    const { orient } = config;
    const splitTickText = this.splitTickText.bind(ctx);
    const isLeftRight = /^(left|right)$/.test(orient);
    const isTopBottom = /^(top|bottom)$/.test(orient);
    const tickTransform = helper.getTickTransformSetter(isTopBottom ? "x" : "y");
    const axisPx = tickTransform === helper.axisX ? "y" : "x";
    const sign = /^(top|left)$/.test(orient) ? -1 : 1;
    const rotate = params.tickTextRotate;
    this.config.range = scale.rangeExtent ? scale.rangeExtent() : helper.scaleExtent((params.orgXScale || scale).range());
    const { innerTickSize, tickLength, range } = config;
    const id = params.id;
    const type = getBaseAxisId(id);
    const { isSubAxes } = params;
    const tickTextPos = !isSubAxes && type && /^(x|y|y2)$/.test(type) ? params.config[`axis_${type}_tick_text_position`] : { x: 0, y: 0 };
    const prefix = getAxisOptionPrefix(id);
    const axisShow = params.config[`${prefix}_show`];
    const tickShow = isSubAxes ? { tick: true, text: true } : {
      tick: axisShow ? params.config[`${prefix}_tick_show`] : false,
      text: axisShow ? params.config[`${prefix}_tick_text_show`] : false
    };
    const evalTextSize = params.config.axis_evalTextSize;
    let $g;
    g.each(function() {
      const g2 = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
      let scale0 = this.__chart__ || scale;
      let scale1 = helper.copyScale();
      $g = g2;
      this.__chart__ = scale1;
      config.tickOffset = params.isCategory ? (scale1(1) - scale1(0)) / 2 : 0;
      const path = g2.selectAll(".domain").data([0]);
      path.enter().append("path").attr("class", "domain").merge(path).attr("d", () => {
        const outerTickSized = config.outerTickSize * sign;
        return isTopBottom ? `M${range[0]},${outerTickSized}V0H${range[1]}V${outerTickSized}` : `M${outerTickSized},${range[0]}H0V${range[1]}H${outerTickSized}`;
      });
      if (tickShow.tick || tickShow.text) {
        const ticks = config.tickValues || helper.generateTicks(scale1, isLeftRight || params.config.axis_rotated);
        ctx.generatedTicks = ticks;
        let tick = g2.selectAll(".tick");
        const canReuseTickNodes = ctx.canReuseTickNodesOnResize(
          tick,
          ticks,
          isLeftRight || params.config.axis_rotated,
          tickShow
        );
        if (canReuseTickNodes) {
          tickTransform(tick, scale1);
        } else {
          tick = tick.data(ticks, scale1);
          const tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick");
          const tickExit = tick.exit().remove();
          tick = tickEnter.merge(tick);
          tickShow.tick && tickEnter.append("line");
          tickShow.text && tickEnter.append("text");
          const hasTickChange = !tickEnter.empty() || !tickExit.empty();
          const reuseTickText = tickShow.text && !hasTickChange && ctx.canReuseTickTextOnResize(isLeftRight || params.config.axis_rotated);
          let sizeFor1Char = { w: 0, h: 0 };
          let textUpdate = tick.selectAll("text.__bb-empty");
          if (tickShow.text && !reuseTickText) {
            const tickText = tick.select("text");
            const counts = [];
            textUpdate = tickText;
            if (isFunction(evalTextSize)) {
              sizeFor1Char = evalTextSize.bind(ctx.params.owner.api)(
                tickText.node(),
                id
              );
              if (this.classList.contains($COMMON.dummy)) {
                this.sizeFor1Char = sizeFor1Char;
              }
            }
            if (!sizeFor1Char || sizeFor1Char.w === 0 || sizeFor1Char.h === 0) {
              sizeFor1Char = ctx.helper.getSizeFor1Char(
                orient,
                tickText,
                !!evalTextSize
              );
            }
            let tspan = tickText.selectAll("tspan").data((d, index) => {
              let split;
              if (params.tickMultiline) {
                split = splitTickText(
                  d,
                  scale1,
                  ticks,
                  isLeftRight,
                  sizeFor1Char.w
                );
              } else {
                const formatted = helper.textFormatted(d);
                split = isArray(formatted) ? formatted.concat() : [formatted];
              }
              counts[index] = split.length;
              return split.map((splitted) => ({ index, splitted }));
            });
            tspan.exit().remove();
            tspan = tspan.enter().append("tspan").merge(tspan).text((d) => d.splitted);
            tspan.attr("x", isTopBottom ? 0 : tickLength * sign).attr("dx", (() => {
              let dx = 0;
              if (/(top|bottom)/.test(orient) && rotate) {
                dx = 8 * Math.sin(Math.PI * (rotate / 180)) * (orient === "top" ? -1 : 1);
              }
              return dx + (tickTextPos.x || 0);
            })()).attr("dy", (d, i) => {
              const defValue = ".71em";
              let dy = 0;
              if (orient !== "top") {
                dy = sizeFor1Char.h;
                if (i === 0) {
                  dy = isLeftRight ? -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3) : tickTextPos.y === 0 ? defValue : 0;
                }
              }
              return isNumber(dy) && tickTextPos.y ? dy + tickTextPos.y : dy || defValue;
            });
          }
          const lineUpdate = tick.select("line");
          tickEnter.select("line").attr(`${axisPx}2`, innerTickSize * sign);
          tickEnter.select("text").attr(axisPx, tickLength * sign);
          ctx.setTickLineTextPosition(lineUpdate, textUpdate, sizeFor1Char);
          if (params.tickTitle) {
            const title = textUpdate.select("title");
            const tickTitle = params.tickTitle;
            (title.empty() ? textUpdate.append("title") : title).text((index) => tickTitle[Number(index)]);
          }
          if (scale1.bandwidth) {
            const x = scale1;
            const dx = x.bandwidth() / 2;
            scale0 = (d) => x(d) + dx;
            scale1 = scale0;
          } else if (scale0.bandwidth) {
            scale0 = scale1;
          } else {
            tickTransform(tickExit, scale1);
          }
          tick = params.owner.state.flowing ? helper.transitionise(tick) : params.owner.$T(tick);
          tickTransform(tickEnter, scale0);
          tickTransform(tick.style("opacity", null), scale1);
        }
      }
    });
    this.g = $g;
  }
  /**
   * Get generated ticks
   * @param {number} count Count of ticks
   * @returns {Array} Generated ticks
   * @private
   */
  getGeneratedTicks(count) {
    var _a;
    const len = ((_a = this.generatedTicks) == null ? void 0 : _a.length) - 1;
    let res = this.generatedTicks;
    if (len > count) {
      const interval = Math.round(len / count + 0.1);
      res = this.generatedTicks.map((v, i) => i % interval === 0 ? v : null).filter((v) => v !== null).splice(0, count);
    }
    return res;
  }
  /**
   * Get tick x/y coordinate
   * @returns {{x: number, y: number}}
   * @private
   */
  getTickXY() {
    const { config } = this;
    const pos = { x: 0, y: 0 };
    if (this.params.isCategory) {
      pos.x = config.tickCentered ? 0 : config.tickOffset;
      pos.y = config.tickCentered ? config.tickOffset : 0;
    }
    return pos;
  }
  /**
   * Get tick size
   * @param {object} d data object
   * @returns {number}
   * @private
   */
  getTickSize(d) {
    const { scale } = this.helper;
    const { config } = this;
    const { innerTickSize, range } = config;
    const tickPosition = scale(d) + (config.tickCentered ? 0 : config.tickOffset);
    return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;
  }
  /**
   * Set tick's line & text position
   * @param {d3.selection} lineUpdate Line selection
   * @param {d3.selection} textUpdate Text selection
   * @param {object} sizeFor1Char Size for 1 char
   * @private
   */
  setTickLineTextPosition(lineUpdate, textUpdate, sizeFor1Char) {
    const tickPos = this.getTickXY();
    const { innerTickSize, orient, tickLength, tickOffset } = this.config;
    const axisId = this.params.id;
    const rotate = this.params.tickTextRotate;
    const baseHeight = 6;
    const charHeight = sizeFor1Char.h / 2 - baseHeight;
    const textAnchorForText = (r) => {
      const value = ["start", "end"];
      orient === "top" && value.reverse();
      return !r ? "middle" : value[r > 0 ? 0 : 1];
    };
    const textTransform = (r) => r ? `rotate(${r})` : null;
    const yForText = (r) => {
      const r2 = r / (orient === "bottom" ? 15 : 23);
      const y = r ? 11.5 - 2.5 * r2 * (r > 0 ? 1 : -1) : tickLength;
      return y;
    };
    const {
      config: {
        axis_rotated: isRotated,
        axis_x_tick_text_inner: inner
      }
    } = this.params.owner;
    const tickLineInner = this.params.config[`axis_${getBaseAxisId(axisId)}_tick_inner`];
    switch (orient) {
      case "bottom":
        lineUpdate.attr("x1", tickPos.x).attr("x2", tickPos.x).attr("y2", (d) => this.getTickSize.bind(this)(d) * (tickLineInner ? -1 : 1));
        textUpdate.attr("x", 0).attr("y", yForText(rotate)).style("text-anchor", (d, i, { length }) => {
          if (!isRotated && i === 0 && (inner === true || inner.first)) {
            return "start";
          } else if (!isRotated && i === length - 1 && (inner === true || inner.last)) {
            return "end";
          }
          return textAnchorForText(rotate);
        }).attr("transform", textTransform(rotate));
        break;
      case "top":
        lineUpdate.attr("x2", 0).attr("y2", tickLineInner ? innerTickSize : -innerTickSize);
        textUpdate.attr("x", 0).attr("y", -(yForText(rotate) + charHeight + baseHeight)).style("text-anchor", textAnchorForText(rotate)).attr("transform", textTransform(rotate));
        break;
      case "left":
        lineUpdate.attr("x2", tickLineInner ? innerTickSize : -innerTickSize).attr("y1", tickPos.y).attr("y2", tickPos.y);
        textUpdate.attr("x", -tickLength).attr("y", tickOffset + (isRotated ? charHeight / 4 : charHeight)).style("text-anchor", "end");
        break;
      case "right":
        lineUpdate.attr("x2", tickLineInner ? -innerTickSize : innerTickSize).attr("y2", 0);
        textUpdate.attr("x", tickLength).attr("y", charHeight).style("text-anchor", "start");
    }
  }
  // this should be called only when category axis
  splitTickText(d, scale, ticks, isLeftRight, charWidth) {
    const { params } = this;
    const tickText = this.helper.textFormatted(d);
    const splitted = isString(tickText) && tickText.indexOf("\n") > -1 ? tickText.split("\n") : [];
    if (splitted.length) {
      return splitted;
    }
    if (isArray(tickText)) {
      return tickText;
    }
    let tickWidth = params.tickWidth;
    if (!tickWidth || tickWidth <= 0) {
      tickWidth = isLeftRight ? 95 : params.isCategory ? (params.isInverted ? scale(ticks[0]) - scale(ticks[1]) : scale(ticks[1]) - scale(ticks[0])) - 12 : 110;
    }
    function split(splitted2, text) {
      let subtext;
      let spaceIndex;
      let textWidth;
      for (let i = 1; i < text.length; i++) {
        if (text.charAt(i) === " ") {
          spaceIndex = i;
        }
        subtext = text.substr(0, i + 1);
        textWidth = charWidth * subtext.length;
        if (tickWidth < textWidth) {
          return split(
            splitted2.concat(text.substr(0, spaceIndex || i)),
            text.slice(spaceIndex ? spaceIndex + 1 : i)
          );
        }
      }
      return splitted2.concat(text);
    }
    return split(splitted, String(tickText));
  }
  scale(x) {
    if (!arguments.length) {
      return this.helper.scale;
    }
    this.helper.scale = x;
    return this;
  }
  orient(x) {
    if (!arguments.length) {
      return this.config.orient;
    }
    this.config.orient = x in {
      top: 1,
      right: 1,
      bottom: 1,
      left: 1
    } ? String(x) : "bottom";
    return this;
  }
  tickFormat(format) {
    const { config } = this;
    if (!arguments.length) {
      return config.tickFormat;
    }
    config.tickFormat = format;
    return this;
  }
  tickCentered(isCentered) {
    const { config } = this;
    if (!arguments.length) {
      return config.tickCentered;
    }
    config.tickCentered = isCentered;
    return this;
  }
  /**
   * Return tick's offset value.
   * The value will be set for 'category' axis type.
   * @returns {number}
   * @private
   */
  tickOffset() {
    return this.config.tickOffset;
  }
  /**
   * Get tick interval count
   * @private
   * @param {number} size Total data size
   * @returns {number}
   */
  tickInterval(size) {
    var _a, _b, _c;
    const { outerTickSize, tickOffset, tickValues } = this.config;
    let interval;
    if (this.params.isCategory) {
      const scale = (_a = this.params.owner.scale.zoom) != null ? _a : this.helper.scale;
      interval = tickOffset * 2 || Math.abs(scale(1) - scale(0));
    } else {
      const scale = (_b = this.params.owner.scale.zoom) != null ? _b : this.helper.scale;
      const length = this.g ? this.g.select("path.domain").node().getTotalLength() - outerTickSize * 2 : Math.abs(scale.range()[1] - scale.range()[0]);
      interval = length / (size || ((_c = this.g) == null ? void 0 : _c.selectAll("line").size()) || 1);
      if (tickValues) {
        for (let i = 0; i < tickValues.length - 1; i++) {
          const intervalByValue = scale(tickValues[i + 1]) - scale(tickValues[i]);
          if (intervalByValue && intervalByValue < interval) {
            interval = intervalByValue;
          }
        }
      }
    }
    return interval === Infinity ? 0 : interval;
  }
  ticks(...args) {
    const { config } = this;
    if (!args.length) {
      return config.tickArguments;
    }
    config.tickArguments = toArray(args);
    return this;
  }
  tickCulling(culling) {
    const { config } = this;
    if (!arguments.length) {
      return config.tickCulling;
    }
    config.tickCulling = culling;
    return this;
  }
  tickValues(x) {
    const { config } = this;
    if (isFunction(x)) {
      config.tickValues = () => x(this.helper.scale.domain());
    } else {
      if (!arguments.length) {
        return config.tickValues;
      }
      config.tickValues = x;
    }
    return this;
  }
  setTransition(t) {
    this.config.transition = t;
    return this;
  }
}

;// ./src/ChartInternal/Axis/Axis.ts
var Axis_defProp = Object.defineProperty;
var Axis_defProps = Object.defineProperties;
var Axis_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var Axis_getOwnPropSymbols = Object.getOwnPropertySymbols;
var Axis_hasOwnProp = Object.prototype.hasOwnProperty;
var Axis_propIsEnum = Object.prototype.propertyIsEnumerable;
var Axis_defNormalProp = (obj, key, value) => key in obj ? Axis_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var Axis_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (Axis_hasOwnProp.call(b, prop))
      Axis_defNormalProp(a, prop, b[prop]);
  if (Axis_getOwnPropSymbols)
    for (var prop of Axis_getOwnPropSymbols(b)) {
      if (Axis_propIsEnum.call(b, prop))
        Axis_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var Axis_spreadProps = (a, b) => Axis_defProps(a, Axis_getOwnPropDescs(b));
var Axis_publicField = (obj, key, value) => Axis_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);






function Axis_getBaseAxisId(id) {
  return id === "subX" ? "x" : id === "subY" ? "y" : id === "subY2" ? "y2" : id;
}
function isSubAxis(id) {
  return /^sub/.test(id);
}
function Axis_getAxisTickOption(config, id, key) {
  const type = Axis_getBaseAxisId(id);
  const subValue = config[`subchart_axis_${type}_tick_${key}`];
  return isSubAxis(id) && subValue !== void 0 ? subValue : config[`axis_${type}_tick_${key}`];
}
function _sampleTickNodes(nodes) {
  var _a, _b;
  const sampled = [nodes[0], nodes[nodes.length - 1]];
  let maxLen = 0;
  let longestNode = null;
  for (const node of nodes) {
    const len = (_b = (_a = node.textContent) == null ? void 0 : _a.length) != null ? _b : 0;
    if (len > maxLen) {
      maxLen = len;
      longestNode = node;
    }
  }
  if (longestNode && !sampled.includes(longestNode)) {
    sampled.push(longestNode);
  }
  const mid = nodes[Math.floor(nodes.length / 2)];
  if (!sampled.includes(mid)) {
    sampled.push(mid);
  }
  return sampled;
}
const MAX_TICK_MEASURE_VALUES = 50;
const TICK_WIDTH_FALLBACK = /* @__PURE__ */ Symbol("tickWidthFallback");
function _getTickLineWidth(tickNodes) {
  var _a, _b, _c;
  const line = tickNodes.select("line").node();
  const strokeWidth = ((_b = (_a = line == null ? void 0 : line.ownerDocument) == null ? void 0 : _a.defaultView) == null ? void 0 : _b.getComputedStyle) ? parseFloat(line.ownerDocument.defaultView.getComputedStyle(line).strokeWidth) : parseFloat((_c = line == null ? void 0 : line.getAttribute) == null ? void 0 : _c.call(line, "stroke-width"));
  return Number.isFinite(strokeWidth) && strokeWidth > 0 ? strokeWidth : 1;
}
function _hasOverlappedTickLineIntervals(axis, tickValues, tickLineWidth) {
  var _a;
  const scale = (_a = axis == null ? void 0 : axis.scale) == null ? void 0 : _a.call(axis);
  if (!scale || tickValues.length < 2) {
    return false;
  }
  const halfWidth = Math.max(1, tickLineWidth) / 2;
  const positions = tickValues.map((value) => +scale(value)).filter(Number.isFinite).sort((a, b) => a - b);
  if (positions.length < 2) {
    return false;
  }
  let previousEnd = positions[0] + halfWidth;
  for (let i = 1; i < positions.length; i++) {
    const start = positions[i] - halfWidth;
    const end = positions[i] + halfWidth;
    if (start <= previousEnd + AXIS_TICK_LINE_OVERLAP_PADDING) {
      return true;
    }
    previousEnd = Math.max(previousEnd, end);
  }
  return false;
}
function _sampleTickValues(values, format) {
  if (values.length <= MAX_TICK_MEASURE_VALUES) {
    return values;
  }
  const sampled = /* @__PURE__ */ new Map();
  const add = (index) => {
    if (index >= 0 && index < values.length) {
      sampled.set(index, values[index]);
    }
  };
  add(0);
  add(values.length - 1);
  add(Math.floor(values.length / 2));
  const step = Math.max(1, Math.floor(values.length / (MAX_TICK_MEASURE_VALUES - 3)));
  let maxLength = -1;
  let maxIndex = 0;
  for (let i = 0; i < values.length; i += step) {
    add(i);
    const value = values[i];
    const text = format ? format(value) : value;
    const length = Array.isArray(text) ? text.join("").length : String(text != null ? text : "").length;
    if (length > maxLength) {
      maxLength = length;
      maxIndex = i;
    }
  }
  add(maxIndex);
  return Array.from(sampled.keys()).sort((a, b) => a - b).map((index) => sampled.get(index));
}
function _getTickValuesCacheValue(values) {
  if (isFunction(values)) {
    return _getCacheReferenceId(values);
  }
  if (!Array.isArray(values) || values.length <= MAX_TICK_MEASURE_VALUES) {
    return values;
  }
  return {
    length: values.length,
    first: values[0],
    middle: values[Math.floor(values.length / 2)],
    last: values[values.length - 1]
  };
}
function _getTickWidthFallback(ticks) {
  return ticks[TICK_WIDTH_FALLBACK];
}
function _setTickWidthFallback(ticks, width) {
  if (isNumber(width)) {
    Object.defineProperty(ticks, TICK_WIDTH_FALLBACK, {
      configurable: true,
      value: width,
      writable: true
    });
  } else {
    delete ticks[TICK_WIDTH_FALLBACK];
  }
}
function _clearTickWidths(ticks) {
  ticks.length = 0;
  _setTickWidthFallback(ticks);
}
function _compactTickWidths(ticks, length, width) {
  _clearTickWidths(ticks);
  ticks.length = length;
  _setTickWidthFallback(ticks, width);
}
function _cloneTickWidths(ticks) {
  const clone = [];
  clone.length = ticks.length;
  Object.keys(ticks).forEach((key) => {
    const index = +key;
    clone[index] = ticks[index];
  });
  _setTickWidthFallback(clone, _getTickWidthFallback(ticks));
  return clone;
}
function _restoreTickWidths(target, source) {
  _clearTickWidths(target);
  target.length = source.length;
  Object.keys(source).forEach((key) => {
    const index = +key;
    target[index] = source[index];
  });
  _setTickWidthFallback(target, _getTickWidthFallback(source));
}
function _getTickWidth(ticks, index, fallback) {
  const value = ticks[index];
  if (isNumber(value)) {
    return value;
  }
  const numericValue = Number(value);
  return Number.isFinite(numericValue) ? numericValue : fallback;
}
const cacheReferenceIds = /* @__PURE__ */ new WeakMap();
let cacheReferenceUid = 0;
function _getCacheReferenceId(value) {
  if (!value || !/^(function|object)$/.test(typeof value)) {
    return `${typeof value}:${String(value)}`;
  }
  let id = cacheReferenceIds.get(value);
  if (!id) {
    id = ++cacheReferenceUid;
    cacheReferenceIds.set(value, id);
  }
  return `${typeof value}:${id}`;
}
function _stringifyCacheValue(value) {
  if (value instanceof Date) {
    return `date:${+value}`;
  } else if (Array.isArray(value)) {
    return `[${value.map((v) => _stringifyCacheValue(v)).join(",")}]`;
  } else if (value && typeof value === "object") {
    return `{${Object.keys(value).sort().map((key) => `${key}:${_stringifyCacheValue(value[key])}`).join(
      ","
    )}}`;
  } else if (typeof value === "function") {
    return _getCacheReferenceId(value);
  }
  return `${typeof value}:${String(value)}`;
}
function _cloneCacheValue(value) {
  return value instanceof Date ? /* @__PURE__ */ new Date(+value) : Array.isArray(value) ? value.map((v) => _cloneCacheValue(v)) : value;
}
function _cloneMaxTickSize(tickSize) {
  return {
    width: tickSize.width,
    height: tickSize.height,
    ticks: tickSize.ticks && _cloneTickWidths(tickSize.ticks),
    clipPath: tickSize.clipPath,
    domain: _cloneCacheValue(tickSize.domain)
  };
}
function _restoreMaxTickSize(target, source) {
  target.width = source.width;
  target.height = source.height;
  target.clipPath = source.clipPath;
  target.domain = _cloneCacheValue(source.domain);
  if (target.ticks && source.ticks) {
    _restoreTickWidths(target.ticks, source.ticks);
  }
  return target;
}
/* harmony default export */ var Axis = ({
  getAxisInstance: function() {
    return this.axis || new Axis_Axis(this);
  }
});
class Axis_Axis {
  constructor(owner) {
    Axis_publicField(this, "owner");
    Axis_publicField(this, "x");
    Axis_publicField(this, "subX");
    Axis_publicField(this, "subY");
    Axis_publicField(this, "subY2");
    Axis_publicField(this, "y");
    Axis_publicField(this, "y2");
    Axis_publicField(this, "axesList", {});
    Axis_publicField(this, "tick", {
      x: null,
      y: null,
      y2: null
    });
    Axis_publicField(this, "xs", []);
    Axis_publicField(this, "orient", {
      x: "bottom",
      y: "left",
      y2: "right",
      subX: "bottom",
      subY: "left",
      subY2: "right"
    });
    this.owner = owner;
    this.setOrient();
  }
  getAxisClassName(id) {
    return `${$AXIS.axis} ${$AXIS[`axis${capitalize(id)}`]}`;
  }
  isHorizontal($$, forHorizontal) {
    const isRotated = $$.config.axis_rotated;
    return forHorizontal ? isRotated : !isRotated;
  }
  isCategorized() {
    const { config, state } = this.owner;
    return config.axis_x_type.indexOf("category") >= 0 || state.hasRadar;
  }
  isCustomX() {
    const { config } = this.owner;
    return !this.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
  }
  isTimeSeries(id = "x") {
    return this.owner.config[`axis_${id}_type`] === "timeseries";
  }
  isLog(id = "x") {
    return this.owner.config[`axis_${id}_type`] === "log";
  }
  isTimeSeriesY() {
    return this.isTimeSeries("y");
  }
  getAxisType(id = "x") {
    let type = "linear";
    if (this.isTimeSeries(id)) {
      type = this.owner.config.axis_x_localtime ? "time" : "utc";
    } else if (this.isLog(id)) {
      type = "log";
    }
    return type;
  }
  /**
   * Get extent value
   * @returns {Array} default extent
   * @private
   */
  getExtent() {
    const $$ = this.owner;
    const { config, scale } = $$;
    let extent = config.axis_x_extent;
    if (extent) {
      if (isFunction(extent)) {
        extent = extent.bind($$.api)($$.getXDomain($$.data.targets), scale.subX);
      } else if (this.isTimeSeries() && extent.every(isNaN)) {
        const fn = parseDate.bind($$);
        extent = extent.map((v) => scale.subX(fn(v)));
      }
    }
    return extent;
  }
  init() {
    const $$ = this.owner;
    const { config, $el: { main, axis }, state: { clip } } = $$;
    const target = ["x", "y"];
    config.axis_y2_show && target.push("y2");
    target.forEach((v) => {
      const classAxis = this.getAxisClassName(v);
      axis[v] = main.append("g").attr("class", classAxis).attr("clip-path", () => {
        let res = null;
        if (v === "x") {
          res = clip.pathXAxis;
        } else if (v === "y") {
          res = clip.pathYAxis;
        }
        return res;
      }).attr("transform", $$.getTranslate(v)).style("visibility", config[`axis_${v}_show`] ? null : "hidden");
      this.generateAxes(v);
    });
  }
  /**
   * Set axis orient according option value
   * @private
   */
  setOrient() {
    const $$ = this.owner;
    const {
      axis_rotated: isRotated,
      axis_y_inner: yInner,
      axis_y2_inner: y2Inner
    } = $$.config;
    this.orient = {
      x: isRotated ? "left" : "bottom",
      y: isRotated ? yInner ? "top" : "bottom" : yInner ? "right" : "left",
      y2: isRotated ? y2Inner ? "bottom" : "top" : y2Inner ? "left" : "right",
      subX: isRotated ? "left" : "bottom",
      subY: isRotated ? yInner ? "top" : "bottom" : yInner ? "right" : "left",
      subY2: isRotated ? y2Inner ? "bottom" : "top" : y2Inner ? "left" : "right"
    };
  }
  /**
   * Generate axes
   * It's used when axis' axes option is set
   * @param {string} id Axis id
   * @private
   */
  generateAxes(id) {
    const $$ = this.owner;
    const { config } = $$;
    const axes = [];
    const axesConfig = config[`axis_${id}_axes`];
    const isRotated = config.axis_rotated;
    let orient;
    if (id === "x") {
      orient = isRotated ? "left" : "bottom";
    } else if (id === "y") {
      orient = isRotated ? "bottom" : "left";
    } else if (id === "y2") {
      orient = isRotated ? "top" : "right";
    }
    if (axesConfig.length) {
      axesConfig.forEach((v) => {
        const tick = v.tick || {};
        const scale = $$.scale[id].copy();
        v.domain && scale.domain(v.domain);
        const axis = new AxisRenderer({
          outerTick: tick.outer !== false,
          noTransition: false,
          config,
          id,
          isSubAxes: true,
          owner: $$
        }).scale(scale).orient(orient).tickFormat(
          isFunction(tick.format) ? tick.format.bind($$.api) : ((x) => x)
        );
        isValue(tick.count) && axis.ticks(tick.count);
        tick.values && axis.tickValues(tick.values);
        axes.push(axis);
      });
    }
    this.axesList[id] = axes;
  }
  /**
   * Update axes nodes
   * @private
   */
  updateAxes() {
    const $$ = this.owner;
    const { config, $el: { main }, $T } = $$;
    Object.keys(this.axesList).forEach((id) => {
      const axesConfig = config[`axis_${id}_axes`];
      const scale = $$.scale[id].copy();
      const range = scale.range();
      this.axesList[id].forEach((v, i) => {
        const axisRange = v.scale().range();
        if (!range.every((v2, i2) => v2 === axisRange[i2])) {
          v.scale().range(range);
        }
        const className = `${this.getAxisClassName(id)}-${i + 1}`;
        let g = main.select(`.${className.replace(/\s/, ".")}`);
        if (g.empty()) {
          g = main.append("g").attr("class", className).style("visibility", config[`axis_${id}_show`] ? null : "hidden");
          v.create(g);
        } else {
          axesConfig[i].domain && scale.domain(axesConfig[i].domain);
          v.scale(scale).create($T(g));
        }
        g.attr("transform", $$.getTranslate(id, i + 1));
      });
    });
  }
  /**
   * Set Axis & tick values
   * called from: updateScales()
   * @param {string} id Axis id string
   * @param {d3Scale} scale Scale
   * @param {boolean} outerTick If show outer tick
   * @param {boolean} noTransition If with no transition
   * @private
   */
  setAxis(id, scale, outerTick, noTransition) {
    const $$ = this.owner;
    const type = Axis_getBaseAxisId(id);
    if (!isSubAxis(id)) {
      this.tick[type] = this.getTickValues(type);
    }
    this[id] = this.getAxis(
      id,
      scale,
      outerTick,
      // do not transit x Axis on zoom and resizing
      // https://github.com/naver/billboard.js/issues/1949
      id === "x" && ($$.scale.zoom || $$.config.subchart_show || $$.state.resizing) ? true : noTransition
    );
  }
  // called from : getMaxTickSize()
  getAxis(id, scale, outerTick, noTransition, noTickTextRotate) {
    const $$ = this.owner;
    const { config } = $$;
    const isX = /^(x|subX)$/.test(id);
    const type = Axis_getBaseAxisId(id);
    const isCategory = isX && this.isCategorized();
    const orient = this.orient[id];
    const tickTextRotate = noTickTextRotate ? 0 : $$.getAxisTickRotate(type);
    let tickFormat;
    if (isX) {
      tickFormat = id === "subX" ? $$.format.subXAxisTick : $$.format.xAxisTick;
    } else {
      const fn = isSubAxis(id) ? config[`subchart_axis_${type}_tick_format`] || config[`axis_${type}_tick_format`] : config[`axis_${type}_tick_format`];
      if (isFunction(fn)) {
        tickFormat = fn.bind($$.api);
      }
    }
    let tickValues = isSubAxis(id) ? this.getTickValues(type, true) : this.tick[type];
    const axisParams = mergeObj({
      outerTick,
      noTransition,
      config,
      id,
      tickTextRotate,
      owner: $$
    }, isX && {
      isCategory,
      isInverted: config.axis_x_inverted,
      tickMultiline: config.axis_x_tick_multiline,
      tickWidth: config.axis_x_tick_width,
      tickTitle: isCategory && config.axis_x_tick_tooltip && $$.api.categories(),
      orgXScale: $$.scale.x
    });
    if (!isX) {
      axisParams.tickStepSize = config[`axis_${type}_tick_stepSize`];
    }
    const axis = new AxisRenderer(axisParams).scale(isX && $$.scale.zoom || scale).orient(orient);
    if (isX && this.isTimeSeries() && tickValues && !isFunction(tickValues)) {
      const fn = parseDate.bind($$);
      tickValues = tickValues.map((v) => fn(v));
    } else if (!isX && this.isTimeSeriesY()) {
      axis.ticks(config.axis_y_tick_time_value);
      tickValues = null;
    }
    tickValues && axis.tickValues(tickValues);
    axis.tickFormat(
      tickFormat || !isX && ($$.isStackNormalized() && $$.hasAxisGroupedData(type) && ((x) => `${x}%`))
    );
    if (isCategory) {
      axis.tickCentered(config.axis_x_tick_centered);
      if (isEmpty(config.axis_x_tick_culling)) {
        config.axis_x_tick_culling = false;
      }
    }
    const tickCount = Axis_getAxisTickOption(config, id, "count");
    tickCount && axis.ticks(tickCount);
    return axis;
  }
  updateXAxisTickValues(targets, axis) {
    var _a;
    const $$ = this.owner;
    const { config } = $$;
    const fit = config.axis_x_tick_fit;
    const generateValues = (countOption = config.axis_x_tick_count) => {
      let count = countOption;
      let values2;
      if (fit) {
        values2 = $$.mapTargetsToUniqueXs(targets);
        if (this.isCategorized() && count > values2.length) {
          count = values2.length;
        }
        values2 = this.generateTickValues(
          values2,
          count,
          this.isTimeSeries()
        );
      }
      return values2;
    };
    const values = generateValues();
    if (axis) {
      axis.tickValues(values);
    } else if (this.x) {
      const subTickValues = this.getTickValues("x", true);
      const subTickCount = Axis_getAxisTickOption(config, "subX", "count");
      const subValues = subTickValues != null ? subTickValues : subTickCount !== config.axis_x_tick_count ? generateValues(subTickCount) : values;
      this.x.tickValues(values);
      (_a = this.subX) == null ? void 0 : _a.tickValues(subValues);
    }
    return values;
  }
  getId(id) {
    const { config, scale } = this.owner;
    let axis = config.data_axes[id];
    if (!axis || !scale[axis]) {
      axis = "y";
    }
    return axis;
  }
  getXAxisTickFormat(forSubchart) {
    const $$ = this.owner;
    const { config, format } = $$;
    const tickFormat = forSubchart ? config.subchart_axis_x_tick_format || config.axis_x_tick_format : config.axis_x_tick_format;
    const isTimeSeries = this.isTimeSeries();
    const isCategorized = this.isCategorized();
    let currFormat;
    if (tickFormat) {
      if (isFunction(tickFormat)) {
        currFormat = tickFormat.bind($$.api);
      } else if (isTimeSeries) {
        currFormat = (date) => date ? format.axisTime(tickFormat)(date) : "";
      }
    } else {
      currFormat = isTimeSeries ? format.defaultAxisTime : isCategorized ? $$.categoryName : (v) => v < 0 ? v.toFixed(0) : v;
    }
    return isFunction(currFormat) ? (v) => currFormat.apply($$, isCategorized ? [v, $$.categoryName(v)] : [v]) : currFormat;
  }
  getTickValues(id, isSub = false) {
    const $$ = this.owner;
    const tickValues = isSub ? Axis_getAxisTickOption($$.config, `sub${capitalize(id)}`, "values") : $$.config[`axis_${id}_tick_values`];
    const values = isFunction(tickValues) ? tickValues.call($$.api) : tickValues;
    const axis = $$[`${id}Axis`];
    return isSub ? values != null ? values : void 0 : values || (axis ? axis.tickValues() : void 0);
  }
  getLabelOptionByAxisId(id) {
    return this.owner.config[`axis_${id}_label`];
  }
  getLabelText(id) {
    const option = this.getLabelOptionByAxisId(id);
    return isString(option) ? option : option ? option.text : null;
  }
  setLabelText(id, text) {
    const $$ = this.owner;
    const { config } = $$;
    const option = this.getLabelOptionByAxisId(id);
    if (isString(option)) {
      config[`axis_${id}_label`] = text;
    } else if (option) {
      option.text = text;
    }
  }
  getLabelPosition(id, defaultPosition) {
    const isRotated = this.owner.config.axis_rotated;
    const option = this.getLabelOptionByAxisId(id);
    const position = isObjectType(option) && option.position ? option.position : defaultPosition[+!isRotated];
    const has = (v) => !!~position.indexOf(v);
    return {
      isInner: has("inner"),
      isOuter: has("outer"),
      isLeft: has("left"),
      isCenter: has("center"),
      isRight: has("right"),
      isTop: has("top"),
      isMiddle: has("middle"),
      isBottom: has("bottom")
    };
  }
  getAxisLabelPosition(id) {
    return this.getLabelPosition(
      id,
      id === "x" ? ["inner-top", "inner-right"] : ["inner-right", "inner-top"]
    );
  }
  xForAxisLabel(id) {
    const $$ = this.owner;
    const { state: { width, height } } = $$;
    const position = this.getAxisLabelPosition(id);
    let x = position.isMiddle ? -height / 2 : 0;
    if (this.isHorizontal($$, id !== "x")) {
      x = position.isLeft ? 0 : position.isCenter ? width / 2 : width;
    } else if (position.isBottom) {
      x = -height;
    }
    return x;
  }
  textAnchorForAxisLabel(id) {
    const $$ = this.owner;
    const position = this.getAxisLabelPosition(id);
    let anchor = position.isMiddle ? "middle" : "end";
    if (this.isHorizontal($$, id !== "x")) {
      anchor = position.isLeft ? "start" : position.isCenter ? "middle" : "end";
    } else if (position.isBottom) {
      anchor = "start";
    }
    return anchor;
  }
  dxForAxisLabel(id) {
    const $$ = this.owner;
    const position = this.getAxisLabelPosition(id);
    let dx = position.isBottom ? "0.5em" : "0";
    if (this.isHorizontal($$, id !== "x")) {
      dx = position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
    } else if (position.isTop) {
      dx = "-0.5em";
    }
    return dx;
  }
  dyForAxisLabel(id) {
    const $$ = this.owner;
    const { config } = $$;
    const isRotated = config.axis_rotated;
    const isInner = this.getAxisLabelPosition(id).isInner;
    const tickRotate = config[`axis_${id}_tick_rotate`] ? $$.getHorizontalAxisHeight(id) : 0;
    const { width: maxTickWidth } = this.getMaxTickSize(id);
    let dy;
    if (id === "x") {
      const xHeight = config.axis_x_height;
      if (isRotated) {
        dy = isInner ? "1.2em" : -25 - maxTickWidth;
      } else if (isInner) {
        dy = "-0.5em";
      } else if (xHeight) {
        dy = xHeight - 10;
      } else if (tickRotate) {
        dy = tickRotate - 10;
      } else {
        dy = "3em";
      }
    } else {
      dy = {
        y: ["-0.5em", 10, "3em", "1.2em", 10],
        y2: ["1.2em", -20, "-2.2em", "-0.5em", 15]
      }[id];
      if (isRotated) {
        if (isInner) {
          dy = dy[0];
        } else if (tickRotate) {
          dy = tickRotate * (id === "y2" ? -1 : 1) - dy[1];
        } else {
          dy = dy[2];
        }
      } else {
        dy = isInner ? dy[3] : (dy[4] + (config[`axis_${id}_inner`] ? 0 : maxTickWidth + dy[4])) * (id === "y" ? -1 : 1);
      }
    }
    return dy;
  }
  getTickFormatCacheValue(id) {
    const $$ = this.owner;
    const { config } = $$;
    const isX = id === "x";
    return isX ? {
      format: config.axis_x_tick_format,
      type: config.axis_x_type,
      localtime: config.axis_x_localtime,
      categories: config.axis_x_categories
    } : {
      format: config[`axis_${id}_tick_format`],
      normalized: $$.isStackNormalized(),
      grouped: $$.hasAxisGroupedData(id),
      type: config[`axis_${id}_type`]
    };
  }
  getMaxTickSizeFingerprint(id, scale, domain, axis, tickRotate, withoutRecompute) {
    var _a;
    const $$ = this.owner;
    const { config, state } = $$;
    const isX = id === "x";
    const configPrefix = isX ? "axis_x" : `axis_${id}`;
    const tickValues = axis.tickValues();
    return _stringifyCacheValue({
      id,
      withoutRecompute: !!withoutRecompute,
      dataGeneration: state.dataGeneration,
      size: [state.current.width, state.current.height],
      range: (_a = scale.range) == null ? void 0 : _a.call(scale),
      domain,
      type: scale.type,
      orient: this.orient[id],
      axisRotated: config.axis_rotated,
      evalTextSize: config.axis_evalTextSize,
      format: this.getTickFormatCacheValue(id),
      ticks: {
        values: _getTickValuesCacheValue(tickValues),
        rawValues: config[`${configPrefix}_tick_values`],
        arguments: axis.ticks(),
        count: config[`${configPrefix}_tick_count`],
        rotate: tickRotate,
        show: config[`${configPrefix}_tick_show`],
        textShow: config[`${configPrefix}_tick_text_show`],
        textPosition: config[`${configPrefix}_tick_text_position`],
        inner: config[`${configPrefix}_tick_inner`],
        culling: config[`${configPrefix}_tick_culling`],
        cullingMax: config[`${configPrefix}_tick_culling_max`],
        cullingLines: config[`${configPrefix}_tick_culling_lines`],
        cullingReverse: config[`${configPrefix}_tick_culling_reverse`],
        stepSize: !isX && config[`${configPrefix}_tick_stepSize`],
        timeValue: !isX && config[`${configPrefix}_tick_time_value`],
        fit: isX && config.axis_x_tick_fit,
        autorotate: isX && config.axis_x_tick_autorotate,
        centered: isX && config.axis_x_tick_centered,
        inverted: isX && config.axis_x_inverted,
        multiline: isX && config.axis_x_tick_multiline,
        width: isX && config.axis_x_tick_width
      }
    });
  }
  /**
   * Get max tick size
   * @param {string} id axis id string
   * @param {boolean} withoutRecompute wheather or not to recompute
   * @returns {object} {width, height}
   * @private
   */
  getMaxTickSize(id, withoutRecompute) {
    var _a;
    const $$ = this.owner;
    const { config, state, $el: { svg, chart } } = $$;
    const { current, resizing } = state;
    const currentTickMax = current.maxTickSize[id];
    const cacheKey = `${KEY.maxTickSize}_${id}_${!!withoutRecompute}`;
    const cached = $$.cache.get(cacheKey);
    if (cached && cached.generation === state.redrawGeneration) {
      return currentTickMax;
    }
    const configPrefix = `axis_${id}`;
    const max = {
      width: 0,
      height: 0
    };
    let fingerprint;
    if (resizing || withoutRecompute || !config[`${configPrefix}_show`] || currentTickMax.width > 0 && $$.filterTargetsToShow().length === 0) {
      return currentTickMax;
    }
    if ((svg || config.render_mode === "canvas") && ((_a = $$.scale[id]) == null ? void 0 : _a.copy)) {
      const isYAxis = /^y2?$/.test(id);
      const targetsToShow = $$.getTargetsToShow();
      const scale = $$.scale[id].copy().domain(
        $$[`get${isYAxis ? "Y" : "X"}Domain`](targetsToShow, id)
      );
      const domain = scale.domain();
      const isDomainSame = domain[0] === domain[1] && domain.every((v) => v > 0);
      const isCurrentMaxTickDomainSame = isArray(currentTickMax.domain) && currentTickMax.domain[0] === currentTickMax.domain[1] && currentTickMax.domain.every((v) => v > 0);
      if (isDomainSame || isCurrentMaxTickDomainSame) {
        return currentTickMax;
      } else {
        currentTickMax.domain = domain;
      }
      if (!isYAxis) {
        _clearTickWidths(currentTickMax.ticks);
      }
      const axis = this.getAxis(id, scale, false, false, true);
      const tickRotate = config[`${configPrefix}_tick_rotate`];
      const tickCount = config[`${configPrefix}_tick_count`];
      const tickValues = config[`${configPrefix}_tick_values`];
      if (!tickValues && tickCount) {
        axis.tickValues(
          this.generateTickValues(
            domain,
            tickCount,
            isYAxis ? this.isTimeSeriesY() : this.isTimeSeries()
          )
        );
      }
      !isYAxis && this.updateXAxisTickValues(targetsToShow, axis);
      fingerprint = this.getMaxTickSizeFingerprint(
        id,
        scale,
        domain,
        axis,
        tickRotate,
        withoutRecompute
      );
      if ((cached == null ? void 0 : cached.fingerprint) === fingerprint) {
        $$.cache.add(cacheKey, Axis_spreadProps(Axis_spreadValues({}, cached), {
          generation: state.redrawGeneration
        }));
        return _restoreMaxTickSize(currentTickMax, cached.value);
      }
      const originalTickValues = axis.tickValues();
      const hasLargeTickValues = !isYAxis && Array.isArray(originalTickValues) && originalTickValues.length > MAX_TICK_MEASURE_VALUES;
      hasLargeTickValues && axis.tickValues(
        _sampleTickValues(originalTickValues, axis.tickFormat())
      );
      const dummy = chart.append("svg").style("visibility", "hidden").style("position", "fixed").style("top", "0").style("left", "0");
      const g = dummy.append("g").attr("class", `${$AXIS[`axis${capitalize(id)}`]} ${$COMMON.dummy}`);
      axis.create(g);
      const { sizeFor1Char } = g.node();
      const textSelection = dummy.selectAll("text").attr("transform", isNumber(tickRotate) ? `rotate(${tickRotate})` : null);
      const measuredTickCount = hasLargeTickValues ? originalTickValues.length : textSelection.size();
      if (sizeFor1Char) {
        textSelection.each(function(d, i) {
          const width = this.textContent.length * sizeFor1Char.w;
          const height = sizeFor1Char.h;
          max.width = Math.max(max.width, width);
          max.height = Math.max(max.height, height);
          if (!isYAxis) {
            currentTickMax.ticks[i] = width;
          }
        });
      } else {
        const textNodes = [];
        textSelection.each(function() {
          textNodes.push(this);
        });
        const nodesToMeasure = textNodes.length <= 5 ? textNodes : _sampleTickNodes(textNodes);
        nodesToMeasure.map((node) => getBoundingRect(node, true)).forEach((dim) => {
          max.width = Math.max(max.width, dim.width);
          max.height = Math.max(max.height, dim.height);
        });
        if (!isYAxis) {
          for (let i = 0; i < textNodes.length; i++) {
            currentTickMax.ticks[i] = max.width;
          }
        }
      }
      if (!isYAxis && hasLargeTickValues) {
        _compactTickWidths(currentTickMax.ticks, measuredTickCount, max.width);
      }
      dummy.remove();
    }
    Object.keys(max).forEach((key) => {
      if (max[key] > 0) {
        currentTickMax[key] = max[key];
      }
    });
    $$.cache.add(cacheKey, {
      fingerprint,
      generation: state.redrawGeneration,
      value: _cloneMaxTickSize(currentTickMax)
    });
    return currentTickMax;
  }
  getXAxisTickTextY2Overflow(defaultPadding) {
    const $$ = this.owner;
    const { axis, config, state: { current, isLegendRight, legendItemWidth } } = $$;
    const xAxisTickRotate = $$.getAxisTickRotate("x");
    const positiveRotation = xAxisTickRotate > 0 && xAxisTickRotate < 90;
    if ((axis.isCategorized() || axis.isTimeSeries()) && config.axis_x_tick_fit && (!config.axis_x_tick_culling || isEmpty(config.axis_x_tick_culling)) && !config.axis_x_tick_multiline && positiveRotation) {
      const y2AxisWidth = config.axis_y2_show && current.maxTickSize.y2.width || 0;
      const legendWidth = isLegendRight && legendItemWidth || 0;
      const widthWithoutCurrentPaddingLeft = current.width - $$.getCurrentPaddingByDirection("left");
      const maxOverflow = this.getXAxisTickMaxOverflow(
        xAxisTickRotate,
        widthWithoutCurrentPaddingLeft - defaultPadding
      ) - y2AxisWidth - legendWidth;
      const xAxisTickTextY2Overflow = Math.max(0, maxOverflow) + defaultPadding;
      return Math.min(xAxisTickTextY2Overflow, widthWithoutCurrentPaddingLeft / 2);
    }
    return 0;
  }
  getXAxisTickMaxOverflow(xAxisTickRotate, widthWithoutCurrentPaddingLeft) {
    var _a;
    const $$ = this.owner;
    const { axis, config, state } = $$;
    const isTimeSeries = axis.isTimeSeries();
    const tickTextWidths = state.current.maxTickSize.x.ticks;
    const tickCount = tickTextWidths.length;
    const fallbackTickTextWidth = (_a = _getTickWidthFallback(tickTextWidths)) != null ? _a : state.current.maxTickSize.x.width;
    const { left, right } = state.axis.x.padding;
    let maxOverflow = 0;
    const remaining = tickCount - (isTimeSeries && config.axis_x_tick_fit ? 0.5 : 0);
    for (let i = 0; i < tickCount; i++) {
      const tickIndex = i + 1;
      const rotatedTickTextWidth = Math.cos(Math.PI * xAxisTickRotate / 180) * _getTickWidth(tickTextWidths, i, fallbackTickTextWidth);
      const ticksBeforeTickText = tickIndex - (isTimeSeries ? 1 : 0.5) + left;
      if (ticksBeforeTickText <= 0) {
        continue;
      }
      const xAxisLengthWithoutTickTextWidth = widthWithoutCurrentPaddingLeft - rotatedTickTextWidth;
      const tickLength = xAxisLengthWithoutTickTextWidth / ticksBeforeTickText;
      const remainingTicks = remaining - tickIndex;
      const paddingRightLength = right * tickLength;
      const remainingTickWidth = remainingTicks * tickLength + paddingRightLength;
      const overflow = rotatedTickTextWidth - tickLength / 2 - remainingTickWidth;
      maxOverflow = Math.max(maxOverflow, overflow);
    }
    const filteredTargets = $$.getTargetsToShow();
    let tickOffset = 0;
    if (!isTimeSeries && config.axis_x_tick_count <= filteredTargets.length && filteredTargets[0].values.length) {
      const scale = getScale(
        $$.axis.getAxisType("x"),
        0,
        widthWithoutCurrentPaddingLeft - maxOverflow
      ).domain([
        left * -1,
        $$.getXDomainMax($$.data.targets) + 1 + right
      ]);
      tickOffset = (scale(1) - scale(0)) / 2;
    }
    return maxOverflow + tickOffset;
  }
  /**
   * Update axis label text
   * @param {boolean} withTransition Weather update with transition
   * @private
   */
  updateLabels(withTransition) {
    const $$ = this.owner;
    const { config, $el: { main }, $T } = $$;
    const isRotated = config.axis_rotated;
    ["x", "y", "y2"].forEach((id) => {
      const text = this.getLabelText(id);
      const selector = `axis${capitalize(id)}`;
      const classLabel = $AXIS[`${selector}Label`];
      if (text) {
        let axisLabel = main.select(`text.${classLabel}`);
        if (axisLabel.empty()) {
          axisLabel = main.select(`g.${$AXIS[selector]}`).insert("text", ":first-child").attr("class", classLabel).attr("transform", ["rotate(-90)", null][id === "x" ? +!isRotated : +isRotated]).style("text-anchor", () => this.textAnchorForAxisLabel(id));
        }
        $T(axisLabel, withTransition).attr("x", () => this.xForAxisLabel(id)).attr("dx", () => this.dxForAxisLabel(id)).attr("dy", () => this.dyForAxisLabel(id)).text(text);
      }
    });
  }
  /**
   * Get axis padding value
   * @param {number|object} padding Padding object
   * @param {string} key Key string of padding
   * @param {Date|number} defaultValue Default value
   * @param {number} domainLength Domain length
   * @returns {number} Padding value in scale
   * @private
   */
  getPadding(padding, key, defaultValue, domainLength) {
    const p = isNumber(padding) ? padding : padding[key];
    if (!isValue(p)) {
      return defaultValue;
    }
    return this.owner.convertPixelToScale(
      /(bottom|top)/.test(key) ? "y" : "x",
      p,
      domainLength
    );
  }
  generateTickValues(values, tickCount, forTimeSeries) {
    let tickValues = values;
    if (tickCount) {
      const targetCount = isFunction(tickCount) ? tickCount() : tickCount;
      if (targetCount === 1) {
        tickValues = [values[0]];
      } else if (targetCount === 2) {
        tickValues = [values[0], values[values.length - 1]];
      } else if (targetCount > 2) {
        const isCategorized = this.isCategorized();
        const count = targetCount - 2;
        const start = values[0];
        const end = values[values.length - 1];
        const interval = (end - start) / (count + 1);
        let tickValue;
        tickValues = [start];
        for (let i = 0; i < count; i++) {
          tickValue = +start + interval * (i + 1);
          tickValues.push(
            forTimeSeries ? new Date(tickValue) : isCategorized ? Math.round(tickValue) : tickValue
          );
        }
        tickValues.push(end);
      }
    }
    if (!forTimeSeries) {
      tickValues = tickValues.sort((a, b) => a - b);
    }
    return tickValues;
  }
  generateTransitions(withTransition) {
    const $$ = this.owner;
    const { $el: { axis }, $T } = $$;
    const [axisX, axisY, axisY2, axisSubX, axisSubY, axisSubY2] = [
      "x",
      "y",
      "y2",
      "subX",
      "subY",
      "subY2"
    ].map((v) => $T(axis[v], withTransition));
    return { axisX, axisY, axisY2, axisSubX, axisSubY, axisSubY2 };
  }
  redraw(transitions, isHidden, isInit) {
    const $$ = this.owner;
    const { config, state, $el } = $$;
    const opacity = isHidden ? "0" : null;
    ["x", "y", "y2", "subX", "subY", "subY2"].forEach((id) => {
      const axis = this[id];
      const $axis = $el.axis[id];
      if (axis && $axis) {
        if (!isInit && !config.transition_duration) {
          axis.config.withoutTransition = true;
        }
        $axis.style("opacity", opacity);
        axis.create(transitions[`axis${capitalize(id)}`]);
      }
    });
    this.updateAxes();
    !state.rendered && config.axis_tooltip && this.setAxisTooltip();
  }
  /**
   * Synchronize axis domains and tick values.
   * @param {Array} targetsToShow targets data to be shown
   * @param {object} wth option object
   * @param {object} flow flow object
   * @private
   */
  syncAxisDomains(targetsToShow, wth, flow) {
    var _a;
    const $$ = this.owner;
    const { config, scale, $el } = $$;
    const hasZoom = !!scale.zoom;
    let xDomainForZoom;
    if (!hasZoom && this.isCategorized() && targetsToShow.length === 0 && $el.axis.x) {
      scale.x.domain([0, $el.axis.x.selectAll(".tick").size()]);
    }
    if (scale.x && targetsToShow.length) {
      !hasZoom && $$.updateXDomain(
        targetsToShow,
        wth.UpdateXDomain,
        wth.UpdateOrgXDomain,
        wth.TrimXDomain
      );
      if (!config.axis_x_tick_values) {
        this.updateXAxisTickValues(targetsToShow);
      }
    } else if (this.x) {
      this.x.tickValues([]);
      (_a = this.subX) == null ? void 0 : _a.tickValues([]);
    }
    if (config.zoom_rescale && !flow) {
      xDomainForZoom = scale.x.orgDomain();
    }
    ["y", "y2"].forEach((key) => {
      const prefix = `axis_${key}_`;
      const axisScale = scale[key];
      if (axisScale) {
        const tickValues = config[`${prefix}tick_values`];
        const tickCount = config[`${prefix}tick_count`];
        axisScale.domain($$.getYDomain(targetsToShow, key, xDomainForZoom));
        if (!tickValues && tickCount) {
          const axis = $$.axis[key];
          const domain = axisScale.domain();
          axis.tickValues(
            this.generateTickValues(
              domain,
              domain.every((v) => v === 0) ? 1 : tickCount,
              this.isTimeSeriesY()
            )
          );
        }
      }
    });
    if (wth.Y) {
      const updateSubDomain = () => {
        var _a2, _b;
        (_a2 = scale.subY) == null ? void 0 : _a2.domain($$.getYDomain(targetsToShow, "y"));
        (_b = scale.subY2) == null ? void 0 : _b.domain($$.getYDomain(targetsToShow, "y2"));
        ["y", "y2"].forEach((key) => {
          const subAxisId = key === "y2" ? "subY2" : "subY";
          const axisScale = scale[subAxisId];
          const axis = $$.axis[subAxisId];
          const tickValues = this.getTickValues(key, true);
          const tickCount = Axis_getAxisTickOption(config, subAxisId, "count");
          if (!axisScale || !axis || tickValues || !tickCount) {
            return;
          }
          const domain = axisScale.domain();
          axis.tickValues(
            this.generateTickValues(
              domain,
              domain.every((v) => v === 0) ? 1 : tickCount,
              this.isTimeSeriesY()
            )
          );
        });
      };
      config.subchart_show ? $$.withSubchartTypeContext(updateSubDomain) : updateSubDomain();
    }
  }
  /**
   * Redraw axis
   * @param {Array} targetsToShow targets data to be shown
   * @param {object} wth option object
   * @param {d3.Transition} transitions Transition object
   * @param {object} flow flow object
   * @param {boolean} isInit called from initialization
   * @private
   */
  redrawAxis(targetsToShow, wth, transitions, flow, isInit) {
    const $$ = this.owner;
    this.syncAxisDomains(targetsToShow, wth, flow);
    this.redraw(transitions, $$.hasArcType(), isInit);
    this.updateLabels(wth.Transition);
    if ((wth.UpdateXDomain || wth.UpdateXAxis || wth.Y) && targetsToShow.length) {
      this.setCulling();
    }
  }
  /**
   * Set manual culling
   * @private
   */
  setCulling() {
    const $$ = this.owner;
    const { config, state: { clip, current }, $el } = $$;
    ["subX", "x", "y", "y2", "subY", "subY2"].forEach((type) => {
      const axis = $el.axis[type];
      const toCull = Axis_getAxisTickOption(config, type, "culling");
      if (axis && toCull) {
        const tickNodes = axis.selectAll(".tick");
        const tickValues = sortValue(
          tickNodes.data(),
          !Axis_getAxisTickOption(config, type, "culling_reverse")
        );
        const tickSize = tickValues.length;
        const cullingMax = Axis_getAxisTickOption(config, type, "culling_max");
        const lines = Axis_getAxisTickOption(config, type, "culling_lines");
        const cullTickLine = !lines || _hasOverlappedTickLineIntervals(
          this[type],
          tickValues,
          _getTickLineWidth(tickNodes)
        );
        let intervalForCulling;
        if (tickSize) {
          for (let i = 1; i < tickSize; i++) {
            if (tickSize / i < cullingMax) {
              intervalForCulling = i;
              break;
            }
          }
          intervalForCulling = intervalForCulling != null ? intervalForCulling : tickSize;
          const tickIndexMap = /* @__PURE__ */ new Map();
          for (let i = 0; i < tickValues.length; i++) {
            tickIndexMap.set(tickValues[i], i);
          }
          tickNodes.each(function(d) {
            var _a;
            const node = cullTickLine ? this : this.querySelector("text");
            if (node) {
              node.style.display = ((_a = tickIndexMap.get(d)) != null ? _a : 0) % intervalForCulling ? "none" : null;
            }
          });
        } else {
          tickNodes.style("display", null);
        }
        if (type === "x") {
          const clipPath = current.maxTickSize.x.clipPath ? clip.pathXAxisTickTexts : null;
          $el.svg.selectAll(`.${$AXIS.axisX} .tick text`).attr("clip-path", clipPath);
        }
      }
    });
  }
  /**
   * Set axis tooltip
   * @private
   */
  setAxisTooltip() {
    var _a;
    const $$ = this.owner;
    const { config: { axis_rotated: isRotated, axis_tooltip }, $el: { axis, axisTooltip } } = $$;
    const bgColor = (_a = axis_tooltip.backgroundColor) != null ? _a : "black";
    $$.generateTextBGColorFilter(
      bgColor,
      {
        x: -0.15,
        y: -0.2,
        width: 1.3,
        height: 1.3
      }
    );
    ["x", "y", "y2"].forEach((v) => {
      var _a2, _b, _c;
      if (isString(bgColor) || bgColor[v]) {
        axisTooltip[v] = (_a2 = axis[v]) == null ? void 0 : _a2.append("text").classed($AXIS[`axis${v.toUpperCase()}Tooltip`], true).attr("filter", $$.updateTextBGColor({ id: v }, bgColor));
        if (isRotated) {
          const pos = v === "x" ? "x" : "y";
          const val = v === "y" ? "1.15em" : v === "x" ? "-0.3em" : "-0.4em";
          (_b = axisTooltip[v]) == null ? void 0 : _b.attr(pos, val).attr(`d${v === "x" ? "y" : "x"}`, v === "x" ? "0.4em" : "-1.3em").style("text-anchor", v === "x" ? "end" : null);
        } else {
          const pos = v === "x" ? "y" : "x";
          const val = v === "x" ? "1.15em" : `${v === "y" ? "-" : ""}0.4em`;
          (_c = axisTooltip[v]) == null ? void 0 : _c.attr(pos, val).attr(`d${v === "x" ? "x" : "y"}`, v === "x" ? "-1em" : "0.3em").style("text-anchor", v === "y" ? "end" : null);
        }
      }
    });
  }
}

;// ./src/ChartInternal/interactions/eventrect.ts
var __pow = Math.pow;


/* harmony default export */ var eventrect = ({
  /**
   * Initialize the area that detects the event.
   * Add a container for the zone that detects the event.
   * @private
   */
  initEventRect() {
    const $$ = this;
    $$.$el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $EVENT.eventRects).style("fill-opacity", "0");
  },
  /**
   * Redraws the area that detects the event.
   * @private
   */
  redrawEventRect() {
    var _a;
    const $$ = this;
    const { config, state, $el } = $$;
    const isMultipleX = $$.isMultipleX();
    const isInverted = config.axis_x_inverted;
    if ($el.eventRect) {
      $$.updateEventRect($el.eventRect, true);
    } else if ($$.data.targets.length) {
      const eventRects = $$.$el.main.select(`.${$EVENT.eventRects}`).style("cursor", config.zoom_enabled && config.zoom_type !== "drag" ? config.axis_rotated ? "ns-resize" : "ew-resize" : null).classed($EVENT.eventRectsMultiple, isMultipleX).classed($EVENT.eventRectsSingle, !isMultipleX);
      const eventRectUpdate = eventRects.selectAll(`.${$EVENT.eventRect}`).data([0]).enter().append("rect");
      $$.updateEventRect(eventRectUpdate);
      $$.updateEventType(eventRectUpdate);
      eventRectUpdate.call($$.getDraggableSelection());
      $el.eventRect = eventRectUpdate;
      if ($$.state.inputType === "touch" && !$el.svg.on("touchstart.eventRect") && !$$.hasArcType()) {
        $$.bindTouchOnEventRect();
      }
      state.rendered && $$.updateEventRect($el.eventRect, true);
    }
    if (!isMultipleX) {
      const xAxisTickValues = $$.getMaxDataCountTarget();
      if (!config.data_xSort || isInverted) {
        xAxisTickValues.sort((a, b) => isInverted ? b.x - a.x : a.x - b.x);
      }
      $$.updateDataIndexByX(xAxisTickValues);
      $$.updateXs(xAxisTickValues);
      (_a = $$.updatePointClass) == null ? void 0 : _a.call($$, true);
      state.eventReceiver.data = xAxisTickValues;
    }
    $$.updateEventRectData();
  },
  bindTouchOnEventRect() {
    const $$ = this;
    const { config, state, $el: { eventRect, svg } } = $$;
    const selectRect = (context) => {
      if ($$.isMultipleX()) {
        $$.selectRectForMultipleXs(context);
      } else {
        const index = $$.getDataIndexFromEvent(state.event);
        $$.callOverOutForTouch(index);
        index === -1 ? $$.unselectRect() : $$.selectRectForSingle(context, index);
      }
    };
    const unselectRect = () => {
      $$.unselectRect();
      $$.callOverOutForTouch();
    };
    const preventDefault = config.interaction_inputType_touch.preventDefault;
    const isPrevented = isBoolean(preventDefault) && preventDefault || false;
    const preventThreshold = !isNaN(preventDefault) && preventDefault || null;
    let startPx;
    const passiveOption = !isPrevented && preventThreshold === null;
    const preventEvent = (event) => {
      const eventType = event.type;
      const touch = event.changedTouches[0];
      const currentXY = touch[`client${config.axis_rotated ? "Y" : "X"}`];
      if (eventType === "touchstart") {
        if (isPrevented) {
          event.preventDefault();
        } else if (preventThreshold !== null) {
          startPx = currentXY;
        }
      } else if (eventType === "touchmove") {
        if (isPrevented || startPx === true || preventThreshold !== null && Math.abs(startPx - currentXY) >= preventThreshold) {
          startPx = true;
          event.preventDefault();
        }
      }
    };
    eventRect.on("touchstart", (event) => {
      state.event = event;
      $$.updateEventRect();
    }, { passive: passiveOption }).on("touchstart.eventRect touchmove.eventRect", (event) => {
      state.event = event;
      if (!eventRect.empty() && eventRect.classed($EVENT.eventRect)) {
        if (state.dragging || state.flowing || $$.hasArcType() || event.touches.length > 1) {
          return;
        }
        preventEvent(event);
        selectRect(eventRect.node());
      } else {
        unselectRect();
      }
    }, { passive: passiveOption }).on("touchend.eventRect", (event) => {
      state.event = event;
      if (!eventRect.empty() && eventRect.classed($EVENT.eventRect)) {
        if ($$.hasArcType() || !$$.toggleShape || state.cancelClick) {
          state.cancelClick && (state.cancelClick = false);
        }
      }
    }, { passive: passiveOption });
    svg.on("touchstart", (event) => {
      state.event = event;
      const { target } = event;
      if (target && target !== eventRect.node()) {
        unselectRect();
      }
    }, { passive: passiveOption });
  },
  /**
   * Update event rect size
   * @param {d3Selection} eventRect Event <rect> element
   * @param {boolean} force Force to update
   * @private
   */
  updateEventRect(eventRect, force = false) {
    const $$ = this;
    const { state, $el } = $$;
    const { eventReceiver, width, height, rendered, resizing } = state;
    const rectElement = eventRect || $el.eventRect;
    const updateClientRect = () => {
      if (eventReceiver) {
        const scrollPos = getScrollPosition($el.chart.node());
        eventReceiver.rect = getBoundingRect(rectElement.node(), true).toJSON();
        eventReceiver.rect.top += scrollPos.y;
        eventReceiver.rect.left += scrollPos.x;
      }
    };
    if (!rendered || resizing || force) {
      rectElement.attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
      if (!rendered || force) {
        rectElement.classed($EVENT.eventRect, true);
      }
    }
    updateClientRect();
  },
  /**
   * Update event type (single or multiple x)
   * @param {d3Selection | boolean} target Target element or boolean to rebind event
   */
  updateEventType(target) {
    const $$ = this;
    const isRebindCall = isBoolean(target);
    const eventRect = isRebindCall ? $$.$el.eventRect : target;
    const unbindEvent = isRebindCall ? target !== (eventRect == null ? void 0 : eventRect.datum().multipleX) : false;
    if (eventRect) {
      unbindEvent && (eventRect == null ? void 0 : eventRect.on("mouseover mousemove mouseout click", null));
      $$.isMultipleX() ? $$.generateEventRectsForMultipleXs(eventRect) : $$.generateEventRectsForSingleX(eventRect);
    }
  },
  /**
   * Updates the location and size of the eventRect.
   * @private
   */
  updateEventRectData() {
    const $$ = this;
    const { config, scale, state } = $$;
    const xScale = scale.zoom || scale.x;
    const isRotated = config.axis_rotated;
    const isMultipleX = $$.isMultipleX();
    const xDomain = xScale == null ? void 0 : xScale.domain();
    const fingerprint = xDomain ? `${xDomain[0]}_${xDomain[1]}_${state.width}_${state.height}_${$$.data.targets.length}_${state.dataGeneration}_${[...state.hiddenTargetIds].join(",")}` : null;
    if (fingerprint && fingerprint === state._eventRectFingerprint) {
      return;
    }
    state._eventRectFingerprint = fingerprint;
    let x;
    let y;
    let w;
    let h;
    $$.updateEventType(isMultipleX);
    if (isMultipleX) {
      x = 0;
      y = 0;
      w = state.width;
      h = state.height;
    } else {
      let rectW;
      let rectX;
      if ($$.axis.isCategorized()) {
        rectW = $$.getEventRectWidth();
        rectX = (d) => xScale(d.x) - rectW / 2;
      } else {
        const getPrevNextX = ({ index }) => ({
          prev: $$.getPrevX(index),
          next: $$.getNextX(index)
        });
        rectW = (d) => {
          const x2 = getPrevNextX(d);
          const xDomain2 = xScale.domain();
          let val;
          if (x2.prev === null && x2.next === null) {
            val = isRotated ? state.height : state.width;
          } else if (x2.prev === null) {
            val = (xScale(x2.next) + xScale(d.x)) / 2;
          } else if (x2.next === null) {
            val = xScale(xDomain2[1]) - (xScale(x2.prev) + xScale(d.x)) / 2;
          } else {
            val = Math.max(0, (xScale(x2.next) - xScale(x2.prev)) / 2);
          }
          return val;
        };
        rectX = (d) => {
          const x2 = getPrevNextX(d);
          let val;
          if (x2.prev === null && x2.next === null) {
            val = 0;
          } else if (x2.prev === null) {
            val = xScale(xScale.domain()[0]);
          } else {
            val = (xScale(d.x) + xScale(x2.prev)) / 2;
          }
          return val;
        };
      }
      x = isRotated ? 0 : rectX;
      y = isRotated ? rectX : 0;
      w = isRotated ? state.width : rectW;
      h = isRotated ? rectW : state.height;
    }
    const { eventReceiver } = state;
    const call = (fn, v) => isFunction(fn) ? fn(v) : fn;
    eventReceiver.coords.splice(eventReceiver.data.length);
    eventReceiver.data.forEach((d, i) => {
      eventReceiver.coords[i] = {
        x: call(x, d),
        y: call(y, d),
        w: call(w, d),
        h: call(h, d)
      };
    });
  },
  /**
   * Seletct rect for single x value
   * @param {d3Selection} context Event rect element
   * @param {number} index x Axis index
   * @private
   */
  selectRectForSingle(context, index) {
    var _a, _b, _c, _d, _e, _f, _g;
    const $$ = this;
    const { config, state, $el: { main, circle } } = $$;
    const isSelectionEnabled = config.data_selection_enabled;
    const isSelectionGrouped = config.data_selection_grouped;
    const isSelectable = config.data_selection_isselectable;
    const isTooltipGrouped = config.tooltip_grouped;
    const selectedData = $$.getAllValuesOnIndex(index);
    if (isTooltipGrouped) {
      $$.showTooltip(selectedData, context);
      (_a = $$.showGridFocus) == null ? void 0 : _a.call($$, selectedData);
      (_b = $$.showSubchartGridFocus) == null ? void 0 : _b.call($$, selectedData);
      if (!isSelectionEnabled || isSelectionGrouped) {
        return;
      }
    }
    !circle && main.selectAll(`.${$COMMON.EXPANDED}:not(.${$SHAPE.shape}-${index})`).classed(
      $COMMON.EXPANDED,
      false
    );
    const shapeAtIndex = main.selectAll(`.${$SHAPE.shape}-${index}`).classed($COMMON.EXPANDED, true).style("cursor", isSelectable ? "pointer" : null).filter(function(d) {
      return $$.isWithinShape(this, d);
    });
    shapeAtIndex.call((selected) => {
      var _a2, _b2, _c2;
      const d = selected.data();
      if (isSelectionEnabled && (isSelectionGrouped || (isSelectable == null ? void 0 : isSelectable.bind($$.api)(d)))) {
        context.style.cursor = "pointer";
      }
      if (!isTooltipGrouped) {
        $$.showTooltip(d, context);
        (_a2 = $$.showGridFocus) == null ? void 0 : _a2.call($$, d);
        (_b2 = $$.showSubchartGridFocus) == null ? void 0 : _b2.call($$, d);
        (_c2 = $$.unexpandCircles) == null ? void 0 : _c2.call($$);
        selected.each((d2) => $$.setExpand(index, d2.id));
      }
    });
    if (!isTooltipGrouped && shapeAtIndex.empty()) {
      const mouse = getPointer(state.event, context);
      const closestData = selectedData.filter((d) => {
        if ($$.isTargetToShow(d.id)) {
          const dist = $$.dist(d, mouse);
          return dist < $$.getPointSensitivity(d);
        }
        return false;
      });
      if (closestData.length > 0) {
        let closest = closestData[0];
        let minDist = $$.dist(closest, mouse);
        for (let i = 1; i < closestData.length; i++) {
          const d = closestData[i];
          const dist = $$.dist(d, mouse);
          if (dist < minDist) {
            minDist = dist;
            closest = d;
          }
        }
        $$.showTooltip([closest], context);
        (_c = $$.showGridFocus) == null ? void 0 : _c.call($$, [closest]);
        (_d = $$.showSubchartGridFocus) == null ? void 0 : _d.call($$, [closest]);
        (_e = $$.unexpandCircles) == null ? void 0 : _e.call($$);
        $$.setExpand(index, closest.id, true);
        if (isSelectionEnabled && (isSelectionGrouped || (isSelectable == null ? void 0 : isSelectable.bind($$.api)(closest)))) {
          context.style.cursor = "pointer";
        }
      } else if (config.interaction_onout) {
        (_f = $$.hideGridFocus) == null ? void 0 : _f.call($$);
        (_g = $$.hideSubchartGridFocus) == null ? void 0 : _g.call($$);
        $$.hideTooltip();
        !isSelectionGrouped && $$.setExpand(index);
      }
    }
  },
  /**
   * Select rect for multiple x values
   * @param {d3Selection} context Event rect element
   * @param {boolean} [triggerEvent=true] Whether trigger event or not
   * @private
   */
  selectRectForMultipleXs(context, triggerEvent = true) {
    var _a, _b;
    const $$ = this;
    const { config, state } = $$;
    const targetsToShow = $$.getTargetsToShow();
    if (state.dragging || $$.hasArcType(targetsToShow)) {
      return;
    }
    const mouse = getPointer(state.event, context);
    const closest = $$.findClosestFromTargets(targetsToShow, mouse);
    if (triggerEvent && state.mouseover && (!closest || closest.id !== state.mouseover.id)) {
      config.data_onout.call($$.api, state.mouseover);
      state.mouseover = void 0;
    }
    if (!closest) {
      $$.unselectRect();
      return;
    }
    const sameXData = $$.isBubbleType(closest) || $$.isScatterType(closest) || !config.tooltip_grouped ? [closest] : $$.filterByX(targetsToShow, closest.x);
    const selectedData = sameXData.map((d) => $$.addName(d));
    $$.showTooltip(selectedData, context);
    $$.setExpand(closest.index, closest.id, true);
    (_a = $$.showGridFocus) == null ? void 0 : _a.call($$, selectedData);
    (_b = $$.showSubchartGridFocus) == null ? void 0 : _b.call($$, selectedData);
    const dist = $$.dist(closest, mouse);
    if ($$.isBarType(closest.id) || dist < $$.getPointSensitivity(closest)) {
      $$.$el.eventRect.style("cursor", "pointer");
      if (triggerEvent && (!state.mouseover || state.mouseover.x !== closest.x || state.mouseover.id !== closest.id)) {
        config.data_onover.call($$.api, closest);
        state.mouseover = closest;
      }
    }
  },
  /**
   * Unselect EventRect.
   * @private
   */
  unselectRect() {
    var _a, _b, _c, _d;
    const $$ = this;
    const { state, $el: { circle, tooltip } } = $$;
    state._lastTooltipMouse = null;
    if (state.isCanvasMode) {
      (_a = $$.clearCanvasFocus) == null ? void 0 : _a.call($$);
      tooltip && $$.hideTooltip();
      return;
    }
    (_b = $$.$el.eventRect) == null ? void 0 : _b.style("cursor", null);
    (_c = $$.hideGridFocus) == null ? void 0 : _c.call($$);
    (_d = $$.hideSubchartGridFocus) == null ? void 0 : _d.call($$);
    if (tooltip) {
      $$.hideTooltip();
      $$._handleLinkedCharts(false);
    }
    circle && !$$.isPointFocusOnly() && $$.unexpandCircles();
    $$.expandBarTypeShapes(false);
  },
  /**
   * Create eventRect for each data on the x-axis.
   * Register touch and drag events.
   * @param {object} eventRectEnter d3.select($EVENT.eventRects) object.
   * @returns {object} d3.select($EVENT.eventRects) object.
   * @private
   */
  generateEventRectsForSingleX(eventRectEnter) {
    const $$ = this;
    const { config, state } = $$;
    const { eventReceiver } = state;
    const rect = eventRectEnter.style(
      "cursor",
      config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null
    ).on("click", function(event) {
      state.event = event;
      const { currentIdx, data } = eventReceiver;
      const d = data[currentIdx === -1 ? $$.getDataIndexFromEvent(event) : currentIdx];
      $$.clickHandlerForSingleX.bind(this)(d, $$);
    }).datum({ multipleX: false });
    if (state.inputType === "mouse") {
      const getData = (event) => {
        const index = event ? $$.getDataIndexFromEvent(event) : eventReceiver.currentIdx;
        return index > -1 ? eventReceiver.data[index] : null;
      };
      rect.on("mouseover", (event) => {
        state.event = event;
        $$.updateEventRect();
        Object.values($$.$el.axisTooltip).forEach((v) => v == null ? void 0 : v.style("display", null));
      }).on("mousemove", function(event) {
        var _a;
        const d = getData(event);
        state.event = event;
        if (!d) {
          return;
        }
        let { index } = d;
        const stepType = config.line_step_type;
        if (config.line_step_tooltipMatch && $$.hasType("step") && /^step\-(before|after)$/.test(stepType)) {
          const scale = $$.scale.zoom || $$.scale.x;
          const xs = $$.axis.xs[index];
          const inverted = scale.invert(getPointer(event, this)[0]);
          if (stepType === "step-after" && inverted < xs) {
            index -= 1;
          } else if (stepType === "step-before" && inverted > xs) {
            index += 1;
          }
        }
        (_a = $$.showAxisGridFocus) == null ? void 0 : _a.call($$);
        const eventOnSameIdx = config.tooltip_grouped && index === eventReceiver.currentIdx;
        if (state.dragging || state.flowing || $$.hasArcType() || eventOnSameIdx) {
          if (config.tooltip_show && eventOnSameIdx) {
            const [mx, my] = getPointer(event, this);
            const last = state._lastTooltipMouse;
            if (!last || __pow(mx - last[0], 2) + __pow(my - last[1], 2) >= 9) {
              state._lastTooltipMouse = [mx, my];
              $$.setTooltipPosition();
            }
          }
          return;
        }
        if (index !== eventReceiver.currentIdx) {
          $$.setOverOut(false, eventReceiver.currentIdx);
          eventReceiver.currentIdx = index;
        }
        index === -1 ? $$.unselectRect() : $$.selectRectForSingle(this, index);
        $$.setOverOut(index !== -1, index);
      }).on("mouseout", (event) => {
        var _a;
        state.event = event;
        if (!$$.config || $$.hasArcType() || eventReceiver.currentIdx === -1 || !config.interaction_onout) {
          return;
        }
        (_a = $$.hideAxisGridFocus) == null ? void 0 : _a.call($$);
        $$.unselectRect();
        $$.setOverOut(false, eventReceiver.currentIdx);
        eventReceiver.currentIdx = -1;
      });
    }
    return rect;
  },
  clickHandlerForSingleX(d, ctx) {
    const $$ = ctx;
    const { config, state, $el: { main } } = $$;
    if (!d || $$.hasArcType() || state.cancelClick) {
      state.cancelClick && (state.cancelClick = false);
      return;
    }
    const { index } = d;
    main.selectAll(`.${$SHAPE.shape}-${index}`).each(function(d2) {
      var _a;
      if (config.data_selection_grouped || $$.isWithinShape(this, d2)) {
        (_a = $$.toggleShape) == null ? void 0 : _a.call($$, this, d2, index);
        config.data_onclick.bind($$.api)(d2, this);
      }
    });
  },
  /**
   * Create an eventRect,
   * Register touch and drag events.
   * @param {object} eventRectEnter d3.select($EVENT.eventRects) object.
   * @private
   */
  generateEventRectsForMultipleXs(eventRectEnter) {
    const $$ = this;
    const { config, state } = $$;
    eventRectEnter.on("click", function(event) {
      state.event = event;
      $$.clickHandlerForMultipleXS.bind(this)($$);
    }).datum({ multipleX: true });
    if (state.inputType === "mouse") {
      eventRectEnter.on("mouseover mousemove", function(event) {
        state.event = event;
        $$.selectRectForMultipleXs(this);
      }).on("mouseout", (event) => {
        state.event = event;
        if (!$$.config || $$.hasArcType() || !config.interaction_onout) {
          return;
        }
        $$.unselectRect();
      });
    }
  },
  clickHandlerForMultipleXS(ctx) {
    const $$ = ctx;
    const { config, state } = $$;
    const targetsToShow = $$.getTargetsToShow();
    if ($$.hasArcType(targetsToShow)) {
      return;
    }
    const mouse = getPointer(state.event, this);
    const closest = $$.findClosestFromTargets(targetsToShow, mouse);
    if (!closest) {
      return;
    }
    const sensitivity = $$.getPointSensitivity(closest);
    if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < sensitivity) {
      $$.$el.main.selectAll(`.${$SHAPE.shapes}${$$.getTargetSelectorSuffix(closest.id)}`).selectAll(`.${$SHAPE.shape}-${closest.index}`).each(function() {
        var _a;
        if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
          (_a = $$.toggleShape) == null ? void 0 : _a.call($$, this, closest, closest.index);
          config.data_onclick.bind($$.api)(closest, this);
        }
      });
    }
  }
});

;// ./src/ChartInternal/internals/clip.ts
/* harmony default export */ var clip = ({
  initClip() {
    const $$ = this;
    const { clip, datetimeId } = $$.state;
    clip.id = `${datetimeId}-clip`;
    clip.idXAxis = `${clip.id}-xaxis`;
    clip.idYAxis = `${clip.id}-yaxis`;
    clip.idGrid = `${clip.id}-grid`;
    clip.path = $$.getClipPath(clip.id);
    clip.pathXAxis = $$.getClipPath(clip.idXAxis);
    clip.pathYAxis = $$.getClipPath(clip.idYAxis);
    clip.pathGrid = $$.getClipPath(clip.idGrid);
  },
  getClipPath(id) {
    const $$ = this;
    const { config } = $$;
    if (!config.clipPath && /-clip$/.test(id) || !config.axis_x_clipPath && /-clip-xaxis$/.test(id) || !config.axis_y_clipPath && /-clip-yaxis$/.test(id)) {
      return null;
    }
    return `url(#${id})`;
  },
  appendClip(parent, id) {
    id && parent.append("clipPath").attr("id", id).append("rect");
  },
  /**
   * Set x Axis clipPath dimension
   * @param {d3Selecton} node clipPath <rect> selection
   * @private
   */
  setXAxisClipPath(node) {
    const $$ = this;
    const { config, state: { margin, width, height } } = $$;
    const isRotated = config.axis_rotated;
    const left = Math.max(30, margin.left) - (isRotated ? 0 : 20);
    const h = (isRotated ? margin.top + height + 10 : margin.bottom) + 20;
    const x = isRotated ? -(1 + left) : -(left - 1);
    const y = -15;
    const w = isRotated ? margin.left + 20 : width + 10 + left;
    node.attr("x", x).attr("y", y).attr("width", w).attr("height", h);
  },
  /**
   * Set y Axis clipPath dimension
   * @param {d3Selection} node clipPath <rect> selection
   * @private
   */
  setYAxisClipPath(node) {
    const $$ = this;
    const { config, state: { margin, width, height } } = $$;
    const isRotated = config.axis_rotated;
    const left = Math.max(30, margin.left) - (isRotated ? 20 : 0);
    const isInner = config.axis_y_inner;
    const x = isInner && !isRotated ? config.axis_y_label.text ? -20 : -1 : isRotated ? -(1 + left) : -(left - 1);
    const y = -(isRotated ? 20 : margin.top);
    const w = (isRotated ? width + 15 + left : margin.left + 20) + (isInner ? 20 : 0);
    const h = (isRotated ? margin.bottom + 10 : margin.top + height) + 10;
    node.attr("x", x).attr("y", y).attr("width", w).attr("height", h);
  },
  updateXAxisTickClip() {
    const $$ = this;
    const { config, state: { clip, xAxisHeight }, $el: { defs } } = $$;
    const newXAxisHeight = $$.getHorizontalAxisHeight("x");
    if (defs && !clip.idXAxisTickTexts) {
      const clipId = `${clip.id}-xaxisticktexts`;
      $$.appendClip(defs, clipId);
      clip.idXAxisTickTexts = clipId;
      clip.pathXAxisTickTexts = $$.getClipPath(clip.idXAxisTickTexts);
    }
    if (!config.axis_x_tick_multiline && $$.getAxisTickRotate("x") && newXAxisHeight !== xAxisHeight) {
      $$.setXAxisTickClipWidth();
      $$.setXAxisTickTextClipPathWidth();
    }
    $$.state.xAxisHeight = newXAxisHeight;
  },
  setXAxisTickClipWidth() {
    const $$ = this;
    const { config, state: { current: { maxTickSize } } } = $$;
    const xAxisTickRotate = $$.getAxisTickRotate("x");
    if (!config.axis_x_tick_multiline && xAxisTickRotate) {
      const sinRotation = Math.sin(Math.PI / 180 * Math.abs(xAxisTickRotate));
      maxTickSize.x.clipPath = ($$.getHorizontalAxisHeight("x") - 20) / sinRotation;
    } else {
      maxTickSize.x.clipPath = null;
    }
  },
  setXAxisTickTextClipPathWidth() {
    const $$ = this;
    const { state: { clip, current }, $el: { svg } } = $$;
    if (svg) {
      svg.select(`#${clip.idXAxisTickTexts} rect`).attr("width", current.maxTickSize.x.clipPath).attr("height", 30);
    }
  }
});

;// ./src/ChartInternal/internals/size.axis.ts

/* harmony default export */ var size_axis = ({
  /**
   * Get Axis size according its position
   * @param {string} id Axis id value - x, y or y2
   * @returns {number} size Axis size value
   * @private
   */
  getAxisSize(id) {
    const $$ = this;
    const isRotated = $$.config.axis_rotated;
    return isRotated && id === "x" || !isRotated && /y2?/.test(id) ? $$.getAxisWidthByAxisId(id, true) : $$.getHorizontalAxisHeight(id);
  },
  getAxisWidthByAxisId(id, withoutRecompute) {
    var _a, _b;
    const $$ = this;
    if ($$.axis) {
      const position = (_a = $$.axis) == null ? void 0 : _a.getAxisLabelPosition(id);
      const { width } = $$.axis.getMaxTickSize(id, withoutRecompute);
      const gap = width === 0 ? 0.5 : 0;
      return width + (((_b = $$.config.padding) == null ? void 0 : _b.mode) === "fit" ? position.isInner ? 10 + gap : 10 : position.isInner ? 20 + gap : 40);
    } else {
      return 40;
    }
  },
  getHorizontalAxisHeight(id) {
    var _a, _b;
    const $$ = this;
    const { config, state } = $$;
    const { rotatedPadding, isLegendRight, isLegendInset } = state;
    const isRotated = config.axis_rotated;
    const isFitPadding = ((_a = config.padding) == null ? void 0 : _a.mode) === "fit";
    const isInner = config[`axis_${id}_inner`];
    const hasLabelText = config[`axis_${id}_label`].text;
    const defaultHeight = 13;
    let h = ((_b = config.padding) == null ? void 0 : _b.mode) === "fit" ? isInner && !hasLabelText ? id === "y" ? 1 : 0 : 20 : 30;
    if (id === "x" && !config.axis_x_show) {
      return 8;
    }
    if (id === "x" && isNumber(config.axis_x_height)) {
      return config.axis_x_height;
    }
    if (id === "y" && !config.axis_y_show) {
      return config.legend_show && !isLegendRight && !isLegendInset ? 10 : 1;
    }
    if (id === "y2" && !config.axis_y2_show) {
      return isFitPadding ? 0 : rotatedPadding.top;
    }
    const maxtickSize = $$.axis.getMaxTickSize(id);
    const isXAxisTickRotated = Math.abs(config.axis_x_tick_rotate) > 0 && (!config.axis_x_tick_autorotate || $$.needToRotateXAxisTickTexts());
    if ((config.axis_x_tick_multiline || isXAxisTickRotated) && maxtickSize.height > defaultHeight) {
      h += maxtickSize.height - defaultHeight;
    }
    return h + ($$.axis.getAxisLabelPosition(id).isInner ? 0 : 10) + (id === "y2" && !isRotated ? -10 : 0);
  },
  getEventRectWidth() {
    const $$ = this;
    const { config, axis } = $$;
    const isInverted = config.axis_x_inverted;
    const tickInterval = axis.x.tickInterval();
    return Math.max(0, isInverted ? Math.abs(tickInterval) : tickInterval);
  },
  /**
   * Get axis tick test rotate value
   * @param {string} id Axis id
   * @returns {number} rotate value
   * @private
   */
  getAxisTickRotate(id) {
    const $$ = this;
    const { axis, config, state, $el } = $$;
    let rotate = config[`axis_${id}_tick_rotate`];
    if (id === "x") {
      const allowedXAxisTypes = axis.isCategorized() || axis.isTimeSeries();
      if (config.axis_x_tick_fit && allowedXAxisTypes) {
        const xTickCount = config.axis_x_tick_count;
        const currentXTicksLength = state.current.maxTickSize.x.ticks.length;
        let tickCount = 0;
        if (xTickCount) {
          tickCount = xTickCount > currentXTicksLength ? currentXTicksLength : xTickCount;
        } else if (currentXTicksLength) {
          tickCount = currentXTicksLength;
        }
        if (tickCount !== state.axis.x.tickCount) {
          const { targets } = $$.data;
          state.axis.x.padding = $$.getXDomainPadding([
            $$.getXDomainMinMax(targets, "min"),
            $$.getXDomainMinMax(targets, "max")
          ], tickCount);
        }
        state.axis.x.tickCount = tickCount;
      }
      if (($el.svg || state.isCanvasMode) && config.axis_x_tick_autorotate && config.axis_x_tick_fit && !config.axis_x_tick_multiline && !config.axis_x_tick_culling && allowedXAxisTypes) {
        rotate = $$.needToRotateXAxisTickTexts() ? config.axis_x_tick_rotate : 0;
      }
    }
    return rotate;
  },
  /**
   * Check weather axis tick text needs to be rotated
   * @returns {boolean}
   * @private
   */
  needToRotateXAxisTickTexts() {
    const $$ = this;
    const { state: { axis, current, isLegendRight, legendItemWidth } } = $$;
    const legendWidth = isLegendRight && legendItemWidth;
    const xAxisLength = current.width - legendWidth - $$.getCurrentPaddingByDirection("left") - $$.getCurrentPaddingByDirection("right");
    const tickCountWithPadding = axis.x.tickCount + axis.x.padding.left + axis.x.padding.right;
    const { width } = $$.axis.getMaxTickSize("x");
    const tickLength = tickCountWithPadding ? xAxisLength / tickCountWithPadding : 0;
    return width > tickLength;
  }
});

;// ./src/config/Options/axis/x.ts
/* harmony default export */ var axis_x = ({
  /**
   * Set clip-path attribute for x axis element
   * @name axis․x․clipPath
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo]()
   * @example
   * // don't set 'clip-path' attribute
   * clipPath: false
   */
  axis_x_clipPath: true,
  /**
   * Show or hide x axis.
   * @name axis․x․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   x: {
   *     show: false
   *   }
   * }
   */
  axis_x_show: true,
  /**
   * Force the x axis to interact as single rather than multiple x axes.
   * - **NOTE:** The tooltip event will be triggered nearing each data points(for multiple xs) rather than x axis based(as single x does) in below condition:
   *   - for `bubble` & `scatter` type
   *   - when `data.xs` is set
   *   - when `tooltip.grouped=false` is set
   *     - `tooltip.grouped` options will take precedence over `axis.forceSingleX` option.
   * @name axis․x․forceAsSingle
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.ForceAsSingle)
   * @example
   * axis: {
   *   x: {
   *      // will work as single x axis
   *      forceAsSingle: true
   *   }
   * }
   */
  axis_x_forceAsSingle: false,
  /**
   * Set type of x axis.<br><br>
   * **Available Values:**
   * - category
   * - indexed
   * - log
   * - timeseries
   *
   * **NOTE:**<br>
   * - **log** type:
   *   - the x values specified by [`data.x`](#.data%25E2%2580%25A4x)(or by any equivalent option), must be exclusively-positive.
   *   - x axis min value should be >= 0.
   *   - for 'category' type, `data.xs` option isn't supported.
   * @name axis․x․type
   * @memberof Options
   * @type {string}
   * @default indexed
   * @see [Demo: indexed](https://naver.github.io/billboard.js/demo/#Chart.AreaChart)
   * @see [Demo: timeseries](https://naver.github.io/billboard.js/demo/#Chart.TimeseriesChart)
   * @see [Demo: category](https://naver.github.io/billboard.js/demo/#Data.CategoryData)
   * @see [Demo: log](https://naver.github.io/billboard.js/demo/#Axis.LogScales)
   * @example
   * axis: {
   *   x: {
   *     type: "timeseries"
   *   }
   * }
   */
  axis_x_type: "indexed",
  /**
   * Set how to treat the timezone of x values.<br>
   * If true, treat x value as localtime. If false, convert to UTC internally.
   * @name axis․x․localtime
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   x: {
   *     localtime: false
   *   }
   * }
   */
  axis_x_localtime: true,
  /**
   * Set category names on category axis.
   * This must be an array that includes category names in string. If category names are included in the date by data.x option, this is not required.
   * @name axis․x․categories
   * @memberof Options
   * @type {Array}
   * @default []
   * @example
   * axis: {
   *   x: {
   *     categories: ["Category 1", "Category 2", ...]
   *   }
   * }
   */
  axis_x_categories: [],
  /**
   * centerize ticks on category axis.
   * @name axis․x․tick․centered
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       centered: true
   *     }
   *   }
   * }
   */
  axis_x_tick_centered: false,
  /**
   * A function to format tick value. Format string is also available for timeseries data.
   * @name axis․x․tick․format
   * @memberof Options
   * @type {function|string}
   * @default undefined
   * @see [D3's time specifier](https://d3js.org/d3-time-format#locale_format)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *        // for timeseries, a 'datetime' object is given as parameter
   *       format: function(x) {
   *           return x.getFullYear();
   *       }
   *
   *       // for category, index(Number) and categoryName(String) are given as parameter
   *       format: function(index, categoryName) {
   *           return categoryName.substr(0, 10);
   *       },
   *
   *        // for timeseries format specifier
   *        format: "%Y-%m-%d %H:%M:%S"
   *     }
   *   }
   * }
   */
  axis_x_tick_format: void 0,
  /**
   * Setting for culling ticks.
   * - `true`: the ticks will be culled, then only limited tick text will be shown.<br>
   *   This option does not hide the tick lines by default, if want to hide tick lines, set `axis.x.tick.culling.lines=false`.
   * - `false`: all of ticks will be shown.<br><br>
   * The number of ticks to be shown can be changed by `axis.x.tick.culling.max`.
   * @name axis․x․tick․culling
   * @memberof Options
   * @type {boolean}
   * @default
   * `true` for indexed axis and timeseries axis, `false` for category axis
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       culling: false,
   *     }
   *   }
   * }
   */
  axis_x_tick_culling: {},
  /**
   * The number of tick texts will be adjusted to less than this value.
   * @name axis․x․tick․culling․max
   * @memberof Options
   * @type {number}
   * @default 10
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       culling: {
   *           max: 5
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_culling_max: 10,
  /**
   * Control visibility of tick lines within culling option, along with tick text.
   * @name axis․x․tick․culling․lines
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       culling: {
   *           lines: false,
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_culling_lines: true,
  /**
   * Control culling start point to be reversed. If set to true, the culling will be started from the end to start.
   * - **NOTE:** This option is only available when `axis.x.tick.culling` is set to truthy value.
   * @name axis․x․tick․culling․reverse
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickCulling)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       culling: {
   *           reverse: true,
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_culling_reverse: false,
  /**
   * The number of x axis ticks to show.<br><br>
   * This option hides tick lines together with tick text. If this option is used on timeseries axis, the ticks position will be determined precisely and not nicely positioned (e.g. it will have rough second value).
   * @name axis․x․tick․count
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       count: 5
   *     }
   *   }
   * }
   */
  axis_x_tick_count: void 0,
  /**
   * Set the axis tick line to be positioned inside of the chart.
   * @name axis․x․tick․inner
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.TickInner)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       inner: true
   *     }
   *   }
   * }
   */
  axis_x_tick_inner: false,
  /**
   * Show or hide x axis tick line.
   * @name axis․x․tick․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       show: false
   *     }
   *   }
   * }
   */
  axis_x_tick_show: true,
  /**
   * Show or hide x axis tick text.
   * @name axis․x․tick․text․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       text: {
   *           show: false
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_text_show: true,
  /**
   * Set the first/last axis tick text to be positioned inside of the chart on non-rotated axis.
   * @name axis․x․tick․text․inner
   * @memberof Options
   * @type {boolean|object}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickInner)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       text: {
   *          inner: true,
   *
   *          // or specify each position of the first and last tick text
   *          inner: {
   *       	   first: true,
   *       	   last: true
   *       	}
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_text_inner: false,
  /**
   * Set the x Axis tick text's position relatively its original position
   * @name axis․x․tick․text․position
   * @memberof Options
   * @type {object}
   * @default {x: 0, y:0}
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       text: {
   *         position: {
   *           x: 10,
   *           y: 10
   *         }
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_text_position: { x: 0, y: 0 },
  /**
   * Fit x axis ticks.
   * - **true**: ticks will be shown according to x value of the data points.
   * - **false**: ticks will be shown as to have same intervals.
   * @name axis․x․tick․fit
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickFitting)
   * @see [Demo: for timeseries zoom](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickTimeseries)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       fit: false
   *     }
   *   }
   * }
   */
  axis_x_tick_fit: true,
  /**
   * Set the x values of ticks manually.<br><br>
   * If this option is provided, the position of the ticks will be determined based on those values.<br>
   * This option works with `timeseries` data and the x values will be parsed according to the type of the value and data.xFormat option.
   * @name axis․x․tick․values
   * @memberof Options
   * @type {Array|function}
   * @default null
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       values: [1, 2, 4, 8, 16, 32, ...],
   *
   *       // an Array value should be returned
   *       values: function() {
   *       	return [ ... ];
   *       }
   *     }
   *   }
   * }
   */
  axis_x_tick_values: null,
  /**
   * Rotate x axis tick text if there is not enough space for 'category' and 'timeseries' type axis.
   * - **NOTE:** The conditions where `autorotate` is enabled are:
   *   - axis.x.type='category' or 'timeseries
   *   - axis.x.tick.multiline=false
   *   - axis.x.tick.culling=false
   *   - axis.x.tick.fit=true
   * - **NOTE:** axis.x.tick.clippath=false is necessary for calculating the overflow padding between the end of x axis and the width of the SVG
   * @name axis․x․tick․autorotate
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickAutorotate)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       rotate: 15,
   *       autorotate: true,
   *       multiline: false,
   *       culling: false,
   *       fit: true
   *     },
   *     clipPath: false
   *   }
   * }
   */
  axis_x_tick_autorotate: false,
  /**
   * Rotate x axis tick text.
   * - If you set negative value, it will rotate to opposite direction.
   * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `false`.
   * - As long as `axis_x_tick_fit` is set to `true` it will calculate an overflow for the y2 axis and add this value to the right padding.
   * @name axis․x․tick․rotate
   * @memberof Options
   * @type {number}
   * @default 0
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.RotateXAxisTickText)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       rotate: 60
   *     }
   *   }
   * }
   */
  axis_x_tick_rotate: 0,
  /**
   * Show x axis outer tick.
   * @name axis․x․tick․outer
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       outer: false
   *     }
   *   }
   * }
   */
  axis_x_tick_outer: true,
  /**
   * Set tick text to be multiline
   * - **NOTE:**
   *  > When x tick text contains `\n`, it's used as line break and 'axis.x.tick.width' option is ignored.
   * @name axis․x․tick․multiline
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickMultiline)
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       multiline: false
   *     }
   *   }
   * }
   * @example
   * // example of line break with '\n'
   * // In this case, 'axis.x.tick.width' is ignored
   * data: {
   *    x: "x",
   *    columns: [
   *        ["x", "long\ntext", "Another\nLong\nText"],
   *        ...
   *    ],
   * }
   */
  axis_x_tick_multiline: true,
  /**
   * Set tick width
   * - **NOTE:**
   *  > When x tick text contains `\n`, this option is ignored.
   * @name axis․x․tick․width
   * @memberof Options
   * @type {number}
   * @default null
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       width: 50
   *     }
   *   }
   * }
   */
  axis_x_tick_width: null,
  /**
   * Set to display system tooltip(via `<title>` element) for tick text
   * - **NOTE:** Only available for category axis type (`axis.x.type='category'`)
   * @name axis․x․tick․tooltip
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   x: {
   *     tick: {
   *       tooltip: true
   *     }
   *   }
   * }
   */
  axis_x_tick_tooltip: false,
  /**
   * Set max value of x axis range.
   * @name axis․x․max
   * @memberof Options
   * @property {number} max Set the max value
   * @property {boolean} [max.fit=false] When specified `max.value` is greater than the bound data value, setting `true` will make x axis max to be fitted to the bound data max value.
   * - **NOTE:** If the bound data max value is greater than the `max.value`, the x axis max will be limited as the given `max.value`.
   * @property {number} [max.value] Set the max value
   * @example
   * axis: {
   *   x: {
   *     max: 100,
   *
   *     max: {
   *       // 'fit=true' will make x axis max to be limited as the bound data value max when 'max.value' is greater.
   *       // - when bound data max is '10' and max.value: '100' ==>  x axis max will be '10'
   *       // - when bound data max is '1000' and max.value: '100' ==> x axis max will be '100'
   *       fit: true,
   *       value: 100
   *     }
   *   }
   * }
   */
  axis_x_max: void 0,
  /**
   * Set min value of x axis range.
   * @name axis․x․min
   * @memberof Options
   * @property {number} min Set the min value
   * @property {boolean} [min.fit=false] When specified `min.value` is lower than the bound data value, setting `true` will make x axis min to be fitted to the bound data min value.
   * - **NOTE:** If the bound data min value is lower than the `min.value`, the x axis min will be limited as the given `min.value`.
   * @property {number} [min.value] Set the min value
   * @example
   * axis: {
   *   x: {
   *     min: -100,
   *
   *     min: {
   *       // 'fit=true' will make x axis min to be limited as the bound data value min when 'min.value' is lower.
   *       // - when bound data min is '-10' and min.value: '-100' ==>  x axis min will be '-10'
   *       // - when bound data min is '-1000' and min.value: '-100' ==> x axis min will be '-100'
   *       fit: true,
   *       value: -100
   *     }
   *   }
   * }
   */
  axis_x_min: void 0,
  /**
   * Change the direction of x axis.<br><br>
   * If true set, the direction will be `right -> left`.
   * @name axis․x․inverted
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.InvertedAxis)
   * @example
   * axis: {
   *   x: {
   *     inverted: true
   *   }
   * }
   */
  axis_x_inverted: false,
  /**
   * Set padding for x axis.<br><br>
   * If this option is set, the range of x axis will increase/decrease according to the values.
   * If no padding is needed in the rage of x axis, 0 should be set.
   * By default, left/right padding are set depending on x axis type or chart types.
   * - **NOTE:**
   *   - The meaning of padding values, differs according axis types:<br>
   *     - **category/indexed:** The unit of tick value
   *       ex. the given value `1`, is same as the width of 1 tick width
   *     - **timeseries:** Numeric time value
   *       ex. the given value `1000*60*60*24`, which is numeric time equivalent of a day, is same as the width of 1 tick width
   *   - If want values to be treated as pixels, specify `unit:"px"`.
   *     - The pixel value will be converted based on the scale values. Hence can not reflect accurate padding result.
   * @name axis․x․padding
   * @memberof Options
   * @type {object|number}
   * @default {}
   * @example
   * axis: {
   *   x: {
   *     padding: {
   *       // when axis type is 'category'
   *       left: 1,  // set left padding width of equivalent value of a tick's width
   *       right: 0.5  // set right padding width as half of equivalent value of tick's width
   *
   *       // when axis type is 'timeseries'
   *       left: 1000*60*60*24,  // set left padding width of equivalent value of a day tick's width
   *       right: 1000*60*60*12   // set right padding width as half of equivalent value of a day tick's width
   *     },
   *
   *     // or set both values at once.
   *     padding: 10,
   *
   *     // or set padding values as pixel unit.
   *     padding: {
   *       left: 100,
   *       right: 50,
   *       unit: "px"
   *     },
   *   }
   * }
   */
  axis_x_padding: {},
  /**
   * Set height of x axis.<br><br>
   * The height of x axis can be set manually by this option. If you need more space for x axis, please use this option for that. The unit is pixel.
   * @name axis․x․height
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   x: {
   *     height: 20
   *   }
   * }
   */
  axis_x_height: void 0,
  /**
   * Set extent for subchart and zoom(drag only). This can be an array or function that returns an array.
   * - **NOTE:** Specifying value, will limit the zoom scope selection within.
   * @name axis․x․extent
   * @memberof Options
   * @type {Array|function}
   * @default undefined
   * @example
   * axis: {
   *   x: {
   *     // extent range as a pixel value
   *     extent: [0, 200],
   *
   *     // when axis is 'timeseries', parsable datetime string
   *     extent: ["2019-03-01", "2019-03-05"],
   *
   *     // return extent value
   *     extent: function(domain, scale) {
   *    	 var extent = domain.map(function(v) {
   *     	    return scale(v);
   *     	 });
   *
   *   	 // it should return a format of array
   *   	 // ex) [0, 584]
   *     	 return extent;
   *     }
   *   }
   * }
   */
  axis_x_extent: void 0,
  /**
   * Set label on x axis.<br><br>
   * You can set x axis label and change its position by this option.
   * `string` and `object` can be passed and we can change the poisiton by passing object that has position key.<br>
   * Available position differs according to the axis direction (vertical or horizontal).
   * If string set, the position will be the default.
   *
   *  - **If it's horizontal axis:**
   *    - inner-right [default]
   *    - inner-center
   *    - inner-left
   *    - outer-right
   *    - outer-center
   *    - outer-left
   *  - **If it's vertical axis:**
   *    - inner-top [default]
   *    - inner-middle
   *    - inner-bottom
   *    - outer-top
   *    - outer-middle
   *    - outer-bottom
   * @name axis․x․label
   * @memberof Options
   * @type {string|object}
   * @default undefined
   * @example
   * axis: {
   *   x: {
   *     label: "Your X Axis"
   *   }
   * }
   *
   * axis: {
   *   x: {
   *     label: {
   *        text: "Your X Axis",
   *        position: "outer-center"
   *     }
   *   }
   * }
   */
  axis_x_label: {},
  /**
   * Set additional axes for x Axis.
   * - **NOTE:** Axis' scale is based on x Axis value if domain option isn't set.
   *
   * Each axis object should consist with following options:
   *
   * | Name | Type | Default | Description |
   * | --- | --- | --- | --- |
   * | domain | Array | - | Set the domain value |
   * | tick.outer | boolean | true | Show outer tick |
   * | tick.format | Function | - | Set formatter for tick text |
   * | tick.count | Number | - | Set the number of y axis ticks |
   * | tick.values | Array | - | Set tick values manually |
   * @name axis․x․axes
   * @memberof Options
   * @type {Array}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)
   * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)
   * @example
   * x: {
   *    axes: [
   *      {
   *        // if set, will not be correlated with the main x Axis domain value
   *        domain: [0, 1000],
   *        tick: {
   *          outer: false,
   *          format: function(x) {
   *             return x + "%";
   *          },
   *          count: 2,
   *          values: [10, 20, 30]
   *        }
   *      },
   *      ...
   *    ]
   * }
   */
  axis_x_axes: []
});

;// ./src/config/Options/axis/y.ts
/* harmony default export */ var y = ({
  /**
   * Set clip-path attribute for y axis element
   * - **NOTE**: `clip-path` attribute for y Axis is set only when `axis.y.inner` option is true.
   * @name axis․y․clipPath
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * // don't set 'clip-path' attribute
   * clipPath: false
   */
  axis_y_clipPath: true,
  /**
   * Show or hide y axis.
   * @name axis․y․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   y: {
   *     show: false
   *   }
   * }
   */
  axis_y_show: true,
  /**
   * Set type of y axis.<br><br>
   * **Available Values:**
   *  - indexed
   *  - log
   *  - timeseries
   *
   * **NOTE:**<br>
   * - **log** type:
   *   - the bound data values must be exclusively-positive.
   *   - y axis min value should be >= 0.
   *   - [`data.groups`](#.data%25E2%2580%25A4groups)(stacked data) option aren't supported.
   *
   * @name axis․y․type
   * @memberof Options
   * @type {string}
   * @default "indexed"
   * @see [Demo: log](https://naver.github.io/billboard.js/demo/#Axis.LogScales)
   * @example
   * axis: {
   *   y: {
   *     type: "log"
   *   }
   * }
   */
  axis_y_type: "indexed",
  /**
   * Set max value of y axis.
   * - **NOTE:** Padding will be added based on this value, so if you don't need the padding, please set axis.y.padding to disable it (e.g. axis.y.padding = 0).
   * @name axis․y․max
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y: {
   *     max: 1000
   *   }
   * }
   */
  axis_y_max: void 0,
  /**
   * Set min value of y axis.
   * - **NOTE:**
   *   Padding will be added based on this value, so if you don't need the padding, please set axis.y.padding to disable it (e.g. axis.y.padding = 0).
   * @name axis․y․min
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y: {
   *     min: 1000
   *   }
   * }
   */
  axis_y_min: void 0,
  /**
   * Change the direction of y axis.<br><br>
   * If true set, the direction will be `top -> bottom`.
   * @name axis․y․inverted
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.InvertedAxis)
   * @example
   * axis: {
   *   y: {
   *     inverted: true
   *   }
   * }
   */
  axis_y_inverted: false,
  /**
   * Set center value of y axis.
   * @name axis․y․center
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y: {
   *     center: 0
   *   }
   * }
   */
  axis_y_center: void 0,
  /**
   * Show y axis inside of the chart.
   * @name axis․y․inner
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y: {
   *     inner: true
   *   }
   * }
   */
  axis_y_inner: false,
  /**
   * Set label on y axis.<br><br>
   * You can set y axis label and change its position by this option. This option works in the same way as [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label).
   * @name axis․y․label
   * @memberof Options
   * @type {string|object}
   * @default {}
   * @see [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label) for position string value.
   * @example
   * axis: {
   *   y: {
   *     label: "Your Y Axis"
   *   }
   * }
   *
   * axis: {
   *   y: {
   *     label: {
   *        text: "Your Y Axis",
   *        position: "outer-middle"
   *     }
   *   }
   * }
   */
  axis_y_label: {},
  /**
   * Set formatter for y axis tick text.<br><br>
   * This option accepts d3.format object as well as a function you define.
   * @name axis․y․tick․format
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       format: function(x) {
   *           return x.getFullYear();
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_format: void 0,
  /**
   * Setting for culling ticks.
   * - `true`: the ticks will be culled, then only limited tick text will be shown.<br>
   *   This option does not hide the tick lines by default, if want to hide tick lines, set `axis.y.tick.culling.lines=false`.
   * - `false`: all of ticks will be shown.<br><br>
   * The number of ticks to be shown can be changed by `axis.y.tick.culling.max`.
   * @name axis․y․tick․culling
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       culling: false
   *     }
   *   }
   * }
   */
  axis_y_tick_culling: false,
  /**
   * The number of tick texts will be adjusted to less than this value.
   * @name axis․y․tick․culling․max
   * @memberof Options
   * @type {number}
   * @default 5
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       culling: {
   *           max: 5
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_culling_max: 5,
  /**
   * Control visibility of tick lines within culling option, along with tick text.
   * @name axis․y․tick․culling․lines
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       culling: {
   *           lines: false,
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_culling_lines: true,
  /**
   * Control culling start point to be reversed. If set to true, the culling will be started from the end to start.
   * - **NOTE:** This option is only available when `axis.y.tick.culling` is set to truthy value.
   * @name axis․y․tick․culling․reverse
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       culling: {
   *           reverse: true,
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_culling_reverse: false,
  /**
   * Set the axis tick line to be positioned inside of the chart.
   * @name axis․y․tick․inner
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.TickInner)
   * axis: {
   *   y: {
   *     tick: {
   *       inner: true
   *     }
   *   }
   * }
   */
  axis_y_tick_inner: false,
  /**
   * Show y axis outer tick.
   * @name axis․y․tick․outer
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       outer: false
   *     }
   *   }
   * }
   */
  axis_y_tick_outer: true,
  /**
   * Set y axis tick values manually.
   * @name axis․y․tick․values
   * @memberof Options
   * @type {Array|function}
   * @default null
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       values: [100, 1000, 10000],
   *
   *       // an Array value should be returned
   *       values: function() {
   *       	return [ ... ];
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_values: null,
  /**
   * Rotate y axis tick text.
   * - If you set negative value, it will rotate to opposite direction.
   * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `true`.
   * @name axis․y․tick․rotate
   * @memberof Options
   * @type {number}
   * @default 0
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       rotate: 60
   *     }
   *   }
   * }
   */
  axis_y_tick_rotate: 0,
  /**
   * Set the number of y axis ticks.<br><br>
   * - **NOTE:** The position of the ticks will be calculated precisely, so the values on the ticks will not be rounded nicely. In the case, axis.y.tick.format or axis.y.tick.values will be helpful.
   * @name axis․y․tick․count
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       count: 5
   *     }
   *   }
   * }
   */
  axis_y_tick_count: void 0,
  /**
   * Show or hide y axis tick line.
   * @name axis․y․tick․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       show: false
   *     }
   *   }
   * }
   */
  axis_y_tick_show: true,
  /**
   * Set axis tick step(interval) size.
   * - **NOTE:** Will be ignored if `axis.y.tick.count` or `axis.y.tick.values` options are set.
   * @name axis․y․tick․stepSize
   * @memberof Options
   * @type {number}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.StepSizeForYAxis)
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       // tick value will step as indicated interval value.
   *       // ex) 'stepSize=15' ==> [0, 15, 30, 45, 60]
   *       stepSize: 15
   *     }
   *   }
   * }
   */
  axis_y_tick_stepSize: null,
  /**
   * Show or hide y axis tick text.
   * @name axis․y․tick․text․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       text: {
   *           show: false
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_text_show: true,
  /**
   * Set the y Axis tick text's position relatively its original position
   * @name axis․y․tick․text․position
   * @memberof Options
   * @type {object}
   * @default {x: 0, y:0}
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       text: {
   *         position: {
   *           x: 10,
   *           y: 10
   *         }
   *       }
   *     }
   *   }
   * }
   */
  axis_y_tick_text_position: { x: 0, y: 0 },
  /**
   * Set the number of y axis ticks.<br><br>
   * - **NOTE:** The position of the ticks will be calculated precisely, so the values on the ticks will not be rounded nicely. In the case, axis.y.tick.format or axis.y.tick.values will be helpful.
   * @name axis․y․tick․time
   * @memberof Options
   * @private
   * @type {object}
   * @property {object} time time object
   * @property {function} [time.value] D3's time interval function (https://github.com/d3/d3-time#intervals)
   * @example
   * axis: {
   *   y: {
   *     tick: {
   *       time: {
   *          // ticks at 15-minute intervals
   *          // https://github.com/d3/d3-scale/blob/master/README.md#time_ticks
   *          value: d3.timeMinute.every(15)
   *       }
   *     }
   *   }
   * }
   */
  // @TODO: not fully implemented yet
  axis_y_tick_time_value: void 0,
  /**
   * Set padding for y axis.<br><br>
   * You can set padding for y axis to create more space on the edge of the axis.
   * This option accepts object and it can include top and bottom. top, bottom will be treated as pixels.
   *
   * - **NOTE:**
   *   - Given values are translated relative to the y Axis domain value for padding
   *   - For area and bar type charts, [area.zerobased](#.area) or [bar.zerobased](#.bar) options should be set to 'false` to get padded bottom.
   * @name axis․y․padding
   * @memberof Options
   * @type {object|number}
   * @default {}
   * @example
   * axis: {
   *   y: {
   *     padding: {
   *       top: 0,
   *       bottom: 0
   *     },
   *
   *     // or set both values at once.
   *     padding: 10
   *   }
   * }
   */
  axis_y_padding: {},
  /**
   * Set default range of y axis.<br><br>
   * This option set the default value for y axis when there is no data on init.
   * @name axis․y․default
   * @memberof Options
   * @type {Array}
   * @default undefined
   * @example
   * axis: {
   *   y: {
   *     default: [0, 1000]
   *   }
   * }
   */
  axis_y_default: void 0,
  /**
   * Set additional axes for y Axis.
   * - **NOTE:** Axis' scale is based on y Axis value if domain option isn't set.
   *
   * Each axis object should consist with following options:
   *
   * | Name | Type | Default | Description |
   * | --- | --- | --- | --- |
   * | domain | Array | - | Set the domain value |
   * | tick.outer | boolean | true | Show outer tick |
   * | tick.format | Function | - | Set formatter for tick text |
   * | tick.count | Number | - | Set the number of y axis ticks |
   * | tick.values | Array | - | Set tick values manually |
   * @name axis․y․axes
   * @memberof Options
   * @type {Array}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)
   * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)
   * @example
   * y: {
   *    axes: [
   *      {
   *        // if set, will not be correlated with the main y Axis domain value
   *        domain: [0, 1000],
   *        tick: {
   *          outer: false,
   *          format: function(x) {
   *             return x + "%";
   *          },
   *          count: 2,
   *          values: [10, 20, 30]
   *        }
   *      },
   *      ...
   *    ]
   * }
   */
  axis_y_axes: []
});

;// ./src/config/Options/axis/y2.ts
/* harmony default export */ var y2 = ({
  /**
   * Show or hide y2 axis.
   * - **NOTE**:
   *   - When set to `false` will not generate y2 axis node. In this case, all 'y2' axis related functionality won't work properly.
   *   - If need to use 'y2' related options while y2 isn't visible, set the value `true` and control visibility by css display property.
   * @name axis․y2․show
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y2: {
   *     show: true
   *   }
   * }
   */
  axis_y2_show: false,
  /**
   * Set type of y2 axis.<br><br>
   * **Available Values:**
   *  - indexed
   *  - log
   *  - timeseries
   *
   * **NOTE:**<br>
   * - **log** type:
   *   - the bound data values must be exclusively-positive.
   *   - y2 axis min value should be >= 0.
   *   - [`data.groups`](#.data%25E2%2580%25A4groups)(stacked data) option aren't supported.
   *
   * @name axis․y2․type
   * @memberof Options
   * @type {string}
   * @default "indexed"
   * @see [Demo: log](https://naver.github.io/billboard.js/demo/#Axis.LogScales)
   * @example
   * axis: {
   *   y2: {
   *     type: "indexed"
   *   }
   * }
   */
  axis_y2_type: "indexed",
  /**
   * Set max value of y2 axis.
   * @name axis․y2․max
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y2: {
   *     max: 1000
   *   }
   * }
   */
  axis_y2_max: void 0,
  /**
   * Set min value of y2 axis.
   * @name axis․y2․min
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y2: {
   *     min: -1000
   *   }
   * }
   */
  axis_y2_min: void 0,
  /**
   * Change the direction of y2 axis.<br><br>
   * If true set, the direction will be `top -> bottom`.
   * @name axis․y2․inverted
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.InvertedAxis)
   * @example
   * axis: {
   *   y2: {
   *     inverted: true
   *   }
   * }
   */
  axis_y2_inverted: false,
  /**
   * Set center value of y2 axis.
   * @name axis․y2․center
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y2: {
   *     center: 0
   *   }
   * }
   */
  axis_y2_center: void 0,
  /**
   * Show y2 axis inside of the chart.
   * @name axis․y2․inner
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y2: {
   *     inner: true
   *   }
   * }
   */
  axis_y2_inner: false,
  /**
   * Set label on y2 axis.<br><br>
   * You can set y2 axis label and change its position by this option. This option works in the same way as [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label).
   * @name axis․y2․label
   * @memberof Options
   * @type {string|object}
   * @default {}
   * @see [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label) for position string value.
   * @example
   * axis: {
   *   y2: {
   *     label: "Your Y2 Axis"
   *   }
   * }
   *
   * axis: {
   *   y2: {
   *     label: {
   *        text: "Your Y2 Axis",
   *        position: "outer-middle"
   *     }
   *   }
   * }
   */
  axis_y2_label: {},
  /**
   * Set formatter for y2 axis tick text.<br><br>
   * This option works in the same way as axis.y.format.
   * @name axis․y2․tick․format
   * @memberof Options
   * @type {function}
   * @default undefined
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       format: d3.format("$,")
   *       //or format: function(d) { return "$" + d; }
   *     }
   *   }
   * }
   */
  axis_y2_tick_format: void 0,
  /**
   * Setting for culling ticks.
   * - `true`: the ticks will be culled, then only limited tick text will be shown.<br>
   *   This option does not hide the tick lines by default, if want to hide tick lines, set `axis.y2.tick.culling.lines=false`.
   * - `false`: all of ticks will be shown.<br><br>
   * The number of ticks to be shown can be changed by `axis.y2.tick.culling.max`.
   * @name axis․y2․tick․culling
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       culling: false
   *     }
   *   }
   * }
   */
  axis_y2_tick_culling: false,
  /**
   * The number of tick texts will be adjusted to less than this value.
   * @name axis․y2․tick․culling․max
   * @memberof Options
   * @type {number}
   * @default 5
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       culling: {
   *           max: 5
   *       }
   *     }
   *   }
   * }
   */
  axis_y2_tick_culling_max: 5,
  /**
   * Control visibility of tick lines within culling option, along with tick text.
   * @name axis․y2․tick․culling․lines
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       culling: {
   *           lines: false,
   *       }
   *     }
   *   }
   * }
   */
  axis_y2_tick_culling_lines: true,
  /**
   * Control culling start point to be reversed. If set to true, the culling will be started from the end to start.
   * - **NOTE:** This option is only available when `axis.y2.tick.culling` is set to truthy value.
   * @name axis․y2․tick․culling․reverse
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       culling: {
   *           reverse: true,
   *       }
   *     }
   *   }
   * }
   */
  axis_y2_tick_culling_reverse: false,
  /**
   * Set the axis tick line to be positioned inside of the chart.
   * @name axis․y2․tick․inner
   * @memberof Options
   * @type {boolean}
   * @default false
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.TickInner)
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       inner: true
   *     }
   *   }
   * }
   */
  axis_y2_tick_inner: false,
  /**
   * Show or hide y2 axis outer tick.
   * @name axis․y2․tick․outer
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       outer: false
   *     }
   *   }
   * }
   */
  axis_y2_tick_outer: true,
  /**
   * Set y2 axis tick values manually.
   * @name axis․y2․tick․values
   * @memberof Options
   * @type {Array|function}
   * @default null
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       values: [100, 1000, 10000],
   *
   *       // an Array value should be returned
   *       values: function() {
   *       	return [ ... ];
   *       }
   *     }
   *   }
   * }
   */
  axis_y2_tick_values: null,
  /**
   * Rotate y2 axis tick text.
   * - If you set negative value, it will rotate to opposite direction.
   * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `true`.
   * @name axis․y2․tick․rotate
   * @memberof Options
   * @type {number}
   * @default 0
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       rotate: 60
   *     }
   *   }
   * }
   */
  axis_y2_tick_rotate: 0,
  /**
   * Set the number of y2 axis ticks.
   * - **NOTE:** This works in the same way as axis.y.tick.count.
   * @name axis․y2․tick․count
   * @memberof Options
   * @type {number}
   * @default undefined
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       count: 5
   *     }
   *   }
   * }
   */
  axis_y2_tick_count: void 0,
  /**
   * Show or hide y2 axis tick line.
   * @name axis․y2․tick․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       show: false
   *     }
   *   }
   * }
   */
  axis_y2_tick_show: true,
  /**
   * Set axis tick step(interval) size.
   * - **NOTE:** Will be ignored if `axis.y2.tick.count` or `axis.y2.tick.values` options are set.
   * @name axis․y2․tick․stepSize
   * @memberof Options
   * @type {number}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.StepSizeForYAxis)
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       // tick value will step as indicated interval value.
   *       // ex) 'stepSize=15' ==> [0, 15, 30, 45, 60]
   *       stepSize: 15
   *     }
   *   }
   * }
   */
  axis_y2_tick_stepSize: null,
  /**
   * Show or hide y2 axis tick text.
   * @name axis․y2․tick․text․show
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       text: {
   *           show: false
   *       }
   *     }
   *   }
   * }
   */
  axis_y2_tick_text_show: true,
  /**
   * Set the y2 Axis tick text's position relatively its original position
   * @name axis․y2․tick․text․position
   * @memberof Options
   * @type {object}
   * @default {x: 0, y:0}
   * @example
   * axis: {
   *   y2: {
   *     tick: {
   *       text: {
   *         position: {
   *           x: 10,
   *           y: 10
   *         }
   *       }
   *     }
   *   }
   * }
   */
  axis_y2_tick_text_position: { x: 0, y: 0 },
  /**
   * Set padding for y2 axis.<br><br>
   * You can set padding for y2 axis to create more space on the edge of the axis.
   * This option accepts object and it can include top and bottom. top, bottom will be treated as pixels.
   *
   * - **NOTE:**
   *   - Given values are translated relative to the y2 Axis domain value for padding
   *   - For area and bar type charts, [area.zerobased](#.area) or [bar.zerobased](#.bar) options should be set to 'false` to get padded bottom.
   * @name axis․y2․padding
   * @memberof Options
   * @type {object|number}
   * @default {}
   * @example
   * axis: {
   *   y2: {
   *     padding: {
   *       top: 100,
   *       bottom: 100
   *     }
   *
   *     // or set both values at once.
   *     padding: 10
   * }
   */
  axis_y2_padding: {},
  /**
   * Set default range of y2 axis.<br><br>
   * This option set the default value for y2 axis when there is no data on init.
   * @name axis․y2․default
   * @memberof Options
   * @type {Array}
   * @default undefined
   * @example
   * axis: {
   *   y2: {
   *     default: [0, 1000]
   *   }
   * }
   */
  axis_y2_default: void 0,
  /**
   * Set additional axes for y2 Axis.
   * - **NOTE:** Axis' scale is based on y2 Axis value if domain option isn't set.
   *
   * Each axis object should consist with following options:
   *
   * | Name | Type | Default | Description |
   * | --- | --- | --- | --- |
   * | domain | Array | - | Set the domain value |
   * | tick.outer | boolean | true | Show outer tick |
   * | tick.format | Function | - | Set formatter for tick text |
   * | tick.count | Number | - | Set the number of y axis ticks |
   * | tick.values | Array | - | Set tick values manually |
   * @name axis․y2․axes
   * @memberof Options
   * @type {Array}
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)
   * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)
   * @example
   * y2: {
   *    axes: [
   *      {
   *        // if set, will not be correlated with the main y2 Axis domain value
   *        domain: [0, 1000],
   *        tick: {
   *          outer: false,
   *          format: function(x) {
   *             return x + "%";
   *          },
   *          count: 2,
   *          values: [10, 20, 30]
   *        }
   *      },
   *      ...
   *    ]
   * }
   */
  axis_y2_axes: []
});

;// ./src/config/Options/axis/axis.ts
var axis_defProp = Object.defineProperty;
var axis_getOwnPropSymbols = Object.getOwnPropertySymbols;
var axis_hasOwnProp = Object.prototype.hasOwnProperty;
var axis_propIsEnum = Object.prototype.propertyIsEnumerable;
var axis_defNormalProp = (obj, key, value) => key in obj ? axis_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var axis_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (axis_hasOwnProp.call(b, prop))
      axis_defNormalProp(a, prop, b[prop]);
  if (axis_getOwnPropSymbols)
    for (var prop of axis_getOwnPropSymbols(b)) {
      if (axis_propIsEnum.call(b, prop))
        axis_defNormalProp(a, prop, b[prop]);
    }
  return a;
};



/* harmony default export */ var axis_axis = (axis_spreadValues(axis_spreadValues(axis_spreadValues({
  /**
   * Setup the way to evaluate tick text size.
   * - **NOTE:**
   *   - When setting `false` or a custom evaluator, it is highly recommended to memoize evaluated text dimension value to not degrade performance.
   * @name axis․evalTextSize
   * @memberof Options
   * @type {boolean|function}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.AxisEvalTextSize)
   * @example
   * axis: {
   *   // will evaluate getting text size every time.
   *   evalTextSize: false,
   *
   *   // set a custom evaluator
   *   evalTextSize: function(textElement, axisId) {
   *     // set some character to be evaluated
   *     // NOTE: The dummy textElement is a descendant of given axisId('x', 'y' or 'y2').
   *     textElement.textContent = "0";
   *
   *     // get the size
   *     const box = textElement.getBBox();
   *
   *     // clear text
   *     textElement.textContent = "";
   *
   *     return { w: 7, h: 12};
   *   },
   *
   *   // set a custom evaluator by returning fixed value
   *   evalTextSize: function(textElement, axisId) {
   *     return {
   *        x: {w: 7, h: 12},
   *        y: {w: 15.75, h: 30},
   *        y2: {w: 9.5, h: 18}
   *     }[axisId];
   *   }
   * }
   */
  axis_evalTextSize: true,
  /**
   * Switch x and y axis position.
   * @name axis․rotated
   * @memberof Options
   * @type {boolean}
   * @default false
   * @example
   * axis: {
   *   rotated: true
   * }
   */
  axis_rotated: false,
  /**
   * Set axis tooltip.
   * - **NOTE:**
   *   - When enabled, will disable default focus grid line.
   *   - For `timeseries` x Axis, tooltip will be formatted using x Axis' tick format.
   *   - For `category` x Axis, tooltip will be displaying scales' value text.
   * @name axis․tooltip
   * @memberof Options
   * @type {boolean}
   * @default false
   * @property {object} axis Axis object
   * @property {boolean} [axis.tooltip=false] Show tooltip or not.
   * @property {string|object} [axis.tooltip.backgroundColor] Set axis tooltip text background colors.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.AxisTooltip)
   * @example
   * axis: {
   *     tooltip: true, // default background color is
   *
   *     // set background color for axis tooltip texts
   *     tooltip: {
   *          backgroundColor: "red",
   *
   *          // set different background colors per axes
   *          // NOTE: In this case, only specified axes tooltip will appear.
   *          backgroundColor: {
   *               x: "green",
   *               y: "yellow",
   *               y2: "red"
   *          }
   *     }
   * }
   */
  axis_tooltip: false
}, axis_x), y), y2));

;// ./src/config/Options/data/axis.ts
/* harmony default export */ var data_axis = ({
  /**
   * Specify the keys of the x values for each data.<br><br>
   * This option can be used if we want to show the data that has different x values.
   * @name data․xs
   * @memberof Options
   * @type {object}
   * @default {}
   * @example
   * data: {
   *   xs: {
   *      data1: "x1",
   *      data2: "x2"
   *   }
   * }
   */
  data_xs: {},
  /**
   * Set a format specifier to parse string specified as x.
   * @name data․xFormat
   * @memberof Options
   * @type {string}
   * @default %Y-%m-%d
   * @example
   * data: {
   *    x: "x",
   *    columns: [
   *        ["x", "01012019", "02012019", "03012019"],
   *        ["data1", 30, 200, 100]
   *    ],
   *    // Format specifier to parse as datetime for given 'x' string value
   *    xFormat: "%m%d%Y"
   * },
   * axis: {
   *    x: {
   *        type: "timeseries"
   *    }
   * }
   * @see [D3's time specifier](https://d3js.org/d3-time-format#locale_format)
   */
  data_xFormat: "%Y-%m-%d",
  /**
   * Set localtime format to parse x axis.
   * @name data․xLocaltime
   * @memberof Options
   * @type {boolean}
   * @default true
   * @example
   * data: {
   *   xLocaltime: false
   * }
   */
  data_xLocaltime: true,
  /**
   * Sort on x axis.
   * - **NOTE:** This option works for lineish(area/line/spline/step) types only.
   * @name data․xSort
   * @memberof Options
   * @type {boolean}
   * @default true
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataXSort)
   * @example
   * data: {
   *   xSort: false,
   *   x: "x",
   *   columns: [
   *     // The line graph will start to be drawn following the x axis sequence
   *     // Below data, will start drawing x=1: 200, x=2: 300, x=3: 100
   *     ["x", 3, 1, 2],
   *     ["data1", 100, 200, 300]
   *   ]
   * }
   */
  data_xSort: true,
  /**
   * Set y axis the data related to. y and y2 can be used.
   * - **NOTE:** If all data is related to one of the axes, the domain of axis without related data will be replaced by the domain from the axis with related data
   * @name data․axes
   * @memberof Options
   * @type {object}
   * @default {}
   * @example
   * data: {
   *   axes: {
   *     data1: "y",
   *     data2: "y2"
   *   }
   * }
   */
  data_axes: {},
  /**
   * Define regions for each data.<br>
   * The values must be an array for each data and it should include an object that has `start`, `end` and `style`.
   * - The object type should be as:
   *   - start {number}: Start data point number. If not set, the start will be the first data point.
   *   - [end] {number}: End data point number. If not set, the end will be the last data point.
   *   - [style.dasharray="2 2"] {string}: The first number specifies a distance for the filled area, and the second a distance for the unfilled area.
   * - **NOTE:**
   *   - Supports only line type.
   *   - `start` and `end` values should be in the exact x value range.
   *   - Dashes will be applied using `stroke-dasharray` css property when data doesn't contain nullish value(or nullish value with `line.connectNull=true` set).
   *   - Dashes will be applied via path command when data contains nullish value.
   * @name data․regions
   * @memberof Options
   * @type {object}
   * @default {}
   * @example
   * data: {
   *   regions: {
   *     data1: [{
   *         start: 1,
   *         end: 2,
   *         style: {
   *             dasharray: "5 2"
   *         }
   *     }, {
   *         start: 3
   *     }],
   *     ...
   *   }
   * }
   */
  data_regions: {},
  /**
   * Set the stacking to be normalized
   * - **NOTE:**
   *   - For stacking, '[data.groups](#.data%25E2%2580%25A4groups)' option should be set
   *   - y Axis will be set in percentage value (0 ~ 100%)
   *   - Must have positive values
   *   - Data not in any group will not be normalized when using perGroup option
   * @name data․stack․normalize
   * @memberof Options
   * @type {boolean|object}
   * @default false
   * @see [Demo: Data Stack Normalized](https://naver.github.io/billboard.js/demo/#Data.DataStackNormalized)
   * @see [Demo: Data Stack Normalized per Group](https://naver.github.io/billboard.js/demo/#Data.DataStackNormalizedGroup)
   * @example
   * data: {
   *   stack: {
   *      // Normalize all grouped data together (all groups combined to 0-100%)
   *      normalize: true
   *
   *      // Normalize per group (each group independently becomes 0-100%)
   *      // Data not in any group will display with their original values.
   *      // If non-grouped data shares the same axis (e.g., y), it will be
   *      // displayed on the 0-100 absolute scale. To display original values,
   *      // assign them to a separate axis (e.g., y2).
   *      normalize: {
   *        perGroup: true
   *      }
   *   },
   *   groups: [
   *     ["data1", "data2"]  // This group will be normalized to 0-100%
   *   ],
   *   // data3 is not in any group, so it displays original values
   *   // Assign it to y2 axis to use a separate scale
   *   axes: {
   *     data3: "y2"
   *   }
   * },
   * axis: {
   *   y2: {
   *     show: true
   *   }
   * }
   */
  data_stack_normalize: false
});

;// ./src/config/resolver/axis.ts









const api = [
  api_axis,
  group,
  x
];
const internal = {
  axis: Axis,
  clip: clip,
  eventrect: eventrect,
  sizeAxis: size_axis
};
const options = {
  optDataAxis: data_axis,
  optAxis: axis_axis
};

;// ./src/config/resolver/axis.core.ts





function getValues(obj) {
  return Object.keys(obj).map((key) => obj[key]);
}
function extendAxisModules(module = [], option = []) {
  extend(ChartInternal.prototype, getValues(internal).concat(module));
  extend(Chart.prototype, api);
  Options.setOptions(getValues(options).concat(option));
}

;// ./src/config/resolver/shape/axis.helpers.ts






function extendAxis(module = [], option = []) {
  extendAxisModules(module, option);
}
function extendLine(module, option = []) {
  const modules = Array.isArray(module) ? module : module ? [module] : [];
  extendAxisModules(
    [point, shape_point, line].concat(modules),
    [common_point, shape_line].concat(option)
  );
}

;// ./src/config/resolver/shape/area.ts





let area_area = () => (extendLine(shape_area, [Options_shape_area]), (area_area = () => TYPE.AREA)());
let areaLineRange = () => (extendLine(shape_area, [Options_shape_area]), (areaLineRange = () => TYPE.AREA_LINE_RANGE)());
let areaStepRange = () => (extendLine(shape_area, [Options_shape_area]), (areaStepRange = () => TYPE.AREA_STEP_RANGE)());
let areaSpline = () => (extendLine(shape_area, [Options_shape_area, spline]), (areaSpline = () => TYPE.AREA_SPLINE)());
let areaSplineRange = () => (extendLine(shape_area, [Options_shape_area, spline]), (areaSplineRange = () => TYPE.AREA_SPLINE_RANGE)());
let areaStep = () => (extendLine(shape_area, [Options_shape_area]), (areaStep = () => TYPE.AREA_STEP)());

;// ./src/ChartInternal/shape/bar.ts





function _getConnectLineType(id) {
  const connectLine = this.config.bar_connectLine;
  const type = (connectLine == null ? void 0 : connectLine[id]) || connectLine;
  return /^(start|end)\-(start|end)$/.test(type) ? type : null;
}
/* harmony default export */ var bar = ({
  initBar() {
    const { $el, config, state: { clip } } = this;
    $el.bar = $el.main.select(`.${$COMMON.chart}`);
    $el.bar = config.bar_front ? $el.bar.append("g") : $el.bar.insert("g", ":first-child");
    $el.bar.attr("class", $BAR.chartBars).call(this.setCssRule(false, `.${$BAR.chartBars}`, ["pointer-events:none"]));
    if (config.clipPath === false && (config.bar_radius || config.bar_radius_ratio)) {
      $el.bar.attr("clip-path", clip.pathXAxis.replace(/#[^)]*/, `#${clip.id}`));
    }
  },
  updateTargetsForBar(targets) {
    const $$ = this;
    const { config } = $$;
    const classBars = $$.getClass("bars", true);
    const isSelectable = config.interaction_enabled && config.data_selection_isselectable;
    const mainBarEnter = updateTargetsForShape.call($$, targets, {
      type: "Bar",
      elKey: "bar",
      containerClass: $BAR.chartBars,
      itemClass: $BAR.chartBar,
      initFn: $$.initBar
    });
    mainBarEnter.append("g").attr("class", classBars).style("cursor", (d) => {
      var _a;
      return ((_a = isSelectable == null ? void 0 : isSelectable.bind) == null ? void 0 : _a.call(isSelectable, $$.api)(d)) ? "pointer" : null;
    }).call((selection) => {
      $$.setCssRule(true, ` .${$BAR.bar}`, ["fill"], $$.color)(selection);
      selection.each(function(d) {
        if (_getConnectLineType.call($$, d.id)) {
          (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).append("path").attr("class", $BAR.barConnectLine);
        }
      });
    });
  },
  /**
   * Generate/Update elements
   * @param {boolean} withTransition Transition for exit elements
   * @param {boolean} isSub Subchart draw
   * @private
   */
  updateBar(withTransition, isSub = false) {
    const $$ = this;
    if ($$.state.isCanvasMode) {
      return;
    }
    const { config, $el, $T } = $$;
    const $root = isSub ? $el.subchart : $el;
    const classBar = $$.getClass("bar", true);
    const initialOpacity = $$.initialOpacity.bind($$);
    config.bar_linearGradient && $$.updateLinearGradient();
    const bar = $root.main.selectAll(`.${$BAR.bars}`).selectAll(`.${$BAR.bar}`).data($$.labelishData.bind($$));
    $T(bar.exit(), withTransition).style("opacity", "0").remove();
    $root.bar = bar.enter().append("path").attr("class", classBar).style("fill", $$.generateUpdateBarColor()).merge(bar).style("opacity", initialOpacity);
    $$.setRatioForGroupedData($root.bar.data());
  },
  /**
   * Generate bar color accessor, hoisting the bound color function
   * to be created once per call (not per datum)
   * @returns {function} Color accessor
   * @private
   */
  generateUpdateBarColor() {
    const $$ = this;
    const fn = $$.getStylePropValue($$.color) || (() => null);
    return (d) => getShapeColorWithGradient.call($$, d, "bar_linearGradient", fn);
  },
  /**
   * Update bar color
   * @param {object} d Data object
   * @returns {string} Color string
   * @private
   */
  updateBarColor(d) {
    return this.generateUpdateBarColor()(d);
  },
  /**
   * Redraw function
   * @param {function} drawFn Retuned function from .getDrawShape() => .generateDrawBar()
   * @param {boolean} withTransition With or without transition
   * @param {boolean} isSub Subchart draw
   * @returns {Array}
   * @private
   */
  redrawBar(drawFn, withTransition, isSub = false) {
    const $$ = this;
    if ($$.state.isCanvasMode) {
      return [];
    }
    const { bar } = isSub ? $$.$el.subchart : $$.$el;
    const barPath = [];
    const connectLineCache = /* @__PURE__ */ new Map();
    const getRadius = getBarRadiusResolver($$);
    const barColor = $$.generateUpdateBarColor();
    const getBarPath = function(d, i, arr) {
      var _a;
      const isDrawable = isNumber(d.value) || $$.isBarRangeType(d) || ((_a = $$.isSubchartCandlestickBarValue) == null ? void 0 : _a.call($$, d, isSub));
      const path = isDrawable ? drawFn(d, i) : [""];
      let connectLineType = connectLineCache.get(d.id);
      if (connectLineType === void 0) {
        connectLineType = _getConnectLineType.call($$, d.id);
        connectLineCache.set(d.id, connectLineType);
      }
      if (path.length > 1) {
        barPath.push(path[1]);
      }
      if (i === arr.length - 1 && barPath.length) {
        const barConnectLineNode = $$.$T(
          (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(
            this.parentNode.querySelector(`.${$BAR.barConnectLine}`)
          ),
          withTransition,
          getRandom()
        );
        $$.updateConnectLine(barConnectLineNode, connectLineType, barPath);
        barPath.splice(0);
      }
      return path[0];
    };
    const barTransition = $$.$T(bar, withTransition, getRandom());
    if (getRadius && typeof barTransition.attrTween === "function") {
      barTransition.attrTween(
        "d",
        function(d, i, arr) {
          var _a;
          const target = getBarPath.call(this, d, i, arr);
          return getBarPathInterpolator((_a = this.getAttribute("d")) != null ? _a : "", target);
        }
      );
    } else {
      barTransition.attr("d", getBarPath);
    }
    return [
      barTransition.style("fill", (d) => {
        var _a;
        return ((_a = $$.getSubchartCandlestickBarColor) == null ? void 0 : _a.call($$, d, isSub)) || barColor(d);
      }).style("clip-path", (d) => d.clipPath).style("opacity", null)
    ];
  },
  /**
   * Generate draw function
   * @param {object} barIndices data order within x axis.
   * barIndices ==> {data1: 0, data2: 0, data3: 1, data4: 1, __max__: 1}
   *
   * When gropus given as:
   *  groups: [
   * 		["data1", "data2"],
   * 		["data3", "data4"]
   * 	],
   *
   * Will be rendered as:
   * 		data1 data3   data1 data3
   * 		data2 data4   data2 data4
   * 		-------------------------
   * 			 0             1
   * @param {boolean} isSub If is for subchart
   * @returns {function}
   * @private
   */
  generateDrawBar(barIndices, isSub) {
    const $$ = this;
    const { config } = $$;
    const getPoints = $$.generateGetBarPoints(barIndices, isSub);
    const getRadius = getBarRadiusResolver($$);
    const stackingRadiusSet = getRadius ? getStackingBarRadiusSet($$) : /* @__PURE__ */ new Set();
    const connectLineCache = /* @__PURE__ */ new Map();
    return (d, i) => {
      const points = getPoints(d, i);
      const {
        indexX,
        indexY,
        isNegative,
        pos,
        radius,
        clipPath
      } = getBarRadiusInfo(
        $$,
        d,
        points,
        getRadius,
        stackingRadiusSet,
        $$.isStackingRadiusData.bind($$)
      );
      const pathRadius = ["", ""];
      d.clipPath = clipPath;
      if (getRadius) {
        const arc = `a${radius} ${radius} ${isNegative ? "1 0 0" : "0 0 1"} `;
        pathRadius[indexY] = `${arc}${radius},${radius}`;
        pathRadius[indexX] = `${arc}${[-radius, radius][config.axis_rotated ? "sort" : "reverse"]()}`;
        isNegative && pathRadius.reverse();
      }
      const path = config.axis_rotated ? `H${pos} ${pathRadius[0]}V${points[2][indexY] - radius} ${pathRadius[1]}H${points[3][indexX]}` : `V${pos} ${pathRadius[0]}H${points[2][indexX] - radius} ${pathRadius[1]}V${points[3][indexY]}`;
      const coords = [`M${points[0][indexX]},${points[0][indexY]}${path}z`];
      let connectLineType = connectLineCache.get(d.id);
      if (connectLineType === void 0) {
        connectLineType = _getConnectLineType.call($$, d.id);
        connectLineCache.set(d.id, connectLineType);
      }
      if (connectLineType) {
        coords.push(config.axis_rotated ? {
          x: points[0][indexX],
          y: points[0][indexY],
          width: points[0][indexX] - pos,
          height: points[2][indexY] - points[0][indexY]
        } : {
          x: points[0][indexX],
          y: pos,
          width: points[2][indexX] - points[0][indexX],
          height: points[3][indexY] - pos
        });
      }
      return coords;
    };
  },
  /**
   * Determine if given stacking bar data is radius type
   * @param {object} d Data row
   * @returns {boolean}
   */
  isStackingRadiusData(d) {
    const $$ = this;
    const { $el, config, data, state } = $$;
    const { id, index, value } = d;
    if (state.hiddenTargetIds.has(id)) {
      const target = $el.bar.filter((d2) => d2.id === id && d2.value === value);
      return !target.empty() && /a\d+/i.test(target.attr("d"));
    }
    const keys = config.data_groups.find((v) => v.indexOf(id) > -1);
    const sortedList = $$.orderTargets(
      $$.filterTargetsToShow(data.targets.filter($$.isBarType, $$))
    ).filter((v) => keys.indexOf(v.id) > -1);
    const sortedIds = sortedList.map((v) => {
      const v2 = v.values[index];
      if (v2 && (isNumber(value) && value > 0 ? v2.value > 0 : v2.value < 0)) {
        return v2;
      }
      return void 0;
    }).filter(Boolean).map((v) => v.id);
    return value !== 0 && sortedIds.indexOf(id) === sortedIds.length - 1;
  },
  /**
   * Update the bar connect line path
   * @param {d3Selection} node d3 selection of bar connect line
   * @param {string} type Type of connect line, one of "start-start", "start-end", "end-start", "end-end"
   * @param {Array} barPath d3 path data for the bar
   */
  updateConnectLine(node, type, barPath) {
    const path = barPath.map((v, i, arr) => {
      const isRotated = this.config.axis_rotated;
      const isStart = /^start-(start|end)$/.test(type);
      const isEnd = /^end-(start|end)$/.test(type);
      const path2 = [];
      const x = isRotated ? isEnd ? v.x - v.width : v.x : v.x + v.width;
      const y = isRotated ? v.y + v.height : isStart ? v.y + v.height : v.y;
      if (i === 0) {
        path2.push(`${x},${y}`);
      } else {
        path2.push(
          isRotated ? `L${v.x - (/\w+-end$/.test(type) ? v.width : 0)},${v.y}` : `L${v.x},${v.y + (/\w+-start$/.test(type) ? v.height : 0)}`
        );
        if (i < arr.length - 1) {
          path2.push(`M${x},${y}`);
        }
      }
      return path2.join(" ");
    });
    node.attr("d", `M${path.join("")}z`);
  }
});

;// ./src/config/Options/shape/bar.ts
/* harmony default export */ var shape_bar = ({
  /**
   * Set bar options
   * @name bar
   * @memberof Options
   * @type {object}
   * @property {object} bar Bar object
   * @property {boolean} [bar.front=false] Set 'bar' to be positioned over(on the top) other shapes elements.
   * @property {number} [bar.indices.removeNull=false] Remove nullish data on bar indices positions.
   * @property {number} [bar.label.threshold=0] Set threshold ratio to show/hide labels.
   * @property {boolean|object} [bar.linearGradient=false] Set the linear gradient on bar.<br><br>
   * Or customize by giving below object value:
   *  - x {Array}: `x1`, `x2` value (default: `[0, 0]`)
   *  - y {Array}: `y1`, `y2` value (default: `[0, 1]`)
   *  - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.
   *    - (default: `[[0, $DATA_COLOR, 1], [1, $DATA_COLOR, 0]]`)
   * @property {boolean} [bar.overlap=false] Bars will be rendered at same position, which will be overlapped each other. (for non-grouped bars only)
   * @property {number} [bar.padding=0] The padding pixel value between each bar.
   * @property {number} [bar.radius] Set the radius of bar edge in pixel.
   * @property {number} [bar.radius.ratio] Set the radius ratio of bar edge in relative the bar's width.
   * @property {number} [bar.sensitivity=2] The sensitivity offset value for interaction boundary.
   * @property {number|function|object} [bar.width] Change the width of bar chart.
   * @property {number} [bar.width.ratio=0.6] Change the width of bar chart by ratio.
   * - **NOTE:** Criteria for ratio.
   *   - When x ticks count is same with the data count, the baseline for ratio is the minimum interval value of x ticks.
   * 	   - ex. when timeseries x values are: [2024-01-01, 2024-02-01, 2024-03-01], the minimum interval will be `2024-02-01 ~ 2024-03-01`
   *     - if the minimum interval is 30px, then ratio=1 means 30px.
   *   - When x ticks count is lower than the data count, the baseline will be calculated as `chart width / data count`.
   * 	   - ex. when chart width is 500, data count is 5, then ratio=1 means 100px.
   * @property {number} [bar.width.max] The maximum width value for ratio.
   * @property {number} [bar.width.dataname] Change the width of bar for indicated dataset only.
   * @property {number} [bar.width.dataname.ratio=0.6] Change the width of bar chart by ratio.
   *  - **NOTE:**
   *   - Works only for non-stacked bar
   * @property {number} [bar.width.dataname.max] The maximum width value for ratio.
   * @property {boolean} [bar.zerobased=true] Set if min or max value will be 0 on bar chart.
   * @see [Demo: bar front](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarFront)
   * @see [Demo: bar indices](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarIndices)
   * @see [Demo: bar overlap](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarOverlap)
   * @see [Demo: bar padding](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarPadding)
   * @see [Demo: bar radius](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarRadius)
   * @see [Demo: bar width](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidth)
   * @see [Demo: bar width variant](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidthVariant)
   * @example
   *  bar: {
   *      // make bar shape to be positioned over the other shape elements
   *      front: true,
   *
   *      // remove nullish data on bar indices positions
   *      indices: {
   *          removeNull: true
   *      },
   *
   *      // will generate following linearGradient:
   *      // for more info: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
   *      // <linearGradient x1="0" x2="0" y1="0" y2="1">
   *      //    <stop offset="0" stop-color="$DATA_COLOR" stop-opacity="1"></stop>
   *      //    <stop offset="1" stop-color="$DATA_COLOR" stop-opacity="0"></stop>
   *      // </linearGradient>
   *      linearGradient: true,
   *
   *      // Or customized gradient
   *      linearGradient: {
   *      	x: [0, 0],  // x1, x2 attributes
   *      	y: [0, 0],  // y1, y2 attributes
   *      	stops: [
   *      	  // offset, stop-color, stop-opacity
   *      	  [0, "#7cb5ec", 1],
   *
   *      	  // setting 'null' for stop-color, will set its original data color
   *      	  [0.5, null, 0],
   *
   *      	  // setting 'function' for stop-color, will pass data id as argument.
   *      	  // It should return color string or null value
   *      	  [1, function(id) { return id === "data1" ? "red" : "blue"; }, 0],
   *      	]
   *      },
   *
   *      // remove nullish da
   *      overlap: true,
   *
   *      padding: 1,
   *
   *      // bar radius
   *      radius: 10,
   *      // or
   *      radius: {
   *          ratio: 0.5
   *      }
   *
   *      label: {
   *          // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the y Axis domain range value.
   *          // if data value is below than 0.1, text label will be hidden.
   *          threshold: 0.1,
   *      },
   *
   *      // will not have offset between each bar elements for interaction
   *      sensitivity: 0,
   *
   *      width: 10,
   *
   *      // or specify width callback. The callback will receive width, targetsNum, maxDataCount as arguments.
   *      // - width: chart area width
   *      // - targetsNum: number of targets
   *      // - maxDataCount: maximum data count among targets
   *      width: function(width, targetsNum, maxDataCount) {
   *            return width / (targetsNum * maxDataCount);
   *      }
   *
   *      // or specify ratio & max
   *      width: {
   *          ratio: 0.2,
   *          max: 20
   *      },
   *
   *      // or specify width per dataset
   *      width: {
   *          data1: 20,
   *          data2: {
   *              ratio: 0.2,
   *              max: 20
   *          }
   *      },
   *
   *      zerobased: false
   *  }
   */
  bar_connectLine: false,
  bar_front: false,
  bar_indices_removeNull: false,
  bar_label_threshold: 0,
  bar_linearGradient: false,
  bar_overlap: false,
  bar_padding: 0,
  bar_radius: void 0,
  bar_radius_ratio: void 0,
  bar_sensitivity: 2,
  bar_width: void 0,
  bar_width_ratio: 0.6,
  bar_width_max: void 0,
  bar_zerobased: true
});

;// ./src/config/resolver/shape/bar.ts






let bar_bar = () => (extendAxis([bar, point], [shape_bar, common_point]), (bar_bar = () => TYPE.BAR)());

;// ./src/ChartInternal/shape/core/bubble.ts


/* harmony default export */ var bubble = ({
  /**
   * Initializer
   * @private
   */
  initBubble() {
    const $$ = this;
    const { config } = $$;
    if ($$.hasType("bubble")) {
      config.point_show = true;
      config.point_type = "circle";
    }
  },
  /**
   * Get user agent's computed value
   * @returns {number}
   * @private
   */
  getBaseLength() {
    const $$ = this;
    const { width, height } = $$.state;
    const cacheKey = KEY.bubbleBaseLength;
    let baseLength = $$.cache.get(cacheKey);
    if (!baseLength) {
      $$.cache.add(cacheKey, baseLength = getMinMax("min", [width, height]));
    }
    return baseLength;
  },
  /**
   * Get the radius value for bubble circle
   * @param {object} d Data object
   * @returns {number}
   * @private
   */
  getBubbleR(d) {
    const $$ = this;
    let maxR = $$.config.bubble_maxR;
    if (isFunction(maxR)) {
      maxR = maxR.bind($$.api)(d);
    } else if (!isNumber(maxR)) {
      maxR = $$.getBaseLength() / ($$.getMaxDataCount() * 2) + 12;
    }
    const cacheKey = KEY.bubbleMaxValue;
    let max = $$.cache.get(cacheKey);
    if (max === null) {
      $$.cache.add(cacheKey, max = getMinMax("max", $$.getMinMaxData().max.map((d2) => $$.isBubbleZType(d2) ? $$.getBubbleZData(d2.value, "y") : isObject(d2.value) ? d2.value.mid : d2.value)));
    }
    const maxArea = maxR * maxR * Math.PI;
    const area = ($$.isBubbleZType(d) ? $$.getBubbleZData(d.value, "z") : d.value) * (maxArea / max);
    return Math.sqrt(area / Math.PI);
  },
  /**
   * Get bubble dimension data
   * @param {object|Array} d data value
   * @param {string} type - y or z
   * @returns {number}
   * @private
   */
  getBubbleZData(d, type) {
    return isObject(d) ? d[type] : d[type === "y" ? 0 : 1];
  }
});

;// ./src/ChartInternal/shape/bubble.ts

/* harmony default export */ var shape_bubble = (bubble);

;// ./src/config/Options/shape/bubble.ts
/* harmony default export */ var Options_shape_bubble = ({
  /**
   * Set bubble options
   * @name bubble
   * @memberof Options
   * @type {object}
   * @property {object} bubble bubble object
   * @property {number|function} [bubble.maxR=35] Set the max bubble radius value
   * @property {boolean} [bubble.zerobased=false] Set if min or max value will be 0 on bubble chart.
   * @example
   *  bubble: {
   *      // ex) If 100 is the highest value among data bound, the representation bubble of 100 will have radius of 50.
   *      // And the lesser will have radius relatively from the max value.
   *      maxR: 50,
   *
   *      // or set radius callback
   *      maxR: function(d) {
   *          // ex. of d param - {x: Fri Oct 06 2017 00:00:00 GMT+0900, value: 80, id: "data2", index: 5}
   *          ...
   *          return Math.sqrt(d.value * 2);
   *      },
   *      zerobased: false
   *  }
   */
  bubble_maxR: 35,
  bubble_zerobased: false
});

;// ./src/config/resolver/shape/bubble.ts







let bubble_bubble = () => (extendAxis(
  [point, shape_point, shape_bubble],
  [Options_shape_bubble, common_point]
), (bubble_bubble = () => TYPE.BUBBLE)());

;// ./src/ChartInternal/shape/core/candlestick.ts
var candlestick_defProp = Object.defineProperty;
var candlestick_getOwnPropSymbols = Object.getOwnPropertySymbols;
var candlestick_hasOwnProp = Object.prototype.hasOwnProperty;
var candlestick_propIsEnum = Object.prototype.propertyIsEnumerable;
var candlestick_defNormalProp = (obj, key, value) => key in obj ? candlestick_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var candlestick_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (candlestick_hasOwnProp.call(b, prop))
      candlestick_defNormalProp(a, prop, b[prop]);
  if (candlestick_getOwnPropSymbols)
    for (var prop of candlestick_getOwnPropSymbols(b)) {
      if (candlestick_propIsEnum.call(b, prop))
        candlestick_defNormalProp(a, prop, b[prop]);
    }
  return a;
};

/* harmony default export */ var candlestick = ({
  /**
   * Generate shape drawing points
   * @param {object} indices Indice data
   * @param {boolean} isSub Subchart draw
   * @returns {function}
   */
  generateGetCandlestickPoints(indices, isSub = false) {
    const $$ = this;
    const axis = isSub ? $$.axis.subX : $$.axis.x;
    const targetsNum = $$.getIndicesMax(indices) + 1;
    const barW = $$.getBarW("candlestick", axis, targetsNum);
    const x = $$.getShapeX(barW, indices, !!isSub);
    const y = $$.getShapeY(!!isSub);
    const shapeOffset = $$.getShapeOffset($$.isCandlestickType, indices, !!isSub);
    const yScale = $$.getYScaleById.bind($$);
    return (d, i) => {
      const y0 = yScale.call($$, d.id, isSub)($$.getShapeYMin(d.id, isSub));
      const offset = shapeOffset(d, i) || y0;
      const width = isNumber(barW) ? barW : barW[d.id] || barW._$width;
      const value = $$.getCandlestickData(d);
      let points;
      if (value && isNumber(value.open) && isNumber(value.close)) {
        const posX = {
          start: x(d),
          end: 0
        };
        posX.end = posX.start + width;
        const posY = {
          start: y(value.open),
          end: y(value.close)
        };
        const posLine = {
          x: posX.start + width / 2,
          high: y(value.high),
          low: y(value.low)
        };
        const offsetDelta = y0 - offset;
        posY.start -= offsetDelta;
        posY.end -= offsetDelta;
        posLine.high -= offsetDelta;
        posLine.low -= offsetDelta;
        points = [
          [posX.start, posY.start],
          [posX.end, posY.end],
          [posLine.x, posLine.low, posLine.high]
        ];
      } else {
        points = [[0, 0], [0, 0], [0, 0, 0]];
      }
      return points;
    };
  },
  /**
   * Get candlestick data as object
   * @param {object} param Data object
   * @param {Array|object} param.value Data value
   * @returns {object|null} Converted data object
   * @private
   */
  getCandlestickData({ value }) {
    let d;
    if (isArray(value)) {
      const [open, high, low, close, volume = false] = value;
      d = { open, high, low, close };
      if (volume !== false) {
        d.volume = volume;
      }
    } else if (isObject(value)) {
      d = candlestick_spreadValues({}, value);
    }
    if (d) {
      d._isUp = d.close >= d.open;
    }
    return d || null;
  }
});

;// ./src/ChartInternal/shape/candlestick.ts
var shape_candlestick_defProp = Object.defineProperty;
var candlestick_defProps = Object.defineProperties;
var candlestick_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var shape_candlestick_getOwnPropSymbols = Object.getOwnPropertySymbols;
var shape_candlestick_hasOwnProp = Object.prototype.hasOwnProperty;
var shape_candlestick_propIsEnum = Object.prototype.propertyIsEnumerable;
var shape_candlestick_defNormalProp = (obj, key, value) => key in obj ? shape_candlestick_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var shape_candlestick_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (shape_candlestick_hasOwnProp.call(b, prop))
      shape_candlestick_defNormalProp(a, prop, b[prop]);
  if (shape_candlestick_getOwnPropSymbols)
    for (var prop of shape_candlestick_getOwnPropSymbols(b)) {
      if (shape_candlestick_propIsEnum.call(b, prop))
        shape_candlestick_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var candlestick_spreadProps = (a, b) => candlestick_defProps(a, candlestick_getOwnPropDescs(b));





/* harmony default export */ var shape_candlestick = (candlestick_spreadProps(shape_candlestick_spreadValues({}, candlestick), {
  initCandlestick() {
    initShapeElement.call(this, {
      elKey: "candlestick",
      className: $CANDLESTICK.chartCandlesticks
    });
  },
  /**
   * Update targets by its data
   * called from: ChartInternal.updateTargets()
   * @param {Array} targets Filtered target by type
   * @private
   */
  updateTargetsForCandlestick(targets) {
    updateTargetsForShape.call(this, targets, {
      type: "Candlestick",
      elKey: "candlestick",
      containerClass: $CANDLESTICK.chartCandlesticks,
      itemClass: $CANDLESTICK.chartCandlestick,
      initFn: this.initCandlestick,
      withFocus: false,
      withStyles: false
    }).style("pointer-events", "none");
  },
  /**
   * Generate/Update elements
   * @param {boolean} withTransition Transition for exit elements
   * @param {boolean} isSub Subchart draw
   * @private
   */
  updateCandlestick(withTransition, isSub = false) {
    const $$ = this;
    const { $el, $T } = $$;
    const $root = isSub ? $el.subchart : $el;
    const classSetter = $$.getClass("candlestick", true);
    const initialOpacity = $$.initialOpacity.bind($$);
    const candlestick = $root.main.selectAll(`.${$CANDLESTICK.chartCandlestick}`).selectAll(`.${$CANDLESTICK.candlestick}`).data($$.labelishData.bind($$));
    $T(candlestick.exit(), withTransition).style("opacity", "0").remove();
    const candlestickEnter = candlestick.enter().filter((d) => d.value).append("g").attr("class", classSetter);
    candlestickEnter.append("line");
    candlestickEnter.append("path");
    $root.candlestick = candlestick.merge(candlestickEnter).style("opacity", initialOpacity);
  },
  /**
   * Get draw function
   * @param {object} indices Indice data
   * @param {boolean} isSub Subchart draw
   * @returns {function}
   * @private
   */
  generateDrawCandlestick(indices, isSub) {
    const $$ = this;
    const { config } = $$;
    const getPoints = $$.generateGetCandlestickPoints(indices, isSub);
    const isRotated = config.axis_rotated;
    const downColor = config.candlestick_color_down;
    return (d, i, g) => {
      const points = getPoints(d, i);
      const value = $$.getCandlestickData(d);
      const isUp = value == null ? void 0 : value._isUp;
      const indexX = +isRotated;
      const indexY = +!indexX;
      if (g.classed) {
        g.classed($CANDLESTICK[isUp ? "valueUp" : "valueDown"], true);
      }
      const path = isRotated ? `H${points[1][1]} V${points[1][0]} H${points[0][1]}` : `V${points[1][1]} H${points[1][0]} V${points[0][1]}`;
      g.select("path").attr("d", `M${points[0][indexX]},${points[0][indexY]}${path}z`).style("fill", (d2) => {
        const color = isUp ? $$.color(d2) : isObject(downColor) ? downColor[d2.id] : downColor;
        return color || $$.color(d2);
      });
      const line = g.select("line");
      const pos = isRotated ? {
        x1: points[2][1],
        x2: points[2][2],
        y1: points[2][0],
        y2: points[2][0]
      } : {
        x1: points[2][0],
        x2: points[2][0],
        y1: points[2][1],
        y2: points[2][2]
      };
      for (const x in pos) {
        line.attr(x, pos[x]);
      }
    };
  },
  /**
   * Redraw function
   * @param {function} drawFn Retuned functino from .generateDrawCandlestick()
   * @param {boolean} withTransition With or without transition
   * @param {boolean} isSub Subchart draw
   * @returns {Array}
   */
  redrawCandlestick(drawFn, withTransition, isSub = false) {
    const $$ = this;
    const { $el, $T } = $$;
    const { candlestick } = isSub ? $el.subchart : $el;
    const rand = getRandom(true);
    return [
      candlestick.each(function(d, i) {
        const g = $T((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this), withTransition, rand);
        drawFn(d, i, g);
      }).style("opacity", null)
    ];
  }
}));

;// ./src/config/Options/shape/candlestick.ts
/* harmony default export */ var Options_shape_candlestick = ({
  /**
   * Set candlestick options
   * @name candlestick
   * @memberof Options
   * @type {object}
   * @property {object} candlestick Candlestick object
   * @property {number} [candlestick.width] Change the width.
   * @property {number} [candlestick.width.ratio=0.6] Change the width by ratio.
   * @property {number} [candlestick.width.max] The maximum width value for ratio.
   * @property {number} [candlestick.width.dataname] Change the width for indicated dataset only.
   * @property {number} [candlestick.width.dataname.ratio=0.6] Change the width of bar chart by ratio.
   * @property {number} [candlestick.width.dataname.max] The maximum width value for ratio.
   * @property {object} [candlestick.color] Color setting.
   * @property {string|object} [candlestick.color.down] Change down(bearish) value color.
   * @property {string} [candlestick.color.down.dataname] Change down value color for indicated dataset only.
   *
   * @see [Demo](https://naver.github.io/billboard.js/demo/##Chart.CandlestickChart)
   * @example
   *  candlestick: {
   *      width: 10,
   *
   *      // or
   *      width: {
   *         	ratio: 0.2,
   *         	max: 20
   *      },
   *
   *      // or specify width per dataset
   *      width: {
   *         	data1: 20,
   *         	data2: {
   *         	    ratio: 0.2,
   *         		max: 20
   *         	}
   *      },
   *      color: {
   *  	  	// specify bearish color
   *  	  	down: "red",
   *
   *  	  	// or specify color per dataset
   *  	  	down: {
   *  	  		data1: "red",
   *  	  		data2: "blue",
   *  	  	}
   *      }
   *  }
   */
  candlestick_width: void 0,
  candlestick_width_ratio: 0.6,
  candlestick_width_max: void 0,
  candlestick_color_down: "red"
});

;// ./src/config/resolver/shape/candlestick.ts






let candlestick_candlestick = () => (extendAxis(
  [shape_candlestick, point],
  [Options_shape_candlestick, common_point]
), (candlestick_candlestick = () => TYPE.CANDLESTICK)());

;// ./src/config/Options/shape/arc.ts
/* harmony default export */ var arc = ({
  /**
   * Set arc options
   * @name arc
   * @memberof Options
   * @type {object}
   * @property {object} arc Arc object
   * @property {number|function} [arc.cornerRadius=0] Set corner radius of Arc(donut/gauge/pie/polar) shape.
   *  - **NOTE:**
   * 	  - Corner radius can't surpass the `(outerRadius - innerRadius) /2` of indicated shape.
   * @property {number} [arc.cornerRadius.ratio=0] Set ratio relative of outer radius.
   * @property {object} [arc.needle] Set needle options.
   * @property {boolean} [arc.needle.show=false] Show or hide needle.
   * @property {string} [arc.needle.color] Set needle filled color.
   * @property {function} [arc.needle.path] Set custom needle path function.
   *  - **NOTE:**
   *   - The path should be starting from 0,0 (which is center) to top center coordinate.
   *   - The function will receive, `length`{number} parameter which indicating the needle length in pixel relative to radius.
   * @property {number} [arc.needle.value] Set needle value.
   *  - **NOTE:**
   *   - For single gauge chart, needle will point the data value by default, otherwise will point 0(zero).
   * @property {number} [arc.needle.length=100] Set needle length in percentages relative to radius.
   * @property {object} [arc.needle.top] Set needle top options.
   * @property {number} [arc.needle.top.rx=0] Set needle top [rx radius value](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve).
   * @property {number} [arc.needle.top.ry=0] Set needle top [ry radius value](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve).
   * @property {number} [arc.needle.top.width=0] Set needle top width in pixel.
   * @property {object} [arc.needle.bottom] Set needle bottom options.
   * @property {number} [arc.needle.bottom.rx=1] Set needle bottom [rx radius value](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve).
   * @property {number} [arc.needle.bottom.ry=1] Set needle bottom [ry radius value](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve).
   * @property {number} [arc.needle.bottom.width=15] Set needle bottom width in pixel.
   * @property {number} [arc.needle.bottom.len=0] Set needle bottom length in pixel. Setting this value, will make bottom larger starting from center.
   * @property {object} [arc.rangeText] Set rangeText options.
   * @property {Array} [arc.rangeText.values] Set range text values to be shown around Arc.
   * - When `unit: 'absolute'`: Given values are treated as absolute values.
   * - When `unit: '%'`: Given values are treated as percentages.
   * @property {string} [arc.rangeText.unit="absolute"] Specify the range text unit.
   * - "absolute": Show absolute value
   * - "%": Show percentage value
   * @property {boolean} [arc.rangeText.fixed=false] Set if range text shown will be fixed w/o data toggle update. Only available for gauge chart.
   * @property {function} [arc.rangeText.format] Set format function for the range text.
   * @property {number} [arc.rangeText.position] Set position function or object for the range text.
   * @see [Demo: Donut corner radius](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutCornerRadius)
   * @see [Demo: Donut corner radius](https://naver.github.io/billboard.js/demo/#PieChartOptions.CornerRadius)
   * @see [Demo: Donut needle](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutNeedle)
   * @see [Demo: Donut RangeText](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutRangeText)
   * @see [Demo: Gauge corner radius](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeCornerRadius)
   * @see [Demo: Gauge needle](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeNeedle)
   * @see [Demo: Gauge RangeText](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeRangeText)
   * @example
   *  arc: {
   *      cornerRadius: 12,
   *
   *      // can customize corner radius for each data with function callback
   *      //
   *      // The function will receive:
   *      // - id {string}: Data id
   *      // - value {number}: Data value
   *      // - outerRadius {number}: Outer radius value
   *      cornerRadius: function(id, value, outerRadius) {
   *          return (id === "data1" && value > 10) ?
   *          	50 : outerRadius * 1.2;
   *      },
   *
   *      // set ratio relative of outer radius
   *      cornerRadius: {
   *          ratio: 0.5
   *      },
   *
   *      needle: {
   *       	show: true,
   *       	color: "red", // any valid CSS color
   *       	path: function(length) {
   *       	  const len = length - 20;
   *
   *       	  // will return upper arrow shape path
   *       	  // Note: The path should begun from '0,0' coordinate to top center.
   *       	  const path = `M 0 -${len + 20}
   *       		L -12 -${len}
   *       		L -5 -${len}
   *       		L -5 0
   *       		A 1 1 0 0 0 5 0
   *       		L 5 -${len}
   *       		L 12 -${len} Z`;
   *
   *       	  return path;
   *       	},
   *       	value: 40,  // will make needle to point value 40.
   *       	length: 80, // needle length in percentages relative to radius.
   *
   *       	top: {
   *       	  // rx and ry are the two radii of the ellipse;
   *       	  // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve
   *       	  rx: 1,
   *       	  ry: 1,
   *       	  width: 5
   *       	},
   *       	bottom: {
   *       	  // rx and ry are the two radii of the ellipse;
   *       	  // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve
   *       	  rx: 1,
   *       	  ry: 1,
   *       	  width: 10
   *       	  len: 10
   *       	}
   *      },
   *
   *      rangeText: {
   *       	values: [15, 30, 50, 75, 95],
   *       	unit: "%",
   *       	fixed: false, // only available for gauge chart
   *       	format: function(v) {
   *       	  return v === 15 ? "Fifteen" : v;
   *       	},
   *
   *       	position: function(v) {
   *       	  return v === 15 ? {x: 20, y: 10} : null; // can return one props value also.
   *       	},
   *       	position: {x: 10, y: 15},
   *       	position: {x: 10}
   *      }
   *  }
   */
  arc_cornerRadius: 0,
  arc_cornerRadius_ratio: 0,
  arc_needle_show: false,
  arc_needle_color: void 0,
  arc_needle_value: void 0,
  arc_needle_path: void 0,
  arc_needle_length: 100,
  arc_needle_top_rx: 0,
  arc_needle_top_ry: 0,
  arc_needle_top_width: 0,
  arc_needle_bottom_rx: 1,
  arc_needle_bottom_ry: 1,
  arc_needle_bottom_width: 15,
  arc_needle_bottom_len: 0,
  arc_rangeText_values: void 0,
  arc_rangeText_unit: "absolute",
  arc_rangeText_fixed: false,
  arc_rangeText_format: void 0,
  arc_rangeText_position: void 0
});

;// ./src/config/Options/shape/donut.ts
/* harmony default export */ var donut = ({
  /**
   * Set donut options
   * @name donut
   * @memberof Options
   * @type {object}
   * @property {object} donut Donut object
   * @property {boolean} [donut.label.show=true] Show or hide label on each donut piece.
   * @property {function} [donut.label.format] Set formatter for the label on each donut piece.
   * @property {number} [donut.label.threshold=0.05] Set threshold ratio to show/hide labels.
   * @property {number|function} [donut.label.ratio=undefined] Set ratio of labels position.
   * @property {boolean|object} [donut.label.line=false] Enable label with lines (displayed outside with connector lines).
   *  - `true`: Enable label with lines with default settings
   *  - `false`: Labels are displayed inside the donut slices (default behavior).
   *  - `{show: boolean, distance: number, text: boolean}`: Enable label with lines with custom settings. When object member is not provided, it will be set to default values.
   * @property {boolean} [donut.label.line.show=true] Show or hide connector lines.
   * @property {number} [donut.label.line.distance=20] Set the distance of the horizontal part of the connector line in pixels.
   * @property {boolean|function} [donut.label.line.text=true] Show text at the end of the connector line (outside the shape).
   *  - `true`: show data "id" text
   *  - `false`: use default formatter(label.format) to show text
   *  - `function(value, ratio, id)`: Custom formatter function for the text.
   *  - **NOTE:** When the viewport size decreases, the size is adjusted based on the shape, so text may appear clipped. In this case, consider setting `overflow: visible` on the SVG node.
   * @property {object|function} [donut.label.image] Set image to be displayed next to the label text.<br><br>
   * When function is specified, will receives 3 arguments such as `v, id, i` and it must return an image object with `url`, `width`, `height`, and optional `pos` properties.<br><br>
   * The arguments are:<br>
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   * @property {string} donut.label.image.url Image URL path. Can use placeholder `{=ID}` which will be replaced with the data ID.
   * @property {number} donut.label.image.width Image width in pixels.
   * @property {number} donut.label.image.height Image height in pixels.
   * @property {object} [donut.label.image.pos] Image position relative to the label text.
   * @property {number} [donut.label.image.pos.x=0] x coordinate position, relative the original.
   * @property {number} [donut.label.image.pos.y=0] y coordinate position, relative the original.
   * @property {boolean} [donut.expand=true] Enable or disable expanding donut pieces.
   * @property {number} [donut.expand.rate=0.98] Set expand rate.
   * @property {number} [donut.expand.duration=50] Set expand transition time in ms.
   * @property {number} [donut.width] Set width of donut chart.
   * @property {string} [donut.title=""] Set title of donut chart. Use `\n` character for line break.
   *  - **NOTE:**
   *    - When `arc.needle.show=true` is set, special template `{=NEEDLE_VALUE}` can be used inside the title text to show current needle value.
   * @property {number} [donut.padAngle=0] Set padding between data.
   * @property {number} [donut.startingAngle=0] Set starting angle where data draws.
   * @see [Demo: Corner Radius](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutCornerRadius)
   * @see [Demo: Needle](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutNeedle)
   * @see [Demo: Range Text](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutRangeText)
   * @see [Demo: Label Image](https://naver.github.io/billboard.js/demo/#DonutChartOptions.LabelImage)
   * @see [Demo: Label Line](https://naver.github.io/billboard.js/demo/#DonutChartOptions.LabelLine)
   * @see [Demo: Label Ratio](https://naver.github.io/billboard.js/demo/#DonutChartOptions.LabelRatio)
   * @see [Demo: Multiline Label](https://naver.github.io/billboard.js/demo/#DonutChartOptions.MultilineLabel)
   * @see [Demo: Multiline Title](https://naver.github.io/billboard.js/demo/#DonutChartOptions.MultilineTitle)
   * @see [Demo: Pad Angle](https://naver.github.io/billboard.js/demo/#DonutChartOptions.padAngle)
   * @see [Demo: Starting Angle](https://naver.github.io/billboard.js/demo/#DonutChartOptions.StartingAngle)
   *
   * @example
   *  donut: {
   *      label: {
   *          show: false,
   *          format: function(value, ratio, id) {
   *              return d3.format("$")(value);
   *
   *              // to multiline, return with '\n' character
   *              // return value +"%\nLine1\n2Line2";
   *          },
   *
   *          // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
   *          // if data value is below than 0.1, text label will be hidden.
   *          threshold: 0.1,
   *
   *          // set ratio callback. Should return ratio value
   *          ratio: function(d, radius, h) {
   *          	...
   *          	return ratio;
   *          },
   *          // or set ratio number
   *          ratio: 0.5,
   *
   *          // Enable label with lines (displayed outside with connector lines)
   *          line: false,  // default - labels inside
   *          line: true,   // enable label with lines with default settings
   *          line: {       // enable label with lines with custom settings
   *             show: true,
   *             distance: 20,  // horizontal line distance in pixels
   *
   *             // show text at the end of connector line (outside the shape)
   *             text: true,  // use default formatter
   *             text: function(value, ratio, id) {  // custom formatter
   *                 return d3.format(".1%")(ratio);
   *             }
   *          },
   *
   *          // set image to be displayed next to the label text
   *          image: {
   *             url: "./sample.svg",
   *
   *             // use placeholder to dynamically set image URL based on data ID
   *             url: "./images/{=ID}.svg",  // will be replaced to "./images/data1.svg", "./images/data2.svg", etc.
   *             width: 35,
   *             height: 35,
   *             pos: {
   *                x: 0,
   *                y: 0
   *             }
   *          },
   *
   *          // or use function to return image configuration dynamically
   *          image: function(v, id, i) {
   *             // Return different images based on value
   *             if (v > 500) {
   *                return {
   *                   url: "./high-value.svg",
   *                   width: 40,
   *                   height: 40,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if (v > 100) {
   *                return {
   *                   url: "./medium-value.svg",
   *                   width: 30,
   *                   height: 30,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if(v < 5) {
   *                // Return falsy value in case of don't want to show image
   *                return null;
   *             } else {
   *                return {
   *                   url: "./low-value.svg",
   *                   width: 20,
   *                   height: 20,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             }
   *          }
   *      },
   *
   *      // disable expand transition for interaction
   *      expand: false,
   *
   *      expand: {
   *      	// set duration of expand transition to 500ms.
   *          duration: 500,
   *
   *      	// set expand area rate
   *          rate: 1
   *      },
   *
   *      width: 10,
   *      padAngle: 0.2,
   *      startingAngle: 1,
   *      title: "Donut Title"
   *
   *      // when 'arc.needle.show=true' is set, can show current needle value.
   *      title: "Needle value:\n{=NEEDLE_VALUE}",
   *
   *      // title with line break
   *      title: "Title1\nTitle2"
   *  }
   */
  donut_label_show: true,
  donut_label_format: void 0,
  donut_label_threshold: 0.05,
  donut_label_line: false,
  donut_label_image: void 0,
  donut_label_ratio: void 0,
  donut_width: void 0,
  donut_title: "",
  donut_expand: {},
  donut_expand_rate: 0.98,
  donut_expand_duration: 50,
  donut_padAngle: 0,
  donut_startingAngle: 0
});

// EXTERNAL MODULE: external {"commonjs":"d3-interpolate","commonjs2":"d3-interpolate","amd":"d3-interpolate","root":"d3"}
var external_commonjs_d3_interpolate_commonjs2_d3_interpolate_amd_d3_interpolate_root_d3_ = __webpack_require__(10);
;// ./src/ChartInternal/internals/text.arc.ts




const BREAK_POINT_OFFSET = 15;
const DEFAULT_LINE_DISTANCE = 20;
const TEXT_VERTICAL_OFFSET = 0.35;
function getArcType(excludeMultiGauge = false) {
  const $$ = this;
  return ["donut", "pie", "polar", "gauge"].find(
    (type) => $$.hasType(type) && !(type === "gauge" && excludeMultiGauge && $$.hasMultiArcGauge())
  );
}
function getConfig() {
  const $$ = this;
  const { config } = $$;
  const chartType = getArcType.call($$, true);
  const lineConfig = chartType && config[`${chartType}_label_line`];
  const isValidConfig = isObjectType(lineConfig);
  const defaultFormatter = (value, ratio, id) => id;
  const line = {
    show: lineConfig === true || isValidConfig && (lineConfig == null ? void 0 : lineConfig.show) !== false,
    distance: isValidConfig && (lineConfig == null ? void 0 : lineConfig.distance) || DEFAULT_LINE_DISTANCE
  };
  if (lineConfig === true) {
    return {
      chartType,
      line,
      text: { formatter: defaultFormatter }
    };
  }
  if (!isValidConfig) {
    return {
      chartType,
      line: { show: false, distance: DEFAULT_LINE_DISTANCE },
      text: { formatter: null }
    };
  }
  let formatter = defaultFormatter;
  if (isFunction(lineConfig.text)) {
    formatter = lineConfig.text;
  } else if (lineConfig.text === false) {
    formatter = null;
  }
  return {
    chartType,
    line,
    text: { formatter }
  };
}
function getLinePosition(d, lineDistance) {
  const $$ = this;
  const { state } = $$;
  const updated = $$.updateAngle(d);
  if (!updated) {
    return null;
  }
  let { outerRadius } = $$.getRadius(d);
  let arcOuterRadius = outerRadius;
  if ($$.hasType("polar")) {
    arcOuterRadius = $$.getPolarOuterRadius(d, outerRadius);
    outerRadius = state.radius;
  }
  let midAngle = (updated.startAngle + updated.endAngle) / 2;
  const isFullCircleArc = Math.abs(updated.endAngle - updated.startAngle - 2 * Math.PI) < 0.01;
  if (isFullCircleArc) {
    midAngle = Math.PI / 2;
  }
  const sinAngle = Math.sin(midAngle);
  const cosAngle = -Math.cos(midAngle);
  const startPoint = {
    x: sinAngle * arcOuterRadius,
    y: cosAngle * arcOuterRadius
  };
  const breakRadius = outerRadius + BREAK_POINT_OFFSET;
  const breakPoint = {
    x: sinAngle * breakRadius,
    y: cosAngle * breakRadius
  };
  const isRight = sinAngle >= 0;
  const endPoint = {
    x: breakPoint.x + lineDistance * (isRight ? 1 : -1),
    y: breakPoint.y
  };
  return { startPoint, breakPoint, endPoint, isRight, midAngle };
}
function isLabelWithLine() {
  return getConfig.call(this).line.show;
}
function redrawArcLabelLines(duration) {
  const $$ = this;
  const { $el: { arcs }, $T } = $$;
  const { line: lineConfig, text: textConfig } = getConfig.call($$);
  const lineDistance = lineConfig.distance;
  let cachedFontSize = null;
  arcs.selectAll(`.${$ARC.chartArc}`).each(function(d) {
    var _a, _b, _c;
    const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
    const linePos = getLinePosition.call($$, d, lineDistance);
    const { ratio, meetsThreshold, updated } = (_a = d._cache) != null ? _a : {};
    if (!updated || !linePos) {
      return;
    }
    const isVisible = $$.isTargetToShow(d.data.id) && meetsThreshold;
    const { startPoint, breakPoint, endPoint, isRight } = linePos;
    const points = `${startPoint.x},${startPoint.y} ${breakPoint.x},${breakPoint.y} ${endPoint.x},${endPoint.y}`;
    if (lineConfig.show) {
      let line = g.select(`.${$ARC.arcLabelLine}`);
      if (line.empty()) {
        line = g.append("polyline").attr("class", $ARC.arcLabelLine);
      }
      $T(line, duration).attr("points", points).style("stroke", $$.color(d.data)).style("opacity", isVisible ? null : "0");
    }
    let labelLineText = g.select(`.${$ARC.arcLabelLineText}`);
    if (labelLineText.empty()) {
      labelLineText = g.append("text").attr("class", $ARC.arcLabelLineText).style("pointer-events", "none");
    }
    if (isVisible) {
      const { value } = updated;
      const { id } = d.data;
      const text = ((_c = (_b = textConfig.formatter) != null ? _b : $$.getArcLabelConfig("format")) != null ? _c : $$.defaultArcValueFormat)(value, ratio, id).toString();
      setTextValue(labelLineText, text, [-1, 1], false);
      const pos = {
        x: endPoint.x + 5 * (isRight ? 1 : -1),
        // 5: label offset from endpoint
        y: endPoint.y
      };
      labelLineText.style("text-anchor", isRight ? "start" : "end");
      const textNode = labelLineText.node();
      const tspanNodes = textNode == null ? void 0 : textNode.querySelectorAll("tspan");
      if (cachedFontSize === null) {
        cachedFontSize = parseFloat(win.getComputedStyle(textNode).fontSize) || 12;
      }
      if (tspanNodes && tspanNodes.length > 1) {
        const lineCount = tspanNodes.length;
        const centerOffset = (lineCount - 3) / 2;
        pos.y += (-centerOffset + TEXT_VERTICAL_OFFSET) * cachedFontSize;
      } else {
        pos.y += TEXT_VERTICAL_OFFSET * cachedFontSize;
      }
      $T(labelLineText, duration).attr("transform", `translate(${pos.x},${pos.y})`).style("opacity", null).style("fill", $$.updateTextColor.bind($$)(d));
    } else {
      $T(labelLineText, duration).style("opacity", "0");
    }
  });
}


;// ./src/ChartInternal/shape/arc.ts
var arc_defProp = Object.defineProperty;
var arc_defProps = Object.defineProperties;
var arc_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var arc_getOwnPropSymbols = Object.getOwnPropertySymbols;
var arc_hasOwnProp = Object.prototype.hasOwnProperty;
var arc_propIsEnum = Object.prototype.propertyIsEnumerable;
var arc_defNormalProp = (obj, key, value) => key in obj ? arc_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var arc_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (arc_hasOwnProp.call(b, prop))
      arc_defNormalProp(a, prop, b[prop]);
  if (arc_getOwnPropSymbols)
    for (var prop of arc_getOwnPropSymbols(b)) {
      if (arc_propIsEnum.call(b, prop))
        arc_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var arc_spreadProps = (a, b) => arc_defProps(a, arc_getOwnPropDescs(b));








const ARC_TYPES = ["donut", "gauge", "pie", "polar"];
function _getArcType($$) {
  return ["donut", "pie", "polar", "gauge"].find((type) => $$.hasType(type));
}
function _calculateRangeOrGaugePosition($$, d, updated, forRange) {
  var _a, _b;
  const { config, state: { radiusExpanded } } = $$;
  const angle = updated.endAngle - Math.PI / 2;
  const sinAngle = Math.sin(angle);
  const pos = {
    x: Math.cos(angle) * (radiusExpanded + (forRange ? 5 : 25)),
    // 5: range offset, 25: gauge offset
    y: sinAngle * (radiusExpanded + 15 - Math.abs(sinAngle * 10)) + 3
    // 10: y factor, 3: y offset
  };
  if (forRange) {
    const rangeTextPosition = config.arc_rangeText_position;
    if (rangeTextPosition) {
      const rangeValues = config.arc_rangeText_values;
      const position = isFunction(rangeTextPosition) ? rangeTextPosition(rangeValues[d.index]) : rangeTextPosition;
      pos.x += (_a = position == null ? void 0 : position.x) != null ? _a : 0;
      pos.y += (_b = position == null ? void 0 : position.y) != null ? _b : 0;
    }
  }
  return pos;
}
function _calculateLabelRatio($$, d, outerRadius, distance) {
  const { config } = $$;
  const chartType = _getArcType($$);
  let ratio = chartType ? config[`${chartType}_label_ratio`] : void 0;
  if (ratio) {
    ratio = isFunction(ratio) ? ratio.bind($$.api)(d, outerRadius, distance) : ratio;
  } else {
    const LABEL_MIN_SIZE = 36;
    const LABEL_RATIO_THRESHOLD = 0.375;
    const LABEL_RATIO_BASE = 1.175;
    const LABEL_RATIO_LARGE = 0.8;
    const labelSpaceRatio = LABEL_MIN_SIZE / outerRadius;
    const isSmallChart = labelSpaceRatio > LABEL_RATIO_THRESHOLD;
    ratio = outerRadius && distance ? (isSmallChart ? LABEL_RATIO_BASE - labelSpaceRatio : LABEL_RATIO_LARGE) * outerRadius / distance : 0;
  }
  return ratio;
}
function _calculateStandardArcPosition($$, d, updated) {
  let { outerRadius } = $$.getRadius(d);
  if ($$.hasType("polar")) {
    outerRadius = $$.getPolarOuterRadius(d, outerRadius);
  }
  const [x, y] = $$.svgArc.centroid(updated).map((v) => isNaN(v) ? 0 : v);
  const distance = Math.sqrt(x * x + y * y);
  const ratio = _calculateLabelRatio($$, d, outerRadius, distance);
  return {
    pos: { x, y },
    ratio
  };
}
function _getRadiusFn(expandRate = 0) {
  const $$ = this;
  const { config, state } = $$;
  const hasMultiArcGauge = $$.hasMultiArcGauge();
  const singleArcWidth = state.gaugeArcWidth / $$.getTargetsToShow().length;
  const expandWidth = expandRate ? Math.min(
    state.radiusExpanded * expandRate - state.radius,
    singleArcWidth * 0.8 - (1 - expandRate) * 100
  ) : 0;
  return {
    /**
     * Getter of arc innerRadius value
     * @param {IArcData} d Data object
     * @returns {number} innerRadius value
     * @private
     */
    inner(d) {
      const { innerRadius } = $$.getRadius(d);
      return hasMultiArcGauge ? state.radius - singleArcWidth * (d.index + 1) : isNumber(innerRadius) ? innerRadius : 0;
    },
    /**
     * Getter of arc outerRadius value
     * @param {IArcData} d Data object
     * @returns {number} outerRadius value
     * @private
     */
    outer(d) {
      const { outerRadius } = $$.getRadius(d);
      let radius;
      if (hasMultiArcGauge) {
        radius = state.radius - singleArcWidth * d.index + expandWidth;
      } else if ($$.hasType("polar") && !expandRate) {
        radius = $$.getPolarOuterRadius(d, outerRadius);
      } else {
        radius = outerRadius;
        if (expandRate) {
          let { radiusExpanded } = state;
          if (state.radius !== outerRadius) {
            radiusExpanded -= Math.abs(state.radius - outerRadius);
          }
          radius = radiusExpanded * expandRate;
        }
      }
      return radius;
    },
    /**
     * Getter of arc cornerRadius value
     * @param {IArcData} d Data object
     * @param {number} outerRadius outer radius value
     * @returns {number} cornerRadius value
     * @private
     */
    corner(d, outerRadius) {
      const {
        arc_cornerRadius_ratio: ratio = 0,
        arc_cornerRadius: cornerRadius = 0
      } = config;
      const { data: { id }, value } = d;
      let corner;
      if (ratio) {
        corner = ratio * outerRadius;
      } else {
        corner = isNumber(cornerRadius) ? cornerRadius : cornerRadius.call($$.api, id, value, outerRadius);
      }
      return corner;
    }
  };
}
function _getAttrTweenFn(fn) {
  return function(d) {
    const getAngleKeyValue = ({ startAngle = 0, endAngle = 0, padAngle = 0 }) => ({
      startAngle,
      endAngle,
      padAngle
    });
    const interpolate = (0,external_commonjs_d3_interpolate_commonjs2_d3_interpolate_amd_d3_interpolate_root_d3_.interpolate)(
      getAngleKeyValue(this._current),
      getAngleKeyValue(d)
    );
    this._current = d;
    return function(t) {
      const interpolated = interpolate(t);
      const { data, index, value } = d;
      return fn(arc_spreadProps(arc_spreadValues({}, interpolated), { data, index, value }));
    };
  };
}
/* harmony default export */ var shape_arc = ({
  initPie() {
    const $$ = this;
    const { config } = $$;
    const dataType = config.data_type;
    const padding = config[`${dataType}_padding`];
    const startingAngle = config[`${dataType}_startingAngle`] || 0;
    const padAngle = (padding ? padding * 0.01 : config[`${dataType}_padAngle`]) || 0;
    $$.pie = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.pie)().startAngle(startingAngle).endAngle(startingAngle + 2 * Math.PI).padAngle(padAngle).value((d) => {
      var _a, _b;
      return (_b = (_a = d.values) == null ? void 0 : _a.reduce((a, b) => a + b.value, 0)) != null ? _b : d;
    }).sort($$.getSortCompareFn.bind($$)(true));
  },
  updateRadius() {
    const $$ = this;
    const { config, state } = $$;
    const dataType = config.data_type;
    const padding = config[`${dataType}_padding`];
    const w = config.gauge_width || config.donut_width;
    const gaugeArcWidth = $$.getTargetsToShow().length * config.gauge_arcs_minWidth;
    const LABEL_RADIUS_RATIO = 0.85;
    const labelWithLineRatio = isLabelWithLine.call($$) ? LABEL_RADIUS_RATIO : 1;
    state.radiusExpanded = Math.min(state.arcWidth, state.arcHeight) / 2 * ($$.hasMultiArcGauge() && config.gauge_label_show ? LABEL_RADIUS_RATIO : labelWithLineRatio);
    state.radius = state.radiusExpanded * 0.95;
    state.innerRadiusRatio = w ? (state.radius - w) / state.radius : 0.6;
    state.gaugeArcWidth = w || (gaugeArcWidth <= state.radius - state.innerRadius ? state.radius - state.innerRadius : gaugeArcWidth <= state.radius ? gaugeArcWidth : state.radius);
    const innerRadius = config.pie_innerRadius || (padding ? padding * (state.innerRadiusRatio + 0.1) : 0);
    state.outerRadius = config.pie_outerRadius;
    state.innerRadius = $$.hasType("donut") || $$.hasType("gauge") ? state.radius * state.innerRadiusRatio : innerRadius;
  },
  /**
   * Get pie's inner & outer radius value
   * @param {object|undefined} d Data object
   * @returns {object}
   * @private
   */
  getRadius(d) {
    const $$ = this;
    const data = d == null ? void 0 : d.data;
    let { innerRadius, outerRadius } = $$.state;
    if (!isNumber(innerRadius) && data) {
      innerRadius = innerRadius[data.id] || 0;
    }
    if (isObject(outerRadius) && data && data.id in outerRadius) {
      outerRadius = outerRadius[data.id];
    } else if (!isNumber(outerRadius)) {
      outerRadius = $$.state.radius;
    }
    return { innerRadius, outerRadius };
  },
  updateArc() {
    const $$ = this;
    $$.updateRadius();
    $$.svgArc = $$.getSvgArc();
    $$.svgArcExpanded = $$.getSvgArcExpanded();
  },
  getArcLength() {
    const $$ = this;
    const { config } = $$;
    const arcLengthInPercent = config.gauge_arcLength * 3.6;
    let len = 2 * (arcLengthInPercent / 360);
    if (arcLengthInPercent < -360) {
      len = -2;
    } else if (arcLengthInPercent > 360) {
      len = 2;
    }
    return len * Math.PI;
  },
  getStartingAngle() {
    const $$ = this;
    const { config } = $$;
    const dataType = config.data_type;
    const isFullCircle = $$.hasType("gauge") ? config.gauge_fullCircle : false;
    const defaultStartAngle = -1 * Math.PI / 2;
    const defaultEndAngle = Math.PI / 2;
    let startAngle = config[`${dataType}_startingAngle`] || 0;
    if (!isFullCircle && startAngle <= defaultStartAngle) {
      startAngle = defaultStartAngle;
    } else if (!isFullCircle && startAngle >= defaultEndAngle) {
      startAngle = defaultEndAngle;
    } else if (startAngle > Math.PI || startAngle < -1 * Math.PI) {
      startAngle = Math.PI;
    }
    return startAngle;
  },
  /**
   * Update angle data
   * @param {object} dValue Data object
   * @param {boolean} forRange Weather is for ranged text option(arc.rangeText.values)
   * @returns {object|null} Updated angle data
   * @private
   */
  updateAngle(dValue, forRange = false) {
    var _a;
    const $$ = this;
    const { config, state } = $$;
    const hasGauge = forRange && $$.hasType("gauge");
    let { pie } = $$;
    let d = dValue;
    let found = false;
    if (!config) {
      return null;
    }
    const gStart = $$.getStartingAngle();
    const radius = config.gauge_fullCircle || forRange && !hasGauge ? $$.getArcLength() : gStart * -2;
    const isSingleArcGauge = d.data && $$.isGaugeType(d.data) && !$$.hasMultiArcGauge();
    if (isSingleArcGauge) {
      const { gauge_min: gMin, gauge_max: gMax } = config;
      const totalSum = $$.getTotalDataSum(state.rendered);
      const gEnd = radius * ((totalSum - gMin) / (gMax - gMin));
      pie = pie.startAngle(gStart).endAngle(gEnd + gStart);
    }
    if (forRange === false) {
      let layout;
      if (isSingleArcGauge) {
        layout = pie($$.filterTargetsToShow());
      } else {
        const cacheKey = "$arcPieLayout";
        let cached = $$.cache.get(cacheKey);
        if (!cached || cached.generation !== state.redrawGeneration) {
          cached = {
            generation: state.redrawGeneration,
            layout: pie($$.filterTargetsToShow())
          };
          $$.cache.add(cacheKey, cached);
        }
        layout = cached.layout;
      }
      layout.forEach((t, i) => {
        var _a2;
        if (!found && t.data.id === ((_a2 = d.data) == null ? void 0 : _a2.id)) {
          found = true;
          d = t;
          d.index = i;
        }
      });
    }
    if (isNaN(d.startAngle)) {
      d.startAngle = 0;
    }
    if (isNaN(d.endAngle)) {
      d.endAngle = d.startAngle;
    }
    if (forRange || d.data && (config.gauge_enforceMinMax || $$.hasMultiArcGauge())) {
      const { gauge_min: gMin, gauge_max: gMax } = config;
      const max = forRange && !hasGauge ? $$.getTotalDataSum(state.rendered) : gMax;
      const gTic = radius / (max - gMin);
      const value = (_a = d.value) != null ? _a : 0;
      const gValue = value < gMin ? 0 : value < max ? value - gMin : max - gMin;
      d.startAngle = gStart;
      d.endAngle = gStart + gTic * gValue;
    }
    return found || forRange ? d : null;
  },
  getSvgArc() {
    const $$ = this;
    const { inner, outer, corner } = _getRadiusFn.call($$);
    const arc = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.arc)().innerRadius(inner).outerRadius(outer);
    const newArc = function(d, withoutUpdate) {
      var _a;
      let path = "M 0 0";
      if (d.value || d.data) {
        const data = withoutUpdate ? d : (_a = $$.updateAngle(d)) != null ? _a : null;
        if (data) {
          path = arc.cornerRadius(
            corner(data, outer(data))
          )(data);
        }
      }
      return path;
    };
    newArc.centroid = arc.centroid;
    return newArc;
  },
  /**
   * Get expanded arc path function
   * @param {number} rate Expand rate
   * @returns {function} Expanded arc path getter function
   * @private
   */
  getSvgArcExpanded(rate = 1) {
    const $$ = this;
    const { inner, outer, corner } = _getRadiusFn.call($$, rate);
    const arc = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.arc)().innerRadius(inner).outerRadius(outer);
    return (d) => {
      const updated = $$.updateAngle(d);
      const outerR = outer(updated);
      let cornerR = 0;
      if (updated) {
        cornerR = corner(updated, outerR);
      }
      return updated ? arc.cornerRadius(cornerR)(updated) || "M 0 0" : "M 0 0";
    };
  },
  getArc(d, withoutUpdate, force) {
    return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
  },
  /**
   * Render range value text
   * @private
   */
  redrawArcRangeText() {
    const $$ = this;
    const { config, $el: { arcs }, state, $T } = $$;
    const format = config.arc_rangeText_format;
    const fixed = $$.hasType("gauge") && config.arc_rangeText_fixed;
    let values = config.arc_rangeText_values;
    if (values == null ? void 0 : values.length) {
      const isPercent = config.arc_rangeText_unit === "%";
      const totalSum = $$.getTotalDataSum(state.rendered);
      if (isPercent) {
        values = values.map((v) => totalSum / 100 * v);
      }
      const pieData = $$.pie(values).map((d, i) => (d.index = i, d));
      let rangeText = arcs.selectAll(`.${$ARC.arcRange}`).data(values);
      rangeText.exit().remove();
      rangeText = $T(rangeText.enter().append("text").attr("class", $ARC.arcRange).style("text-anchor", "middle").style("pointer-events", "none").style("opacity", "0").text((v) => {
        const range = isPercent ? v / totalSum * 100 : v;
        return isFunction(format) ? format(range) : `${range}${isPercent ? "%" : ""}`;
      }).merge(rangeText));
      if ((!state.rendered || state.rendered && !fixed) && totalSum > 0) {
        rangeText.attr("transform", function(d, i) {
          return $$.transformForArcLabel(this, pieData[i], true);
        });
      }
      rangeText.style(
        "opacity",
        (d) => !fixed && (d > totalSum || totalSum === 0) ? "0" : null
      );
    }
  },
  /**
   * Set transform attributes to arc label text
   * @param {SVGTextElement} textNode Text node element
   * @param {object} d Data object
   * @param {boolean} forRange Weather is for ranged text option(arc.rangeText.values)
   * @returns {string} Translate attribute string
   * @private
   */
  transformForArcLabel(textNode, d, forRange = false) {
    const $$ = this;
    const updated = $$.updateAngle(d, forRange);
    if (!updated) {
      return "";
    }
    let pos;
    let ratio = 1;
    if (forRange || $$.hasMultiArcGauge()) {
      pos = _calculateRangeOrGaugePosition($$, d, updated, forRange);
    } else if (!$$.hasType("gauge") || $$.data.targets.length > 1) {
      const result = _calculateStandardArcPosition($$, d, updated);
      pos = result.pos;
      ratio = result.ratio;
    } else {
      return "";
    }
    updateTextImagePos.call($$, textNode, pos);
    return `translate(${pos.x * ratio},${pos.y * ratio})`;
  },
  convertToArcData(d) {
    return this.addName({
      id: "data" in d ? d.data.id : d.id,
      value: d.value,
      ratio: this.getRatio("arc", d),
      index: d.index
    });
  },
  textForArcLabel(selection) {
    var _a;
    const $$ = this;
    const hasGauge = $$.hasType("gauge");
    const chartType = (_a = ARC_TYPES.filter($$.hasType.bind($$))) == null ? void 0 : _a[0];
    if ($$.shouldShowArcLabel()) {
      selection.style("fill", $$.updateTextColor.bind($$)).attr("filter", (d) => $$.updateTextBGColor.bind($$)(d, $$.config.data_labels_backgroundColors)).each(function(d) {
        const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        const updated = $$.updateAngle(d);
        const ratio = $$.getRatio("arc", updated);
        const meetsThreshold = meetsLabelThreshold.call($$, ratio, chartType);
        d._cache = { updated, ratio, meetsThreshold };
        if (meetsThreshold) {
          const { value } = updated || d;
          const text = ($$.getArcLabelConfig("format") || $$.defaultArcValueFormat)(value, ratio, d.data.id).toString();
          setTextValue(node, text, [-1, 1], hasGauge);
        } else {
          node.text("");
        }
      });
    }
  },
  expandArc(targetIds) {
    const $$ = this;
    const { state: { transiting }, $el } = $$;
    if (transiting) {
      const interval = setInterval(() => {
        if (!$$.state.transiting) {
          clearInterval(interval);
          $el.legend.selectAll(`.${$FOCUS.legendItemFocused}`).size() > 0 && $$.expandArc(targetIds);
        }
      }, 10);
      return;
    }
    const newTargetIds = $$.mapToTargetIds(targetIds);
    $el.svg.selectAll($$.selectorTargets(newTargetIds, `.${$ARC.chartArc}`)).each(function(d) {
      if (!$$.shouldExpand(d.data.id)) {
        return;
      }
      const expandDuration = $$.getExpandConfig(d.data.id, "duration");
      const svgArcExpandedSub = $$.getSvgArcExpanded(
        $$.getExpandConfig(d.data.id, "rate")
      );
      (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).selectAll("path").transition().duration(expandDuration).attrTween("d", _getAttrTweenFn($$.svgArcExpanded.bind($$))).transition().duration(expandDuration * 2).attrTween("d", _getAttrTweenFn(svgArcExpandedSub.bind($$)));
    });
  },
  unexpandArc(targetIds) {
    const $$ = this;
    const { state: { transiting }, $el: { svg } } = $$;
    if (transiting) {
      return;
    }
    const newTargetIds = $$.mapToTargetIds(targetIds);
    svg.selectAll($$.selectorTargets(newTargetIds, `.${$ARC.chartArc}`)).selectAll("path").transition().duration((d) => $$.getExpandConfig(d.data.id, "duration")).attrTween("d", _getAttrTweenFn($$.svgArc.bind($$)));
    svg.selectAll(`${$ARC.arc}`).style("opacity", null);
  },
  /**
   * Get expand config value
   * @param {string} id data ID
   * @param {string} key config key: 'duration | rate'
   * @returns {number}
   * @private
   */
  getExpandConfig(id, key) {
    const $$ = this;
    const { config } = $$;
    const def = {
      duration: 50,
      rate: 0.98
    };
    let type;
    if ($$.isDonutType(id)) {
      type = "donut";
    } else if ($$.isGaugeType(id)) {
      type = "gauge";
    } else if ($$.isPieType(id)) {
      type = "pie";
    }
    return type ? config[`${type}_expand_${key}`] : def[key];
  },
  shouldExpand(id) {
    const $$ = this;
    const { config } = $$;
    const type = $$.isDonutType(id) ? "donut" : $$.isGaugeType(id) ? "gauge" : $$.isPieType(id) ? "pie" : null;
    return type ? !!config[`${type}_expand`] : false;
  },
  shouldShowArcLabel() {
    const $$ = this;
    const { config } = $$;
    return ARC_TYPES.some((v) => $$.hasType(v) && config[`${v}_label_show`]);
  },
  getArcLabelConfig(name = "format") {
    const $$ = this;
    const { config } = $$;
    let fn = (v) => v;
    ARC_TYPES.filter($$.hasType.bind($$)).forEach((v) => {
      fn = config[`${v}_label_${name}`];
    });
    if (name === "format") {
      return isFunction(fn) ? fn.bind($$.api) : fn;
    } else {
      return fn;
    }
  },
  updateTargetsForArc(targets) {
    const $$ = this;
    const { $el } = $$;
    const hasGauge = $$.hasType("gauge");
    const classChartArc = $$.getChartClass("Arc");
    const classArcs = $$.getClass("arcs", true);
    const classFocus = $$.classFocus.bind($$);
    const chartArcs = $el.main.select(`.${$ARC.chartArcs}`);
    const mainPieUpdate = chartArcs.selectAll(`.${$ARC.chartArc}`).data($$.pie(targets)).attr("class", (d) => classChartArc(d) + classFocus(d.data));
    const mainPieEnter = mainPieUpdate.enter().append("g").attr("class", classChartArc).call(
      this.setCssRule(false, `.${$ARC.chartArcs} text`, [
        "pointer-events:none",
        "text-anchor:middle"
      ])
    );
    mainPieEnter.append("g").attr("class", classArcs).merge(mainPieUpdate);
    mainPieEnter.append("text").attr("dy", hasGauge && !$$.hasMultiTargets() ? "-.1em" : null).style("opacity", "0").style("text-anchor", $$.getStylePropValue("middle")).style("pointer-events", $$.getStylePropValue("none"));
    $el.text = chartArcs.selectAll(`.${$COMMON.target} text`);
  },
  initArc() {
    const $$ = this;
    const { $el } = $$;
    $el.arcs = $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $ARC.chartArcs).attr("transform", $$.getTranslate("arc"));
    $$.setArcTitle();
  },
  /**
   * Set arc title text
   * @param {string} str Title text
   * @private
   */
  setArcTitle(str) {
    const $$ = this;
    const title = str || $$.getArcTitle();
    const hasGauge = $$.hasType("gauge");
    if (title) {
      const className = hasGauge ? $GAUGE.chartArcsGaugeTitle : $ARC.chartArcsTitle;
      let text = $$.$el.arcs.select(`.${className}`);
      if (text.empty()) {
        text = $$.$el.arcs.append("text").attr("class", className).style("text-anchor", "middle");
      }
      hasGauge && text.attr("dy", "-0.3em");
      setTextValue(text, title, hasGauge ? void 0 : [-0.6, 1.35], true);
    }
  },
  /**
   * Return arc title text
   * @returns {string} Arc title text
   * @private
   */
  getArcTitle() {
    const $$ = this;
    const type = $$.hasType("donut") && "donut" || $$.hasType("gauge") && "gauge";
    return type ? $$.config[`${type}_title`] : "";
  },
  /**
   * Get arc title text with needle value
   * @returns {string|boolean} When title contains needle template string will return processed string, otherwise false
   * @private
   */
  getArcTitleWithNeedleValue() {
    const $$ = this;
    const { config, state } = $$;
    const title = $$.getArcTitle();
    if (title && $$.config.arc_needle_show && /{=[A-Z_]+}/.test(title)) {
      let value = state.current.needle;
      if (!isNumber(value)) {
        value = config.arc_needle_value;
      }
      return tplProcess(title, {
        NEEDLE_VALUE: ~~value
      });
    }
    return false;
  },
  redrawArc(duration, durationForExit, withTransform) {
    const $$ = this;
    const { config, state, $el: { main } } = $$;
    const hasInteraction = config.interaction_enabled;
    const isSelectable = hasInteraction && config.data_selection_isselectable;
    let mainArc = main.selectAll(`.${$ARC.arcs}`).selectAll(`.${$ARC.arc}`).data($$.arcData.bind($$));
    mainArc.exit().transition().duration(durationForExit).style("opacity", "0").remove();
    mainArc = mainArc.enter().append("path").attr("class", $$.getClass("arc", true)).style("fill", (d) => $$.color(d.data)).style("cursor", (d) => {
      var _a;
      return ((_a = isSelectable == null ? void 0 : isSelectable.bind) == null ? void 0 : _a.call(isSelectable, $$.api)(d)) ? "pointer" : null;
    }).style("opacity", "0").each(function(d) {
      if ($$.isGaugeType(d.data)) {
        d.startAngle = config.gauge_startingAngle;
        d.endAngle = config.gauge_startingAngle;
      }
      this._current = d;
    }).merge(mainArc);
    if ($$.hasType("gauge")) {
      $$.updateGaugeMax();
      $$.hasMultiArcGauge() && $$.redrawArcGaugeLine();
    }
    mainArc.attr("transform", (d) => !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : "").style("opacity", function(d) {
      return d === this._current ? "0" : null;
    }).each(() => {
      state.transiting = true;
    }).transition().duration(duration).attrTween("d", function(d) {
      const updated = $$.updateAngle(d);
      if (!updated) {
        return () => "M 0 0";
      }
      if (isNaN(this._current.startAngle)) {
        this._current.startAngle = 0;
      }
      if (isNaN(this._current.endAngle)) {
        this._current.endAngle = this._current.startAngle;
      }
      const interpolate = (0,external_commonjs_d3_interpolate_commonjs2_d3_interpolate_amd_d3_interpolate_root_d3_.interpolate)(this._current, updated);
      this._current = interpolate(0);
      return function(t) {
        const interpolated = interpolate(t);
        interpolated.data = d.data;
        return $$.getArc(interpolated, true);
      };
    }).attr("transform", withTransform ? "scale(1)" : "").style("fill", (d) => {
      let color;
      if ($$.levelColor) {
        color = $$.levelColor(d.data.values[0].value);
        config.data_colors[d.data.id] = color;
      } else {
        color = $$.color(d.data);
      }
      return color;
    }).style("opacity", null).call(endall, function() {
      if ($$.levelColor) {
        const path = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
        const d = path.datum(this._current);
        $$.updateLegendItemColor(d.data.id, path.style("fill"));
      }
      state.transiting = false;
      if (state.redrawing) {
        state.redrawing = false;
        state._targetsToShow = null;
        state._cachedDrawShape = null;
      }
      callFn(config.onrendered, $$.api);
    });
    hasInteraction && $$.bindArcEvent(mainArc);
    $$.hasType("polar") && $$.redrawPolar();
    $$.hasType("gauge") && $$.redrawBackgroundArcs();
    config.arc_needle_show && $$.redrawNeedle();
    $$.redrawArcText(duration);
    $$.redrawArcRangeText();
  },
  /**
   * Update needle element
   * @private
   */
  redrawNeedle() {
    const $$ = this;
    const { $el, config, state: { hiddenTargetIds, radius } } = $$;
    const length = (radius - 1) / 100 * config.arc_needle_length;
    const hasDataToShow = hiddenTargetIds.size !== $$.data.targets.length;
    let needle = $$.$el.arcs.select(`.${$ARC.needle}`);
    const pathFn = config.arc_needle_path;
    const baseWidth = config.arc_needle_bottom_width / 2;
    const topWidth = config.arc_needle_top_width / 2;
    const topRx = config.arc_needle_top_rx;
    const topRy = config.arc_needle_top_ry;
    const bottomLen = config.arc_needle_bottom_len;
    const bottomRx = config.arc_needle_bottom_rx;
    const bottomRy = config.arc_needle_bottom_ry;
    const needleAngle = $$.getNeedleAngle();
    const updateNeedleValue = () => {
      const title = $$.getArcTitleWithNeedleValue();
      title && $$.setArcTitle(title);
    };
    updateNeedleValue();
    if (needle.empty()) {
      needle = $el.arcs.append("path").classed($ARC.needle, true);
      $el.needle = needle;
      $el.needle.updateHelper = (v, updateConfig = false) => {
        if ($el.needle.style("display") !== "none") {
          $$.$T($el.needle).style("transform", `rotate(${$$.getNeedleAngle(v)}deg)`).call(endall, () => {
            updateConfig && (config.arc_needle_value = v);
            updateNeedleValue();
          });
        }
      };
    }
    if (hasDataToShow) {
      const path = isFunction(pathFn) ? pathFn.call($$, length) : `M-${baseWidth} ${bottomLen} A${bottomRx} ${bottomRy} 0 0 0 ${baseWidth} ${bottomLen} L${topWidth} -${length} A${topRx} ${topRy} 0 0 0 -${topWidth} -${length} L-${baseWidth} ${bottomLen} Z`;
      $$.$T(needle).attr("d", path).style("fill", config.arc_needle_color).style("display", null).style("transform", `rotate(${needleAngle}deg)`);
    } else {
      needle.style("display", "none");
    }
  },
  /**
   * Get needle angle value relative given value
   * @param {number} v Value to be calculated angle
   * @returns {number} angle value
   * @private
   */
  getNeedleAngle(v) {
    const $$ = this;
    const { config, state } = $$;
    const arcLength = $$.getArcLength();
    const hasGauge = $$.hasType("gauge");
    const total = $$.getTotalDataSum(true);
    let value = isDefined(v) ? v : config.arc_needle_value;
    let startingAngle = config[`${config.data_type}_startingAngle`] || 0;
    let radian;
    if (!isNumber(value)) {
      value = hasGauge && $$.data.targets.length === 1 ? total : 0;
    }
    state.current.needle = value;
    if (hasGauge) {
      startingAngle = $$.getStartingAngle();
      const radius = config.gauge_fullCircle ? arcLength : startingAngle * -2;
      const { gauge_min: min, gauge_max: max } = config;
      radian = radius * ((value - min) / (max - min));
    } else {
      radian = total ? arcLength * (value / total) : 0;
    }
    return (startingAngle + radian) * (180 / Math.PI);
  },
  redrawBackgroundArcs() {
    const $$ = this;
    const { config, state } = $$;
    const hasMultiArcGauge = $$.hasMultiArcGauge();
    const isFullCircle = config.gauge_fullCircle;
    const showEmptyTextLabel = $$.getTargetsToShow().length === 0 && !!config.data_empty_label_text;
    const startAngle = $$.getStartingAngle();
    const endAngle = isFullCircle ? startAngle + $$.getArcLength() : startAngle * -1;
    let backgroundArc = $$.$el.arcs.select(
      `${hasMultiArcGauge ? "g" : ""}.${$ARC.chartArcsBackground}`
    );
    if (hasMultiArcGauge) {
      let index = 0;
      backgroundArc = backgroundArc.selectAll(`path.${$ARC.chartArcsBackground}`).data($$.data.targets);
      backgroundArc.enter().append("path").attr("class", (d, i) => `${$ARC.chartArcsBackground} ${$ARC.chartArcsBackground}-${i}`).merge(backgroundArc).style("fill", config.gauge_background || null).attr("d", ({ id }) => {
        if (showEmptyTextLabel || state.hiddenTargetIds.has(id)) {
          return "M 0 0";
        }
        const d = {
          data: [{ value: config.gauge_max }],
          startAngle,
          endAngle,
          index: index++
        };
        return $$.getArc(d, true, true);
      });
      backgroundArc.exit().remove();
    } else {
      backgroundArc.attr("d", showEmptyTextLabel ? "M 0 0" : () => {
        const d = {
          data: [{ value: config.gauge_max }],
          startAngle,
          endAngle
        };
        return $$.getArc(d, true, true);
      });
    }
  },
  bindArcEvent(arc) {
    const $$ = this;
    const { config, state } = $$;
    const isTouch = state.inputType === "touch";
    const isMouse = state.inputType === "mouse";
    const _getArcData = (d) => {
      const updated = $$.updateAngle(d);
      return updated ? $$.convertToArcData(updated) : null;
    };
    function selectArc(_this, arcData, id) {
      $$.expandArc(id);
      $$.api.focus(id);
      $$.toggleFocusLegend(id, true);
      $$.showTooltip([arcData], _this);
    }
    function unselectArc(arcData) {
      const id = (arcData == null ? void 0 : arcData.id) || void 0;
      $$.unexpandArc(id);
      $$.api.revert();
      $$.revertLegend();
      $$.hideTooltip();
    }
    arc.on("click", function(event, d, i) {
      var _a;
      const arcData = _getArcData(d);
      if (arcData) {
        (_a = $$.toggleShape) == null ? void 0 : _a.call($$, this, arcData, i);
        config.data_onclick.bind($$.api)(arcData, this);
      }
    });
    if (isMouse) {
      arc.on("mouseover", function(event, d) {
        if (state.transiting) {
          return;
        }
        state.event = event;
        const arcData = _getArcData(d);
        const id = (arcData == null ? void 0 : arcData.id) || void 0;
        selectArc(this, arcData, id);
        $$.setOverOut(true, arcData);
      }).on("mouseout", (event, d) => {
        if (state.transiting || !config.interaction_onout) {
          return;
        }
        state.event = event;
        const arcData = _getArcData(d);
        unselectArc();
        $$.setOverOut(false, arcData);
      }).on("mousemove", function(event, d) {
        const arcData = _getArcData(d);
        state.event = event;
        $$.showTooltip([arcData], this);
      });
    }
    if (isTouch && $$.hasArcType() && !$$.radars) {
      const getEventArc = (event) => {
        var _a, _b;
        const { clientX, clientY } = (_b = (_a = event.changedTouches) == null ? void 0 : _a[0]) != null ? _b : { clientX: 0, clientY: 0 };
        const eventArc = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(browser_doc.elementFromPoint(clientX, clientY));
        return eventArc;
      };
      $$.$el.svg.on("touchstart touchmove", function(event) {
        if (state.transiting) {
          return;
        }
        state.event = event;
        const eventArc = getEventArc(event);
        const datum = eventArc.datum();
        const updated = (datum == null ? void 0 : datum.data) && datum.data.id ? $$.updateAngle(datum) : null;
        const arcData = updated ? $$.convertToArcData(updated) : null;
        const id = (arcData == null ? void 0 : arcData.id) || void 0;
        $$.callOverOutForTouch(arcData);
        isUndefined(id) ? unselectArc() : selectArc(this, arcData, id);
      }, { passive: true });
    }
  },
  redrawArcText(duration) {
    const $$ = this;
    const { config, state, $el: { main, arcs } } = $$;
    const hasGauge = $$.hasType("gauge");
    const hasMultiArcGauge = $$.hasMultiArcGauge();
    let text;
    if (!(hasGauge && $$.data.targets.length === 1 && config.gauge_title)) {
      text = main.selectAll(`.${$ARC.chartArc}`).select("text").style("opacity", "0").attr("class", (d) => $$.isGaugeType(d.data) ? $GAUGE.gaugeValue : null).call($$.textForArcLabel.bind($$)).style("font-size", (d) => $$.isGaugeType(d.data) && $$.data.targets.length === 1 && !hasMultiArcGauge ? `${Math.round(state.radius / 5)}px` : null);
      updateTextImage.call($$);
      text.attr("transform", function(d) {
        return $$.transformForArcLabel.bind($$)(this, d);
      }).transition().duration(duration).style(
        "opacity",
        (d) => $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? null : "0"
      );
      hasMultiArcGauge && text.attr("dy", "-.1em");
    }
    main.select(`.${$ARC.chartArcsTitle}`).style("opacity", $$.hasType("donut") || hasGauge ? null : "0");
    if (hasGauge) {
      const isFullCircle = config.gauge_fullCircle;
      isFullCircle && (text == null ? void 0 : text.attr("dy", `${hasMultiArcGauge ? 0 : Math.round(state.radius / 14)}`));
      if (config.gauge_label_show) {
        arcs.select(`.${$GAUGE.chartArcsGaugeUnit}`).attr("dy", `${isFullCircle ? 1.5 : 0.75}em`).text(config.gauge_units);
        arcs.select(`.${$GAUGE.chartArcsGaugeMin}`).attr("dx", `${-1 * (state.innerRadius + (state.radius - state.innerRadius) / (isFullCircle ? 1 : 2))}px`).attr("dy", "1.2em").text($$.textForGaugeMinMax(config.gauge_min, false));
        !isFullCircle && arcs.select(`.${$GAUGE.chartArcsGaugeMax}`).attr("dx", `${state.innerRadius + (state.radius - state.innerRadius) / 2}px`).attr("dy", "1.2em").text($$.textForGaugeMinMax(config.gauge_max, true));
      }
    }
    isLabelWithLine.call($$) && redrawArcLabelLines.call($$, duration);
  },
  /**
   * Get Arc element by id or index
   * @param {string|number} value id or index of Arc
   * @returns {d3Selection} Arc path element
   * @private
   */
  getArcElementByIdOrIndex(value) {
    const $$ = this;
    const { $el: { arcs } } = $$;
    const filterFn = isNumber(value) ? (d) => d.index === value : (d) => d.data.id === value;
    return arcs == null ? void 0 : arcs.selectAll(`.${$COMMON.target} path`).filter(filterFn);
  }
});

;// ./src/config/resolver/shape/arc.helpers.ts






function extendArc(module, option) {
  extend(ChartInternal.prototype, [shape_arc, point].concat(module || []));
  Options.setOptions([common_point].concat(option || []));
}

;// ./src/config/resolver/shape/donut.ts




let donut_donut = () => (extendArc(void 0, [arc, donut]), (donut_donut = () => TYPE.DONUT)());

;// ./src/ChartInternal/shape/funnel.ts
var funnel_defProp = Object.defineProperty;
var funnel_getOwnPropSymbols = Object.getOwnPropertySymbols;
var funnel_hasOwnProp = Object.prototype.hasOwnProperty;
var funnel_propIsEnum = Object.prototype.propertyIsEnumerable;
var funnel_defNormalProp = (obj, key, value) => key in obj ? funnel_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var funnel_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (funnel_hasOwnProp.call(b, prop))
      funnel_defNormalProp(a, prop, b[prop]);
  if (funnel_getOwnPropSymbols)
    for (var prop of funnel_getOwnPropSymbols(b)) {
      if (funnel_propIsEnum.call(b, prop))
        funnel_defNormalProp(a, prop, b[prop]);
    }
  return a;
};




function _getSize(checkNeck = false) {
  const $$ = this;
  const { config, state: { current: { width, height } } } = $$;
  const padding = $$.getCurrentPadding();
  const size = funnel_spreadValues({
    width: width - padding.left - padding.right,
    height: height - (config.legend_show ? $$.getLegendHeight() + 10 : 0) - padding.top - padding.bottom
  }, padding);
  if (checkNeck) {
    const neck = _getNeckSize.call($$, size);
    const isRotated = config.funnel_rotated;
    size.width = Math.max(size.width, isRotated ? neck.height : neck.width);
    size.height = Math.max(size.height, isRotated ? neck.width : neck.height);
  }
  return size;
}
function _getNeckSize(current) {
  const $$ = this;
  const { config } = $$;
  const isRotated = config.funnel_rotated;
  const [w, h] = [config.funnel_neck_width, config.funnel_neck_height].map(
    (v, i) => isObject(v) ? current[isRotated !== !i ? "width" : "height"] * v.ratio : v
  );
  return { width: w, height: h };
}
function _getCoord(d) {
  const $$ = this;
  const isRotated = $$.config.funnel_rotated;
  const { width, height } = _getSize.call($$, true);
  const coords = [];
  d.forEach((item, i) => {
    const { ratio = 0 } = item;
    const prev = i > 0 ? coords[i - 1][2][isRotated ? 0 : 1] : 0;
    const end = ratio + prev;
    coords.push(item.coords = isRotated ? [
      [prev, 0],
      [end, 0],
      [end, height],
      [prev, height],
      [prev, 0]
    ] : [
      [0, prev],
      [width, prev],
      [width, end],
      [0, end],
      [0, prev]
    ]);
  });
  return coords;
}
function _getClipPath() {
  const $$ = this;
  const isRotated = $$.config.funnel_rotated;
  const { width, height } = _getSize.call($$, true);
  const neck = _getNeckSize.call($$, { width, height });
  let middleCoords;
  if (isRotated) {
    const neckY = (height - neck.width) / 2;
    const bodyW = width - neck.height;
    middleCoords = [
      [bodyW, neckY],
      [width, neckY],
      [width, height - neckY],
      [bodyW, height - neckY],
      [0, height]
    ];
  } else {
    const neckX = (width - neck.width) / 2;
    const bodyH = height - neck.height;
    middleCoords = [
      [width, 0],
      [width - neckX, bodyH],
      [width - neckX, height],
      [neckX, height],
      [neckX, bodyH]
    ];
  }
  return `M${[[0, 0], ...middleCoords, [0, 0]].join("L")}z`;
}
function _getFunnelData(d) {
  const $$ = this;
  const { config } = $$;
  const data = d.map((d2) => ({
    id: d2.id,
    value: d2.values.reduce((a, b) => a + b.value, 0)
  }));
  config.data_order && data.sort($$.getSortCompareFn.bind($$)(true));
  return _updateRatio.call($$, data);
}
function _updateRatio(data) {
  const $$ = this;
  const { width, height } = _getSize.call($$);
  const total = $$.getTotalDataSum(true);
  const dimension = $$.config.funnel_rotated ? width : height;
  data.forEach((d) => {
    d.ratio = d.value / total * dimension;
  });
  return data;
}
function _easeInOutCubic(t) {
  return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
function _generateSmoothEdgePoints(start, end, startEdge, endEdge, isRotated) {
  const points = [];
  const SPLINE_POINTS = 20;
  for (let i = 0; i <= SPLINE_POINTS; i++) {
    const t = i / SPLINE_POINTS;
    const pos = start + (end - start) * t;
    const edge = startEdge + (endEdge - startEdge) * _easeInOutCubic(t);
    points.push(isRotated ? [pos, edge] : [edge, pos]);
  }
  return points;
}
function _getSplineClipPath() {
  var _a;
  const $$ = this;
  const isRotated = $$.config.funnel_rotated;
  const { width, height } = _getSize.call($$, true);
  const neck = _getNeckSize.call($$, { width, height });
  const lineGen = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.line)().x((d) => d[0]).y((d) => d[1]).curve(external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveLinear);
  const neckHalf = (isRotated ? height - neck.width : width - neck.width) / 2;
  const bodySize = isRotated ? width - neck.height : height - neck.height;
  const edge1 = _generateSmoothEdgePoints(
    0,
    bodySize,
    isRotated ? 0 : width,
    isRotated ? neckHalf : width - neckHalf,
    isRotated
  );
  const edge2 = [];
  if (neck.height > 0) {
    edge1.push(isRotated ? [width, neckHalf] : [width - neckHalf, height]);
    edge2.push(isRotated ? [width, height - neckHalf] : [neckHalf, height]);
  }
  edge2.push(..._generateSmoothEdgePoints(
    bodySize,
    0,
    isRotated ? height - neckHalf : neckHalf,
    isRotated ? height : 0,
    isRotated
  ));
  if (edge1.length > 1) {
    const [a, b] = isRotated ? [1, 0] : [0, 1];
    edge1.splice(1, 0, [edge1[a][0], edge1[b][1]]);
    const lastIdx = edge2.length - 1;
    if (lastIdx > 0) {
      edge2.splice(lastIdx, 0, [edge2[lastIdx - a][0], edge2[lastIdx - b][1]]);
    }
  }
  const path1 = lineGen(edge1) || "";
  const path2 = ((_a = lineGen(edge2)) == null ? void 0 : _a.replace(/^M/, "L")) || "";
  return isRotated ? `${path1}${path2}z` : `M0,0${path1.replace(/^M/, "L")}${path2}z`;
}
/* harmony default export */ var funnel = ({
  /**
   * Initialize funnel
   * @private
   */
  initFunnel() {
    const $$ = this;
    const { $el } = $$;
    $el.funnel = $el.main.select(`.${$COMMON.chart}`).append("g").classed($FUNNEL.chartFunnels, true);
    $el.funnel.background = $el.funnel.append("path").classed($FUNNEL.funnelBackground, true);
    $$.bindFunnelEvent();
  },
  /**
   * Bind events
   * @private
   */
  bindFunnelEvent() {
    const $$ = this;
    const { $el: { funnel }, config, state } = $$;
    if (!config.interaction_enabled) {
      return;
    }
    const getTarget = (event) => {
      var _a;
      const target = event.isTrusted ? event.target : (_a = state.eventReceiver.rect) == null ? void 0 : _a.node();
      if (target && /^path$/i.test(target.tagName)) {
        state.event = event;
        return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
      }
    };
    const isTouch = state.inputType === "touch";
    funnel.on(isTouch ? "touchstart" : "mouseover mousemove", (event) => {
      const data = getTarget(event);
      if (data) {
        $$.showTooltip([data], event.target);
        /^(touchstart|mouseover)$/.test(event.type) && $$.setOverOut(true, data);
      }
    }, isTouch ? { passive: true } : void 0).on(isTouch ? "touchend" : "mouseout", (event) => {
      const data = getTarget(event);
      if (config.interaction_onout) {
        $$.hideTooltip();
        $$.setOverOut(false, data);
      }
    });
  },
  /**
   * Update targets for funnel
   * @param {object} t Data object
   * @private
   */
  updateTargetsForFunnel(t) {
    const $$ = this;
    const { $el: { funnel } } = $$;
    if (!funnel) {
      $$.initFunnel();
    }
    const classChartFunnel = $$.getChartClass("Funnel");
    const classFunnel = $$.getClass("funnel", true);
    const targets = _getFunnelData.call($$, t.filter($$.isFunnelType.bind($$)));
    const mainFunnelUpdate = $$.filterNullish(targets);
    const mainFunnel = funnel.selectAll(`.${$FUNNEL.chartFunnel}`).data(mainFunnelUpdate);
    mainFunnel.exit().remove();
    const mainFunnelEnter = mainFunnel.enter().insert("g", `.${$FUNNEL.funnelBackground}`);
    mainFunnelEnter.append("path");
    funnel.path = mainFunnelEnter.merge(mainFunnel).attr("class", classChartFunnel).select("path").attr("class", classFunnel).style("opacity", "0").style("fill", $$.color);
  },
  /**
   * Update funnel path selection
   * @param {object} targets Updated target data
   * @private
   */
  updateFunnel(targets) {
    const $$ = this;
    const { $el: { funnel } } = $$;
    const targetIds = targets.map(({ id }) => id);
    funnel.path = funnel.path.filter((d) => targetIds.includes(d.id));
  },
  /**
   * Generate funnel coordinate points data for text labels
   * @returns {function(IDataRow): Array.<Array.<number>>} Point getter function
   * @private
   */
  generateGetFunnelPoints() {
    const $$ = this;
    const { config, $el: { funnel } } = $$;
    const isRotated = config.funnel_rotated;
    const targets = $$.filterTargetsToShow(funnel.path);
    const { top, left, width, height } = _getSize.call($$);
    const points = {};
    let accumulated = 0;
    targets.each((d) => {
      const start = accumulated;
      const { ratio } = d;
      accumulated += ratio;
      const offset = isRotated ? left : top;
      const segmentStart = offset + start;
      const segmentEnd = offset + accumulated;
      const center = (segmentStart + segmentEnd) / 2;
      const crossCenter = isRotated ? top + height / 2 : left + width / 2;
      points[d.id] = isRotated ? [[segmentStart, crossCenter], [segmentEnd, crossCenter], [center, crossCenter]] : [[crossCenter, segmentStart], [crossCenter, segmentEnd], [crossCenter, center]];
    });
    return (d) => points[d.id];
  },
  /**
   * Called whenever redraw happens
   * @private
   */
  redrawFunnel() {
    const $$ = this;
    const { config, $T, $el: { funnel } } = $$;
    const targets = $$.filterTargetsToShow(funnel.path);
    const coords = _getCoord.call($$, _updateRatio.call($$, targets.data()));
    const { top, left } = _getSize.call($$);
    const clipPath = (config.funnel_spline ? _getSplineClipPath : _getClipPath).call($$);
    funnel.attr("transform", `translate(${left}, ${top})`).attr("clip-path", `path('${clipPath}')`);
    funnel.background.attr("d", clipPath);
    $T(targets).attr("d", (_, i) => `M${coords[i].join("L")}z`).style("opacity", "1");
    funnel.selectAll("g").style("opacity", null);
  }
});

;// ./src/config/Options/shape/funnel.ts
/* harmony default export */ var shape_funnel = ({
  /**
   * Set funnel options
   * @name funnel
   * @memberof Options
   * @type {object}
   * @property {object} funnel Funnel object
   * @property {number} [funnel.neck.width=0] Set funnel neck width.
   * @property {number} [funnel.neck.height=0] Set funnel neck height.
   * @property {number} [funnel.neck.width.ratio] Set funnel neck width in ratio.
   * @property {number} [funnel.neck.height.ratio] Set funnel neck height in ratio.
   * @property {boolean} [funnel.rotated=false] Set funnel direction rotated. When set to `true`, the funnel will be rendered horizontally (left to right) instead of vertically (top to bottom).
   * @property {boolean} [funnel.spline=false] Enable spline (curved) edges for the funnel.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.PolarChart)
   * @example
   *  funnel: {
   *      neck: {
   *          width: 200,
   *          height: 100,
   *
   *          // or specify as ratio value (relative to the chart size)
   *          width: {
   *            ratio: 0.5
   *          },
   *          height: {
   *            ratio: 0.5
   *          }
   *      },
   *
   *      // Render funnel horizontally (left to right)
   *      rotated: true,
   *
   *      // Enable curved edges
   *      spline: true
   *  }
   */
  funnel_neck_width: 0,
  funnel_neck_height: 0,
  funnel_rotated: false,
  funnel_spline: false
});

;// ./src/config/resolver/shape/funnel.ts




let funnel_funnel = () => (extendArc([funnel], [shape_funnel]), (funnel_funnel = () => TYPE.FUNNEL)());

;// ./src/ChartInternal/shape/gauge.ts



/* harmony default export */ var gauge = ({
  initGauge() {
    const $$ = this;
    const { config, $el: { arcs } } = $$;
    const appendText = (className = null, value = "") => {
      arcs.append("text").attr("class", className).style("text-anchor", "middle").style("pointer-events", "none").text(value);
    };
    if ($$.hasType("gauge")) {
      const hasMulti = $$.hasMultiArcGauge();
      arcs.append(hasMulti ? "g" : "path").attr("class", $ARC.chartArcsBackground).style("fill", !hasMulti && config.gauge_background || null);
      config.gauge_units && appendText($GAUGE.chartArcsGaugeUnit);
      if (config.gauge_label_show) {
        appendText($GAUGE.chartArcsGaugeMin);
        !config.gauge_fullCircle && appendText($GAUGE.chartArcsGaugeMax);
      }
    }
  },
  updateGaugeMax() {
    const $$ = this;
    const { config, state } = $$;
    const hasMultiGauge = $$.hasMultiArcGauge();
    const max = hasMultiGauge ? $$.getMinMaxData().max[0].value : $$.getTotalDataSum(state.rendered);
    if (!config.gauge_enforceMinMax && max + config.gauge_min * (config.gauge_min > 0 ? -1 : 1) > config.gauge_max) {
      config.gauge_max = max - config.gauge_min;
    }
  },
  redrawArcGaugeLine() {
    const $$ = this;
    const { config, state, $el } = $$;
    const { hiddenTargetIds } = $$.state;
    const arcLabelLines = $el.main.selectAll(`.${$ARC.arcs}`).selectAll(`.${$ARC.arcLabelLine}`).data($$.arcData.bind($$));
    const mainArcLabelLine = arcLabelLines.enter().append("rect").attr(
      "class",
      (d) => `${$ARC.arcLabelLine} ${$COMMON.target} ${$COMMON.target}-${d.data.id}`
    ).merge(arcLabelLines);
    mainArcLabelLine.style(
      "fill",
      (d) => $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data)
    ).style("display", config.gauge_label_show ? null : "none").each(function(d) {
      let lineLength = 0;
      const lineThickness = 2;
      let x = 0;
      let y = 0;
      let transform = "";
      if (!hiddenTargetIds.has(d.data.id)) {
        const updated = $$.updateAngle(d);
        const innerLineLength = state.gaugeArcWidth / $$.getTargetsToShow().length * (updated.index + 1);
        const lineAngle = updated.endAngle - Math.PI / 2;
        const arcInnerRadius = state.radius - innerLineLength;
        const linePositioningAngle = lineAngle - (arcInnerRadius === 0 ? 0 : 1 / arcInnerRadius);
        lineLength = state.radiusExpanded - state.radius + innerLineLength;
        x = Math.cos(linePositioningAngle) * arcInnerRadius;
        y = Math.sin(linePositioningAngle) * arcInnerRadius;
        transform = `rotate(${lineAngle * 180 / Math.PI}, ${x}, ${y})`;
      }
      ;(0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).attr("x", x).attr("y", y).attr("width", lineLength).attr("height", lineThickness).attr("transform", transform).style("stroke-dasharray", `0, ${lineLength + lineThickness}, 0`);
    });
  },
  textForGaugeMinMax(value, isMax) {
    const $$ = this;
    const { config } = $$;
    const format = config.gauge_label_extents;
    return isFunction(format) ? format.bind($$.api)(value, isMax) : value;
  },
  getGaugeLabelHeight() {
    const { config } = this;
    return this.config.gauge_label_show && !config.gauge_fullCircle ? 20 : 0;
  },
  getPaddingBottomForGauge() {
    return this.getGaugeLabelHeight() * 2;
  }
});

;// ./src/config/Options/shape/gauge.ts
/* harmony default export */ var shape_gauge = ({
  /**
   * Set gauge options
   * @name gauge
   * @memberof Options
   * @type {object}
   * @property {object} gauge Gauge object
   * @property {boolean} [gauge.background=""] Set background color. (The `.bb-chart-arcs-background` element)
   * @property {boolean} [gauge.fullCircle=false] Show full circle as donut. When set to 'true', the max label will not be showed due to start and end points are same location.
   * @property {boolean} [gauge.label.show=true] Show or hide label on gauge.
   * @property {function} [gauge.label.extents] Set customized min/max label text.
   * @property {function} [gauge.label.format] Set formatter for the label on gauge. Label text can be multilined with `\n` character.<br>
   * Will pass following arguments to the given function:
   * - value {number}: absolute value
   * - ratio {number}: value's ratio
   * - id {string}: data's id value
   * @property {number|function} [gauge.label.ratio=undefined] Set ratio of labels position.
   * @property {number} [gauge.label.threshold=0] Set threshold ratio to show/hide labels.
   * @property {boolean|object} [gauge.label.line=false] Enable label with lines (displayed outside with connector lines).
   *  - **NOTE:** Only applicable for single gauge (not for `gauge.type="multi"`).
   *  - `true`: Enable label with lines with default settings
   *  - `false`: Labels are displayed inside the gauge (default behavior).
   *  - `{show: boolean, distance: number, text: boolean}`: Enable label with lines with custom settings. When object member is not provided, it will be set to default values.
   * @property {boolean} [gauge.label.line.show=true] Show or hide connector lines.
   * @property {number} [gauge.label.line.distance=20] Set the distance of the horizontal part of the connector line in pixels.
   * @property {boolean|function} [gauge.label.line.text=true] Show text at the end of the connector line (outside the shape).
   *  - `true`: show data "id" text
   *  - `false`: use default formatter(label.format) to show text
   *  - `function(value, ratio, id)`: Custom formatter function for the text.
   *  - **NOTE:** When the viewport size decreases, the size is adjusted based on the shape, so text may appear clipped. In this case, consider setting `overflow: visible` on the SVG node.
   * @property {object|function} [gauge.label.image] Set image to be displayed next to the label text.<br><br>
   * When function is specified, will receives 3 arguments such as `v, id, i` and it must return an image object with `url`, `width`, `height`, and optional `pos` properties.<br><br>
   * The arguments are:<br>
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   * @property {string} gauge.label.image.url Image URL path. Can use placeholder `{=ID}` which will be replaced with the data ID.
   * @property {number} gauge.label.image.width Image width in pixels.
   * @property {number} gauge.label.image.height Image height in pixels.
   * @property {object} [gauge.label.image.pos] Image position relative to the label text.
   * @property {number} [gauge.label.image.pos.x=0] x coordinate position, relative the original.
   * @property {number} [gauge.label.image.pos.y=0] y coordinate position, relative the original.
   * @property {boolean} [gauge.expand=true] Enable or disable expanding gauge.
   * @property {number} [gauge.expand.rate=0.98] Set expand rate.
   * @property {number} [gauge.expand.duration=50] Set the expand transition time in milliseconds.
   * @property {boolean} [gauge.enforceMinMax=false] Enforce to given min/max value.
   * - **Note:** Applies only to unstacked/multi-arc gauges; stacked gauge data is not supported.
   * 	- When `gauge.min=50` and given value is `30`, gauge will render as empty value.
   * 	- When `gauge.max=100` and given value is `120`, gauge will render till 100, not surpassing max value.
   * @property {number} [gauge.min=0] Set min value of the gauge.
   * @property {number} [gauge.max=100] Set max value of the gauge.
   * @property {number} [gauge.startingAngle=-1 * Math.PI / 2] Set starting angle where data draws.
   *
   * **Limitations:**
   * - when `gauge.fullCircle=false`:
   *   - -1 * Math.PI / 2 <= startingAngle <= Math.PI / 2
   *   - `startingAngle <= -1 * Math.PI / 2` defaults to `-1 * Math.PI / 2`
   *   - `startingAngle >= Math.PI / 2` defaults to `Math.PI / 2`
   * - when `gauge.fullCircle=true`:
   *   - -1 * Math.PI < startingAngle < Math.PI
   *   - `startingAngle < -1 * Math.PI` defaults to `Math.PI`
   *   - `startingAngle >  Math.PI` defaults to `Math.PI`
   * @property {number} [gauge.arcLength=100] Set the length of the arc to be drawn in percent from -100 to 100.<br>
   * Negative value will draw the arc **counterclockwise**. Need to be used in conjunction with `gauge.fullCircle=true`.
   *
   * **Limitations:**
   * - -100 <= arcLength (in percent) <= 100
   * - 'arcLength < -100' defaults to -100
   * - 'arcLength > 100' defaults to 100
   * @property {string} [gauge.title=""] Set title of gauge chart. Use `\n` character for line break.
   *  - **NOTE:**
   *    - When `arc.needle.show=true` is set, special template `{=NEEDLE_VALUE}` can be used inside the title text to show current needle value.
   * @property {string} [gauge.units] Set units of the gauge.
   * @property {number} [gauge.width] Set width of gauge chart.
   * @property {string} [gauge.type="single"] Set type of gauge to be displayed.<br><br>
   * **Available Values:**
   * - single
   * - multi
   * @property {number} [gauge.arcs.minWidth=5] Set minimal width of gauge arcs until the innerRadius disappears.
   * @see [Demo: enforceMinMax, min/max](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeMinMax)
   * @see [Demo: archLength](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeArcLength)
   * @see [Demo: startingAngle](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeStartingAngle)
   * @see [Demo: label image](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeLabelImage)
   * @see [Demo: label line](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeLabelLine)
   * @see [Demo: label ratio](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeLabelRatio)
   * @example
   *  gauge: {
   *      background: "#eee", // will set 'fill' css prop for '.bb-chart-arcs-background' classed element.
   *      fullCircle: false,
   *      label: {
   *          show: false,
   *          format: function(value, ratio, id) {
   *              return value;
   *
   *              // to multiline, return with '\n' character
   *              // return value +"%\nLine1\n2Line2";
   *          },
   *
   *           extents: function(value, isMax) {
   *              return (isMax ? "Max:" : "Min:") + value;
   *          },
   *
   *          // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
   *          // if data value is below than 0.1, text label will be hidden.
   *          threshold: 0.1,
   *
   *          // Enable label with lines (displayed outside with connector lines)
   *          // NOTE: Only works with single gauge (not gauge.type="multi")
   *          line: true,   // enable label with lines with default settings
   *          line: {       // enable label with lines with custom settings
   *              show: true,      // enable lines (default: true when line is enabled)
   *              distance: 30,    // distance of horizontal line in pixels (default: 20)
   *
   *              // show text at the end of connector line (outside the shape)
   *              text: true,  // use default formatter
   *              text: function(value, ratio, id) {  // custom formatter
   *                  return d3.format(".1%")(ratio);
   *              }
   *          },
   *
   *          // set ratio callback. Should return ratio value
   *          ratio: function(d, radius, h) {
   *              ...
   *              return ratio;
   *          },
   *          // or set ratio number
   *          ratio: 0.5,
   *
   *          // set image to be displayed next to the label text
   *          image: {
   *             url: "./sample.svg",
   *
   *             // use placeholder to dynamically set image URL based on data ID
   *             url: "./images/{=ID}.svg",  // will be replaced to "./images/data1.svg", "./images/data2.svg", etc.
   *             width: 35,
   *             height: 35,
   *             pos: {
   *                x: 0,
   *                y: 0
   *             }
   *          },
   *
   *          // or use function to return image configuration dynamically
   *          image: function(v, id, i) {
   *             // Return different images based on value
   *             if (v > 500) {
   *                return {
   *                   url: "./high-value.svg",
   *                   width: 40,
   *                   height: 40,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if (v > 100) {
   *                return {
   *                   url: "./medium-value.svg",
   *                   width: 30,
   *                   height: 30,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if(v < 5) {
   *                // Return falsy value in case of don't want to show image
   *                return null;
   *             } else {
   *                return {
   *                   url: "./low-value.svg",
   *                   width: 20,
   *                   height: 20,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             }
   *          }
   *      },
   *
   *      // disable expand transition for interaction
   *      expand: false,
   *
   *      expand: {
   *      	// set duration of expand transition to 500ms.
   *          duration: 500,
   *
   *      	// set expand area rate
   *          rate: 1
   *      },
   *
   *      // enforce min/max value.
   * 		// when given value < min, will render as empty value.
   * 		// when value > max, will render to given max value not surpassing it.
   *      enforceMinMax: true,
   *
   *      min: -100,
   *      max: 200,
   *      type: "single"  // or 'multi'
   *      title: "Title Text",
   *
   *      // when 'arc.needle.show=true' is set, can show current needle value.
   *      title: "Needle value:\n{=NEEDLE_VALUE}",
   *
   *      units: "%",
   *      width: 10,
   *      startingAngle: -1 * Math.PI / 2,
   *      arcLength: 100,
   *      arcs: {
   *          minWidth: 5
   *      }
   *  }
   */
  gauge_background: "",
  gauge_fullCircle: false,
  gauge_label_show: true,
  gauge_label_extents: void 0,
  gauge_label_format: void 0,
  gauge_label_ratio: void 0,
  gauge_label_threshold: 0,
  gauge_label_line: false,
  gauge_label_image: void 0,
  gauge_enforceMinMax: false,
  gauge_min: 0,
  gauge_max: 100,
  gauge_type: "single",
  gauge_startingAngle: -1 * Math.PI / 2,
  gauge_arcLength: 100,
  gauge_title: "",
  gauge_units: void 0,
  gauge_width: void 0,
  gauge_arcs_minWidth: 5,
  gauge_expand: {},
  gauge_expand_rate: 0.98,
  gauge_expand_duration: 50
});

;// ./src/config/resolver/shape/gauge.ts





let gauge_gauge = () => (extendArc([gauge], [arc, shape_gauge]), (gauge_gauge = () => TYPE.GAUGE)());

;// ./src/config/resolver/shape/line.ts



let line_line = () => (extendLine(), (line_line = () => TYPE.LINE)());
let line_spline = () => (extendLine(void 0, [spline]), (line_spline = () => TYPE.SPLINE)());
let step = () => (extendLine(), (step = () => TYPE.STEP)());

;// ./src/config/Options/shape/pie.ts
/* harmony default export */ var pie = ({
  /**
   * Set pie options
   * @name pie
   * @memberof Options
   * @type {object}
   * @property {object} pie Pie object
   * @property {boolean} [pie.label.show=true] Show or hide label on each pie piece.
   * @property {function} [pie.label.format] Set formatter for the label on each pie piece.
   * @property {number|function} [pie.label.ratio=undefined] Set ratio of labels position.
   * @property {number} [pie.label.threshold=0.05] Set threshold ratio to show/hide labels.
   * @property {boolean|object} [pie.label.line=false] Enable label with lines (displayed outside with connector lines).
   *  - `true`: Enable label with lines with default settings
   *  - `false`: Labels are displayed inside the pie slices (default behavior).
   *  - `{show: boolean, distance: number, text: boolean}`: Enable label with lines with custom settings. When object member is not provided, it will be set to default values.
   * @property {boolean} [pie.label.line.show=true] Show or hide connector lines.
   * @property {number} [pie.label.line.distance=20] Set the distance of the horizontal part of the connector line in pixels.
   * @property {boolean|function} [pie.label.line.text=true] Show text at the end of the connector line (outside the shape).
   *  - `true`: show data "id" text
   *  - `false`: use default formatter(label.format) to show text
   *  - `function(value, ratio, id)`: Custom formatter function for the text.
   *  - **NOTE:** When the viewport size decreases, the size is adjusted based on the shape, so text may appear clipped. In this case, consider setting `overflow: visible` on the SVG node.
   * @property {object|function} [pie.label.image] Set image to be displayed next to the label text.<br><br>
   * When function is specified, will receives 3 arguments such as `v, id, i` and it must return an image object with `url`, `width`, `height`, and optional `pos` properties.<br><br>
   * The arguments are:<br>
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   * @property {string} pie.label.image.url Image URL path. Can use placeholder `{=ID}` which will be replaced with the data ID.
   * @property {number} pie.label.image.width Image width in pixels.
   * @property {number} pie.label.image.height Image height in pixels.
   * @property {object} [pie.label.image.pos] Image position relative to the label text.
   * @property {number} [pie.label.image.pos.x=0] x coordinate position, relative the original.
   * @property {number} [pie.label.image.pos.y=0] y coordinate position, relative the original.
   * @property {boolean|object} [pie.expand=true] Enable or disable expanding pie pieces.
   * @property {number} [pie.expand.rate=0.98] Set expand rate.
   * @property {number} [pie.expand.duration=50] Set expand transition time in ms.
   * @property {number|object} [pie.innerRadius=0] Sets the inner radius of pie arc.
   * @property {number|object|undefined} [pie.outerRadius=undefined] Sets the outer radius of pie arc.
   * @property {number} [pie.padAngle=0] Set padding between data.
   * @property {number} [pie.padding=0] Sets the gap between pie arcs.
   * @property {number} [pie.startingAngle=0] Set starting angle where data draws.
   * @see [Demo: expand.rate](https://naver.github.io/billboard.js/demo/#PieChartOptions.ExpandRate)
   * @see [Demo: innerRadius](https://naver.github.io/billboard.js/demo/#PieChartOptions.InnerRadius)
   * @see [Demo: outerRadius](https://naver.github.io/billboard.js/demo/#PieChartOptions.OuterRadius)
   * @see [Demo: startingAngle](https://naver.github.io/billboard.js/demo/#PieChartOptions.StartingAngle)
   * @see [Demo: label image](https://naver.github.io/billboard.js/demo/#PieChartOptions.LabelImage)
   * @see [Demo: label line](https://naver.github.io/billboard.js/demo/#PieChartOptions.LabelLine)
   * @example
   *  pie: {
   *      label: {
   *          show: false,
   *          format: function(value, ratio, id) {
   *              return d3.format("$")(value);
   *
   *              // to multiline, return with '\n' character
   *              // return value +"%\nLine1\n2Line2";
   *          },
   *
   *          // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
   *          // if data value is below than 0.1, text label will be hidden.
   *          threshold: 0.1,
   *
   *          // set ratio callback. Should return ratio value
   *          ratio: function(d, radius, h) {
   *              ...
   *              return ratio;
   *          },
   *          // or set ratio number
   *          ratio: 0.5,
   *
   *          // Enable label with lines (displayed outside with connector lines)
   *          line: false,  // default - labels inside
   *          line: true,   // enable label with lines with default settings
   *          line: {       // enable label with lines with custom settings
   *             show: true,
   *             distance: 20,  // horizontal line distance in pixels
   *
   *             // show text at the end of connector line (outside the shape)
   *             text: true,  // use default formatter
   *             text: function(value, ratio, id) {  // custom formatter
   *                 return d3.format(".1%")(ratio);
   *             }
   *          },
   *
   *          // set image to be displayed next to the label text
   *          image: {
   *             url: "./sample.svg",
   *
   *             // use placeholder to dynamically set image URL based on data ID
   *             url: "./images/{=ID}.svg",  // will be replaced to "./images/data1.svg", "./images/data2.svg", etc.
   *             width: 35,
   *             height: 35,
   *             pos: {
   *                x: 0,
   *                y: 0
   *             }
   *          },
   *
   *          // or use function to return image configuration dynamically
   *          image: function(v, id, i) {
   *             // Return different images based on value
   *             if (v > 500) {
   *                return {
   *                   url: "./high-value.svg",
   *                   width: 40,
   *                   height: 40,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if (v > 100) {
   *                return {
   *                   url: "./medium-value.svg",
   *                   width: 30,
   *                   height: 30,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if(v < 5) {
   *                // Return falsy value in case of don't want to show image
   *                return null;
   *             } else {
   *                return {
   *                   url: "./low-value.svg",
   *                   width: 20,
   *                   height: 20,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             }
   *          }
   *      },
   *
   *      // disable expand transition for interaction
   *      expand: false,
   *
   *      expand: {
   *      	// set duration of expand transition to 500ms.
   *          duration: 500,
   *
   *      	// set expand area rate
   *          rate: 1
   *      },
   *
   *      innerRadius: 0,
   *
   *      // set different innerRadius for each data
   *      innerRadius: {
   *      	data1: 10,
   *      	data2: 0
   *      },
   *
   *      outerRadius: 100,
   *
   *      // set different outerRadius for each data
   *      outerRadius: {
   *      	data1: 50,
   *      	data2: 100
   *      }
   *
   *      padAngle: 0.1,
   *      padding: 0,
   *      startingAngle: 1
   *  }
   */
  pie_label_show: true,
  pie_label_format: void 0,
  pie_label_ratio: void 0,
  pie_label_threshold: 0.05,
  pie_label_line: false,
  pie_label_image: void 0,
  pie_expand: {},
  pie_expand_rate: 0.98,
  pie_expand_duration: 50,
  pie_innerRadius: 0,
  pie_outerRadius: void 0,
  pie_padAngle: 0,
  pie_padding: 0,
  pie_startingAngle: 0
});

;// ./src/config/resolver/shape/pie.ts




let pie_pie = () => (extendArc(void 0, [arc, pie]), (pie_pie = () => TYPE.PIE)());

;// ./src/ChartInternal/shape/polar.ts


function getDataMax($$) {
  const levelMax = $$.config.polar_level_max;
  let dataMax = $$.getMinMaxData().max[0].value;
  if (levelMax && levelMax > dataMax) {
    dataMax = levelMax;
  }
  return dataMax;
}
/* harmony default export */ var polar = ({
  /**
   * Initialize polar
   * @private
   */
  initPolar() {
    const $$ = this;
    const { $el: { arcs }, config } = $$;
    const levelTextShow = config.polar_level_text_show;
    const levelTextBgColor = config.polar_level_text_backgroundColor;
    arcs.levels = arcs.append("g").attr("class", $LEVEL.levels);
    if (levelTextShow && levelTextBgColor) {
      $$.generateTextBGColorFilter(levelTextBgColor);
    }
  },
  /**
   * Get polar outer radius according to the data value
   * @param {object} d Data object
   * @param {numbet} outerRadius Outer radius
   * @returns {number} outer radius
   * @private
   */
  getPolarOuterRadius(d, outerRadius) {
    var _a;
    const dataMax = getDataMax(this);
    return ((_a = d == null ? void 0 : d.data.values[0].value) != null ? _a : 0) / dataMax * outerRadius;
  },
  /**
   * Update polar based on given data array
   * @param {object} targets Data object
   * @private
   */
  updateTargetsForPolar(targets) {
    this.updateTargetsForArc(targets);
  },
  /**
   * Called whenever redraw happens
   * @private
   */
  redrawPolar() {
    const $$ = this;
    const { config } = $$;
    config.polar_level_show && $$.updatePolarLevel();
  },
  /**
   * Update polar level circle
   * @private
   */
  updatePolarLevel() {
    const $$ = this;
    const { config, state, $el: { arcs: { levels } } } = $$;
    const depth = config.polar_level_depth;
    const dataMax = getDataMax($$);
    const levelData = getRange(0, depth);
    const outerRadius = state.radius;
    const levelRatio = levelData.map((l) => outerRadius * ((l + 1) / depth));
    const levelTextFormat = (config.polar_level_text_format || function() {
    }).bind($$.api);
    const level = levels.selectAll(`.${$LEVEL.level}`).data(levelData);
    level.exit().remove();
    const levelEnter = level.enter().append("g").attr("class", (d, i) => `${$LEVEL.level} ${$LEVEL.level}-${i}`);
    levelEnter.append("circle");
    levelEnter.merge(level).selectAll("circle").style("visibility", config.polar_level_show ? null : "hidden").attr("cx", 0).attr("cy", 0).attr("r", (d) => levelRatio[d]);
    if (config.polar_level_text_show) {
      const levelTextBackgroundColor = config.polar_level_text_backgroundColor;
      const defsId = `#${state.datetimeId}-labels-bg${$$.getTargetSelectorSuffix(levelTextBackgroundColor)}`;
      levelEnter.append("text").style("text-anchor", "middle");
      levelEnter.merge(level).selectAll("text").attr("dy", (d) => -levelRatio[d] + 5).attr("filter", levelTextBackgroundColor ? `url(${defsId})` : null).text((d) => levelTextFormat(dataMax / levelData.length * (d + 1)));
    }
  }
});

;// ./src/config/Options/shape/polar.ts
/* harmony default export */ var shape_polar = ({
  /**
   * Set polar options
   * @name polar
   * @memberof Options
   * @type {object}
   * @property {object} polar Polar object
   * @property {boolean} [polar.label.show=true] Show or hide label on each polar piece.
   * @property {function} [polar.label.format] Set formatter for the label on each polar piece.
   * @property {number} [polar.label.threshold=0.05] Set threshold ratio to show/hide labels.
   * @property {number|function} [polar.label.ratio=undefined] Set ratio of labels position.
   * @property {boolean|object} [polar.label.line=false] Enable label with lines (displayed outside with connector lines).
   *  - `true`: Enable label with lines with default settings
   *  - `false`: Labels are displayed inside the polar slices (default behavior).
   *  - `{show: boolean, distance: number, text: boolean}`: Enable label with lines with custom settings. When object member is not provided, it will be set to default values.
   * @property {boolean} [polar.label.line.show=true] Show or hide connector lines.
   * @property {number} [polar.label.line.distance=20] Set the distance of the horizontal part of the connector line in pixels.
   * @property {boolean|function} [polar.label.line.text=true] Show text at the end of the connector line (outside the shape).
   *  - `true`: show data "id" text
   *  - `false`: use default formatter(label.format) to show text
   *  - `function(value, ratio, id)`: Custom formatter function for the text.
   *  - **NOTE:** When the viewport size decreases, the size is adjusted based on the shape, so text may appear clipped. In this case, consider setting `overflow: visible` on the SVG node.
   * @property {object|function} [polar.label.image] Set image to be displayed next to the label text.<br><br>
   * When function is specified, will receives 3 arguments such as `v, id, i` and it must return an image object with `url`, `width`, `height`, and optional `pos` properties.<br><br>
   * The arguments are:<br>
   *  - `v` is the value of the data point where the label is shown.
   *  - `id` is the id of the data where the label is shown.
   *  - `i` is the index of the data series point where the label is shown.
   * @property {string} polar.label.image.url Image URL path. Can use placeholder `{=ID}` which will be replaced with the data ID.
   * @property {number} polar.label.image.width Image width in pixels.
   * @property {number} polar.label.image.height Image height in pixels.
   * @property {object} [polar.label.image.pos] Image position relative to the label text.
   * @property {number} [polar.label.image.pos.x=0] x coordinate position, relative the original.
   * @property {number} [polar.label.image.pos.y=0] y coordinate position, relative the original.
   * @property {number} [polar.level.depth=3] Set the level depth.
   * @property {boolean} [polar.level.show=true] Show or hide level.
   * @property {string} [polar.level.text.backgroundColor="#fff"] Set label text's background color.
   * @property {function} [polar.level.text.format] Set format function for the level value.<br>- Default value: `(x) => x % 1 === 0 ? x : x.toFixed(2)`
   * @property {boolean} [polar.level.text.show=true] Show or hide level text.
   * @property {number} [polar.padAngle=0] Set padding between data.
   * @property {number} [polar.padding=0] Sets the gap between pie arcs.
   * @property {number} [polar.startingAngle=0] Set starting angle where data draws.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.PolarChart)
   * @see [Demo: label image](https://naver.github.io/billboard.js/demo/#PolarChartOptions.LabelImage)
   * @see [Demo: label line](https://naver.github.io/billboard.js/demo/#PolarChartOptions.LabelLine)
   * @example
   *  polar: {
   *      label: {
   *          show: false,
   *          format: function(value, ratio, id) {
   *              return d3.format("$")(value);
   *
   *              // to multiline, return with '\n' character
   *              // return value +"%\nLine1\n2Line2";
   *          },
   *
   *          // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
   *          // if data value is below than 0.1, text label will be hidden.
   *          threshold: 0.1,
   *
   *          // set ratio callback. Should return ratio value
   *          ratio: function(d, radius, h) {
   *              ...
   *              return ratio;
   *          },
   *          // or set ratio number
   *          ratio: 0.5,
   *
   *          // Enable label with lines (displayed outside with connector lines)
   *          line: false,  // default - labels inside
   *          line: true,   // enable label with lines with default settings
   *          line: {       // enable label with lines with custom settings
   *             show: true,
   *             distance: 20,  // horizontal line distance in pixels
   *
   *             // show text at the end of connector line (outside the shape)
   *             text: true,  // use default formatter
   *             text: function(value, ratio, id) {  // custom formatter
   *                 return d3.format(".1%")(ratio);
   *             }
   *          },
   *
   *          // set image to be displayed next to the label text
   *          image: {
   *             url: "./sample.svg",
   *
   *             // use placeholder to dynamically set image URL based on data ID
   *             url: "./images/{=ID}.svg",  // will be replaced to "./images/data1.svg", "./images/data2.svg", etc.
   *             width: 35,
   *             height: 35,
   *             pos: {
   *                x: 0,
   *                y: 0
   *             }
   *          },
   *
   *          // or use function to return image configuration dynamically
   *          image: function(v, id, i) {
   *             // Return different images based on value
   *             if (v > 500) {
   *                return {
   *                   url: "./high-value.svg",
   *                   width: 40,
   *                   height: 40,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if (v > 100) {
   *                return {
   *                   url: "./medium-value.svg",
   *                   width: 30,
   *                   height: 30,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             } else if(v < 5) {
   *                // Return falsy value in case of don't want to show image
   *                return null;
   *             } else {
   *                return {
   *                   url: "./low-value.svg",
   *                   width: 20,
   *                   height: 20,
   *                   pos: { x: 0, y: 0 }
   *                };
   *             }
   *          }
   *      },
   *      level: {
   *          depth: 3,
   *          max: 500,
   *          show: true,
   *          text: {
   *              format: function(x) {
   *                  return x + "%";
   *              },
   *              show: true,
   *              backgroundColor: "red"
   *          }
   *      },
   *      padAngle: 0.1,
   *      padding: 0,
   *      startingAngle: 1
   *  }
   */
  polar_label_show: true,
  polar_label_format: void 0,
  polar_label_threshold: 0.05,
  polar_label_line: false,
  polar_label_image: void 0,
  polar_label_ratio: void 0,
  polar_level_depth: 3,
  polar_level_max: void 0,
  polar_level_show: true,
  polar_level_text_backgroundColor: "#fff",
  polar_level_text_format: (x) => x % 1 === 0 ? x : x.toFixed(2),
  polar_level_text_show: true,
  polar_padAngle: 0,
  polar_padding: 0,
  polar_startingAngle: 0
});

;// ./src/config/resolver/shape/polar.ts





let polar_polar = () => (extendArc([polar], [arc, shape_polar]), (polar_polar = () => TYPE.POLAR)());

;// ./src/ChartInternal/shape/radar.ts




function _getPosition(isClockwise, type, edge, pos, range, ratio) {
  const index = isClockwise && pos > 0 ? edge - pos : pos;
  const r = 2 * Math.PI;
  const func = type === "x" ? Math.sin : Math.cos;
  return range * (1 - ratio * func(index * r / edge));
}
const cacheKeyPoints = KEY.radarPoints;
const cacheKeyTextWidth = KEY.radarTextWidth;
/* harmony default export */ var radar = ({
  initRadar() {
    const $$ = this;
    const { config, state: { current }, $el } = $$;
    if ($$.hasType("radar")) {
      $el.radar = $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $RADAR.chartRadars);
      $el.radar.levels = $el.radar.append("g").attr("class", $LEVEL.levels);
      $el.radar.axes = $el.radar.append("g").attr("class", $AXIS.axis);
      $el.radar.shapes = $el.radar.append("g").attr("class", $SHAPE.shapes);
      current.dataMax = config.radar_axis_max || $$.getMinMaxData().max[0].value;
      if (config.radar_axis_text_show) {
        config.interaction_enabled && $$.bindRadarEvent();
        $$.updateRadarLevel();
        $$.updateRadarAxes();
      }
    }
  },
  getRadarSize() {
    const $$ = this;
    const { config, state: { arcWidth, arcHeight } } = $$;
    const padding = config.axis_x_categories.length < 4 ? -20 : 10;
    const size = (Math.min(arcWidth, arcHeight) - padding) / 2;
    return [size, size];
  },
  updateTargetsForRadar(targets) {
    const $$ = this;
    const { config } = $$;
    if (isEmpty(config.axis_x_categories)) {
      config.axis_x_categories = getRange(0, getMinMax("max", targets.map(
        (v) => v.values.length
      )));
    }
    $$.generateRadarPoints();
  },
  getRadarPosition(type, index, range, ratio) {
    const $$ = this;
    const { config } = $$;
    const [width, height] = $$.getRadarSize();
    const edge = config.axis_x_categories.length;
    const isClockwise = config.radar_direction_clockwise;
    const pos = toArray(type).map(
      (v) => _getPosition(
        isClockwise,
        v,
        edge,
        index,
        isDefined(range) ? range : type === "x" ? width : height,
        isNumber(ratio) ? ratio : config.radar_size_ratio
      )
    );
    return pos.length === 1 ? pos[0] : pos;
  },
  /**
   * Generate data points
   * @private
   */
  generateRadarPoints() {
    const $$ = this;
    const targets = $$.data.targets;
    const [width, height] = $$.getRadarSize();
    const points = $$.cache.get(cacheKeyPoints) || {};
    const size = points._size;
    if (!size || size.width !== width && size.height !== height) {
      targets.forEach((d) => {
        points[d.id] = d.values.map((v, i) => $$.getRadarPosition(["x", "y"], i, void 0, $$.getRatio("radar", v)));
      });
      points._size = { width, height };
      $$.cache.add(cacheKeyPoints, points);
    }
  },
  redrawRadar() {
    const $$ = this;
    const { radar, main } = $$.$el;
    const translate = $$.getTranslate("radar");
    if (translate) {
      radar.attr("transform", translate);
      main.select(`.${$TEXT.chartTexts}`).attr("transform", translate);
      $$.generateRadarPoints();
      $$.updateRadarLevel();
      $$.updateRadarAxes();
      $$.updateRadarShape();
    }
  },
  generateGetRadarPoints() {
    const points = this.cache.get(cacheKeyPoints);
    return (d, i) => {
      const point = points[d.id][i];
      return [
        point,
        point,
        point,
        point
      ];
    };
  },
  updateRadarLevel() {
    const $$ = this;
    const { config, state, $el: { radar } } = $$;
    const [width, height] = $$.getRadarSize();
    const depth = config.radar_level_depth;
    const edge = config.axis_x_categories.length;
    const showText = config.radar_level_text_show;
    const radarLevels = radar.levels;
    const levelData = getRange(0, depth);
    const radius = config.radar_size_ratio * Math.min(width, height);
    const levelRatio = levelData.map((l) => radius * ((l + 1) / depth));
    const levelTextFormat = (config.radar_level_text_format || function() {
    }).bind($$.api);
    const points = levelData.map((v) => {
      const range = levelRatio[v];
      const pos = getRange(0, edge).map(
        (i) => $$.getRadarPosition(["x", "y"], i, range, 1).join(",")
      );
      return pos.join(" ");
    });
    const level = radarLevels.selectAll(`.${$LEVEL.level}`).data(levelData);
    level.exit().remove();
    const levelEnter = level.enter().append("g").attr("class", (d, i) => `${$LEVEL.level} ${$LEVEL.level}-${i}`);
    levelEnter.append("polygon").style("visibility", config.radar_level_show ? null : "hidden");
    if (showText) {
      if (radarLevels.select("text").empty()) {
        radarLevels.append("text").attr("dx", "-.5em").attr("dy", "-.7em").style("text-anchor", "end").text(() => levelTextFormat(0));
      }
      levelEnter.append("text").attr("dx", "-.5em").style("text-anchor", "end").text(
        (d) => levelTextFormat(
          state.current.dataMax / levelData.length * (d + 1)
        )
      );
    }
    levelEnter.merge(level).attr(
      "transform",
      (d) => `translate(${width - levelRatio[d]}, ${height - levelRatio[d]})`
    ).selectAll("polygon").attr("points", (d) => points[d]);
    if (showText) {
      radarLevels.selectAll("text").attr("x", (d) => isUndefined(d) ? width : points[d].split(",")[0]).attr("y", (d) => isUndefined(d) ? height : 0);
    }
  },
  updateRadarAxes() {
    const $$ = this;
    const { config, $el: { radar } } = $$;
    const [width, height] = $$.getRadarSize();
    const categories = config.axis_x_categories;
    let axis = radar.axes.selectAll("g").data(categories);
    axis.exit().remove();
    const axisEnter = axis.enter().append("g").attr("class", (d, i) => `${$AXIS.axis}-${i}`);
    config.radar_axis_line_show && axisEnter.append("line");
    config.radar_axis_text_show && axisEnter.append("text");
    axis = axisEnter.merge(axis);
    if (config.radar_axis_line_show) {
      axis.select("line").attr("x1", width).attr("y1", height).attr("x2", (d, i) => $$.getRadarPosition("x", i)).attr("y2", (d, i) => $$.getRadarPosition("y", i));
    }
    if (config.radar_axis_text_show) {
      const { x = 0, y = 0 } = config.radar_axis_text_position;
      const textWidth = $$.cache.get(cacheKeyTextWidth) || 0;
      axis.select("text").style("text-anchor", "middle").attr("dy", ".5em").call((selection) => {
        selection.each(function(d) {
          setTextValue((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this), String(d), [-0.6, 1.2]);
        });
      }).datum((d, i) => ({ index: i })).attr("transform", function(d) {
        if (isUndefined(this.width)) {
          this.width = getBoundingRect(this, true).width / 2;
        }
        let posX = $$.getRadarPosition("x", d.index, void 0, 1);
        let posY = Math.round($$.getRadarPosition("y", d.index, void 0, 1));
        if (posX > width) {
          posX += this.width + x;
        } else if (Math.round(posX) < width) {
          posX -= this.width + x;
        }
        if (posY > height) {
          if (posY / 2 === height && this.firstChild.tagName === "tspan") {
            this.firstChild.setAttribute("dy", "0em");
          }
          posY += y;
        } else if (posY < height) {
          posY -= y;
        }
        return `translate(${posX} ${posY})`;
      });
      if (!textWidth) {
        const widths = [radar.axes, radar.levels].map((v) => getPathBox(v.node()).width);
        if (widths.every((v) => v > 0)) {
          $$.cache.add(cacheKeyTextWidth, widths[0] - widths[1]);
        }
      }
    }
  },
  bindRadarEvent() {
    const $$ = this;
    const { config, state, $el: { radar, svg } } = $$;
    const focusOnly = $$.isPointFocusOnly();
    const { inputType, transiting } = state;
    const isMouse = inputType === "mouse";
    const hide = (event) => {
      state.event = event;
      if (!config.interaction_onout) {
        return;
      }
      const index = $$.getDataIndexFromEvent(event);
      const noIndex = isUndefined(index);
      if (isMouse || noIndex) {
        $$.hideTooltip();
        focusOnly ? $$.hideCircleFocus() : $$.unexpandCircles();
        if (isMouse) {
          $$.setOverOut(false, index);
        } else if (noIndex) {
          $$.callOverOutForTouch();
        }
      }
    };
    radar.axes.on(isMouse ? "mouseover " : "touchstart", (event) => {
      if (transiting) {
        return;
      }
      state.event = event;
      const index = $$.getDataIndexFromEvent(event);
      $$.selectRectForSingle(svg.node(), index);
      isMouse ? $$.setOverOut(true, index) : $$.callOverOutForTouch(index);
    }, isMouse ? void 0 : { passive: true }).on("mouseout", isMouse ? hide : null);
    if (!isMouse) {
      svg.on("touchstart", hide, { passive: true });
    }
  },
  updateRadarShape() {
    const $$ = this;
    const targets = $$.data.targets.filter((d) => $$.isRadarType(d));
    const points = $$.cache.get(cacheKeyPoints);
    const areas = $$.$el.radar.shapes.selectAll("polygon").data($$.filterNullish(targets));
    const areasEnter = areas.enter().append("g").attr("class", $$.getChartClass("Radar"));
    $$.$T(areas.exit()).remove();
    areasEnter.append("polygon").merge(areas).style("fill", $$.color).style("stroke", $$.color).attr("points", (d) => points[d.id].join(" "));
    $$.updateTargetForCircle(targets, areasEnter);
  },
  /**
   * Get data point x coordinate
   * @param {object} d Data object
   * @returns {number}
   * @private
   */
  radarCircleX(d) {
    return this.cache.get(cacheKeyPoints)[d.id][d.index][0];
  },
  /**
   * Get data point y coordinate
   * @param {object} d Data object
   * @returns {number}
   * @private
   */
  radarCircleY(d) {
    return this.cache.get(cacheKeyPoints)[d.id][d.index][1];
  }
});

;// ./src/config/Options/shape/radar.ts
/* harmony default export */ var shape_radar = ({
  /**
   * Set radar options
   * - **NOTE:**
   *  > When x tick text contains `\n`, it's used as line break.
   * @name radar
   * @memberof Options
   * @type {object}
   * @property {object} radar Radar object
   * @property {number} [radar.axis.max=undefined] The max value of axis. If not given, it'll take the max value from the given data.
   * @property {boolean} [radar.axis.line.show=true] Show or hide axis line.
   * @property {number} [radar.axis.text.position.x=0] x coordinate position, relative the original.
   * @property {number} [radar.axis.text.position.y=0] y coordinate position, relative the original.
   * @property {boolean} [radar.axis.text.show=true] Show or hide axis text.
   * @property {boolean} [radar.direction.clockwise=false] Set the direction to be drawn.
   * @property {number} [radar.level.depth=3] Set the level depth.
   * @property {boolean} [radar.level.show=true] Show or hide level.
   * @property {function} [radar.level.text.format] Set format function for the level value.<br>- Default value: `(x) => x % 1 === 0 ? x : x.toFixed(2)`
   * @property {boolean} [radar.level.text.show=true] Show or hide level text.
   * @property {number} [radar.size.ratio=0.87] Set size ratio.
   * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.RadarChart)
   * @see [Demo: radar axis](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarAxis)
   * @see [Demo: radar level](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarLevel)
   * @see [Demo: radar size](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarSize)
   * @see [Demo: radar axis multiline](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarAxisMultiline)
   * @example
   *  radar: {
   *      axis: {
   *          max: 50,
   *          line: {
   *              show: false
   *          },
   *          text: {
   *              position: {
   *              	x: 0,
   *              	y: 0
   *              },
   *              show: false
   *          }
   *      },
   *      direction: {
   *          clockwise: true
   *      },
   *      level: {
   *          show: false,
   *          text: {
   *              format: function(x) {
   *                  return x + "%";
   *              },
   *              show: true
   *          }
   *      },
   *      size: {
   *          ratio: 0.7
   *      }
   *  }
   */
  radar_axis_max: void 0,
  radar_axis_line_show: true,
  radar_axis_text_show: true,
  radar_axis_text_position: {},
  radar_level_depth: 3,
  radar_level_show: true,
  radar_level_text_format: (x) => x % 1 === 0 ? x : x.toFixed(2),
  radar_level_text_show: true,
  radar_size_ratio: 0.87,
  radar_direction_clockwise: false
});

;// ./src/config/resolver/shape/radar.ts







let radar_radar = () => (extendArc(
  [internal.eventrect, shape_point, radar],
  [common_point, shape_radar, { axis_x_categories: options.optAxis.axis_x_categories }]
), (radar_radar = () => TYPE.RADAR)());

;// ./src/config/Options/shape/scatter.ts
/* harmony default export */ var scatter = ({
  /**
   * Set scatter options
   * @name scatter
   * @memberof Options
   * @type {object}
   * @property {object} [scatter] scatter object
   * @property {boolean} [scatter.zerobased=false] Set if min or max value will be 0 on scatter chart.
   * @example
   *  scatter: {
   *      connectNull: true,
   *      step: {
   *          type: "step-after"
   *      },
   *
   *      // hide all data points ('point.show=false' also has similar effect)
   *      point: false,
   *
   *      // show data points for only indicated data
   *      point: [
   *          "data1", "data3"
   *      ],
   *
   *      zerobased: false
   *  }
   */
  scatter_zerobased: false
});

;// ./src/config/resolver/shape/scatter.ts






let scatter_scatter = () => (extendAxis(
  [point, shape_point],
  [common_point, scatter]
), (scatter_scatter = () => TYPE.SCATTER)());

// EXTERNAL MODULE: external {"commonjs":"d3-hierarchy","commonjs2":"d3-hierarchy","amd":"d3-hierarchy","root":"d3"}
var external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_ = __webpack_require__(11);
;// ./src/ChartInternal/shape/core/treemap.ts

function convertDataToTreemapData(data) {
  const $$ = this;
  return data.map((d) => {
    const { id, values } = d;
    const { value } = values[0];
    return {
      name: id,
      id,
      // needed to keep compatibility on whole code logic
      value,
      ratio: $$.getRatio("treemap", values[0])
    };
  });
}
/* harmony default export */ var treemap = ({
  /**
   * Initialize treemap layout generator.
   * @private
   */
  initTreemapLayout() {
    this.treemap = (0,external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemap)().tile(this.getTreemapTile());
  },
  /**
   * Get tiling function
   * @returns {function}
   * @private
   */
  getTreemapTile() {
    var _a, _b;
    const $$ = this;
    const { config, state: { current: { width, height } } } = $$;
    const tile = (_b = {
      binary: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapBinary,
      dice: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapDice,
      slice: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapSlice,
      sliceDice: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapSliceDice,
      squarify: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapSquarify,
      resquarify: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapResquarify
    }[(_a = config.treemap_tile) != null ? _a : "binary"]) != null ? _b : external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapBinary;
    return (node, x0, y0, x1, y1) => {
      tile(node, 0, 0, width, height);
      for (const child of node.children) {
        child.x0 = x0 + child.x0 / width * (x1 - x0);
        child.x1 = x0 + child.x1 / width * (x1 - x0);
        child.y0 = y0 + child.y0 / height * (y1 - y0);
        child.y1 = y0 + child.y1 / height * (y1 - y0);
      }
    };
  },
  /**
   * Get treemap hierarchy data
   * @param {Array} targets Data targets
   * @returns {object}
   * @private
   */
  getTreemapData(targets) {
    const $$ = this;
    return {
      name: "root",
      children: convertDataToTreemapData.bind($$)(
        $$.filterTargetsToShow(targets.filter($$.isTreemapType, $$))
      )
    };
  },
  /**
   * Get treemap hierarchy root.
   * @param {Array} targets Data targets
   * @returns {object}
   * @private
   */
  getTreemapRoot(targets) {
    const $$ = this;
    const data = $$.getTreemapData(targets != null ? targets : $$.data.targets);
    const hierarchyData = (0,external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.hierarchy)(data).sum((d) => d.value);
    const sortFn = $$.getSortCompareFn(true);
    if (!$$.treemap) {
      $$.initTreemapLayout();
    }
    return $$.treemap(
      sortFn ? hierarchyData.sort(sortFn) : hierarchyData
    );
  }
});

;// ./src/ChartInternal/shape/treemap.ts
var treemap_defProp = Object.defineProperty;
var treemap_defProps = Object.defineProperties;
var treemap_getOwnPropDescs = Object.getOwnPropertyDescriptors;
var treemap_getOwnPropSymbols = Object.getOwnPropertySymbols;
var treemap_hasOwnProp = Object.prototype.hasOwnProperty;
var treemap_propIsEnum = Object.prototype.propertyIsEnumerable;
var treemap_defNormalProp = (obj, key, value) => key in obj ? treemap_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var treemap_spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (treemap_hasOwnProp.call(b, prop))
      treemap_defNormalProp(a, prop, b[prop]);
  if (treemap_getOwnPropSymbols)
    for (var prop of treemap_getOwnPropSymbols(b)) {
      if (treemap_propIsEnum.call(b, prop))
        treemap_defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var treemap_spreadProps = (a, b) => treemap_defProps(a, treemap_getOwnPropDescs(b));






function position(group, root) {
  const $$ = this;
  group.selectAll("g").attr("transform", (d) => {
    const rect = getTreemapNodeRect($$, d, root);
    return `translate(${rect.x},${rect.y})`;
  }).select("rect").attr("width", (d) => getTreemapNodeRect($$, d, root).w).attr("height", (d) => getTreemapNodeRect($$, d, root).h);
}
/* harmony default export */ var shape_treemap = (treemap_spreadProps(treemap_spreadValues({}, treemap), {
  initTreemap() {
    const $$ = this;
    const {
      $el,
      state: {
        current: { width, height },
        clip,
        datetimeId
      }
    } = $$;
    clip.id = `${datetimeId}-clip`;
    $$.initTreemapLayout();
    $el.defs.append("clipPath").attr("id", clip.id).append("rect").attr("width", width).attr("height", height);
    $el.treemap = $el.main.select(`.${$COMMON.chart}`).attr("clip-path", `url(#${clip.id})`).append("g").classed($TREEMAP.chartTreemaps, true);
    $$.bindTreemapEvent();
  },
  /**
   * Bind events
   * @private
   */
  bindTreemapEvent() {
    const $$ = this;
    const { $el, config, state } = $$;
    const getTarget = (event) => {
      var _a;
      const target = event.isTrusted ? event.target : (_a = state.eventReceiver.rect) == null ? void 0 : _a.node();
      let data;
      if (target && /^rect$/i.test(target.tagName)) {
        state.event = event;
        data = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
      }
      return data == null ? void 0 : data.data;
    };
    if (config.interaction_enabled) {
      const isTouch = state.inputType === "touch";
      $el.treemap.on(isTouch ? "touchstart" : "mouseover mousemove", (event) => {
        const data = getTarget(event);
        if (data) {
          $$.showTooltip([data], event.currentTarget);
          /^(touchstart|mouseover)$/.test(event.type) && $$.setOverOut(true, data);
        }
      }, isTouch ? { passive: true } : void 0).on(isTouch ? "touchend" : "mouseout", (event) => {
        const data = getTarget(event);
        if (config.interaction_onout) {
          $$.hideTooltip();
          $$.setOverOut(false, data);
        }
      });
    }
  },
  /**
   * Update treemap data
   * @param {Array} targets Data targets
   * @private
   */
  updateTargetsForTreemap(targets) {
    const $$ = this;
    const { $el: { treemap } } = $$;
    const treemapData = [$$.getTreemapRoot(targets != null ? targets : $$.data.targets)];
    treemap.data($$.filterNullish(treemapData));
  },
  /**
   * Render treemap
   * @param {number} durationForExit Duration for exit transition
   * @private
   */
  updateTreemap(durationForExit) {
    const $$ = this;
    const { $el, $T } = $$;
    const data = $el.treemap.datum();
    const classChartTreemap = $$.getChartClass("Treemap");
    const classTreemap = $$.getClass("treemap", true);
    const treemap = $el.treemap.selectAll("g").data(data.children);
    $T(treemap.exit(), durationForExit).style("opacity", "0").remove();
    treemap.enter().append("g").append("rect");
    $el.treemap.selectAll("g").attr("class", classChartTreemap).select("rect").attr("class", classTreemap).attr("fill", (d) => $$.color(d.data.name));
  },
  /**
   * Generate treemap coordinate points data
   * @returns {Array} Array of coordinate points
   * @private
   */
  generateGetTreemapPoints() {
    const $$ = this;
    const { $el } = $$;
    const points = {};
    $el.treemap.selectAll("g").each((d) => {
      const rect = getTreemapNodeRect($$, d);
      points[d.data.name] = [
        [rect.x, rect.y],
        [rect.x + rect.w, rect.y + rect.h]
      ];
    });
    return (d) => points[d.id];
  },
  /**
   * Redraw treemap
   * @param {boolean} withTransition With or without transition
   * @returns {Array} Selections
   * @private
   */
  redrawTreemap(withTransition) {
    const $$ = this;
    const { $el, state: { current: { width, height } } } = $$;
    $el.defs.select("rect").attr("width", width).attr("height", height);
    return [
      $$.$T($el.treemap, withTransition, getRandom()).call(position.bind($$), $el.treemap.datum())
    ];
  },
  /**
   * Get treemap data label format function
   * @param {object} d Data object
   * @returns {function} Label formatter function
   * @private
   */
  treemapDataLabelFormat(d) {
    const $$ = this;
    const { $el: { treemap }, config, scale: { x, y } } = $$;
    const { id, value } = d;
    const format = config.treemap_label_format;
    const ratio = $$.getRatio("treemap", d);
    const percentValue = (ratio * 100).toFixed(2);
    const meetLabelThreshold = config.treemap_label_show && meetsLabelThreshold.call($$, ratio, "treemap") ? null : "0";
    const treemapNode = treemap.selectAll("g").filter((node) => node.data.id === id).datum();
    let width = 0;
    let height = 0;
    if (treemapNode) {
      const { x0, x1, y0, y1 } = treemapNode;
      width = x(x1) - x(x0);
      height = y(y1) - y(y0);
    }
    return function(node) {
      node.style("opacity", meetLabelThreshold);
      return isFunction(format) ? format.bind($$.api)(value, ratio, id, { width, height }) : `${id}
${percentValue}%`;
    };
  }
}));

;// ./src/config/Options/shape/treemap.ts
/* harmony default export */ var Options_shape_treemap = ({
  /**
   * Set treemap options
   * @name treemap
   * @memberof Options
   * @type {object}
   * @property {object} treemap Treemap object
   * @property {string} [treemap.tile="binary"] Treemap tile type
   * - **Available tile type values:**
   * 	- binary ([d3.treemapBinary](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapBinary))
   * 	- dice ([d3.treemapDice](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapDice))
   * 	- slice ([d3.treemapSlice](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapSlice))
   * 	- sliceDice ([d3.treemapSliceDice](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapSliceDice))
   * 	- squarify ([d3.treemapSquarify](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapSquarify))
   * 	- resquarify ([d3.treemapResquarify](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapResquarify))
   * @property {function} [treemap.label.format] Set formatter for the label text.<br>
   * - **Arguments:**
   *   - `value {number}`: Data value
   *   - `ratio {number}`: The `ratio` of how much space this tile occupies relative to the total area (0~1)
   *   - `id {string}`: Data id
   *   - `size {object}`: Tile size `{width, height}` in pixels
   * @property {number} [treemap.label.threshold=0.05] Set threshold ratio to show/hide labels text.
   * @property {number} [treemap.label.show=true] Show or hide label text.
   * @see [Demo: treemap](https://naver.github.io/billboard.js/demo/#Chart.TreemapChart)
   * @example
   *  treemap: {
   *      // "binary", "dice", "slice", "sliceDice", "squarify", "resquarify"
   *      tile: "dice",
   *
   *      label: {
   *          // show or hide label text
   *          show: false,
   *
   *          // Example 1: Format with currency
   *          format: function(value, ratio, id, size) {
   *              // size: {width, height} - tile size in pixels
   *              return d3.format("$")(value);
   *          },
   *
   *          // Example 2: Show different content based on tile size
   *          format: function(value, ratio, id, size) {
   *              if (size.width > 100 && size.height > 50) {
   *                  return `${id}\n${d3.format("$")(value)}\n(${(ratio * 100).toFixed(1)}%)`;
   *              } else if (size.width > 50) {
   *                  return `${id}\n${d3.format("$")(value)}`;
   *              } else {
   *                  return d3.format("$")(value);
   *              }
   *          },
   *
   *          // Example 3: Include tile dimensions in label
   *          format: function(value, ratio, id, size) {
   *              return `${id}\n${value}\n${size.width.toFixed(0)}x${size.height.toFixed(0)}px`;
   *          },
   *
   *          // Example 4: Conditional formatting based on ratio
   *          format: function(value, ratio, id, size) {
   *              return ratio > 0.1 ?
   *                  `${id}\n${value} (${(ratio * 100).toFixed(1)}%)` :
   *                  value;
   *          },
   *
   *          // set ratio number
   *          ratio: 0.05
   *      }
   *  }
   */
  treemap_tile: "binary",
  treemap_label_format: void 0,
  treemap_label_threshold: 0.05,
  treemap_label_show: true
});

;// ./src/config/resolver/shape/treemap.ts




let treemap_treemap = () => (extendAxis([shape_treemap], [Options_shape_treemap]), (treemap_treemap = () => TYPE.TREEMAP)());

;// ./src/config/resolver/shape/index.ts














;// ./src/core.ts


let defaults = /* @__PURE__ */ Object.create(null);
const bb = {
  /**
   * Version information
   * @property {string} version version
   * @example
   *    bb.version;  // "1.0.0"
   * @memberof bb
   */
  version: "4.1.1",
  /**
   * Generate chart
   * - **NOTE:** Bear in mind for the possibility of ***throwing an error***, during the generation when:
   *   - Unused option value is given.
   *     - ex) For `data.type="pie"` option, setting 'axis' option can cause unexpected generation error.
   *   - Insufficient value is given for certain option used.
   *     - ex) `data: { x: "x", columns: [["x"], ["data1", 30, 200, 100]] }`
   * @param {Options} config chart options
   * @memberof bb
   * @returns {Chart}
   * @see {@link Options} for different generation options
   * @see {@link Chart} for different methods API
   * @example
   *  <!-- chart holder -->
   * <div id="LineChart"></div>
   * @example
   *  // Generate chart with options
   *  var chart = bb.generate({
   *      "bindto": "#LineChart"
   *      "data": {
   *          "columns": [
   *              ["data1", 30, 200, 100, 400, 150, 250],
   *              ["data2", 50, 20, 10, 40, 15, 25]
   *           ],
   *          "type": "line"
   *      }
   *  });
   *
   *  // call some API
   *  // ex) get the data of 'data1'
   *  chart.data("data1");
   * @example
   * // Generate chart by importing ESM.
   * // Import only the shape and API resolvers you use for a smaller bundle.
   * import bb, {
   *   bar,
   *   category,
   *   exportApi,
   *   flow,
   *   grid,
   *   line,
   *   regions,
   *   step
   * } from "billboard.js";
   *
   * const chart = bb.generate({
   *   ...category(),
   *   ...exportApi(),
   *   ...flow(),
   *   ...grid(),
   *   ...regions(),
   *   bindto: "#LineChart",
   *   data: {
   *     columns: [
   *       ["data1", 30, 200, 100, 400, 150, 250],
   *       ["data2", 50, 20, 10, 40, 15, 25]
   *     ],
   *     type: line(),
   *
   *     // or specify per-series types
   *     types: {
   *       data1: bar(),
   *       data2: step()
   *     }
   *   },
   *   axis: {
   *     x: {
   *       type: "category",
   *       categories: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
   *     }
   *   },
   *   grid: {
   *     x: {show: true}
   *   },
   *   regions: [
   *     {axis: "x", start: "Feb", end: "Apr"}
   *   ]
   * });
   *
   * chart.export();
   * @example
   * // Generate a canvas-rendered chart by importing the canvas ESM entry.
   * import bb, {
   *   bar,
   *   canvas,
   *   category,
   *   exportApi,
   *   flow,
   *   grid,
   *   regions,
   *   subchart
   * } from "billboard.js/canvas";
   *
   * const chart = bb.generate({
   *   render: {
   *     mode: canvas()
   *   },
   *   ...category(),
   *   ...exportApi(),
   *   ...flow(),
   *   ...grid(),
   *   ...regions(),
   *   bindto: "#LineChart",
   *   data: {
   *     columns: [
   *       ["data1", 30, 200, 100, 400]
   *     ],
   *     type: bar()
   *   },
   *   axis: {
   *     x: {
   *       type: "category",
   *       categories: ["Jan", "Feb", "Mar", "Apr"]
   *     }
   *   },
   *   grid: {
   *     x: {show: true, lines: [{value: "Feb", text: "Milestone"}]},
   *     y: {show: true}
   *   },
   *   regions: [
   *     {axis: "x", start: "Feb", end: "Mar", label: {text: "Campaign"}}
   *   ],
   *   subchart: {
   *     show: subchart()
   *   }
   * });
   *
   * chart.xgrids([{value: "Mar", text: "API grid"}]);
   * chart.regions([{axis: "x", start: "Jan", end: "Feb"}]);
   * chart.flow({columns: [["data1", 120]]});
   * chart.export();
   *
   * // Arc-family chart types (`pie`, `donut`, `gauge`, `polar`, `radar`)
   * // stay SVG-only because canvas mode doesn't provide meaningful benefit.
   */
  generate(config) {
    const options = mergeObj(/* @__PURE__ */ Object.create(null), defaults, config);
    const inst = new Chart(options);
    inst.internal.charts = this.instance;
    this.instance.push(inst);
    return inst;
  },
  /**
   * Set or get global default options.
   * - **NOTE:**
   *   - The options values settings are valid within page context only.
   *   - If is called multiple times, will override the last value.
   * @param {Options} options chart options
   * @memberof bb
   * @returns {Options}
   * @see {@link Options}
   * @example
   * // Set same option value as for `.generate()`
   * bb.defaults({
   *   data: {
   *     type: "bar"
   *   }
   * });
   *
   * bb.defaults();  // {data:{type: "bar"}}
   *
   * // data.type defaults to 'bar'
   * var chart = bb.generate({ ... });
   */
  defaults(options) {
    if (isObject(options)) {
      defaults = options;
    }
    return defaults;
  },
  /**
   * An array containing instance created
   * @property {Array} instance instance array
   * @example
   *  // generate charts
   *  var chart1 = bb.generate(...);
   *  var chart2 = bb.generate(...);
   *
   *  bb.instance;  // [ chart1, chart2, ... ]
   * @memberof bb
   */
  instance: [],
  /**
   * Namespace for plugins
   * @property {object} plugin plugin namespace
   * @example
   *  // Stanford diagram plugin
   *  bb.plugin.stanford;
   * @memberof bb
   */
  plugin: {}
};


;// ./src/index.ts








Object.keys(shape_namespaceObject).forEach((v) => shape_namespaceObject[v]());
Object.keys(interaction_namespaceObject).forEach((v) => interaction_namespaceObject[v]());
exportApi();
flow_flow();
grid_grid();
regions_regions();
category_category();
canvas();


}();
/******/ 	return __webpack_exports__;
/******/ })()
;
});