billboard.js
Version:
Re-usable easy interface JavaScript chart library, based on D3 v4+
1,572 lines (1,525 loc) • 1.24 MB
JavaScript
/*!
* 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.0.1
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("d3-axis"), 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-axis", "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-axis"), 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"], root["d3"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(this, function(__WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__12__, __WEBPACK_EXTERNAL_MODULE__11__, __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
/******/ "use strict";
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */,
/* 2 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__2__;
/***/ }),
/* 3 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__3__;
/***/ }),
/* 4 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__4__;
/***/ }),
/* 5 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__5__;
/***/ }),
/* 6 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__6__;
/***/ }),
/* 7 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__7__;
/***/ }),
/* 8 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__8__;
/***/ }),
/* 9 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__9__;
/***/ }),
/* 10 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__10__;
/***/ }),
/* 11 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__11__;
/***/ }),
/* 12 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__12__;
/***/ })
/******/ ]);
/************************************************************************/
/******/ // 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 */
/******/ !function() {
/******/ // define getter 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 */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // 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 isolated against other entry modules.
!function() {
// extracted by mini-css-extract-plugin
}();
// This entry needs to be wrapped in an IIFE because it needs to be isolated against other entry modules.
!function() {
// 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: ./src/config/resolver/interaction/index.ts
var resolver_interaction_namespaceObject = {};
__webpack_require__.r(resolver_interaction_namespaceObject);
__webpack_require__.d(resolver_interaction_namespaceObject, {
selection: function() { return selectionModule; },
subchart: function() { return subchartModule; },
zoom: function() { return zoomModule; }
});
// NAMESPACE OBJECT: ./src/config/resolver/shape/index.ts
var resolver_shape_namespaceObject = {};
__webpack_require__.r(resolver_shape_namespaceObject);
__webpack_require__.d(resolver_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 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) {
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(/:/gi, ":").replace(/&newline;/gi, "\n").replace(/&tab;/gi, " ").replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/&/gi, "&").replace(/"/gi, '"').replace(/'/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 = {
'"': """,
"'": "'",
"`": "`"
};
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) + ">";
}
if (isAllowedTag(match)) {
return sanitizeTag(match);
}
return match.replace(/</g, "<");
}
);
}
;// ./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;
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, 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);
if (config.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);
}
} 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 {
(_f = $$.updateArc) == null ? void 0 : _f.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 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 ? cullDat