UNPKG

764 kBJavaScriptView Raw
1/*!
2 * Copyright (c) 2017 ~ present NAVER Corp.
3 * billboard.js project is licensed under the MIT license
4 *
5 * billboard.js, JavaScript chart library
6 * https://naver.github.io/billboard.js/
7 *
8 * @version 3.14.2
9 */
10(function webpackUniversalModuleDefinition(root, factory) {
11 if(typeof exports === 'object' && typeof module === 'object')
12 module.exports = factory(require("d3-axis"), require("d3-brush"), require("d3-drag"), require("d3-dsv"), require("d3-ease"), 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"));
13 else if(typeof define === 'function' && define.amd)
14 define(["d3-axis", "d3-brush", "d3-drag", "d3-dsv", "d3-ease", "d3-hierarchy", "d3-interpolate", "d3-scale", "d3-selection", "d3-shape", "d3-time-format", "d3-transition", "d3-zoom"], factory);
15 else {
16 var a = typeof exports === 'object' ? factory(require("d3-axis"), require("d3-brush"), require("d3-drag"), require("d3-dsv"), require("d3-ease"), 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"], root["d3"], root["d3"]);
17 for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
18 }
19})(this, function(__WEBPACK_EXTERNAL_MODULE__11__, __WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__5__, __WEBPACK_EXTERNAL_MODULE__12__, __WEBPACK_EXTERNAL_MODULE__14__, __WEBPACK_EXTERNAL_MODULE__13__, __WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__9__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__8__, __WEBPACK_EXTERNAL_MODULE__10__) {
20return /******/ (function() { // webpackBootstrap
21/******/ "use strict";
22/******/ var __webpack_modules__ = ([
23/* 0 */,
24/* 1 */,
25/* 2 */
26/***/ (function(module) {
27
28module.exports = __WEBPACK_EXTERNAL_MODULE__2__;
29
30/***/ }),
31/* 3 */
32/***/ (function(module) {
33
34module.exports = __WEBPACK_EXTERNAL_MODULE__3__;
35
36/***/ }),
37/* 4 */
38/***/ (function(module) {
39
40module.exports = __WEBPACK_EXTERNAL_MODULE__4__;
41
42/***/ }),
43/* 5 */
44/***/ (function(module) {
45
46module.exports = __WEBPACK_EXTERNAL_MODULE__5__;
47
48/***/ }),
49/* 6 */
50/***/ (function(module) {
51
52module.exports = __WEBPACK_EXTERNAL_MODULE__6__;
53
54/***/ }),
55/* 7 */
56/***/ (function(module) {
57
58module.exports = __WEBPACK_EXTERNAL_MODULE__7__;
59
60/***/ }),
61/* 8 */
62/***/ (function(module) {
63
64module.exports = __WEBPACK_EXTERNAL_MODULE__8__;
65
66/***/ }),
67/* 9 */
68/***/ (function(module) {
69
70module.exports = __WEBPACK_EXTERNAL_MODULE__9__;
71
72/***/ }),
73/* 10 */
74/***/ (function(module) {
75
76module.exports = __WEBPACK_EXTERNAL_MODULE__10__;
77
78/***/ }),
79/* 11 */
80/***/ (function(module) {
81
82module.exports = __WEBPACK_EXTERNAL_MODULE__11__;
83
84/***/ }),
85/* 12 */
86/***/ (function(module) {
87
88module.exports = __WEBPACK_EXTERNAL_MODULE__12__;
89
90/***/ }),
91/* 13 */
92/***/ (function(module) {
93
94module.exports = __WEBPACK_EXTERNAL_MODULE__13__;
95
96/***/ }),
97/* 14 */
98/***/ (function(module) {
99
100module.exports = __WEBPACK_EXTERNAL_MODULE__14__;
101
102/***/ })
103/******/ ]);
104/************************************************************************/
105/******/ // The module cache
106/******/ var __webpack_module_cache__ = {};
107/******/
108/******/ // The require function
109/******/ function __webpack_require__(moduleId) {
110/******/ // Check if module is in cache
111/******/ var cachedModule = __webpack_module_cache__[moduleId];
112/******/ if (cachedModule !== undefined) {
113/******/ return cachedModule.exports;
114/******/ }
115/******/ // Create a new module (and put it into the cache)
116/******/ var module = __webpack_module_cache__[moduleId] = {
117/******/ // no module.id needed
118/******/ // no module.loaded needed
119/******/ exports: {}
120/******/ };
121/******/
122/******/ // Execute the module function
123/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
124/******/
125/******/ // Return the exports of the module
126/******/ return module.exports;
127/******/ }
128/******/
129/************************************************************************/
130/******/ /* webpack/runtime/define property getters */
131/******/ !function() {
132/******/ // define getter functions for harmony exports
133/******/ __webpack_require__.d = function(exports, definition) {
134/******/ for(var key in definition) {
135/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
136/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
137/******/ }
138/******/ }
139/******/ };
140/******/ }();
141/******/
142/******/ /* webpack/runtime/hasOwnProperty shorthand */
143/******/ !function() {
144/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
145/******/ }();
146/******/
147/******/ /* webpack/runtime/make namespace object */
148/******/ !function() {
149/******/ // define __esModule on exports
150/******/ __webpack_require__.r = function(exports) {
151/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
152/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
153/******/ }
154/******/ Object.defineProperty(exports, '__esModule', { value: true });
155/******/ };
156/******/ }();
157/******/
158/************************************************************************/
159var __webpack_exports__ = {};
160// This entry needs to be wrapped in an IIFE because it needs to be isolated against other entry modules.
161!function() {
162// extracted by mini-css-extract-plugin
163
164}();
165// This entry needs to be wrapped in an IIFE because it needs to be isolated against other entry modules.
166!function() {
167// ESM COMPAT FLAG
168__webpack_require__.r(__webpack_exports__);
169
170// EXPORTS
171__webpack_require__.d(__webpack_exports__, {
172 bb: function() { return /* reexport */ bb; },
173 "default": function() { return /* reexport */ bb; }
174});
175
176// NAMESPACE OBJECT: ./src/config/resolver/interaction.ts
177var resolver_interaction_namespaceObject = {};
178__webpack_require__.r(resolver_interaction_namespaceObject);
179__webpack_require__.d(resolver_interaction_namespaceObject, {
180 selection: function() { return selectionModule; },
181 subchart: function() { return subchartModule; },
182 zoom: function() { return zoomModule; }
183});
184
185// NAMESPACE OBJECT: ./src/config/resolver/shape.ts
186var resolver_shape_namespaceObject = {};
187__webpack_require__.r(resolver_shape_namespaceObject);
188__webpack_require__.d(resolver_shape_namespaceObject, {
189 area: function() { return resolver_shape_area; },
190 areaLineRange: function() { return areaLineRange; },
191 areaSpline: function() { return areaSpline; },
192 areaSplineRange: function() { return areaSplineRange; },
193 areaStep: function() { return areaStep; },
194 areaStepRange: function() { return areaStepRange; },
195 bar: function() { return resolver_shape_bar; },
196 bubble: function() { return resolver_shape_bubble; },
197 candlestick: function() { return resolver_shape_candlestick; },
198 donut: function() { return shape_donut; },
199 funnel: function() { return resolver_shape_funnel; },
200 gauge: function() { return resolver_shape_gauge; },
201 line: function() { return resolver_shape_line; },
202 pie: function() { return shape_pie; },
203 polar: function() { return resolver_shape_polar; },
204 radar: function() { return resolver_shape_radar; },
205 scatter: function() { return shape_scatter; },
206 spline: function() { return shape_spline; },
207 step: function() { return step; },
208 treemap: function() { return resolver_shape_treemap; }
209});
210
211// EXTERNAL MODULE: external {"commonjs":"d3-selection","commonjs2":"d3-selection","amd":"d3-selection","root":"d3"}
212var external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_ = __webpack_require__(2);
213// EXTERNAL MODULE: external {"commonjs":"d3-time-format","commonjs2":"d3-time-format","amd":"d3-time-format","root":"d3"}
214var external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_ = __webpack_require__(3);
215;// ./src/config/classes.ts
216var __defProp = Object.defineProperty;
217var __getOwnPropSymbols = Object.getOwnPropertySymbols;
218var __hasOwnProp = Object.prototype.hasOwnProperty;
219var __propIsEnum = Object.prototype.propertyIsEnumerable;
220var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
221var __spreadValues = (a, b) => {
222 for (var prop in b || (b = {}))
223 if (__hasOwnProp.call(b, prop))
224 __defNormalProp(a, prop, b[prop]);
225 if (__getOwnPropSymbols)
226 for (var prop of __getOwnPropSymbols(b)) {
227 if (__propIsEnum.call(b, prop))
228 __defNormalProp(a, prop, b[prop]);
229 }
230 return a;
231};
232const $COMMON = {
233 button: "bb-button",
234 chart: "bb-chart",
235 empty: "bb-empty",
236 main: "bb-main",
237 target: "bb-target",
238 EXPANDED: "_expanded_"
239};
240const $ARC = {
241 arc: "bb-arc",
242 arcLabelLine: "bb-arc-label-line",
243 arcRange: "bb-arc-range",
244 arcs: "bb-arcs",
245 chartArc: "bb-chart-arc",
246 chartArcs: "bb-chart-arcs",
247 chartArcsBackground: "bb-chart-arcs-background",
248 chartArcsTitle: "bb-chart-arcs-title",
249 needle: "bb-needle"
250};
251const $AREA = {
252 area: "bb-area",
253 areas: "bb-areas"
254};
255const $AXIS = {
256 axis: "bb-axis",
257 axisX: "bb-axis-x",
258 axisXLabel: "bb-axis-x-label",
259 axisY: "bb-axis-y",
260 axisY2: "bb-axis-y2",
261 axisY2Label: "bb-axis-y2-label",
262 axisYLabel: "bb-axis-y-label",
263 axisXTooltip: "bb-axis-x-tooltip",
264 axisYTooltip: "bb-axis-y-tooltip",
265 axisY2Tooltip: "bb-axis-y2-tooltip"
266};
267const $BAR = {
268 bar: "bb-bar",
269 bars: "bb-bars",
270 chartBar: "bb-chart-bar",
271 chartBars: "bb-chart-bars"
272};
273const $CANDLESTICK = {
274 candlestick: "bb-candlestick",
275 candlesticks: "bb-candlesticks",
276 chartCandlestick: "bb-chart-candlestick",
277 chartCandlesticks: "bb-chart-candlesticks",
278 valueDown: "bb-value-down",
279 valueUp: "bb-value-up"
280};
281const $CIRCLE = {
282 chartCircles: "bb-chart-circles",
283 circle: "bb-circle",
284 circles: "bb-circles"
285};
286const $COLOR = {
287 colorPattern: "bb-color-pattern",
288 colorScale: "bb-colorscale"
289};
290const $DRAG = {
291 dragarea: "bb-dragarea",
292 INCLUDED: "_included_"
293};
294const $FUNNEL = {
295 funnel: "bb-funnel",
296 chartFunnel: "bb-chart-funnel",
297 chartFunnels: "bb-chart-funnels",
298 funnelBackground: "bb-funnel-background"
299};
300const $GAUGE = {
301 chartArcsGaugeMax: "bb-chart-arcs-gauge-max",
302 chartArcsGaugeMin: "bb-chart-arcs-gauge-min",
303 chartArcsGaugeUnit: "bb-chart-arcs-gauge-unit",
304 chartArcsGaugeTitle: "bb-chart-arcs-gauge-title",
305 gaugeValue: "bb-gauge-value"
306};
307const $LEGEND = {
308 legend: "bb-legend",
309 legendBackground: "bb-legend-background",
310 legendItem: "bb-legend-item",
311 legendItemEvent: "bb-legend-item-event",
312 legendItemHidden: "bb-legend-item-hidden",
313 legendItemPoint: "bb-legend-item-point",
314 legendItemTile: "bb-legend-item-tile"
315};
316const $LINE = {
317 chartLine: "bb-chart-line",
318 chartLines: "bb-chart-lines",
319 line: "bb-line",
320 lines: "bb-lines"
321};
322const $EVENT = {
323 eventRect: "bb-event-rect",
324 eventRects: "bb-event-rects",
325 eventRectsMultiple: "bb-event-rects-multiple",
326 eventRectsSingle: "bb-event-rects-single"
327};
328const $FOCUS = {
329 focused: "bb-focused",
330 defocused: "bb-defocused",
331 legendItemFocused: "bb-legend-item-focused",
332 xgridFocus: "bb-xgrid-focus",
333 ygridFocus: "bb-ygrid-focus"
334};
335const $GRID = {
336 grid: "bb-grid",
337 gridLines: "bb-grid-lines",
338 xgrid: "bb-xgrid",
339 xgridLine: "bb-xgrid-line",
340 xgridLines: "bb-xgrid-lines",
341 xgrids: "bb-xgrids",
342 ygrid: "bb-ygrid",
343 ygridLine: "bb-ygrid-line",
344 ygridLines: "bb-ygrid-lines",
345 ygrids: "bb-ygrids"
346};
347const $LEVEL = {
348 level: "bb-level",
349 levels: "bb-levels"
350};
351const $RADAR = {
352 chartRadar: "bb-chart-radar",
353 chartRadars: "bb-chart-radars"
354};
355const $REGION = {
356 region: "bb-region",
357 regions: "bb-regions"
358};
359const $SELECT = {
360 selectedCircle: "bb-selected-circle",
361 selectedCircles: "bb-selected-circles",
362 SELECTED: "_selected_"
363};
364const $SHAPE = {
365 shape: "bb-shape",
366 shapes: "bb-shapes"
367};
368const $SUBCHART = {
369 brush: "bb-brush",
370 subchart: "bb-subchart"
371};
372const $TEXT = {
373 chartText: "bb-chart-text",
374 chartTexts: "bb-chart-texts",
375 text: "bb-text",
376 texts: "bb-texts",
377 title: "bb-title",
378 TextOverlapping: "text-overlapping"
379};
380const $TOOLTIP = {
381 tooltip: "bb-tooltip",
382 tooltipContainer: "bb-tooltip-container",
383 tooltipName: "bb-tooltip-name"
384};
385const $TREEMAP = {
386 treemap: "bb-treemap",
387 chartTreemap: "bb-chart-treemap",
388 chartTreemaps: "bb-chart-treemaps"
389};
390const $ZOOM = {
391 buttonZoomReset: "bb-zoom-reset",
392 zoomBrush: "bb-zoom-brush"
393};
394/* harmony default export */ var classes = (__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, $COMMON), $ARC), $AREA), $AXIS), $BAR), $CANDLESTICK), $CIRCLE), $COLOR), $DRAG), $GAUGE), $LEGEND), $LINE), $EVENT), $FOCUS), $FUNNEL), $GRID), $RADAR), $REGION), $SELECT), $SHAPE), $SUBCHART), $TEXT), $TOOLTIP), $TREEMAP), $ZOOM));
395
396;// ./src/config/Options/common/boost.ts
397/* harmony default export */ var boost = ({
398 /**
399 * Set boost options
400 * @name boost
401 * @memberof Options
402 * @type {object}
403 * @property {object} boost boost object
404 * @property {boolean} [boost.useCssRule=false] Avoid setting inline styles for each shape elements.
405 * - **NOTE:**
406 * - Will append <style> to the head tag and will add shpes' CSS rules dynamically.
407 * - For now, covers colors related properties (fill, stroke, etc.) only.
408 * @property {boolean} [boost.useWorker=false] Use Web Worker as possible for processing.
409 * - **NOTE:**
410 * - For now, only applies for data conversion at the initial time.
411 * - As of Web Worker's async nature, handling chart instance synchrously is not recommended.
412 * @example
413 * boost: {
414 * useCssRule: true,
415 * useWorker: false
416 * }
417 */
418 boost_useCssRule: false,
419 boost_useWorker: false
420});
421
422;// ./src/config/Options/common/color.ts
423/* harmony default export */ var color = ({
424 /**
425 * Set color of the data values
426 * @name color
427 * @memberof Options
428 * @type {object}
429 * @property {object} color color object
430 * @property {string|object|Function} [color.onover] Set the color value for each data point when mouse/touch onover event occurs.
431 * @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.
432 * @property {Function} [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).
433 * - **NOTE:** The pattern element's id will be defined as `bb-colorize-pattern-$COLOR-VALUE`.<br>
434 * ex. When color pattern value is `['red', '#fff']` and defined 2 patterns,then ids for pattern elements are:<br>
435 * - `bb-colorize-pattern-red`
436 * - `bb-colorize-pattern-fff`
437 * @property {object} [color.threshold] color threshold for gauge and tooltip color
438 * @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.
439 * @property {Array} [color.threshold.values] Threshold values for each steps
440 * @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`.
441 * @example
442 * color: {
443 * pattern: ["#1f77b4", "#aec7e8", ...],
444 *
445 * // Set colors' patterns
446 * // it should return an array of SVGPatternElement
447 * tiles: function() {
448 * var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern");
449 * var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
450 * var circle1 = document.createElementNS("http://www.w3.org/2000/svg", "circle");
451 *
452 * pattern.setAttribute("patternUnits", "userSpaceOnUse");
453 * pattern.setAttribute("width", "32");
454 * pattern.setAttribute("height", "32");
455 *
456 * g.style.fill = "#000";
457 * g.style.opacity = "0.2";
458 *
459 * circle1.setAttribute("cx", "3");
460 * circle1.setAttribute("cy", "3");
461 * circle1.setAttribute("r", "3");
462 *
463 * g.appendChild(circle1);
464 * pattern.appendChild(g);
465 *
466 * return [pattern];
467 * },
468 *
469 * // for threshold usage, pattern values should be set for each steps
470 * pattern: ["grey", "green", "yellow", "orange", "red"],
471 * threshold: {
472 * unit: "value",
473 *
474 * // when value is 20 => 'green', value is 40 => 'orange' will be set.
475 * values: [10, 20, 30, 40, 50],
476 *
477 * // the equation for max:
478 * // - unit == 'value': max => 30
479 * // - unit != 'value': max => value*100/30
480 * max: 30
481 * },
482 *
483 * // set all data to 'red'
484 * onover: "red",
485 *
486 * // set different color for data
487 * onover: {
488 * data1: "red",
489 * data2: "yellow"
490 * },
491 *
492 * // will pass data object to the callback
493 * onover: function(d) {
494 * return d.id === "data1" ? "red" : "green";
495 * }
496 * }
497 */
498 color_pattern: [],
499 color_tiles: void 0,
500 color_threshold: {},
501 color_onover: void 0
502});
503
504;// ./src/config/Options/common/legend.ts
505/* harmony default export */ var legend = ({
506 /**
507 * Legend options
508 * @name legend
509 * @memberof Options
510 * @type {object}
511 * @property {object} legend Legend object
512 * @property {boolean} [legend.show=true] Show or hide legend.
513 * @property {boolean} [legend.hide=false] Hide legend
514 * If true given, all legend will be hidden. If string or array given, only the legend that has the id will be hidden.
515 * @property {string|HTMLElement} [legend.contents.bindto=undefined] Set CSS selector or element reference to bind legend items.
516 * - **NOTE:** Should be used along with `legend.contents.template`.
517 * @property {string|Function} [legend.contents.template="<span style='color:#fff;padding:5px;background-color:{=COLOR}'>{=TITLE}</span>"] Set item's template.<br>
518 * - If set `string` value, within template the 'color' and 'title' can be replaced using template-like syntax string:
519 * - {=COLOR}: data color value
520 * - {=TITLE}: data title value
521 * - If set `function` value, will pass following arguments to the given function:
522 * - title {string}: data's id value
523 * - color {string}: color string
524 * - data {Array}: data array
525 * @property {string} [legend.position=bottom] Change the position of legend.<br>
526 * Available values are: `bottom`, `right` and `inset` are supported.
527 * @property {object} [legend.inset={anchor: 'top-left',x: 10,y: 0,step: undefined}] Change inset legend attributes.<br>
528 * This option accepts object that has the keys `anchor`, `x`, `y` and `step`.
529 * - **anchor** decides the position of the legend:
530 * - top-left
531 * - top-right
532 * - bottom-left
533 * - bottom-right
534 * - **x** and **y**:
535 * - set the position of the legend based on the anchor.
536 * - **step**:
537 * - defines the max step the legend has (e.g. If 2 set and legend has 3 legend item, the legend 2 columns).
538 * @property {boolean} [legend.equally=false] Set to all items have same width size.
539 * @property {number} [legend.padding=0] Set padding value
540 * @property {boolean} [legend.item.interaction=true] Set legend item interaction.
541 * - **NOTE:**
542 * - This setting will not have effect on `.toggle()` method.
543 * - `legend.item.onXXX` listener options will work if set, regardless of this option value.
544 * @property {boolean} [legend.item.interaction.dblclick=false] Set legend item to interact on double click.
545 * - **NOTE:**
546 * - Double clicking will make focused clicked dataseries only, hiding all others.
547 * - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
548 * - To return initial state(which all dataseries are showing), double click current focused legend item again.
549 * - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
550 * - In this case, default `click` interaction will be disabled.
551 * @property {Function} [legend.item.onclick=undefined] Set click event handler to the legend item.
552 * - **NOTE:**
553 * - When set, default `click` interaction will be disabled.
554 * - When `interaction.dblclick=true` is set, will be called on double click.
555 * @property {Function} [legend.item.onover=undefined] Set mouse/touch over event handler to the legend item.
556 * - **NOTE:** When set, default `mouseover` interaction will be disabled.
557 * @property {Function} [legend.item.onout=undefined] Set mouse/touch out event handler to the legend item.
558 * - **NOTE:** When set, default `mouseout` interaction will be disabled.
559 * @property {number} [legend.item.tile.width=10] Set width for 'rectangle' legend item tile element.
560 * @property {number} [legend.item.tile.height=10] Set height for 'rectangle' legend item tile element.
561 * @property {number} [legend.item.tile.r=5] Set the radius for 'circle' legend item tile type.
562 * @property {string} [legend.item.tile.type="rectangle"] Set legend item shape type.<br>
563 * - **Available Values:**
564 * - circle
565 * - rectangle
566 * @property {boolean} [legend.format] Set formatter function for legend text.
567 * The argument:<br>
568 * - `id`: Legend text value. When `data.names` is specified, will pass from it, otherwise will pass data id.
569 * - `dataId`: When `data.names` specified, will pass the original data id. Otherwise will be undefined.
570 * @property {boolean} [legend.tooltip=false] Show full legend text value using system tooltip(via `<title>` element).
571 * @property {boolean} [legend.usePoint=false] Whether to use custom points in legend.
572 * @see [Demo: format](https://naver.github.io/billboard.js/demo/#Legend.LegendFormat)
573 * @see [Demo: item.interaction](https://naver.github.io/billboard.js/demo/#Legend.LegendItemInteraction)
574 * @see [Demo: item.tile.type](https://naver.github.io/billboard.js/demo/#Legend.LegendItemTileType)
575 * @see [Demo: position](https://naver.github.io/billboard.js/demo/#Legend.LegendPosition)
576 * @see [Demo: contents.template](https://naver.github.io/billboard.js/demo/#Legend.LegendTemplate1)
577 * @see [Demo: usePoint](https://naver.github.io/billboard.js/demo/#Legend.usePoint)
578 * @example
579 * legend: {
580 * show: true,
581 * hide: true,
582 * //or hide: "data1"
583 * //or hide: ["data1", "data2"]
584 * contents: {
585 * bindto: "#legend", // <ul id='legend'></ul>
586 *
587 * // will be as: <li style='background-color:#1f77b4'>data1</li>
588 * template: "<li style='background-color:{=COLOR}'>{=TITLE}</li>"
589 *
590 * // or using function
591 * template: function(id, color, data) {
592 * // if you want omit some legend, return falsy value
593 * if (id !== "data1") {
594 * return "<li style='background-color:"+ color +">"+ id +"</li>";
595 * }
596 * }
597 * },
598 * position: "bottom", // bottom, right, inset
599 * inset: {
600 * anchor: "top-right" // top-left, top-right, bottom-left, bottom-right
601 * x: 20,
602 * y: 10,
603 * step: 2
604 * },
605 * equally: false,
606 * padding: 10,
607 * item: {
608 * // will disable default interaction
609 * interaction: false,
610 *
611 * // set legend interact on double click
612 * // by double clicking, will make focused clicked dataseries only, hiding all others.
613 * interaction: {
614 * dblclick: true
615 * }
616 *
617 * // when set below callback, will disable corresponding default interactions
618 * onclick: function(id, visible) {
619 * // toggle based on the data visibility
620 * this[visible ? "hide" : "show"](id);
621 * },
622 * onover: function(id, visible) { ... },
623 * onout: function(id, visible) { ... },
624 *
625 * // set tile's size
626 * tile: {
627 * // set tile type
628 * type: "circle" // or "rectangle" (default)
629 *
630 * // width & height, are only applicable for 'rectangle' legend type
631 * width: 15,
632 * height: 15
633 *
634 * // radis is only applicable for 'circle' legend type
635 * r: 10
636 * }
637 * },
638 * format: function(id, dataId) {
639 * // set ellipsis string when length is > 5
640 * // to get full legend value, combine with 'legend.tooltip=true'
641 * if (id.length > 5) {
642 * id = id.substr(0, 5) + "...";
643 * }
644 *
645 * return id;
646 * },
647 * tooltip: true,
648 * usePoint: true
649 * }
650 */
651 legend_contents_bindto: void 0,
652 legend_contents_template: "<span style='color:#fff;padding:5px;background-color:{=COLOR}'>{=TITLE}</span>",
653 legend_equally: false,
654 legend_hide: false,
655 legend_inset_anchor: "top-left",
656 legend_inset_x: 10,
657 legend_inset_y: 0,
658 legend_inset_step: void 0,
659 legend_item_interaction: true,
660 legend_item_dblclick: false,
661 legend_item_onclick: void 0,
662 legend_item_onover: void 0,
663 legend_item_onout: void 0,
664 legend_item_tile_width: 10,
665 legend_item_tile_height: 10,
666 legend_item_tile_r: 5,
667 legend_item_tile_type: "rectangle",
668 legend_format: void 0,
669 legend_padding: 0,
670 legend_position: "bottom",
671 legend_show: true,
672 legend_tooltip: false,
673 legend_usePoint: false
674});
675
676;// ./src/config/Options/common/main.ts
677/* harmony default export */ var main = ({
678 /**
679 * Specify the CSS selector or the element which the chart will be set to. D3 selection object can be specified also.<br>
680 * If other chart is set already, it will be replaced with the new one (only one chart can be set in one element).
681 * - **NOTE:** In case of element doesn't exist or not specified, will add a `<div>` element to the body.
682 * @name bindto
683 * @memberof Options
684 * @property {string|HTMLElement|d3.selection|object} [bindto="#chart"] Specify the element where chart will be drawn.
685 * @property {string|HTMLElement|d3.selection} bindto.element="#chart" Specify the element where chart will be drawn.
686 * @property {string} [bindto.classname=bb] Specify the class name of bind element.<br>
687 * **NOTE:** When class name isn't `bb`, then you also need to update the default CSS to be rendered correctly.
688 * @default #chart
689 * @example
690 * bindto: "#myContainer"
691 *
692 * // or HTMLElement
693 * bindto: document.getElementById("myContainer")
694 *
695 * // or D3 selection object
696 * bindto: d3.select("#myContainer")
697 *
698 * // or to change default classname
699 * bindto: {
700 * element: "#chart",
701 * classname: "bill-board" // ex) <div id='chart' class='bill-board'>
702 * }
703 */
704 bindto: "#chart",
705 /**
706 * Set chart background.
707 * @name background
708 * @memberof Options
709 * @property {object} background background object
710 * @property {string} background.class Specify the class name for background element.
711 * @property {string} background.color Specify the fill color for background element.<br>**NOTE:** Will be ignored if `imgUrl` option is set.
712 * @property {string} background.imgUrl Specify the image url string for background.
713 * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Background)
714 * @example
715 * background: {
716 * class: "myClass",
717 * color: "red",
718 *
719 * // Set image url for background.
720 * // If specified, 'color' option will be ignored.
721 * imgUrl: "https://naver.github.io/billboard.js/img/logo/billboard.js.svg",
722 * }
723 */
724 background: {},
725 /**
726 * Set 'clip-path' attribute for chart element
727 * - **NOTE:**
728 * > When is false, chart node element is positioned after the axis node in DOM tree hierarchy.
729 * > Is to make chart element positioned over axis element.
730 * @name clipPath
731 * @memberof Options
732 * @type {boolean}
733 * @default true
734 * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.clipPath)
735 * @example
736 * // don't set 'clip-path' attribute
737 * clipPath: false
738 */
739 clipPath: true,
740 /**
741 * Set svg element's class name
742 * @name svg
743 * @memberof Options
744 * @type {object}
745 * @property {object} [svg] svg object
746 * @property {string} [svg.classname] class name for svg element
747 * @example
748 * svg: {
749 * classname: "test_class"
750 * }
751 */
752 svg_classname: void 0,
753 /**
754 * The desired size of the chart element.
755 * If value is not specified, the width of the chart will be calculated by the size of the parent element it's appended to.
756 * @name size
757 * @memberof Options
758 * @type {object}
759 * @property {object} [size] size object
760 * @property {number} [size.width] width of the chart element
761 * @property {number} [size.height] height of the chart element
762 * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.ChartSize)
763 * @example
764 * size: {
765 * width: 640,
766 * height: 480
767 * }
768 */
769 size_width: void 0,
770 size_height: void 0,
771 /**
772 * The padding of the chart element.
773 * - **NOTE:** for more information, see the "[`Understanding padding`](https://github.com/naver/billboard.js/wiki/Understanding-padding)"" wiki documentaion.
774 * @name padding
775 * @memberof Options
776 * @type {object}
777 * @property {object|boolean} [padding=true] Set padding of chart, and accepts object or boolean type.
778 * - `Object`: Specify each side's padding.
779 * - `false`: Remove padding completely and make shape to fully occupy the container element.
780 * - In this case, axes and subchart will be hidden.
781 * - To adjust some padding from this state, use `axis.[x|y].padding` option.
782 * @property {string} [padding.mode] padding mode
783 * - `"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.
784 * @property {number} [padding.top] padding on the top of chart
785 * @property {number} [padding.right] padding on the right of chart
786 * @property {number} [padding.bottom] padding on the bottom of chart
787 * @property {number} [padding.left] padding on the left of chart
788 * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Padding)
789 * @see [Demo: Fit padding](https://naver.github.io/billboard.js/demo/#ChartOptions.FitPadding)
790 * @example
791 * // remove padding completely.
792 * padding: false,
793 *
794 * padding: {
795 * // specifying mode value, will reduce padding and make fit to the container element.
796 * mode: "fit"
797 *
798 * // when mode is "fit", all padding values will be relative from fitted value.
799 * // so, 0 will be initial fitted value.
800 * top: 20,
801 * right: 20,
802 * bottom: 20,
803 * left: 20
804 * }
805 *
806 * // or specify padding value for each side
807 * padding: {
808 * top: 20,
809 * right: 20,
810 * bottom: 20,
811 * left: 20
812 * }
813 */
814 padding: true,
815 padding_mode: void 0,
816 padding_left: void 0,
817 padding_right: void 0,
818 padding_top: void 0,
819 padding_bottom: void 0,
820 /**
821 * Set chart resize options
822 * @name resize
823 * @memberof Options
824 * @type {object}
825 * @property {object} [resize] resize object
826 * @property {boolean|string} [resize.auto=true] Set chart resize automatically on viewport changes.
827 * - **NOTE:** Available options
828 * - true: Enables automatic resize.
829 * - false: Disables automatic resize.
830 * - "viewBox": Enables automatic resize, and size will be fixed based on the viewbox.
831 * @property {boolean|number} [resize.timer=true] Set resize timer option.
832 * - **NOTE:** Available options
833 * - The resize function will be called using:
834 * - true: `setTimeout()`
835 * - false: `requestIdleCallback()`
836 * - Given number(delay in ms) value, resize function will be triggered using `setTimeout()` with given delay.
837 * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.resizeViewBox)
838 * @example
839 * resize: {
840 * auto: false,
841 *
842 * // set resize based on viewBox value
843 * auto: "viewBox",
844 *
845 * // set resize function will be triggered using `setTimeout()`
846 * timer: true,
847 *
848 * // set resize function will be triggered using `requestIdleCallback()`
849 * timer: false,
850 *
851 * // set resize function will be triggered using `setTimeout()` with a delay of `100ms`.
852 * timer: 100
853 * }
854 */
855 resize_auto: true,
856 resize_timer: true,
857 /**
858 * Set a callback to execute when the chart is clicked.
859 * @name onclick
860 * @memberof Options
861 * @type {Function}
862 * @default undefined
863 * @example
864 * onclick: function(event) {
865 * this; // chart instance itself
866 * event; // native event object
867 * ...
868 * }
869 */
870 onclick: void 0,
871 /**
872 * Set a callback to execute when mouse/touch enters the chart.
873 * @name onover
874 * @memberof Options
875 * @type {Function}
876 * @default undefined
877 * @example
878 * onover: function(event) {
879 * this; // chart instance itself
880 * event; // native event object
881 * ...
882 * }
883 */
884 onover: void 0,
885 /**
886 * Set a callback to execute when mouse/touch leaves the chart.
887 * @name onout
888 * @memberof Options
889 * @type {Function}
890 * @default undefined
891 * @example
892 * onout: function(event) {
893 * this; // chart instance itself
894 * event; // native event object
895 * ...
896 * }
897 */
898 onout: void 0,
899 /**
900 * Set a callback to execute when user resizes the screen.
901 * @name onresize
902 * @memberof Options
903 * @type {Function}
904 * @default undefined
905 * @example
906 * onresize: function() {
907 * this; // chart instance itself
908 * ...
909 * }
910 */
911 onresize: void 0,
912 /**
913 * Set a callback to execute when screen resize finished.
914 * @name onresized
915 * @memberof Options
916 * @type {Function}
917 * @default undefined
918 * @example
919 * onresized: function() {
920 * this; // chart instance itself
921 * ...
922 * }
923 */
924 onresized: void 0,
925 /**
926 * Set a callback to execute before the chart is initialized
927 * @name onbeforeinit
928 * @memberof Options
929 * @type {Function}
930 * @default undefined
931 * @example
932 * onbeforeinit: function() {
933 * this; // chart instance itself
934 * ...
935 * }
936 */
937 onbeforeinit: void 0,
938 /**
939 * Set a callback to execute when the chart is initialized.
940 * @name oninit
941 * @memberof Options
942 * @type {Function}
943 * @default undefined
944 * @example
945 * oninit: function() {
946 * this; // chart instance itself
947 * ...
948 * }
949 */
950 oninit: void 0,
951 /**
952 * Set a callback to execute after the chart is initialized
953 * @name onafterinit
954 * @memberof Options
955 * @type {Function}
956 * @default undefined
957 * @example
958 * onafterinit: function() {
959 * this; // chart instance itself
960 * ...
961 * }
962 */
963 onafterinit: void 0,
964 /**
965 * Set a callback which is executed when the chart is rendered. Basically, this callback will be called in each time when the chart is redrawed.
966 * @name onrendered
967 * @memberof Options
968 * @type {Function}
969 * @default undefined
970 * @example
971 * onrendered: function() {
972 * this; // chart instance itself
973 * ...
974 * }
975 */
976 onrendered: void 0,
977 /**
978 * Set duration of transition (in milliseconds) for chart animation.<br><br>
979 * - **NOTE:** If `0 `or `null` set, transition will be skipped. So, this makes initial rendering faster especially in case you have a lot of data.
980 * @name transition
981 * @memberof Options
982 * @type {object}
983 * @property {object} [transition] transition object
984 * @property {number} [transition.duration=350] duration in milliseconds
985 * @example
986 * transition: {
987 * duration: 500
988 * }
989 */
990 transition_duration: 250,
991 /**
992 * Set plugins
993 * @name plugins
994 * @memberof Options
995 * @type {Array}
996 * @example
997 * plugins: [
998 * new bb.plugin.stanford({ ... }),
999 * new PluginA(),
1000 * ...
1001 * ]
1002 */
1003 plugins: [],
1004 /**
1005 * Control the render timing
1006 * @name render
1007 * @memberof Options
1008 * @type {object}
1009 * @property {object} [render] render object
1010 * @property {boolean} [render.lazy=true] Make to not render at initialization.
1011 * - **NOTE**:
1012 * - Enabled by default when bind element's visibility is hidden.
1013 * - 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.
1014 * @property {boolean} [render.observe=true] Observe bind element's visibility(`display` or `visiblity` inline css property or class value) & render when is visible automatically (for IEs, only works IE11+). When set to **false**, call [`.flush()`](./Chart.html#flush) to render.
1015 * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.LazyRender)
1016 * @example
1017 * render: {
1018 * lazy: true,
1019 * observe: true
1020 * }
1021 *
1022 * @example
1023 * // <!-- render.lazy will detect visibility defined -->
1024 * // (a) <div id='chart' class='hide'></div>
1025 * // (b) <div id='chart' style='display:none'></div>
1026 *
1027 * // render.lazy enabled by default when element is hidden
1028 * var chart = bb.generate({ ... });
1029 *
1030 * // chart will be rendered automatically when element's visibility changes
1031 * // Note: works only for inlined css property or class attribute changes
1032 * document.getElementById('chart').classList.remove('hide') // (a)
1033 * document.getElementById('chart').style.display = 'block'; // (b)
1034 *
1035 * @example
1036 * // chart won't be rendered and not observing bind element's visiblity changes
1037 * var chart = bb.generate({
1038 * render: {
1039 * lazy: true,
1040 * observe: false
1041 * }
1042 * });
1043 *
1044 * // call at any point when you want to render
1045 * chart.flush();
1046 */
1047 render: {},
1048 /**
1049 * Show rectangles inside the chart.<br><br>
1050 * This option accepts array including object that has axis, start, end and class.
1051 * The keys start, end and class are optional.
1052 * axis must be x, y or y2. start and end should be the value where regions start and end.
1053 * If not specified, the edge values will be used.
1054 * If timeseries x axis, date string, Date object and unixtime integer can be used.
1055 * If class is set, the region element will have it as class.
1056 * @name regions
1057 * @memberof Options
1058 * @type {Array}
1059 * @default []
1060 * @see [Demo](https://naver.github.io/billboard.js/demo/#Region.RegionLabel)
1061 * @example
1062 * regions: [
1063 * {
1064 * axis: "x",
1065 * start: 1,
1066 * end: 4,
1067 * class: "region-1-4",
1068 * label: {
1069 * text: "Region Text",
1070 * x: 5, // position relative of the initial x coordinate
1071 * y: 5, // position relative of the initial y coordinate
1072 * color: "red", // color string
1073 * rotated: true // make text to show in vertical or horizontal
1074 * }
1075 * }
1076 * ]
1077 */
1078 regions: []
1079});
1080
1081;// ./src/config/Options/common/title.ts
1082/* harmony default export */ var title = ({
1083 /**
1084 * Set title options
1085 * @name title
1086 * @memberof Options
1087 * @type {object}
1088 * @property {object} title Title object
1089 * @property {string} [title.text] Title text. If contains `\n`, it's used as line break allowing multiline title.
1090 * @property {number} [title.padding.top=0] Top padding value.
1091 * @property {number} [title.padding.right=0] Right padding value.
1092 * @property {number} [title.padding.bottom=0] Bottom padding value.
1093 * @property {number} [title.padding.left=0] Left padding value.
1094 * @property {string} [title.position=center] Available values are: 'center', 'right' and 'left'.
1095 * @see [Demo](https://naver.github.io/billboard.js/demo/#Title.MultilinedTitle)
1096 * @example
1097 * title: {
1098 * text: "Title Text",
1099 *
1100 * // or Multiline title text
1101 * text: "Main title text\nSub title text",
1102 *
1103 * padding: {
1104 * top: 10,
1105 * right: 10,
1106 * bottom: 10,
1107 * left: 10
1108 * },
1109 * position: "center"
1110 * }
1111 */
1112 title_text: void 0,
1113 title_padding: {
1114 top: 0,
1115 right: 0,
1116 bottom: 0,
1117 left: 0
1118 },
1119 title_position: "center"
1120});
1121
1122;// ./src/config/Options/common/tooltip.ts
1123/* harmony default export */ var tooltip = ({
1124 /**
1125 * Tooltip options
1126 * @name tooltip
1127 * @memberof Options
1128 * @type {object}
1129 * @property {object} tooltip Tooltip object
1130 * @property {boolean} [tooltip.show=true] Show or hide tooltip.
1131 * @property {boolean} [tooltip.doNotHide=false] Make tooltip keep showing not hiding on interaction.
1132 * @property {boolean} [tooltip.grouped=true] Set if tooltip is grouped or not for the data points.
1133 * - **NOTE:** The overlapped data points will be displayed as grouped even if set false.
1134 * @property {boolean} [tooltip.linked=false] Set if tooltips on all visible charts with like x points are shown together when one is shown.
1135 * @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.
1136 * @property {Function} [tooltip.format.title] Set format for the title of tooltip.<br>
1137 * Specified function receives x of the data point to show.
1138 * @property {Function} [tooltip.format.name] Set format for the name of each data in tooltip.<br>
1139 * 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.
1140 * @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.
1141 * - Will pass following arguments to the given function:
1142 * - `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.
1143 * - `ratio {number}`: Ratio of the data point in the `pie/donut/gauge` and `area/bar` when contains grouped data. Otherwise is `undefined`.
1144 * - `id {string}`: id of the data point
1145 * - `index {number}`: Index of the data point
1146 * @property {Function} [tooltip.position] Set custom position function for the tooltip.<br>
1147 * This option can be used to modify the tooltip position by returning object that has top and left.
1148 * - Will pass following arguments to the given function:
1149 * - `data {Array}`: Current selected data array object.
1150 * - `width {number}`: Width of tooltip.
1151 * - `height {number}`: Height of tooltip.
1152 * - `element {SVGElement}`: Tooltip event bound element
1153 * - `pos {object}`: Current position of the tooltip.
1154 * @property {Function|object} [tooltip.contents] Set custom HTML for the tooltip.<br>
1155 * If tooltip.grouped is true, data includes multiple data points.<br><br>
1156 * Specified function receives `data` array and `defaultTitleFormat`, `defaultValueFormat` and `color` functions of the data point to show.
1157 * - **Note:**
1158 * - defaultTitleFormat:
1159 * - if `axis.x.tick.format` option will be used if set.
1160 * - otherwise, will return function based on tick format type(category, timeseries).
1161 * - defaultValueFormat:
1162 * - for Arc type (except gauge, radar), the function will return value from `(ratio * 100).toFixed(1)`.
1163 * - for Axis based types, will be used `axis.[y|y2].tick.format` option value if is set.
1164 * - otherwise, will parse value and return as number.
1165 * @property {string|HTMLElement} [tooltip.contents.bindto=undefined] Set CSS selector or element reference to bind tooltip.
1166 * - **NOTE:** When is specified, will not be updating tooltip's position.
1167 * @property {string} [tooltip.contents.template=undefined] Set tooltip's template.<br><br>
1168 * Within template, below syntax will be replaced using template-like syntax string:
1169 * - **{{ ... }}**: the doubly curly brackets indicate loop block for data rows.
1170 * - **{=CLASS_TOOLTIP}**: default tooltip class name `bb-tooltip`.
1171 * - **{=CLASS_TOOLTIP_NAME}**: default tooltip data class name (ex. `bb-tooltip-name-data1`)
1172 * - **{=TITLE}**: title value.
1173 * - **{=COLOR}**: data color.
1174 * - **{=NAME}**: data id value.
1175 * - **{=VALUE}**: data value.
1176 * @property {object} [tooltip.contents.text=undefined] Set additional text content within data loop, using template syntax.
1177 * - **NOTE:** It should contain `{ key: Array, ... }` value
1178 * - 'key' name is used as substitution within template as '{=KEY}'
1179 * - The value array length should match with the data length
1180 * @property {boolean} [tooltip.init.show=false] Show tooltip at the initialization.
1181 * @property {number} [tooltip.init.x=0] Set x Axis index(or index for Arc(donut, gauge, pie) types) to be shown at the initialization.
1182 * @property {object} [tooltip.init.position] Set the position of tooltip at the initialization.
1183 * @property {Function} [tooltip.onshow] Set a callback that will be invoked before the tooltip is shown.
1184 * @property {Function} [tooltip.onhide] Set a callback that will be invoked before the tooltip is hidden.
1185 * @property {Function} [tooltip.onshown] Set a callback that will be invoked after the tooltip is shown
1186 * @property {Function} [tooltip.onhidden] Set a callback that will be invoked after the tooltip is hidden.
1187 * @property {string|Function|null} [tooltip.order=null] Set tooltip data display order.<br><br>
1188 * **Available Values:**
1189 * - `desc`: In descending data value order
1190 * - `asc`: In ascending data value order
1191 * - `null`: It keeps the data display order<br>
1192 * **NOTE:** When `data.groups` is set, the order will follow as the stacked graph order.<br>
1193 * If want to order as data bound, set any value rather than asc, desc or null. (ex. empty string "")
1194 * - `function(data1, data2) { ... }`: [Array.sort compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters)
1195 * @see [Demo: Hide Tooltip](https://naver.github.io/billboard.js/demo/#Tooltip.HideTooltip)
1196 * @see [Demo: Tooltip Grouping](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipGrouping)
1197 * @see [Demo: Tooltip Format](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipFormat)
1198 * @see [Demo: Linked Tooltip](https://naver.github.io/billboard.js/demo/#Tooltip.LinkedTooltips)
1199 * @see [Demo: Tooltip Position](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipPosition)
1200 * @see [Demo: Tooltip Template](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipTemplate)
1201 * @example
1202 * tooltip: {
1203 * show: true,
1204 * doNotHide: true,
1205 * grouped: false,
1206 * format: {
1207 * title: function(x) { return "Data " + x; },
1208 * name: function(name, ratio, id, index) { return name; },
1209 *
1210 * // If data row contains multiple or ranged(ex. candlestick, area range, etc.) value,
1211 * // formatter will be called as value length times.
1212 * value: function(value, ratio, id, index) { return ratio; }
1213 * },
1214 * position: function(data, width, height, element, pos) {
1215 * // data: [{x, index, id, name, value}, ...]
1216 * // width: Tooltip width
1217 * // height: Tooltip height
1218 * // element: Tooltip event bound element
1219 * // pos: {
1220 * // x: Current mouse event x position,
1221 * // y: Current mouse event y position,
1222 * // xAxis: Current x Axis position (the value is given for axis based chart type only)
1223 * // yAxis: Current y Axis position value or function(the value is given for axis based chart type only)
1224 * // }
1225 *
1226 * // yAxis will work differently per data lenghts
1227 * // - a) Single data: `yAxis` will return `number` value
1228 * // - b) Multiple data: `yAxis` will return a function with property value
1229 *
1230 * // a) Single data:
1231 * // Get y coordinate
1232 * pos.yAxis; // y axis coordinate value of current data point
1233 *
1234 * // b) Multiple data:
1235 * // Get y coordinate of value 500, where 'data1' scales(y or y2).
1236 * // When 'data.axes' option is used, data can bound to different axes.
1237 * // - when "data.axes={data1: 'y'}", wil return y value from y axis scale.
1238 * // - when "data.axes={data1: 'y2'}", wil return y value from y2 axis scale.
1239 * pos.yAxis(500, "data1"); // will return y coordinate value of data1
1240 *
1241 * pos.yAxis(500); // get y coordinate with value of 500, using y axis scale
1242 * pos.yAxis(500, null, "y2"); // get y coordinate with value of 500, using y2 axis scale
1243 *
1244 * return {
1245 * top: 0,
1246 * left: 0
1247 * }
1248 * },
1249 *
1250 * contents: function(d, defaultTitleFormat, defaultValueFormat, color) {
1251 * return ... // formatted html as you want
1252 * },
1253 *
1254 * // specify tooltip contents using template
1255 * // - example of HTML returned:
1256 * // <ul class="bb-tooltip">
1257 * // <li class="bb-tooltip-name-data1"><span>250</span><br><span style="color:#00c73c">data1</span></li>
1258 * // <li class="bb-tooltip-name-data2"><span>50</span><br><span style="color:#fa7171">data2</span></li>
1259 * // </ul>
1260 * contents: {
1261 * bindto: "#tooltip",
1262 * template: '<ul class={=CLASS_TOOLTIP}>{{' +
1263 * '<li class="{=CLASS_TOOLTIP_NAME}"><span>{=VALUE}</span><br>' +
1264 * '<span style=color:{=COLOR}>{=NAME}</span></li>' +
1265 * '}}</ul>'
1266 * }
1267 *
1268 * // with additional text value
1269 * // - example of HTML returned:
1270 * // <ul class="bb-tooltip">
1271 * // <li class="bb-tooltip-name-data1"><span>250</span><br>comment1<span style="color:#00c73c">data1</span>text1</li>
1272 * // <li class="bb-tooltip-name-data2"><span>50</span><br>comment2<span style="color:#fa7171">data2</span>text2</li>
1273 * // </ul>
1274 * contents: {
1275 * bindto: "#tooltip",
1276 * text: {
1277 * // a) 'key' name is used as substitution within template as '{=KEY}'
1278 * // b) the length should match with the data length
1279 * VAR1: ["text1", "text2"],
1280 * VAR2: ["comment1", "comment2"],
1281 * },
1282 * template: '<ul class={=CLASS_TOOLTIP}>{{' +
1283 * '<li class="{=CLASS_TOOLTIP_NAME}"><span>{=VALUE}</span>{=VAR2}<br>' +
1284 * '<span style=color:{=COLOR}>{=NAME}</span>{=VAR1}</li>' +
1285 * '}}</ul>'
1286 * }
1287 *
1288 * // sort tooltip data value display in ascending order
1289 * order: "asc",
1290 *
1291 * // specifying sort function
1292 * order: function(a, b) {
1293 * // param data passed format
1294 * {x: 5, value: 250, id: "data1", index: 5, name: "data1"}
1295 * ...
1296 * },
1297 *
1298 * // show at the initialization
1299 * init: {
1300 * show: true,
1301 * x: 2, // x Axis index (or index for Arc(donut, gauge, pie) types)
1302 * position: {
1303 * top: "150px", // specify as number or as string with 'px' unit string
1304 * left: 250 // specify as number or as string with 'px' unit string
1305 * }
1306 * },
1307 *
1308 * // fires prior tooltip is shown
1309 * onshow: function(selectedData) {
1310 * // current dataset selected
1311 * // ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
1312 * selectedData;
1313 * },
1314 *
1315 * // fires prior tooltip is hidden
1316 * onhide: function(selectedData) {
1317 * // current dataset selected
1318 * // ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
1319 * selectedData;
1320 * },
1321 *
1322 * // fires after tooltip is shown
1323 * onshown: function(selectedData) {
1324 * // current dataset selected
1325 * // ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
1326 * selectedData;
1327 * },
1328 *
1329 * // fires after tooltip is hidden
1330 * onhidden: function(selectedData) {
1331 * // current dataset selected
1332 * // ==> [{x: 4, value: 150, id: "data2", index: 4, name: "data2"}, ...]
1333 * selectedData;
1334 * },
1335 *
1336 * // Link any tooltips when multiple charts are on the screen where same x coordinates are available
1337 * // Useful for timeseries correlation
1338 * linked: true,
1339 *
1340 * // Specify name to interact those with the same name only.
1341 * linked: {
1342 * name: "some-group"
1343 * }
1344 * }
1345 */
1346 tooltip_show: true,
1347 tooltip_doNotHide: false,
1348 tooltip_grouped: true,
1349 tooltip_format_title: void 0,
1350 tooltip_format_name: void 0,
1351 tooltip_format_value: void 0,
1352 tooltip_position: void 0,
1353 tooltip_contents: {},
1354 tooltip_init_show: false,
1355 tooltip_init_x: 0,
1356 tooltip_init_position: void 0,
1357 tooltip_linked: false,
1358 tooltip_linked_name: "",
1359 tooltip_onshow: () => {
1360 },
1361 tooltip_onhide: () => {
1362 },
1363 tooltip_onshown: () => {
1364 },
1365 tooltip_onhidden: () => {
1366 },
1367 tooltip_order: null
1368});
1369
1370;// ./src/config/Options/data/data.ts
1371/* harmony default export */ var data = ({
1372 /**
1373 * Specify the key of x values in the data.<br><br>
1374 * 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 category axis, the values of the data on the key will be used for category names.
1375 * @name data․x
1376 * @memberof Options
1377 * @type {string}
1378 * @default undefined
1379 * @example
1380 * data: {
1381 * x: "date"
1382 * }
1383 */
1384 data_x: void 0,
1385 /**
1386 * Converts data id value
1387 * @name data․idConverter
1388 * @memberof Options
1389 * @type {Function}
1390 * @default function(id) { return id; }
1391 * @example
1392 * data: {
1393 * idConverter: function(id) {
1394 * // when id is 'data1', converts to be 'data2'
1395 * // 'data2' should be given as the initial data value
1396 * if (id === "data1") {
1397 * return "data2";
1398 * } else {
1399 * return id;
1400 * }
1401 * }
1402 * }
1403 */
1404 data_idConverter: (id) => id,
1405 /**
1406 * Set custom data name.
1407 * If a name is set to `null`, the series is omitted from the legend.
1408 * @name data․names
1409 * @memberof Options
1410 * @type {object}
1411 * @default {}
1412 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataName)
1413 * @example
1414 * data: {
1415 * names: {
1416 * data1: "Data Name 1",
1417 * data2: "Data Name 2"
1418 * }
1419 * }
1420 */
1421 data_names: {},
1422 /**
1423 * Set custom data class.<br><br>
1424 * 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).
1425 * @name data․classes
1426 * @memberof Options
1427 * @type {object}
1428 * @default {}
1429 * @example
1430 * data: {
1431 * classes: {
1432 * data1: "additional-data1-class",
1433 * data2: "additional-data2-class"
1434 * }
1435 * }
1436 */
1437 data_classes: {},
1438 /**
1439 * Set chart type at once.<br><br>
1440 * If this option is specified, the type will be applied to every data. This setting can be overwritten by data.types.<br><br>
1441 * **Available Values:**
1442 * - area
1443 * - area-line-range
1444 * - area-spline
1445 * - area-spline-range
1446 * - area-step
1447 * - area-step-range
1448 * - bar
1449 * - bubble
1450 * - candlestick
1451 * - donut
1452 * - funnel
1453 * - gauge
1454 * - line
1455 * - pie
1456 * - polar
1457 * - radar
1458 * - scatter
1459 * - spline
1460 * - step
1461 * - treemap
1462 * @name data․type
1463 * @memberof Options
1464 * @type {string}
1465 * @default "line"<br>NOTE: When importing shapes by ESM, `line()` should be specified for type.
1466 * @example
1467 * data: {
1468 * type: "bar"
1469 * }
1470 * @example
1471 * // Generate chart by importing ESM
1472 * // Import types to be used only, where this will make smaller bundle size.
1473 * import bb, {
1474 * area,
1475 * areaLineRange,
1476 * areaSpline,
1477 * areaSplineRange,
1478 * areaStep,
1479 * areaStepRange,
1480 * bar,
1481 * bubble,
1482 * candlestick,
1483 * donut,
1484 * funnel,
1485 * gauge,
1486 * line,
1487 * pie,
1488 * polar,
1489 * radar,
1490 * scatter,
1491 * spline,
1492 * step,
1493 * treemap
1494 * }
1495 *
1496 * bb.generate({
1497 * ...,
1498 * data: {
1499 * type: bar()
1500 * }
1501 * });
1502 */
1503 data_type: void 0,
1504 /**
1505 * Set chart type for each data.<br>
1506 * This setting overwrites data.type setting.
1507 * - **NOTE:** `radar` and `treemap` type can't be combined with other types.
1508 * @name data․types
1509 * @memberof Options
1510 * @type {object}
1511 * @default {}
1512 * @example
1513 * data: {
1514 * types: {
1515 * data1: "bar",
1516 * data2: "spline"
1517 * }
1518 * }
1519 * @example
1520 * // Generate chart by importing ESM
1521 * // Import types to be used only, where this will make smaller bundle size.
1522 * import bb, {
1523 * area,
1524 * areaLineRange,
1525 * areaSpline,
1526 * areaSplineRange,
1527 * areaStep,
1528 * areaStepRange,
1529 * bar,
1530 * bubble,
1531 * candlestick,
1532 * donut,
1533 * funnel,
1534 * gauge,
1535 * line,
1536 * pie,
1537 * polar,
1538 * radar,
1539 * scatter,
1540 * spline,
1541 * step,
1542 * treemap
1543 * }
1544 *
1545 * bb.generate({
1546 * ...,
1547 * data: {
1548 * types: {
1549 * data1: bar(),
1550 * data1: spline()
1551 * }
1552 * }
1553 * });
1554 */
1555 data_types: {},
1556 /**
1557 * This option changes the order of stacking data and pieces of pie/donut.
1558 * - If `null` specified, it will be the order the data loaded.
1559 * - If function 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>
1560 *
1561 * **Available Values:**
1562 * - `desc`: In descending order
1563 * - `asc`: In ascending order
1564 * - `null`: It keeps the data load order
1565 * - `function(data1, data2) { ... }`: Array.sort compareFunction
1566 *
1567 * **NOTE**: order function, only works for Axis based types & Arc types, except `Radar` type.
1568 * @name data․order
1569 * @memberof Options
1570 * @type {string|Function|null}
1571 * @default desc
1572 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataOrder)
1573 * @example
1574 * data: {
1575 * // in descending order (default)
1576 * order: "desc"
1577 *
1578 * // in ascending order
1579 * order: "asc"
1580 *
1581 * // keeps data input order
1582 * order: null
1583 *
1584 * // specifying sort function
1585 * order: function(a, b) {
1586 * // param data passed format
1587 * // {
1588 * // id: "data1", id_org: "data1", values: [
1589 * // {x: 5, value: 250, id: "data1", index: 5, name: "data1"},
1590 * // ...
1591 * // ]
1592 * // }
1593 *
1594 * const reducer = (p, c) => p + Math.abs(c.value);
1595 * const aSum = a.values.reduce(reducer, 0);
1596 * const bSum = b.values.reduce(reducer, 0);
1597 *
1598 * // ascending order
1599 * return aSum - bSum;
1600 *
1601 * // descending order
1602 * // return bSum - aSum;
1603 * }
1604 * }
1605 */
1606 data_order: "desc",
1607 /**
1608 * Set groups for the data for stacking.
1609 * @name data․groups
1610 * @memberof Options
1611 * @type {Array}
1612 * @default []
1613 * @example
1614 * data: {
1615 * groups: [
1616 * ["data1", "data2"],
1617 * ["data3"]
1618 * ]
1619 * }
1620 */
1621 data_groups: [],
1622 /**
1623 * Set how zero value will be treated on groups.<br>
1624 * Possible values:
1625 * - `zero`: 0 will be positioned at absolute axis zero point.
1626 * - `positive`: 0 will be positioned at the top of a stack.
1627 * - `negative`: 0 will be positioned at the bottom of a stack.
1628 * @name data․groupsZeroAs
1629 * @memberof Options
1630 * @type {string}
1631 * @default "positive"
1632 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.Groups)
1633 * @example
1634 * data: {
1635 * groupsZeroAs: "zero" // "positive" or "negative"
1636 * }
1637 */
1638 data_groupsZeroAs: "positive",
1639 /**
1640 * Set color converter function.<br><br>
1641 * This option should 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').
1642 * @name data․color
1643 * @memberof Options
1644 * @type {Function}
1645 * @default undefined
1646 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataColor)
1647 * @example
1648 * data: {
1649 * color: function(color, d) { ... }
1650 * }
1651 */
1652 data_color: void 0,
1653 /**
1654 * Set color for each data.
1655 * @name data․colors
1656 * @memberof Options
1657 * @type {object}
1658 * @default {}
1659 * @example
1660 * data: {
1661 * colors: {
1662 * data1: "#ff0000",
1663 * data2: function(d) {
1664 * return "#000";
1665 * }
1666 * ...
1667 * }
1668 * }
1669 */
1670 data_colors: {},
1671 /**
1672 * Set labels options
1673 * @name data․labels
1674 * @memberof Options
1675 * @type {object}
1676 * @property {object} data Data object
1677 * @property {boolean} [data.labels=false] Show or hide labels on each data points
1678 * @property {boolean} [data.labels.centered=false] Centerize labels on `bar` shape. (**NOTE:** works only for 'bar' type)
1679 * @property {Function} [data.labels.format] Set formatter function for data labels.<br>
1680 * 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>
1681 * The arguments are:<br>
1682 * - `v` is the value of the data point where the label is shown.
1683 * - `id` is the id of the data where the label is shown.
1684 * - `i` is the index of the data series point where the label is shown.
1685 * - `texts` is the array of whole corresponding data series' text labels.<br><br>
1686 * Formatter function can be defined for each data by specifying as an object and D3 formatter function can be set (ex. d3.format('$'))
1687 * @property {string|object} [data.labels.backgroundColors] Set label text background colors.
1688 * @property {string|object|Function} [data.labels.colors] Set label text colors.
1689 * @property {object|Function} [data.labels.position] Set each dataset position, relative the original.<br><br>
1690 * When function is specified, will receives 5 arguments such as `type, v, id, i, texts` and it must return a position number.<br><br>
1691 * The arguments are:<br>
1692 * - `type` coordinate type string, which will be 'x' or 'y'.
1693 * - `v` is the value of the data point where the label is shown.
1694 * - `id` is the id of the data where the label is shown.
1695 * - `i` is the index of the data series point where the label is shown.
1696 * - `texts` is the array of whole corresponding data series' text labels.<br><br>
1697 * @property {number} [data.labels.position.x=0] x coordinate position, relative the original.
1698 * @property {number} [data.labels.position.y=0] y coordinate position, relative the original.
1699 * @property {object} [data.labels.rotate] Rotate label text. Specify degree value in a range of `0 ~ 360`.
1700 * - **NOTE:** Depend on rotate value, text position need to be adjusted manually(using `data.labels.position` option) to be shown nicely.
1701 * @memberof Options
1702 * @type {object}
1703 * @default {}
1704 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataLabel)
1705 * @see [Demo: label colors](https://naver.github.io/billboard.js/demo/#Data.DataLabelColors)
1706 * @see [Demo: label format](https://naver.github.io/billboard.js/demo/#Data.DataLabelFormat)
1707 * @see [Demo: label multiline](https://naver.github.io/billboard.js/demo/#Data.DataLabelMultiline)
1708 * @see [Demo: label overlap](https://naver.github.io/billboard.js/demo/#Data.DataLabelOverlap)
1709 * @see [Demo: label position](https://naver.github.io/billboard.js/demo/#Data.DataLabelPosition)
1710 * @see [Demo: label rotate](https://naver.github.io/billboard.js/demo/#Data.DataLabelRotate)
1711 * @example
1712 * data: {
1713 * labels: true,
1714 *
1715 * // or set specific options
1716 * labels: {
1717 * format: function(v, id, i, texts) {
1718 * ...
1719 * // to multiline, return with '\n' character
1720 * return "Line1\nLine2";
1721 * },
1722 *
1723 * // it's possible to set for each data
1724 * format: {
1725 * data1: function(v, id, i, texts) { ... },
1726 * ...
1727 * },
1728 *
1729 * // align text to center of the 'bar' shape (works only for 'bar' type)
1730 * centered: true,
1731 *
1732 * // apply backgound color for label texts
1733 * backgroundColors: "red",
1734 *
1735 * // set differenct backround colors per dataset
1736 * backgroundColors: {
1737 * data1: "green",
1738 * data2: "yellow"
1739 * }
1740 *
1741 * // apply for all label texts
1742 * colors: "red",
1743 *
1744 * // set different colors per dataset
1745 * // for not specified dataset, will have the default color value
1746 * colors: {
1747 * data1: "yellow",
1748 * data3: "green"
1749 * },
1750 *
1751 * // call back for label text color
1752 * colors: function(color, d) {
1753 * // color: the default data label color string
1754 * // data: ex) {x: 0, value: 200, id: "data3", index: 0}
1755 * ....
1756 * return d.value > 200 ? "cyan" : color;
1757 * },
1758 *
1759 * // return x, y coordinate position
1760 * // apt to handle each text position manually
1761 * position: function(type, v, id, i, texts) {
1762 * ...
1763 * return type == "x" ? 10 : 20;
1764 * },
1765 *
1766 * // set x, y coordinate position
1767 * position: {
1768 * x: -10,
1769 * y: 10
1770 * },
1771 *
1772 * // or set x, y coordinate position by each dataset
1773 * position: {
1774 * data1: {x: 5, y: 5},
1775 * data2: {x: 10, y: -20}
1776 * },
1777 *
1778 * // rotate degree for label text
1779 * rotate: 90
1780 * }
1781 * }
1782 */
1783 data_labels: {},
1784 data_labels_backgroundColors: void 0,
1785 data_labels_colors: void 0,
1786 data_labels_position: {},
1787 /**
1788 * Hide each data when the chart appears.<br><br>
1789 * If true specified, all of data will be hidden. If multiple ids specified as an array, those will be hidden.
1790 * @name data․hide
1791 * @memberof Options
1792 * @type {boolean|Array}
1793 * @default false
1794 * @example
1795 * data: {
1796 * // all of data will be hidden
1797 * hide: true
1798 *
1799 * // specified data will be hidden
1800 * hide: ["data1", ...]
1801 * }
1802 */
1803 data_hide: false,
1804 /**
1805 * Filter values to be shown
1806 * The data value is the same as the returned by `.data()`.
1807 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
1808 * @name data․filter
1809 * @memberof Options
1810 * @type {Function}
1811 * @default undefined
1812 * @example
1813 * data: {
1814 * // filter for id value
1815 * filter: function(v) {
1816 * // v: [{id: "data1", id_org: "data1", values: [
1817 * // {x: 0, value: 130, id: "data2", index: 0}, ...]
1818 * // }, ...]
1819 * return v.id !== "data1";
1820 * }
1821 */
1822 data_filter: void 0,
1823 /**
1824 * Set a callback for click event on each data point.<br><br>
1825 * This callback will be called when each data point clicked and will receive `d` and element as the arguments.
1826 * - `d` is the data clicked and element is the element clicked.
1827 * - `element` is the current interacting svg element.
1828 * - In this callback, `this` will be the Chart object.
1829 * @name data․onclick
1830 * @memberof Options
1831 * @type {Function}
1832 * @default function() {}
1833 * @example
1834 * data: {
1835 * onclick: function(d, element) {
1836 * // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
1837 * // element - <circle>
1838 * ...
1839 * }
1840 * }
1841 */
1842 data_onclick: () => {
1843 },
1844 /**
1845 * Set a callback for mouse/touch over event on each data point.<br><br>
1846 * This callback will be called when mouse cursor or via touch moves onto each data point and will receive `d` and `element` as the argument.
1847 * - `d` is the data where mouse cursor moves onto.
1848 * - `element` is the current interacting svg element.
1849 * - In this callback, `this` will be the Chart object.
1850 * @name data․onover
1851 * @memberof Options
1852 * @type {Function}
1853 * @default function() {}
1854 * @example
1855 * data: {
1856 * onover: function(d, element) {
1857 * // d - ex) {x: 4, value: 150, id: "data1", index: 4}
1858 * // element - <circle>
1859 * ...
1860 * }
1861 * }
1862 */
1863 data_onover: () => {
1864 },
1865 /**
1866 * Set a callback for mouse/touch out event on each data point.<br><br>
1867 * This callback will be called when mouse cursor or via touch moves out each data point and will receive `d` as the argument.
1868 * - `d` is the data where mouse cursor moves out.
1869 * - `element` is the current interacting svg element.
1870 * - In this callback, `this` will be the Chart object.
1871 * @name data․onout
1872 * @memberof Options
1873 * @type {Function}
1874 * @default function() {}
1875 * @example
1876 * data: {
1877 * onout: function(d, element) {
1878 * // d - ex) {x: 4, value: 150, id: "data1", index: 4}
1879 * // element - <circle>
1880 * ...
1881 * }
1882 * }
1883 */
1884 data_onout: () => {
1885 },
1886 /**
1887 * Set a callback for when data is shown.<br>
1888 * The callback will receive shown data ids in array.
1889 * @name data․onshown
1890 * @memberof Options
1891 * @type {Function}
1892 * @default undefined
1893 * @example
1894 * data: {
1895 * onshown: function(ids) {
1896 * // ids - ["data1", "data2", ...]
1897 * ...
1898 * }
1899 * }
1900 */
1901 data_onshown: void 0,
1902 /**
1903 * Set a callback for when data is hidden.<br>
1904 * The callback will receive hidden data ids in array.
1905 * @name data․onhidden
1906 * @memberof Options
1907 * @type {Function}
1908 * @default undefined
1909 * @example
1910 * data: {
1911 * onhidden: function(ids) {
1912 * // ids - ["data1", "data2", ...]
1913 * ...
1914 * }
1915 * }
1916 */
1917 data_onhidden: void 0,
1918 /**
1919 * Set a callback for minimum data
1920 * - **NOTE:** For 'area-line-range', 'area-step-range' and 'area-spline-range', `mid` data will be taken for the comparison
1921 * @name data․onmin
1922 * @memberof Options
1923 * @type {Function}
1924 * @default undefined
1925 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.OnMinMaxCallback)
1926 * @example
1927 * onmin: function(data) {
1928 * // data - ex) [{x: 3, value: 400, id: "data1", index: 3}, ... ]
1929 * ...
1930 * }
1931 */
1932 data_onmin: void 0,
1933 /**
1934 * Set a callback for maximum data
1935 * - **NOTE:** For 'area-line-range', 'area-step-range' and 'area-spline-range', `mid` data will be taken for the comparison
1936 * @name data․onmax
1937 * @memberof Options
1938 * @type {Function}
1939 * @default undefined
1940 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.OnMinMaxCallback)
1941 * @example
1942 * onmax: function(data) {
1943 * // data - ex) [{x: 3, value: 400, id: "data1", index: 3}, ... ]
1944 * ...
1945 * }
1946 */
1947 data_onmax: void 0,
1948 /**
1949 * Load a CSV or JSON file from a URL. NOTE that this will not work if loading via the "file://" protocol as the most browsers will block XMLHTTPRequests.
1950 * @name data․url
1951 * @memberof Options
1952 * @type {string}
1953 * @default undefined
1954 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.LoadData)
1955 * @example
1956 * data: {
1957 * url: "/data/test.csv"
1958 * }
1959 */
1960 data_url: void 0,
1961 /**
1962 * XHR header value
1963 * - **NOTE:** Should be used with `data.url` option
1964 * @name data․headers
1965 * @memberof Options
1966 * @type {string}
1967 * @default undefined
1968 * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader
1969 * @example
1970 * data: {
1971 * url: "/data/test.csv",
1972 * headers: {
1973 * "Content-Type": "text/xml",
1974 * ...
1975 * }
1976 * }
1977 */
1978 data_headers: void 0,
1979 /**
1980 * Parse a JSON object for data. See also data.keys.
1981 * @name data․json
1982 * @memberof Options
1983 * @type {Array}
1984 * @default undefined
1985 * @see [data․keys](#.data%25E2%2580%25A4keys)
1986 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.JSONData)
1987 * @example
1988 * data: {
1989 * json: [
1990 * {name: "www.site1.com", upload: 200, download: 200, total: 400},
1991 * {name: "www.site2.com", upload: 100, download: 300, total: 400},
1992 * {name: "www.site3.com", upload: 300, download: 200, total: 500},
1993 * {name: "www.site4.com", upload: 400, download: 100, total: 500}
1994 * ],
1995 * keys: {
1996 * // case 1: specify 'x' key for category axis
1997 * x: "name", // 'name' key will be used as category x axis values
1998 * value: ["upload", "download"]
1999 *
2000 * // case 2: without 'x' key for non-category axis
2001 * value: ["upload", "download"]
2002 * }
2003 * }
2004 */
2005 data_json: void 0,
2006 /**
2007 * Load data from a multidimensional array, with the first element containing the data names, the following containing related data in that order.
2008 * @name data․rows
2009 * @memberof Options
2010 * @type {Array}
2011 * @default undefined
2012 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.RowOrientedData)
2013 * @example
2014 * data: {
2015 * rows: [
2016 * ["A", "B", "C"],
2017 * [90, 120, 300],
2018 * [40, 160, 240],
2019 * [50, 200, 290],
2020 * [120, 160, 230],
2021 * [80, 130, 300],
2022 * [90, 220, 320]
2023 * ]
2024 * }
2025 *
2026 * // for 'bar' type, data can contain:
2027 * // - an array of [start, end] data following the order
2028 * data: {
2029 * rows: [
2030 * ["data1", "data2"],
2031 * [[100, 150], 120],
2032 * [[200, 300], 55],
2033 * [[-400, 500], 60]
2034 * ],
2035 * type: "bar"
2036 * }
2037 *
2038 * // for 'range' types('area-line-range' or 'area-step-range' or 'area-spline-range'), data should contain:
2039 * // - an array of [high, mid, low] data following the order
2040 * // - or an object with 'high', 'mid' and 'low' key value
2041 * data: {
2042 * rows: [
2043 * ["data1", "data2"],
2044 * [
2045 * // or {high:150, mid: 140, low: 110}, 120
2046 * [150, 140, 110], 120
2047 * ],
2048 * [[155, 130, 115], 55],
2049 * [[160, 135, 120], 60]
2050 * ],
2051 * types: {
2052 * data1: "area-line-range",
2053 * data2: "line"
2054 * }
2055 * }
2056 *
2057 * // for 'bubble' type, data can contain dimension value:
2058 * // - an array of [y, z] data following the order
2059 * // - or an object with 'y' and 'z' key value
2060 * // 'y' is for y axis coordination and 'z' is the bubble radius value
2061 * data: {
2062 * rows: [
2063 * ["data1", "data2"],
2064 * [
2065 * // or {y:10, z: 140}, 120
2066 * [10, 140], 120
2067 * ],
2068 * [[100, 30], 55],
2069 * [[50, 100], 60]
2070 * ],
2071 * types: {
2072 * data1: "bubble",
2073 * data2: "line"
2074 * }
2075 * }
2076 *
2077 * // for 'canlestick' type, data should contain:
2078 * // - an array of [open, high, low, close, volume(optional)] data following the order
2079 * // - or an object with 'open', 'high', 'low', 'close' and 'value'(optional) key value
2080 * data: {
2081 * rows: [
2082 * ["data1", "data2"],
2083 * [
2084 * // open, high, low, close, volume (optional)
2085 * {open: 1300, high: 1369, low: 1200, close: 1339, volume: 100},
2086 * [1000, 1100, 850, 870]
2087 * ],
2088 * [
2089 * {open: 1348, high: 1371, low: 1271, close: 1320},
2090 * [870, 1250, 830, 1200, 50]
2091 * ]
2092 * ],
2093 * type: "candlestick"
2094 * }
2095 */
2096 data_rows: void 0,
2097 /**
2098 * Load data from a multidimensional array, with each element containing an array consisting of a datum name and associated data values.
2099 * @name data․columns
2100 * @memberof Options
2101 * @type {Array}
2102 * @default undefined
2103 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.ColumnOrientedData)
2104 * @example
2105 * data: {
2106 * columns: [
2107 * ["data1", 30, 20, 50, 40, 60, 50],
2108 * ["data2", 200, 130, 90, 240, 130, 220],
2109 * ["data3", 300, 200, 160, 400, 250, 250]
2110 * ]
2111 * }
2112 *
2113 * // for 'bar' type, data can contain:
2114 * // - an array of [start, end] data following the order
2115 * data: {
2116 * columns: [
2117 * ["data1", -100, 50, [100, 200], [200, 300]],
2118 * ["data2", -200, 300, [-100, 100], [-50, -30]],
2119 * ],
2120 * type: "bar"
2121 * }
2122 *
2123 * // for 'range' types('area-line-range' or 'area-step-range' or 'area-spline-range'), data should contain:
2124 * // - an array of [high, mid, low] data following the order
2125 * // - or an object with 'high', 'mid' and 'low' key value
2126 * data: {
2127 * columns: [
2128 * ["data1",
2129 * [150, 140, 110], // or {high:150, mid: 140, low: 110}
2130 * [150, 140, 110],
2131 * [150, 140, 110]
2132 * ]
2133 * ],
2134 * type: "area-line-range"
2135 * }
2136 *
2137 * // for 'bubble' type, data can contain dimension value:
2138 * // - an array of [y, z] data following the order
2139 * // - or an object with 'y' and 'z' key value
2140 * // 'y' is for y axis coordination and 'z' is the bubble radius value
2141 * data: {
2142 * columns: [
2143 * ["data1",
2144 * [10, 140], // or {y:10, z: 140}
2145 * [100, 30],
2146 * [50, 100]
2147 * ]
2148 * ],
2149 * type: "bubble"
2150 * }
2151 *
2152 * // for 'canlestick' type, data should contain:
2153 * // - an array of [open, high, low, close, volume(optional)] data following the order
2154 * // - or an object with 'open', 'high', 'low', 'close' and 'value'(optional) key value
2155 * data: {
2156 * columns: [
2157 * ["data1",
2158 * [1000, 1100, 850, 870, 100], // or {open:1000, high: 1100, low: 870, volume: 100}
2159 * [870, 1250, 830, 1200] // 'volume' can be omitted
2160 * ]
2161 * ],
2162 * type: "candlestick"
2163 * }
2164 */
2165 data_columns: void 0,
2166 /**
2167 * Used if loading JSON via data.url.
2168 * - **Available Values:**
2169 * - json
2170 * - csv
2171 * - tsv
2172 * @name data․mimeType
2173 * @memberof Options
2174 * @type {string}
2175 * @default csv
2176 * @example
2177 * data: {
2178 * mimeType: "json"
2179 * }
2180 */
2181 data_mimeType: "csv",
2182 /**
2183 * Choose which JSON object keys correspond to desired data.
2184 * - **NOTE:** Only for JSON object given as array.
2185 * @name data․keys
2186 * @memberof Options
2187 * @type {string}
2188 * @default undefined
2189 * @example
2190 * data: {
2191 * json: [
2192 * {name: "www.site1.com", upload: 200, download: 200, total: 400},
2193 * {name: "www.site2.com", upload: 100, download: 300, total: 400},
2194 * {name: "www.site3.com", upload: 300, download: 200, total: 500},
2195 * {name: "www.site4.com", upload: 400, download: 100, total: 500}
2196 * ],
2197 * keys: {
2198 * // case 1: specify 'x' key for category axis
2199 * x: "name", // 'name' key will be used as category x axis values
2200 * value: ["upload", "download"]
2201 *
2202 * // case 2: without 'x' key for non-category axis
2203 * value: ["upload", "download"]
2204 * }
2205 * }
2206 */
2207 data_keys: void 0,
2208 /**
2209 * Set text label to be displayed when there's no data to show.
2210 * - ex. Toggling all visible data to not be shown, unloading all current data, etc.
2211 * @name data․empty․label․text
2212 * @memberof Options
2213 * @type {string}
2214 * @default ""
2215 * @example
2216 * data: {
2217 * empty: {
2218 * label: {
2219 * text: "No Data"
2220 * }
2221 * }
2222 * }
2223 */
2224 data_empty_label_text: ""
2225});
2226
2227;// ./src/config/Options/interaction/interaction.ts
2228/* harmony default export */ var interaction = ({
2229 /**
2230 * Interaction options
2231 * @name interaction
2232 * @memberof Options
2233 * @type {object}
2234 * @property {object} interaction Intersection object
2235 * @property {boolean} [interaction.enabled=true] Indicate if the chart should have interactions.<br>
2236 * If `false` is set, all of interactions (showing/hiding tooltip, selection, mouse events, etc) will be disabled.
2237 * @property {boolean} [interaction.brighten=true] Make brighter for the selected area (ex. 'pie' type data selected area)
2238 * @property {boolean} [interaction.inputType.mouse=true] enable or disable mouse interaction
2239 * @property {boolean} [interaction.inputType.touch=true] enable or disable touch interaction
2240 * @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.
2241 * @property {boolean} [interaction.onout=true] Enable or disable "onout" event.<br>
2242 * When is disabled, defocus(hiding tooltip, focused gridline, etc.) event won't work.
2243 * @see [Demo: touch.preventDefault](https://naver.github.io/billboard.js/demo/#Interaction.PreventScrollOnTouch)
2244 * @example
2245 * interaction: {
2246 * enabled: false,
2247 * brighten: false,
2248 * inputType: {
2249 * mouse: true,
2250 * touch: false
2251 *
2252 * // or declare preventDefault explicitly.
2253 * // In this case touch inputType is enabled by default
2254 * touch: {
2255 * preventDefault: true
2256 *
2257 * // or threshold pixel value (pixel moved from touchstart to touchmove)
2258 * preventDefault: 5
2259 * }
2260 * },
2261 *
2262 * // disable "onout" event
2263 * onout: false
2264 * }
2265 */
2266 interaction_enabled: true,
2267 interaction_brighten: true,
2268 interaction_inputType_mouse: true,
2269 interaction_inputType_touch: {},
2270 interaction_onout: true
2271});
2272
2273// EXTERNAL MODULE: external {"commonjs":"d3-brush","commonjs2":"d3-brush","amd":"d3-brush","root":"d3"}
2274var external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_ = __webpack_require__(4);
2275;// ./src/module/browser.ts
2276function getGlobal() {
2277 return typeof globalThis === "object" && globalThis !== null && globalThis.Object === Object && globalThis || typeof global === "object" && global !== null && global.Object === Object && global || typeof self === "object" && self !== null && self.Object === Object && self || Function("return this")();
2278}
2279function getFallback(w) {
2280 const hasRAF = typeof (w == null ? void 0 : w.requestAnimationFrame) === "function" && typeof (w == null ? void 0 : w.cancelAnimationFrame) === "function";
2281 const hasRIC = typeof (w == null ? void 0 : w.requestIdleCallback) === "function" && typeof (w == null ? void 0 : w.cancelIdleCallback) === "function";
2282 const request = (cb) => setTimeout(cb, 1);
2283 const cancel = (id) => clearTimeout(id);
2284 return [
2285 hasRAF ? w.requestAnimationFrame : request,
2286 hasRAF ? w.cancelAnimationFrame : cancel,
2287 hasRIC ? w.requestIdleCallback : request,
2288 hasRIC ? w.cancelIdleCallback : cancel
2289 ];
2290}
2291const win = getGlobal();
2292const browser_doc = win == null ? void 0 : win.document;
2293const [
2294 requestAnimationFrame,
2295 cancelAnimationFrame,
2296 requestIdleCallback,
2297 cancelIdleCallback
2298] = getFallback(win);
2299
2300
2301;// ./src/module/util.ts
2302var util_defProp = Object.defineProperty;
2303var util_getOwnPropSymbols = Object.getOwnPropertySymbols;
2304var util_hasOwnProp = Object.prototype.hasOwnProperty;
2305var util_propIsEnum = Object.prototype.propertyIsEnumerable;
2306var util_defNormalProp = (obj, key, value) => key in obj ? util_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2307var util_spreadValues = (a, b) => {
2308 for (var prop in b || (b = {}))
2309 if (util_hasOwnProp.call(b, prop))
2310 util_defNormalProp(a, prop, b[prop]);
2311 if (util_getOwnPropSymbols)
2312 for (var prop of util_getOwnPropSymbols(b)) {
2313 if (util_propIsEnum.call(b, prop))
2314 util_defNormalProp(a, prop, b[prop]);
2315 }
2316 return a;
2317};
2318
2319
2320
2321
2322const isValue = (v) => v || v === 0;
2323const isFunction = (v) => typeof v === "function";
2324const isString = (v) => typeof v === "string";
2325const isNumber = (v) => typeof v === "number";
2326const isUndefined = (v) => typeof v === "undefined";
2327const isDefined = (v) => typeof v !== "undefined";
2328const isBoolean = (v) => typeof v === "boolean";
2329const ceil10 = (v) => Math.ceil(v / 10) * 10;
2330const asHalfPixel = (n) => Math.ceil(n) + 0.5;
2331const diffDomain = (d) => d[1] - d[0];
2332const isObjectType = (v) => typeof v === "object";
2333const isEmpty = (o) => isUndefined(o) || o === null || isString(o) && o.length === 0 || isObjectType(o) && !(o instanceof Date) && Object.keys(o).length === 0 || isNumber(o) && isNaN(o);
2334const notEmpty = (o) => !isEmpty(o);
2335const isArray = (arr) => Array.isArray(arr);
2336const isObject = (obj) => obj && !(obj == null ? void 0 : obj.nodeType) && isObjectType(obj) && !isArray(obj);
2337function getOption(options, key, defaultValue) {
2338 return isDefined(options[key]) ? options[key] : defaultValue;
2339}
2340function hasValue(dict, value) {
2341 let found = false;
2342 Object.keys(dict).forEach((key) => dict[key] === value && (found = true));
2343 return found;
2344}
2345function callFn(fn, thisArg, ...args) {
2346 const isFn = isFunction(fn);
2347 isFn && fn.call(thisArg, ...args);
2348 return isFn;
2349}
2350function endall(transition, cb) {
2351 let n = 0;
2352 const end = function(...args) {
2353 !--n && cb.apply(this, ...args);
2354 };
2355 if ("duration" in transition) {
2356 transition.each(() => ++n).on("end", end);
2357 } else {
2358 ++n;
2359 transition.call(end);
2360 }
2361}
2362function sanitize(str) {
2363 return isString(str) ? str.replace(/<(script|img)?/ig, "&lt;").replace(/(script)?>/ig, "&gt;") : str;
2364}
2365function setTextValue(node, text, dy = [-1, 1], toMiddle = false) {
2366 if (!node || !isString(text)) {
2367 return;
2368 }
2369 if (text.indexOf("\n") === -1) {
2370 node.text(text);
2371 } else {
2372 const diff = [node.text(), text].map((v) => v.replace(/[\s\n]/g, ""));
2373 if (diff[0] !== diff[1]) {
2374 const multiline = text.split("\n");
2375 const len = toMiddle ? multiline.length - 1 : 1;
2376 node.html("");
2377 multiline.forEach((v, i) => {
2378 node.append("tspan").attr("x", 0).attr("dy", `${i === 0 ? dy[0] * len : dy[1]}em`).text(v);
2379 });
2380 }
2381 }
2382}
2383function getRectSegList(path) {
2384 const { x, y, width, height } = path.getBBox();
2385 return [
2386 { x, y: y + height },
2387 // seg0
2388 { x, y },
2389 // seg1
2390 { x: x + width, y },
2391 // seg2
2392 { x: x + width, y: y + height }
2393 // seg3
2394 ];
2395}
2396function getPathBox(path) {
2397 const { width, height } = path.getBoundingClientRect();
2398 const items = getRectSegList(path);
2399 const x = items[0].x;
2400 const y = Math.min(items[0].y, items[1].y);
2401 return {
2402 x,
2403 y,
2404 width,
2405 height
2406 };
2407}
2408function getPointer(event, element) {
2409 var _a;
2410 const touches = event && ((_a = event.touches || event.sourceEvent && event.sourceEvent.touches) == null ? void 0 : _a[0]);
2411 let pointer = [0, 0];
2412 try {
2413 pointer = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.pointer)(touches || event, element);
2414 } catch (e) {
2415 }
2416 return pointer.map((v) => isNaN(v) ? 0 : v);
2417}
2418function getBrushSelection(ctx) {
2419 const { event, $el } = ctx;
2420 const main = $el.subchart.main || $el.main;
2421 let selection;
2422 if (event && event.type === "brush") {
2423 selection = event.selection;
2424 } else if (main && (selection = main.select(".bb-brush").node())) {
2425 selection = (0,external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_.brushSelection)(selection);
2426 }
2427 return selection;
2428}
2429function getBoundingRect(node) {
2430 const needEvaluate = !("rect" in node) || "rect" in node && node.hasAttribute("width") && node.rect.width !== +node.getAttribute("width");
2431 return needEvaluate ? node.rect = node.getBoundingClientRect() : node.rect;
2432}
2433function getRandom(asStr = true, min = 0, max = 1e4) {
2434 const crpt = win.crypto || win.msCrypto;
2435 const rand = crpt ? min + crpt.getRandomValues(new Uint32Array(1))[0] % (max - min + 1) : Math.floor(Math.random() * (max - min) + min);
2436 return asStr ? String(rand) : rand;
2437}
2438function findIndex(arr, v, start, end, isRotated) {
2439 if (start > end) {
2440 return -1;
2441 }
2442 const mid = Math.floor((start + end) / 2);
2443 let { x, w = 0 } = arr[mid];
2444 if (isRotated) {
2445 x = arr[mid].y;
2446 w = arr[mid].h;
2447 }
2448 if (v >= x && v <= x + w) {
2449 return mid;
2450 }
2451 return v < x ? findIndex(arr, v, start, mid - 1, isRotated) : findIndex(arr, v, mid + 1, end, isRotated);
2452}
2453function brushEmpty(ctx) {
2454 const selection = getBrushSelection(ctx);
2455 if (selection) {
2456 return selection[0] === selection[1];
2457 }
2458 return true;
2459}
2460function deepClone(...objectN) {
2461 const clone = (v) => {
2462 if (isObject(v) && v.constructor) {
2463 const r = new v.constructor();
2464 for (const k in v) {
2465 r[k] = clone(v[k]);
2466 }
2467 return r;
2468 }
2469 return v;
2470 };
2471 return objectN.map((v) => clone(v)).reduce((a, c) => util_spreadValues(util_spreadValues({}, a), c));
2472}
2473function extend(target = {}, source) {
2474 if (isArray(source)) {
2475 source.forEach((v) => extend(target, v));
2476 }
2477 for (const p in source) {
2478 if (/^\d+$/.test(p) || p in target) {
2479 continue;
2480 }
2481 target[p] = source[p];
2482 }
2483 return target;
2484}
2485const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2486function camelize(str, separator = "-") {
2487 return str.split(separator).map((v, i) => i ? v.charAt(0).toUpperCase() + v.slice(1).toLowerCase() : v.toLowerCase()).join("");
2488}
2489const toArray = (v) => [].slice.call(v);
2490function addCssRules(style, selector, prop) {
2491 const { rootSelector = "", sheet } = style;
2492 const getSelector = (s) => s.replace(/\s?(bb-)/g, ".$1").replace(/\.+/g, ".");
2493 const rule = `${rootSelector} ${getSelector(selector)} {${prop.join(";")}}`;
2494 return sheet[sheet.insertRule ? "insertRule" : "addRule"](
2495 rule,
2496 sheet.cssRules.length
2497 );
2498}
2499function getCssRules(styleSheets) {
2500 let rules = [];
2501 styleSheets.forEach((sheet) => {
2502 var _a;
2503 try {
2504 if (sheet.cssRules && sheet.cssRules.length) {
2505 rules = rules.concat(toArray(sheet.cssRules));
2506 }
2507 } catch (e) {
2508 (_a = win.console) == null ? void 0 : _a.warn(`Error while reading rules from ${sheet.href}: ${e.toString()}`);
2509 }
2510 });
2511 return rules;
2512}
2513function getScrollPosition(node) {
2514 var _a, _b, _c, _d, _e, _f;
2515 return {
2516 x: ((_b = (_a = win.pageXOffset) != null ? _a : win.scrollX) != null ? _b : 0) + ((_c = node.scrollLeft) != null ? _c : 0),
2517 y: ((_e = (_d = win.pageYOffset) != null ? _d : win.scrollY) != null ? _e : 0) + ((_f = node.scrollTop) != null ? _f : 0)
2518 };
2519}
2520function getTransformCTM(node, x = 0, y = 0, inverse = true) {
2521 const point = new DOMPoint(x, y);
2522 const screen = node.getScreenCTM();
2523 const res = point.matrixTransform(
2524 inverse ? screen == null ? void 0 : screen.inverse() : screen
2525 );
2526 if (inverse === false) {
2527 const rect = node.getBoundingClientRect();
2528 res.x -= rect.x;
2529 res.y -= rect.y;
2530 }
2531 return res;
2532}
2533function getTranslation(node) {
2534 const transform = node ? node.transform : null;
2535 const baseVal = transform && transform.baseVal;
2536 return baseVal && baseVal.numberOfItems ? baseVal.getItem(0).matrix : { a: 0, b: 0, c: 0, d: 0, e: 0, f: 0 };
2537}
2538function getUnique(data) {
2539 const isDate = data[0] instanceof Date;
2540 const d = (isDate ? data.map(Number) : data).filter((v, i, self) => self.indexOf(v) === i);
2541 return isDate ? d.map((v) => new Date(v)) : d;
2542}
2543function mergeArray(arr) {
2544 return arr && arr.length ? arr.reduce((p, c) => p.concat(c)) : [];
2545}
2546function mergeObj(target, ...objectN) {
2547 if (!objectN.length || objectN.length === 1 && !objectN[0]) {
2548 return target;
2549 }
2550 const source = objectN.shift();
2551 if (isObject(target) && isObject(source)) {
2552 Object.keys(source).forEach((key) => {
2553 const value = source[key];
2554 if (isObject(value)) {
2555 !target[key] && (target[key] = {});
2556 target[key] = mergeObj(target[key], value);
2557 } else {
2558 target[key] = isArray(value) ? value.concat() : value;
2559 }
2560 });
2561 }
2562 return mergeObj(target, ...objectN);
2563}
2564function sortValue(data, isAsc = true) {
2565 let fn;
2566 if (data[0] instanceof Date) {
2567 fn = isAsc ? (a, b) => a - b : (a, b) => b - a;
2568 } else {
2569 if (isAsc && !data.every(isNaN)) {
2570 fn = (a, b) => a - b;
2571 } else if (!isAsc) {
2572 fn = (a, b) => a > b && -1 || a < b && 1 || a === b && 0;
2573 }
2574 }
2575 return data.concat().sort(fn);
2576}
2577function getMinMax(type, data) {
2578 let res = data.filter((v) => notEmpty(v));
2579 if (res.length) {
2580 if (isNumber(res[0])) {
2581 res = Math[type](...res);
2582 } else if (res[0] instanceof Date) {
2583 res = sortValue(res, type === "min")[0];
2584 }
2585 } else {
2586 res = void 0;
2587 }
2588 return res;
2589}
2590const getRange = (start, end, step = 1) => {
2591 const res = [];
2592 const n = Math.max(0, Math.ceil((end - start) / step)) | 0;
2593 for (let i = start; i < n; i++) {
2594 res.push(start + i * step);
2595 }
2596 return res;
2597};
2598const emulateEvent = {
2599 mouse: (() => {
2600 const getParams = () => ({
2601 bubbles: false,
2602 cancelable: false,
2603 screenX: 0,
2604 screenY: 0,
2605 clientX: 0,
2606 clientY: 0
2607 });
2608 try {
2609 new MouseEvent("t");
2610 return (el, eventType, params = getParams()) => {
2611 el.dispatchEvent(new MouseEvent(eventType, params));
2612 };
2613 } catch (e) {
2614 return (el, eventType, params = getParams()) => {
2615 const mouseEvent = browser_doc.createEvent("MouseEvent");
2616 mouseEvent.initMouseEvent(
2617 eventType,
2618 params.bubbles,
2619 params.cancelable,
2620 win,
2621 0,
2622 // the event's mouse click count
2623 params.screenX,
2624 params.screenY,
2625 params.clientX,
2626 params.clientY,
2627 false,
2628 false,
2629 false,
2630 false,
2631 0,
2632 null
2633 );
2634 el.dispatchEvent(mouseEvent);
2635 };
2636 }
2637 })(),
2638 touch: (el, eventType, params) => {
2639 const touchObj = new Touch(mergeObj({
2640 identifier: Date.now(),
2641 target: el,
2642 radiusX: 2.5,
2643 radiusY: 2.5,
2644 rotationAngle: 10,
2645 force: 0.5
2646 }, params));
2647 el.dispatchEvent(new TouchEvent(eventType, {
2648 cancelable: true,
2649 bubbles: true,
2650 shiftKey: true,
2651 touches: [touchObj],
2652 targetTouches: [],
2653 changedTouches: [touchObj]
2654 }));
2655 }
2656};
2657function tplProcess(tpl, data) {
2658 let res = tpl;
2659 for (const x in data) {
2660 res = res.replace(new RegExp(`{=${x}}`, "g"), data[x]);
2661 }
2662 return res;
2663}
2664function parseDate(date) {
2665 var _a;
2666 let parsedDate;
2667 if (date instanceof Date) {
2668 parsedDate = date;
2669 } else if (isString(date)) {
2670 const { config, format } = this;
2671 parsedDate = (_a = format.dataTime(config.data_xFormat)(date)) != null ? _a : new Date(date);
2672 } else if (isNumber(date) && !isNaN(date)) {
2673 parsedDate = /* @__PURE__ */ new Date(+date);
2674 }
2675 if (!parsedDate || isNaN(+parsedDate)) {
2676 console && console.error && console.error(`Failed to parse x '${date}' to Date object`);
2677 }
2678 return parsedDate;
2679}
2680function hasViewBox(svg) {
2681 const attr = svg.attr("viewBox");
2682 return attr ? /(\d+(\.\d+)?){3}/.test(attr) : false;
2683}
2684function hasStyle(node, condition, all = false) {
2685 const isD3Node = !!node.node;
2686 let has = false;
2687 for (const [key, value] of Object.entries(condition)) {
2688 has = isD3Node ? node.style(key) === value : node.style[key] === value;
2689 if (all === false && has) {
2690 break;
2691 }
2692 }
2693 return has;
2694}
2695function isTabVisible() {
2696 var _a, _b;
2697 return ((_a = browser_doc) == null ? void 0 : _a.hidden) === false || ((_b = browser_doc) == null ? void 0 : _b.visibilityState) === "visible";
2698}
2699function convertInputType(mouse, touch) {
2700 const { DocumentTouch, matchMedia, navigator } = win;
2701 const hasPointerCoarse = matchMedia == null ? void 0 : matchMedia("(pointer:coarse)").matches;
2702 let hasTouch = false;
2703 if (touch) {
2704 if (navigator && "maxTouchPoints" in navigator) {
2705 hasTouch = navigator.maxTouchPoints > 0;
2706 } else if ("ontouchmove" in win || DocumentTouch && browser_doc instanceof DocumentTouch) {
2707 hasTouch = true;
2708 } else {
2709 if (hasPointerCoarse) {
2710 hasTouch = true;
2711 } else {
2712 const UA = navigator.userAgent;
2713 hasTouch = /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) || /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA);
2714 }
2715 }
2716 }
2717 const hasMouse = mouse && !hasPointerCoarse && (matchMedia == null ? void 0 : matchMedia("(pointer:fine)").matches);
2718 return hasMouse && "mouse" || hasTouch && "touch" || "mouse";
2719}
2720function runUntil(fn, conditionFn) {
2721 if (conditionFn() === false) {
2722 requestAnimationFrame(() => runUntil(fn, conditionFn));
2723 } else {
2724 fn();
2725 }
2726}
2727
2728;// ./src/config/Options/Options.ts
2729var Options_defProp = Object.defineProperty;
2730var Options_getOwnPropSymbols = Object.getOwnPropertySymbols;
2731var Options_hasOwnProp = Object.prototype.hasOwnProperty;
2732var Options_propIsEnum = Object.prototype.propertyIsEnumerable;
2733var Options_defNormalProp = (obj, key, value) => key in obj ? Options_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2734var Options_spreadValues = (a, b) => {
2735 for (var prop in b || (b = {}))
2736 if (Options_hasOwnProp.call(b, prop))
2737 Options_defNormalProp(a, prop, b[prop]);
2738 if (Options_getOwnPropSymbols)
2739 for (var prop of Options_getOwnPropSymbols(b)) {
2740 if (Options_propIsEnum.call(b, prop))
2741 Options_defNormalProp(a, prop, b[prop]);
2742 }
2743 return a;
2744};
2745var __publicField = (obj, key, value) => Options_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755const _Options = class _Options {
2756 static setOptions(options) {
2757 this.data = options.reduce((a, c) => Options_spreadValues(Options_spreadValues({}, a), c), this.data);
2758 }
2759 constructor() {
2760 return deepClone(
2761 main,
2762 boost,
2763 data,
2764 color,
2765 interaction,
2766 legend,
2767 title,
2768 tooltip,
2769 _Options.data
2770 );
2771 }
2772};
2773__publicField(_Options, "data", {});
2774let Options = _Options;
2775
2776
2777;// ./src/config/Store/Element.ts
2778class Element {
2779 constructor() {
2780 const element = {
2781 chart: null,
2782 main: null,
2783 svg: null,
2784 axis: {
2785 // axes
2786 x: null,
2787 y: null,
2788 y2: null,
2789 subX: null
2790 },
2791 axisTooltip: {
2792 x: null,
2793 y: null,
2794 y2: null
2795 },
2796 defs: null,
2797 tooltip: null,
2798 legend: null,
2799 title: null,
2800 subchart: {
2801 main: null,
2802 // $$.context
2803 bar: null,
2804 // $$.contextBar
2805 line: null,
2806 // $$.contextLine
2807 area: null
2808 // $$.contextArea
2809 },
2810 arcs: null,
2811 bar: null,
2812 // mainBar,
2813 candlestick: null,
2814 line: null,
2815 // mainLine,
2816 area: null,
2817 // mainArea,
2818 circle: null,
2819 // mainCircle,
2820 radar: null,
2821 text: null,
2822 // mainText,
2823 grid: {
2824 main: null,
2825 // grid (also focus)
2826 x: null,
2827 // xgrid,
2828 y: null
2829 // ygrid,
2830 },
2831 gridLines: {
2832 main: null,
2833 // gridLines
2834 x: null,
2835 // xgridLines,
2836 y: null
2837 // ygridLines
2838 },
2839 region: {
2840 main: null,
2841 // region
2842 list: null
2843 // mainRegion
2844 },
2845 eventRect: null,
2846 zoomResetBtn: null
2847 // drag zoom reset button
2848 };
2849 return element;
2850 }
2851}
2852
2853;// ./src/config/Store/State.ts
2854class State {
2855 constructor() {
2856 return {
2857 // chart drawn area dimension, excluding axes
2858 width: 0,
2859 width2: 0,
2860 height: 0,
2861 height2: 0,
2862 margin: {
2863 top: 0,
2864 bottom: 0,
2865 left: 0,
2866 right: 0
2867 },
2868 margin2: {
2869 top: 0,
2870 bottom: 0,
2871 left: 0,
2872 right: 0
2873 },
2874 margin3: {
2875 top: 0,
2876 bottom: 0,
2877 left: 0,
2878 right: 0
2879 },
2880 arcWidth: 0,
2881 arcHeight: 0,
2882 xAxisHeight: 0,
2883 hasAxis: false,
2884 hasFunnel: false,
2885 hasRadar: false,
2886 hasTreemap: false,
2887 // for data CSS rule index (used when boost.useCssRule is true)
2888 cssRule: {},
2889 current: {
2890 // current domain value. Assigned when is zoom is called
2891 domain: void 0,
2892 // chart whole dimension
2893 width: 0,
2894 height: 0,
2895 dataMax: 0,
2896 maxTickSize: {
2897 x: {
2898 width: 0,
2899 height: 0,
2900 ticks: [],
2901 clipPath: 0,
2902 domain: ""
2903 },
2904 y: { width: 0, height: 0, domain: "" },
2905 y2: { width: 0, height: 0, domain: "" }
2906 },
2907 // current used chart type list
2908 types: [],
2909 needle: void 0
2910 // arc needle current value
2911 },
2912 // legend
2913 isLegendRight: false,
2914 isLegendInset: false,
2915 isLegendTop: false,
2916 isLegendLeft: false,
2917 legendStep: 0,
2918 legendItemWidth: 0,
2919 legendItemHeight: 0,
2920 legendHasRendered: false,
2921 eventReceiver: {
2922 currentIdx: -1,
2923 // current event interaction index
2924 rect: {},
2925 // event rect's clientBoundingRect
2926 data: [],
2927 // event data bound of previoous eventRect
2928 coords: []
2929 // coordination value of previous eventRect
2930 },
2931 axis: {
2932 x: {
2933 padding: { left: 0, right: 0 },
2934 tickCount: 0
2935 }
2936 },
2937 rotatedPadding: {
2938 left: 30,
2939 right: 0,
2940 top: 5
2941 },
2942 withoutFadeIn: {},
2943 inputType: "",
2944 datetimeId: "",
2945 // clip id string
2946 clip: {
2947 id: "",
2948 idXAxis: "",
2949 idYAxis: "",
2950 idXAxisTickTexts: "",
2951 idGrid: "",
2952 idSubchart: "",
2953 // clipIdForSubchart
2954 path: "",
2955 pathXAxis: "",
2956 pathYAxis: "",
2957 pathXAxisTickTexts: "",
2958 pathGrid: ""
2959 },
2960 // state
2961 event: null,
2962 // event object
2963 dragStart: null,
2964 dragging: false,
2965 flowing: false,
2966 cancelClick: false,
2967 mouseover: false,
2968 rendered: false,
2969 transiting: false,
2970 redrawing: false,
2971 // if redraw() is on process
2972 resizing: false,
2973 // resize event called
2974 toggling: false,
2975 // legend toggle
2976 zooming: false,
2977 hasNegativeValue: false,
2978 hasPositiveValue: true,
2979 orgAreaOpacity: "0.2",
2980 orgConfig: {},
2981 // user original genration config
2982 // ID strings
2983 hiddenTargetIds: [],
2984 hiddenLegendIds: [],
2985 focusedTargetIds: [],
2986 defocusedTargetIds: [],
2987 // value for Arc
2988 radius: 0,
2989 innerRadius: 0,
2990 outerRadius: void 0,
2991 innerRadiusRatio: 0,
2992 gaugeArcWidth: 0,
2993 radiusExpanded: 0,
2994 // xgrid attribute
2995 xgridAttr: {
2996 x1: null,
2997 x2: null,
2998 y1: null,
2999 y2: null
3000 }
3001 };
3002 }
3003}
3004
3005;// ./src/config/Store/Store.ts
3006
3007
3008const Store_classes = {
3009 element: Element,
3010 state: State
3011};
3012class Store {
3013 constructor() {
3014 Object.keys(Store_classes).forEach((v) => {
3015 this[v] = new Store_classes[v]();
3016 });
3017 }
3018 getStore(name) {
3019 return this[name];
3020 }
3021}
3022
3023;// ./src/module/Cache.ts
3024var Cache_defProp = Object.defineProperty;
3025var Cache_defNormalProp = (obj, key, value) => key in obj ? Cache_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3026var Cache_publicField = (obj, key, value) => Cache_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
3027
3028const KEY = {
3029 bubbleBaseLength: "$baseLength",
3030 colorPattern: "__colorPattern__",
3031 dataMinMax: "$dataMinMax",
3032 dataTotalSum: "$dataTotalSum",
3033 dataTotalPerIndex: "$totalPerIndex",
3034 legendItemTextBox: "legendItemTextBox",
3035 radarPoints: "$radarPoints",
3036 radarTextWidth: "$radarTextWidth",
3037 setOverOut: "setOverOut",
3038 callOverOutForTouch: "callOverOutForTouch",
3039 textRect: "textRect"
3040};
3041class Cache {
3042 constructor() {
3043 Cache_publicField(this, "cache", {});
3044 }
3045 /**
3046 * Add cache
3047 * @param {string} key Cache key
3048 * @param {*} value Value to be stored
3049 * @param {boolean} isDataType Weather the cache is data typed '{id:'data', id_org: 'data', values: [{x:0, index:0,...}, ...]}'
3050 * @returns {*} Added data value
3051 * @private
3052 */
3053 add(key, value, isDataType = false) {
3054 this.cache[key] = isDataType ? this.cloneTarget(value) : value;
3055 return this.cache[key];
3056 }
3057 /**
3058 * Remove cache
3059 * @param {string|Array} key Cache key
3060 * @private
3061 */
3062 remove(key) {
3063 (isString(key) ? [key] : key).forEach((v) => delete this.cache[v]);
3064 }
3065 /**
3066 * Get cahce
3067 * @param {string|Array} key Cache key
3068 * @param {boolean} isDataType Weather the cache is data typed '{id:'data', id_org: 'data', values: [{x:0, index:0,...}, ...]}'
3069 * @returns {*}
3070 * @private
3071 */
3072 get(key, isDataType = false) {
3073 if (isDataType && Array.isArray(key)) {
3074 const targets = [];
3075 for (let i = 0, id; id = key[i]; i++) {
3076 if (id in this.cache) {
3077 targets.push(this.cloneTarget(this.cache[id]));
3078 }
3079 }
3080 return targets;
3081 } else {
3082 const value = this.cache[key];
3083 return isValue(value) ? value : null;
3084 }
3085 }
3086 /**
3087 * Reset cached data
3088 * @param {boolean} all true: reset all data, false: reset only '$' prefixed key data
3089 * @private
3090 */
3091 reset(all) {
3092 const $$ = this;
3093 for (const x in $$.cache) {
3094 if (all || /^\$/.test(x)) {
3095 $$.cache[x] = null;
3096 }
3097 }
3098 }
3099 /**
3100 * Clone data target object
3101 * @param {object} target Data object
3102 * @returns {object}
3103 * @private
3104 */
3105 cloneTarget(target) {
3106 return {
3107 id: target.id,
3108 id_org: target.id_org,
3109 values: target.values.map((d) => ({ x: d.x, value: d.value, id: d.id }))
3110 };
3111 }
3112}
3113
3114;// ./src/config/const.ts
3115const TYPE = {
3116 AREA: "area",
3117 AREA_LINE_RANGE: "area-line-range",
3118 AREA_SPLINE: "area-spline",
3119 AREA_SPLINE_RANGE: "area-spline-range",
3120 AREA_STEP: "area-step",
3121 AREA_STEP_RANGE: "area-step-range",
3122 BAR: "bar",
3123 BUBBLE: "bubble",
3124 CANDLESTICK: "candlestick",
3125 DONUT: "donut",
3126 FUNNEL: "funnel",
3127 GAUGE: "gauge",
3128 LINE: "line",
3129 PIE: "pie",
3130 POLAR: "polar",
3131 RADAR: "radar",
3132 SCATTER: "scatter",
3133 SPLINE: "spline",
3134 STEP: "step",
3135 TREEMAP: "treemap"
3136};
3137const TYPE_METHOD_NEEDED = {
3138 AREA: "initArea",
3139 AREA_LINE_RANGE: "initArea",
3140 AREA_SPLINE: "initArea",
3141 AREA_SPLINE_RANGE: "initArea",
3142 AREA_STEP: "initArea",
3143 AREA_STEP_RANGE: "initArea",
3144 BAR: "initBar",
3145 BUBBLE: "initCircle",
3146 CANDLESTICK: "initCandlestick",
3147 DONUT: "initArc",
3148 FUNNEL: "initFunnel",
3149 GAUGE: "initArc",
3150 LINE: "initLine",
3151 PIE: "initArc",
3152 POLAR: "initPolar",
3153 RADAR: "initCircle",
3154 SCATTER: "initCircle",
3155 SPLINE: "initLine",
3156 STEP: "initLine",
3157 TREEMAP: "initTreemap"
3158};
3159const TYPE_BY_CATEGORY = {
3160 Area: [
3161 TYPE.AREA,
3162 TYPE.AREA_SPLINE,
3163 TYPE.AREA_SPLINE_RANGE,
3164 TYPE.AREA_LINE_RANGE,
3165 TYPE.AREA_STEP,
3166 TYPE.AREA_STEP_RANGE
3167 ],
3168 AreaRange: [
3169 TYPE.AREA_SPLINE_RANGE,
3170 TYPE.AREA_LINE_RANGE,
3171 TYPE.AREA_STEP_RANGE
3172 ],
3173 Arc: [
3174 TYPE.PIE,
3175 TYPE.DONUT,
3176 TYPE.GAUGE,
3177 TYPE.POLAR,
3178 TYPE.RADAR
3179 ],
3180 Line: [
3181 TYPE.LINE,
3182 TYPE.SPLINE,
3183 TYPE.AREA,
3184 TYPE.AREA_SPLINE,
3185 TYPE.AREA_SPLINE_RANGE,
3186 TYPE.AREA_LINE_RANGE,
3187 TYPE.STEP,
3188 TYPE.AREA_STEP,
3189 TYPE.AREA_STEP_RANGE
3190 ],
3191 Step: [
3192 TYPE.STEP,
3193 TYPE.AREA_STEP,
3194 TYPE.AREA_STEP_RANGE
3195 ],
3196 Spline: [
3197 TYPE.SPLINE,
3198 TYPE.AREA_SPLINE,
3199 TYPE.AREA_SPLINE_RANGE
3200 ]
3201};
3202
3203;// ./src/module/error.ts
3204
3205
3206
3207
3208function checkModuleImport(ctx) {
3209 const $$ = ctx;
3210 const { config } = $$;
3211 let type = "";
3212 if (isEmpty(config.data_type || config.data_types) && !$$[TYPE_METHOD_NEEDED.LINE]) {
3213 type = "line";
3214 } else {
3215 for (const x in TYPE_METHOD_NEEDED) {
3216 const t = TYPE[x];
3217 if ($$.hasType(t) && !$$[TYPE_METHOD_NEEDED[x]]) {
3218 type = t;
3219 break;
3220 }
3221 }
3222 }
3223 type && logError(
3224 `Please, make sure if %c${camelize(type)}`,
3225 "module has been imported and specified correctly.",
3226 "https://github.com/naver/billboard.js/wiki/CHANGELOG-v2#modularization-by-its-functionality"
3227 );
3228}
3229function logError(head, tail, info) {
3230 var _a;
3231 const prefix = "[billboard.js]";
3232 const hasConsole = (_a = win.console) == null ? void 0 : _a.error;
3233 if (hasConsole) {
3234 const tailMsg = tail ? ["background:red;color:white;display:block;font-size:15px", tail] : [];
3235 console.error(
3236 `\u274C ${prefix} ${head}`,
3237 "background:red;color:white;display:block;font-size:15px",
3238 ...tailMsg
3239 );
3240 info && console.info("%c\u2139\uFE0F", "font-size:15px", info);
3241 }
3242 throw Error(`${prefix} ${head.replace(/\%c([a-z-]+)/i, "'$1' ")} ${tail != null ? tail : ""}`);
3243}
3244
3245;// ./src/module/generator.ts
3246
3247
3248const { setTimeout: generator_setTimeout, clearTimeout: generator_clearTimeout } = win;
3249function generateResize(option) {
3250 const fn = [];
3251 let timeout;
3252 const callResizeFn = function() {
3253 callResizeFn.clear();
3254 if (option === false) {
3255 requestIdleCallback(() => {
3256 fn.forEach((f) => f());
3257 }, { timeout: 200 });
3258 } else {
3259 timeout = generator_setTimeout(() => {
3260 fn.forEach((f) => f());
3261 }, isNumber(option) ? option : 200);
3262 }
3263 };
3264 callResizeFn.clear = () => {
3265 if (timeout) {
3266 generator_clearTimeout(timeout);
3267 timeout = null;
3268 }
3269 };
3270 callResizeFn.add = (f) => fn.push(f);
3271 callResizeFn.remove = (f) => fn.splice(fn.indexOf(f), 1);
3272 return callResizeFn;
3273}
3274function generateWait() {
3275 let transitionsToWait = [];
3276 const f = function(selection, callback) {
3277 function loop() {
3278 var _a;
3279 let done = 0;
3280 for (let i = 0, t; t = transitionsToWait[i]; i++) {
3281 if (t === true || ((_a = t.empty) == null ? void 0 : _a.call(t))) {
3282 done++;
3283 continue;
3284 }
3285 if (isTabVisible() === false) {
3286 done = transitionsToWait.length;
3287 break;
3288 }
3289 try {
3290 t.transition();
3291 } catch (e) {
3292 done++;
3293 }
3294 }
3295 return done === transitionsToWait.length;
3296 }
3297 runUntil(() => {
3298 callback == null ? void 0 : callback();
3299 }, loop);
3300 };
3301 f.add = function(t) {
3302 isArray(t) ? transitionsToWait = transitionsToWait.concat(t) : transitionsToWait.push(t);
3303 };
3304 return f;
3305}
3306
3307;// ./src/module/worker.ts
3308
3309const blob = {};
3310function getObjectURL(fn, depsFn) {
3311 var _a;
3312 const fnString = fn.toString();
3313 const key = fnString.replace(/(function|[\s\W\n])/g, "").substring(0, 15);
3314 if (!(key in blob)) {
3315 blob[key] = new win.Blob([
3316 `${(_a = depsFn == null ? void 0 : depsFn.map(String).join(";")) != null ? _a : ""}
3317
3318 self.onmessage=function({data}) {
3319 const result = (${fnString}).apply(null, data);
3320 self.postMessage(result);
3321 };`
3322 ], {
3323 type: "text/javascript"
3324 });
3325 }
3326 return win.URL.createObjectURL(blob[key]);
3327}
3328function getWorker(src) {
3329 const worker = new win.Worker(src);
3330 worker.onerror = function(e) {
3331 console.error ? console.error(e) : console.log(e);
3332 };
3333 return worker;
3334}
3335function runWorker(useWorker = true, fn, callback, depsFn) {
3336 let runFn = function(...args) {
3337 const res = fn(...args);
3338 callback(res);
3339 };
3340 if (win.Worker && useWorker) {
3341 const src = getObjectURL(fn, depsFn);
3342 const worker = getWorker(src);
3343 runFn = function(...args) {
3344 worker.postMessage(args);
3345 worker.onmessage = function(e) {
3346 win.URL.revokeObjectURL(src);
3347 return callback(e.data);
3348 };
3349 };
3350 }
3351 return runFn;
3352}
3353
3354// EXTERNAL MODULE: external {"commonjs":"d3-dsv","commonjs2":"d3-dsv","amd":"d3-dsv","root":"d3"}
3355var external_commonjs_d3_dsv_commonjs2_d3_dsv_amd_d3_dsv_root_d3_ = __webpack_require__(5);
3356;// ./src/ChartInternal/data/convert.helper.ts
3357
3358
3359function columns(columns2) {
3360 const newRows = [];
3361 columns2.forEach(function(col, i) {
3362 const key = col[0];
3363 col.forEach(function(v, j) {
3364 if (j > 0) {
3365 if (typeof newRows[j - 1] === "undefined") {
3366 newRows[j - 1] = {};
3367 }
3368 if (typeof v === "undefined") {
3369 throw new Error(`Source data is missing a component at (${i}, ${j})!`);
3370 }
3371 newRows[j - 1][key] = v;
3372 }
3373 });
3374 });
3375 return newRows;
3376}
3377function rows(rows2) {
3378 const keys = rows2[0];
3379 const newRows = [];
3380 rows2.forEach(function(row, i) {
3381 if (i > 0) {
3382 const newRow = {};
3383 row.forEach(function(v, j) {
3384 if (typeof v === "undefined") {
3385 throw new Error(`Source data is missing a component at (${i}, ${j})!`);
3386 }
3387 newRow[keys[j]] = v;
3388 });
3389 newRows.push(newRow);
3390 }
3391 });
3392 return newRows;
3393}
3394function json(json2, keysParam) {
3395 const newRows = [];
3396 let targetKeys;
3397 let data;
3398 if (Array.isArray(json2)) {
3399 const findValueInJson = function(object, path) {
3400 if (object[path] !== void 0) {
3401 return object[path];
3402 }
3403 const convertedPath = path.replace(/\[(\w+)\]/g, ".$1");
3404 const pathArray = convertedPath.replace(/^\./, "").split(".");
3405 let target = object;
3406 pathArray.some(function(k) {
3407 return !(target = target && k in target ? target[k] : void 0);
3408 });
3409 return target;
3410 };
3411 if (keysParam.x) {
3412 targetKeys = keysParam.value.concat(keysParam.x);
3413 } else {
3414 targetKeys = keysParam.value;
3415 }
3416 newRows.push(targetKeys);
3417 json2.forEach(function(o) {
3418 const newRow = targetKeys.map(function(key) {
3419 let v = findValueInJson(o, key);
3420 if (typeof v === "undefined") {
3421 v = null;
3422 }
3423 return v;
3424 });
3425 newRows.push(newRow);
3426 });
3427 data = rows(newRows);
3428 } else {
3429 Object.keys(json2).forEach(function(key) {
3430 var _a;
3431 const tmp = json2[key].concat();
3432 (_a = tmp.unshift) == null ? void 0 : _a.call(tmp, key);
3433 newRows.push(tmp);
3434 });
3435 data = columns(newRows);
3436 }
3437 return data;
3438}
3439function url(url2, mimeType = "csv", headers, keys, done) {
3440 const req = new XMLHttpRequest();
3441 const converter = { csv, tsv, json };
3442 req.open("GET", url2);
3443 if (headers) {
3444 Object.keys(headers).forEach(function(key) {
3445 req.setRequestHeader(key, headers[key]);
3446 });
3447 }
3448 req.onreadystatechange = function() {
3449 if (req.readyState === 4) {
3450 if (req.status === 200) {
3451 const response = req.responseText;
3452 response && done.call(this, converter[mimeType](
3453 mimeType === "json" ? JSON.parse(response) : response,
3454 keys
3455 ));
3456 } else {
3457 throw new Error(`${url2}: Something went wrong loading!`);
3458 }
3459 }
3460 };
3461 req.send();
3462}
3463function convertCsvTsvToData(parser, xsv) {
3464 const rows2 = parser.rows(xsv);
3465 let d;
3466 if (rows2.length === 1) {
3467 d = [{}];
3468 rows2[0].forEach((id) => {
3469 d[0][id] = null;
3470 });
3471 } else {
3472 d = parser.parse(xsv);
3473 }
3474 return d;
3475}
3476function csv(xsv) {
3477 return convertCsvTsvToData({
3478 rows: external_commonjs_d3_dsv_commonjs2_d3_dsv_amd_d3_dsv_root_d3_.csvParseRows,
3479 parse: external_commonjs_d3_dsv_commonjs2_d3_dsv_amd_d3_dsv_root_d3_.csvParse
3480 }, xsv);
3481}
3482function tsv(tsv2) {
3483 return convertCsvTsvToData({
3484 rows: external_commonjs_d3_dsv_commonjs2_d3_dsv_amd_d3_dsv_root_d3_.tsvParseRows,
3485 parse: external_commonjs_d3_dsv_commonjs2_d3_dsv_amd_d3_dsv_root_d3_.tsvParse
3486 }, tsv2);
3487}
3488
3489;// ./src/ChartInternal/data/convert.ts
3490
3491
3492
3493function getDataKeyForJson(keysParam, config) {
3494 const keys = keysParam || (config == null ? void 0 : config.data_keys);
3495 if (keys == null ? void 0 : keys.x) {
3496 config.data_x = keys.x;
3497 }
3498 return keys;
3499}
3500/* harmony default export */ var convert = ({
3501 /**
3502 * Convert data according its type
3503 * @param {object} args data object
3504 * @param {Function} [callback] callback for url(XHR) type loading
3505 * @private
3506 */
3507 convertData(args, callback) {
3508 const { config } = this;
3509 const useWorker = config.boost_useWorker;
3510 let data = args;
3511 if (args.bindto) {
3512 data = {};
3513 ["url", "mimeType", "headers", "keys", "json", "keys", "rows", "columns"].forEach((v) => {
3514 const key = `data_${v}`;
3515 if (key in args) {
3516 data[v] = args[key];
3517 }
3518 });
3519 }
3520 if (data.url && callback) {
3521 url(
3522 data.url,
3523 data.mimeType,
3524 data.headers,
3525 getDataKeyForJson(data.keys, config),
3526 callback
3527 );
3528 } else if (data.json) {
3529 runWorker(useWorker, json, callback, [columns, rows])(
3530 data.json,
3531 getDataKeyForJson(data.keys, config)
3532 );
3533 } else if (data.rows) {
3534 runWorker(useWorker, rows, callback)(data.rows);
3535 } else if (data.columns) {
3536 runWorker(useWorker, columns, callback)(data.columns);
3537 } else if (args.bindto) {
3538 throw Error("url or json or rows or columns is required.");
3539 }
3540 },
3541 convertDataToTargets(data, appendXs) {
3542 const $$ = this;
3543 const { axis, config, state } = $$;
3544 const chartType = config.data_type;
3545 let isCategorized = false;
3546 let isTimeSeries = false;
3547 let isCustomX = false;
3548 if (axis) {
3549 isCategorized = axis.isCategorized();
3550 isTimeSeries = axis.isTimeSeries();
3551 isCustomX = axis.isCustomX();
3552 }
3553 const dataKeys = Object.keys(data[0] || {});
3554 const ids = dataKeys.length ? dataKeys.filter($$.isNotX, $$) : [];
3555 const xs = dataKeys.length ? dataKeys.filter($$.isX, $$) : [];
3556 let xsData;
3557 ids.forEach((id) => {
3558 const xKey = this.getXKey(id);
3559 if (isCustomX || isTimeSeries) {
3560 if (xs.indexOf(xKey) >= 0) {
3561 xsData = (appendXs && $$.data.xs[id] || []).concat(
3562 data.map((d) => d[xKey]).filter(isValue).map((rawX, i) => $$.generateTargetX(rawX, id, i))
3563 );
3564 } else if (config.data_x) {
3565 xsData = this.getOtherTargetXs();
3566 } else if (notEmpty(config.data_xs)) {
3567 xsData = $$.getXValuesOfXKey(xKey, $$.data.targets);
3568 }
3569 } else {
3570 xsData = data.map((d, i) => i);
3571 }
3572 xsData && (this.data.xs[id] = xsData);
3573 });
3574 ids.forEach((id) => {
3575 if (!this.data.xs[id]) {
3576 throw new Error(`x is not defined for id = "${id}".`);
3577 }
3578 });
3579 const targets = ids.map((id, index) => {
3580 const convertedId = config.data_idConverter.bind($$.api)(id);
3581 const xKey = $$.getXKey(id);
3582 const isCategory = isCustomX && isCategorized;
3583 const hasCategory = isCategory && data.map((v) => v.x).every((v) => config.axis_x_categories.indexOf(v) > -1);
3584 const isDataAppend = data.__append__;
3585 const xIndex = xKey === null && isDataAppend ? $$.api.data.values(id).length : 0;
3586 return {
3587 id: convertedId,
3588 id_org: id,
3589 values: data.map((d, i) => {
3590 const rawX = d[xKey];
3591 let value = d[id];
3592 let x;
3593 value = value !== null && !isNaN(value) && !isObject(value) ? +value : isArray(value) || isObject(value) ? value : null;
3594 if ((isCategory || state.hasRadar) && index === 0 && !isUndefined(rawX)) {
3595 if (!hasCategory && index === 0 && i === 0 && !isDataAppend) {
3596 config.axis_x_categories = [];
3597 }
3598 x = config.axis_x_categories.indexOf(rawX);
3599 if (x === -1) {
3600 x = config.axis_x_categories.length;
3601 config.axis_x_categories.push(rawX);
3602 }
3603 } else {
3604 x = $$.generateTargetX(rawX, id, xIndex + i);
3605 }
3606 if (isUndefined(value) || $$.data.xs[id].length <= i) {
3607 x = void 0;
3608 }
3609 return {
3610 x,
3611 value,
3612 id: convertedId,
3613 index: -1
3614 };
3615 }).filter((v) => isDefined(v.x))
3616 };
3617 });
3618 targets.forEach((t) => {
3619 var _a;
3620 if (config.data_xSort) {
3621 t.values = t.values.sort((v1, v2) => {
3622 const x1 = v1.x || v1.x === 0 ? v1.x : Infinity;
3623 const x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
3624 return x1 - x2;
3625 });
3626 }
3627 t.values.forEach((v, i) => v.index = i);
3628 (_a = $$.data.xs[t.id]) == null ? void 0 : _a.sort((v1, v2) => v1 - v2);
3629 });
3630 state.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
3631 state.hasPositiveValue = $$.hasPositiveValueInTargets(targets);
3632 if (chartType && $$.isValidChartType(chartType)) {
3633 const targetIds = $$.mapToIds(targets).filter(
3634 (id) => !(id in config.data_types) || !$$.isValidChartType(config.data_types[id])
3635 );
3636 $$.setTargetType(targetIds, chartType);
3637 }
3638 targets.forEach((d) => $$.cache.add(d.id_org, d, true));
3639 return targets;
3640 }
3641});
3642
3643;// ./src/ChartInternal/data/data.ts
3644
3645
3646
3647
3648/* harmony default export */ var data_data = ({
3649 isX(key) {
3650 const $$ = this;
3651 const { config } = $$;
3652 const dataKey = config.data_x && key === config.data_x;
3653 const existValue = notEmpty(config.data_xs) && hasValue(config.data_xs, key);
3654 return dataKey || existValue;
3655 },
3656 isNotX(key) {
3657 return !this.isX(key);
3658 },
3659 isStackNormalized() {
3660 const { config } = this;
3661 return !!(config.data_stack_normalize && config.data_groups.length);
3662 },
3663 /**
3664 * Check if given id is grouped data or has grouped data
3665 * @param {string} id Data id value
3666 * @returns {boolean} is grouped data or has grouped data
3667 * @private
3668 */
3669 isGrouped(id) {
3670 const groups = this.config.data_groups;
3671 return id ? groups.some((v) => v.indexOf(id) >= 0 && v.length > 1) : groups.length > 0;
3672 },
3673 getXKey(id) {
3674 const $$ = this;
3675 const { config } = $$;
3676 return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
3677 },
3678 getXValuesOfXKey(key, targets) {
3679 const $$ = this;
3680 const ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
3681 let xValues;
3682 ids.forEach((id) => {
3683 if ($$.getXKey(id) === key) {
3684 xValues = $$.data.xs[id];
3685 }
3686 });
3687 return xValues;
3688 },
3689 /**
3690 * Get index number based on given x Axis value
3691 * @param {Date|number|string} x x Axis to be compared
3692 * @param {Array} basedX x Axis list to be based on
3693 * @returns {number} index number
3694 * @private
3695 */
3696 getIndexByX(x, basedX) {
3697 const $$ = this;
3698 return basedX ? basedX.indexOf(isString(x) ? x : +x) : ($$.filterByX($$.data.targets, x)[0] || { index: null }).index;
3699 },
3700 getXValue(id, i) {
3701 const $$ = this;
3702 return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
3703 },
3704 getOtherTargetXs() {
3705 const $$ = this;
3706 const idsForX = Object.keys($$.data.xs);
3707 return idsForX.length ? $$.data.xs[idsForX[0]] : null;
3708 },
3709 getOtherTargetX(index) {
3710 const xs = this.getOtherTargetXs();
3711 return xs && index < xs.length ? xs[index] : null;
3712 },
3713 addXs(xs) {
3714 const $$ = this;
3715 const { config } = $$;
3716 Object.keys(xs).forEach((id) => {
3717 config.data_xs[id] = xs[id];
3718 });
3719 },
3720 /**
3721 * Determine if x axis is multiple
3722 * @returns {boolean} true: multiple, false: single
3723 * @private
3724 */
3725 isMultipleX() {
3726 return !this.config.axis_x_forceAsSingle && (notEmpty(this.config.data_xs) || this.hasType("bubble") || this.hasType("scatter"));
3727 },
3728 addName(data) {
3729 const $$ = this;
3730 const { config } = $$;
3731 let name;
3732 if (data) {
3733 name = config.data_names[data.id];
3734 data.name = name !== void 0 ? name : data.id;
3735 }
3736 return data;
3737 },
3738 /**
3739 * Get all values on given index
3740 * @param {number} index Index
3741 * @param {boolean} filterNull Filter nullish value
3742 * @returns {Array}
3743 * @private
3744 */
3745 getAllValuesOnIndex(index, filterNull = false) {
3746 const $$ = this;
3747 let value = $$.filterTargetsToShow($$.data.targets).map((t) => $$.addName($$.getValueOnIndex(t.values, index)));
3748 if (filterNull) {
3749 value = value.filter((v) => v && "value" in v && isValue(v.value));
3750 }
3751 return value;
3752 },
3753 getValueOnIndex(values, index) {
3754 const valueOnIndex = values.filter((v) => v.index === index);
3755 return valueOnIndex.length ? valueOnIndex[0] : null;
3756 },
3757 updateTargetX(targets, x) {
3758 const $$ = this;
3759 targets.forEach((t) => {
3760 t.values.forEach((v, i) => {
3761 v.x = $$.generateTargetX(x[i], t.id, i);
3762 });
3763 $$.data.xs[t.id] = x;
3764 });
3765 },
3766 updateTargetXs(targets, xs) {
3767 const $$ = this;
3768 targets.forEach((t) => {
3769 xs[t.id] && $$.updateTargetX([t], xs[t.id]);
3770 });
3771 },
3772 generateTargetX(rawX, id, index) {
3773 const $$ = this;
3774 const { axis } = $$;
3775 let x = (axis == null ? void 0 : axis.isCategorized()) ? index : rawX || index;
3776 if (axis == null ? void 0 : axis.isTimeSeries()) {
3777 const fn = parseDate.bind($$);
3778 x = rawX ? fn(rawX) : fn($$.getXValue(id, index));
3779 } else if ((axis == null ? void 0 : axis.isCustomX()) && !(axis == null ? void 0 : axis.isCategorized())) {
3780 x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
3781 }
3782 return x;
3783 },
3784 updateXs(values) {
3785 if (values.length) {
3786 this.axis.xs = values.map((v) => v.x);
3787 }
3788 },
3789 getPrevX(i) {
3790 const x = this.axis.xs[i - 1];
3791 return isDefined(x) ? x : null;
3792 },
3793 getNextX(i) {
3794 const x = this.axis.xs[i + 1];
3795 return isDefined(x) ? x : null;
3796 },
3797 /**
3798 * Get base value isAreaRangeType
3799 * @param {object} data Data object
3800 * @returns {number}
3801 * @private
3802 */
3803 getBaseValue(data) {
3804 const $$ = this;
3805 const { hasAxis } = $$.state;
3806 let { value } = data;
3807 if (value && hasAxis) {
3808 if ($$.isAreaRangeType(data)) {
3809 value = $$.getRangedData(data, "mid");
3810 } else if ($$.isBubbleZType(data)) {
3811 value = $$.getBubbleZData(value, "y");
3812 }
3813 }
3814 return value;
3815 },
3816 /**
3817 * Get min/max value from the data
3818 * @private
3819 * @param {Array} data array data to be evaluated
3820 * @returns {{min: {number}, max: {number}}}
3821 */
3822 getMinMaxValue(data) {
3823 const getBaseValue = this.getBaseValue.bind(this);
3824 let min;
3825 let max;
3826 (data || this.data.targets.map((t) => t.values)).forEach((v, i) => {
3827 const value = v.map(getBaseValue).filter(isNumber);
3828 min = Math.min(i ? min : Infinity, ...value);
3829 max = Math.max(i ? max : -Infinity, ...value);
3830 });
3831 return { min, max };
3832 },
3833 /**
3834 * Get the min/max data
3835 * @private
3836 * @returns {{min: Array, max: Array}}
3837 */
3838 getMinMaxData() {
3839 const $$ = this;
3840 const cacheKey = KEY.dataMinMax;
3841 let minMaxData = $$.cache.get(cacheKey);
3842 if (!minMaxData) {
3843 const data = $$.data.targets.map((t) => t.values);
3844 const minMax = $$.getMinMaxValue(data);
3845 let min = [];
3846 let max = [];
3847 data.forEach((v) => {
3848 const minData = $$.getFilteredDataByValue(v, minMax.min);
3849 const maxData = $$.getFilteredDataByValue(v, minMax.max);
3850 if (minData.length) {
3851 min = min.concat(minData);
3852 }
3853 if (maxData.length) {
3854 max = max.concat(maxData);
3855 }
3856 });
3857 $$.cache.add(cacheKey, minMaxData = { min, max });
3858 }
3859 return minMaxData;
3860 },
3861 /**
3862 * Get sum of data per index
3863 * @private
3864 * @returns {Array}
3865 */
3866 getTotalPerIndex() {
3867 const $$ = this;
3868 const cacheKey = KEY.dataTotalPerIndex;
3869 let sum = $$.cache.get(cacheKey);
3870 if (($$.config.data_groups.length || $$.isStackNormalized()) && !sum) {
3871 sum = [];
3872 $$.data.targets.forEach((row) => {
3873 row.values.forEach((v, i) => {
3874 if (!sum[i]) {
3875 sum[i] = 0;
3876 }
3877 sum[i] += isNumber(v.value) ? v.value : 0;
3878 });
3879 });
3880 }
3881 return sum;
3882 },
3883 /**
3884 * Get total data sum
3885 * @param {boolean} subtractHidden Subtract hidden data from total
3886 * @returns {number}
3887 * @private
3888 */
3889 getTotalDataSum(subtractHidden) {
3890 const $$ = this;
3891 const cacheKey = KEY.dataTotalSum;
3892 let total = $$.cache.get(cacheKey);
3893 if (!isNumber(total)) {
3894 const sum = mergeArray($$.data.targets.map((t) => t.values)).map((v) => v.value);
3895 total = sum.length ? sum.reduce((p, c) => p + c) : 0;
3896 $$.cache.add(cacheKey, total);
3897 }
3898 if (subtractHidden) {
3899 total -= $$.getHiddenTotalDataSum();
3900 }
3901 return total;
3902 },
3903 /**
3904 * Get total hidden data sum
3905 * @returns {number}
3906 * @private
3907 */
3908 getHiddenTotalDataSum() {
3909 const $$ = this;
3910 const { api, state: { hiddenTargetIds } } = $$;
3911 let total = 0;
3912 if (hiddenTargetIds.length) {
3913 total = api.data.values.bind(api)(hiddenTargetIds).reduce((p, c) => p + c);
3914 }
3915 return total;
3916 },
3917 /**
3918 * Get filtered data by value
3919 * @param {object} data Data
3920 * @param {number} value Value to be filtered
3921 * @returns {Array} filtered array data
3922 * @private
3923 */
3924 getFilteredDataByValue(data, value) {
3925 return data.filter((t) => this.getBaseValue(t) === value);
3926 },
3927 /**
3928 * Return the max length of the data
3929 * @returns {number} max data length
3930 * @private
3931 */
3932 getMaxDataCount() {
3933 return Math.max(...this.data.targets.map((t) => t.values.length), 0);
3934 },
3935 getMaxDataCountTarget() {
3936 let target = this.filterTargetsToShow() || [];
3937 const length = target.length;
3938 const isInverted = this.config.axis_x_inverted;
3939 if (length > 1) {
3940 target = target.map((t) => t.values).reduce((a, b) => a.concat(b)).map((v) => v.x);
3941 target = sortValue(getUnique(target)).map((x, index, array) => ({
3942 x,
3943 index: isInverted ? array.length - index - 1 : index
3944 }));
3945 } else if (length) {
3946 target = target[0].values.concat();
3947 }
3948 return target;
3949 },
3950 mapToIds(targets) {
3951 return targets.map((d) => d.id);
3952 },
3953 mapToTargetIds(ids) {
3954 const $$ = this;
3955 return ids ? isArray(ids) ? ids.concat() : [ids] : $$.mapToIds($$.data.targets);
3956 },
3957 hasTarget(targets, id) {
3958 const ids = this.mapToIds(targets);
3959 for (let i = 0, val; val = ids[i]; i++) {
3960 if (val === id) {
3961 return true;
3962 }
3963 }
3964 return false;
3965 },
3966 isTargetToShow(targetId) {
3967 return this.state.hiddenTargetIds.indexOf(targetId) < 0;
3968 },
3969 isLegendToShow(targetId) {
3970 return this.state.hiddenLegendIds.indexOf(targetId) < 0;
3971 },
3972 filterTargetsToShow(targets) {
3973 const $$ = this;
3974 return (targets || $$.data.targets).filter((t) => $$.isTargetToShow(t.id));
3975 },
3976 mapTargetsToUniqueXs(targets) {
3977 const $$ = this;
3978 const { axis } = $$;
3979 let xs = [];
3980 if (targets == null ? void 0 : targets.length) {
3981 xs = getUnique(
3982 mergeArray(targets.map((t) => t.values.map((v) => +v.x)))
3983 );
3984 xs = (axis == null ? void 0 : axis.isTimeSeries()) ? xs.map((x) => /* @__PURE__ */ new Date(+x)) : xs.map(Number);
3985 }
3986 return sortValue(xs);
3987 },
3988 /**
3989 * Add to the state target Ids
3990 * @param {string} type State's prop name
3991 * @param {Array|string} targetIds Target ids array
3992 * @private
3993 */
3994 addTargetIds(type, targetIds) {
3995 const { state } = this;
3996 const ids = isArray(targetIds) ? targetIds : [targetIds];
3997 ids.forEach((v) => {
3998 state[type].indexOf(v) < 0 && state[type].push(v);
3999 });
4000 },
4001 /**
4002 * Remove from the state target Ids
4003 * @param {string} type State's prop name
4004 * @param {Array|string} targetIds Target ids array
4005 * @private
4006 */
4007 removeTargetIds(type, targetIds) {
4008 const { state } = this;
4009 const ids = isArray(targetIds) ? targetIds : [targetIds];
4010 ids.forEach((v) => {
4011 const index = state[type].indexOf(v);
4012 index >= 0 && state[type].splice(index, 1);
4013 });
4014 },
4015 addHiddenTargetIds(targetIds) {
4016 this.addTargetIds("hiddenTargetIds", targetIds);
4017 },
4018 removeHiddenTargetIds(targetIds) {
4019 this.removeTargetIds("hiddenTargetIds", targetIds);
4020 },
4021 addHiddenLegendIds(targetIds) {
4022 this.addTargetIds("hiddenLegendIds", targetIds);
4023 },
4024 removeHiddenLegendIds(targetIds) {
4025 this.removeTargetIds("hiddenLegendIds", targetIds);
4026 },
4027 getValuesAsIdKeyed(targets) {
4028 const $$ = this;
4029 const { hasAxis } = $$.state;
4030 const ys = {};
4031 const isMultipleX = $$.isMultipleX();
4032 const xs = isMultipleX ? $$.mapTargetsToUniqueXs(targets).map((v) => isString(v) ? v : +v) : null;
4033 targets.forEach((t) => {
4034 const data = [];
4035 t.values.filter(({ value }) => isValue(value) || value === null).forEach((v) => {
4036 let { value } = v;
4037 if (value !== null && $$.isCandlestickType(v)) {
4038 value = isArray(value) ? value.slice(0, 4) : [value.open, value.high, value.low, value.close];
4039 }
4040 if (isArray(value)) {
4041 data.push(...value);
4042 } else if (isObject(value) && "high" in value) {
4043 data.push(...Object.values(value));
4044 } else if ($$.isBubbleZType(v)) {
4045 data.push(hasAxis && $$.getBubbleZData(value, "y"));
4046 } else {
4047 if (isMultipleX) {
4048 data[$$.getIndexByX(v.x, xs)] = value;
4049 } else {
4050 data.push(value);
4051 }
4052 }
4053 });
4054 ys[t.id] = data;
4055 });
4056 return ys;
4057 },
4058 checkValueInTargets(targets, checker) {
4059 const ids = Object.keys(targets);
4060 let values;
4061 for (let i = 0; i < ids.length; i++) {
4062 values = targets[ids[i]].values;
4063 for (let j = 0; j < values.length; j++) {
4064 if (checker(values[j].value)) {
4065 return true;
4066 }
4067 }
4068 }
4069 return false;
4070 },
4071 hasMultiTargets() {
4072 return this.filterTargetsToShow().length > 1;
4073 },
4074 hasNegativeValueInTargets(targets) {
4075 return this.checkValueInTargets(targets, (v) => v < 0);
4076 },
4077 hasPositiveValueInTargets(targets) {
4078 return this.checkValueInTargets(targets, (v) => v > 0);
4079 },
4080 /**
4081 * Sort targets data
4082 * Note: For stacked bar, will sort from the total sum of data series, not for each stacked bar
4083 * @param {Array} targetsValue Target value
4084 * @returns {Array}
4085 * @private
4086 */
4087 orderTargets(targetsValue) {
4088 const $$ = this;
4089 const targets = [...targetsValue];
4090 const fn = $$.getSortCompareFn();
4091 fn && targets.sort(fn);
4092 return targets;
4093 },
4094 /**
4095 * Get data.order compare function
4096 * @param {boolean} isReversed for Arc & Treemap type sort order needs to be reversed
4097 * @returns {Function} compare function
4098 * @private
4099 */
4100 getSortCompareFn(isReversed = false) {
4101 const $$ = this;
4102 const { config } = $$;
4103 const order = config.data_order;
4104 const orderAsc = /asc/i.test(order);
4105 const orderDesc = /desc/i.test(order);
4106 let fn;
4107 if (orderAsc || orderDesc) {
4108 const reducer = (p, c) => p + Math.abs(c.value);
4109 const sum = (v) => isNumber(v) ? v : "values" in v ? v.values.reduce(reducer, 0) : v.value;
4110 fn = (t1, t2) => {
4111 const t1Sum = sum(t1);
4112 const t2Sum = sum(t2);
4113 return isReversed ? orderAsc ? t1Sum - t2Sum : t2Sum - t1Sum : orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
4114 };
4115 } else if (isFunction(order)) {
4116 fn = order.bind($$.api);
4117 }
4118 return fn || null;
4119 },
4120 filterByX(targets, x) {
4121 return mergeArray(targets.map((t) => t.values)).filter((v) => v.x - x === 0);
4122 },
4123 filterRemoveNull(data) {
4124 return data.filter((d) => isValue(this.getBaseValue(d)));
4125 },
4126 filterByXDomain(targets, xDomain) {
4127 return targets.map((t) => ({
4128 id: t.id,
4129 id_org: t.id_org,
4130 values: t.values.filter((v) => xDomain[0] <= v.x && v.x <= xDomain[1])
4131 }));
4132 },
4133 hasDataLabel() {
4134 const dataLabels = this.config.data_labels;
4135 return isBoolean(dataLabels) && dataLabels || isObjectType(dataLabels) && notEmpty(dataLabels);
4136 },
4137 /**
4138 * Determine if has null value
4139 * @param {Array} targets Data array to be evaluated
4140 * @returns {boolean}
4141 * @private
4142 */
4143 hasNullDataValue(targets) {
4144 return targets.some(({ value }) => value === null);
4145 },
4146 /**
4147 * Get data index from the event coodinates
4148 * @param {Event} event Event object
4149 * @returns {number}
4150 * @private
4151 */
4152 getDataIndexFromEvent(event) {
4153 const $$ = this;
4154 const {
4155 $el,
4156 config,
4157 state: { hasRadar, inputType, eventReceiver: { coords, rect } }
4158 } = $$;
4159 let index;
4160 if (hasRadar) {
4161 let target = event.target;
4162 if (/tspan/i.test(target.tagName)) {
4163 target = target.parentNode;
4164 }
4165 const d = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
4166 index = d && Object.keys(d).length === 1 ? d.index : void 0;
4167 } else {
4168 const isRotated = config.axis_rotated;
4169 const scrollPos = getScrollPosition($el.chart.node());
4170 const e = inputType === "touch" && event.changedTouches ? event.changedTouches[0] : event;
4171 let point = isRotated ? e.clientY + scrollPos.y : e.clientX + scrollPos.x;
4172 if (hasViewBox($el.svg)) {
4173 const pos = [point, 0];
4174 isRotated && pos.reverse();
4175 point = getTransformCTM($el.svg.node(), ...pos)[isRotated ? "y" : "x"];
4176 } else {
4177 point -= isRotated ? rect.top : rect.left;
4178 }
4179 index = findIndex(
4180 coords,
4181 point,
4182 0,
4183 coords.length - 1,
4184 isRotated
4185 );
4186 }
4187 return index;
4188 },
4189 getDataLabelLength(min, max, key) {
4190 const $$ = this;
4191 const lengths = [0, 0];
4192 const paddingCoef = 1.3;
4193 $$.$el.chart.select("svg").selectAll(".dummy").data([min, max]).enter().append("text").text((d) => $$.dataLabelFormat(d.id)(d)).each(function(d, i) {
4194 lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
4195 }).remove();
4196 return lengths;
4197 },
4198 isNoneArc(d) {
4199 return this.hasTarget(this.data.targets, d.id);
4200 },
4201 isArc(d) {
4202 return "data" in d && this.hasTarget(this.data.targets, d.data.id);
4203 },
4204 findSameXOfValues(values, index) {
4205 const targetX = values[index].x;
4206 const sames = [];
4207 let i;
4208 for (i = index - 1; i >= 0; i--) {
4209 if (targetX !== values[i].x) {
4210 break;
4211 }
4212 sames.push(values[i]);
4213 }
4214 for (i = index; i < values.length; i++) {
4215 if (targetX !== values[i].x) {
4216 break;
4217 }
4218 sames.push(values[i]);
4219 }
4220 return sames;
4221 },
4222 findClosestFromTargets(targets, pos) {
4223 const $$ = this;
4224 const candidates = targets.map((target) => $$.findClosest(target.values, pos));
4225 return $$.findClosest(candidates, pos);
4226 },
4227 findClosest(values, pos) {
4228 const $$ = this;
4229 const { $el: { main } } = $$;
4230 const data = values.filter((v) => v && isValue(v.value));
4231 let minDist;
4232 let closest;
4233 data.filter((v) => $$.isBarType(v.id) || $$.isCandlestickType(v.id)).forEach((v) => {
4234 const selector = $$.isBarType(v.id) ? `.${$BAR.chartBar}.${$COMMON.target}${$$.getTargetSelectorSuffix(v.id)} .${$BAR.bar}-${v.index}` : `.${$CANDLESTICK.chartCandlestick}.${$COMMON.target}${$$.getTargetSelectorSuffix(v.id)} .${$CANDLESTICK.candlestick}-${v.index} path`;
4235 if (!closest && $$.isWithinBar(main.select(selector).node())) {
4236 closest = v;
4237 }
4238 });
4239 data.filter((v) => !$$.isBarType(v.id) && !$$.isCandlestickType(v.id)).forEach((v) => {
4240 const d = $$.dist(v, pos);
4241 minDist = $$.getPointSensitivity(v);
4242 if (d < minDist) {
4243 minDist = d;
4244 closest = v;
4245 }
4246 });
4247 return closest;
4248 },
4249 dist(data, pos) {
4250 const $$ = this;
4251 const { config: { axis_rotated: isRotated }, scale } = $$;
4252 const xIndex = +isRotated;
4253 const yIndex = +!isRotated;
4254 const y = $$.circleY(data, data.index);
4255 const x = (scale.zoom || scale.x)(data.x);
4256 return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
4257 },
4258 /**
4259 * Convert data for step type
4260 * @param {Array} values Object data values
4261 * @returns {Array}
4262 * @private
4263 */
4264 convertValuesToStep(values) {
4265 const $$ = this;
4266 const { axis, config } = $$;
4267 const stepType = config.line_step_type;
4268 const isCategorized = axis ? axis.isCategorized() : false;
4269 const converted = isArray(values) ? values.concat() : [values];
4270 if (!(isCategorized || /step\-(after|before)/.test(stepType))) {
4271 return values;
4272 }
4273 if (converted.length) {
4274 const head = converted[0];
4275 const tail = converted[converted.length - 1];
4276 const { id } = head;
4277 let { x } = head;
4278 converted.unshift({ x: --x, value: head.value, id });
4279 isCategorized && stepType === "step-after" && converted.unshift({ x: --x, value: head.value, id });
4280 x = tail.x;
4281 converted.push({ x: ++x, value: tail.value, id });
4282 isCategorized && stepType === "step-before" && converted.push({ x: ++x, value: tail.value, id });
4283 }
4284 return converted;
4285 },
4286 convertValuesToRange(values) {
4287 const converted = isArray(values) ? values.concat() : [values];
4288 const ranges = [];
4289 converted.forEach((range) => {
4290 const { x, id } = range;
4291 ranges.push({
4292 x,
4293 id,
4294 value: range.value[0]
4295 });
4296 ranges.push({
4297 x,
4298 id,
4299 value: range.value[2]
4300 });
4301 });
4302 return ranges;
4303 },
4304 updateDataAttributes(name, attrs) {
4305 const $$ = this;
4306 const { config } = $$;
4307 const current = config[`data_${name}`];
4308 if (isUndefined(attrs)) {
4309 return current;
4310 }
4311 Object.keys(attrs).forEach((id) => {
4312 current[id] = attrs[id];
4313 });
4314 $$.redraw({ withLegend: true });
4315 return current;
4316 },
4317 getRangedData(d, key = "", type = "areaRange") {
4318 const value = d == null ? void 0 : d.value;
4319 if (isArray(value)) {
4320 if (type === "bar") {
4321 return value.reduce((a, c) => c - a);
4322 } else {
4323 const index = {
4324 areaRange: ["high", "mid", "low"],
4325 candlestick: ["open", "high", "low", "close", "volume"]
4326 }[type].indexOf(key);
4327 return index >= 0 && value ? value[index] : void 0;
4328 }
4329 } else if (value && key) {
4330 return value[key];
4331 }
4332 return value;
4333 },
4334 /**
4335 * Set ratio for grouped data
4336 * @param {Array} data Data array
4337 * @private
4338 */
4339 setRatioForGroupedData(data) {
4340 const $$ = this;
4341 const { config } = $$;
4342 if (config.data_groups.length && data.some((d) => $$.isGrouped(d.id))) {
4343 const setter = (d) => $$.getRatio("index", d, true);
4344 data.forEach((v) => {
4345 "values" in v ? v.values.forEach(setter) : setter(v);
4346 });
4347 }
4348 },
4349 /**
4350 * Get ratio value
4351 * @param {string} type Ratio for given type
4352 * @param {object} d Data value object
4353 * @param {boolean} asPercent Convert the return as percent or not
4354 * @returns {number} Ratio value
4355 * @private
4356 */
4357 getRatio(type, d, asPercent = false) {
4358 const $$ = this;
4359 const { config, state } = $$;
4360 const api = $$.api;
4361 let ratio = 0;
4362 if (d && api.data.shown().length) {
4363 ratio = d.ratio || d.value;
4364 if (type === "arc") {
4365 if ($$.pie.padAngle()()) {
4366 ratio = d.value / $$.getTotalDataSum(true);
4367 } else {
4368 const gaugeArcLength = config.gauge_fullCircle ? $$.getArcLength() : $$.getStartingAngle() * -2;
4369 const arcLength = $$.hasType("gauge") ? gaugeArcLength : Math.PI * 2;
4370 ratio = (d.endAngle - d.startAngle) / arcLength;
4371 }
4372 } else if (type === "index") {
4373 const dataValues = api.data.values.bind(api);
4374 let total = this.getTotalPerIndex();
4375 if (state.hiddenTargetIds.length) {
4376 let hiddenSum = dataValues(state.hiddenTargetIds, false);
4377 if (hiddenSum.length) {
4378 hiddenSum = hiddenSum.reduce(
4379 (acc, curr) => acc.map((v, i) => (isNumber(v) ? v : 0) + curr[i])
4380 );
4381 total = total.map((v, i) => v - hiddenSum[i]);
4382 }
4383 }
4384 const divisor = total[d.index];
4385 d.ratio = isNumber(d.value) && total && divisor ? d.value / divisor : 0;
4386 ratio = d.ratio;
4387 } else if (type === "radar") {
4388 ratio = parseFloat(String(Math.max(d.value, 0))) / state.current.dataMax * config.radar_size_ratio;
4389 } else if (type === "bar") {
4390 const yScale = $$.getYScaleById.bind($$)(d.id);
4391 const max = yScale.domain().reduce((a, c) => c - a);
4392 ratio = max === 0 ? 0 : Math.abs(
4393 $$.getRangedData(d, null, type) / max
4394 );
4395 } else if (type === "treemap") {
4396 ratio /= $$.getTotalDataSum(true);
4397 }
4398 }
4399 return asPercent && ratio ? ratio * 100 : ratio;
4400 },
4401 /**
4402 * Sort data index to be aligned with x axis.
4403 * @param {Array} tickValues Tick array values
4404 * @private
4405 */
4406 updateDataIndexByX(tickValues) {
4407 const $$ = this;
4408 const tickValueMap = tickValues.reduce((out, tick, index) => {
4409 out[Number(tick.x)] = index;
4410 return out;
4411 }, {});
4412 $$.data.targets.forEach((t) => {
4413 t.values.forEach((value, valueIndex) => {
4414 let index = tickValueMap[Number(value.x)];
4415 if (index === void 0) {
4416 index = valueIndex;
4417 }
4418 value.index = index;
4419 });
4420 });
4421 },
4422 /**
4423 * Determine if bubble has dimension data
4424 * @param {object|Array} d data value
4425 * @returns {boolean}
4426 * @private
4427 */
4428 isBubbleZType(d) {
4429 const $$ = this;
4430 return $$.isBubbleType(d) && (isObject(d.value) && ("z" in d.value || "y" in d.value) || isArray(d.value) && d.value.length >= 2);
4431 },
4432 /**
4433 * Determine if bar has ranged data
4434 * @param {Array} d data value
4435 * @returns {boolean}
4436 * @private
4437 */
4438 isBarRangeType(d) {
4439 const $$ = this;
4440 const { value } = d;
4441 return $$.isBarType(d) && isArray(value) && value.length >= 2 && value.every((v) => isNumber(v));
4442 },
4443 /**
4444 * Get data object by id
4445 * @param {string} id data id
4446 * @returns {object}
4447 * @private
4448 */
4449 getDataById(id) {
4450 var _a;
4451 const d = this.cache.get(id) || this.api.data(id);
4452 return (_a = d == null ? void 0 : d[0]) != null ? _a : d;
4453 }
4454});
4455
4456;// ./src/ChartInternal/data/load.ts
4457
4458
4459function callDone(fn, resizeAfter = false) {
4460 const $$ = this;
4461 const { api } = $$;
4462 resizeAfter && $$.api.flush(true);
4463 fn == null ? void 0 : fn.call(api);
4464}
4465/* harmony default export */ var load = ({
4466 load(rawTargets, args) {
4467 const $$ = this;
4468 const { axis, data, org, scale } = $$;
4469 const { append } = args;
4470 const zoomState = {
4471 domain: null,
4472 currentDomain: null,
4473 x: null
4474 };
4475 let targets = rawTargets;
4476 if (targets) {
4477 if (args.filter) {
4478 targets = targets.filter(args.filter);
4479 }
4480 if (args.type || args.types) {
4481 targets.forEach((t) => {
4482 var _a;
4483 const type = ((_a = args.types) == null ? void 0 : _a[t.id]) || args.type;
4484 $$.setTargetType(t.id, type);
4485 });
4486 }
4487 data.targets.forEach((d) => {
4488 for (let i = 0; i < targets.length; i++) {
4489 if (d.id === targets[i].id) {
4490 d.values = append ? d.values.concat(targets[i].values) : targets[i].values;
4491 targets.splice(i, 1);
4492 break;
4493 }
4494 }
4495 });
4496 data.targets = data.targets.concat(targets);
4497 }
4498 $$.updateTargets(data.targets);
4499 if (scale.zoom) {
4500 zoomState.x = axis.isCategorized() ? scale.x.orgScale() : (org.xScale || scale.x).copy();
4501 zoomState.domain = $$.getXDomain(data.targets);
4502 zoomState.x.domain(zoomState.domain);
4503 zoomState.currentDomain = $$.zoom.getDomain();
4504 if (!$$.withinRange(zoomState.currentDomain, void 0, zoomState.domain)) {
4505 scale.x.domain(zoomState.domain);
4506 scale.zoom = null;
4507 $$.$el.eventRect.property("__zoom", null);
4508 }
4509 }
4510 $$.redraw({
4511 withUpdateOrgXDomain: true,
4512 withUpdateXDomain: true,
4513 withLegend: true
4514 });
4515 if (scale.zoom) {
4516 org.xDomain = zoomState.domain;
4517 org.xScale = zoomState.x;
4518 if (axis.isCategorized()) {
4519 zoomState.currentDomain = $$.getZoomDomainValue(zoomState.currentDomain);
4520 org.xDomain = $$.getZoomDomainValue(org.xDomain);
4521 org.xScale = zoomState.x.domain(org.xDomain);
4522 }
4523 $$.updateCurrentZoomTransform(zoomState.x, zoomState.currentDomain);
4524 } else if (org.xScale) {
4525 org.xScale.domain(org.xDomain);
4526 }
4527 $$.updateTypesElements();
4528 callDone.call($$, args.done, args.resizeAfter);
4529 },
4530 loadFromArgs(args) {
4531 const $$ = this;
4532 if (!$$.config) {
4533 return;
4534 }
4535 $$.cache.reset();
4536 $$.convertData(args, (d) => {
4537 const data = args.data || d;
4538 args.append && (data.__append__ = true);
4539 data && $$.load($$.convertDataToTargets(data), args);
4540 });
4541 },
4542 unload(rawTargetIds, customDoneCb) {
4543 var _a;
4544 const $$ = this;
4545 const { state, $el, $T } = $$;
4546 const hasLegendDefsPoint = !!((_a = $$.hasLegendDefsPoint) == null ? void 0 : _a.call($$));
4547 let done = customDoneCb;
4548 let targetIds = rawTargetIds;
4549 $$.cache.reset();
4550 if (!done) {
4551 done = () => {
4552 };
4553 }
4554 targetIds = targetIds.filter((id) => $$.hasTarget($$.data.targets, id));
4555 if (!targetIds || targetIds.length === 0) {
4556 done();
4557 return;
4558 }
4559 const targets = $el.svg.selectAll(targetIds.map((id) => $$.selectorTarget(id)));
4560 $T(targets).style("opacity", "0").remove().call(endall, done);
4561 targetIds.forEach((id) => {
4562 var _a2;
4563 const suffixId = $$.getTargetSelectorSuffix(id);
4564 state.withoutFadeIn[id] = false;
4565 if ($el.legend) {
4566 $el.legend.selectAll(`.${$LEGEND.legendItem}${suffixId}`).remove();
4567 }
4568 $$.data.targets = $$.data.targets.filter((t) => t.id !== id);
4569 hasLegendDefsPoint && ((_a2 = $el.defs) == null ? void 0 : _a2.select(`#${$$.getDefsPointId(suffixId)}`).remove());
4570 });
4571 state.hasFunnel && $$.updateFunnel($$.data.targets);
4572 state.hasTreemap && $$.updateTargetsForTreemap($$.data.targets);
4573 $$.updateTypesElements();
4574 }
4575});
4576
4577// EXTERNAL MODULE: external {"commonjs":"d3-drag","commonjs2":"d3-drag","amd":"d3-drag","root":"d3"}
4578var external_commonjs_d3_drag_commonjs2_d3_drag_amd_d3_drag_root_d3_ = __webpack_require__(6);
4579;// ./src/ChartInternal/interactions/interaction.ts
4580
4581
4582
4583
4584
4585/* harmony default export */ var interactions_interaction = ({
4586 /**
4587 * Expand data shape/point
4588 * @param {number} index Index number
4589 * @param {string} id Data id
4590 * @param {boolean} reset Reset expand state
4591 * @private
4592 */
4593 setExpand(index, id, reset) {
4594 const $$ = this;
4595 const { config, $el: { circle } } = $$;
4596 circle && config.point_focus_expand_enabled && $$.expandCircles(index, id, reset);
4597 $$.expandBarTypeShapes(true, index, id, reset);
4598 },
4599 /**
4600 * Expand/Unexpand bar type shapes
4601 * @param {boolean} expand Expand or unexpand
4602 * @param {number} i Shape index
4603 * @param {string} id Data id
4604 * @param {boolean} reset Reset expand style
4605 * @private
4606 */
4607 expandBarTypeShapes(expand = true, i, id, reset) {
4608 const $$ = this;
4609 ["bar", "candlestick"].filter((v) => $$.$el[v]).forEach((v) => {
4610 reset && $$.$el[v].classed($COMMON.EXPANDED, false);
4611 $$.getShapeByIndex(v, i, id).classed($COMMON.EXPANDED, expand);
4612 });
4613 },
4614 /**
4615 * Handle data.onover/out callback options
4616 * @param {boolean} isOver Over or not
4617 * @param {number|object} d data object
4618 * @private
4619 */
4620 setOverOut(isOver, d) {
4621 const $$ = this;
4622 const { config, state: { hasFunnel, hasRadar, hasTreemap }, $el: { main } } = $$;
4623 const isArcishData = isObject(d);
4624 if (isArcishData || d !== -1) {
4625 const callback = config[isOver ? "data_onover" : "data_onout"].bind($$.api);
4626 config.color_onover && $$.setOverColor(isOver, d, isArcishData);
4627 if (isArcishData && "id") {
4628 const suffix = $$.getTargetSelectorSuffix(d.id);
4629 const selector = hasFunnel || hasTreemap ? `${$COMMON.target + suffix} .${$SHAPE.shape}` : $ARC.arc + suffix;
4630 callback(d, main.select(`.${selector}`).node());
4631 } else if (!config.tooltip_grouped) {
4632 const last = $$.cache.get(KEY.setOverOut) || [];
4633 const shapesAtIndex = main.selectAll(`.${$SHAPE.shape}-${d}`).filter(function(d2) {
4634 return $$.isWithinShape(this, d2);
4635 });
4636 const shape = shapesAtIndex.filter(function() {
4637 return last.every((v) => v !== this);
4638 });
4639 if (!isOver || shapesAtIndex.empty() || last.length === shape.size() && shape.nodes().every((v, i) => v !== last[i])) {
4640 while (last.length) {
4641 const target = last.pop();
4642 config.data_onout.bind($$.api)((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum(), target);
4643 }
4644 }
4645 shape.each(function() {
4646 if (isOver) {
4647 callback((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).datum(), this);
4648 last.push(this);
4649 }
4650 });
4651 $$.cache.add(KEY.setOverOut, last);
4652 } else {
4653 if (isOver) {
4654 hasRadar && $$.isPointFocusOnly() ? $$.showCircleFocus($$.getAllValuesOnIndex(d, true)) : $$.setExpand(d, null, true);
4655 }
4656 !$$.isMultipleX() && main.selectAll(`.${$SHAPE.shape}-${d}`).each(function(d2) {
4657 callback(d2, this);
4658 });
4659 }
4660 }
4661 },
4662 /**
4663 * Call data.onover/out callback for touch event
4664 * @param {number|object} d target index or data object for Arc type
4665 * @private
4666 */
4667 callOverOutForTouch(d) {
4668 const $$ = this;
4669 const last = $$.cache.get(KEY.callOverOutForTouch);
4670 if (isObject(d) && last ? d.id !== last.id : d !== last) {
4671 (last || isNumber(last)) && $$.setOverOut(false, last);
4672 (d || isNumber(d)) && $$.setOverOut(true, d);
4673 $$.cache.add(KEY.callOverOutForTouch, d);
4674 }
4675 },
4676 /**
4677 * Return draggable selection function
4678 * @returns {Function}
4679 * @private
4680 */
4681 getDraggableSelection() {
4682 const $$ = this;
4683 const { config, state } = $$;
4684 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) {
4685 state.event = event;
4686 $$.drag(getPointer(event, this));
4687 }).on("start", function(event) {
4688 state.event = event;
4689 $$.dragstart(getPointer(event, this));
4690 }).on("end", (event) => {
4691 state.event = event;
4692 $$.dragend();
4693 }) : () => {
4694 };
4695 },
4696 /**
4697 * Dispatch a mouse event.
4698 * @private
4699 * @param {string} type event type
4700 * @param {number} index Index of eventRect
4701 * @param {Array} mouse x and y coordinate value
4702 */
4703 dispatchEvent(type, index, mouse) {
4704 var _a, _b;
4705 const $$ = this;
4706 const {
4707 config,
4708 state: {
4709 eventReceiver,
4710 hasAxis,
4711 hasFunnel,
4712 hasRadar,
4713 hasTreemap
4714 },
4715 $el: { eventRect, funnel, radar, svg, treemap }
4716 } = $$;
4717 let element = (_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();
4718 if (element) {
4719 const isMultipleX = $$.isMultipleX();
4720 const isRotated = config.axis_rotated;
4721 let { width, left, top } = element.getBoundingClientRect();
4722 if (hasAxis && !hasRadar && !isMultipleX) {
4723 const coords = eventReceiver.coords[index];
4724 if (coords) {
4725 width = coords.w;
4726 left += coords.x;
4727 top += coords.y;
4728 } else {
4729 width = 0;
4730 left = 0;
4731 top = 0;
4732 }
4733 }
4734 let x = left + (mouse ? mouse[0] : 0) + (isMultipleX || isRotated ? 0 : width / 2);
4735 let y = top + (mouse ? mouse[1] : 0) + (isRotated ? 4 : 0);
4736 if (hasViewBox(svg)) {
4737 const ctm = getTransformCTM($$.$el.svg.node(), x, y, false);
4738 x = ctm.x;
4739 y = ctm.y;
4740 }
4741 const params = {
4742 screenX: x,
4743 screenY: y,
4744 clientX: x,
4745 clientY: y,
4746 bubbles: hasRadar
4747 // radar type needs to bubble up event
4748 };
4749 if (hasFunnel || hasTreemap) {
4750 element = (funnel != null ? funnel : treemap).node();
4751 }
4752 emulateEvent[/^(mouse|click)/.test(type) ? "mouse" : "touch"](
4753 element,
4754 type,
4755 params
4756 );
4757 }
4758 },
4759 setDragStatus(isDragging) {
4760 this.state.dragging = isDragging;
4761 },
4762 /**
4763 * Unbind zoom events
4764 * @private
4765 */
4766 unbindZoomEvent() {
4767 const $$ = this;
4768 const { $el: { eventRect, zoomResetBtn } } = $$;
4769 eventRect == null ? void 0 : eventRect.on(".zoom wheel.zoom .drag", null);
4770 zoomResetBtn == null ? void 0 : zoomResetBtn.on("click", null).style("display", "none");
4771 },
4772 /**
4773 * Unbind all attached events
4774 * @private
4775 */
4776 unbindAllEvents() {
4777 var _a;
4778 const $$ = this;
4779 const { $el: { arcs, eventRect, legend, region, svg, treemap }, brush } = $$;
4780 const list = [
4781 "wheel",
4782 "click",
4783 "mouseover",
4784 "mousemove",
4785 "mouseout",
4786 "touchstart",
4787 "touchmove",
4788 "touchend",
4789 "touchstart.eventRect",
4790 "touchmove.eventRect",
4791 "touchend.eventRect",
4792 ".brush",
4793 ".drag",
4794 ".zoom",
4795 "wheel.zoom",
4796 "dblclick.zoom"
4797 ].join(" ");
4798 [
4799 svg,
4800 eventRect,
4801 region == null ? void 0 : region.list,
4802 brush == null ? void 0 : brush.getSelection(),
4803 arcs == null ? void 0 : arcs.selectAll("path"),
4804 legend == null ? void 0 : legend.selectAll("g"),
4805 treemap
4806 ].forEach((v) => v == null ? void 0 : v.on(list, null));
4807 (_a = $$.unbindZoomEvent) == null ? void 0 : _a.call($$);
4808 }
4809});
4810
4811;// ./src/ChartInternal/internals/category.ts
4812/* harmony default export */ var category = ({
4813 /**
4814 * Category Name
4815 * @param {number} i Index number
4816 * @returns {string} category Name
4817 * @private
4818 */
4819 categoryName(i) {
4820 var _a;
4821 const { axis_x_categories } = this.config;
4822 return (_a = axis_x_categories == null ? void 0 : axis_x_categories[i]) != null ? _a : i;
4823 }
4824});
4825
4826;// ./src/ChartInternal/internals/class.ts
4827
4828/* harmony default export */ var internals_class = ({
4829 generateClass(prefix, targetId) {
4830 return ` ${prefix} ${prefix + this.getTargetSelectorSuffix(targetId)}`;
4831 },
4832 /**
4833 * Get class string
4834 * @param {string} type Shape type
4835 * @param {boolean} withShape Get with shape prefix
4836 * @returns {string} Class string
4837 * @private
4838 */
4839 getClass(type, withShape) {
4840 const isPlural = /s$/.test(type);
4841 const useIdKey = /^(area|arc|line|funnel|treemap)s?$/.test(type);
4842 const key = isPlural ? "id" : "index";
4843 return (d) => {
4844 const data = d.data || d;
4845 const result = (withShape ? this.generateClass(classes[isPlural ? "shapes" : "shape"], data[key]) : "") + this.generateClass(classes[type], data[useIdKey ? "id" : key]);
4846 return result.trim();
4847 };
4848 },
4849 /**
4850 * Get chart class string
4851 * @param {string} type Shape type
4852 * @returns {string} Class string
4853 * @private
4854 */
4855 getChartClass(type) {
4856 return (d) => classes[`chart${type}`] + this.classTarget((d.data ? d.data : d).id);
4857 },
4858 generateExtraLineClass() {
4859 const $$ = this;
4860 const classes = $$.config.line_classes || [];
4861 const ids = [];
4862 return function(d) {
4863 var _a;
4864 const id = d.id || ((_a = d.data) == null ? void 0 : _a.id) || d;
4865 if (ids.indexOf(id) < 0) {
4866 ids.push(id);
4867 }
4868 return classes[ids.indexOf(id) % classes.length];
4869 };
4870 },
4871 classRegion(d, i) {
4872 return `${this.generateClass(classes.region, i)} ${"class" in d ? d.class : ""}`;
4873 },
4874 classTarget(id) {
4875 const additionalClassSuffix = this.config.data_classes[id];
4876 let additionalClass = "";
4877 if (additionalClassSuffix) {
4878 additionalClass = ` ${classes.target}-${additionalClassSuffix}`;
4879 }
4880 return this.generateClass(classes.target, id) + additionalClass;
4881 },
4882 classFocus(d) {
4883 return this.classFocused(d) + this.classDefocused(d);
4884 },
4885 classFocused(d) {
4886 return ` ${this.state.focusedTargetIds.indexOf(d.id) >= 0 ? classes.focused : ""}`;
4887 },
4888 classDefocused(d) {
4889 return ` ${this.state.defocusedTargetIds.indexOf(d.id) >= 0 ? classes.defocused : ""}`;
4890 },
4891 getTargetSelectorSuffix(targetId) {
4892 const targetStr = targetId || targetId === 0 ? `-${targetId}` : "";
4893 return targetStr.replace(/[\x00-\x20\x7F-\xA0\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, "-");
4894 },
4895 selectorTarget(id, prefix = "", postfix = "") {
4896 const target = this.getTargetSelectorSuffix(id);
4897 return `${prefix}.${classes.target + target} ${postfix}, ${prefix}.${classes.circles + target} ${postfix}`;
4898 },
4899 selectorTargets(idsValue, prefix) {
4900 const ids = idsValue || [];
4901 return ids.length ? ids.map((id) => this.selectorTarget(id, prefix)) : null;
4902 },
4903 selectorLegend(id) {
4904 return `.${classes.legendItem + this.getTargetSelectorSuffix(id)}`;
4905 },
4906 selectorLegends(ids) {
4907 return (ids == null ? void 0 : ids.length) ? ids.map((id) => this.selectorLegend(id)) : null;
4908 }
4909});
4910
4911// EXTERNAL MODULE: external {"commonjs":"d3-scale","commonjs2":"d3-scale","amd":"d3-scale","root":"d3"}
4912var external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_ = __webpack_require__(7);
4913;// ./src/ChartInternal/internals/color.ts
4914
4915
4916
4917
4918
4919
4920const colorizePattern = (pattern, color, id) => {
4921 const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(pattern.cloneNode(true));
4922 node.attr("id", id).insert("rect", ":first-child").attr("width", node.attr("width")).attr("height", node.attr("height")).style("fill", color);
4923 return {
4924 id,
4925 node: node.node()
4926 };
4927};
4928function getColorFromCss(element) {
4929 const cacheKey = KEY.colorPattern;
4930 const { body } = browser_doc;
4931 let pattern = body[cacheKey];
4932 if (!pattern) {
4933 const delimiter = ";";
4934 const content = element.classed($COLOR.colorPattern, true).style("background-image");
4935 element.classed($COLOR.colorPattern, false);
4936 if (content.indexOf(delimiter) > -1) {
4937 pattern = content.replace(/url[^#]*|["'()]|(\s|%20)/g, "").split(delimiter).map((v) => v.trim().replace(/[\"'\s]/g, "")).filter(Boolean);
4938 body[cacheKey] = pattern;
4939 }
4940 }
4941 return pattern;
4942}
4943const schemeCategory10 = [
4944 "#1f77b4",
4945 "#ff7f0e",
4946 "#2ca02c",
4947 "#d62728",
4948 "#9467bd",
4949 "#8c564b",
4950 "#e377c2",
4951 "#7f7f7f",
4952 "#bcbd22",
4953 "#17becf"
4954];
4955/* harmony default export */ var internals_color = ({
4956 generateColor() {
4957 const $$ = this;
4958 const { $el, config } = $$;
4959 const colors = config.data_colors;
4960 const callback = config.data_color;
4961 const ids = [];
4962 let pattern = notEmpty(config.color_pattern) ? config.color_pattern : (0,external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleOrdinal)(getColorFromCss($el.chart) || schemeCategory10).range();
4963 const originalColorPattern = pattern;
4964 if (isFunction(config.color_tiles)) {
4965 const tiles = config.color_tiles.bind($$.api)();
4966 const colorizedPatterns = pattern.map((p, index) => {
4967 const color = p.replace(/[#\(\)\s,]/g, "");
4968 const id = `${$$.state.datetimeId}-pattern-${color}-${index}`;
4969 return colorizePattern(tiles[index % tiles.length], p, id);
4970 });
4971 pattern = colorizedPatterns.map((p) => `url(#${p.id})`);
4972 $$.patterns = colorizedPatterns;
4973 }
4974 return function(d) {
4975 var _a;
4976 const id = d.id || ((_a = d.data) == null ? void 0 : _a.id) || d;
4977 const isLine = $$.isTypeOf(id, ["line", "spline", "step"]) || !config.data_types[id];
4978 let color;
4979 if (isFunction(colors[id])) {
4980 color = colors[id].bind($$.api)(d);
4981 } else if (colors[id]) {
4982 color = colors[id];
4983 } else {
4984 if (ids.indexOf(id) < 0) {
4985 ids.push(id);
4986 }
4987 color = isLine ? originalColorPattern[ids.indexOf(id) % originalColorPattern.length] : pattern[ids.indexOf(id) % pattern.length];
4988 colors[id] = color;
4989 }
4990 return isFunction(callback) ? callback.bind($$.api)(color, d) : color;
4991 };
4992 },
4993 generateLevelColor() {
4994 const $$ = this;
4995 const { config } = $$;
4996 const colors = config.color_pattern;
4997 const threshold = config.color_threshold;
4998 const asValue = threshold.unit === "value";
4999 const max = threshold.max || 100;
5000 const values = threshold.values && threshold.values.length ? threshold.values : [];
5001 return notEmpty(threshold) ? function(value) {
5002 const v = asValue ? value : value * 100 / max;
5003 let color = colors[colors.length - 1];
5004 for (let i = 0, l = values.length; i < l; i++) {
5005 if (v <= values[i]) {
5006 color = colors[i];
5007 break;
5008 }
5009 }
5010 return color;
5011 } : null;
5012 },
5013 /**
5014 * Append data backgound color filter definition
5015 * @param {string|object} color Color string
5016 * @param {object} attr filter attribute
5017 * @private
5018 */
5019 generateTextBGColorFilter(color, attr = {
5020 x: 0,
5021 y: 0,
5022 width: 1,
5023 height: 1
5024 }) {
5025 const $$ = this;
5026 const { $el, state } = $$;
5027 if (color) {
5028 let ids = [];
5029 if (isString(color)) {
5030 ids.push("");
5031 } else if (isObject(color)) {
5032 ids = Object.keys(color);
5033 }
5034 ids.forEach((v) => {
5035 const id = `${state.datetimeId}-labels-bg${$$.getTargetSelectorSuffix(v)}${isString(color) ? $$.getTargetSelectorSuffix(color) : ""}`;
5036 $el.defs.append("filter").attr("x", attr.x).attr("y", attr.y).attr("width", attr.width).attr("height", attr.height).attr("id", id).html(
5037 `<feFlood flood-color="${v === "" ? color : color[v]}" />
5038 <feComposite in="SourceGraphic" />`
5039 );
5040 });
5041 }
5042 },
5043 /**
5044 * Get data gradient color url
5045 * @param {string} id Data id
5046 * @returns {string}
5047 * @private
5048 */
5049 getGradienColortUrl(id) {
5050 return `url(#${this.state.datetimeId}-gradient${this.getTargetSelectorSuffix(id)})`;
5051 },
5052 /**
5053 * Update linear/radial gradient definition
5054 * - linear: area & bar only
5055 * - radial: type which has data points only
5056 * @private
5057 */
5058 updateLinearGradient() {
5059 const $$ = this;
5060 const { config, data: { targets }, state: { datetimeId }, $el: { defs } } = $$;
5061 targets.forEach((d) => {
5062 const id = `${datetimeId}-gradient${$$.getTargetSelectorSuffix(d.id)}`;
5063 const radialGradient = $$.hasPointType() && config.point_radialGradient;
5064 const supportedType = $$.isAreaType(d) && "area" || $$.isBarType(d) && "bar";
5065 if ((radialGradient || supportedType) && defs.select(`#${id}`).empty()) {
5066 const color = $$.color(d);
5067 const gradient = {
5068 defs: null,
5069 stops: []
5070 };
5071 if (radialGradient) {
5072 const {
5073 cx = 0.3,
5074 cy = 0.3,
5075 r = 0.7,
5076 stops = [[0.1, color, 0], [0.9, color, 1]]
5077 } = radialGradient;
5078 gradient.stops = stops;
5079 gradient.defs = defs.append("radialGradient").attr("id", `${id}`).attr("cx", cx).attr("cy", cy).attr("r", r);
5080 } else {
5081 const isRotated = config.axis_rotated;
5082 const {
5083 x = isRotated ? [1, 0] : [0, 0],
5084 y = isRotated ? [0, 0] : [0, 1],
5085 stops = [[0, color, 1], [1, color, 0]]
5086 } = config[`${supportedType}_linearGradient`];
5087 gradient.stops = stops;
5088 gradient.defs = defs.append("linearGradient").attr("id", `${id}`).attr("x1", x[0]).attr("x2", x[1]).attr("y1", y[0]).attr("y2", y[1]);
5089 }
5090 gradient.stops.forEach((v) => {
5091 const [offset, stopColor, stopOpacity] = v;
5092 const colorValue = isFunction(stopColor) ? stopColor.bind($$.api)(d.id) : stopColor;
5093 gradient.defs && gradient.defs.append("stop").attr("offset", offset).attr("stop-color", colorValue || color).attr("stop-opacity", stopOpacity);
5094 });
5095 }
5096 });
5097 },
5098 /**
5099 * Set the data over color.
5100 * When is out, will restate in its previous color value
5101 * @param {boolean} isOver true: set overed color, false: restore
5102 * @param {number|object} d target index or data object for Arc type
5103 * @private
5104 */
5105 setOverColor(isOver, d) {
5106 const $$ = this;
5107 const { config, $el: { main } } = $$;
5108 const onover = config.color_onover;
5109 let color = isOver ? onover : $$.color;
5110 if (isObject(color)) {
5111 color = ({ id }) => id in onover ? onover[id] : $$.color(id);
5112 } else if (isString(color)) {
5113 color = () => onover;
5114 } else if (isFunction(onover)) {
5115 color = color.bind($$.api);
5116 }
5117 main.selectAll(
5118 isObject(d) ? (
5119 // when is Arc type
5120 `.${$ARC.arc}${$$.getTargetSelectorSuffix(d.id)}`
5121 ) : `.${$SHAPE.shape}-${d}`
5122 ).style("fill", color);
5123 }
5124});
5125
5126;// ./src/ChartInternal/internals/domain.ts
5127
5128
5129/* harmony default export */ var domain = ({
5130 getYDomainMinMax(targets, type) {
5131 const $$ = this;
5132 const { axis, config } = $$;
5133 const isMin = type === "min";
5134 const dataGroups = config.data_groups;
5135 const ids = $$.mapToIds(targets);
5136 const ys = $$.getValuesAsIdKeyed(targets);
5137 if (dataGroups.length > 0) {
5138 const hasValue = $$[`has${isMin ? "Negative" : "Positive"}ValueInTargets`](targets);
5139 dataGroups.forEach((groupIds) => {
5140 const idsInGroup = groupIds.filter((v) => ids.indexOf(v) >= 0);
5141 if (idsInGroup.length) {
5142 const baseId = idsInGroup[0];
5143 const baseAxisId = axis.getId(baseId);
5144 if (hasValue && ys[baseId]) {
5145 ys[baseId] = ys[baseId].map((v) => (isMin ? v < 0 : v > 0) ? v : 0);
5146 }
5147 idsInGroup.filter((v, i) => i > 0).forEach((id) => {
5148 if (ys[id]) {
5149 const axisId = axis.getId(id);
5150 ys[id].forEach((v, i) => {
5151 const val = +v;
5152 const meetCondition = isMin ? val > 0 : val < 0;
5153 if (axisId === baseAxisId && !(hasValue && meetCondition)) {
5154 ys[baseId][i] += val;
5155 }
5156 });
5157 }
5158 });
5159 }
5160 });
5161 }
5162 return getMinMax(type, Object.keys(ys).map((key) => getMinMax(type, ys[key])));
5163 },
5164 /**
5165 * Check if hidden targets bound to the given axis id
5166 * @param {string} id ID to be checked
5167 * @returns {boolean}
5168 * @private
5169 */
5170 isHiddenTargetWithYDomain(id) {
5171 const $$ = this;
5172 return $$.state.hiddenTargetIds.some((v) => $$.axis.getId(v) === id);
5173 },
5174 getYDomain(targets, axisId, xDomain) {
5175 const $$ = this;
5176 const { axis, config, scale } = $$;
5177 const pfx = `axis_${axisId}`;
5178 if ($$.isStackNormalized()) {
5179 return [0, 100];
5180 }
5181 const isLog = (scale == null ? void 0 : scale[axisId]) && scale[axisId].type === "log";
5182 const targetsByAxisId = targets.filter((t) => axis.getId(t.id) === axisId);
5183 const yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId;
5184 if (yTargets.length === 0) {
5185 if ($$.isHiddenTargetWithYDomain(axisId)) {
5186 return scale[axisId].domain();
5187 } else {
5188 return axisId === "y2" ? scale.y.domain() : (
5189 // When all data bounds to y2, y Axis domain is called prior y2.
5190 // So, it needs to call to get y2 domain here
5191 $$.getYDomain(targets, "y2", xDomain)
5192 );
5193 }
5194 }
5195 const yMin = config[`${pfx}_min`];
5196 const yMax = config[`${pfx}_max`];
5197 const center = config[`${pfx}_center`];
5198 const isInverted = config[`${pfx}_inverted`];
5199 const showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated;
5200 const showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
5201 let yDomainMin = $$.getYDomainMinMax(yTargets, "min");
5202 let yDomainMax = $$.getYDomainMinMax(yTargets, "max");
5203 let isZeroBased = [TYPE.BAR, TYPE.BUBBLE, TYPE.SCATTER, ...TYPE_BY_CATEGORY.Line].some((v) => {
5204 const type = v.indexOf("area") > -1 ? "area" : v;
5205 return $$.hasType(v, yTargets, true) && config[`${type}_zerobased`];
5206 });
5207 yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? yDomainMin <= yMax ? yDomainMin : yMax - 10 : yDomainMin;
5208 yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? yMin <= yDomainMax ? yDomainMax : yMin + 10 : yDomainMax;
5209 if (isNaN(yDomainMin)) {
5210 yDomainMin = 0;
5211 }
5212 if (isNaN(yDomainMax)) {
5213 yDomainMax = yDomainMin;
5214 }
5215 if (yDomainMin === yDomainMax) {
5216 yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
5217 }
5218 const isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
5219 const isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
5220 if (isValue(yMin) && isAllPositive || isValue(yMax) && isAllNegative) {
5221 isZeroBased = false;
5222 }
5223 if (isZeroBased) {
5224 isAllPositive && (yDomainMin = 0);
5225 isAllNegative && (yDomainMax = 0);
5226 }
5227 const domainLength = Math.abs(yDomainMax - yDomainMin);
5228 let padding = { top: domainLength * 0.1, bottom: domainLength * 0.1 };
5229 if (isDefined(center)) {
5230 const yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
5231 yDomainMax = center + yDomainAbs;
5232 yDomainMin = center - yDomainAbs;
5233 }
5234 if (showHorizontalDataLabel) {
5235 const diff = diffDomain(scale.y.range());
5236 const ratio = $$.getDataLabelLength(yDomainMin, yDomainMax, "width").map((v) => v / diff);
5237 ["bottom", "top"].forEach((v, i) => {
5238 padding[v] += domainLength * (ratio[i] / (1 - ratio[0] - ratio[1]));
5239 });
5240 } else if (showVerticalDataLabel) {
5241 const lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, "height");
5242 ["bottom", "top"].forEach((v, i) => {
5243 padding[v] += $$.convertPixelToScale("y", lengths[i], domainLength);
5244 });
5245 }
5246 padding = $$.getResettedPadding(padding);
5247 const p = config[`${pfx}_padding`];
5248 if (notEmpty(p)) {
5249 ["bottom", "top"].forEach((v) => {
5250 padding[v] = axis.getPadding(p, v, padding[v], domainLength);
5251 });
5252 }
5253 if (isZeroBased) {
5254 isAllPositive && (padding.bottom = yDomainMin);
5255 isAllNegative && (padding.top = -yDomainMax);
5256 }
5257 const domain = isLog ? [yDomainMin, yDomainMax].map((v) => v < 0 ? 0 : v) : [yDomainMin - padding.bottom, yDomainMax + padding.top];
5258 return isInverted ? domain.reverse() : domain;
5259 },
5260 getXDomainMinMax(targets, type) {
5261 var _a;
5262 const $$ = this;
5263 const configValue = $$.config[`axis_x_${type}`];
5264 const dataValue = getMinMax(
5265 type,
5266 targets.map((t) => getMinMax(type, t.values.map((v) => v.x)))
5267 );
5268 let value = isObject(configValue) ? configValue.value : configValue;
5269 value = isDefined(value) && ((_a = $$.axis) == null ? void 0 : _a.isTimeSeries()) ? parseDate.bind(this)(value) : value;
5270 if (isObject(configValue) && configValue.fit && (type === "min" && value < dataValue || type === "max" && value > dataValue)) {
5271 value = void 0;
5272 }
5273 return isDefined(value) ? value : dataValue;
5274 },
5275 /**
5276 * Get x Axis padding
5277 * @param {Array} domain x Axis domain
5278 * @param {number} tickCount Tick count
5279 * @returns {object} Padding object values with 'left' & 'right' key
5280 * @private
5281 */
5282 getXDomainPadding(domain, tickCount) {
5283 const $$ = this;
5284 const { axis, config } = $$;
5285 const padding = config.axis_x_padding;
5286 const isTimeSeriesTickCount = axis.isTimeSeries() && tickCount;
5287 const diff = diffDomain(domain);
5288 let defaultValue;
5289 if (axis.isCategorized() || isTimeSeriesTickCount) {
5290 defaultValue = 0;
5291 } else if ($$.hasType("bar")) {
5292 const maxDataCount = $$.getMaxDataCount();
5293 defaultValue = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : 0.5;
5294 } else {
5295 defaultValue = $$.getResettedPadding(diff * 0.01);
5296 }
5297 let { left = defaultValue, right = defaultValue } = isNumber(padding) ? { left: padding, right: padding } : padding;
5298 if (padding.unit === "px") {
5299 const domainLength = Math.abs(diff + diff * 0.2);
5300 left = axis.getPadding(padding, "left", defaultValue, domainLength);
5301 right = axis.getPadding(padding, "right", defaultValue, domainLength);
5302 } else {
5303 const range = diff + left + right;
5304 if (isTimeSeriesTickCount && range) {
5305 const relativeTickWidth = diff / tickCount / range;
5306 left = left / range / relativeTickWidth;
5307 right = right / range / relativeTickWidth;
5308 }
5309 }
5310 return { left, right };
5311 },
5312 /**
5313 * Get x Axis domain
5314 * @param {Array} targets targets
5315 * @returns {Array} x Axis domain
5316 * @private
5317 */
5318 getXDomain(targets) {
5319 const $$ = this;
5320 const { axis, config, scale: { x } } = $$;
5321 const isInverted = config.axis_x_inverted;
5322 const domain = [
5323 $$.getXDomainMinMax(targets, "min"),
5324 $$.getXDomainMinMax(targets, "max")
5325 ];
5326 let [min = 0, max = 0] = domain;
5327 if (x.type !== "log") {
5328 const isCategorized = axis.isCategorized();
5329 const isTimeSeries = axis.isTimeSeries();
5330 const padding = $$.getXDomainPadding(domain);
5331 let [firstX, lastX] = domain;
5332 if (firstX - lastX === 0 && !isCategorized) {
5333 if (isTimeSeries) {
5334 firstX = new Date(firstX.getTime() * 0.5);
5335 lastX = new Date(lastX.getTime() * 1.5);
5336 } else {
5337 firstX = firstX === 0 ? 1 : firstX * 0.5;
5338 lastX = lastX === 0 ? -1 : lastX * 1.5;
5339 }
5340 }
5341 if (firstX || firstX === 0) {
5342 min = isTimeSeries ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
5343 }
5344 if (lastX || lastX === 0) {
5345 max = isTimeSeries ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
5346 }
5347 }
5348 return isInverted ? [max, min] : [min, max];
5349 },
5350 updateXDomain(targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
5351 var _a;
5352 const $$ = this;
5353 const { config, org, scale: { x, subX } } = $$;
5354 const zoomEnabled = config.zoom_enabled;
5355 if (withUpdateOrgXDomain) {
5356 x.domain(domain || sortValue($$.getXDomain(targets), !config.axis_x_inverted));
5357 org.xDomain = x.domain();
5358 subX.domain(x.domain());
5359 (_a = $$.brush) == null ? void 0 : _a.scale(subX);
5360 }
5361 if (withUpdateXDomain) {
5362 const domainValue = domain || (!$$.brush || brushEmpty($$)) ? org.xDomain : getBrushSelection($$).map(subX.invert);
5363 x.domain(domainValue);
5364 }
5365 if (withUpdateOrgXDomain || withUpdateXDomain) {
5366 zoomEnabled && $$.zoom.updateScaleExtent();
5367 }
5368 withTrim && x.domain($$.trimXDomain(x.orgDomain()));
5369 return x.domain();
5370 },
5371 /**
5372 * Trim x domain when given domain surpasses the range
5373 * @param {Array} domain Domain value
5374 * @returns {Array} Trimed domain if given domain is out of range
5375 * @private
5376 */
5377 trimXDomain(domain) {
5378 const $$ = this;
5379 const isInverted = $$.config.axis_x_inverted;
5380 const zoomDomain = $$.getZoomDomain();
5381 const [min, max] = zoomDomain;
5382 if (isInverted ? domain[0] >= min : domain[0] <= min) {
5383 domain[1] = +domain[1] + (min - domain[0]);
5384 domain[0] = min;
5385 }
5386 if (isInverted ? domain[1] <= max : domain[1] >= max) {
5387 domain[0] = +domain[0] - (domain[1] - max);
5388 domain[1] = max;
5389 }
5390 return domain;
5391 },
5392 /**
5393 * Get subchart/zoom domain
5394 * @param {string} type "subX" or "zoom"
5395 * @param {boolean} getCurrent Get current domain if true
5396 * @returns {Array} zoom domain
5397 * @private
5398 */
5399 getZoomDomain(type = "zoom", getCurrent = false) {
5400 const $$ = this;
5401 const { config, scale, org } = $$;
5402 let [min, max] = getCurrent && scale[type] ? scale[type].domain() : org.xDomain;
5403 if (type === "zoom") {
5404 if (isDefined(config.zoom_x_min)) {
5405 min = getMinMax("min", [min, config.zoom_x_min]);
5406 }
5407 if (isDefined(config.zoom_x_max)) {
5408 max = getMinMax("max", [max, config.zoom_x_max]);
5409 }
5410 }
5411 return [min, max];
5412 },
5413 /**
5414 * Return zoom domain from given domain
5415 * - 'category' type need to add offset to original value
5416 * @param {Array} domainValue domain value
5417 * @returns {Array} Zoom domain
5418 * @private
5419 */
5420 getZoomDomainValue(domainValue) {
5421 const $$ = this;
5422 const { config, axis } = $$;
5423 if (axis.isCategorized() && Array.isArray(domainValue)) {
5424 const isInverted = config.axis_x_inverted;
5425 const domain = domainValue.map(
5426 (v, i) => Number(v) + (i === 0 ? +isInverted : +!isInverted)
5427 );
5428 return domain;
5429 }
5430 return domainValue;
5431 },
5432 /**
5433 * Converts pixels to axis' scale values
5434 * @param {string} type Axis type
5435 * @param {number} pixels Pixels
5436 * @param {number} domainLength Domain length
5437 * @returns {number}
5438 * @private
5439 */
5440 convertPixelToScale(type, pixels, domainLength) {
5441 const $$ = this;
5442 const { config, state } = $$;
5443 const isRotated = config.axis_rotated;
5444 let length;
5445 if (type === "x") {
5446 length = isRotated ? "height" : "width";
5447 } else {
5448 length = isRotated ? "width" : "height";
5449 }
5450 return domainLength * (pixels / state[length]);
5451 },
5452 /**
5453 * Check if the given domain is within subchart/zoom range
5454 * @param {Array} domain Target domain value
5455 * @param {Array} current Current subchart/zoom domain value
5456 * @param {Array} range subchart/zoom range value
5457 * @returns {boolean}
5458 * @private
5459 */
5460 withinRange(domain, current = [0, 0], range) {
5461 const $$ = this;
5462 const isInverted = $$.config.axis_x_inverted;
5463 const [min, max] = range;
5464 if (Array.isArray(domain)) {
5465 const target = [...domain];
5466 isInverted && target.reverse();
5467 if (target[0] < target[1]) {
5468 return domain.every(
5469 (v, i) => (i === 0 ? isInverted ? +v <= min : +v >= min : isInverted ? +v >= max : +v <= max) && !domain.every((v2, i2) => v2 === current[i2])
5470 );
5471 }
5472 }
5473 return false;
5474 }
5475});
5476
5477;// ./src/ChartInternal/internals/format.ts
5478
5479function getFormat($$, typeValue, v) {
5480 const { config } = $$;
5481 const type = `axis_${typeValue}_tick_format`;
5482 const format = config[type] ? config[type] : $$.defaultValueFormat;
5483 return format.call($$.api, v);
5484}
5485/* harmony default export */ var format = ({
5486 yFormat(v) {
5487 return getFormat(this, "y", v);
5488 },
5489 y2Format(v) {
5490 return getFormat(this, "y2", v);
5491 },
5492 /**
5493 * Get default value format function
5494 * @returns {Function} formatter function
5495 * @private
5496 */
5497 getDefaultValueFormat() {
5498 const $$ = this;
5499 const { defaultArcValueFormat, yFormat, y2Format } = $$;
5500 const hasArc = $$.hasArcType(null, ["gauge", "polar", "radar"]);
5501 return function(v, ratio, id) {
5502 const format = hasArc ? defaultArcValueFormat : $$.axis && $$.axis.getId(id) === "y2" ? y2Format : yFormat;
5503 return format.call($$, v, ratio);
5504 };
5505 },
5506 defaultValueFormat(v) {
5507 return isArray(v) ? v.join("~") : isValue(v) ? +v : "";
5508 },
5509 defaultArcValueFormat(v, ratio) {
5510 return `${(ratio * 100).toFixed(1)}%`;
5511 },
5512 defaultPolarValueFormat(v) {
5513 return `${v}`;
5514 },
5515 dataLabelFormat(targetId) {
5516 const $$ = this;
5517 const dataLabels = $$.config.data_labels;
5518 const defaultFormat = (v) => {
5519 const delimiter = "~";
5520 let res = v;
5521 if (isArray(v)) {
5522 res = v.join(delimiter);
5523 } else if (isObject(v)) {
5524 res = Object.values(v).join(delimiter);
5525 }
5526 return res;
5527 };
5528 let format = defaultFormat;
5529 if (isFunction(dataLabels.format)) {
5530 format = dataLabels.format;
5531 } else if (isObjectType(dataLabels.format)) {
5532 if (dataLabels.format[targetId]) {
5533 format = dataLabels.format[targetId] === true ? defaultFormat : dataLabels.format[targetId];
5534 } else {
5535 format = () => "";
5536 }
5537 }
5538 return format.bind($$.api);
5539 }
5540});
5541
5542;// ./src/ChartInternal/internals/legend.ts
5543
5544
5545
5546
5547
5548function getLegendColor(id) {
5549 const $$ = this;
5550 const data = $$.getDataById(id);
5551 const color = $$.levelColor ? $$.levelColor(data.values[0].value) : $$.color(data);
5552 return color;
5553}
5554function getFormattedText(id, formatted = true) {
5555 var _a;
5556 const { config } = this;
5557 let text = (_a = config.data_names[id]) != null ? _a : id;
5558 if (formatted && isFunction(config.legend_format)) {
5559 text = config.legend_format(text, id !== text ? id : void 0);
5560 }
5561 return text;
5562}
5563/* harmony default export */ var internals_legend = ({
5564 /**
5565 * Initialize the legend.
5566 * @private
5567 */
5568 initLegend() {
5569 const $$ = this;
5570 const { config, $el } = $$;
5571 $$.legendItemTextBox = {};
5572 $$.state.legendHasRendered = false;
5573 if (config.legend_show) {
5574 if (!config.legend_contents_bindto) {
5575 $el.legend = $$.$el.svg.append("g").classed($LEGEND.legend, true).attr("transform", $$.getTranslate("legend"));
5576 }
5577 $$.updateLegend();
5578 } else {
5579 $$.state.hiddenLegendIds = $$.mapToIds($$.data.targets);
5580 }
5581 },
5582 /**
5583 * Update legend element
5584 * @param {Array} targetIds ID's of target
5585 * @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.
5586 * @param {object} transitions Return value of the generateTransitions
5587 * @private
5588 */
5589 updateLegend(targetIds, options, transitions) {
5590 var _a;
5591 const $$ = this;
5592 const { config, state, scale, $el } = $$;
5593 const optionz = options || {
5594 withTransform: false,
5595 withTransitionForTransform: false,
5596 withTransition: false
5597 };
5598 optionz.withTransition = getOption(optionz, "withTransition", true);
5599 optionz.withTransitionForTransform = getOption(optionz, "withTransitionForTransform", true);
5600 if (config.legend_contents_bindto && config.legend_contents_template) {
5601 $$.updateLegendTemplate();
5602 } else if (!state.hasTreemap) {
5603 $$.updateLegendElement(
5604 targetIds || $$.mapToIds($$.data.targets),
5605 optionz,
5606 transitions
5607 );
5608 }
5609 (_a = $el.legend) == null ? void 0 : _a.selectAll(`.${$LEGEND.legendItem}`).classed($LEGEND.legendItemHidden, function(id) {
5610 const hide = !$$.isTargetToShow(id);
5611 if (hide) {
5612 this.style.opacity = null;
5613 }
5614 return hide;
5615 });
5616 $$.updateScales(false, !scale.zoom);
5617 $$.updateSvgSize();
5618 $$.transformAll(optionz.withTransitionForTransform, transitions);
5619 state.legendHasRendered = true;
5620 },
5621 /**
5622 * Update legend using template option
5623 * @private
5624 */
5625 updateLegendTemplate() {
5626 const $$ = this;
5627 const { config, $el } = $$;
5628 const wrapper = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(config.legend_contents_bindto);
5629 const template = config.legend_contents_template;
5630 if (!wrapper.empty()) {
5631 const targets = $$.mapToIds($$.data.targets);
5632 const ids = [];
5633 let html = "";
5634 targets.forEach((v) => {
5635 const content = isFunction(template) ? template.bind($$.api)(v, $$.color(v), $$.api.data(v)[0].values) : tplProcess(template, {
5636 COLOR: $$.color(v),
5637 TITLE: v
5638 });
5639 if (content) {
5640 ids.push(v);
5641 html += content;
5642 }
5643 });
5644 const legendItem = wrapper.html(html).selectAll(function() {
5645 return this.childNodes;
5646 }).data(ids);
5647 $$.setLegendItem(legendItem);
5648 $el.legend = wrapper;
5649 }
5650 },
5651 /**
5652 * Update the size of the legend.
5653 * @param {Obejct} size Size object
5654 * @private
5655 */
5656 updateSizeForLegend(size) {
5657 const $$ = this;
5658 const {
5659 config,
5660 state: {
5661 isLegendTop,
5662 isLegendLeft,
5663 isLegendRight,
5664 isLegendInset,
5665 current
5666 }
5667 } = $$;
5668 const { width, height } = size;
5669 const insetLegendPosition = {
5670 top: isLegendTop ? $$.getCurrentPaddingByDirection("top") + config.legend_inset_y + 5.5 : current.height - height - $$.getCurrentPaddingByDirection("bottom") - config.legend_inset_y,
5671 left: isLegendLeft ? $$.getCurrentPaddingByDirection("left") + config.legend_inset_x + 0.5 : current.width - width - $$.getCurrentPaddingByDirection("right") - config.legend_inset_x + 0.5
5672 };
5673 $$.state.margin3 = {
5674 top: isLegendRight ? 0 : isLegendInset ? insetLegendPosition.top : current.height - height,
5675 right: NaN,
5676 bottom: 0,
5677 left: isLegendRight ? current.width - width : isLegendInset ? insetLegendPosition.left : 0
5678 };
5679 },
5680 /**
5681 * Transform Legend
5682 * @param {boolean} withTransition whether or not to transition.
5683 * @private
5684 */
5685 transformLegend(withTransition) {
5686 const $$ = this;
5687 const { $el: { legend }, $T } = $$;
5688 $T(legend, withTransition).attr("transform", $$.getTranslate("legend"));
5689 },
5690 /**
5691 * Update the legend step
5692 * @param {number} step Step value
5693 * @private
5694 */
5695 updateLegendStep(step) {
5696 this.state.legendStep = step;
5697 },
5698 /**
5699 * Update legend item width
5700 * @param {number} width Width value
5701 * @private
5702 */
5703 updateLegendItemWidth(width) {
5704 this.state.legendItemWidth = width;
5705 },
5706 /**
5707 * Update legend item height
5708 * @param {number} height Height value
5709 * @private
5710 */
5711 updateLegendItemHeight(height) {
5712 this.state.legendItemHeight = height;
5713 },
5714 /**
5715 * Update legend item color
5716 * @param {string} id Corresponding data ID value
5717 * @param {string} color Color value
5718 * @private
5719 */
5720 updateLegendItemColor(id, color) {
5721 const { legend } = this.$el;
5722 if (legend) {
5723 legend.select(`.${$LEGEND.legendItem}-${id} line`).style("stroke", color);
5724 }
5725 },
5726 /**
5727 * Get the width of the legend
5728 * @returns {number} width
5729 * @private
5730 */
5731 getLegendWidth() {
5732 const $$ = this;
5733 const { current: { width }, isLegendRight, isLegendInset, legendItemWidth, legendStep } = $$.state;
5734 return $$.config.legend_show ? isLegendRight || isLegendInset ? legendItemWidth * (legendStep + 1) : width : 0;
5735 },
5736 /**
5737 * Get the height of the legend
5738 * @returns {number} height
5739 * @private
5740 */
5741 getLegendHeight() {
5742 var _a;
5743 const $$ = this;
5744 const { current, isLegendRight, legendItemHeight, legendStep } = $$.state;
5745 const isFitPadding = ((_a = $$.config.padding) == null ? void 0 : _a.mode) === "fit";
5746 const height = $$.config.legend_show ? isLegendRight ? current.height : Math.max(isFitPadding ? 10 : 20, legendItemHeight) * (legendStep + 1) : 0;
5747 return height;
5748 },
5749 /**
5750 * Get the opacity of the legend that is unfocused
5751 * @param {d3.selection} legendItem Legend item node
5752 * @returns {string|null} opacity
5753 * @private
5754 */
5755 opacityForUnfocusedLegend(legendItem) {
5756 return legendItem.classed($LEGEND.legendItemHidden) ? null : "0.3";
5757 },
5758 /**
5759 * Toggles the focus of the legend
5760 * @param {Array} targetIds ID's of target
5761 * @param {boolean} focus whether or not to focus.
5762 * @private
5763 */
5764 toggleFocusLegend(targetIds, focus) {
5765 const $$ = this;
5766 const { $el: { legend }, $T } = $$;
5767 const targetIdz = $$.mapToTargetIds(targetIds);
5768 legend && $T(legend.selectAll(`.${$LEGEND.legendItem}`).filter((id) => targetIdz.indexOf(id) >= 0).classed($FOCUS.legendItemFocused, focus)).style("opacity", function() {
5769 return focus ? null : $$.opacityForUnfocusedLegend.call($$, (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this));
5770 });
5771 },
5772 /**
5773 * Revert the legend to its default state
5774 * @private
5775 */
5776 revertLegend() {
5777 const $$ = this;
5778 const { $el: { legend }, $T } = $$;
5779 legend && $T(legend.selectAll(`.${$LEGEND.legendItem}`).classed($FOCUS.legendItemFocused, false)).style("opacity", null);
5780 },
5781 /**
5782 * Shows the legend
5783 * @param {Array} targetIds ID's of target
5784 * @private
5785 */
5786 showLegend(targetIds) {
5787 const $$ = this;
5788 const { config, $el, $T } = $$;
5789 if (!config.legend_show) {
5790 config.legend_show = true;
5791 $el.legend ? $el.legend.style("visibility", null) : $$.initLegend();
5792 !$$.state.legendHasRendered && $$.updateLegend();
5793 }
5794 $$.removeHiddenLegendIds(targetIds);
5795 $T(
5796 $el.legend.selectAll($$.selectorLegends(targetIds)).style("visibility", null)
5797 ).style("opacity", null);
5798 },
5799 /**
5800 * Hide the legend
5801 * @param {Array} targetIds ID's of target
5802 * @private
5803 */
5804 hideLegend(targetIds) {
5805 const $$ = this;
5806 const { config, $el: { legend } } = $$;
5807 if (config.legend_show && isEmpty(targetIds)) {
5808 config.legend_show = false;
5809 legend.style("visibility", "hidden");
5810 }
5811 $$.addHiddenLegendIds(targetIds);
5812 legend.selectAll($$.selectorLegends(targetIds)).style("opacity", "0").style("visibility", "hidden");
5813 },
5814 /**
5815 * Get legend item textbox dimension
5816 * @param {string} id Data ID
5817 * @param {HTMLElement|d3.selection} textElement Text node element
5818 * @returns {object} Bounding rect
5819 * @private
5820 */
5821 getLegendItemTextBox(id, textElement) {
5822 const $$ = this;
5823 const { cache, state } = $$;
5824 let data;
5825 const cacheKey = KEY.legendItemTextBox;
5826 if (id) {
5827 data = !state.redrawing && cache.get(cacheKey) || {};
5828 if (!data[id]) {
5829 data[id] = $$.getTextRect(textElement, $LEGEND.legendItem);
5830 cache.add(cacheKey, data);
5831 }
5832 data = data[id];
5833 }
5834 return data;
5835 },
5836 /**
5837 * Set legend item style & bind events
5838 * @param {d3.selection} item Item node
5839 * @private
5840 */
5841 setLegendItem(item) {
5842 const $$ = this;
5843 const { $el, api, config, state } = $$;
5844 const isTouch = state.inputType === "touch";
5845 const hasGauge = $$.hasType("gauge");
5846 const useCssRule = config.boost_useCssRule;
5847 const interaction = config.legend_item_interaction;
5848 item.attr("class", function(id) {
5849 const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
5850 const itemClass = !node.empty() && node.attr("class") || "";
5851 return itemClass + $$.generateClass($LEGEND.legendItem, id);
5852 }).style("visibility", (id) => $$.isLegendToShow(id) ? null : "hidden");
5853 if (config.interaction_enabled) {
5854 if (useCssRule) {
5855 [
5856 [`.${$LEGEND.legendItem}`, "cursor:pointer"],
5857 [`.${$LEGEND.legendItem} text`, "pointer-events:none"],
5858 [`.${$LEGEND.legendItemPoint} text`, "pointer-events:none"],
5859 [`.${$LEGEND.legendItemTile}`, "pointer-events:none"],
5860 [`.${$LEGEND.legendItemEvent}`, "fill-opacity:0"]
5861 ].forEach((v) => {
5862 const [selector, props] = v;
5863 $$.setCssRule(false, selector, [props])($el.legend);
5864 });
5865 }
5866 item.on(
5867 interaction.dblclick ? "dblclick" : "click",
5868 interaction || isFunction(config.legend_item_onclick) ? function(event, id) {
5869 if (!callFn(
5870 config.legend_item_onclick,
5871 api,
5872 id,
5873 !state.hiddenTargetIds.includes(id)
5874 )) {
5875 const { altKey, target, type } = event;
5876 if (type === "dblclick" || altKey) {
5877 if (state.hiddenTargetIds.length && target.parentNode.getAttribute("class").indexOf(
5878 $LEGEND.legendItemHidden
5879 ) === -1) {
5880 api.show();
5881 } else {
5882 api.hide();
5883 api.show(id);
5884 }
5885 } else {
5886 api.toggle(id);
5887 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused, false);
5888 }
5889 }
5890 isTouch && $$.hideTooltip();
5891 } : null
5892 );
5893 !isTouch && item.on("mouseout", interaction || isFunction(config.legend_item_onout) ? function(event, id) {
5894 if (!callFn(
5895 config.legend_item_onout,
5896 api,
5897 id,
5898 !state.hiddenTargetIds.includes(id)
5899 )) {
5900 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused, false);
5901 if (hasGauge) {
5902 $$.undoMarkOverlapped($$, `.${$GAUGE.gaugeValue}`);
5903 }
5904 $$.api.revert();
5905 }
5906 } : null).on("mouseover", interaction || isFunction(config.legend_item_onover) ? function(event, id) {
5907 if (!callFn(
5908 config.legend_item_onover,
5909 api,
5910 id,
5911 !state.hiddenTargetIds.includes(id)
5912 )) {
5913 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused, true);
5914 if (hasGauge) {
5915 $$.markOverlapped(id, $$, `.${$GAUGE.gaugeValue}`);
5916 }
5917 if (!state.transiting && $$.isTargetToShow(id)) {
5918 api.focus(id);
5919 }
5920 }
5921 } : null);
5922 !item.empty() && item.on("click mouseout mouseover") && item.style("cursor", $$.getStylePropValue("pointer"));
5923 }
5924 },
5925 /**
5926 * Update the legend
5927 * @param {Array} targetIds ID's of target
5928 * @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.
5929 * @private
5930 */
5931 updateLegendElement(targetIds, options) {
5932 const $$ = this;
5933 const { config, state, $el: { legend }, $T } = $$;
5934 const legendType = config.legend_item_tile_type;
5935 const isRectangle = legendType !== "circle";
5936 const legendItemR = config.legend_item_tile_r;
5937 const itemTileSize = {
5938 width: isRectangle ? config.legend_item_tile_width : legendItemR * 2,
5939 height: isRectangle ? config.legend_item_tile_height : legendItemR * 2
5940 };
5941 const dimension = {
5942 padding: {
5943 top: 4,
5944 right: 10
5945 },
5946 max: {
5947 width: 0,
5948 height: 0
5949 },
5950 posMin: 10,
5951 step: 0,
5952 tileWidth: itemTileSize.width + 5,
5953 totalLength: 0
5954 };
5955 const sizes = {
5956 offsets: {},
5957 widths: {},
5958 heights: {},
5959 margins: [0],
5960 steps: {}
5961 };
5962 let xForLegend;
5963 let yForLegend;
5964 let background;
5965 const targetIdz = targetIds.filter((id) => !isDefined(config.data_names[id]) || config.data_names[id] !== null);
5966 const withTransition = options.withTransition;
5967 const updatePositions = $$.getUpdateLegendPositions(targetIdz, dimension, sizes);
5968 if (state.isLegendInset) {
5969 dimension.step = config.legend_inset_step ? config.legend_inset_step : targetIdz.length;
5970 $$.updateLegendStep(dimension.step);
5971 }
5972 if (state.isLegendRight) {
5973 xForLegend = (id) => dimension.max.width * sizes.steps[id];
5974 yForLegend = (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
5975 } else if (state.isLegendInset) {
5976 xForLegend = (id) => dimension.max.width * sizes.steps[id] + 10;
5977 yForLegend = (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
5978 } else {
5979 xForLegend = (id) => sizes.margins[sizes.steps[id]] + sizes.offsets[id];
5980 yForLegend = (id) => dimension.max.height * sizes.steps[id];
5981 }
5982 const posFn = {
5983 xText: (id, i) => xForLegend(id, i) + 4 + itemTileSize.width,
5984 xRect: (id, i) => xForLegend(id, i),
5985 x1Tile: (id, i) => xForLegend(id, i) - 2,
5986 x2Tile: (id, i) => xForLegend(id, i) - 2 + itemTileSize.width,
5987 yText: (id, i) => yForLegend(id, i) + 9,
5988 yRect: (id, i) => yForLegend(id, i) - 5,
5989 yTile: (id, i) => yForLegend(id, i) + 4
5990 };
5991 $$.generateLegendItem(targetIdz, itemTileSize, updatePositions, posFn);
5992 background = legend.select(`.${$LEGEND.legendBackground} rect`);
5993 if (state.isLegendInset && dimension.max.width > 0 && background.size() === 0) {
5994 background = legend.insert("g", `.${$LEGEND.legendItem}`).attr("class", $LEGEND.legendBackground).append("rect");
5995 }
5996 if (config.legend_tooltip) {
5997 legend.selectAll("title").data(targetIdz).text((id) => getFormattedText.bind($$)(id, false));
5998 }
5999 const texts = legend.selectAll("text").data(targetIdz).text((id) => getFormattedText.bind($$)(id)).each(function(id, i) {
6000 updatePositions(this, id, i);
6001 });
6002 $T(texts, withTransition).attr("x", posFn.xText).attr("y", posFn.yText);
6003 const rects = legend.selectAll(`rect.${$LEGEND.legendItemEvent}`).data(targetIdz);
6004 $T(rects, withTransition).attr("width", (id) => sizes.widths[id]).attr("height", (id) => sizes.heights[id]).attr("x", posFn.xRect).attr("y", posFn.yRect);
6005 $$.updateLegendItemPos(targetIdz, withTransition, posFn);
6006 if (background) {
6007 $T(background, withTransition).attr("height", $$.getLegendHeight() - 12).attr("width", dimension.max.width * (dimension.step + 1) + 10);
6008 }
6009 $$.updateLegendItemWidth(dimension.max.width);
6010 $$.updateLegendItemHeight(dimension.max.height);
6011 $$.updateLegendStep(dimension.step);
6012 },
6013 /**
6014 * Get position update function
6015 * @param {Array} targetIdz Data ids
6016 * @param {object} dimension Dimension object
6017 * @param {object} sizes Size object
6018 * @returns {Function} Update position function
6019 * @private
6020 */
6021 getUpdateLegendPositions(targetIdz, dimension, sizes) {
6022 const $$ = this;
6023 const { config, state } = $$;
6024 const isLegendRightOrInset = state.isLegendRight || state.isLegendInset;
6025 return function(textElement, id, index) {
6026 const reset = index === 0;
6027 const isLast = index === targetIdz.length - 1;
6028 const box = $$.getLegendItemTextBox(id, textElement);
6029 const itemWidth = box.width + dimension.tileWidth + (isLast && !isLegendRightOrInset ? 0 : dimension.padding.right) + config.legend_padding;
6030 const itemHeight = box.height + dimension.padding.top;
6031 const itemLength = isLegendRightOrInset ? itemHeight : itemWidth;
6032 const areaLength = isLegendRightOrInset ? $$.getLegendHeight() : $$.getLegendWidth();
6033 let margin;
6034 const updateValues = function(id2, withoutStep) {
6035 if (!withoutStep) {
6036 margin = (areaLength - dimension.totalLength - itemLength) / 2;
6037 if (margin < dimension.posMin) {
6038 margin = (areaLength - itemLength) / 2;
6039 dimension.totalLength = 0;
6040 dimension.step++;
6041 }
6042 }
6043 sizes.steps[id2] = dimension.step;
6044 sizes.margins[dimension.step] = state.isLegendInset ? 10 : margin;
6045 sizes.offsets[id2] = dimension.totalLength;
6046 dimension.totalLength += itemLength;
6047 };
6048 if (reset) {
6049 dimension.totalLength = 0;
6050 dimension.step = 0;
6051 dimension.max.width = 0;
6052 dimension.max.height = 0;
6053 }
6054 if (config.legend_show && !$$.isLegendToShow(id)) {
6055 sizes.widths[id] = 0;
6056 sizes.heights[id] = 0;
6057 sizes.steps[id] = 0;
6058 sizes.offsets[id] = 0;
6059 return;
6060 }
6061 sizes.widths[id] = itemWidth;
6062 sizes.heights[id] = itemHeight;
6063 if (!dimension.max.width || itemWidth >= dimension.max.width) {
6064 dimension.max.width = itemWidth;
6065 }
6066 if (!dimension.max.height || itemHeight >= dimension.max.height) {
6067 dimension.max.height = itemHeight;
6068 }
6069 const maxLength = isLegendRightOrInset ? dimension.max.height : dimension.max.width;
6070 if (config.legend_equally) {
6071 Object.keys(sizes.widths).forEach((id2) => sizes.widths[id2] = dimension.max.width);
6072 Object.keys(sizes.heights).forEach(
6073 (id2) => sizes.heights[id2] = dimension.max.height
6074 );
6075 margin = (areaLength - maxLength * targetIdz.length) / 2;
6076 if (margin < dimension.posMin) {
6077 dimension.totalLength = 0;
6078 dimension.step = 0;
6079 targetIdz.forEach((id2) => updateValues(id2));
6080 } else {
6081 updateValues(id, true);
6082 }
6083 } else {
6084 updateValues(id);
6085 }
6086 };
6087 },
6088 /**
6089 * Generate legend item elements
6090 * @param {Array} targetIdz Data ids
6091 * @param {object} itemTileSize Item tile size {width, height}
6092 * @param {Function} updatePositions Update position function
6093 * @param {object} posFn Position functions
6094 * @private
6095 */
6096 generateLegendItem(targetIdz, itemTileSize, updatePositions, posFn) {
6097 const $$ = this;
6098 const { config, state, $el: { legend } } = $$;
6099 const usePoint = config.legend_usePoint;
6100 const legendItemR = config.legend_item_tile_r;
6101 const legendType = config.legend_item_tile_type;
6102 const isRectangle = legendType !== "circle";
6103 const isLegendRightOrInset = state.isLegendRight || state.isLegendInset;
6104 const pos = -200;
6105 const l = legend.selectAll(`.${$LEGEND.legendItem}`).data(targetIdz).enter().append("g");
6106 $$.setLegendItem(l);
6107 if (config.legend_tooltip) {
6108 l.append("title").text((id) => id);
6109 }
6110 l.append("text").text((id) => getFormattedText.bind($$)(id)).each(function(id, i) {
6111 updatePositions(this, id, i);
6112 }).style("pointer-events", $$.getStylePropValue("none")).attr("x", isLegendRightOrInset ? posFn.xText : pos).attr("y", isLegendRightOrInset ? pos : posFn.yText);
6113 l.append("rect").attr("class", $LEGEND.legendItemEvent).style("fill-opacity", $$.getStylePropValue("0")).attr("x", isLegendRightOrInset ? posFn.xRect : pos).attr("y", isLegendRightOrInset ? pos : posFn.yRect);
6114 if (usePoint) {
6115 const ids = [];
6116 l.append((d) => {
6117 const pattern = notEmpty(config.point_pattern) ? config.point_pattern : [config.point_type];
6118 ids.indexOf(d) === -1 && ids.push(d);
6119 let point = pattern[ids.indexOf(d) % pattern.length];
6120 if (point === "rectangle") {
6121 point = "rect";
6122 }
6123 return browser_doc.createElementNS(
6124 external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.svg,
6125 "hasValidPointType" in $$ && $$.hasValidPointType(point) ? point : "use"
6126 );
6127 }).attr("class", $LEGEND.legendItemPoint).style("fill", getLegendColor.bind($$)).style("pointer-events", $$.getStylePropValue("none")).attr("href", (data, idx, selection) => {
6128 const node = selection[idx];
6129 const nodeName = node.nodeName.toLowerCase();
6130 const id = $$.getTargetSelectorSuffix(data);
6131 return nodeName === "use" ? `#${state.datetimeId}-point${id}` : void 0;
6132 });
6133 } else {
6134 l.append(isRectangle ? "line" : legendType).attr("class", $LEGEND.legendItemTile).style("stroke", getLegendColor.bind($$)).style("pointer-events", $$.getStylePropValue("none")).call((selection) => {
6135 if (legendType === "circle") {
6136 selection.attr("r", legendItemR).style("fill", getLegendColor.bind($$)).attr("cx", isLegendRightOrInset ? posFn.x2Tile : pos).attr("cy", isLegendRightOrInset ? pos : posFn.yTile);
6137 } else if (isRectangle) {
6138 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);
6139 }
6140 });
6141 }
6142 },
6143 /**
6144 * Update legend item position
6145 * @param {Array} targetIdz Data ids
6146 * @param {boolean} withTransition Whether or not to apply transition
6147 * @param {object} posFn Position functions
6148 * @private
6149 */
6150 updateLegendItemPos(targetIdz, withTransition, posFn) {
6151 const $$ = this;
6152 const { config, $el: { legend }, $T } = $$;
6153 const usePoint = config.legend_usePoint;
6154 const legendType = config.legend_item_tile_type;
6155 const isRectangle = legendType !== "circle";
6156 if (usePoint) {
6157 const tiles = legend.selectAll(`.${$LEGEND.legendItemPoint}`).data(targetIdz);
6158 $T(tiles, withTransition).each(function() {
6159 const nodeName = this.nodeName.toLowerCase();
6160 const pointR = config.point_r;
6161 let x = "x";
6162 let y = "y";
6163 let xOffset = 2;
6164 let yOffset = 2.5;
6165 let radius = null;
6166 let width = null;
6167 let height = null;
6168 if (nodeName === "circle") {
6169 const size = pointR * 0.2;
6170 x = "cx";
6171 y = "cy";
6172 radius = pointR + size;
6173 xOffset = pointR * 2;
6174 yOffset = -size;
6175 } else if (nodeName === "rect") {
6176 const size = pointR * 2.5;
6177 width = size;
6178 height = size;
6179 yOffset = 3;
6180 }
6181 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).attr(x, (d) => posFn.x1Tile(d) + xOffset).attr(y, (d) => posFn.yTile(d) - yOffset).attr("r", radius).attr("width", width).attr("height", height);
6182 });
6183 } else {
6184 const tiles = legend.selectAll(`.${$LEGEND.legendItemTile}`).data(targetIdz);
6185 $T(tiles, withTransition).style("stroke", getLegendColor.bind($$)).call((selection) => {
6186 if (legendType === "circle") {
6187 selection.attr("cx", (d) => {
6188 const x2 = posFn.x2Tile(d);
6189 return x2 - (x2 - posFn.x1Tile(d)) / 2;
6190 }).attr("cy", posFn.yTile);
6191 } else if (isRectangle) {
6192 selection.attr("x1", posFn.x1Tile).attr("y1", posFn.yTile).attr("x2", posFn.x2Tile).attr("y2", posFn.yTile);
6193 }
6194 });
6195 }
6196 }
6197});
6198
6199// EXTERNAL MODULE: external {"commonjs":"d3-transition","commonjs2":"d3-transition","amd":"d3-transition","root":"d3"}
6200var external_commonjs_d3_transition_commonjs2_d3_transition_amd_d3_transition_root_d3_ = __webpack_require__(8);
6201;// ./src/ChartInternal/internals/redraw.ts
6202
6203
6204
6205
6206/* harmony default export */ var redraw = ({
6207 redraw(options = {}) {
6208 var _a, _b, _c, _d;
6209 const $$ = this;
6210 const { config, state, $el } = $$;
6211 const { main, treemap } = $el;
6212 state.redrawing = true;
6213 const targetsToShow = $$.filterTargetsToShow($$.data.targets);
6214 const { flow, initializing } = options;
6215 const wth = $$.getWithOption(options);
6216 const duration = wth.Transition ? config.transition_duration : 0;
6217 const durationForExit = wth.TransitionForExit ? duration : 0;
6218 const durationForAxis = wth.TransitionForAxis ? duration : 0;
6219 const transitions = (_a = $$.axis) == null ? void 0 : _a.generateTransitions(durationForAxis);
6220 $$.updateSizes(initializing);
6221 if (wth.Legend && config.legend_show) {
6222 options.withTransition = !!duration;
6223 !treemap && $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
6224 } else if (wth.Dimension) {
6225 $$.updateDimension(true);
6226 }
6227 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);
6228 if (state.hasAxis) {
6229 $$.axis.redrawAxis(targetsToShow, wth, transitions, flow, initializing);
6230 $$.hasGrid() && $$.updateGrid();
6231 config.regions.length && $$.updateRegion();
6232 ["bar", "candlestick", "line", "area"].forEach((v) => {
6233 const name = capitalize(v);
6234 if (/^(line|area)$/.test(v) && $$.hasTypeOf(name) || $$.hasType(v)) {
6235 $$[`update${name}`](wth.TransitionForExit);
6236 }
6237 });
6238 $el.text && main.selectAll(`.${$SELECT.selectedCircles}`).filter($$.isBarType.bind($$)).selectAll("circle").remove();
6239 if (config.interaction_enabled && !flow && wth.EventRect) {
6240 $$.redrawEventRect();
6241 (_b = $$.bindZoomEvent) == null ? void 0 : _b.call($$);
6242 }
6243 } else {
6244 $el.arcs && $$.redrawArc(duration, durationForExit, wth.Transform);
6245 $el.radar && $$.redrawRadar();
6246 $el.polar && $$.redrawPolar();
6247 $el.funnel && $$.redrawFunnel();
6248 treemap && $$.updateTreemap(durationForExit);
6249 }
6250 if (!state.resizing && !treemap && ($$.hasPointType() || state.hasRadar)) {
6251 $$.updateCircle();
6252 } else if ((_c = $$.hasLegendDefsPoint) == null ? void 0 : _c.call($$)) {
6253 $$.data.targets.forEach($$.point("create", this));
6254 }
6255 $$.hasDataLabel() && !$$.hasArcType(null, ["radar"]) && $$.updateText();
6256 (_d = $$.redrawTitle) == null ? void 0 : _d.call($$);
6257 initializing && $$.updateTypesElements();
6258 $$.generateRedrawList(targetsToShow, flow, duration, wth.Subchart);
6259 $$.updateTooltipOnRedraw();
6260 $$.callPluginHook("$redraw", options, duration);
6261 },
6262 /**
6263 * Generate redraw list
6264 * @param {object} targets targets data to be shown
6265 * @param {object} flow flow object
6266 * @param {number} duration duration value
6267 * @param {boolean} withSubchart whether or not to show subchart
6268 * @private
6269 */
6270 generateRedrawList(targets, flow, duration, withSubchart) {
6271 const $$ = this;
6272 const { config, state } = $$;
6273 const shape = $$.getDrawShape();
6274 if (state.hasAxis) {
6275 config.subchart_show && $$.redrawSubchart(withSubchart, duration, shape);
6276 }
6277 const flowFn = flow && $$.generateFlow({
6278 targets,
6279 flow,
6280 duration: flow.duration,
6281 shape,
6282 xv: $$.xv.bind($$)
6283 });
6284 const withTransition = (duration || flowFn) && isTabVisible();
6285 const redrawList = $$.getRedrawList(shape, flow, flowFn, withTransition);
6286 const afterRedraw = () => {
6287 flowFn && flowFn();
6288 state.redrawing = false;
6289 callFn(config.onrendered, $$.api);
6290 };
6291 if (afterRedraw) {
6292 if (withTransition && redrawList.length) {
6293 const waitForDraw = generateWait();
6294 (0,external_commonjs_d3_transition_commonjs2_d3_transition_amd_d3_transition_root_d3_.transition)().duration(duration).each(() => {
6295 redrawList.reduce((acc, t1) => acc.concat(t1), []).forEach((t) => waitForDraw.add(t));
6296 }).call(waitForDraw, afterRedraw);
6297 } else if (!state.transiting) {
6298 afterRedraw();
6299 }
6300 }
6301 $$.mapToIds($$.data.targets).forEach((id) => {
6302 state.withoutFadeIn[id] = true;
6303 });
6304 },
6305 getRedrawList(shape, flow, flowFn, withTransition) {
6306 const $$ = this;
6307 const { config, state: { hasAxis, hasRadar, hasTreemap }, $el: { grid } } = $$;
6308 const { cx, cy, xForText, yForText } = shape.pos;
6309 const list = [];
6310 if (hasAxis) {
6311 if (config.grid_x_lines.length || config.grid_y_lines.length) {
6312 list.push($$.redrawGrid(withTransition));
6313 }
6314 if (config.regions.length) {
6315 list.push($$.redrawRegion(withTransition));
6316 }
6317 Object.keys(shape.type).forEach((v) => {
6318 const name = capitalize(v);
6319 const drawFn = shape.type[v];
6320 if (/^(area|line)$/.test(v) && $$.hasTypeOf(name) || $$.hasType(v)) {
6321 list.push($$[`redraw${name}`](drawFn, withTransition));
6322 }
6323 });
6324 !flow && grid.main && list.push($$.updateGridFocus());
6325 }
6326 if (!$$.hasArcType() || hasRadar) {
6327 notEmpty(config.data_labels) && config.data_labels !== false && list.push($$.redrawText(xForText, yForText, flow, withTransition));
6328 }
6329 if (($$.hasPointType() || hasRadar) && !$$.isPointFocusOnly()) {
6330 $$.redrawCircle && list.push($$.redrawCircle(cx, cy, withTransition, flowFn));
6331 }
6332 if (hasTreemap) {
6333 list.push($$.redrawTreemap(withTransition));
6334 }
6335 return list;
6336 },
6337 updateAndRedraw(options = {}) {
6338 const $$ = this;
6339 const { config, state } = $$;
6340 let transitions;
6341 options.withTransition = getOption(options, "withTransition", true);
6342 options.withTransform = getOption(options, "withTransform", false);
6343 options.withLegend = getOption(options, "withLegend", false);
6344 options.withUpdateXDomain = true;
6345 options.withUpdateOrgXDomain = true;
6346 options.withTransitionForExit = false;
6347 options.withTransitionForTransform = getOption(
6348 options,
6349 "withTransitionForTransform",
6350 options.withTransition
6351 );
6352 if (!(options.withLegend && config.legend_show)) {
6353 if (state.hasAxis) {
6354 transitions = $$.axis.generateTransitions(
6355 options.withTransitionForAxis ? config.transition_duration : 0
6356 );
6357 }
6358 $$.updateScales();
6359 $$.updateSvgSize();
6360 $$.transformAll(options.withTransitionForTransform, transitions);
6361 }
6362 $$.redraw(options, transitions);
6363 }
6364});
6365
6366;// ./src/ChartInternal/internals/scale.ts
6367
6368
6369function getScale(type = "linear", min, max) {
6370 const scale = {
6371 linear: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLinear,
6372 log: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleSymlog,
6373 _log: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLog,
6374 time: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleTime,
6375 utc: external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleUtc
6376 }[type]();
6377 scale.type = type;
6378 /_?log/.test(type) && scale.clamp(true);
6379 return scale.range([min != null ? min : 0, max != null ? max : 1]);
6380}
6381/* harmony default export */ var scale = ({
6382 /**
6383 * Get x Axis scale function
6384 * @param {number} min Min range value
6385 * @param {number} max Max range value
6386 * @param {Array} domain Domain value
6387 * @param {Function} offset The offset getter to be sum
6388 * @returns {Function} scale
6389 * @private
6390 */
6391 getXScale(min, max, domain, offset) {
6392 const $$ = this;
6393 const scale = $$.state.loading !== "append" && $$.scale.zoom || getScale($$.axis.getAxisType("x"), min, max);
6394 return $$.getCustomizedXScale(
6395 domain ? scale.domain(domain) : scale,
6396 offset
6397 );
6398 },
6399 /**
6400 * Get y Axis scale function
6401 * @param {string} id Axis id: 'y' or 'y2'
6402 * @param {number} min Min value
6403 * @param {number} max Max value
6404 * @param {Array} domain Domain value
6405 * @returns {Function} Scale function
6406 * @private
6407 */
6408 getYScale(id, min, max, domain) {
6409 const $$ = this;
6410 const scale = getScale($$.axis.getAxisType(id), min, max);
6411 domain && scale.domain(domain);
6412 return scale;
6413 },
6414 /**
6415 * Get y Axis scale
6416 * @param {string} id Axis id
6417 * @param {boolean} isSub Weather is sub Axis
6418 * @returns {Function} Scale function
6419 * @private
6420 */
6421 getYScaleById(id, isSub = false) {
6422 var _a;
6423 const isY2 = ((_a = this.axis) == null ? void 0 : _a.getId(id)) === "y2";
6424 const key = isSub ? isY2 ? "subY2" : "subY" : isY2 ? "y2" : "y";
6425 return this.scale[key];
6426 },
6427 /**
6428 * Get customized x axis scale
6429 * @param {d3.scaleLinear|d3.scaleTime} scaleValue Scale function
6430 * @param {Function} offsetValue Offset getter to be sum
6431 * @returns {Function} Scale function
6432 * @private
6433 */
6434 getCustomizedXScale(scaleValue, offsetValue) {
6435 const $$ = this;
6436 const offset = offsetValue || (() => $$.axis.x.tickOffset());
6437 const isInverted = $$.config.axis_x_inverted;
6438 const scale = function(d) {
6439 return scaleValue(d) + offset();
6440 };
6441 for (const key in scaleValue) {
6442 scale[key] = scaleValue[key];
6443 }
6444 scale.orgDomain = () => scaleValue.domain();
6445 scale.orgScale = () => scaleValue;
6446 if ($$.axis.isCategorized()) {
6447 scale.domain = function(domainValue) {
6448 let domain = domainValue;
6449 if (!arguments.length) {
6450 domain = this.orgDomain();
6451 return isInverted ? [domain[0] + 1, domain[1]] : [domain[0], domain[1] + 1];
6452 }
6453 scaleValue.domain(domain);
6454 return scale;
6455 };
6456 }
6457 return scale;
6458 },
6459 /**
6460 * Update scale
6461 * @param {boolean} isInit Param is given at the init rendering
6462 * @param {boolean} updateXDomain If update x domain
6463 * @private
6464 */
6465 updateScales(isInit, updateXDomain = true) {
6466 var _a, _b;
6467 const $$ = this;
6468 const {
6469 axis,
6470 config,
6471 format,
6472 org,
6473 scale,
6474 state: { current, width, height, width2, height2, hasAxis, hasTreemap }
6475 } = $$;
6476 if (hasAxis) {
6477 const isRotated = config.axis_rotated;
6478 const resettedPadding = $$.getResettedPadding(1);
6479 const min = {
6480 x: isRotated ? resettedPadding : 0,
6481 y: isRotated ? 0 : height,
6482 subX: isRotated ? 1 : 0,
6483 subY: isRotated ? 0 : height2
6484 };
6485 const max = {
6486 x: isRotated ? height : width,
6487 y: isRotated ? width : resettedPadding,
6488 subX: isRotated ? height : width,
6489 subY: isRotated ? width2 : 1
6490 };
6491 const xDomain = updateXDomain && ((_a = scale.x) == null ? void 0 : _a.orgDomain());
6492 const xSubDomain = updateXDomain && org.xDomain;
6493 scale.x = $$.getXScale(min.x, max.x, xDomain, () => axis.x.tickOffset());
6494 scale.subX = $$.getXScale(min.x, max.x, xSubDomain, (d) => {
6495 var _a2;
6496 return d % 1 ? 0 : ((_a2 = axis.subX) != null ? _a2 : axis.x).tickOffset();
6497 });
6498 format.xAxisTick = axis.getXAxisTickFormat();
6499 format.subXAxisTick = axis.getXAxisTickFormat(true);
6500 axis.setAxis("x", scale.x, config.axis_x_tick_outer, isInit);
6501 if (config.subchart_show) {
6502 axis.setAxis("subX", scale.subX, config.axis_x_tick_outer, isInit);
6503 }
6504 scale.y = $$.getYScale(
6505 "y",
6506 min.y,
6507 max.y,
6508 scale.y ? scale.y.domain() : config.axis_y_default
6509 );
6510 scale.subY = $$.getYScale(
6511 "y",
6512 min.subY,
6513 max.subY,
6514 scale.subY ? scale.subY.domain() : config.axis_y_default
6515 );
6516 axis.setAxis("y", scale.y, config.axis_y_tick_outer, isInit);
6517 if (config.axis_y2_show) {
6518 scale.y2 = $$.getYScale(
6519 "y2",
6520 min.y,
6521 max.y,
6522 scale.y2 ? scale.y2.domain() : config.axis_y2_default
6523 );
6524 scale.subY2 = $$.getYScale(
6525 "y2",
6526 min.subY,
6527 max.subY,
6528 scale.subY2 ? scale.subY2.domain() : config.axis_y2_default
6529 );
6530 axis.setAxis("y2", scale.y2, config.axis_y2_tick_outer, isInit);
6531 }
6532 } else if (hasTreemap) {
6533 const padding = $$.getCurrentPadding();
6534 scale.x = (0,external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLinear)().rangeRound([padding.left, current.width - padding.right]);
6535 scale.y = (0,external_commonjs_d3_scale_commonjs2_d3_scale_amd_d3_scale_root_d3_.scaleLinear)().rangeRound([padding.top, current.height - padding.bottom]);
6536 } else {
6537 (_b = $$.updateArc) == null ? void 0 : _b.call($$);
6538 }
6539 },
6540 /**
6541 * Get the zoom or unzoomed scaled value
6542 * @param {Date|number|object} d Data value
6543 * @returns {number|null}
6544 * @private
6545 */
6546 xx(d) {
6547 const $$ = this;
6548 const { config, scale: { x, zoom } } = $$;
6549 const fn = config.zoom_enabled && zoom ? zoom : x;
6550 return d ? fn(isValue(d.x) ? d.x : d) : null;
6551 },
6552 xv(d) {
6553 const $$ = this;
6554 const { axis, config, scale: { x, zoom } } = $$;
6555 const fn = config.zoom_enabled && zoom ? zoom : x;
6556 let value = $$.getBaseValue(d);
6557 if (axis.isTimeSeries()) {
6558 value = parseDate.call($$, value);
6559 } else if (axis.isCategorized() && isString(value)) {
6560 value = config.axis_x_categories.indexOf(value);
6561 }
6562 return fn(value);
6563 },
6564 yv(d) {
6565 const $$ = this;
6566 const { scale: { y, y2 } } = $$;
6567 const yScale = d.axis && d.axis === "y2" ? y2 : y;
6568 return yScale($$.getBaseValue(d));
6569 },
6570 subxx(d) {
6571 return d ? this.scale.subX(d.x) : null;
6572 }
6573});
6574
6575;// ./src/ChartInternal/internals/size.ts
6576
6577
6578
6579
6580/* harmony default export */ var size = ({
6581 /**
6582 * Update container size
6583 * @private
6584 */
6585 setContainerSize() {
6586 const $$ = this;
6587 const { state } = $$;
6588 state.current.width = $$.getCurrentWidth();
6589 state.current.height = $$.getCurrentHeight();
6590 },
6591 getCurrentWidth() {
6592 const $$ = this;
6593 return $$.config.size_width || $$.getParentWidth();
6594 },
6595 getCurrentHeight() {
6596 const $$ = this;
6597 const { config } = $$;
6598 const h = config.size_height || $$.getParentHeight();
6599 return h > 0 ? h : 320 / ($$.hasType("gauge") && !config.gauge_fullCircle ? 2 : 1);
6600 },
6601 /**
6602 * Get the parent rect element's size
6603 * @param {string} key property/attribute name
6604 * @returns {number}
6605 * @private
6606 */
6607 getParentRectValue(key) {
6608 const offsetName = `offset${capitalize(key)}`;
6609 let parent = this.$el.chart.node();
6610 let v = 0;
6611 while (v < 30 && parent && parent.tagName !== "BODY") {
6612 try {
6613 v = parent.getBoundingClientRect()[key];
6614 } catch (e) {
6615 if (offsetName in parent) {
6616 v = parent[offsetName];
6617 }
6618 }
6619 parent = parent.parentNode;
6620 }
6621 const bodySize = browser_doc.body[offsetName];
6622 v > bodySize && (v = bodySize);
6623 return v;
6624 },
6625 getParentWidth() {
6626 return this.getParentRectValue("width");
6627 },
6628 getParentHeight() {
6629 const h = this.$el.chart.style("height");
6630 let height = 0;
6631 if (h) {
6632 height = /px$/.test(h) ? parseInt(h, 10) : this.getParentRectValue("height");
6633 }
6634 return height;
6635 },
6636 getSvgLeft(withoutRecompute) {
6637 const $$ = this;
6638 const { config, state: { hasAxis }, $el } = $$;
6639 const isRotated = config.axis_rotated;
6640 const hasLeftAxisRect = isRotated || !isRotated && !config.axis_y_inner;
6641 const leftAxisClass = isRotated ? $AXIS.axisX : $AXIS.axisY;
6642 const leftAxis = $el.main.select(`.${leftAxisClass}`).node();
6643 const leftLabel = hasAxis && config[`axis_${isRotated ? "x" : "y"}_label`];
6644 let labelWidth = 0;
6645 if (hasAxis && (isString(leftLabel) || isString(leftLabel.text) || /^inner-/.test(leftLabel == null ? void 0 : leftLabel.position))) {
6646 const label = $el.main.select(`.${leftAxisClass}-label`);
6647 if (!label.empty()) {
6648 labelWidth = label.node().getBoundingClientRect().left;
6649 }
6650 }
6651 const svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : { right: 0 };
6652 const chartRectLeft = $el.chart.node().getBoundingClientRect().left + labelWidth;
6653 const hasArc = $$.hasArcType();
6654 const svgLeft = svgRect.right - chartRectLeft - (hasArc ? 0 : $$.getCurrentPaddingByDirection("left", withoutRecompute));
6655 return svgLeft > 0 ? svgLeft : 0;
6656 },
6657 updateDimension(withoutAxis) {
6658 var _a;
6659 const $$ = this;
6660 const { config, state: { hasAxis }, $el } = $$;
6661 if (hasAxis && !withoutAxis && $$.axis.x && config.axis_rotated) {
6662 (_a = $$.axis.subX) == null ? void 0 : _a.create($el.axis.subX);
6663 }
6664 $$.updateScales(withoutAxis);
6665 $$.updateSvgSize();
6666 $$.transformAll(false);
6667 },
6668 updateSvgSize() {
6669 const $$ = this;
6670 const { config, state: { clip, current, hasAxis, width, height }, $el: { svg } } = $$;
6671 if (config.resize_auto === "viewBox") {
6672 svg.attr("viewBox", `0 0 ${current.width} ${current.height}`);
6673 } else {
6674 svg.attr("width", current.width).attr("height", current.height);
6675 }
6676 if (hasAxis) {
6677 const brush = svg.select(`.${$SUBCHART.brush} .overlay`);
6678 const brushSize = { width: 0, height: 0 };
6679 if (brush.size()) {
6680 brushSize.width = +brush.attr("width");
6681 brushSize.height = +brush.attr("height");
6682 }
6683 svg.selectAll([`#${clip.id}`, `#${clip.idGrid}`]).select("rect").attr("width", width).attr("height", height);
6684 svg.select(`#${clip.idXAxis}`).select("rect").call($$.setXAxisClipPath.bind($$));
6685 svg.select(`#${clip.idYAxis}`).select("rect").call($$.setYAxisClipPath.bind($$));
6686 clip.idSubchart && svg.select(`#${clip.idSubchart}`).select("rect").attr("width", width).attr("height", brushSize.height);
6687 }
6688 },
6689 /**
6690 * Get padding by the direction.
6691 * @param {string} type "top" | "bottom" | "left" | "right"
6692 * @param {boolean} [withoutRecompute=false] If set true, do not recompute the padding value.
6693 * @param {boolean} [withXAxisTickTextOverflow=false] If set true, calculate x axis tick text overflow.
6694 * @returns {number} padding value
6695 * @private
6696 */
6697 getCurrentPaddingByDirection(type, withoutRecompute = false, withXAxisTickTextOverflow = false) {
6698 var _a;
6699 const $$ = this;
6700 const { config, $el, state: { hasAxis } } = $$;
6701 const isRotated = config.axis_rotated;
6702 const isFitPadding = ((_a = config.padding) == null ? void 0 : _a.mode) === "fit";
6703 const paddingOption = isNumber(config[`padding_${type}`]) ? config[`padding_${type}`] : void 0;
6704 const axisId = hasAxis ? {
6705 top: isRotated ? "y2" : null,
6706 bottom: isRotated ? "y" : "x",
6707 left: isRotated ? "x" : "y",
6708 right: isRotated ? null : "y2"
6709 }[type] : null;
6710 const isLeftRight = /^(left|right)$/.test(type);
6711 const isAxisInner = axisId && config[`axis_${axisId}_inner`];
6712 const isAxisShow = axisId && config[`axis_${axisId}_show`];
6713 const axesLen = axisId ? config[`axis_${axisId}_axes`].length : 0;
6714 let axisSize = axisId ? isLeftRight ? $$.getAxisWidthByAxisId(axisId, withoutRecompute) : $$.getHorizontalAxisHeight(axisId) : 0;
6715 const defaultPadding = 20;
6716 let gap = 0;
6717 if (!isFitPadding && isLeftRight) {
6718 axisSize = ceil10(axisSize);
6719 }
6720 let padding = hasAxis && isLeftRight && (isAxisInner || isUndefined(paddingOption) && !isAxisShow) ? 0 : isFitPadding ? (isAxisShow ? axisSize : 0) + (paddingOption != null ? paddingOption : 0) : isUndefined(paddingOption) ? axisSize : paddingOption;
6721 if (isLeftRight && hasAxis) {
6722 if (axisId && (isFitPadding || isAxisInner) && config[`axis_${axisId}_label`].text) {
6723 padding += $$.axis.getAxisLabelPosition(axisId).isOuter ? defaultPadding : 0;
6724 }
6725 if (type === "right") {
6726 padding += isRotated ? !isFitPadding && isUndefined(paddingOption) ? 10 : 2 : !isAxisShow || isAxisInner ? isFitPadding ? 2 : 1 : 0;
6727 padding += withXAxisTickTextOverflow ? $$.axis.getXAxisTickTextY2Overflow(defaultPadding) : 0;
6728 } else if (type === "left" && isRotated && isUndefined(paddingOption)) {
6729 padding = !config.axis_x_show ? 1 : isFitPadding ? axisSize : Math.max(axisSize, 40);
6730 }
6731 } else {
6732 if (type === "top") {
6733 if ($el.title && $el.title.node()) {
6734 padding += $$.getTitlePadding();
6735 }
6736 gap = isRotated && !isAxisInner ? axesLen : 0;
6737 } else if (type === "bottom" && hasAxis && isRotated && !isAxisShow) {
6738 padding += 1;
6739 }
6740 }
6741 return padding + axisSize * axesLen - gap;
6742 },
6743 getCurrentPadding(withXAxisTickTextOverflow = false) {
6744 const $$ = this;
6745 const [top, bottom, left, right] = ["top", "bottom", "left", "right"].map((v) => $$.getCurrentPaddingByDirection(v, null, withXAxisTickTextOverflow));
6746 return { top, bottom, left, right };
6747 },
6748 /**
6749 * Get resetted padding values when 'padding=false' option is set
6750 * https://github.com/naver/billboard.js/issues/2367
6751 * @param {number|object} v Padding values to be resetted
6752 * @returns {number|object} Padding value
6753 * @private
6754 */
6755 getResettedPadding(v) {
6756 const $$ = this;
6757 const { config } = $$;
6758 const isNum = isNumber(v);
6759 let p = isNum ? 0 : {};
6760 if (config.padding === false) {
6761 !isNum && Object.keys(v).forEach((key) => {
6762 p[key] = !isEmpty(config.data_labels) && config.data_labels !== false && key === "top" ? v[key] : 0;
6763 });
6764 } else {
6765 p = v;
6766 }
6767 return p;
6768 },
6769 /**
6770 * Update size values
6771 * @param {boolean} isInit If is called at initialization
6772 * @private
6773 */
6774 updateSizes(isInit) {
6775 var _a, _b, _c, _d, _e;
6776 const $$ = this;
6777 const { config, state, $el: { legend } } = $$;
6778 const isRotated = config.axis_rotated;
6779 const isNonAxis = $$.hasArcType() || state.hasFunnel || state.hasTreemap;
6780 const isFitPadding = ((_a = config.padding) == null ? void 0 : _a.mode) === "fit";
6781 !isInit && $$.setContainerSize();
6782 const currLegend = {
6783 width: legend ? $$.getLegendWidth() : 0,
6784 height: legend ? $$.getLegendHeight() : 0
6785 };
6786 if (!isNonAxis && config.axis_x_show && config.axis_x_tick_autorotate) {
6787 $$.updateXAxisTickClip();
6788 }
6789 const legendSize = {
6790 right: config.legend_show && state.isLegendRight ? $$.getLegendWidth() + (isFitPadding ? 0 : 20) : 0,
6791 bottom: !config.legend_show || state.isLegendRight || state.isLegendInset ? 0 : currLegend.height
6792 };
6793 const xAxisHeight = isRotated || isNonAxis ? 0 : $$.getHorizontalAxisHeight("x");
6794 const subchartXAxisHeight = config.subchart_axis_x_show && config.subchart_axis_x_tick_text_show ? xAxisHeight : 30;
6795 const subchartHeight = config.subchart_show && !isNonAxis ? config.subchart_size_height + subchartXAxisHeight : 0;
6796 const gaugeHeight = $$.hasType("gauge") && config.arc_needle_show && !config.gauge_fullCircle && !config.gauge_label_show ? 10 : 0;
6797 const padding = $$.getCurrentPadding(true);
6798 state.margin = !isNonAxis && isRotated ? {
6799 top: padding.top,
6800 right: isNonAxis ? 0 : padding.right + legendSize.right,
6801 bottom: legendSize.bottom + padding.bottom,
6802 left: subchartHeight + (isNonAxis ? 0 : padding.left)
6803 } : {
6804 top: (isFitPadding ? 0 : 4) + padding.top,
6805 // for top tick text
6806 right: isNonAxis ? 0 : padding.right + legendSize.right,
6807 bottom: gaugeHeight + subchartHeight + legendSize.bottom + padding.bottom,
6808 left: isNonAxis ? 0 : padding.left
6809 };
6810 state.margin = $$.getResettedPadding(state.margin);
6811 state.margin2 = isRotated ? {
6812 top: state.margin.top,
6813 right: NaN,
6814 bottom: 20 + legendSize.bottom,
6815 left: $$.state.rotatedPadding.left
6816 } : {
6817 top: state.current.height - subchartHeight - legendSize.bottom,
6818 right: NaN,
6819 bottom: subchartXAxisHeight + legendSize.bottom,
6820 left: state.margin.left
6821 };
6822 state.margin3 = {
6823 top: 0,
6824 right: NaN,
6825 bottom: 0,
6826 left: 0
6827 };
6828 (_b = $$.updateSizeForLegend) == null ? void 0 : _b.call($$, currLegend);
6829 state.width = state.current.width - state.margin.left - state.margin.right;
6830 state.height = state.current.height - state.margin.top - state.margin.bottom;
6831 if (state.width < 0) {
6832 state.width = 0;
6833 }
6834 if (state.height < 0) {
6835 state.height = 0;
6836 }
6837 state.width2 = isRotated ? state.margin.left - state.rotatedPadding.left - state.rotatedPadding.right : state.width;
6838 state.height2 = isRotated ? state.height : state.current.height - state.margin2.top - state.margin2.bottom;
6839 if (state.width2 < 0) {
6840 state.width2 = 0;
6841 }
6842 if (state.height2 < 0) {
6843 state.height2 = 0;
6844 }
6845 if ($$.hasArcType()) {
6846 const hasGauge = $$.hasType("gauge");
6847 const isLegendRight = config.legend_show && state.isLegendRight;
6848 const textWidth = (_c = state.hasRadar && $$.cache.get(KEY.radarTextWidth)) != null ? _c : 0;
6849 state.arcWidth = state.width - (isLegendRight ? currLegend.width + 10 : 0) - textWidth;
6850 state.arcHeight = state.height - (isLegendRight && !hasGauge ? 0 : 10);
6851 if ((_d = config.arc_rangeText_values) == null ? void 0 : _d.length) {
6852 if (hasGauge) {
6853 state.arcWidth -= 25;
6854 state.arcHeight -= 10;
6855 state.margin.left += 10;
6856 } else {
6857 state.arcHeight -= 20;
6858 state.margin.top += 10;
6859 }
6860 }
6861 if (hasGauge && !config.gauge_fullCircle) {
6862 state.arcHeight += state.height - $$.getPaddingBottomForGauge();
6863 }
6864 (_e = $$.updateRadius) == null ? void 0 : _e.call($$);
6865 }
6866 if (state.isLegendRight && isNonAxis) {
6867 state.margin3.left = state.arcWidth / 2 + state.radiusExpanded * 1.1;
6868 }
6869 }
6870});
6871
6872;// ./src/ChartInternal/internals/style.ts
6873
6874
6875/* harmony default export */ var style = ({
6876 /**
6877 * Add props color css rule to given selector
6878 * @param {boolean} withShape Set shpes' prefix class
6879 * @param {string} selector CSS selector
6880 * @param {Array} props CSS props list
6881 * @param {Function} propsFn Function to retrieve value or determine for props
6882 * @returns {Function}
6883 * @private
6884 */
6885 setCssRule(withShape, selector, props, propsFn) {
6886 const $$ = this;
6887 const { config, state: { cssRule, style } } = $$;
6888 return config.boost_useCssRule ? (selection) => {
6889 selection.each((d) => {
6890 const res = propsFn && (propsFn == null ? void 0 : propsFn.call($$, d));
6891 const shapeSelector = `${withShape ? `.${$SHAPE.shapes + $$.getTargetSelectorSuffix(d.id)}` : ""}${selector}`;
6892 selector in cssRule && style.sheet.deleteRule(cssRule[shapeSelector]);
6893 $$.state.cssRule[shapeSelector] = addCssRules(
6894 style,
6895 shapeSelector,
6896 props.filter(Boolean).map((v) => isString(res) && v.indexOf(":") === -1 ? `${v}: ${res}` : v || "")
6897 );
6898 });
6899 } : () => {
6900 };
6901 },
6902 /**
6903 * Get style prop value
6904 * @param {Function|string} v Value
6905 * @returns {string|null}
6906 * @private
6907 */
6908 getStylePropValue(v) {
6909 const { config: { boost_useCssRule: useCssRule } } = this;
6910 return useCssRule ? null : isFunction(v) ? v.bind(this) : v;
6911 }
6912});
6913
6914;// ./src/ChartInternal/internals/text.ts
6915
6916
6917
6918
6919function getRotateAnchor(angle) {
6920 let anchor = "middle";
6921 if (angle > 0 && angle <= 170) {
6922 anchor = "end";
6923 } else if (angle > 190 && angle <= 360) {
6924 anchor = "start";
6925 }
6926 return anchor;
6927}
6928function setRotatePos(d, pos, anchor, isRotated, isInverted) {
6929 var _a;
6930 const $$ = this;
6931 const { value } = d;
6932 const isCandlestickType = $$.isCandlestickType(d);
6933 const isNegative = isNumber(value) && value < 0 || isCandlestickType && !((_a = $$.getCandlestickData(d)) == null ? void 0 : _a._isUp);
6934 let { x, y } = pos;
6935 const gap = 4;
6936 const doubleGap = gap * 2;
6937 if (isRotated) {
6938 if (anchor === "start") {
6939 x += isNegative ? 0 : doubleGap;
6940 y += gap;
6941 } else if (anchor === "middle") {
6942 x += doubleGap;
6943 y -= doubleGap;
6944 } else if (anchor === "end") {
6945 isNegative && (x -= doubleGap);
6946 y += gap;
6947 }
6948 } else {
6949 if (anchor === "start") {
6950 x += gap;
6951 isNegative && (y += doubleGap * 2);
6952 } else if (anchor === "middle") {
6953 y -= doubleGap;
6954 } else if (anchor === "end") {
6955 x -= gap;
6956 isNegative && (y += doubleGap * 2);
6957 }
6958 if (isInverted) {
6959 y += isNegative ? -17 : isCandlestickType ? 13 : 7;
6960 }
6961 }
6962 return { x, y };
6963}
6964function getTextPos(d, type) {
6965 var _a;
6966 const position = this.config.data_labels_position;
6967 const { id, index, value } = d;
6968 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;
6969}
6970/* harmony default export */ var internals_text = ({
6971 opacityForText(d) {
6972 const $$ = this;
6973 return $$.isBarType(d) && !$$.meetsLabelThreshold(
6974 Math.abs($$.getRatio("bar", d)),
6975 "bar"
6976 ) ? "0" : $$.hasDataLabel ? null : "0";
6977 },
6978 /**
6979 * Initializes the text
6980 * @private
6981 */
6982 initText() {
6983 const { $el } = this;
6984 $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $TEXT.chartTexts).style("pointer-events", $el.funnel || $el.treemap ? "none" : null);
6985 },
6986 /**
6987 * Update chartText
6988 * @param {object} targets $$.data.targets
6989 * @private
6990 */
6991 updateTargetsForText(targets) {
6992 const $$ = this;
6993 const classChartText = $$.getChartClass("Text");
6994 const classTexts = $$.getClass("texts", "id");
6995 const classFocus = $$.classFocus.bind($$);
6996 const mainTextUpdate = $$.$el.main.select(`.${$TEXT.chartTexts}`).selectAll(`.${$TEXT.chartText}`).data(targets).attr("class", (d) => `${classChartText(d)}${classFocus(d)}`.trim());
6997 const mainTextEnter = mainTextUpdate.enter().append("g").style("opacity", "0").attr("class", classChartText).call(
6998 $$.setCssRule(
6999 true,
7000 ` .${$TEXT.text}`,
7001 ["fill", "pointer-events:none"],
7002 $$.updateTextColor
7003 )
7004 );
7005 mainTextEnter.append("g").attr("class", classTexts);
7006 },
7007 /**
7008 * Update text
7009 * @private
7010 */
7011 updateText() {
7012 const $$ = this;
7013 const { $el, $T, config, axis } = $$;
7014 const classText = $$.getClass("text", "index");
7015 const labelsCentered = config.data_labels.centered;
7016 const text = $el.main.selectAll(`.${$TEXT.texts}`).selectAll(`.${$TEXT.text}`).data($$.labelishData.bind($$));
7017 $T(text.exit()).style("fill-opacity", "0").remove();
7018 $el.text = text.enter().append("text").merge(text).attr("class", classText).attr("text-anchor", (d) => {
7019 const isInverted = config[`axis_${axis == null ? void 0 : axis.getId(d.id)}_inverted`];
7020 let isEndAnchor = isInverted ? d.value > 0 : d.value < 0;
7021 if ($$.isCandlestickType(d)) {
7022 const data = $$.getCandlestickData(d);
7023 isEndAnchor = !(data == null ? void 0 : data._isUp);
7024 } else if ($$.isTreemapType(d)) {
7025 return labelsCentered ? "middle" : "start";
7026 }
7027 return config.axis_rotated ? isEndAnchor ? "end" : "start" : "middle";
7028 }).style("fill", $$.getStylePropValue($$.updateTextColor)).style("fill-opacity", "0").each(function(d, i, texts) {
7029 const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
7030 let { value } = d;
7031 if ($$.isBubbleZType(d)) {
7032 value = $$.getBubbleZData(value, "z");
7033 } else if ($$.isCandlestickType(d)) {
7034 const data = $$.getCandlestickData(d);
7035 if (data) {
7036 value = data.close;
7037 }
7038 }
7039 value = $$.isTreemapType(d) ? $$.treemapDataLabelFormat(d)(node) : $$.dataLabelFormat(d.id)(value, d.id, d.index, texts);
7040 if (isNumber(value)) {
7041 this.textContent = value;
7042 } else {
7043 setTextValue(node, value);
7044 }
7045 });
7046 },
7047 updateTextColor(d) {
7048 const $$ = this;
7049 const { config } = $$;
7050 const labelColors = config.data_labels_colors;
7051 const defaultColor = $$.isArcType(d) && !$$.isRadarType(d) || $$.isFunnelType(d) || $$.isTreemapType(d) ? null : $$.color(d);
7052 let color;
7053 if (isString(labelColors)) {
7054 color = labelColors;
7055 } else if (isObject(labelColors)) {
7056 const { id } = d.data || d;
7057 color = labelColors[id];
7058 } else if (isFunction(labelColors)) {
7059 color = labelColors.bind($$.api)(defaultColor, d);
7060 }
7061 if ($$.isCandlestickType(d) && !isFunction(labelColors)) {
7062 const value = $$.getCandlestickData(d);
7063 if (!(value == null ? void 0 : value._isUp)) {
7064 const downColor = config.candlestick_color_down;
7065 color = isObject(downColor) ? downColor[d.id] : downColor;
7066 }
7067 }
7068 return color || defaultColor;
7069 },
7070 /**
7071 * Update data label text background color
7072 * @param {object} d Data object
7073 * @param {object|string} option option object
7074 * @returns {string|null}
7075 * @private
7076 */
7077 updateTextBGColor(d, option) {
7078 const $$ = this;
7079 const { $el } = $$;
7080 let color = "";
7081 if (isString(option) || isObject(option)) {
7082 const id = isString(option) ? "" : $$.getTargetSelectorSuffix("id" in d ? d.id : d.data.id);
7083 const filter = $el.defs.select(["filter[id*='labels-bg", "']"].join(id));
7084 if (filter.size()) {
7085 color = `url(#${filter.attr("id")})`;
7086 }
7087 }
7088 return color || null;
7089 },
7090 /**
7091 * Redraw chartText
7092 * @param {Function} getX Positioning function for x
7093 * @param {Function} getY Positioning function for y
7094 * @param {boolean} forFlow Weather is flow
7095 * @param {boolean} withTransition transition is enabled
7096 * @returns {Array}
7097 * @private
7098 */
7099 redrawText(getX, getY, forFlow, withTransition) {
7100 const $$ = this;
7101 const { $T, axis, config, state: { hasTreemap } } = $$;
7102 const t = getRandom(true);
7103 const isRotated = config.axis_rotated;
7104 const angle = config.data_labels.rotate;
7105 const anchorString = getRotateAnchor(angle);
7106 const rotateString = angle ? `rotate(${angle})` : "";
7107 $$.$el.text.style("fill", $$.getStylePropValue($$.updateTextColor)).attr(
7108 "filter",
7109 (d) => $$.updateTextBGColor.bind($$)(d, config.data_labels_backgroundColors)
7110 ).style("fill-opacity", forFlow ? 0 : $$.opacityForText.bind($$)).each(function(d, i) {
7111 const node = $T(
7112 hasTreemap && this.childElementCount ? this.parentNode : this,
7113 !!(withTransition && this.getAttribute("x")),
7114 t
7115 );
7116 const isInverted = config[`axis_${axis == null ? void 0 : axis.getId(d.id)}_inverted`];
7117 let pos = {
7118 x: getX.bind(this)(d, i),
7119 y: getY.bind(this)(d, i)
7120 };
7121 if (angle) {
7122 pos = setRotatePos.bind($$)(d, pos, anchorString, isRotated, isInverted);
7123 node.attr("text-anchor", anchorString);
7124 }
7125 if (this.childElementCount || angle) {
7126 node.attr("transform", `translate(${pos.x} ${pos.y}) ${rotateString}`);
7127 } else {
7128 node.attr("x", pos.x).attr("y", pos.y);
7129 }
7130 });
7131 return true;
7132 },
7133 /**
7134 * Gets the getBoundingClientRect value of the element
7135 * @param {HTMLElement|d3.selection} element Target element
7136 * @param {string} className Class name
7137 * @returns {object} value of element.getBoundingClientRect()
7138 * @private
7139 */
7140 getTextRect(element, className) {
7141 const $$ = this;
7142 let base = element.node ? element.node() : element;
7143 if (!/text/i.test(base.tagName)) {
7144 base = base.querySelector("text");
7145 }
7146 const text = base.textContent;
7147 const cacheKey = `${KEY.textRect}-${text.replace(/\W/g, "_")}`;
7148 let rect = $$.cache.get(cacheKey);
7149 if (!rect) {
7150 $$.$el.svg.append("text").style("visibility", "hidden").style("font", (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(base).style("font")).classed(className, true).text(text).call((v) => {
7151 rect = getBoundingRect(v.node());
7152 }).remove();
7153 $$.cache.add(cacheKey, rect);
7154 }
7155 return rect;
7156 },
7157 /**
7158 * Gets the x or y coordinate of the text
7159 * @param {object} indices Indices values
7160 * @param {boolean} forX whether or not to x
7161 * @returns {number} coordinates
7162 * @private
7163 */
7164 generateXYForText(indices, forX) {
7165 const $$ = this;
7166 const { state: { hasRadar, hasFunnel, hasTreemap } } = $$;
7167 const types = Object.keys(indices);
7168 const points = {};
7169 const getter = forX ? $$.getXForText : $$.getYForText;
7170 hasFunnel && types.push("funnel");
7171 hasRadar && types.push("radar");
7172 hasTreemap && types.push("treemap");
7173 types.forEach((v) => {
7174 points[v] = $$[`generateGet${capitalize(v)}Points`](indices[v], false);
7175 });
7176 return function(d, i) {
7177 const type = $$.isAreaType(d) && "area" || $$.isBarType(d) && "bar" || $$.isCandlestickType(d) && "candlestick" || $$.isFunnelType(d) && "funnel" || $$.isRadarType(d) && "radar" || $$.isTreemapType(d) && "treemap" || "line";
7178 return getter.call($$, points[type](d, i), d, this);
7179 };
7180 },
7181 /**
7182 * Get centerized text position for bar type data.label.text
7183 * @param {object} d Data object
7184 * @param {Array} points Data points position
7185 * @param {HTMLElement} textElement Data label text element
7186 * @param {string} type 'x' or 'y'
7187 * @returns {number} Position value
7188 * @private
7189 */
7190 getCenteredTextPos(d, points, textElement, type) {
7191 const $$ = this;
7192 const { config } = $$;
7193 const isRotated = config.axis_rotated;
7194 const isBarType = $$.isBarType(d);
7195 const isTreemapType = $$.isTreemapType(d);
7196 if (config.data_labels.centered && (isBarType || isTreemapType)) {
7197 const rect = getBoundingRect(textElement);
7198 if (isBarType) {
7199 const isPositive = $$.getRangedData(d, null, "bar") >= 0;
7200 if (isRotated) {
7201 const w = (isPositive ? points[1][1] - points[0][1] : points[0][1] - points[1][1]) / 2 + rect.width / 2;
7202 return isPositive ? -w - 3 : w + 2;
7203 } else {
7204 const h = (isPositive ? points[0][1] - points[1][1] : points[1][1] - points[0][1]) / 2 + rect.height / 2;
7205 return isPositive ? h : -h - 2;
7206 }
7207 } else if (isTreemapType) {
7208 return type === "x" ? (points[1][0] - points[0][0]) / 2 : (points[1][1] - points[0][1]) / 2 + rect.height / 2;
7209 }
7210 }
7211 return 0;
7212 },
7213 /**
7214 * Gets the x coordinate of the text
7215 * @param {object} points Data points position
7216 * @param {object} d Data object
7217 * @param {HTMLElement} textElement Data label text element
7218 * @returns {number} x coordinate
7219 * @private
7220 */
7221 getXForText(points, d, textElement) {
7222 var _a;
7223 const $$ = this;
7224 const { config } = $$;
7225 const isRotated = config.axis_rotated;
7226 const isFunnelType = $$.isFunnelType(d);
7227 const isTreemapType = $$.isTreemapType(d);
7228 let xPos = points ? points[0][0] : 0;
7229 if ($$.isCandlestickType(d)) {
7230 if (isRotated) {
7231 xPos = ((_a = $$.getCandlestickData(d)) == null ? void 0 : _a._isUp) ? points[2][2] + 4 : points[2][1] - 4;
7232 } else {
7233 xPos += (points[1][0] - xPos) / 2;
7234 }
7235 } else if (isFunnelType) {
7236 xPos += $$.state.current.width / 2;
7237 } else if (isTreemapType) {
7238 xPos += config.data_labels.centered ? 0 : 5;
7239 } else {
7240 if (isRotated) {
7241 const isInverted = config[`axis_${$$.axis.getId(d.id)}_inverted`];
7242 const padding = $$.isBarType(d) ? 4 : 6;
7243 const value = d.value;
7244 xPos = points[2][1];
7245 if (isInverted) {
7246 xPos -= padding * (value > 0 ? 1 : -1);
7247 } else {
7248 xPos += padding * (value < 0 ? -1 : 1);
7249 }
7250 } else {
7251 xPos = $$.hasType("bar") ? (points[2][0] + points[0][0]) / 2 : xPos;
7252 }
7253 }
7254 if (isRotated || isTreemapType) {
7255 xPos += $$.getCenteredTextPos(d, points, textElement, "x");
7256 }
7257 return xPos + getTextPos.call(this, d, "x");
7258 },
7259 /**
7260 * Gets the y coordinate of the text
7261 * @param {object} points Data points position
7262 * @param {object} d Data object
7263 * @param {HTMLElement} textElement Data label text element
7264 * @returns {number} y coordinate
7265 * @private
7266 */
7267 getYForText(points, d, textElement) {
7268 const $$ = this;
7269 const { axis, config, state } = $$;
7270 const isRotated = config.axis_rotated;
7271 const isInverted = config[`axis_${axis == null ? void 0 : axis.getId(d.id)}_inverted`];
7272 const isBarType = $$.isBarType(d);
7273 const isFunnelType = $$.isFunnelType(d);
7274 const isTreemapType = $$.isTreemapType(d);
7275 const r = config.point_r;
7276 const rect = getBoundingRect(textElement);
7277 let { value } = d;
7278 let baseY = 3;
7279 let yPos;
7280 if ($$.isCandlestickType(d)) {
7281 value = $$.getCandlestickData(d);
7282 if (isRotated) {
7283 yPos = points[0][0];
7284 yPos += (points[1][0] - yPos) / 2 + baseY;
7285 } else {
7286 yPos = value && value._isUp ? points[2][2] - baseY : points[2][1] + baseY * 4;
7287 if (isInverted) {
7288 yPos += 15 * (value._isUp ? 1 : -1);
7289 }
7290 }
7291 } else if (isFunnelType) {
7292 yPos = points ? points[0][1] + (points[1][1] - points[0][1]) / 2 + rect.height / 2 - 3 : 0;
7293 } else if (isTreemapType) {
7294 yPos = points[0][1] + (config.data_labels.centered ? 0 : rect.height + 5);
7295 } else {
7296 if (isRotated) {
7297 yPos = (points[0][0] + points[2][0] + rect.height * 0.6) / 2;
7298 } else {
7299 yPos = points[2][1];
7300 if (isNumber(r) && r > 5 && ($$.isLineType(d) || $$.isScatterType(d))) {
7301 baseY += config.point_r / 2.3;
7302 }
7303 if (value < 0 || value === 0 && !state.hasPositiveValue && state.hasNegativeValue) {
7304 yPos += isInverted ? isBarType ? -3 : -5 : rect.height + (isBarType ? -baseY : baseY);
7305 } else {
7306 let diff = -baseY * 2;
7307 if (isBarType) {
7308 diff = -baseY;
7309 } else if ($$.isBubbleType(d)) {
7310 diff = baseY;
7311 }
7312 if (isInverted) {
7313 diff = isBarType ? 10 : 15;
7314 }
7315 yPos += diff;
7316 }
7317 }
7318 }
7319 if (!isRotated || isTreemapType) {
7320 yPos += $$.getCenteredTextPos(d, points, textElement, "y");
7321 }
7322 return yPos + getTextPos.call(this, d, "y");
7323 },
7324 /**
7325 * Calculate if two or more text nodes are overlapping
7326 * Mark overlapping text nodes with "text-overlapping" class
7327 * @param {string} id Axis id
7328 * @param {ChartInternal} $$ ChartInternal context
7329 * @param {string} selector Selector string
7330 * @private
7331 */
7332 markOverlapped(id, $$, selector) {
7333 const textNodes = $$.$el.arcs.selectAll(selector);
7334 const filteredTextNodes = textNodes.filter((node) => node.data.id !== id);
7335 const textNode = textNodes.filter((node) => node.data.id === id);
7336 const translate = getTranslation(textNode.node());
7337 const calcHypo = (x, y) => Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
7338 textNode.node() && filteredTextNodes.each(function() {
7339 const coordinate = getTranslation(this);
7340 const filteredTextNode = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
7341 const nodeForWidth = calcHypo(translate.e, translate.f) > calcHypo(coordinate.e, coordinate.f) ? textNode : filteredTextNode;
7342 const overlapsX = Math.ceil(Math.abs(translate.e - coordinate.e)) < Math.ceil(nodeForWidth.node().getComputedTextLength());
7343 const overlapsY = Math.ceil(Math.abs(translate.f - coordinate.f)) < parseInt(textNode.style("font-size"), 10);
7344 filteredTextNode.classed($TEXT.TextOverlapping, overlapsX && overlapsY);
7345 });
7346 },
7347 /**
7348 * Calculate if two or more text nodes are overlapping
7349 * Remove "text-overlapping" class on selected text nodes
7350 * @param {ChartInternal} $$ ChartInternal context
7351 * @param {string} selector Selector string
7352 * @private
7353 */
7354 undoMarkOverlapped($$, selector) {
7355 $$.$el.arcs.selectAll(selector).each(function() {
7356 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.selectAll)([this, this.previousSibling]).classed($TEXT.TextOverlapping, false);
7357 });
7358 },
7359 /**
7360 * Check if meets the ratio to show data label text
7361 * @param {number} ratio ratio to meet
7362 * @param {string} type chart type
7363 * @returns {boolean}
7364 * @private
7365 */
7366 meetsLabelThreshold(ratio = 0, type) {
7367 const $$ = this;
7368 const { config } = $$;
7369 const threshold = config[`${type}_label_threshold`] || 0;
7370 return ratio >= threshold;
7371 }
7372});
7373
7374;// ./src/ChartInternal/internals/title.ts
7375
7376
7377function getTextXPos(pos = "left", width) {
7378 const isNum = isNumber(width);
7379 let position;
7380 if (pos.indexOf("center") > -1) {
7381 position = isNum ? width / 2 : "middle";
7382 } else if (pos.indexOf("right") > -1) {
7383 position = isNum ? width : "end";
7384 } else {
7385 position = isNum ? 0 : "start";
7386 }
7387 return position;
7388}
7389/* harmony default export */ var internals_title = ({
7390 /**
7391 * Initializes the title
7392 * @private
7393 */
7394 initTitle() {
7395 const $$ = this;
7396 const { config, $el } = $$;
7397 if (config.title_text) {
7398 $el.title = $el.svg.append("g");
7399 const text = $el.title.append("text").style("text-anchor", getTextXPos(config.title_position)).attr("class", $TEXT.title);
7400 setTextValue(text, config.title_text, [0.3, 1.5]);
7401 }
7402 },
7403 /**
7404 * Redraw title
7405 * @private
7406 */
7407 redrawTitle() {
7408 const $$ = this;
7409 const { config, state: { current }, $el: { title } } = $$;
7410 if (title) {
7411 const x = getTextXPos(config.title_position, current.width);
7412 const y = (config.title_padding.top || 0) + $$.getTextRect($$.$el.title, $TEXT.title).height;
7413 title.attr("transform", `translate(${x}, ${y})`);
7414 }
7415 },
7416 /**
7417 * Get title padding
7418 * @returns {number} padding value
7419 * @private
7420 */
7421 getTitlePadding() {
7422 const $$ = this;
7423 const { $el: { title }, config } = $$;
7424 return (config.title_padding.top || 0) + (title ? $$.getTextRect(title, $TEXT.title).height : 0) + (config.title_padding.bottom || 0);
7425 }
7426});
7427
7428;// ./src/ChartInternal/internals/tooltip.ts
7429
7430
7431
7432
7433/* harmony default export */ var internals_tooltip = ({
7434 /**
7435 * Initializes the tooltip
7436 * @private
7437 */
7438 initTooltip() {
7439 const $$ = this;
7440 const { config, $el } = $$;
7441 $el.tooltip = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(config.tooltip_contents.bindto);
7442 if ($el.tooltip.empty()) {
7443 $el.tooltip = $el.chart.append("div").attr("class", $TOOLTIP.tooltipContainer).style("position", "absolute").style("pointer-events", "none").style("display", "none");
7444 }
7445 $$.bindTooltipResizePos();
7446 },
7447 /**
7448 * Show tooltip at initialization.
7449 * Is called only when tooltip.init.show=true option is set
7450 * @private
7451 */
7452 initShowTooltip() {
7453 var _a;
7454 const $$ = this;
7455 const { config, $el, state: { hasAxis, hasRadar } } = $$;
7456 if (config.tooltip_init_show) {
7457 const isArc = !(hasAxis || hasRadar);
7458 if (((_a = $$.axis) == null ? void 0 : _a.isTimeSeries()) && isString(config.tooltip_init_x)) {
7459 config.tooltip_init_x = parseDate.call($$, config.tooltip_init_x);
7460 }
7461 $$.api.tooltip.show({
7462 data: {
7463 [isArc ? "index" : "x"]: config.tooltip_init_x
7464 }
7465 });
7466 const position = config.tooltip_init_position;
7467 if (!config.tooltip_contents.bindto && !isEmpty(position)) {
7468 const { top = 0, left = 50 } = position;
7469 $el.tooltip.style("top", isString(top) ? top : `${top}px`).style("left", isString(left) ? left : `${left}px`).style("display", null);
7470 }
7471 }
7472 },
7473 /**
7474 * Get the tooltip HTML string
7475 * @param {Array} args Arguments
7476 * @returns {string} Formatted HTML string
7477 * @private
7478 */
7479 getTooltipHTML(...args) {
7480 const $$ = this;
7481 const { api, config } = $$;
7482 return isFunction(config.tooltip_contents) ? config.tooltip_contents.bind(api)(...args) : $$.getTooltipContent(...args);
7483 },
7484 /**
7485 * Returns the tooltip content(HTML string)
7486 * @param {object} d data
7487 * @param {Function} defaultTitleFormat Default title format
7488 * @param {Function} defaultValueFormat Default format for each data value in the tooltip.
7489 * @param {Function} color Color function
7490 * @returns {string} html
7491 * @private
7492 */
7493 getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) {
7494 var _a;
7495 const $$ = this;
7496 const { api, config, state, $el } = $$;
7497 const [titleFn, nameFn, valueFn] = ["title", "name", "value"].map((v) => {
7498 const fn = config[`tooltip_format_${v}`];
7499 return isFunction(fn) ? fn.bind(api) : fn;
7500 });
7501 const titleFormat = (...arg) => sanitize((titleFn || defaultTitleFormat)(...arg));
7502 const nameFormat = (...arg) => sanitize((nameFn || ((name) => name))(...arg));
7503 const valueFormat = (...arg) => {
7504 const fn = valueFn || (state.hasTreemap || $$.isStackNormalized() ? (v, ratio) => `${(ratio * 100).toFixed(2)}%` : defaultValueFormat);
7505 return sanitize(fn(...arg));
7506 };
7507 const order = config.tooltip_order;
7508 const getRowValue = (row2) => $$.axis && $$.isBubbleZType(row2) ? $$.getBubbleZData(row2.value, "z") : $$.getBaseValue(row2);
7509 const getBgColor = $$.levelColor ? (row2) => $$.levelColor(row2.value) : (row2) => color(row2);
7510 const contents = config.tooltip_contents;
7511 const tplStr = contents.template;
7512 const targetIds = $$.mapToTargetIds();
7513 if (order === null && config.data_groups.length) {
7514 const ids = $$.orderTargets($$.data.targets).map((i2) => i2.id).reverse();
7515 d.sort((a, b) => {
7516 let v1 = a ? a.value : null;
7517 let v2 = b ? b.value : null;
7518 if (v1 > 0 && v2 > 0) {
7519 v1 = a.id ? ids.indexOf(a.id) : null;
7520 v2 = b.id ? ids.indexOf(b.id) : null;
7521 }
7522 return v1 - v2;
7523 });
7524 } else if (/^(asc|desc)$/.test(order)) {
7525 const isAscending = order === "asc";
7526 d.sort((a, b) => {
7527 const v1 = a ? getRowValue(a) : null;
7528 const v2 = b ? getRowValue(b) : null;
7529 return isAscending ? v1 - v2 : v2 - v1;
7530 });
7531 } else if (isFunction(order)) {
7532 d.sort(order.bind(api));
7533 }
7534 const tpl = $$.getTooltipContentTemplate(tplStr);
7535 const len = d.length;
7536 let text;
7537 let row;
7538 let param;
7539 let value;
7540 let i;
7541 for (i = 0; i < len; i++) {
7542 row = d[i];
7543 if (!row || !(getRowValue(row) || getRowValue(row) === 0)) {
7544 continue;
7545 }
7546 if (isUndefined(text)) {
7547 const title = (state.hasAxis || state.hasRadar) && titleFormat(row.x);
7548 text = tplProcess(tpl[0], {
7549 CLASS_TOOLTIP: $TOOLTIP.tooltip,
7550 TITLE: isValue(title) ? tplStr ? title : `<tr><th colspan="2">${title}</th></tr>` : ""
7551 });
7552 }
7553 if (!row.ratio && $el.arcs) {
7554 param = ["arc", $$.$el.arcs.select(`path.${$ARC.arc}-${row.id}`).data()[0]];
7555 row.ratio = $$.getRatio(...param);
7556 }
7557 param = [row.ratio, row.id, row.index];
7558 if ($$.isAreaRangeType(row)) {
7559 const [high, low] = ["high", "low"].map(
7560 (v) => valueFormat($$.getRangedData(row, v), ...param)
7561 );
7562 const mid = valueFormat(getRowValue(row), ...param);
7563 value = `<b>Mid:</b> ${mid} <b>High:</b> ${high} <b>Low:</b> ${low}`;
7564 } else if ($$.isCandlestickType(row)) {
7565 const [open, high, low, close, volume] = ["open", "high", "low", "close", "volume"].map((v) => {
7566 const value2 = $$.getRangedData(row, v, "candlestick");
7567 return value2 ? valueFormat(
7568 $$.getRangedData(row, v, "candlestick"),
7569 ...param
7570 ) : void 0;
7571 });
7572 value = `<b>Open:</b> ${open} <b>High:</b> ${high} <b>Low:</b> ${low} <b>Close:</b> ${close}${volume ? ` <b>Volume:</b> ${volume}` : ""}`;
7573 } else if ($$.isBarRangeType(row)) {
7574 const { value: rangeValue, id, index } = row;
7575 value = `${valueFormat(rangeValue, void 0, id, index)}`;
7576 } else {
7577 value = valueFormat(getRowValue(row), ...param);
7578 }
7579 if (value !== void 0) {
7580 if (row.name === null) {
7581 continue;
7582 }
7583 const name = nameFormat((_a = row.name) != null ? _a : row.id, ...param);
7584 const color2 = getBgColor(row);
7585 const contentValue = {
7586 CLASS_TOOLTIP_NAME: $TOOLTIP.tooltipName + $$.getTargetSelectorSuffix(row.id),
7587 COLOR: tplStr || !$$.patterns ? color2 : `<svg><rect style="fill:${color2}" width="10" height="10"></rect></svg>`,
7588 NAME: name,
7589 VALUE: value
7590 };
7591 if (tplStr && isObject(contents.text)) {
7592 const index = targetIds.indexOf(row.id);
7593 Object.keys(contents.text).forEach((key) => {
7594 contentValue[key] = contents.text[key][index];
7595 });
7596 }
7597 text += tplProcess(tpl[1], contentValue);
7598 }
7599 }
7600 return `${text}</table>`;
7601 },
7602 /**
7603 * Get the content template string
7604 * @param {string} tplStr Tempalte string
7605 * @returns {Array} Template string
7606 * @private
7607 */
7608 getTooltipContentTemplate(tplStr) {
7609 return (tplStr || `<table class="{=CLASS_TOOLTIP}"><tbody>
7610 {=TITLE}
7611 {{<tr class="{=CLASS_TOOLTIP_NAME}">
7612 <td class="name">${this.patterns ? `{=COLOR}` : `<span style="background-color:{=COLOR}"></span>`}{=NAME}</td>
7613 <td class="value">{=VALUE}</td>
7614 </tr>}}
7615 </tbody></table>`).replace(/(\r?\n|\t)/g, "").split(/{{(.*)}}/);
7616 },
7617 /**
7618 * Update tooltip position coordinate
7619 * @param {object} dataToShow Data object
7620 * @param {SVGElement} eventTarget Event element
7621 * @private
7622 */
7623 setTooltipPosition(dataToShow, eventTarget) {
7624 var _a, _b;
7625 const $$ = this;
7626 const { config, scale, state, $el: { eventRect, tooltip, svg } } = $$;
7627 const { bindto } = config.tooltip_contents;
7628 const isRotated = config.axis_rotated;
7629 const datum = tooltip == null ? void 0 : tooltip.datum();
7630 if (!bindto && datum) {
7631 const data = dataToShow != null ? dataToShow : JSON.parse(datum.current);
7632 const [x, y] = getPointer(state.event, eventTarget != null ? eventTarget : eventRect == null ? void 0 : eventRect.node());
7633 const currPos = { x, y };
7634 if (state.hasAxis && scale.x && datum && "x" in datum) {
7635 const getYPos = (value = 0, id, axisId = "y") => {
7636 var _a2;
7637 const scaleFn = scale[id ? (_a2 = $$.axis) == null ? void 0 : _a2.getId(id) : axisId];
7638 return scaleFn ? scaleFn(value) + (isRotated ? state.margin.left : state.margin.top) : 0;
7639 };
7640 currPos.xAxis = scale.x(datum.x) + // add margin only when user specified tooltip.position function
7641 (config.tooltip_position ? isRotated ? state.margin.top : state.margin.left : 0);
7642 if (data.length === 1) {
7643 currPos.yAxis = getYPos(data[0].value, data[0].id);
7644 } else {
7645 currPos.yAxis = getYPos;
7646 }
7647 }
7648 const { width = 0, height = 0 } = datum;
7649 const pos = (_b = (_a = config.tooltip_position) == null ? void 0 : _a.bind($$.api)(
7650 data,
7651 width,
7652 height,
7653 eventRect == null ? void 0 : eventRect.node(),
7654 currPos
7655 )) != null ? _b : hasViewBox(svg) ? $$.getTooltipPositionViewBox.bind($$)(width, height, currPos) : $$.getTooltipPosition.bind($$)(width, height, currPos);
7656 ["top", "left"].forEach((v) => {
7657 const value = pos[v];
7658 tooltip.style(v, `${value}px`);
7659 if (v === "left" && !datum.xPosInPercent) {
7660 datum.xPosInPercent = value / state.current.width * 100;
7661 }
7662 });
7663 }
7664 },
7665 /**
7666 * Get tooltip position when svg has vieBox attribute
7667 * @param {number} tWidth Tooltip width value
7668 * @param {number} tHeight Tooltip height value
7669 * @param {object} currPos Current event position value from SVG coordinate
7670 * @returns {object} top, left value
7671 */
7672 getTooltipPositionViewBox(tWidth, tHeight, currPos) {
7673 var _a, _b;
7674 const $$ = this;
7675 const { $el: { eventRect, svg }, config, state } = $$;
7676 const isRotated = config.axis_rotated;
7677 const hasArcType = $$.hasArcType() || state.hasFunnel || state.hasTreemap;
7678 const target = (_b = (_a = hasArcType ? svg : eventRect) == null ? void 0 : _a.node()) != null ? _b : state.event.target;
7679 let { x, y } = currPos;
7680 if (state.hasAxis) {
7681 x = isRotated ? x : currPos.xAxis;
7682 y = isRotated ? currPos.xAxis : y;
7683 }
7684 const ctm = getTransformCTM(target, x, y, false);
7685 const rect = target.getBoundingClientRect();
7686 const size = getTransformCTM(target, 20, 0, false).x;
7687 let top = ctm.y;
7688 let left = ctm.x + tWidth / 2 + size;
7689 if (hasArcType) {
7690 if (state.hasFunnel || state.hasTreemap || state.hasRadar) {
7691 left -= tWidth / 2 + size;
7692 top += tHeight;
7693 } else {
7694 top += rect.height / 2;
7695 left += rect.width / 2 - (tWidth - size);
7696 }
7697 }
7698 if (left + tWidth > rect.width) {
7699 left = rect.width - tWidth - size;
7700 }
7701 if (top + tHeight > rect.height) {
7702 top -= tHeight * 2;
7703 }
7704 return {
7705 top,
7706 left
7707 };
7708 },
7709 /**
7710 * Returns the position of the tooltip
7711 * @param {string} tWidth Width value of tooltip element
7712 * @param {string} tHeight Height value of tooltip element
7713 * @param {object} currPos Current mouse position
7714 * @returns {object} top, left value
7715 * @private
7716 */
7717 getTooltipPosition(tWidth, tHeight, currPos) {
7718 var _a, _b, _c;
7719 const $$ = this;
7720 const { config, scale, state } = $$;
7721 const { width, height, current, hasFunnel, hasRadar, hasTreemap, isLegendRight, inputType } = state;
7722 const hasGauge = $$.hasType("gauge") && !config.gauge_fullCircle;
7723 const isRotated = config.axis_rotated;
7724 const hasArcType = $$.hasArcType();
7725 const svgLeft = $$.getSvgLeft(true);
7726 let chartRight = svgLeft + current.width - $$.getCurrentPaddingByDirection("right");
7727 const size = 20;
7728 let { x, y } = currPos;
7729 if (hasRadar) {
7730 x += x >= width / 2 ? 15 : -(tWidth + 15);
7731 y += 15;
7732 } else if (hasArcType) {
7733 const notTouch = inputType !== "touch";
7734 if (notTouch) {
7735 let titlePadding = (_b = (_a = $$.getTitlePadding) == null ? void 0 : _a.call($$)) != null ? _b : 0;
7736 if (titlePadding && hasGauge && ((_c = config.arc_rangeText_values) == null ? void 0 : _c.length)) {
7737 titlePadding += 10;
7738 }
7739 x += (width - (isLegendRight ? $$.getLegendWidth() : 0)) / 2;
7740 y += (hasGauge ? height : height / 2 + tHeight) + titlePadding;
7741 }
7742 } else if (hasFunnel || hasTreemap) {
7743 y += tHeight;
7744 } else {
7745 const padding = {
7746 top: $$.getCurrentPaddingByDirection("top", true),
7747 left: $$.getCurrentPaddingByDirection("left", true)
7748 };
7749 if (isRotated) {
7750 x += svgLeft + padding.left + size;
7751 y = padding.top + currPos.xAxis + size;
7752 chartRight -= svgLeft;
7753 } else {
7754 x = svgLeft + padding.left + size + (scale.zoom ? x : currPos.xAxis);
7755 y += padding.top - 5;
7756 }
7757 }
7758 if (x + tWidth + 15 > chartRight) {
7759 x -= tWidth + (hasFunnel || hasTreemap || hasArcType ? 0 : isRotated ? size * 2 : 38);
7760 }
7761 if (y + tHeight > current.height) {
7762 const gap = hasTreemap ? tHeight + 10 : 30;
7763 y -= hasGauge ? tHeight * 1.5 : tHeight + gap;
7764 }
7765 const pos = { top: y, left: x };
7766 Object.keys(pos).forEach((v) => {
7767 if (pos[v] < 0) {
7768 pos[v] = 0;
7769 }
7770 });
7771 return pos;
7772 },
7773 /**
7774 * Show the tooltip
7775 * @param {object} selectedData Data object
7776 * @param {SVGElement} eventTarget Event element
7777 * @private
7778 */
7779 showTooltip(selectedData, eventTarget) {
7780 const $$ = this;
7781 const { config, $el: { tooltip } } = $$;
7782 const dataToShow = selectedData.filter((d) => d && isValue($$.getBaseValue(d)));
7783 if (!tooltip || dataToShow.length === 0 || !config.tooltip_show) {
7784 return;
7785 }
7786 let datum = tooltip.datum();
7787 const dataStr = JSON.stringify(selectedData);
7788 if (!datum || datum.current !== dataStr) {
7789 const { index, x } = selectedData.concat().sort()[0];
7790 callFn(config.tooltip_onshow, $$.api, selectedData);
7791 tooltip.html($$.getTooltipHTML(
7792 selectedData,
7793 // data
7794 $$.axis ? $$.axis.getXAxisTickFormat() : $$.categoryName.bind($$),
7795 // defaultTitleFormat
7796 $$.getDefaultValueFormat(),
7797 // defaultValueFormat
7798 $$.color
7799 // color
7800 )).style("display", null).style("visibility", null).datum(datum = {
7801 index,
7802 x,
7803 current: dataStr,
7804 width: tooltip.property("offsetWidth"),
7805 height: tooltip.property("offsetHeight")
7806 });
7807 callFn(config.tooltip_onshown, $$.api, selectedData);
7808 $$._handleLinkedCharts(true, index);
7809 }
7810 $$.setTooltipPosition(dataToShow, eventTarget);
7811 },
7812 /**
7813 * Adjust tooltip position on resize event
7814 * @private
7815 */
7816 bindTooltipResizePos() {
7817 const $$ = this;
7818 const { resizeFunction, state, $el: { tooltip } } = $$;
7819 resizeFunction.add(() => {
7820 if (tooltip.style("display") === "block") {
7821 const { current } = state;
7822 const { width, xPosInPercent } = tooltip.datum();
7823 let value = current.width / 100 * xPosInPercent;
7824 const diff = current.width - (value + width);
7825 if (diff < 0) {
7826 value += diff;
7827 }
7828 tooltip.style("left", `${value}px`);
7829 }
7830 });
7831 },
7832 /**
7833 * Hide the tooltip
7834 * @param {boolean} force Force to hide
7835 * @private
7836 */
7837 hideTooltip(force) {
7838 var _a;
7839 const $$ = this;
7840 const { api, config, $el: { tooltip } } = $$;
7841 if (tooltip && tooltip.style("display") !== "none" && (!config.tooltip_doNotHide || force)) {
7842 const selectedData = JSON.parse((_a = tooltip.datum().current) != null ? _a : {});
7843 callFn(config.tooltip_onhide, api, selectedData);
7844 tooltip.style("display", "none").style("visibility", "hidden").datum(null);
7845 callFn(config.tooltip_onhidden, api, selectedData);
7846 }
7847 },
7848 /**
7849 * Toggle display for linked chart instances
7850 * @param {boolean} show true: show, false: hide
7851 * @param {number} index x Axis index
7852 * @private
7853 */
7854 _handleLinkedCharts(show, index) {
7855 const $$ = this;
7856 const { charts, config, state: { event } } = $$;
7857 if ((event == null ? void 0 : event.isTrusted) && config.tooltip_linked && charts.length > 1) {
7858 const linkedName = config.tooltip_linked_name;
7859 charts.filter((c) => c !== $$.api).forEach((c) => {
7860 const { config: config2, $el } = c.internal;
7861 const isLinked = config2.tooltip_linked;
7862 const name = config2.tooltip_linked_name;
7863 const isInDom = browser_doc.body.contains($el.chart.node());
7864 if (isLinked && linkedName === name && isInDom) {
7865 const data = $el.tooltip.data()[0];
7866 const isNotSameIndex = index !== (data == null ? void 0 : data.index);
7867 try {
7868 c.tooltip[show && isNotSameIndex ? "show" : "hide"]({ index });
7869 } catch (e) {
7870 }
7871 }
7872 });
7873 }
7874 },
7875 /**
7876 * Update tooltip content on redraw
7877 * - In a situation where tooltip is displayed and data load happens, it should reflect loaded data to tooltip
7878 * @param {d3Selection} context Event rect element
7879 * @param {number} index Data index
7880 * @private
7881 */
7882 updateTooltipOnRedraw(context, index) {
7883 var _a;
7884 const $$ = this;
7885 const {
7886 config,
7887 $el: { eventRect, svg, tooltip },
7888 state: { event, hasAxis, hasRadar, hasTreemap }
7889 } = $$;
7890 if ((tooltip == null ? void 0 : tooltip.style("display")) === "block" && event) {
7891 const rect = context != null ? context : (_a = hasRadar ? svg : eventRect) == null ? void 0 : _a.node();
7892 if (hasAxis || hasRadar) {
7893 if ($$.isMultipleX()) {
7894 $$.selectRectForMultipleXs(rect, false);
7895 } else {
7896 const idx = index != null ? index : $$.getDataIndexFromEvent(event);
7897 if (index === -1) {
7898 $$.api.tooltip.hide();
7899 } else {
7900 $$.selectRectForSingle(rect, idx);
7901 $$.setExpand(idx, null, true);
7902 }
7903 }
7904 } else {
7905 const { clientX, clientY } = event;
7906 setTimeout(() => {
7907 let target = [clientX, clientY].every(Number.isFinite) && browser_doc.elementFromPoint(clientX, clientY);
7908 const data = target && (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
7909 if (data) {
7910 const d = $$.hasArcType() ? $$.convertToArcData($$.updateAngle(data)) : data == null ? void 0 : data.data;
7911 hasTreemap && (target = svg.node());
7912 d && $$.showTooltip([d], target);
7913 } else {
7914 $$.api.tooltip.hide();
7915 }
7916 }, config.transition_duration);
7917 }
7918 }
7919 }
7920});
7921
7922;// ./src/ChartInternal/internals/transform.ts
7923
7924
7925/* harmony default export */ var transform = ({
7926 getTranslate(target, index = 0) {
7927 var _a;
7928 const $$ = this;
7929 const { config, state } = $$;
7930 const isRotated = config.axis_rotated;
7931 let padding = 0;
7932 let x;
7933 let y;
7934 if (index && /^(x|y2?)$/.test(target)) {
7935 padding = $$.getAxisSize(target) * index;
7936 }
7937 if (target === "main") {
7938 x = asHalfPixel(state.margin.left);
7939 y = asHalfPixel(state.margin.top);
7940 } else if (target === "context") {
7941 x = asHalfPixel(state.margin2.left);
7942 y = asHalfPixel(state.margin2.top);
7943 } else if (target === "legend") {
7944 x = state.margin3.left;
7945 y = state.margin3.top;
7946 } else if (target === "x") {
7947 x = isRotated ? -padding : 0;
7948 y = isRotated ? 0 : state.height + padding;
7949 } else if (target === "y") {
7950 x = isRotated ? 0 : -padding;
7951 y = isRotated ? state.height + padding : 0;
7952 } else if (target === "y2") {
7953 x = isRotated ? 0 : state.width + padding;
7954 y = isRotated ? -padding - 1 : 0;
7955 } else if (target === "subX") {
7956 x = 0;
7957 y = isRotated ? 0 : state.height2;
7958 } else if (target === "arc") {
7959 x = state.arcWidth / 2;
7960 y = state.arcHeight / 2;
7961 if ((_a = config.arc_rangeText_values) == null ? void 0 : _a.length) {
7962 y += 5 + ($$.hasType("gauge") && config.title_text ? 10 : 0);
7963 }
7964 } else if (target === "polar") {
7965 x = state.arcWidth / 2;
7966 y = state.arcHeight / 2;
7967 } else if (target === "radar") {
7968 const [width, height] = $$.getRadarSize();
7969 x = state.width / 2 - width;
7970 y = state.height / 2 - height;
7971 }
7972 return `translate(${x}, ${y})`;
7973 },
7974 transformMain(withTransition, transitions) {
7975 const $$ = this;
7976 const { $el: { main }, $T } = $$;
7977 const xAxis = (transitions == null ? void 0 : transitions.axisX) ? transitions.axisX : $T(main.select(`.${$AXIS.axisX}`), withTransition);
7978 const yAxis = (transitions == null ? void 0 : transitions.axisY) ? transitions.axisY : $T(main.select(`.${$AXIS.axisY}`), withTransition);
7979 const y2Axis = (transitions == null ? void 0 : transitions.axisY2) ? transitions.axisY2 : $T(main.select(`.${$AXIS.axisY2}`), withTransition);
7980 $T(main, withTransition).attr("transform", $$.getTranslate("main"));
7981 xAxis.attr("transform", $$.getTranslate("x"));
7982 yAxis.attr("transform", $$.getTranslate("y"));
7983 y2Axis.attr("transform", $$.getTranslate("y2"));
7984 main.select(`.${$ARC.chartArcs}`).attr("transform", $$.getTranslate("arc"));
7985 },
7986 transformAll(withTransition, transitions) {
7987 const $$ = this;
7988 const { config, state: { hasAxis, hasFunnel, hasTreemap }, $el } = $$;
7989 !hasFunnel && !hasTreemap && $$.transformMain(withTransition, transitions);
7990 hasAxis && config.subchart_show && $$.transformContext(withTransition, transitions);
7991 $el.legend && $$.transformLegend(withTransition);
7992 }
7993});
7994
7995;// ./src/ChartInternal/internals/type.ts
7996
7997
7998/* harmony default export */ var type = ({
7999 /**
8000 * Check if the given chart type is valid
8001 * @param {string} type Chart type string
8002 * @returns {boolean}
8003 * @private
8004 */
8005 isValidChartType(type) {
8006 return !!(type && Object.values(TYPE).indexOf(type) > -1);
8007 },
8008 setTargetType(targetIds, type) {
8009 const $$ = this;
8010 const { config, state: { withoutFadeIn } } = $$;
8011 $$.mapToTargetIds(targetIds).forEach((id) => {
8012 withoutFadeIn[id] = type === config.data_types[id];
8013 config.data_types[id] = type;
8014 });
8015 if (!targetIds) {
8016 config.data_type = type;
8017 }
8018 },
8019 /**
8020 * Updte current used chart types
8021 * @private
8022 */
8023 updateTypesElements() {
8024 const $$ = this;
8025 const { state: { current } } = $$;
8026 Object.keys(TYPE).forEach((v) => {
8027 const t = TYPE[v];
8028 const has = $$.hasType(t, null, true);
8029 const idx = current.types.indexOf(t);
8030 if (idx === -1 && has) {
8031 current.types.push(t);
8032 } else if (idx > -1 && !has) {
8033 current.types.splice(idx, 1);
8034 }
8035 });
8036 $$.setChartElements();
8037 },
8038 /**
8039 * Check if given chart types exists
8040 * @param {string} type Chart type
8041 * @param {Array} targetsValue Data array
8042 * @param {boolean} checkFromData Force to check type cotains from data targets
8043 * @returns {boolean}
8044 * @private
8045 */
8046 hasType(type, targetsValue, checkFromData = false) {
8047 var _a;
8048 const $$ = this;
8049 const { config, state: { current } } = $$;
8050 const types = config.data_types;
8051 const targets = targetsValue || $$.data.targets;
8052 let has = false;
8053 if (!checkFromData && ((_a = current.types) == null ? void 0 : _a.indexOf(type)) > -1) {
8054 has = true;
8055 } else if (targets == null ? void 0 : targets.length) {
8056 targets.forEach((target) => {
8057 const t = types[target.id];
8058 if (t === type || !t && type === "line") {
8059 has = true;
8060 }
8061 });
8062 } else if (Object.keys(types).length) {
8063 Object.keys(types).forEach((id) => {
8064 if (types[id] === type) {
8065 has = true;
8066 }
8067 });
8068 } else {
8069 has = config.data_type === type;
8070 }
8071 return has;
8072 },
8073 /**
8074 * Check if contains given chart types
8075 * @param {string} type Type key
8076 * @param {object} targets Target data
8077 * @param {Array} exclude Excluded types
8078 * @returns {boolean}
8079 * @private
8080 */
8081 hasTypeOf(type, targets, exclude = []) {
8082 if (type in TYPE_BY_CATEGORY) {
8083 return !TYPE_BY_CATEGORY[type].filter((v) => exclude.indexOf(v) === -1).every((v) => !this.hasType(v, targets));
8084 }
8085 return false;
8086 },
8087 /**
8088 * Check if given data is certain chart type
8089 * @param {object} d Data object
8090 * @param {string|Array} type chart type
8091 * @returns {boolean}
8092 * @private
8093 */
8094 isTypeOf(d, type) {
8095 var _a;
8096 const id = isString(d) ? d : d.id;
8097 const dataType = this.config && (((_a = this.config.data_types) == null ? void 0 : _a[id]) || this.config.data_type);
8098 return isArray(type) ? type.indexOf(dataType) >= 0 : dataType === type;
8099 },
8100 hasPointType() {
8101 const $$ = this;
8102 return $$.hasTypeOf("Line") || $$.hasType("bubble") || $$.hasType("scatter");
8103 },
8104 /**
8105 * Check if contains arc types chart
8106 * @param {object} targets Target data
8107 * @param {Array} exclude Excluded types
8108 * @returns {boolean}
8109 * @private
8110 */
8111 hasArcType(targets, exclude) {
8112 return this.hasTypeOf("Arc", targets, exclude);
8113 },
8114 hasMultiArcGauge() {
8115 return this.hasType("gauge") && this.config.gauge_type === "multi";
8116 },
8117 isLineType(d) {
8118 const id = isString(d) ? d : d.id;
8119 return !this.config.data_types[id] || this.isTypeOf(id, TYPE_BY_CATEGORY.Line);
8120 },
8121 isStepType(d) {
8122 return this.isTypeOf(d, TYPE_BY_CATEGORY.Step);
8123 },
8124 isSplineType(d) {
8125 return this.isTypeOf(d, TYPE_BY_CATEGORY.Spline);
8126 },
8127 isAreaType(d) {
8128 return this.isTypeOf(d, TYPE_BY_CATEGORY.Area);
8129 },
8130 isAreaRangeType(d) {
8131 return this.isTypeOf(d, TYPE_BY_CATEGORY.AreaRange);
8132 },
8133 isBarType(d) {
8134 return this.isTypeOf(d, "bar");
8135 },
8136 isBubbleType(d) {
8137 return this.isTypeOf(d, "bubble");
8138 },
8139 isCandlestickType(d) {
8140 return this.isTypeOf(d, "candlestick");
8141 },
8142 isScatterType(d) {
8143 return this.isTypeOf(d, "scatter");
8144 },
8145 isTreemapType(d) {
8146 return this.isTypeOf(d, "treemap");
8147 },
8148 isPieType(d) {
8149 return this.isTypeOf(d, "pie");
8150 },
8151 isFunnelType(d) {
8152 return this.isTypeOf(d, "funnel");
8153 },
8154 isGaugeType(d) {
8155 return this.isTypeOf(d, "gauge");
8156 },
8157 isDonutType(d) {
8158 return this.isTypeOf(d, "donut");
8159 },
8160 isPolarType(d) {
8161 return this.isTypeOf(d, "polar");
8162 },
8163 isRadarType(d) {
8164 return this.isTypeOf(d, "radar");
8165 },
8166 isArcType(d) {
8167 return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d) || this.isPolarType(d) || this.isRadarType(d);
8168 },
8169 // determine if is 'circle' data point
8170 isCirclePoint(node) {
8171 const { config } = this;
8172 const pattern = config.point_pattern;
8173 let isCircle = false;
8174 if ((node == null ? void 0 : node.tagName) === "circle") {
8175 isCircle = true;
8176 } else {
8177 isCircle = config.point_type === "circle" && (!pattern || isArray(pattern) && pattern.length === 0);
8178 }
8179 return isCircle;
8180 },
8181 lineData(d) {
8182 return this.isLineType(d) ? [d] : [];
8183 },
8184 arcData(d) {
8185 return this.isArcType(d.data) ? [d] : [];
8186 },
8187 /**
8188 * Get data adapt for data label showing
8189 * @param {object} d Data object
8190 * @returns {Array}
8191 * @private
8192 */
8193 labelishData(d) {
8194 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)) : [];
8195 },
8196 barLineBubbleData(d) {
8197 return this.isBarType(d) || this.isLineType(d) || this.isBubbleType(d) ? d.values : [];
8198 },
8199 // https://github.com/d3/d3-shape#curves
8200 isInterpolationType(type) {
8201 return [
8202 "basis",
8203 "basis-closed",
8204 "basis-open",
8205 "bundle",
8206 "cardinal",
8207 "cardinal-closed",
8208 "cardinal-open",
8209 "catmull-rom",
8210 "catmull-rom-closed",
8211 "catmull-rom-open",
8212 "linear",
8213 "linear-closed",
8214 "monotone-x",
8215 "monotone-y",
8216 "natural"
8217 ].indexOf(type) >= 0;
8218 }
8219});
8220
8221// EXTERNAL MODULE: external {"commonjs":"d3-shape","commonjs2":"d3-shape","amd":"d3-shape","root":"d3"}
8222var external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_ = __webpack_require__(9);
8223;// ./src/ChartInternal/shape/shape.ts
8224
8225
8226
8227
8228function getGroupedDataPointsFn(d) {
8229 const $$ = this;
8230 let fn;
8231 if ($$.isLineType(d)) {
8232 fn = $$.generateGetLinePoints($$.getShapeIndices($$.isLineType));
8233 } else if ($$.isBarType(d)) {
8234 fn = $$.generateGetBarPoints($$.getShapeIndices($$.isBarType));
8235 }
8236 return fn;
8237}
8238/* harmony default export */ var shape = ({
8239 /**
8240 * Get the shape draw function
8241 * @returns {object}
8242 * @private
8243 */
8244 getDrawShape() {
8245 const $$ = this;
8246 const isRotated = $$.config.axis_rotated;
8247 const { hasRadar, hasTreemap } = $$.state;
8248 const shape = { type: {}, indices: {}, pos: {} };
8249 !hasTreemap && ["bar", "candlestick", "line", "area"].forEach((v) => {
8250 const name = capitalize(/^(bubble|scatter)$/.test(v) ? "line" : v);
8251 if ($$.hasType(v) || $$.hasTypeOf(name) || v === "line" && ($$.hasType("bubble") || $$.hasType("scatter"))) {
8252 const indices = $$.getShapeIndices($$[`is${name}Type`]);
8253 const drawFn = $$[`generateDraw${name}`];
8254 shape.indices[v] = indices;
8255 shape.type[v] = drawFn ? drawFn.bind($$)(indices, false) : void 0;
8256 }
8257 });
8258 if (!$$.hasArcType() || hasRadar || hasTreemap) {
8259 let cx;
8260 let cy;
8261 if (!hasTreemap) {
8262 cx = hasRadar ? $$.radarCircleX : isRotated ? $$.circleY : $$.circleX;
8263 cy = hasRadar ? $$.radarCircleY : isRotated ? $$.circleX : $$.circleY;
8264 }
8265 shape.pos = {
8266 xForText: $$.generateXYForText(shape.indices, true),
8267 yForText: $$.generateXYForText(shape.indices, false),
8268 cx: (cx || function() {
8269 }).bind($$),
8270 cy: (cy || function() {
8271 }).bind($$)
8272 };
8273 }
8274 return shape;
8275 },
8276 /**
8277 * Get shape's indices according it's position within each axis tick.
8278 *
8279 * From the below example, indices will be:
8280 * ==> {data1: 0, data2: 0, data3: 1, data4: 1, __max__: 1}
8281 *
8282 * data1 data3 data1 data3
8283 * data2 data4 data2 data4
8284 * -------------------------
8285 * 0 1
8286 * @param {Function} typeFilter Chart type filter function
8287 * @returns {object} Indices object with its position
8288 */
8289 getShapeIndices(typeFilter) {
8290 const $$ = this;
8291 const { config } = $$;
8292 const xs = config.data_xs;
8293 const hasXs = notEmpty(xs);
8294 const indices = {};
8295 let i = hasXs ? {} : 0;
8296 if (hasXs) {
8297 getUnique(Object.keys(xs).map((v) => xs[v])).forEach((v) => {
8298 i[v] = 0;
8299 indices[v] = {};
8300 });
8301 }
8302 $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach((d) => {
8303 var _a;
8304 const xKey = d.id in xs ? xs[d.id] : "";
8305 const ind = xKey ? indices[xKey] : indices;
8306 for (let j = 0, groups; groups = config.data_groups[j]; j++) {
8307 if (groups.indexOf(d.id) < 0) {
8308 continue;
8309 }
8310 for (let k = 0, key; key = groups[k]; k++) {
8311 if (key in ind) {
8312 ind[d.id] = ind[key];
8313 break;
8314 }
8315 if (d.id !== key && xKey) {
8316 ind[key] = (_a = ind[d.id]) != null ? _a : i[xKey];
8317 }
8318 }
8319 }
8320 if (isUndefined(ind[d.id])) {
8321 ind[d.id] = xKey ? i[xKey]++ : i++;
8322 ind.__max__ = (xKey ? i[xKey] : i) - 1;
8323 }
8324 });
8325 return indices;
8326 },
8327 /**
8328 * Get indices value based on data ID value
8329 * @param {object} indices Indices object
8330 * @param {object} d Data row
8331 * @param {string} caller Caller function name (Used only for 'sparkline' plugin)
8332 * @returns {object} Indices object
8333 * @private
8334 */
8335 getIndices(indices, d, caller) {
8336 const $$ = this;
8337 const { data_xs: xs, bar_indices_removeNull: removeNull } = $$.config;
8338 const { id, index } = d;
8339 if ($$.isBarType(id) && removeNull) {
8340 const ind = {};
8341 $$.getAllValuesOnIndex(index, true).forEach((v, i) => {
8342 ind[v.id] = i;
8343 ind.__max__ = i;
8344 });
8345 return ind;
8346 }
8347 return notEmpty(xs) ? indices[xs[id]] : indices;
8348 },
8349 /**
8350 * Get indices max number
8351 * @param {object} indices Indices object
8352 * @returns {number} Max number
8353 * @private
8354 */
8355 getIndicesMax(indices) {
8356 return notEmpty(this.config.data_xs) ? (
8357 // if is multiple xs, return total sum of xs' __max__ value
8358 Object.keys(indices).map((v) => indices[v].__max__ || 0).reduce((acc, curr) => acc + curr)
8359 ) : indices.__max__;
8360 },
8361 getShapeX(offset, indices, isSub) {
8362 const $$ = this;
8363 const { config, scale } = $$;
8364 const currScale = isSub ? scale.subX : scale.zoom || scale.x;
8365 const barOverlap = config.bar_overlap;
8366 const barPadding = config.bar_padding;
8367 const sum = (p, c) => p + c;
8368 const halfWidth = isObjectType(offset) && (offset._$total.length ? offset._$total.reduce(sum) / 2 : 0);
8369 return (d) => {
8370 const ind = $$.getIndices(indices, d, "getShapeX");
8371 const index = d.id in ind ? ind[d.id] : 0;
8372 const targetsNum = (ind.__max__ || 0) + 1;
8373 let x = 0;
8374 if (notEmpty(d.x)) {
8375 const xPos = currScale(d.x, true);
8376 if (halfWidth) {
8377 const offsetWidth = offset[d.id] || offset._$width;
8378 x = barOverlap ? xPos - offsetWidth / 2 : xPos - offsetWidth + offset._$total.slice(0, index + 1).reduce(sum) - halfWidth;
8379 } else {
8380 x = xPos - (isNumber(offset) ? offset : offset._$width) * (targetsNum / 2 - (barOverlap ? 1 : index));
8381 }
8382 }
8383 if (offset && x && targetsNum > 1 && barPadding) {
8384 if (index) {
8385 x += barPadding * index;
8386 }
8387 if (targetsNum > 2) {
8388 x -= (targetsNum - 1) * barPadding / 2;
8389 } else if (targetsNum === 2) {
8390 x -= barPadding / 2;
8391 }
8392 }
8393 return x;
8394 };
8395 },
8396 getShapeY(isSub) {
8397 const $$ = this;
8398 const isStackNormalized = $$.isStackNormalized();
8399 return (d) => {
8400 let { value } = d;
8401 if (isNumber(d)) {
8402 value = d;
8403 } else if ($$.isAreaRangeType(d)) {
8404 value = $$.getBaseValue(d, "mid");
8405 } else if (isStackNormalized) {
8406 value = $$.getRatio("index", d, true);
8407 } else if ($$.isBubbleZType(d)) {
8408 value = $$.getBubbleZData(d.value, "y");
8409 } else if ($$.isBarRangeType(d)) {
8410 value = value[1];
8411 }
8412 return $$.getYScaleById(d.id, isSub)(value);
8413 };
8414 },
8415 /**
8416 * Get shape based y Axis min value
8417 * @param {string} id Data id
8418 * @returns {number}
8419 * @private
8420 */
8421 getShapeYMin(id) {
8422 const $$ = this;
8423 const axisId = $$.axis.getId(id);
8424 const scale = $$.scale[axisId];
8425 const [yMin] = scale.domain();
8426 const inverted = $$.config[`axis_${axisId}_inverted`];
8427 return !$$.isGrouped(id) && !inverted && yMin > 0 ? yMin : 0;
8428 },
8429 /**
8430 * Get Shape's offset data
8431 * @param {Function} typeFilter Type filter function
8432 * @returns {object}
8433 * @private
8434 */
8435 getShapeOffsetData(typeFilter) {
8436 const $$ = this;
8437 const targets = $$.orderTargets(
8438 $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))
8439 );
8440 const isStackNormalized = $$.isStackNormalized();
8441 const shapeOffsetTargets = targets.map((target) => {
8442 let rowValues = target.values;
8443 const values = {};
8444 if ($$.isStepType(target)) {
8445 rowValues = $$.convertValuesToStep(rowValues);
8446 }
8447 const rowValueMapByXValue = rowValues.reduce((out, d) => {
8448 const key = Number(d.x);
8449 out[key] = d;
8450 values[key] = isStackNormalized ? $$.getRatio("index", d, true) : d.value;
8451 return out;
8452 }, {});
8453 return {
8454 id: target.id,
8455 rowValues,
8456 rowValueMapByXValue,
8457 values
8458 };
8459 });
8460 const indexMapByTargetId = targets.reduce((out, { id }, index) => {
8461 out[id] = index;
8462 return out;
8463 }, {});
8464 return { indexMapByTargetId, shapeOffsetTargets };
8465 },
8466 getShapeOffset(typeFilter, indices, isSub) {
8467 const $$ = this;
8468 const { shapeOffsetTargets, indexMapByTargetId } = $$.getShapeOffsetData(
8469 typeFilter
8470 );
8471 const groupsZeroAs = $$.config.data_groupsZeroAs;
8472 return (d, idx) => {
8473 const { id, value, x } = d;
8474 const ind = $$.getIndices(indices, d);
8475 const scale = $$.getYScaleById(id, isSub);
8476 if ($$.isBarRangeType(d)) {
8477 return scale(value[0]);
8478 }
8479 const dataXAsNumber = Number(x);
8480 const y0 = scale(groupsZeroAs === "zero" ? 0 : $$.getShapeYMin(id));
8481 let offset = y0;
8482 shapeOffsetTargets.filter((t) => t.id !== id && ind[t.id] === ind[id]).forEach((t) => {
8483 const {
8484 id: tid,
8485 rowValueMapByXValue,
8486 rowValues,
8487 values: tvalues
8488 } = t;
8489 if (indexMapByTargetId[tid] < indexMapByTargetId[id]) {
8490 const rValue = tvalues[dataXAsNumber];
8491 let row = rowValues[idx];
8492 if (!row || Number(row.x) !== dataXAsNumber) {
8493 row = rowValueMapByXValue[dataXAsNumber];
8494 }
8495 if ((row == null ? void 0 : row.value) * value >= 0 && isNumber(rValue)) {
8496 const addOffset = value === 0 ? groupsZeroAs === "positive" && rValue > 0 || groupsZeroAs === "negative" && rValue < 0 : true;
8497 if (addOffset) {
8498 offset += scale(rValue) - y0;
8499 }
8500 }
8501 }
8502 });
8503 return offset;
8504 };
8505 },
8506 /**
8507 * Get data's y coordinate
8508 * @param {object} d Target data
8509 * @param {number} i Index number
8510 * @returns {number} y coordinate
8511 * @private
8512 */
8513 circleY(d, i) {
8514 const $$ = this;
8515 const id = d.id;
8516 let points;
8517 if ($$.isGrouped(id)) {
8518 points = getGroupedDataPointsFn.bind($$)(d);
8519 }
8520 return points ? points(d, i)[0][1] : $$.getYScaleById(id)($$.getBaseValue(d));
8521 },
8522 getBarW(type, axis, targetsNum) {
8523 var _a, _b, _c, _d, _e;
8524 const $$ = this;
8525 const { config, org, scale, state } = $$;
8526 const maxDataCount = $$.getMaxDataCount();
8527 const isGrouped = type === "bar" && ((_a = config.data_groups) == null ? void 0 : _a.length);
8528 const configName = `${type}_width`;
8529 const { k } = (_c = (_b = $$.getZoomTransform) == null ? void 0 : _b.call($$)) != null ? _c : { k: 1 };
8530 const xMinMax = [
8531 (_d = config.axis_x_min) != null ? _d : org.xDomain[0],
8532 (_e = config.axis_x_max) != null ? _e : org.xDomain[1]
8533 ].map($$.axis.isTimeSeries() ? parseDate.bind($$) : Number);
8534 let tickInterval = axis.tickInterval(maxDataCount);
8535 if (scale.zoom && !$$.axis.isCategorized() && k > 1) {
8536 const isSameMinMax = xMinMax.every((v, i) => v === org.xDomain[i]);
8537 tickInterval = org.xDomain.map((v, i) => {
8538 const value = isSameMinMax ? v : v - Math.abs(xMinMax[i]);
8539 return scale.zoom(value);
8540 }).reduce((a, c) => Math.abs(a) + c) / maxDataCount;
8541 }
8542 const getWidth = (id) => {
8543 const width = id ? config[configName][id] : config[configName];
8544 const ratio = id ? width.ratio : config[`${configName}_ratio`];
8545 const max = id ? width.max : config[`${configName}_max`];
8546 const w = isNumber(width) ? width : isFunction(width) ? width.call($$, state.width, targetsNum, maxDataCount) : targetsNum ? tickInterval * ratio / targetsNum : 0;
8547 return max && w > max ? max : w;
8548 };
8549 let result = getWidth();
8550 if (!isGrouped && isObjectType(config[configName])) {
8551 result = { _$width: result, _$total: [] };
8552 $$.filterTargetsToShow($$.data.targets).forEach((v) => {
8553 if (config[configName][v.id]) {
8554 result[v.id] = getWidth(v.id);
8555 result._$total.push(result[v.id] || result._$width);
8556 }
8557 });
8558 }
8559 return result;
8560 },
8561 /**
8562 * Get shape element
8563 * @param {string} shapeName Shape string
8564 * @param {number} i Index number
8565 * @param {string} id Data series id
8566 * @returns {d3Selection}
8567 * @private
8568 */
8569 getShapeByIndex(shapeName, i, id) {
8570 const $$ = this;
8571 const { $el } = $$;
8572 const suffix = isValue(i) ? `-${i}` : ``;
8573 let shape = $el[shapeName];
8574 if (shape && !shape.empty()) {
8575 shape = shape.filter((d) => id ? d.id === id : true).filter((d) => isValue(i) ? d.index === i : true);
8576 } else {
8577 shape = (id ? $el.main.selectAll(
8578 `.${classes[`${shapeName}s`]}${$$.getTargetSelectorSuffix(id)}`
8579 ) : $el.main).selectAll(`.${classes[shapeName]}${suffix}`);
8580 }
8581 return shape;
8582 },
8583 isWithinShape(that, d) {
8584 var _a;
8585 const $$ = this;
8586 const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(that);
8587 let isWithin;
8588 if (!$$.isTargetToShow(d.id)) {
8589 isWithin = false;
8590 } else if ((_a = $$.hasValidPointType) == null ? void 0 : _a.call($$, that.nodeName)) {
8591 isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScaleById(d.id)($$.getBaseValue(d))) : $$.isWithinCircle(
8592 that,
8593 $$.isBubbleType(d) ? $$.pointSelectR(d) * 1.5 : 0
8594 );
8595 } else if (that.nodeName === "path") {
8596 isWithin = shape.classed(classes.bar) ? $$.isWithinBar(that) : true;
8597 }
8598 return isWithin;
8599 },
8600 getInterpolate(d) {
8601 const $$ = this;
8602 const interpolation = $$.getInterpolateType(d);
8603 return {
8604 basis: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBasis,
8605 "basis-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBasisClosed,
8606 "basis-open": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBasisOpen,
8607 bundle: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveBundle,
8608 cardinal: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCardinal,
8609 "cardinal-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCardinalClosed,
8610 "cardinal-open": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCardinalOpen,
8611 "catmull-rom": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCatmullRom,
8612 "catmull-rom-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCatmullRomClosed,
8613 "catmull-rom-open": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveCatmullRomOpen,
8614 "monotone-x": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveMonotoneX,
8615 "monotone-y": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveMonotoneY,
8616 natural: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveNatural,
8617 "linear-closed": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveLinearClosed,
8618 linear: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveLinear,
8619 step: external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveStep,
8620 "step-after": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveStepAfter,
8621 "step-before": external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.curveStepBefore
8622 }[interpolation];
8623 },
8624 getInterpolateType(d) {
8625 const $$ = this;
8626 const { config } = $$;
8627 const type = config.spline_interpolation_type;
8628 const interpolation = $$.isInterpolationType(type) ? type : "cardinal";
8629 return $$.isSplineType(d) ? interpolation : $$.isStepType(d) ? config.line_step_type : "linear";
8630 },
8631 isWithinBar(that) {
8632 const mouse = getPointer(this.state.event, that);
8633 const list = getRectSegList(that);
8634 const [seg0, seg1] = list;
8635 const x = Math.min(seg0.x, seg1.x);
8636 const y = Math.min(seg0.y, seg1.y);
8637 const offset = this.config.bar_sensitivity;
8638 const { width, height } = that.getBBox();
8639 const sx = x - offset;
8640 const ex = x + width + offset;
8641 const sy = y + height + offset;
8642 const ey = y - offset;
8643 const isWithin = sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
8644 return isWithin;
8645 }
8646});
8647
8648;// ./src/ChartInternal/ChartInternal.ts
8649var ChartInternal_defProp = Object.defineProperty;
8650var ChartInternal_defNormalProp = (obj, key, value) => key in obj ? ChartInternal_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8651var ChartInternal_publicField = (obj, key, value) => ChartInternal_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682class ChartInternal {
8683 constructor(api) {
8684 ChartInternal_publicField(this, "api");
8685 // API interface
8686 ChartInternal_publicField(this, "config");
8687 // config object
8688 ChartInternal_publicField(this, "cache");
8689 // cache instance
8690 ChartInternal_publicField(this, "$el");
8691 // elements
8692 ChartInternal_publicField(this, "state");
8693 // state variables
8694 ChartInternal_publicField(this, "charts");
8695 // all Chart instances array within page (equivalent of 'bb.instances')
8696 // data object
8697 ChartInternal_publicField(this, "data", {
8698 xs: {},
8699 targets: []
8700 });
8701 // Axis
8702 ChartInternal_publicField(this, "axis");
8703 // Axis
8704 // scales
8705 ChartInternal_publicField(this, "scale", {
8706 x: null,
8707 y: null,
8708 y2: null,
8709 subX: null,
8710 subY: null,
8711 subY2: null,
8712 zoom: null
8713 });
8714 // original values
8715 ChartInternal_publicField(this, "org", {
8716 xScale: null,
8717 xDomain: null
8718 });
8719 // formatter function
8720 ChartInternal_publicField(this, "color");
8721 ChartInternal_publicField(this, "patterns");
8722 ChartInternal_publicField(this, "levelColor");
8723 ChartInternal_publicField(this, "point");
8724 ChartInternal_publicField(this, "brush");
8725 // format function
8726 ChartInternal_publicField(this, "format", {
8727 extraLineClasses: null,
8728 xAxisTick: null,
8729 dataTime: null,
8730 // dataTimeFormat
8731 defaultAxisTime: null,
8732 // defaultAxisTimeFormat
8733 axisTime: null
8734 // axisTimeFormat
8735 });
8736 const $$ = this;
8737 $$.api = api;
8738 $$.config = new Options();
8739 $$.cache = new Cache();
8740 const store = new Store();
8741 $$.$el = store.getStore("element");
8742 $$.state = store.getStore("state");
8743 $$.$T = $$.$T.bind($$);
8744 }
8745 /**
8746 * Get the selection based on transition config
8747 * @param {SVGElement|d3Selection} selection Target selection
8748 * @param {boolean} force Force transition
8749 * @param {string} name Transition name
8750 * @returns {d3Selection}
8751 * @private
8752 */
8753 $T(selection, force, name) {
8754 const { config, state } = this;
8755 const duration = config.transition_duration;
8756 const subchart = config.subchart_show;
8757 let t = selection;
8758 if (t) {
8759 if ("tagName" in t) {
8760 t = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(t);
8761 }
8762 const transit = (force !== false && duration || force) && (!state.zooming || state.dragging) && !state.resizing && state.rendered && !subchart;
8763 t = transit ? t.transition(name).duration(duration) : t;
8764 }
8765 return t;
8766 }
8767 beforeInit() {
8768 const $$ = this;
8769 $$.callPluginHook("$beforeInit");
8770 callFn($$.config.onbeforeinit, $$.api);
8771 }
8772 afterInit() {
8773 const $$ = this;
8774 $$.callPluginHook("$afterInit");
8775 callFn($$.config.onafterinit, $$.api);
8776 }
8777 init() {
8778 const $$ = this;
8779 const { config, state, $el } = $$;
8780 const useCssRule = config.boost_useCssRule;
8781 checkModuleImport($$);
8782 state.hasRadar = !state.hasAxis && $$.hasType("radar");
8783 state.hasFunnel = !state.hasAxis && $$.hasType("funnel");
8784 state.hasTreemap = !state.hasAxis && $$.hasType("treemap");
8785 state.hasAxis = !$$.hasArcType() && !state.hasFunnel && !state.hasTreemap;
8786 state.datetimeId = `bb-${+/* @__PURE__ */ new Date() * getRandom()}`;
8787 if (useCssRule) {
8788 const styleEl = browser_doc.createElement("style");
8789 styleEl.type = "text/css";
8790 browser_doc.head.appendChild(styleEl);
8791 state.style = {
8792 rootSelctor: `.${state.datetimeId}`,
8793 sheet: styleEl.sheet
8794 };
8795 $el.style = styleEl;
8796 }
8797 const bindto = {
8798 element: config.bindto,
8799 classname: "bb"
8800 };
8801 if (isObject(config.bindto)) {
8802 bindto.element = config.bindto.element || "#chart";
8803 bindto.classname = config.bindto.classname || bindto.classname;
8804 }
8805 $el.chart = isFunction(bindto.element.node) ? config.bindto.element : (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(bindto.element || []);
8806 if ($el.chart.empty()) {
8807 $el.chart = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(browser_doc.body.appendChild(browser_doc.createElement("div")));
8808 }
8809 $el.chart.html("").classed(bindto.classname, true).classed(state.datetimeId, useCssRule).style("position", "relative");
8810 $$.initParams();
8811 $$.initToRender();
8812 }
8813 /**
8814 * Initialize the rendering process
8815 * @param {boolean} forced Force to render process
8816 * @private
8817 */
8818 initToRender(forced) {
8819 const $$ = this;
8820 const { config, state, $el: { chart } } = $$;
8821 const isHidden = () => hasStyle(chart, { display: "none", visibility: "hidden" });
8822 const isLazy = config.render.lazy === false ? false : config.render.lazy || isHidden();
8823 const MutationObserver = win.MutationObserver;
8824 if (isLazy && MutationObserver && config.render.observe !== false && !forced) {
8825 new MutationObserver((mutation, observer) => {
8826 if (!isHidden()) {
8827 observer.disconnect();
8828 !state.rendered && $$.initToRender(true);
8829 }
8830 }).observe(chart.node(), {
8831 attributes: true,
8832 attributeFilter: ["class", "style"]
8833 });
8834 }
8835 if (!isLazy || forced) {
8836 $$.convertData(config, (res) => {
8837 $$.initWithData(res);
8838 $$.afterInit();
8839 });
8840 }
8841 }
8842 initParams() {
8843 var _a;
8844 const $$ = this;
8845 const { config, format: format2, state } = $$;
8846 const isRotated = config.axis_rotated;
8847 $$.color = $$.generateColor();
8848 $$.levelColor = $$.generateLevelColor();
8849 if (config.padding === false) {
8850 config.axis_x_show = false;
8851 config.axis_y_show = false;
8852 config.axis_y2_show = false;
8853 config.subchart_show = false;
8854 }
8855 if ($$.hasPointType() || ((_a = $$.hasLegendDefsPoint) == null ? void 0 : _a.call($$))) {
8856 $$.point = $$.generatePoint();
8857 }
8858 if (state.hasAxis) {
8859 $$.initClip();
8860 format2.extraLineClasses = $$.generateExtraLineClass();
8861 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;
8862 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;
8863 const isDragZoom = $$.config.zoom_enabled && $$.config.zoom_type === "drag";
8864 format2.defaultAxisTime = (d) => {
8865 const { x, zoom } = $$.scale;
8866 const isZoomed = isDragZoom ? zoom : zoom && x.orgDomain().toString() !== zoom.domain().toString();
8867 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";
8868 return format2.axisTime(specifier)(d);
8869 };
8870 }
8871 state.isLegendRight = config.legend_position === "right";
8872 state.isLegendInset = config.legend_position === "inset";
8873 state.isLegendTop = config.legend_inset_anchor === "top-left" || config.legend_inset_anchor === "top-right";
8874 state.isLegendLeft = config.legend_inset_anchor === "top-left" || config.legend_inset_anchor === "bottom-left";
8875 state.rotatedPadding.top = $$.getResettedPadding(state.rotatedPadding.top);
8876 state.rotatedPadding.right = isRotated && !config.axis_x_show ? 0 : 30;
8877 state.inputType = convertInputType(
8878 config.interaction_inputType_mouse,
8879 config.interaction_inputType_touch
8880 );
8881 }
8882 initWithData(data2) {
8883 var _a, _b, _c;
8884 const $$ = this;
8885 const { config, scale: scale2, state, $el, org } = $$;
8886 const { hasAxis, hasFunnel, hasTreemap } = state;
8887 const hasInteraction = config.interaction_enabled;
8888 const hasPolar = $$.hasType("polar");
8889 const labelsBGColor = config.data_labels_backgroundColors;
8890 if (hasAxis) {
8891 $$.axis = $$.getAxisInstance();
8892 config.zoom_enabled && $$.initZoom();
8893 }
8894 $$.data.xs = {};
8895 $$.data.targets = $$.convertDataToTargets(data2);
8896 if (config.data_filter) {
8897 $$.data.targets = $$.data.targets.filter(config.data_filter.bind($$.api));
8898 }
8899 if (config.data_hide) {
8900 $$.addHiddenTargetIds(
8901 config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide
8902 );
8903 }
8904 if (config.legend_hide) {
8905 $$.addHiddenLegendIds(
8906 config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide
8907 );
8908 }
8909 $$.updateSizes();
8910 $$.updateScales(true);
8911 if (hasAxis) {
8912 const { x, y, y2, subX, subY, subY2 } = scale2;
8913 if (x) {
8914 x.domain(sortValue($$.getXDomain($$.data.targets), !config.axis_x_inverted));
8915 subX.domain(x.domain());
8916 org.xDomain = x.domain();
8917 }
8918 if (y) {
8919 y.domain($$.getYDomain($$.data.targets, "y"));
8920 subY.domain(y.domain());
8921 }
8922 if (y2) {
8923 y2.domain($$.getYDomain($$.data.targets, "y2"));
8924 subY2 && subY2.domain(y2.domain());
8925 }
8926 }
8927 $el.svg = $el.chart.append("svg").style("overflow", "hidden").style("display", "block");
8928 if (hasInteraction && state.inputType) {
8929 const isTouch = state.inputType === "touch";
8930 const { onclick, onover, onout } = config;
8931 $el.svg.on("click", (onclick == null ? void 0 : onclick.bind($$.api)) || null).on(isTouch ? "touchstart" : "mouseenter", (onover == null ? void 0 : onover.bind($$.api)) || null).on(isTouch ? "touchend" : "mouseleave", (onout == null ? void 0 : onout.bind($$.api)) || null);
8932 }
8933 config.svg_classname && $el.svg.attr("class", config.svg_classname);
8934 const hasColorPatterns = isFunction(config.color_tiles) && $$.patterns;
8935 if (hasAxis || hasColorPatterns || hasPolar || hasTreemap || labelsBGColor || ((_a = $$.hasLegendDefsPoint) == null ? void 0 : _a.call($$))) {
8936 $el.defs = $el.svg.append("defs");
8937 if (hasAxis) {
8938 ["id", "idXAxis", "idYAxis", "idGrid"].forEach((v) => {
8939 $$.appendClip($el.defs, state.clip[v]);
8940 });
8941 }
8942 $$.generateTextBGColorFilter(labelsBGColor);
8943 if (hasColorPatterns) {
8944 $$.patterns.forEach((p) => $el.defs.append(() => p.node));
8945 }
8946 }
8947 $$.updateSvgSize();
8948 $$.bindResize();
8949 const main = $el.svg.append("g").classed($COMMON.main, true).attr("transform", hasFunnel || hasTreemap ? null : $$.getTranslate("main"));
8950 $el.main = main;
8951 config.subchart_show && $$.initSubchart();
8952 config.tooltip_show && $$.initTooltip();
8953 config.title_text && $$.initTitle();
8954 !hasTreemap && config.legend_show && $$.initLegend();
8955 if (config.data_empty_label_text) {
8956 main.append("text").attr("class", `${$TEXT.text} ${$COMMON.empty}`).attr("text-anchor", "middle").attr("dominant-baseline", "middle");
8957 }
8958 if (hasAxis) {
8959 config.regions.length && $$.initRegion();
8960 !config.clipPath && $$.axis.init();
8961 }
8962 main.append("g").classed($COMMON.chart, true).attr("clip-path", hasAxis ? state.clip.path : null);
8963 $$.callPluginHook("$init");
8964 $$.initChartElements();
8965 if (hasAxis) {
8966 hasInteraction && ((_b = $$.initEventRect) == null ? void 0 : _b.call($$));
8967 $$.initGrid();
8968 config.clipPath && ((_c = $$.axis) == null ? void 0 : _c.init());
8969 }
8970 $$.updateTargets($$.data.targets);
8971 $$.updateDimension();
8972 callFn(config.oninit, $$.api);
8973 $$.setBackground();
8974 $$.redraw({
8975 withTransition: false,
8976 withTransform: true,
8977 withUpdateXDomain: true,
8978 withUpdateOrgXDomain: true,
8979 withTransitionForAxis: false,
8980 initializing: true
8981 });
8982 if (config.data_onmin || config.data_onmax) {
8983 const minMax = $$.getMinMaxData();
8984 callFn(config.data_onmin, $$.api, minMax.min);
8985 callFn(config.data_onmax, $$.api, minMax.max);
8986 }
8987 config.tooltip_show && $$.initShowTooltip();
8988 state.rendered = true;
8989 }
8990 /**
8991 * Initialize chart elements
8992 * @private
8993 */
8994 initChartElements() {
8995 const $$ = this;
8996 const { hasAxis, hasRadar, hasTreemap } = $$.state;
8997 const types = [];
8998 if (hasAxis) {
8999 const shapes = ["bar", "bubble", "candlestick", "line"];
9000 if ($$.config.bar_front) {
9001 shapes.push(shapes.shift());
9002 }
9003 shapes.forEach((v) => {
9004 const name = capitalize(v);
9005 if (v === "line" && $$.hasTypeOf(name) || $$.hasType(v)) {
9006 types.push(name);
9007 }
9008 });
9009 } else if (hasTreemap) {
9010 types.push("Treemap");
9011 } else if ($$.hasType("funnel")) {
9012 types.push("Funnel");
9013 } else {
9014 const hasPolar = $$.hasType("polar");
9015 if (!hasRadar) {
9016 types.push("Arc", "Pie");
9017 }
9018 if ($$.hasType("gauge")) {
9019 types.push("Gauge");
9020 } else if (hasRadar) {
9021 types.push("Radar");
9022 } else if (hasPolar) {
9023 types.push("Polar");
9024 }
9025 }
9026 types.forEach((v) => {
9027 $$[`init${v}`]();
9028 });
9029 notEmpty($$.config.data_labels) && !$$.hasArcType(null, ["radar"]) && $$.initText();
9030 }
9031 /**
9032 * Set chart elements
9033 * @private
9034 */
9035 setChartElements() {
9036 const $$ = this;
9037 const {
9038 $el: {
9039 chart,
9040 svg,
9041 defs,
9042 main,
9043 tooltip: tooltip2,
9044 legend: legend2,
9045 title: title2,
9046 grid,
9047 needle,
9048 arcs: arc,
9049 circle: circles,
9050 bar: bars,
9051 candlestick,
9052 line: lines,
9053 area: areas,
9054 text: texts
9055 }
9056 } = $$;
9057 $$.api.$ = {
9058 chart,
9059 svg,
9060 defs,
9061 main,
9062 tooltip: tooltip2,
9063 legend: legend2,
9064 title: title2,
9065 grid,
9066 arc,
9067 circles,
9068 bar: { bars },
9069 candlestick,
9070 line: { lines, areas },
9071 needle,
9072 text: { texts }
9073 };
9074 }
9075 /**
9076 * Set background element/image
9077 * @private
9078 */
9079 setBackground() {
9080 const $$ = this;
9081 const { config: { background: bg }, state, $el: { svg } } = $$;
9082 if (notEmpty(bg)) {
9083 const element = svg.select("g").insert(bg.imgUrl ? "image" : "rect", ":first-child");
9084 if (bg.imgUrl) {
9085 element.attr("href", bg.imgUrl);
9086 } else if (bg.color) {
9087 element.style("fill", bg.color).attr("clip-path", state.clip.path);
9088 }
9089 element.attr("class", bg.class || null).attr("width", "100%").attr("height", "100%");
9090 }
9091 }
9092 /**
9093 * Update targeted element with given data
9094 * @param {object} targets Data object formatted as 'target'
9095 * @private
9096 */
9097 updateTargets(targets) {
9098 var _a;
9099 const $$ = this;
9100 const { hasAxis, hasFunnel, hasRadar, hasTreemap } = $$.state;
9101 const helper = (type) => $$[`updateTargetsFor${type}`](
9102 targets.filter($$[`is${type}Type`].bind($$))
9103 );
9104 $$.updateTargetsForText(targets);
9105 if (hasAxis) {
9106 ["bar", "candlestick", "line"].forEach((v) => {
9107 const name = capitalize(v);
9108 if (v === "line" && $$.hasTypeOf(name) || $$.hasType(v)) {
9109 helper(name);
9110 }
9111 });
9112 $$.updateTargetsForSubchart && $$.updateTargetsForSubchart(targets);
9113 } else if ($$.hasArcType(targets)) {
9114 let type = "Arc";
9115 if (hasRadar) {
9116 type = "Radar";
9117 } else if ($$.hasType("polar")) {
9118 type = "Polar";
9119 }
9120 helper(type);
9121 } else if (hasFunnel) {
9122 helper("Funnel");
9123 } else if (hasTreemap) {
9124 helper("Treemap");
9125 }
9126 const hasPointType = $$.hasType("bubble") || $$.hasType("scatter");
9127 if (hasPointType) {
9128 (_a = $$.updateTargetForCircle) == null ? void 0 : _a.call($$);
9129 }
9130 $$.filterTargetsToShowAtInit(hasPointType);
9131 }
9132 /**
9133 * Display targeted elements at initialization
9134 * @param {boolean} hasPointType whether has point type(bubble, scatter) or not
9135 * @private
9136 */
9137 filterTargetsToShowAtInit(hasPointType = false) {
9138 const $$ = this;
9139 const { $el: { svg }, $T } = $$;
9140 let selector = `.${$COMMON.target}`;
9141 if (hasPointType) {
9142 selector += `, .${$CIRCLE.chartCircles} > .${$CIRCLE.circles}`;
9143 }
9144 $T(svg.selectAll(selector).filter((d) => $$.isTargetToShow(d.id))).style("opacity", null);
9145 }
9146 getWithOption(options) {
9147 const withOptions = {
9148 Dimension: true,
9149 EventRect: true,
9150 Legend: false,
9151 Subchart: true,
9152 Transform: false,
9153 Transition: true,
9154 TrimXDomain: true,
9155 UpdateXAxis: "UpdateXDomain",
9156 UpdateXDomain: false,
9157 UpdateOrgXDomain: false,
9158 TransitionForExit: "Transition",
9159 TransitionForAxis: "Transition",
9160 Y: true
9161 };
9162 Object.keys(withOptions).forEach((key) => {
9163 let defVal = withOptions[key];
9164 if (isString(defVal)) {
9165 defVal = withOptions[defVal];
9166 }
9167 withOptions[key] = getOption(options, `with${key}`, defVal);
9168 });
9169 return withOptions;
9170 }
9171 initialOpacity(d) {
9172 const $$ = this;
9173 const { withoutFadeIn } = $$.state;
9174 const r = $$.getBaseValue(d) !== null && withoutFadeIn[d.id] ? null : "0";
9175 return r;
9176 }
9177 bindResize() {
9178 const $$ = this;
9179 const { config, state } = $$;
9180 const resizeFunction = generateResize(config.resize_timer);
9181 const list = [];
9182 list.push(() => callFn(config.onresize, $$.api));
9183 if (config.resize_auto === true) {
9184 list.push(() => {
9185 state.resizing = true;
9186 if (config.legend_show) {
9187 $$.updateSizes();
9188 $$.updateLegend();
9189 }
9190 $$.api.flush(false);
9191 });
9192 }
9193 list.push(() => {
9194 callFn(config.onresized, $$.api);
9195 state.resizing = false;
9196 });
9197 list.forEach((v) => resizeFunction.add(v));
9198 $$.resizeFunction = resizeFunction;
9199 win.addEventListener("resize", $$.resizeFunction = resizeFunction);
9200 }
9201 /**
9202 * Call plugin hook
9203 * @param {string} phase The lifecycle phase
9204 * @param {Array} args Arguments
9205 * @private
9206 */
9207 callPluginHook(phase, ...args) {
9208 this.config.plugins.forEach((v) => {
9209 if (phase === "$beforeInit") {
9210 v.$$ = this;
9211 this.api.plugins.push(v);
9212 }
9213 v[phase](...args);
9214 });
9215 }
9216}
9217extend(ChartInternal.prototype, [
9218 // common
9219 convert,
9220 data_data,
9221 load,
9222 category,
9223 internals_class,
9224 internals_color,
9225 domain,
9226 interactions_interaction,
9227 format,
9228 internals_legend,
9229 redraw,
9230 scale,
9231 shape,
9232 size,
9233 style,
9234 internals_text,
9235 internals_title,
9236 internals_tooltip,
9237 transform,
9238 type
9239]);
9240
9241;// ./src/config/config.ts
9242
9243function loadConfig(config) {
9244 const thisConfig = this.config;
9245 let target;
9246 let keys;
9247 let read;
9248 const find = () => {
9249 const key = keys.shift();
9250 if (key && target && isObjectType(target) && key in target) {
9251 target = target[key];
9252 return find();
9253 } else if (!key) {
9254 return target;
9255 }
9256 return void 0;
9257 };
9258 Object.keys(thisConfig).forEach((key) => {
9259 target = config;
9260 keys = key.split("_");
9261 read = find();
9262 if (isDefined(read)) {
9263 thisConfig[key] = read;
9264 }
9265 });
9266 if (this.api) {
9267 this.state.orgConfig = config;
9268 }
9269}
9270
9271;// ./src/Chart/api/chart.ts
9272
9273
9274/* harmony default export */ var chart = ({
9275 /**
9276 * Resize the chart.
9277 * @function resize
9278 * @instance
9279 * @memberof Chart
9280 * @param {object} size This argument should include width and height in pixels.
9281 * @param {number} [size.width] width value
9282 * @param {number} [size.height] height value
9283 * @example
9284 * // Resize to 640x480
9285 * chart.resize({
9286 * width: 640,
9287 * height: 480
9288 * });
9289 */
9290 resize(size) {
9291 const $$ = this.internal;
9292 const { config, state } = $$;
9293 if (state.rendered) {
9294 config.size_width = size ? size.width : null;
9295 config.size_height = size ? size.height : null;
9296 state.resizing = true;
9297 this.flush(false);
9298 $$.resizeFunction();
9299 }
9300 },
9301 /**
9302 * Force to redraw.
9303 * - **NOTE:** When zoom/subchart is used, the zoomed state will be resetted.
9304 * @function flush
9305 * @instance
9306 * @memberof Chart
9307 * @param {boolean} [soft] For soft redraw.
9308 * @example
9309 * chart.flush();
9310 *
9311 * // for soft redraw
9312 * chart.flush(true);
9313 */
9314 flush(soft) {
9315 var _a, _b;
9316 const $$ = this.internal;
9317 const { state, $el: { zoomResetBtn } } = $$;
9318 if (state.rendered) {
9319 if (state.resizing) {
9320 (_a = $$.brush) == null ? void 0 : _a.updateResize();
9321 } else {
9322 (_b = $$.axis) == null ? void 0 : _b.setOrient();
9323 }
9324 zoomResetBtn == null ? void 0 : zoomResetBtn.style("display", "none");
9325 $$.scale.zoom = null;
9326 soft ? $$.redraw({
9327 withTransform: true,
9328 withUpdateXDomain: true,
9329 withUpdateOrgXDomain: true,
9330 withLegend: true
9331 }) : $$.updateAndRedraw({
9332 withLegend: true,
9333 withTransition: false,
9334 withTransitionForTransform: false
9335 });
9336 if (!state.resizing && $$.brush) {
9337 $$.brush.getSelection().call($$.brush.move);
9338 $$.unselectRect();
9339 }
9340 } else {
9341 $$.initToRender(true);
9342 }
9343 },
9344 /**
9345 * Reset the chart object and remove element and events completely.
9346 * @function destroy
9347 * @instance
9348 * @memberof Chart
9349 * @returns {null}
9350 * @example
9351 * chart.destroy();
9352 */
9353 destroy() {
9354 const $$ = this.internal;
9355 const { $el: { chart, style, svg } } = $$;
9356 if (notEmpty($$)) {
9357 $$.callPluginHook("$willDestroy");
9358 $$.charts.splice($$.charts.indexOf(this), 1);
9359 $$.unbindAllEvents();
9360 svg.select("*").interrupt();
9361 $$.resizeFunction.clear();
9362 win.removeEventListener("resize", $$.resizeFunction);
9363 chart.classed("bb", false).style("position", null).selectChildren().remove();
9364 style && style.parentNode.removeChild(style);
9365 Object.keys(this).forEach((key) => {
9366 key === "internal" && Object.keys($$).forEach((k) => {
9367 $$[k] = null;
9368 });
9369 this[key] = null;
9370 delete this[key];
9371 });
9372 for (const key in this) {
9373 this[key] = () => {
9374 };
9375 }
9376 }
9377 return null;
9378 },
9379 /**
9380 * Get or set config option value.
9381 * - **NOTE**
9382 * - The option key name must be specified as the last level.
9383 * - when no argument is given, will return all specified generation options object only. (will exclude any other options not specified at the initialization)
9384 * @function config
9385 * @instance
9386 * @memberof Chart
9387 * @param {string} name The option key name.
9388 * @param {*} [value] The value accepted for indicated option.
9389 * @param {boolean} [redraw] Set to redraw with the new option changes.
9390 * - **NOTE:** Doesn't guarantee work in all circumstances. It can be applied for limited options only.
9391 * @returns {*}
9392 * @example
9393 *
9394 * // Getter
9395 * chart.config("gauge.max");
9396 *
9397 * // Getter specified with top level key name will not work.
9398 * // The option key name must be specified as the last level.
9399 * // chart.config("gauge"); // will not work
9400 *
9401 * // without any arguments, it returns generation config object
9402 * chart.config(); // {data: { ... }, axis: { ... }, ...}
9403 *
9404 * // Setter
9405 * chart.config("gauge.max", 100);
9406 *
9407 * // Setter specified with top level key name will not work.
9408 * // The option key name must be specified as the last level.
9409 * // chart.config("gauge", {min: 10, max: 20}); // will not work
9410 *
9411 * // Setter & redraw with the new option
9412 * chart.config("gauge.max", 100, true);
9413 */
9414 config(name, value, redraw) {
9415 const $$ = this.internal;
9416 const { config, state } = $$;
9417 const key = name == null ? void 0 : name.replace(/\./g, "_");
9418 let res;
9419 if (name && key in config) {
9420 if (isDefined(value)) {
9421 config[key] = value;
9422 res = value;
9423 redraw && this.flush();
9424 } else {
9425 res = config[key];
9426 }
9427 } else if (arguments.length === 0 || isEmpty(name)) {
9428 res = state.orgConfig;
9429 }
9430 return res;
9431 }
9432});
9433
9434;// ./src/Chart/api/color.ts
9435/* harmony default export */ var api_color = ({
9436 /**
9437 * Get the color
9438 * @function color
9439 * @instance
9440 * @memberof Chart
9441 * @param {string} id id to get the color
9442 * @returns {string}
9443 * @example
9444 * chart.color("data1");
9445 */
9446 color(id) {
9447 return this.internal.color(id);
9448 }
9449});
9450
9451;// ./src/Chart/api/data.ts
9452
9453const api_data_data = function(targetIds) {
9454 const { targets } = this.internal.data;
9455 if (!isUndefined(targetIds)) {
9456 const ids = isArray(targetIds) ? targetIds : [targetIds];
9457 return targets.filter((t) => ids.some((v) => v === t.id));
9458 }
9459 return targets;
9460};
9461extend(api_data_data, {
9462 /**
9463 * Get data shown in the chart.
9464 * @function data․shown
9465 * @instance
9466 * @memberof Chart
9467 * @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.
9468 * @returns {Array} Data objects
9469 * @example
9470 * // Get shown data by filtering to include only data1 data
9471 * chart.data.shown("data1");
9472 * // --> [{id: "data1", id_org: "data1", values: Array(6)}, ...]
9473 *
9474 * // Get shown data by filtering to include data1 and data2 data
9475 * chart.data.shown(["data1", "data2"]);
9476 *
9477 * // Get all shown data
9478 * chart.data.shown();
9479 */
9480 shown: function(targetIds) {
9481 return this.internal.filterTargetsToShow(this.data(targetIds));
9482 },
9483 /**
9484 * Get values of the data loaded in the chart.
9485 * @function data․values
9486 * @instance
9487 * @memberof Chart
9488 * @param {string|Array|null} targetIds This API returns the values of specified target. If this argument is not given, null will be retruned
9489 * @param {boolean} [flat=true] Get flatten values
9490 * @returns {Array} Data values
9491 * @example
9492 * // Get data1 values
9493 * chart.data.values("data1");
9494 * // --> [10, 20, 30, 40]
9495 */
9496 values: function(targetIds, flat = true) {
9497 let values = null;
9498 if (targetIds) {
9499 const targets = this.data(targetIds);
9500 if (isArray(targets)) {
9501 values = [];
9502 targets.forEach((v) => {
9503 const dataValue = v.values.map((d) => d.value);
9504 flat ? values = values.concat(dataValue) : values.push(dataValue);
9505 });
9506 }
9507 }
9508 return values;
9509 },
9510 /**
9511 * Get and set names of the data loaded in the chart.
9512 * @function data․names
9513 * @instance
9514 * @memberof Chart
9515 * @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).
9516 * @returns {object} Corresponding names according its key value, if specified names values.
9517 * @example
9518 * // Get current names
9519 * chart.data.names();
9520 * // --> {data1: "test1", data2: "test2"}
9521 *
9522 * // Update names
9523 * chart.data.names({
9524 * data1: "New Name 1",
9525 * data2: "New Name 2"
9526 * });
9527 */
9528 names: function(names) {
9529 const $$ = this.internal;
9530 return $$.updateDataAttributes("names", names);
9531 },
9532 /**
9533 * Get and set colors of the data loaded in the chart.
9534 * @function data․colors
9535 * @instance
9536 * @memberof Chart
9537 * @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).
9538 * @returns {object} Corresponding data color value according its key value.
9539 * @example
9540 * // Get current colors
9541 * chart.data.colors();
9542 * // --> {data1: "#00c73c", data2: "#fa7171"}
9543 *
9544 * // Update colors
9545 * chart.data.colors({
9546 * data1: "#FFFFFF",
9547 * data2: "#000000"
9548 * });
9549 */
9550 colors: function(colors) {
9551 return this.internal.updateDataAttributes("colors", colors);
9552 },
9553 /**
9554 * Get and set axes of the data loaded in the chart.
9555 * - **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
9556 * @function data․axes
9557 * @instance
9558 * @memberof Chart
9559 * @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
9560 * @returns {object} Corresponding axes value for data, if specified axes value.
9561 * @example
9562 * // Get current axes
9563 * chart.data.axes();
9564 * // --> {data1: "y"}
9565 *
9566 * // Update axes
9567 * chart.data.axes({
9568 * data1: "y",
9569 * data2: "y2"
9570 * });
9571 */
9572 axes: function(axes) {
9573 return this.internal.updateDataAttributes("axes", axes);
9574 },
9575 /**
9576 * Get the minimum data value bound to the chart
9577 * @function data․min
9578 * @instance
9579 * @memberof Chart
9580 * @returns {Array} Data objects
9581 * @example
9582 * // Get current axes
9583 * chart.data.min();
9584 * // --> [{x: 0, value: 30, id: "data1", index: 0}, ...]
9585 */
9586 min: function() {
9587 return this.internal.getMinMaxData().min;
9588 },
9589 /**
9590 * Get the maximum data value bound to the chart
9591 * @function data․max
9592 * @instance
9593 * @memberof Chart
9594 * @returns {Array} Data objects
9595 * @example
9596 * // Get current axes
9597 * chart.data.max();
9598 * // --> [{x: 3, value: 400, id: "data1", index: 3}, ...]
9599 */
9600 max: function() {
9601 return this.internal.getMinMaxData().max;
9602 }
9603});
9604/* harmony default export */ var api_data = ({ data: api_data_data });
9605
9606;// ./src/Chart/api/export.ts
9607
9608
9609
9610const b64EncodeUnicode = (str) => {
9611 var _a, _b;
9612 return (_b = (_a = win).btoa) == null ? void 0 : _b.call(
9613 _a,
9614 encodeURIComponent(str).replace(
9615 /%([0-9A-F]{2})/g,
9616 (match, p) => String.fromCharCode(Number(`0x${p}`))
9617 )
9618 );
9619};
9620function nodeToSvgDataUrl(node, option, orgSize) {
9621 const { width, height } = option || orgSize;
9622 const serializer = new XMLSerializer();
9623 const clone = node.cloneNode(true);
9624 const cssText = getCssRules(toArray(browser_doc.styleSheets)).filter((r) => r.cssText).map((r) => r.cssText);
9625 clone.setAttribute("xmlns", external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.xhtml);
9626 clone.style.margin = "0";
9627 clone.style.padding = "0";
9628 if (option.preserveFontStyle) {
9629 clone.querySelectorAll("text").forEach((t) => {
9630 t.innerHTML = "";
9631 });
9632 }
9633 const nodeXml = serializer.serializeToString(clone);
9634 const style = browser_doc.createElement("style");
9635 style.appendChild(browser_doc.createTextNode(cssText.join("\n")));
9636 const styleXml = serializer.serializeToString(style);
9637 const dataStr = `<svg xmlns="${external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.svg}" width="${width}" height="${height}"
9638 viewBox="0 0 ${orgSize.width} ${orgSize.height}"
9639 preserveAspectRatio="${(option == null ? void 0 : option.preserveAspectRatio) === false ? "none" : "xMinYMid meet"}">
9640 <foreignObject width="100%" height="100%">
9641 ${styleXml}
9642 ${nodeXml.replace(/(url\()[^#]+/g, "$1")}
9643 </foreignObject></svg>`;
9644 return `data:image/svg+xml;base64,${b64EncodeUnicode(dataStr)}`;
9645}
9646function getCoords(elem, svgOffset) {
9647 const { top, left } = svgOffset;
9648 const { x, y } = elem.getBBox();
9649 const { a, b, c, d, e, f } = elem.getScreenCTM();
9650 const { width, height } = elem.getBoundingClientRect();
9651 return {
9652 x: a * x + c * y + e - left,
9653 y: b * x + d * y + f - top + (height - Math.round(height / 4)),
9654 width,
9655 height
9656 };
9657}
9658function getGlyph(svg) {
9659 const { left, top } = svg.getBoundingClientRect();
9660 const filterFn = (t) => t.textContent || t.childElementCount;
9661 const glyph = [];
9662 toArray(svg.querySelectorAll("text")).filter(filterFn).forEach((t) => {
9663 const getStyleFn = (ts) => {
9664 const { fill, fontFamily, fontSize, textAnchor, transform } = win.getComputedStyle(
9665 ts
9666 );
9667 const { x, y, width, height } = getCoords(ts, { left, top });
9668 return {
9669 [ts.textContent]: {
9670 x,
9671 y,
9672 width,
9673 height,
9674 fill,
9675 fontFamily,
9676 fontSize,
9677 textAnchor,
9678 transform
9679 }
9680 };
9681 };
9682 if (t.childElementCount > 1) {
9683 const text = [];
9684 toArray(t.querySelectorAll("tspan")).filter(filterFn).forEach((ts) => {
9685 glyph.push(getStyleFn(ts));
9686 });
9687 return text;
9688 } else {
9689 glyph.push(getStyleFn(t));
9690 }
9691 });
9692 return glyph;
9693}
9694function renderText(ctx, glyph) {
9695 glyph.forEach((g) => {
9696 Object.keys(g).forEach((key) => {
9697 const { x, y, width, height, fill, fontFamily, fontSize, transform } = g[key];
9698 ctx.save();
9699 ctx.font = `${fontSize} ${fontFamily}`;
9700 ctx.fillStyle = fill;
9701 if (transform === "none") {
9702 ctx.fillText(key, x, y);
9703 } else {
9704 const args = transform.replace(/(matrix|\(|\))/g, "").split(",");
9705 if (args.splice(4).every((v) => +v === 0)) {
9706 args.push(x + width - width / 4);
9707 args.push(y - height + height / 3);
9708 } else {
9709 args.push(x);
9710 args.push(y);
9711 }
9712 ctx.transform(...args);
9713 ctx.fillText(key, 0, 0);
9714 }
9715 ctx.restore();
9716 });
9717 });
9718}
9719/* harmony default export */ var api_export = ({
9720 /**
9721 * Export chart as an image.
9722 * - **NOTE:**
9723 * - 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
9724 * - 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.
9725 * @function export
9726 * @instance
9727 * @memberof Chart
9728 * @param {object} option Export option
9729 * @param {string} [option.mimeType="image/png"] The desired output image format. (ex. 'image/png' for png, 'image/jpeg' for jpeg format)
9730 * @param {number} [option.width={currentWidth}] width
9731 * @param {number} [option.height={currentHeigth}] height
9732 * @param {boolean} [option.preserveAspectRatio=true] Preserve aspect ratio on given size
9733 * @param {boolean} [option.preserveFontStyle=false] Preserve font style(font-family).<br>
9734 * **NOTE:**
9735 * - This option is useful when outlink web font style's `font-family` are applied to chart's text element.
9736 * - Text element's position(especially "transformed") can't be preserved correctly according the page's layout condition.
9737 * - If need to preserve accurate text position, embed the web font data within to the page and set `preserveFontStyle=false`.
9738 * - 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>
9739 * @param {Function} [callback] The callback to be invoked when export is ready.
9740 * @returns {string} dataURI
9741 * @example
9742 * chart.export();
9743 * // --> "data:image/svg+xml;base64,PHN..."
9744 *
9745 * // Initialize the download automatically
9746 * chart.export({mimeType: "image/png"}, dataUrl => {
9747 * const link = document.createElement("a");
9748 *
9749 * link.download = `${Date.now()}.png`;
9750 * link.href = dataUrl;
9751 * link.innerHTML = "Download chart as image";
9752 *
9753 * document.body.appendChild(link);
9754 * });
9755 *
9756 * // Resize the exported image
9757 * chart.export(
9758 * {
9759 * width: 800,
9760 * height: 600,
9761 * preserveAspectRatio: false,
9762 * preserveFontStyle: false,
9763 * mimeType: "image/png"
9764 * },
9765 * dataUrl => { ... }
9766 * );
9767 */
9768 export(option, callback) {
9769 const $$ = this.internal;
9770 const { state, $el: { chart, svg } } = $$;
9771 const { width, height } = state.current;
9772 const opt = mergeObj({
9773 width,
9774 height,
9775 preserveAspectRatio: true,
9776 preserveFontStyle: false,
9777 mimeType: "image/png"
9778 }, option);
9779 const svgDataUrl = nodeToSvgDataUrl(chart.node(), opt, { width, height });
9780 const glyph = opt.preserveFontStyle ? getGlyph(svg.node()) : [];
9781 if (callback && isFunction(callback)) {
9782 const img = new Image();
9783 img.crossOrigin = "Anonymous";
9784 img.onload = () => {
9785 const canvas = browser_doc.createElement("canvas");
9786 const ctx = canvas.getContext("2d");
9787 canvas.width = opt.width || width;
9788 canvas.height = opt.height || height;
9789 ctx.drawImage(img, 0, 0);
9790 if (glyph.length) {
9791 renderText(ctx, glyph);
9792 glyph.length = 0;
9793 }
9794 callback.bind(this)(canvas.toDataURL(opt.mimeType));
9795 };
9796 img.src = svgDataUrl;
9797 }
9798 return svgDataUrl;
9799 }
9800});
9801
9802;// ./src/Chart/api/focus.ts
9803
9804
9805/* harmony default export */ var api_focus = ({
9806 /**
9807 * This API highlights specified targets and fade out the others.<br><br>
9808 * 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.
9809 * @function focus
9810 * @instance
9811 * @memberof Chart
9812 * @param {string|Array} targetIdsValue Target ids to be highlighted.
9813 * @example
9814 * // data1 will be highlighted and the others will be faded out
9815 * chart.focus("data1");
9816 *
9817 * // data1 and data2 will be highlighted and the others will be faded out
9818 * chart.focus(["data1", "data2"]);
9819 *
9820 * // all targets will be highlighted
9821 * chart.focus();
9822 */
9823 focus(targetIdsValue) {
9824 const $$ = this.internal;
9825 const { state } = $$;
9826 const targetIds = $$.mapToTargetIds(targetIdsValue);
9827 const candidates = $$.$el.svg.selectAll(
9828 $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
9829 );
9830 this.revert();
9831 this.defocus();
9832 candidates.classed($FOCUS.focused, true).classed($FOCUS.defocused, false);
9833 if ($$.hasArcType() && !state.hasRadar) {
9834 $$.expandArc(targetIds);
9835 $$.hasType("gauge") && $$.markOverlapped(targetIdsValue, $$, `.${$GAUGE.gaugeValue}`);
9836 }
9837 $$.toggleFocusLegend(targetIds, true);
9838 state.focusedTargetIds = targetIds;
9839 state.defocusedTargetIds = state.defocusedTargetIds.filter((id) => targetIds.indexOf(id) < 0);
9840 },
9841 /**
9842 * This API fades out specified targets and reverts the others.<br><br>
9843 * 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.
9844 * @function defocus
9845 * @instance
9846 * @memberof Chart
9847 * @param {string|Array} targetIdsValue Target ids to be faded out.
9848 * @example
9849 * // data1 will be faded out and the others will be reverted.
9850 * chart.defocus("data1");
9851 *
9852 * // data1 and data2 will be faded out and the others will be reverted.
9853 * chart.defocus(["data1", "data2"]);
9854 *
9855 * // all targets will be faded out.
9856 * chart.defocus();
9857 */
9858 defocus(targetIdsValue) {
9859 const $$ = this.internal;
9860 const { state } = $$;
9861 const targetIds = $$.mapToTargetIds(targetIdsValue);
9862 const candidates = $$.$el.svg.selectAll(
9863 $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
9864 );
9865 candidates.classed($FOCUS.focused, false).classed($FOCUS.defocused, true);
9866 if ($$.hasArcType(null, ["polar"])) {
9867 $$.unexpandArc(targetIds);
9868 $$.hasType("gauge") && $$.undoMarkOverlapped($$, `.${$GAUGE.gaugeValue}`);
9869 }
9870 $$.toggleFocusLegend(targetIds, false);
9871 state.focusedTargetIds = state.focusedTargetIds.filter((id) => targetIds.indexOf(id) < 0);
9872 state.defocusedTargetIds = targetIds;
9873 },
9874 /**
9875 * Revert focused or defocused state to initial state.<br><br>
9876 * 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.
9877 * @function revert
9878 * @instance
9879 * @memberof Chart
9880 * @param {string|Array} targetIdsValue Target ids to be reverted
9881 * @example
9882 * // 'data1' will be reverted.
9883 * chart.revert("data1");
9884 *
9885 * // 'data1' and 'data2' will be reverted.
9886 * chart.revert(["data1", "data2"]);
9887 *
9888 * // all targets will be reverted.
9889 * chart.revert();
9890 */
9891 revert(targetIdsValue) {
9892 const $$ = this.internal;
9893 const { config, state, $el } = $$;
9894 const targetIds = $$.mapToTargetIds(targetIdsValue);
9895 const candidates = $el.svg.selectAll($$.selectorTargets(targetIds));
9896 candidates.classed($FOCUS.focused, false).classed($FOCUS.defocused, false);
9897 $$.hasArcType(null, ["polar"]) && $$.unexpandArc(targetIds);
9898 if (config.legend_show) {
9899 $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
9900 $el.legend.selectAll($$.selectorLegends(targetIds)).filter(function() {
9901 return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($FOCUS.legendItemFocused);
9902 }).classed($FOCUS.legendItemFocused, false);
9903 }
9904 state.focusedTargetIds = [];
9905 state.defocusedTargetIds = [];
9906 }
9907});
9908
9909;// ./src/Chart/api/legend.ts
9910const legend_legend = {
9911 /**
9912 * Show legend for each target.
9913 * - **NOTE:** Legend APIs aren't supported for `treemap` type.
9914 * @function legend․show
9915 * @instance
9916 * @memberof Chart
9917 * @param {string|Array} targetIds
9918 * - If targetIds is given, specified target's legend will be shown.
9919 * - If only one target is the candidate, String can be passed.
9920 * - If no argument is given, all of target's legend will be shown.
9921 * @example
9922 * // Show legend for data1.
9923 * chart.legend.show("data1");
9924 *
9925 * // Show legend for data1 and data2.
9926 * chart.legend.show(["data1", "data2"]);
9927 *
9928 * // Show all legend.
9929 * chart.legend.show();
9930 */
9931 show: function(targetIds) {
9932 const $$ = this.internal;
9933 $$.showLegend($$.mapToTargetIds(targetIds));
9934 $$.updateAndRedraw({ withLegend: true });
9935 },
9936 /**
9937 * Hide legend for each target.
9938 * @function legend․hide
9939 * @instance
9940 * @memberof Chart
9941 * @param {string|Array} targetIds
9942 * - If targetIds is given, specified target's legend will be hidden.
9943 * - If only one target is the candidate, String can be passed.
9944 * - If no argument is given, all of target's legend will be hidden.
9945 * @example
9946 * // Hide legend for data1.
9947 * chart.legend.hide("data1");
9948 *
9949 * // Hide legend for data1 and data2.
9950 * chart.legend.hide(["data1", "data2"]);
9951 *
9952 * // Hide all legend.
9953 * chart.legend.hide();
9954 */
9955 hide: function(targetIds) {
9956 const $$ = this.internal;
9957 $$.hideLegend($$.mapToTargetIds(targetIds));
9958 $$.updateAndRedraw({ withLegend: true });
9959 }
9960};
9961/* harmony default export */ var api_legend = ({ legend: legend_legend });
9962
9963;// ./src/Chart/api/load.ts
9964
9965
9966
9967/* harmony default export */ var api_load = ({
9968 /**
9969 * Load data to the chart.<br><br>
9970 * 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.
9971 * - <b>Note:</b>
9972 * - unload should be used if some data needs to be unloaded simultaneously.
9973 * 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>
9974 * - done will be called after data loaded, but it's not after rendering.
9975 * It's because rendering will finish after some transition and there is some time lag between loading and rendering
9976 * @function load
9977 * @instance
9978 * @memberof Chart
9979 * @param {object} args The object can consist with following members:<br>
9980 *
9981 * | Key | Type | Description |
9982 * | --- | --- | --- |
9983 * | 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 |
9984 * | 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 |
9985 * | 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 |
9986 * | 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 |
9987 * | &nbsp; | | |
9988 * | 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. |
9989 * | axes | Object | The axes specified by data.axes will be updated. axes must be Object that has target id as keys. |
9990 * | categories | Array | The categories specified by axis.x.categories or data.x will be updated. categories must be Array. |
9991 * | classes | Object | The classes specified by data.classes will be updated. classes must be Object that has target id as keys. |
9992 * | colors | Object | The colors specified by data.colors will be updated. colors must be Object that has target id as keys. |
9993 * | data | Obejct | Data objects to be loaded. Checkout the example. |
9994 * | done | Function | The specified function will be called after data loaded.|
9995 * | headers | string | Set request header if loading via `data.url`.<br>@see [data․headers](Options.html#.data%25E2%2580%25A4headers) |
9996 * | 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) |
9997 * | mimeType | string | Set 'json' if loading JSON via url.<br>@see [data․mimeType](Options.html#.data%25E2%2580%25A4mimeType) |
9998 * | names | Object | Same as data.names() |
9999 * | 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. |
10000 * | type | string | The type of targets will be updated. |
10001 * | types | Object | The types of targets will be updated. |
10002 * | 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. |
10003 * | xs | string | Same as data.xs option |
10004 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataFromURL)
10005 * @example
10006 * // Load data1 and unload data2 and data3
10007 * chart.load({
10008 * columns: [
10009 * ["data1", 100, 200, 150, ...],
10010 * ...
10011 * ],
10012 * unload: ["data2", "data3"],
10013 * url: "...",
10014 * done: function() { ... }
10015 * resizeAfter: true // will resize after load
10016 * });
10017 * @example
10018 * const chart = bb.generate({
10019 * data: {
10020 * columns: [
10021 * ["data1", 20, 30, 40]
10022 * ]
10023 * }
10024 * });
10025 *
10026 * chart.load({
10027 * columns: [
10028 * // with 'append' option, the 'data1' will have `[20,30,40,50,60]`.
10029 * ["data1", 50, 60]
10030 * ],
10031 * append: true
10032 * });
10033 * @example
10034 * const chart = bb.generate({
10035 * data: {
10036 * x: "x",
10037 * xFormat: "%Y-%m-%dT%H:%M:%S",
10038 * columns: [
10039 * ["x", "2021-01-03T03:00:00", "2021-01-04T12:00:00", "2021-01-05T21:00:00"],
10040 * ["data1", 36, 30, 24]
10041 * ]
10042 * },
10043 * axis: {
10044 * x: {
10045 * type: "timeseries"
10046 * }
10047 * }
10048 * };
10049 *
10050 * chart.load({
10051 * columns: [
10052 * // when existing chart has `x` value, should provide correponding 'x' value.
10053 * // with 'append' option, the 'data1' will have `[36,30,24,37]`.
10054 * ["x", "2021-02-01T08:00:00"],
10055 * ["data1", 37]
10056 * ],
10057 * append: true
10058 * });
10059 * @example
10060 * // myAPI.json
10061 * // {
10062 * // "data1": [220, 240, 270, 250, 280],
10063 * // "data2": [180, 150, 300, 70, 120]
10064 * // }
10065 *
10066 * chart.load({
10067 * url: './data/myAPI.json',
10068 * mimeType: "json",
10069 *
10070 * // set request header if is needed
10071 * headers: {
10072 * "Content-Type": "text/json"
10073 * }
10074 * });
10075 * @example
10076 * chart.load({
10077 * data: [
10078 * // equivalent as: columns: [["data1", 30, 200, 100]]
10079 * {"data1": 30}, {"data1": 200}, {"data1": 100}
10080 *
10081 * // or
10082 * // equivalent as: columns: [["data1", 10, 20], ["data2", 13, 30]]
10083 * // {"data1": 10, "data2": 13}, {"data1": 20, "data2": 30}}
10084 * ]
10085 * });
10086 * @example
10087 * chart.load({
10088 * json: [
10089 * {name: "www.site1.com", upload: 800, download: 500, total: 400},
10090 * ],
10091 * keys: {
10092 * x: "name",
10093 * value: ["upload", "download"]
10094 * }
10095 * });
10096 * @example
10097 * chart.load({
10098 * json: {
10099 * data1:[30, 20, 50, 40, 60, 50],
10100 * data2:[200, 130, 90, 240, 130, 220],
10101 * }
10102 * });
10103 */
10104 load(args) {
10105 const $$ = this.internal;
10106 const { config } = $$;
10107 args.xs && $$.addXs(args.xs);
10108 "names" in args && this.data.names(args.names);
10109 "classes" in args && Object.keys(args.classes).forEach((id) => {
10110 config.data_classes[id] = args.classes[id];
10111 });
10112 if ("categories" in args && $$.axis.isCategorized()) {
10113 config.axis_x_categories = args.categories;
10114 }
10115 "axes" in args && Object.keys(args.axes).forEach((id) => {
10116 config.data_axes[id] = args.axes[id];
10117 });
10118 "colors" in args && Object.keys(args.colors).forEach((id) => {
10119 config.data_colors[id] = args.colors[id];
10120 });
10121 if ("unload" in args && args.unload !== false) {
10122 $$.unload($$.mapToTargetIds(args.unload === true ? null : args.unload), () => {
10123 requestIdleCallback(() => $$.loadFromArgs(args));
10124 });
10125 } else {
10126 $$.loadFromArgs(args);
10127 }
10128 },
10129 /**
10130 * Unload data to the chart.<br><br>
10131 * 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.
10132 * - <b>Note:</b>
10133 * 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>
10134 * `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.
10135 * @function unload
10136 * @instance
10137 * @memberof Chart
10138 * @param {object} argsValue
10139 * | key | Type | Description |
10140 * | --- | --- | --- |
10141 * | ids | String &vert; Array | Target id data to be unloaded. If not given, all data will be unloaded. |
10142 * | done | Fuction | Callback after data is unloaded. |
10143 * | 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. |
10144 * @example
10145 * // Unload data2 and data3
10146 * chart.unload({
10147 * ids: ["data2", "data3"],
10148 * done: function() {
10149 * // called after the unloaded
10150 * },
10151 * resizeAfter: true // will resize after unload
10152 * });
10153 */
10154 unload(argsValue) {
10155 const $$ = this.internal;
10156 let args = argsValue || {};
10157 isEmpty(args) && this.tooltip.hide();
10158 if (isArray(args)) {
10159 args = { ids: args };
10160 } else if (isString(args)) {
10161 args = { ids: [args] };
10162 }
10163 const ids = $$.mapToTargetIds(args.ids);
10164 $$.unload(ids, () => {
10165 $$.redraw({
10166 withUpdateOrgXDomain: true,
10167 withUpdateXDomain: true,
10168 withLegend: true
10169 });
10170 $$.cache.remove(ids);
10171 callDone.call($$, args.done, args.resizeAfter);
10172 });
10173 }
10174});
10175
10176;// ./src/Chart/api/show.ts
10177
10178function showHide(show, targetIdsValue, options) {
10179 const $$ = this.internal;
10180 const targetIds = $$.mapToTargetIds(targetIdsValue);
10181 const hiddenIds = $$.state.hiddenTargetIds.map((v) => targetIds.indexOf(v) > -1 && v).filter(Boolean);
10182 $$.state.toggling = true;
10183 $$[`${show ? "remove" : "add"}HiddenTargetIds`](targetIds);
10184 const targets = $$.$el.svg.selectAll($$.selectorTargets(targetIds));
10185 const opacity = show ? null : "0";
10186 if (show && hiddenIds.length) {
10187 targets.style("display", null);
10188 callFn($$.config.data_onshown, this, hiddenIds);
10189 }
10190 $$.$T(targets).style("opacity", opacity, "important").call(endall, () => {
10191 var _a;
10192 if (!show && hiddenIds.length === 0) {
10193 targets.style("display", "none");
10194 callFn((_a = $$.config) == null ? void 0 : _a.data_onhidden, this, targetIds);
10195 }
10196 targets.style("opacity", opacity);
10197 });
10198 options.withLegend && $$[`${show ? "show" : "hide"}Legend`](targetIds);
10199 $$.redraw({
10200 withUpdateOrgXDomain: true,
10201 withUpdateXDomain: true,
10202 withLegend: true
10203 });
10204 $$.state.toggling = false;
10205}
10206/* harmony default export */ var show = ({
10207 /**
10208 * Show data series on chart
10209 * @function show
10210 * @instance
10211 * @memberof Chart
10212 * @param {string|Array} [targetIdsValue] The target id value.
10213 * @param {object} [options] The object can consist with following members:<br>
10214 *
10215 * | Key | Type | default | Description |
10216 * | --- | --- | --- | --- |
10217 * | withLegend | boolean | false | whether or not display legend |
10218 *
10219 * @example
10220 * // show 'data1'
10221 * chart.show("data1");
10222 *
10223 * // show 'data1' and 'data3'
10224 * chart.show(["data1", "data3"]);
10225 */
10226 show(targetIdsValue, options = {}) {
10227 showHide.call(this, true, targetIdsValue, options);
10228 },
10229 /**
10230 * Hide data series from chart
10231 * @function hide
10232 * @instance
10233 * @memberof Chart
10234 * @param {string|Array} [targetIdsValue] The target id value.
10235 * @param {object} [options] The object can consist with following members:<br>
10236 *
10237 * | Key | Type | default | Description |
10238 * | --- | --- | --- | --- |
10239 * | withLegend | boolean | false | whether or not display legend |
10240 *
10241 * @example
10242 * // hide 'data1'
10243 * chart.hide("data1");
10244 *
10245 * // hide 'data1' and 'data3'
10246 * chart.hide(["data1", "data3"]);
10247 */
10248 hide(targetIdsValue, options = {}) {
10249 showHide.call(this, false, targetIdsValue, options);
10250 },
10251 /**
10252 * Toggle data series on chart. When target data is hidden, it will show. If is shown, it will hide in vice versa.
10253 * @function toggle
10254 * @instance
10255 * @memberof Chart
10256 * @param {string|Array} [targetIds] The target id value.
10257 * @param {object} [options] The object can consist with following members:<br>
10258 *
10259 * | Key | Type | default | Description |
10260 * | --- | --- | --- | --- |
10261 * | withLegend | boolean | false | whether or not display legend |
10262 *
10263 * @example
10264 * // toggle 'data1'
10265 * chart.toggle("data1");
10266 *
10267 * // toggle 'data1' and 'data3'
10268 * chart.toggle(["data1", "data3"]);
10269 */
10270 toggle(targetIds, options = {}) {
10271 const $$ = this.internal;
10272 const targets = { show: [], hide: [] };
10273 $$.mapToTargetIds(targetIds).forEach((id) => targets[$$.isTargetToShow(id) ? "hide" : "show"].push(id));
10274 targets.show.length && this.show(targets.show, options);
10275 targets.hide.length && setTimeout(() => this.hide(targets.hide, options), 0);
10276 }
10277});
10278
10279;// ./src/Chart/api/tooltip.ts
10280
10281
10282const tooltip_tooltip = {
10283 /**
10284 * Show tooltip
10285 * @function tooltip․show
10286 * @instance
10287 * @memberof Chart
10288 * @param {object} args The object can consist with following members:<br>
10289 *
10290 * | Key | Type | Description |
10291 * | --- | --- | --- |
10292 * | index | Number | Determine focus by index |
10293 * | x | Number &vert; Date | Determine focus by x Axis index |
10294 * | 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]` |
10295 * | 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. |
10296 *
10297 * @example
10298 * // show the 2nd x Axis coordinate tooltip
10299 * // for Arc(gauge, donut & pie) and radar type, approch showing tooltip by using "index" number.
10300 * chart.tooltip.show({
10301 * index: 1
10302 * });
10303 *
10304 * // show tooltip for the 3rd x Axis in x:50 and y:100 coordinate of '.bb-event-rect' of the x Axis.
10305 * chart.tooltip.show({
10306 * x: 2,
10307 * mouse: [50, 100]
10308 * });
10309 *
10310 * // show tooltip for timeseries x axis
10311 * chart.tooltip.show({
10312 * x: new Date("2018-01-02 00:00")
10313 * });
10314 *
10315 * // treemap type can be shown by using "id" only.
10316 * chart.tooltip.show({
10317 * data: {
10318 * id: "data1" // data id
10319 * }
10320 * });
10321 *
10322 * // for Arc types, specify 'id' or 'index'
10323 * chart.tooltip.show({ data: { id: "data2" }});
10324 * chart.tooltip.show({ data: { index: 2 }});
10325 *
10326 * // when data.xs is used
10327 * chart.tooltip.show({
10328 * data: {
10329 * x: 3, // x Axis value
10330 * id: "data1", // data id
10331 * value: 500 // data value
10332 * }
10333 * });
10334 *
10335 * // when data.xs isn't used, but tooltip.grouped=false is set
10336 * chart.tooltip.show({
10337 * data: {
10338 * index: 3, // or 'x' key value
10339 * id: "data1", // data id
10340 * value: 500 // data value
10341 * }
10342 * });
10343 */
10344 show: function(args) {
10345 var _a, _b, _c;
10346 const $$ = this.internal;
10347 const { $el, config, state: { eventReceiver, hasFunnel, hasTreemap, inputType } } = $$;
10348 let index;
10349 let mouse;
10350 if (args.mouse) {
10351 mouse = args.mouse;
10352 }
10353 if (args.data) {
10354 const { data } = args;
10355 const y = (_a = $$.getYScaleById(data.id)) == null ? void 0 : _a(data.value);
10356 if ((hasFunnel || hasTreemap) && data.id) {
10357 const selector = $$.selectorTarget(data.id, void 0, `.${$SHAPE.shape}`);
10358 eventReceiver.rect = $el.main.select(selector);
10359 } else if ($$.isMultipleX()) {
10360 mouse = [$$.xx(data), y];
10361 } else {
10362 if (!config.tooltip_grouped) {
10363 mouse = [0, y];
10364 }
10365 index = (_c = data.index) != null ? _c : $$.hasArcType() && data.id ? (_b = $$.getArcElementByIdOrIndex(data.id)) == null ? void 0 : _b.datum().index : $$.getIndexByX(data.x);
10366 }
10367 } else if (isDefined(args.x)) {
10368 index = $$.getIndexByX(args.x);
10369 } else if (isDefined(args.index)) {
10370 index = args.index;
10371 }
10372 (inputType === "mouse" ? ["mouseover", "mousemove"] : ["touchstart"]).forEach((eventName) => {
10373 $$.dispatchEvent(eventName, index, mouse);
10374 });
10375 },
10376 /**
10377 * Hide tooltip
10378 * @function tooltip․hide
10379 * @instance
10380 * @memberof Chart
10381 */
10382 hide: function() {
10383 var _a, _b, _c;
10384 const $$ = this.internal;
10385 const { state: { inputType }, $el: { tooltip: tooltip2 } } = $$;
10386 const data = tooltip2 == null ? void 0 : tooltip2.datum();
10387 if (data) {
10388 const { index } = JSON.parse(data.current)[0];
10389 (inputType === "mouse" ? ["mouseout"] : ["touchend"]).forEach((eventName) => {
10390 $$.dispatchEvent(eventName, index);
10391 });
10392 }
10393 inputType === "touch" && $$.callOverOutForTouch();
10394 $$.hideTooltip(true);
10395 (_a = $$.hideGridFocus) == null ? void 0 : _a.call($$);
10396 (_b = $$.unexpandCircles) == null ? void 0 : _b.call($$);
10397 (_c = $$.expandBarTypeShapes) == null ? void 0 : _c.call($$, false);
10398 }
10399};
10400/* harmony default export */ var api_tooltip = ({ tooltip: tooltip_tooltip });
10401
10402;// ./src/Chart/Chart.ts
10403var Chart_defProp = Object.defineProperty;
10404var Chart_defNormalProp = (obj, key, value) => key in obj ? Chart_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10405var Chart_publicField = (obj, key, value) => Chart_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418class Chart {
10419 constructor(options) {
10420 Chart_publicField(this, "plugins", []);
10421 Chart_publicField(this, "internal");
10422 const $$ = new ChartInternal(this);
10423 this.internal = $$;
10424 (function bindThis(fn, target, argThis) {
10425 Object.keys(fn).forEach((key) => {
10426 const isFunc = isFunction(fn[key]);
10427 const isChild = target !== argThis;
10428 const isNotNil = notEmpty(fn[key]);
10429 const hasChild = isNotNil && Object.keys(fn[key]).length > 0;
10430 if (isFunc && (!isChild && hasChild || isChild)) {
10431 target[key] = fn[key].bind(argThis);
10432 } else if (isNotNil && !isFunc) {
10433 target[key] = {};
10434 } else {
10435 target[key] = fn[key];
10436 }
10437 hasChild && bindThis(fn[key], target[key], argThis);
10438 });
10439 })(Chart.prototype, this, this);
10440 loadConfig.call($$, options);
10441 $$.beforeInit();
10442 $$.init();
10443 }
10444}
10445extend(Chart.prototype, [
10446 chart,
10447 api_color,
10448 api_data,
10449 api_export,
10450 api_focus,
10451 api_legend,
10452 api_load,
10453 show,
10454 api_tooltip
10455]);
10456
10457;// ./src/Chart/api/selection.ts
10458
10459
10460
10461function setSelection(isSelection = false, ids, indices, resetOther) {
10462 const $$ = this;
10463 const { config, $el: { main } } = $$;
10464 const selectionGrouped = config.data_selection_grouped;
10465 const isSelectable = config.data_selection_isselectable.bind($$.api);
10466 if (!config.data_selection_enabled) {
10467 return;
10468 }
10469 main.selectAll(`.${$SHAPE.shapes}`).selectAll(`.${$SHAPE.shape}`).each(function(d) {
10470 const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
10471 const { id, index } = d.data ? d.data : d;
10472 const toggle = $$.getToggle(this, d).bind($$);
10473 const isTargetId = selectionGrouped || !ids || ids.indexOf(id) >= 0;
10474 const isTargetIndex = !indices || indices.indexOf(index) >= 0;
10475 const isSelected = shape.classed($SELECT.SELECTED);
10476 if (shape.classed($LINE.line) || shape.classed($AREA.area)) {
10477 return;
10478 }
10479 if (isSelection) {
10480 if (isTargetId && isTargetIndex && isSelectable(d) && !isSelected) {
10481 toggle(true, shape.classed($SELECT.SELECTED, true), d, index);
10482 } else if (isDefined(resetOther) && resetOther && isSelected) {
10483 toggle(false, shape.classed($SELECT.SELECTED, false), d, index);
10484 }
10485 } else {
10486 if (isTargetId && isTargetIndex && isSelectable(d) && isSelected) {
10487 toggle(false, shape.classed($SELECT.SELECTED, false), d, index);
10488 }
10489 }
10490 });
10491}
10492/* harmony default export */ var selection = ({
10493 /**
10494 * Get selected data points.<br><br>
10495 * By this API, you can get selected data points information. To use this API, data.selection.enabled needs to be set true.
10496 * @function selected
10497 * @instance
10498 * @memberof Chart
10499 * @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.
10500 * @returns {Array} dataPoint Array of the data points.<br>ex.) `[{x: 1, value: 200, id: "data1", index: 1, name: "data1"}, ...]`
10501 * @example
10502 * // all selected data points will be returned.
10503 * chart.selected();
10504 * // --> ex.) [{x: 1, value: 200, id: "data1", index: 1, name: "data1"}, ... ]
10505 *
10506 * // all selected data points of data1 will be returned.
10507 * chart.selected("data1");
10508 */
10509 selected(targetId) {
10510 const $$ = this.internal;
10511 const dataPoint = [];
10512 $$.$el.main.selectAll(`.${$SHAPE.shapes + $$.getTargetSelectorSuffix(targetId)}`).selectAll(`.${$SHAPE.shape}`).filter(function() {
10513 return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($SELECT.SELECTED);
10514 }).each((d) => dataPoint.push(d));
10515 return dataPoint;
10516 },
10517 /**
10518 * 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)
10519 * @function select
10520 * @instance
10521 * @memberof Chart
10522 * @param {string|Array} [ids] id value to get selected.
10523 * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.
10524 * @param {boolean} [resetOther] Unselect already selected.
10525 * @example
10526 * // select all data points
10527 * chart.select();
10528 *
10529 * // select all from 'data2'
10530 * chart.select("data2");
10531 *
10532 * // select all from 'data1' and 'data2'
10533 * chart.select(["data1", "data2"]);
10534 *
10535 * // select from 'data1', indices 2 and unselect others selected
10536 * chart.select("data1", [2], true);
10537 *
10538 * // select from 'data1', indices 0, 3 and 5
10539 * chart.select("data1", [0, 3, 5]);
10540 */
10541 select(ids, indices, resetOther) {
10542 const $$ = this.internal;
10543 setSelection.bind($$)(true, ids, indices, resetOther);
10544 },
10545 /**
10546 * Set data points to be un-selected.
10547 * @function unselect
10548 * @instance
10549 * @memberof Chart
10550 * @param {string|Array} [ids] id value to be unselected.
10551 * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.
10552 * @example
10553 * // unselect all data points
10554 * chart.unselect();
10555 *
10556 * // unselect all from 'data1'
10557 * chart.unselect("data1");
10558 *
10559 * // unselect from 'data1', indices 2
10560 * chart.unselect("data1", [2]);
10561 */
10562 unselect(ids, indices) {
10563 const $$ = this.internal;
10564 setSelection.bind($$)(false, ids, indices);
10565 }
10566});
10567
10568;// ./src/Chart/api/subchart.ts
10569
10570
10571const subchart = function(domainValue) {
10572 var _a;
10573 const $$ = this.internal;
10574 const { axis, brush, config, scale: { x, subX }, state } = $$;
10575 let domain;
10576 if (config.subchart_show) {
10577 domain = domainValue;
10578 if (Array.isArray(domain)) {
10579 if (axis.isTimeSeries()) {
10580 domain = domain.map((x2) => parseDate.bind($$)(x2));
10581 }
10582 const isWithinRange = $$.withinRange(
10583 domain,
10584 $$.getZoomDomain("subX", true),
10585 $$.getZoomDomain("subX")
10586 );
10587 if (isWithinRange) {
10588 state.domain = domain;
10589 brush.move(
10590 brush.getSelection(),
10591 domain.map(subX)
10592 );
10593 }
10594 } else {
10595 domain = (_a = state.domain) != null ? _a : x.orgDomain();
10596 }
10597 }
10598 return domain;
10599};
10600extend(subchart, {
10601 /**
10602 * Show subchart
10603 * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
10604 * @function subchart․show
10605 * @instance
10606 * @memberof Chart
10607 * @example
10608 * // for ESM imports, needs to import 'subchart' and must be instantiated first to enable subchart's API.
10609 * import {subchart} from "billboard.js";
10610 *
10611 * const chart = bb.generate({
10612 * ...
10613 * subchart: {
10614 * // need to be instantiated by calling 'subchart()'
10615 * enabled: subchart()
10616 *
10617 * // in case don't want subchart to be shown at initialization, instantiate with '!subchart()'
10618 * enabled: !subchart()
10619 * }
10620 * });
10621 *
10622 * chart.subchart.show();
10623 */
10624 show() {
10625 var _a, _b;
10626 const $$ = this.internal;
10627 const { $el: { subchart: subchart2 }, config } = $$;
10628 const show = config.subchart_show;
10629 if (!show) {
10630 $$.unbindZoomEvent();
10631 config.subchart_show = !show;
10632 !subchart2.main && $$.initSubchart();
10633 let $target = subchart2.main.selectAll(`.${$COMMON.target}`);
10634 if ($$.data.targets.length !== $target.size()) {
10635 $$.updateSizes();
10636 $$.updateTargetsForSubchart($$.data.targets);
10637 $target = (_a = subchart2.main) == null ? void 0 : _a.selectAll(`.${$COMMON.target}`);
10638 }
10639 $target == null ? void 0 : $target.style("opacity", null);
10640 (_b = subchart2.main) == null ? void 0 : _b.style("display", null);
10641 this.resize();
10642 }
10643 },
10644 /**
10645 * Hide generated subchart
10646 * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
10647 * @function subchart․hide
10648 * @instance
10649 * @memberof Chart
10650 * @example
10651 * chart.subchart.hide();
10652 */
10653 hide() {
10654 const $$ = this.internal;
10655 const { $el: { subchart: { main } }, config } = $$;
10656 if (config.subchart_show && (main == null ? void 0 : main.style("display")) !== "none") {
10657 config.subchart_show = false;
10658 main.style("display", "none");
10659 this.resize();
10660 }
10661 },
10662 /**
10663 * Toggle the visiblity of subchart
10664 * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
10665 * @function subchart․toggle
10666 * @instance
10667 * @memberof Chart
10668 * @example
10669 * // When subchart is hidden, will be shown
10670 * // When subchart is shown, will be hidden
10671 * chart.subchart.toggle();
10672 */
10673 toggle() {
10674 const $$ = this.internal;
10675 const { config } = $$;
10676 this.subchart[config.subchart_show ? "hide" : "show"]();
10677 },
10678 /**
10679 * Reset subchart selection
10680 * @function subchart․reset
10681 * @instance
10682 * @memberof Chart
10683 * @example
10684 * // Reset subchart selection
10685 * chart.subchart.reset();
10686 */
10687 reset() {
10688 const $$ = this.internal;
10689 const { brush } = $$;
10690 brush.clear(brush.getSelection());
10691 }
10692});
10693/* harmony default export */ var api_subchart = ({
10694 subchart
10695});
10696
10697// EXTERNAL MODULE: external {"commonjs":"d3-zoom","commonjs2":"d3-zoom","amd":"d3-zoom","root":"d3"}
10698var external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_ = __webpack_require__(10);
10699;// ./src/Chart/api/zoom.ts
10700
10701
10702const zoom = function(domainValue) {
10703 var _a;
10704 const $$ = this.internal;
10705 const { axis, config, org, scale, state } = $$;
10706 const isCategorized = axis.isCategorized();
10707 let domain;
10708 if (config.zoom_enabled) {
10709 domain = domainValue;
10710 if (Array.isArray(domain)) {
10711 if (axis.isTimeSeries()) {
10712 domain = domain.map((x) => parseDate.bind($$)(x));
10713 }
10714 const isWithinRange = $$.withinRange(
10715 domain,
10716 $$.getZoomDomain("zoom", true),
10717 $$.getZoomDomain("zoom")
10718 );
10719 if (isWithinRange) {
10720 state.domain = domain;
10721 domain = $$.getZoomDomainValue(domain);
10722 $$.api.tooltip.hide();
10723 if (config.subchart_show) {
10724 const x = scale.zoom || scale.x;
10725 $$.brush.getSelection().call($$.brush.move, domain.map(x));
10726 } else {
10727 const x = isCategorized ? scale.x.orgScale() : org.xScale || scale.x;
10728 $$.updateCurrentZoomTransform(x, domain);
10729 }
10730 $$.setZoomResetButton();
10731 }
10732 } else {
10733 domain = $$.zoom.getDomain();
10734 }
10735 }
10736 return (_a = state.domain) != null ? _a : domain;
10737};
10738extend(zoom, {
10739 /**
10740 * Enable and disable zooming.
10741 * @function zoom․enable
10742 * @instance
10743 * @memberof Chart
10744 * @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.
10745 * @example
10746 * // Enable zooming using the mouse wheel
10747 * chart.zoom.enable(true);
10748 * // Or
10749 * chart.zoom.enable("wheel");
10750 *
10751 * // Enable zooming by dragging
10752 * chart.zoom.enable("drag");
10753 *
10754 * // Disable zooming
10755 * chart.zoom.enable(false);
10756 */
10757 enable(enabled) {
10758 const $$ = this.internal;
10759 const { config } = $$;
10760 if (/^(drag|wheel)$/.test(enabled)) {
10761 config.zoom_type = enabled;
10762 }
10763 config.zoom_enabled = !!enabled;
10764 if (!$$.zoom) {
10765 $$.initZoom();
10766 $$.bindZoomEvent();
10767 } else if (enabled === false) {
10768 $$.bindZoomEvent(false);
10769 }
10770 $$.updateAndRedraw();
10771 },
10772 /**
10773 * Set or get x Axis maximum zoom range value
10774 * @function zoom․max
10775 * @instance
10776 * @memberof Chart
10777 * @param {number} [max] maximum value to set for zoom
10778 * @returns {number} zoom max value
10779 * @example
10780 * // Set maximum range value
10781 * chart.zoom.max(20);
10782 */
10783 max(max) {
10784 const $$ = this.internal;
10785 const { config, org: { xDomain } } = $$;
10786 if (max === 0 || max) {
10787 config.zoom_x_max = getMinMax("max", [xDomain[1], max]);
10788 }
10789 return config.zoom_x_max;
10790 },
10791 /**
10792 * Set or get x Axis minimum zoom range value
10793 * @function zoom․min
10794 * @instance
10795 * @memberof Chart
10796 * @param {number} [min] minimum value to set for zoom
10797 * @returns {number} zoom min value
10798 * @example
10799 * // Set minimum range value
10800 * chart.zoom.min(-1);
10801 */
10802 min(min) {
10803 const $$ = this.internal;
10804 const { config, org: { xDomain } } = $$;
10805 if (min === 0 || min) {
10806 config.zoom_x_min = getMinMax("min", [xDomain[0], min]);
10807 }
10808 return config.zoom_x_min;
10809 },
10810 /**
10811 * Set zoom range
10812 * @function zoom․range
10813 * @instance
10814 * @memberof Chart
10815 * @param {object} [range] zoom range
10816 * @returns {object} zoom range value
10817 * {
10818 * min: 0,
10819 * max: 100
10820 * }
10821 * @example
10822 * chart.zoom.range({
10823 * min: 10,
10824 * max: 100
10825 * });
10826 */
10827 range(range) {
10828 const zoom2 = this.zoom;
10829 if (isObject(range)) {
10830 const { min, max } = range;
10831 isDefined(min) && zoom2.min(min);
10832 isDefined(max) && zoom2.max(max);
10833 }
10834 return {
10835 min: zoom2.min(),
10836 max: zoom2.max()
10837 };
10838 }
10839});
10840/* harmony default export */ var api_zoom = ({
10841 zoom,
10842 /**
10843 * Unzoom zoomed area
10844 * - **NOTE:** Calling .unzoom() will not trigger zoom events.
10845 * @function unzoom
10846 * @instance
10847 * @memberof Chart
10848 * @example
10849 * chart.unzoom();
10850 */
10851 unzoom() {
10852 const $$ = this.internal;
10853 const { config, $el: { eventRect, zoomResetBtn }, scale: { zoom: zoom2 }, state } = $$;
10854 if (zoom2) {
10855 config.subchart_show ? $$.brush.getSelection().call($$.brush.move, null) : $$.zoom.updateTransformScale(external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity);
10856 $$.updateZoom(true);
10857 zoomResetBtn == null ? void 0 : zoomResetBtn.style("display", "none");
10858 if ((0,external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomTransform)(eventRect.node()) !== external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity) {
10859 $$.zoom.transform(eventRect, external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity);
10860 }
10861 state.domain = void 0;
10862 }
10863 }
10864});
10865
10866;// ./src/ChartInternal/interactions/subchart.ts
10867
10868
10869
10870
10871/* harmony default export */ var interactions_subchart = ({
10872 /**
10873 * Initialize the brush.
10874 * @private
10875 */
10876 initBrush() {
10877 const $$ = this;
10878 const { config, scale, $el: { subchart }, state } = $$;
10879 const isRotated = config.axis_rotated;
10880 const height = config.subchart_size_height;
10881 let lastDomain;
10882 let lastSelection;
10883 let timeout;
10884 $$.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);
10885 $$.brush.on("start brush end", (event) => {
10886 const { selection, sourceEvent, target, type } = event;
10887 if (type === "start") {
10888 $$.state.inputType === "touch" && $$.hideTooltip();
10889 lastSelection = sourceEvent ? selection : null;
10890 }
10891 if (/(start|brush)/.test(type)) {
10892 type === "brush" && sourceEvent && state.domain && (lastSelection == null ? void 0 : lastSelection.forEach((v, i) => {
10893 if (v !== selection[i]) {
10894 state.domain[i] = scale.x.orgDomain()[i];
10895 }
10896 }));
10897 $$.redrawForBrush(type !== "start");
10898 }
10899 if (type === "end") {
10900 lastDomain = scale.x.orgDomain();
10901 }
10902 if (target == null ? void 0 : target.handle) {
10903 if (selection === null) {
10904 $$.brush.handle.attr("display", "none");
10905 } else {
10906 $$.brush.handle.attr("display", null).attr("transform", (d, i) => {
10907 const pos = [selection[i], height / 2];
10908 return `translate(${isRotated ? pos.reverse() : pos})`;
10909 });
10910 }
10911 }
10912 });
10913 $$.brush.updateResize = function() {
10914 timeout && clearTimeout(timeout);
10915 timeout = setTimeout(() => {
10916 const selection = this.getSelection();
10917 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()));
10918 }, 0);
10919 };
10920 $$.brush.update = function() {
10921 var _a;
10922 const extent = this.extent()();
10923 if (extent[1].filter((v) => isNaN(v)).length === 0) {
10924 (_a = subchart.main) == null ? void 0 : _a.select(`.${classes.brush}`).call(this);
10925 }
10926 return this;
10927 };
10928 $$.brush.scale = function(scale2) {
10929 const h = config.subchart_size_height;
10930 let extent = $$.axis.getExtent();
10931 if (!extent && scale2.range) {
10932 extent = [[0, 0], [scale2.range()[1], h]];
10933 } else if (isArray(extent)) {
10934 extent = extent.map((v, i) => [v, i > 0 ? h : i]);
10935 }
10936 isRotated && extent[1].reverse();
10937 this.extent(extent);
10938 this.update();
10939 };
10940 $$.brush.getSelection = () => (
10941 // @ts-ignore
10942 subchart.main ? subchart.main.select(`.${classes.brush}`) : (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)([])
10943 );
10944 },
10945 /**
10946 * Initialize the subchart.
10947 * @private
10948 */
10949 initSubchart() {
10950 const $$ = this;
10951 const { config, state: { clip, hasAxis }, $el: { defs, svg, subchart, axis } } = $$;
10952 if (!hasAxis) {
10953 return;
10954 }
10955 const visibility = config.subchart_show ? null : "hidden";
10956 const clipId = `${clip.id}-subchart`;
10957 const clipPath = $$.getClipPath(clipId);
10958 clip.idSubchart = clipId;
10959 $$.appendClip(defs, clipId);
10960 $$.initBrush();
10961 subchart.main = svg.append("g").classed(classes.subchart, true).attr("transform", $$.getTranslate("context"));
10962 const { main } = subchart;
10963 main.style("visibility", visibility);
10964 main.append("g").attr("clip-path", clipPath).attr("class", classes.chart);
10965 ["bar", "line", "bubble", "candlestick", "scatter"].forEach((v) => {
10966 const type = capitalize(/^(bubble|scatter)$/.test(v) ? "circle" : v);
10967 if ($$.hasType(v) || $$.hasTypeOf(type)) {
10968 const chart = main.select(`.${classes.chart}`);
10969 const chartClassName = classes[`chart${type}s`];
10970 if (chart.select(`.${chartClassName}`).empty()) {
10971 chart.append("g").attr("class", chartClassName);
10972 }
10973 }
10974 });
10975 const brush = main.append("g").attr("clip-path", clipPath).attr("class", classes.brush).call($$.brush);
10976 config.subchart_showHandle && $$.addBrushHandle(brush);
10977 axis.subX = main.append("g").attr("class", classes.axisX).attr("transform", $$.getTranslate("subX")).attr("clip-path", config.axis_rotated ? "" : clip.pathXAxis).style("visibility", config.subchart_axis_x_show ? visibility : "hidden");
10978 },
10979 /**
10980 * Add brush handle
10981 * Enabled when: subchart.showHandle=true
10982 * @param {d3Selection} brush Brush selection
10983 * @private
10984 */
10985 addBrushHandle(brush) {
10986 const $$ = this;
10987 const { config } = $$;
10988 const isRotated = config.axis_rotated;
10989 const initRange = config.subchart_init_range;
10990 const customHandleClass = "handle--custom";
10991 const path = isRotated ? [
10992 "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",
10993 "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"
10994 ] : [
10995 "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",
10996 "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"
10997 ];
10998 $$.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)]).attr("display", initRange ? null : "none");
10999 },
11000 /**
11001 * Update sub chart
11002 * @param {object} targets $$.data.targets
11003 * @private
11004 */
11005 updateTargetsForSubchart(targets) {
11006 const $$ = this;
11007 const { config, state, $el: { subchart: { main } } } = $$;
11008 if (config.subchart_show) {
11009 ["bar", "line", "bubble", "candlestick", "scatter"].filter((v) => $$.hasType(v) || $$.hasTypeOf(capitalize(v))).forEach((v) => {
11010 const isPointType = /^(bubble|scatter)$/.test(v);
11011 const name = capitalize(isPointType ? "circle" : v);
11012 const chartClass = $$.getChartClass(name, true);
11013 const shapeClass = $$.getClass(isPointType ? "circles" : `${v}s`, true);
11014 const shapeChart = main.select(`.${classes[`chart${`${name}s`}`]}`);
11015 if (isPointType) {
11016 const circle = shapeChart.selectAll(`.${classes.circles}`).data(targets.filter($$[`is${capitalize(v)}Type`].bind($$))).attr("class", shapeClass);
11017 circle.exit().remove();
11018 circle.enter().append("g").attr("class", shapeClass);
11019 } else {
11020 const shapeUpdate = shapeChart.selectAll(`.${classes[`chart${name}`]}`).attr("class", chartClass).data(targets.filter($$[`is${name}Type`].bind($$)));
11021 const shapeEnter = shapeUpdate.enter().append("g").style("opacity", "0").attr("class", chartClass).append("g").attr("class", shapeClass);
11022 shapeUpdate.exit().remove();
11023 v === "line" && $$.hasTypeOf("Area") && shapeEnter.append("g").attr("class", $$.getClass("areas", true));
11024 }
11025 });
11026 main.selectAll(`.${classes.brush} rect`).attr(
11027 config.axis_rotated ? "width" : "height",
11028 config.axis_rotated ? state.width2 : state.height2
11029 );
11030 }
11031 },
11032 /**
11033 * Redraw subchart.
11034 * @private
11035 * @param {boolean} withSubchart whether or not to show subchart
11036 * @param {number} duration duration
11037 * @param {object} shape Shape's info
11038 */
11039 redrawSubchart(withSubchart, duration, shape) {
11040 var _a;
11041 const $$ = this;
11042 const { config, $el: { subchart: { main } }, state } = $$;
11043 const withTransition = !!duration;
11044 main.style("visibility", config.subchart_show ? null : "hidden");
11045 if (config.subchart_show) {
11046 if (((_a = state.event) == null ? void 0 : _a.type) === "zoom") {
11047 $$.brush.update();
11048 }
11049 if (withSubchart) {
11050 const initRange = config.subchart_init_range;
11051 !brushEmpty($$) && $$.brush.update();
11052 Object.keys(shape.type).forEach((v) => {
11053 const name = capitalize(v);
11054 const drawFn = $$[`generateDraw${name}`](shape.indices[v], true);
11055 $$[`update${name}`](withTransition, true);
11056 $$[`redraw${name}`](drawFn, withTransition, true);
11057 });
11058 if ($$.hasType("bubble") || $$.hasType("scatter")) {
11059 const { cx } = shape.pos;
11060 const cy = $$.updateCircleY(true);
11061 $$.updateCircle(true);
11062 $$.redrawCircle(cx, cy, withTransition, void 0, true);
11063 }
11064 if (!state.rendered && initRange) {
11065 state.domain = initRange;
11066 $$.brush.move(
11067 $$.brush.getSelection(),
11068 initRange.map($$.scale.x)
11069 );
11070 }
11071 }
11072 }
11073 },
11074 /**
11075 * Redraw the brush.
11076 * @param {boolean} [callCallbck=true] Call 'onbrush' callback or not.
11077 * @private
11078 */
11079 redrawForBrush(callCallbck = true) {
11080 var _a;
11081 const $$ = this;
11082 const {
11083 config: {
11084 subchart_onbrush: onBrush,
11085 zoom_rescale: withY
11086 },
11087 scale,
11088 state
11089 } = $$;
11090 $$.redraw({
11091 withTransition: false,
11092 withY,
11093 withSubchart: false,
11094 withUpdateXDomain: true,
11095 withDimension: false
11096 });
11097 callCallbck && state.rendered && onBrush.bind($$.api)((_a = state.domain) != null ? _a : scale.x.orgDomain());
11098 },
11099 /**
11100 * Transform context
11101 * @param {boolean} withTransition indicates transition is enabled
11102 * @param {object} transitions The return value of the generateTransitions method of Axis.
11103 * @private
11104 */
11105 transformContext(withTransition, transitions) {
11106 const $$ = this;
11107 const { $el: { subchart }, $T } = $$;
11108 const subXAxis = (transitions == null ? void 0 : transitions.axisSubX) ? transitions.axisSubX : $T(subchart.main.select(`.${classes.axisX}`), withTransition);
11109 subchart.main.attr("transform", $$.getTranslate("context"));
11110 subXAxis.attr("transform", $$.getTranslate("subX"));
11111 }
11112});
11113
11114;// ./src/ChartInternal/interactions/zoom.ts
11115
11116
11117
11118
11119
11120/* harmony default export */ var interactions_zoom = ({
11121 /**
11122 * Initialize zoom.
11123 * @private
11124 */
11125 initZoom() {
11126 const $$ = this;
11127 $$.scale.zoom = null;
11128 $$.generateZoom();
11129 $$.config.zoom_type === "drag" && $$.initZoomBehaviour();
11130 },
11131 /**
11132 * Bind zoom event
11133 * @param {boolean} bind Weather bind or unbound
11134 * @private
11135 */
11136 bindZoomEvent(bind = true) {
11137 const $$ = this;
11138 const { config } = $$;
11139 const zoomEnabled = config.zoom_enabled;
11140 if (zoomEnabled && bind) {
11141 !config.subchart_show && $$.bindZoomOnEventRect();
11142 } else if (bind === false) {
11143 $$.api.unzoom();
11144 $$.unbindZoomEvent();
11145 }
11146 },
11147 /**
11148 * Generate zoom
11149 * @private
11150 */
11151 generateZoom() {
11152 const $$ = this;
11153 const { config, org, scale } = $$;
11154 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($$));
11155 zoom.orgScaleExtent = () => {
11156 const extent = config.zoom_extent || [1, 10];
11157 return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];
11158 };
11159 zoom.updateScaleExtent = function() {
11160 const ratio = diffDomain($$.scale.x.orgDomain()) / diffDomain($$.getZoomDomain());
11161 const extent = this.orgScaleExtent();
11162 this.scaleExtent([extent[0] * ratio, extent[1] * ratio]);
11163 return this;
11164 };
11165 zoom.updateTransformScale = (transform, correctTransform) => {
11166 var _a;
11167 const isRotated = config.axis_rotated;
11168 (_a = org.xScale) == null ? void 0 : _a.range(scale.x.range());
11169 const newScale = transform[isRotated ? "rescaleY" : "rescaleX"](org.xScale || scale.x);
11170 if (newScale.domain().some((v) => /(Invalid Date|NaN)/.test(v.toString()))) {
11171 return;
11172 }
11173 const domain = $$.trimXDomain(newScale.domain());
11174 const rescale = config.zoom_rescale;
11175 newScale.domain(domain, org.xDomain);
11176 if (correctTransform) {
11177 const t = newScale(scale.x.domain()[0]);
11178 const tX = isRotated ? transform.x : t;
11179 const tY = isRotated ? t : transform.y;
11180 $$.$el.eventRect.property(
11181 "__zoom",
11182 external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity.translate(tX, tY).scale(transform.k)
11183 );
11184 }
11185 if (!$$.state.xTickOffset) {
11186 $$.state.xTickOffset = $$.axis.x.tickOffset();
11187 }
11188 scale.zoom = $$.getCustomizedXScale(newScale);
11189 $$.axis.x.scale(scale.zoom);
11190 if (rescale) {
11191 !org.xScale && (org.xScale = scale.x.copy());
11192 scale.x.domain(domain);
11193 } else if (org.xScale) {
11194 scale.x.domain(org.xScale.domain());
11195 org.xScale = null;
11196 }
11197 };
11198 zoom.getDomain = () => {
11199 const domain = scale[scale.zoom ? "zoom" : "subX"].domain();
11200 const isCategorized = $$.axis.isCategorized();
11201 if (isCategorized) {
11202 domain[1] -= 2;
11203 }
11204 return domain;
11205 };
11206 $$.zoom = zoom;
11207 },
11208 /**
11209 * 'start' event listener
11210 * @param {object} event Event object
11211 * @private
11212 */
11213 onZoomStart(event) {
11214 const $$ = this;
11215 const { sourceEvent } = event;
11216 if (sourceEvent) {
11217 $$.zoom.startEvent = sourceEvent;
11218 $$.state.zooming = true;
11219 callFn($$.config.zoom_onzoomstart, $$.api, event);
11220 }
11221 },
11222 /**
11223 * 'zoom' event listener
11224 * @param {object} event Event object
11225 * @private
11226 */
11227 onZoom(event) {
11228 var _a;
11229 const $$ = this;
11230 const { config, scale, state, org } = $$;
11231 const { sourceEvent } = event;
11232 const isUnZoom = (event == null ? void 0 : event.transform) === external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity;
11233 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) {
11234 return;
11235 }
11236 if (event.sourceEvent) {
11237 state.zooming = true;
11238 state.domain = void 0;
11239 }
11240 const isMousemove = (sourceEvent == null ? void 0 : sourceEvent.type) === "mousemove";
11241 const isZoomOut = (sourceEvent == null ? void 0 : sourceEvent.wheelDelta) < 0;
11242 const { transform } = event;
11243 if (!isMousemove && isZoomOut && scale.x.domain().every((v, i) => v !== org.xDomain[i])) {
11244 scale.x.domain(org.xDomain);
11245 }
11246 $$.zoom.updateTransformScale(transform, config.zoom_type === "wheel" && sourceEvent);
11247 const doTransition = config.transition_duration > 0 && !config.subchart_show && (state.dragging || isUnZoom || !event.sourceEvent);
11248 $$.redraw({
11249 withTransition: doTransition,
11250 withY: config.zoom_rescale,
11251 withSubchart: false,
11252 withEventRect: false,
11253 withDimension: false
11254 });
11255 $$.state.cancelClick = isMousemove;
11256 !isUnZoom && callFn(
11257 config.zoom_onzoom,
11258 $$.api,
11259 (_a = $$.state.domain) != null ? _a : $$.zoom.getDomain()
11260 );
11261 },
11262 /**
11263 * 'end' event listener
11264 * @param {object} event Event object
11265 * @private
11266 */
11267 onZoomEnd(event) {
11268 var _a, _b;
11269 const $$ = this;
11270 const { config, state } = $$;
11271 let { startEvent } = $$.zoom;
11272 let e = event == null ? void 0 : event.sourceEvent;
11273 const isUnZoom = (event == null ? void 0 : event.transform) === external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomIdentity;
11274 if ((startEvent == null ? void 0 : startEvent.type.indexOf("touch")) > -1) {
11275 startEvent = startEvent.changedTouches[0];
11276 e = (_a = e == null ? void 0 : e.changedTouches) == null ? void 0 : _a[0];
11277 }
11278 if (config.zoom_type === "drag" && (e && startEvent.clientX === e.clientX && startEvent.clientY === e.clientY)) {
11279 return;
11280 }
11281 state.zooming = false;
11282 $$.redrawEventRect();
11283 $$.updateZoom();
11284 !isUnZoom && (e || state.dragging) && callFn(
11285 config.zoom_onzoomend,
11286 $$.api,
11287 (_b = $$.state.domain) != null ? _b : $$.zoom.getDomain()
11288 );
11289 },
11290 /**
11291 * Update zoom
11292 * @param {boolean} force Force unzoom
11293 * @private
11294 */
11295 updateZoom(force) {
11296 const $$ = this;
11297 const { subX, x, zoom } = $$.scale;
11298 if (zoom) {
11299 const zoomDomain = zoom.domain();
11300 const xDomain = subX.domain();
11301 const delta = 0.015;
11302 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);
11303 if (force || isfullyShown) {
11304 $$.axis.x.scale(subX);
11305 x.domain(subX.orgDomain());
11306 $$.scale.zoom = null;
11307 }
11308 }
11309 },
11310 /**
11311 * Set zoom transform to event rect
11312 * @param {Function} x x Axis scale function
11313 * @param {Array} domain Domain value to be set
11314 * @private
11315 */
11316 updateCurrentZoomTransform(x, domain) {
11317 const $$ = this;
11318 const { $el: { eventRect }, config } = $$;
11319 const isRotated = config.axis_rotated;
11320 const translate = [-x(domain[0]), 0];
11321 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(
11322 ...isRotated ? translate.reverse() : translate
11323 );
11324 eventRect.call($$.zoom.transform, transform);
11325 },
11326 /**
11327 * Attach zoom event on <rect>
11328 * @private
11329 */
11330 bindZoomOnEventRect() {
11331 var _a;
11332 const $$ = this;
11333 const { config, $el: { eventRect, svg } } = $$;
11334 const behaviour = config.zoom_type === "drag" ? $$.zoomBehaviour : $$.zoom;
11335 if (win.GestureEvent && /^((?!chrome|android|mobile).)*safari/i.test((_a = win.navigator) == null ? void 0 : _a.userAgent)) {
11336 svg.on("wheel", () => {
11337 });
11338 }
11339 eventRect == null ? void 0 : eventRect.call(behaviour).on("dblclick.zoom", null);
11340 },
11341 /**
11342 * Initialize the drag behaviour used for zooming.
11343 * @private
11344 */
11345 initZoomBehaviour() {
11346 const $$ = this;
11347 const { config, state } = $$;
11348 const isRotated = config.axis_rotated;
11349 let start = 0;
11350 let end = 0;
11351 let zoomRect;
11352 let extent;
11353 const prop = {
11354 axis: isRotated ? "y" : "x",
11355 attr: isRotated ? "height" : "width",
11356 index: isRotated ? 1 : 0
11357 };
11358 $$.zoomBehaviour = (0,external_commonjs_d3_drag_commonjs2_d3_drag_amd_d3_drag_root_d3_.drag)().clickDistance(4).on("start", function(event) {
11359 extent = $$.scale.zoom ? null : $$.axis.getExtent();
11360 state.event = event;
11361 $$.setDragStatus(true);
11362 $$.unselectRect();
11363 if (!zoomRect) {
11364 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);
11365 }
11366 start = getPointer(event, this)[prop.index];
11367 if (extent) {
11368 if (start < extent[0]) {
11369 start = extent[0];
11370 } else if (start > extent[1]) {
11371 start = extent[1];
11372 }
11373 }
11374 end = start;
11375 zoomRect.attr(prop.axis, start).attr(prop.attr, 0);
11376 $$.onZoomStart(event);
11377 }).on("drag", function(event) {
11378 end = getPointer(event, this)[prop.index];
11379 if (extent) {
11380 if (end > extent[1]) {
11381 end = extent[1];
11382 } else if (end < extent[0]) {
11383 end = extent[0];
11384 }
11385 }
11386 zoomRect.attr(prop.axis, Math.min(start, end)).attr(prop.attr, Math.abs(end - start));
11387 }).on("end", (event) => {
11388 const scale = $$.scale.zoom || $$.scale.x;
11389 state.event = event;
11390 zoomRect.attr(prop.axis, 0).attr(prop.attr, 0);
11391 if (start > end) {
11392 [start, end] = [end, start];
11393 }
11394 if (start < 0) {
11395 end += Math.abs(start);
11396 start = 0;
11397 }
11398 if (start !== end) {
11399 $$.api.zoom([start, end].map((v) => scale.invert(v)));
11400 }
11401 $$.setDragStatus(false);
11402 });
11403 },
11404 setZoomResetButton() {
11405 const $$ = this;
11406 const { config, $el } = $$;
11407 const resetButton = config.zoom_resetButton;
11408 if (resetButton && config.zoom_type === "drag") {
11409 if (!$el.zoomResetBtn) {
11410 $el.zoomResetBtn = $$.$el.chart.append("div").classed($COMMON.button, true).append("span").on("click", function() {
11411 isFunction(resetButton.onclick) && resetButton.onclick.bind($$.api)(this);
11412 $$.api.unzoom();
11413 }).classed($ZOOM.buttonZoomReset, true).text(resetButton.text || "Reset Zoom");
11414 } else {
11415 $el.zoomResetBtn.style("display", null);
11416 }
11417 }
11418 },
11419 getZoomTransform() {
11420 const $$ = this;
11421 const { $el: { eventRect } } = $$;
11422 return (eventRect == null ? void 0 : eventRect.node()) ? (0,external_commonjs_d3_zoom_commonjs2_d3_zoom_amd_d3_zoom_root_d3_.zoomTransform)(eventRect.node()) : { k: 1 };
11423 }
11424});
11425
11426;// ./src/ChartInternal/interactions/drag.ts
11427
11428
11429
11430/* harmony default export */ var drag = ({
11431 /**
11432 * Called when dragging.
11433 * Data points can be selected.
11434 * @private
11435 * @param {object} mouse Object
11436 */
11437 drag(mouse) {
11438 const $$ = this;
11439 const { config, state, $el: { main } } = $$;
11440 const isSelectionGrouped = config.data_selection_grouped;
11441 const isSelectable = config.interaction_enabled && config.data_selection_isselectable;
11442 if ($$.hasArcType() || !config.data_selection_enabled || // do nothing if not selectable
11443 config.zoom_enabled && !$$.zoom.altDomain || // skip if zoomable because of conflict drag behavior
11444 !config.data_selection_multiple) {
11445 return;
11446 }
11447 const [sx, sy] = state.dragStart || [0, 0];
11448 const [mx, my] = mouse;
11449 const minX = Math.min(sx, mx);
11450 const maxX = Math.max(sx, mx);
11451 const minY = isSelectionGrouped ? state.margin.top : Math.min(sy, my);
11452 const maxY = isSelectionGrouped ? state.height : Math.max(sy, my);
11453 main.select(`.${$DRAG.dragarea}`).attr("x", minX).attr("y", minY).attr("width", maxX - minX).attr("height", maxY - minY);
11454 main.selectAll(`.${$SHAPE.shapes}`).selectAll(`.${$SHAPE.shape}`).filter((d) => isSelectable == null ? void 0 : isSelectable.bind($$.api)(d)).each(function(d, i) {
11455 const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
11456 const isSelected = shape.classed($SELECT.SELECTED);
11457 const isIncluded = shape.classed($DRAG.INCLUDED);
11458 let isWithin = false;
11459 let toggle;
11460 if (shape.classed($CIRCLE.circle)) {
11461 const x = +shape.attr("cx") * 1;
11462 const y = +shape.attr("cy") * 1;
11463 toggle = $$.togglePoint;
11464 isWithin = minX < x && x < maxX && minY < y && y < maxY;
11465 } else if (shape.classed($BAR.bar)) {
11466 const { x, y, width, height } = getPathBox(this);
11467 toggle = $$.togglePath;
11468 isWithin = !(maxX < x || x + width < minX) && !(maxY < y || y + height < minY);
11469 } else {
11470 return;
11471 }
11472 if (isWithin ^ isIncluded) {
11473 shape.classed($DRAG.INCLUDED, !isIncluded);
11474 shape.classed($SELECT.SELECTED, !isSelected);
11475 toggle.call($$, !isSelected, shape, d, i);
11476 }
11477 });
11478 },
11479 /**
11480 * Called when the drag starts.
11481 * Adds and Shows the drag area.
11482 * @private
11483 * @param {object} mouse Object
11484 */
11485 dragstart(mouse) {
11486 const $$ = this;
11487 const { config, state, $el: { main } } = $$;
11488 if ($$.hasArcType() || !config.data_selection_enabled) {
11489 return;
11490 }
11491 state.dragStart = mouse;
11492 main.select(`.${$COMMON.chart}`).append("rect").attr("class", $DRAG.dragarea).style("opacity", "0.1");
11493 $$.setDragStatus(true);
11494 },
11495 /**
11496 * Called when the drag finishes.
11497 * Removes the drag area.
11498 * @private
11499 */
11500 dragend() {
11501 const $$ = this;
11502 const { config, $el: { main }, $T } = $$;
11503 if ($$.hasArcType() || !config.data_selection_enabled) {
11504 return;
11505 }
11506 $T(main.select(`.${$DRAG.dragarea}`)).style("opacity", "0").remove();
11507 main.selectAll(`.${$SHAPE.shape}`).classed($DRAG.INCLUDED, false);
11508 $$.setDragStatus(false);
11509 }
11510});
11511
11512;// ./src/ChartInternal/internals/selection.ts
11513var selection_defProp = Object.defineProperty;
11514var __defProps = Object.defineProperties;
11515var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
11516var selection_getOwnPropSymbols = Object.getOwnPropertySymbols;
11517var selection_hasOwnProp = Object.prototype.hasOwnProperty;
11518var selection_propIsEnum = Object.prototype.propertyIsEnumerable;
11519var selection_defNormalProp = (obj, key, value) => key in obj ? selection_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11520var selection_spreadValues = (a, b) => {
11521 for (var prop in b || (b = {}))
11522 if (selection_hasOwnProp.call(b, prop))
11523 selection_defNormalProp(a, prop, b[prop]);
11524 if (selection_getOwnPropSymbols)
11525 for (var prop of selection_getOwnPropSymbols(b)) {
11526 if (selection_propIsEnum.call(b, prop))
11527 selection_defNormalProp(a, prop, b[prop]);
11528 }
11529 return a;
11530};
11531var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
11532
11533
11534
11535
11536/* harmony default export */ var internals_selection = (__spreadProps(selection_spreadValues({}, drag), {
11537 /**
11538 * Select a point
11539 * @param {object} target Target point
11540 * @param {object} d Data object
11541 * @param {number} i Index number
11542 * @private
11543 */
11544 selectPoint(target, d, i) {
11545 const $$ = this;
11546 const { config, $el: { main }, $T } = $$;
11547 const isRotated = config.axis_rotated;
11548 const cx = (isRotated ? $$.circleY : $$.circleX).bind($$);
11549 const cy = (isRotated ? $$.circleX : $$.circleY).bind($$);
11550 const r = $$.pointSelectR.bind($$);
11551 callFn(config.data_onselected, $$.api, d, target.node());
11552 $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);
11553 },
11554 /**
11555 * Unelect a point
11556 * @param {object} target Target point
11557 * @param {object} d Data object
11558 * @param {number} i Index number
11559 * @private
11560 */
11561 unselectPoint(target, d, i) {
11562 const $$ = this;
11563 const { config, $el: { main }, $T } = $$;
11564 callFn(config.data_onunselected, $$.api, d, target == null ? void 0 : target.node());
11565 $T(main.select(`.${$SELECT.selectedCircles}${$$.getTargetSelectorSuffix(d.id)}`).selectAll(`.${$SELECT.selectedCircle}-${i}`)).attr("r", 0).remove();
11566 },
11567 /**
11568 * Toggles the selection of points
11569 * @param {boolean} selected whether or not to select.
11570 * @param {object} target Target object
11571 * @param {object} d Data object
11572 * @param {number} i Index number
11573 * @private
11574 */
11575 togglePoint(selected, target, d, i) {
11576 const method = `${selected ? "" : "un"}selectPoint`;
11577 this[method](target, d, i);
11578 },
11579 /**
11580 * Select a path
11581 * @param {object} target Target path
11582 * @param {object} d Data object
11583 * @private
11584 */
11585 selectPath(target, d) {
11586 const $$ = this;
11587 const { config } = $$;
11588 callFn(config.data_onselected, $$.api, d, target.node());
11589 if (config.interaction_brighten) {
11590 target.style("filter", "brightness(1.25)");
11591 }
11592 },
11593 /**
11594 * Unelect a path
11595 * @private
11596 * @param {object} target Target path
11597 * @param {object} d Data object
11598 */
11599 unselectPath(target, d) {
11600 const $$ = this;
11601 const { config } = $$;
11602 callFn(config.data_onunselected, $$.api, d, target.node());
11603 if (config.interaction_brighten) {
11604 target.style("filter", null);
11605 }
11606 },
11607 /**
11608 * Toggles the selection of lines
11609 * @param {boolean} selected whether or not to select.
11610 * @param {object} target Target object
11611 * @param {object} d Data object
11612 * @param {number} i Index number
11613 * @private
11614 */
11615 togglePath(selected, target, d, i) {
11616 this[`${selected ? "" : "un"}selectPath`](target, d, i);
11617 },
11618 /**
11619 * Returns the toggle method of the target
11620 * @param {object} that shape
11621 * @param {object} d Data object
11622 * @returns {Function} toggle method
11623 * @private
11624 */
11625 getToggle(that, d) {
11626 const $$ = this;
11627 return that.nodeName === "path" ? $$.togglePath : $$.isStepType(d) ? () => {
11628 } : (
11629 // circle is hidden in step chart, so treat as within the click area
11630 $$.togglePoint
11631 );
11632 },
11633 /**
11634 * Toggles the selection of shapes
11635 * @param {object} that shape
11636 * @param {object} d Data object
11637 * @param {number} i Index number
11638 * @private
11639 */
11640 toggleShape(that, d, i) {
11641 var _a;
11642 const $$ = this;
11643 const { config, $el: { main } } = $$;
11644 if (config.data_selection_enabled && config.data_selection_isselectable.bind($$.api)(d)) {
11645 const shape = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(that);
11646 const isSelected = shape.classed($SELECT.SELECTED);
11647 const toggle = $$.getToggle(that, d).bind($$);
11648 let toggledShape;
11649 if (!config.data_selection_multiple) {
11650 const focusOnly = (_a = $$.isPointFocusOnly) == null ? void 0 : _a.call($$);
11651 let selector = `.${focusOnly ? $SELECT.selectedCircles : $SHAPE.shapes}`;
11652 if (config.data_selection_grouped) {
11653 selector += $$.getTargetSelectorSuffix(d.id);
11654 }
11655 main.selectAll(selector).selectAll(
11656 focusOnly ? `.${$SELECT.selectedCircle}` : `.${$SHAPE.shape}.${$SELECT.SELECTED}`
11657 ).classed($SELECT.SELECTED, false).each(function(d2) {
11658 const shape2 = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
11659 toggledShape = shape2;
11660 toggle(false, shape2, d2, d2.index);
11661 });
11662 }
11663 if (!toggledShape || toggledShape.node() !== shape.node()) {
11664 shape.classed($SELECT.SELECTED, !isSelected);
11665 toggle(!isSelected, shape, d, i);
11666 }
11667 }
11668 }
11669}));
11670
11671;// ./src/config/Options/data/selection.ts
11672/* harmony default export */ var data_selection = ({
11673 /**
11674 * Set data selection enabled<br><br>
11675 * 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).
11676 * - **NOTE:** for ESM imports, needs to import 'selection' exports and instantiate it by calling `selection()`.
11677 * - `enabled: selection()`
11678 * @name data․selection․enabled
11679 * @memberof Options
11680 * @type {boolean}
11681 * @default false
11682 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataSelection)
11683 * @example
11684 * data: {
11685 * selection: {
11686 * enabled: true
11687 * }
11688 * }
11689 * @example
11690 * // importing ESM
11691 * import bb, {selection} from "billboard.js";
11692 *
11693 * data: {
11694 * selection: {
11695 * enabled: selection(),
11696 * ...
11697 * }
11698 * }
11699 */
11700 data_selection_enabled: false,
11701 /**
11702 * Set grouped selection enabled.<br><br>
11703 * If this option set true, multiple data points that have same x value will be selected by one selection.
11704 * @name data․selection․grouped
11705 * @memberof Options
11706 * @type {boolean}
11707 * @default false
11708 * @example
11709 * data: {
11710 * selection: {
11711 * grouped: true
11712 * }
11713 * }
11714 */
11715 data_selection_grouped: false,
11716 /**
11717 * Set a callback for each data point to determine if it's selectable or not.<br><br>
11718 * The callback will receive d as an argument and it has some parameters like id, value, index. This callback should return boolean.
11719 * @name data․selection․isselectable
11720 * @memberof Options
11721 * @type {Function}
11722 * @default function() { return true; }
11723 * @example
11724 * data: {
11725 * selection: {
11726 * isselectable: function(d) { ... }
11727 * }
11728 * }
11729 */
11730 data_selection_isselectable: () => true,
11731 /**
11732 * Set multiple data points selection enabled.<br><br>
11733 * If this option set true, multile 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.
11734 * @name data․selection․multiple
11735 * @memberof Options
11736 * @type {boolean}
11737 * @default true
11738 * @example
11739 * data: {
11740 * selection: {
11741 * multiple: false
11742 * }
11743 * }
11744 */
11745 data_selection_multiple: true,
11746 /**
11747 * Enable to select data points by dragging.
11748 * If this option set true, data points can be selected by dragging.
11749 * - **NOTE:** If this option set true, scrolling on the chart will be disabled because dragging event will handle the event.
11750 * @name data․selection․draggable
11751 * @memberof Options
11752 * @type {boolean}
11753 * @default false
11754 * @example
11755 * data: {
11756 * selection: {
11757 * draggable: true
11758 * }
11759 * }
11760 */
11761 data_selection_draggable: false,
11762 /**
11763 * Set a callback for on data selection.
11764 * @name data․onselected
11765 * @memberof Options
11766 * @type {Function}
11767 * @default function() {}
11768 * @example
11769 * data: {
11770 * onselected: function(d, element) {
11771 * // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
11772 * // element - <circle>
11773 * ...
11774 * }
11775 * }
11776 */
11777 data_onselected: () => {
11778 },
11779 /**
11780 * Set a callback for on data un-selection.
11781 * @name data․onunselected
11782 * @memberof Options
11783 * @type {Function}
11784 * @default function() {}
11785 * @example
11786 * data: {
11787 * onunselected: function(d, element) {
11788 * // d - ex) {x: 4, value: 150, id: "data1", index: 4, name: "data1"}
11789 * // element - <circle>
11790 * ...
11791 * }
11792 * }
11793 */
11794 data_onunselected: () => {
11795 }
11796});
11797
11798;// ./src/config/Options/interaction/subchart.ts
11799/* harmony default export */ var interaction_subchart = ({
11800 /**
11801 * Set subchart options.
11802 * - **NOTE:** Not supported for `bubble`, `scatter` and non-Axis based(pie, donut, gauge, radar) types.
11803 * @name subchart
11804 * @memberof Options
11805 * @type {object}
11806 * @property {object} subchart Subchart object
11807 * @property {boolean} [subchart.show=false] Show sub chart on the bottom of the chart.
11808 * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
11809 * - `show: subchart()`
11810 * @property {boolean} [subchart.showHandle=false] Show sub chart's handle.
11811 * @property {boolean} [subchart.axis.x.show=true] Show or hide x axis.
11812 * @property {boolean} [subchart.axis.x.tick.show=true] Show or hide x axis tick line.
11813 * @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.
11814 * @property {boolean} [subchart.axis.x.tick.text.show=true] Show or hide x axis tick text.
11815 * @property {Array} [subchart.init.range] Set initial selection domain range.
11816 * @property {number} [subchart.size.height] Change the height of the subchart.
11817 * @property {Function} [subchart.onbrush] Set callback for brush event.<br>
11818 * Specified function receives the current zoomed x domain.
11819 * @see [Demo](https://naver.github.io/billboard.js/demo/#Interaction.SubChart)
11820 * @example
11821 * subchart: {
11822 * show: true,
11823 * showHandle: true,
11824 * size: {
11825 * height: 20
11826 * },
11827 * init: {
11828 * // specify initial range domain selection
11829 * range: [1, 2]
11830 * },
11831 * axis: {
11832 * x: {
11833 * show: true,
11834 * tick: {
11835 * show: true,
11836 * format: (x) => d3Format(".1f")(x)
11837 * text: {
11838 * show: false
11839 * }
11840 * }
11841 * }
11842 * },
11843 * onbrush: function(domain) { ... }
11844 * }
11845 * @example
11846 * // importing ESM
11847 * import bb, {subchart} from "billboard.js";
11848 *
11849 * subchart: {
11850 * show: subchart(),
11851 * ...
11852 * }
11853 */
11854 subchart_show: false,
11855 subchart_showHandle: false,
11856 subchart_size_height: 60,
11857 subchart_axis_x_show: true,
11858 subchart_axis_x_tick_show: true,
11859 subchart_axis_x_tick_format: void 0,
11860 subchart_axis_x_tick_text_show: true,
11861 subchart_init_range: void 0,
11862 subchart_onbrush: () => {
11863 }
11864});
11865
11866;// ./src/config/Options/interaction/zoom.ts
11867/* harmony default export */ var interaction_zoom = ({
11868 /**
11869 * Set zoom options
11870 * @name zoom
11871 * @memberof Options
11872 * @type {object}
11873 * @property {object} zoom Zoom object
11874 * @property {boolean} [zoom.enabled=false] Enable zooming.
11875 * - **NOTE:** for ESM imports, needs to import 'zoom' exports and instantiate it by calling `zoom()`.
11876 * - `enabled: zoom()`
11877 * @property {string} [zoom.type='wheel'] Set zoom interaction type.
11878 * - **Available types:**
11879 * - wheel
11880 * - drag
11881 * @property {boolean} [zoom.rescale=false] Enable to rescale after zooming.<br>
11882 * If true set, y domain will be updated according to the zoomed region.
11883 * @property {Array} [zoom.extent=[1, 10]] Change zoom extent.
11884 * @property {number|Date} [zoom.x.min] Set x Axis minimum zoom range
11885 * @property {number|Date} [zoom.x.max] Set x Axis maximum zoom range
11886 * @property {Function} [zoom.onzoomstart=undefined] Set callback that is called when zooming starts.<br>
11887 * Specified function receives the zoom event.
11888 * @property {Function} [zoom.onzoom=undefined] Set callback that is called when the chart is zooming.<br>
11889 * Specified function receives the zoomed domain.
11890 * @property {Function} [zoom.onzoomend=undefined] Set callback that is called when zooming ends.<br>
11891 * Specified function receives the zoomed domain.
11892 * @property {boolean|object} [zoom.resetButton=true] Set to display zoom reset button for 'drag' type zoom
11893 * @property {Function} [zoom.resetButton.onclick] Set callback when clicks the reset button. The callback will receive reset button element reference as argument.
11894 * @property {string} [zoom.resetButton.text='Reset Zoom'] Text value for zoom reset button.
11895 * @see [Demo:zoom](https://naver.github.io/billboard.js/demo/#Interaction.Zoom)
11896 * @see [Demo:drag zoom](https://naver.github.io/billboard.js/demo/#Interaction.DragZoom)
11897 * @example
11898 * zoom: {
11899 * enabled: true,
11900 * type: "drag",
11901 * rescale: true,
11902 * extent: [1, 100] // enable more zooming
11903 * x: {
11904 * min: -1, // set min range
11905 * max: 10 // set max range
11906 * },
11907 * onzoomstart: function(event) { ... },
11908 * onzoom: function(domain) { ... },
11909 * onzoomend: function(domain) { ... },
11910 *
11911 * // show reset button when is zoomed-in
11912 * resetButton: true,
11913 *
11914 * resetButton: {
11915 * // onclick callback when reset button is clicked
11916 * onclick: function(button) {
11917 * button; // Reset button element reference
11918 * ...
11919 * },
11920 *
11921 * // customized text value for reset zoom button
11922 * text: "Unzoom"
11923 * }
11924 * }
11925 * @example
11926 * // importing ESM
11927 * import bb, {zoom} from "billboard.js";
11928 *
11929 * zoom: {
11930 * enabled: zoom(),
11931 * ...
11932 * }
11933 */
11934 zoom_enabled: false,
11935 zoom_type: "wheel",
11936 zoom_extent: void 0,
11937 zoom_privileged: false,
11938 zoom_rescale: false,
11939 zoom_onzoom: void 0,
11940 zoom_onzoomstart: void 0,
11941 zoom_onzoomend: void 0,
11942 zoom_resetButton: true,
11943 zoom_x_min: void 0,
11944 zoom_x_max: void 0
11945});
11946
11947;// ./src/config/resolver/interaction.ts
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962let selectionModule = () => {
11963 extend(ChartInternal.prototype, internals_selection);
11964 extend(Chart.prototype, selection);
11965 Options.setOptions([data_selection]);
11966 return (selectionModule = () => true)();
11967};
11968let subchartModule = () => {
11969 extend(ChartInternal.prototype, interactions_subchart);
11970 extend(Chart.prototype, api_subchart);
11971 Options.setOptions([interaction_subchart]);
11972 return (subchartModule = () => true)();
11973};
11974let zoomModule = () => {
11975 extend(ChartInternal.prototype, interactions_zoom);
11976 extend(Chart.prototype, api_zoom);
11977 Options.setOptions([interaction_zoom]);
11978 return (zoomModule = () => true)();
11979};
11980
11981;// ./src/Chart/api/axis.ts
11982
11983function setMinMax($$, type, value) {
11984 const { config } = $$;
11985 const helper = (key, value2) => {
11986 const v = isNumber(value2) ? value2 : value2 === false ? void 0 : null;
11987 if (v !== null) {
11988 config[`axis_${key}_${type}`] = v;
11989 }
11990 };
11991 if (isDefined(value)) {
11992 if (isObjectType(value)) {
11993 Object.keys(value).forEach((key) => {
11994 helper(key, value[key]);
11995 });
11996 } else if (isNumber(value) || value === false) {
11997 ["y", "y2"].forEach((key) => {
11998 helper(key, value);
11999 });
12000 }
12001 $$.redraw({
12002 withUpdateOrgXDomain: true,
12003 withUpdateXDomain: true
12004 });
12005 }
12006}
12007function axis_getMinMax($$, type) {
12008 const { config } = $$;
12009 return {
12010 x: config[`axis_x_${type}`],
12011 y: config[`axis_y_${type}`],
12012 y2: config[`axis_y2_${type}`]
12013 };
12014}
12015const axis = {
12016 /**
12017 * Get and set axis labels.
12018 * - **NOTE:** Only applicable for chart types which has x and y axes.
12019 * @function axis․labels
12020 * @instance
12021 * @memberof Chart
12022 * @param {object} labels specified axis' label to be updated.
12023 * @param {string} [labels.x] x Axis string
12024 * @param {string} [labels.y] y Axis string
12025 * @param {string} [labels.y2] y2 Axis string
12026 * @returns {object|undefined} axis labels text object
12027 * @example
12028 * // Update axis' label
12029 * chart.axis.labels({
12030 * x: "New X Axis Label",
12031 * y: "New Y Axis Label",
12032 * y2: "New Y2 Axis Label"
12033 * });
12034 *
12035 * chart.axis.labels();
12036 * // --> {
12037 * // x: "New X Axis Label",
12038 * // y: "New Y Axis Label",
12039 * // y2: "New Y2 Axis Label"
12040 * // }
12041 */
12042 labels: function(labels) {
12043 const $$ = this.internal;
12044 let labelText;
12045 if (labels) {
12046 Object.keys(labels).forEach((axisId) => {
12047 $$.axis.setLabelText(axisId, labels[axisId]);
12048 });
12049 $$.axis.updateLabels();
12050 }
12051 ["x", "y", "y2"].forEach((v) => {
12052 const text = $$.axis.getLabelText(v);
12053 if (text) {
12054 !labelText && (labelText = {});
12055 labelText[v] = text;
12056 }
12057 });
12058 return labelText;
12059 },
12060 /**
12061 * Get and set axis min value.
12062 * - **NOTE:** Only applicable for chart types which has x and y axes.
12063 * @function axis․min
12064 * @instance
12065 * @memberof Chart
12066 * @param {object} min If min is given, specified axis' min value will be updated.<br>
12067 * If no argument is given, the min values set on generating option for each axis will be returned.
12068 * If not set any min values on generation, it will return `undefined`.<br>
12069 * To unset specific axis max, set `false` to each of them.
12070 * @returns {object|undefined}
12071 * @example
12072 * // Update axis' min
12073 * chart.axis.min({
12074 * x: -10,
12075 * y: 1000,
12076 * y2: 100
12077 * });
12078 *
12079 * // To unset specific axis min, set false to each of them.
12080 * chart.axis.min({
12081 * x: false,
12082 * y: false,
12083 * y2: false
12084 * });
12085 *
12086 * // shorthand (only affects y and y2 axis)
12087 * chart.axis.min(-50);
12088 * chart.axis.min(false);
12089 */
12090 min: function(min) {
12091 const $$ = this.internal;
12092 return isValue(min) || min === false ? setMinMax($$, "min", min) : axis_getMinMax($$, "min");
12093 },
12094 /**
12095 * Get and set axis max value.
12096 * - **NOTE:** Only applicable for chart types which has x and y axes.
12097 * @function axis․max
12098 * @instance
12099 * @memberof Chart
12100 * @param {object} max If max is given, specified axis' max value will be updated.<br>
12101 * If no argument is given, the max values set on generating option for each axis will be returned.
12102 * If not set any max values on generation, it will return `undefined`.<br>
12103 * To unset specific axis max, set `false` to each of them.
12104 * @returns {object|undefined}
12105 * @example
12106 * // Update axis' label
12107 * chart.axis.max({
12108 * x: 100,
12109 * y: 1000,
12110 * y2: 10000
12111 * });
12112 *
12113 * // To unset specific axis max, set false to each of them.
12114 * chart.axis.max({
12115 * x: false,
12116 * y: false,
12117 * y2: false
12118 * });
12119 *
12120 * // shorthand (only affects y and y2 axis)
12121 * chart.axis.max(10);
12122 * chart.axis.max(false);
12123 */
12124 max: function(max) {
12125 const $$ = this.internal;
12126 return isValue(max) || max === false ? setMinMax($$, "max", max) : axis_getMinMax($$, "max");
12127 },
12128 /**
12129 * Get and set axis min and max value.
12130 * - **NOTE:** Only applicable for chart types which has x and y axes.
12131 * @function axis․range
12132 * @instance
12133 * @memberof Chart
12134 * @param {object} range If range is given, specified axis' min and max value will be updated.
12135 * If no argument is given, the current min and max values for each axis will be returned.<br>
12136 * To unset specific axis max, set `false` to each of them.
12137 * @returns {object|undefined}
12138 * @example
12139 * // Update axis' label
12140 * chart.axis.range({
12141 * min: {
12142 * x: -10,
12143 * y: -1000,
12144 * y2: -10000
12145 * },
12146 * max: {
12147 * x: 100,
12148 * y: 1000,
12149 * y2: 10000
12150 * },
12151 * });
12152 *
12153 * // To unset specific axis max, set false to each of them.
12154 * chart.axis.range({
12155 * min: {
12156 * x: false,
12157 * y: false,
12158 * y2: false
12159 * },
12160 * max: {
12161 * x: false,
12162 * y: false,
12163 * y2: false
12164 * },
12165 * });
12166 *
12167 * // shorthand (only affects y and y2 axis)
12168 * chart.axis.range({ min: -50, max: 1000 });
12169 * chart.axis.range({ min: false, max: false });
12170 */
12171 range: function(range) {
12172 const { axis: axis2 } = this;
12173 if (arguments.length) {
12174 const { min, max } = range;
12175 isDefined(max) && axis2.max(max);
12176 isDefined(min) && axis2.min(min);
12177 } else {
12178 return {
12179 max: axis2.max(),
12180 min: axis2.min()
12181 };
12182 }
12183 return void 0;
12184 }
12185};
12186/* harmony default export */ var api_axis = ({ axis });
12187
12188;// ./src/Chart/api/category.ts
12189
12190/* harmony default export */ var api_category = ({
12191 /**
12192 * Set specified category name on category axis.
12193 * @function category
12194 * @instance
12195 * @memberof Chart
12196 * @param {number} i index of category to be changed
12197 * @param {string} category category value to be changed
12198 * @returns {string}
12199 * @example
12200 * chart.category(2, "Category 3");
12201 */
12202 category(i, category) {
12203 const $$ = this.internal;
12204 const { config } = $$;
12205 if (arguments.length > 1) {
12206 config.axis_x_categories[i] = category;
12207 $$.redraw();
12208 }
12209 return config.axis_x_categories[i];
12210 },
12211 /**
12212 * Set or get category names on category axis.
12213 * @function categories
12214 * @instance
12215 * @memberof Chart
12216 * @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.
12217 * @returns {Array}
12218 * @example
12219 * chart.categories([
12220 * "Category 1", "Category 2", ...
12221 * ]);
12222 */
12223 categories(categories) {
12224 const $$ = this.internal;
12225 const { config } = $$;
12226 if (!categories || !Array.isArray(categories)) {
12227 const cat = config.axis_x_categories;
12228 return isEmpty(cat) ? Object.values($$.data.xs)[0] : cat;
12229 }
12230 config.axis_x_categories = categories;
12231 $$.redraw();
12232 return config.axis_x_categories;
12233 }
12234});
12235
12236;// ./src/Chart/api/flow.ts
12237
12238/* harmony default export */ var flow = ({
12239 /**
12240 * Flow data to the chart.<br><br>
12241 * By this API, you can append new data points to the chart.
12242 * @function flow
12243 * @instance
12244 * @memberof Chart
12245 * @param {object} args The object can consist with following members:<br>
12246 *
12247 * | Key | Type | Description |
12248 * | --- | --- | --- |
12249 * | json | Object | Data as JSON format (@see [data․json](Options.html#.data%25E2%2580%25A4json)) |
12250 * | rows | Array | Data in array as row format (@see [data․rows](Options.html#.data%25E2%2580%25A4json)) |
12251 * | columns | Array | Data in array as column format (@see [data․columns](Options.html#.data%25E2%2580%25A4columns)) |
12252 * | 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 |
12253 * | length | Number | The lower x edge will move by the number of this argument |
12254 * | duration | Number | The duration of the transition will be specified value. If not given, transition.duration will be used as default |
12255 * | done | Function | The specified function will be called when flow ends |
12256 *
12257 * - **NOTE:**
12258 * - If json, rows and columns given, the data will be loaded.
12259 * - If data that has the same target id is given, the chart will be appended.
12260 * - Otherwise, new target will be added. One of these is required when calling.
12261 * - If json specified, keys is required as well as data.json.
12262 * - If tab isn't visible(by evaluating `document.hidden`), will not be executed to prevent unnecessary work.
12263 * @example
12264 * // 2 data points will be apprended to the tail and popped from the head.
12265 * // After that, 4 data points will be appended and no data points will be poppoed.
12266 * chart.flow({
12267 * columns: [
12268 * ["x", "2018-01-11", "2018-01-21"],
12269 * ["data1", 500, 200],
12270 * ["data2", 100, 300],
12271 * ["data3", 200, 120]
12272 * ],
12273 * to: "2013-01-11",
12274 * done: function () {
12275 * chart.flow({
12276 * columns: [
12277 * ["x", "2018-02-11", "2018-02-12", "2018-02-13", "2018-02-14"],
12278 * ["data1", 200, 300, 100, 250],
12279 * ["data2", 100, 90, 40, 120],
12280 * ["data3", 100, 100, 300, 500]
12281 * ],
12282 * length: 2,
12283 * duration: 1500
12284 * });
12285 * }
12286 * });
12287 */
12288 flow(args) {
12289 const $$ = this.internal;
12290 let data;
12291 if (args.json || args.rows || args.columns) {
12292 $$.convertData(args, (res) => {
12293 data = res;
12294 _();
12295 });
12296 }
12297 function _() {
12298 let domain;
12299 let length = 0;
12300 let tail = 0;
12301 let diff;
12302 let to;
12303 if ($$.state.redrawing || !data || !isTabVisible()) {
12304 return;
12305 }
12306 const notfoundIds = [];
12307 const orgDataCount = $$.getMaxDataCount();
12308 const targets = $$.convertDataToTargets(data, true);
12309 const isTimeSeries = $$.axis.isTimeSeries();
12310 $$.data.targets.forEach((t) => {
12311 let found = false;
12312 for (let i = 0; i < targets.length; i++) {
12313 if (t.id === targets[i].id) {
12314 found = true;
12315 if (t.values[t.values.length - 1]) {
12316 tail = t.values[t.values.length - 1].index + 1;
12317 }
12318 length = targets[i].values.length;
12319 for (let j = 0; j < length; j++) {
12320 targets[i].values[j].index = tail + j;
12321 if (!isTimeSeries) {
12322 targets[i].values[j].x = tail + j;
12323 }
12324 }
12325 t.values = t.values.concat(targets[i].values);
12326 targets.splice(i, 1);
12327 break;
12328 }
12329 }
12330 !found && notfoundIds.push(t.id);
12331 });
12332 $$.data.targets.forEach((t) => {
12333 for (let i = 0; i < notfoundIds.length; i++) {
12334 if (t.id === notfoundIds[i]) {
12335 tail = t.values[t.values.length - 1].index + 1;
12336 for (let j = 0; j < length; j++) {
12337 t.values.push({
12338 id: t.id,
12339 index: tail + j,
12340 x: isTimeSeries ? $$.getOtherTargetX(tail + j) : tail + j,
12341 value: null
12342 });
12343 }
12344 }
12345 }
12346 });
12347 if ($$.data.targets.length) {
12348 targets.forEach((t) => {
12349 const missing = [];
12350 for (let i = $$.data.targets[0].values[0].index; i < tail; i++) {
12351 missing.push({
12352 id: t.id,
12353 index: i,
12354 x: isTimeSeries ? $$.getOtherTargetX(i) : i,
12355 value: null
12356 });
12357 }
12358 t.values.forEach((v) => {
12359 v.index += tail;
12360 if (!isTimeSeries) {
12361 v.x += tail;
12362 }
12363 });
12364 t.values = missing.concat(t.values);
12365 });
12366 }
12367 $$.data.targets = $$.data.targets.concat(targets);
12368 const baseTarget = $$.data.targets[0];
12369 const baseValue = baseTarget.values[0];
12370 if (isDefined(args.to)) {
12371 length = 0;
12372 to = isTimeSeries ? parseDate.call($$, args.to) : args.to;
12373 baseTarget.values.forEach((v) => {
12374 v.x < to && length++;
12375 });
12376 } else if (isDefined(args.length)) {
12377 length = args.length;
12378 }
12379 if (!orgDataCount) {
12380 if (isTimeSeries) {
12381 diff = baseTarget.values.length > 1 ? baseTarget.values[baseTarget.values.length - 1].x - baseValue.x : baseValue.x - $$.getXDomain($$.data.targets)[0];
12382 } else {
12383 diff = 1;
12384 }
12385 domain = [baseValue.x - diff, baseValue.x];
12386 } else if (orgDataCount === 1 && isTimeSeries) {
12387 diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
12388 domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
12389 }
12390 domain && $$.updateXDomain(null, true, true, false, domain);
12391 $$.updateTargets($$.data.targets);
12392 $$.redraw({
12393 flow: {
12394 index: baseValue.index,
12395 length,
12396 duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
12397 done: args.done,
12398 orgDataCount
12399 },
12400 withLegend: true,
12401 withTransition: orgDataCount > 1,
12402 withTrimXDomain: false,
12403 withUpdateXAxis: true
12404 });
12405 }
12406 }
12407});
12408
12409;// ./src/Chart/api/grid.ts
12410
12411function grid(grids, axisId) {
12412 const $$ = this.internal;
12413 const { config } = $$;
12414 const withTransition = config.transition_duration && isTabVisible();
12415 const gridPropLines = `grid_${axisId}_lines`;
12416 if (!grids) {
12417 return config[gridPropLines];
12418 }
12419 config[gridPropLines] = grids;
12420 $$.updateGrid();
12421 $$.redrawGrid(withTransition);
12422 return config[gridPropLines];
12423}
12424function add(grids, axisId) {
12425 const gridPropLines = `grid_${axisId}_lines`;
12426 return grid.bind(this)(
12427 this.internal.config[gridPropLines].concat(grids || []),
12428 axisId
12429 );
12430}
12431function remove(grids, isXAxis) {
12432 this.internal.removeGridLines(grids, isXAxis);
12433}
12434const xgrids = function(grids) {
12435 return grid.bind(this)(grids, "x");
12436};
12437extend(xgrids, {
12438 /**
12439 * Add x grid lines.<br>
12440 * This API adds new x grid lines instead of replacing like xgrids.
12441 * @function xgrids․add
12442 * @instance
12443 * @memberof Chart
12444 * @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.
12445 * @returns {Array}
12446 * @example
12447 * // Add a new x grid line
12448 * chart.xgrids.add(
12449 * {value: 4, text: "Label 4"}
12450 * );
12451 *
12452 * // Add new x grid lines
12453 * chart.xgrids.add([
12454 * {value: 2, text: "Label 2"},
12455 * {value: 4, text: "Label 4"}
12456 * ]);
12457 */
12458 add(grids) {
12459 return add.bind(this)(grids, "x");
12460 },
12461 /**
12462 * Remove x grid lines.<br>
12463 * This API removes x grid lines.
12464 * @function xgrids․remove
12465 * @instance
12466 * @memberof Chart
12467 * @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.
12468 * @param {number} [grids.value] target value
12469 * @param {string} [grids.class] target class
12470 * @returns {void}
12471 * @example
12472 * // x grid line on x = 2 will be removed
12473 * chart.xgrids.remove({value: 2});
12474 *
12475 * // x grid lines that have 'grid-A' will be removed
12476 * chart.xgrids.remove({
12477 * class: "grid-A"
12478 * });
12479 *
12480 * // all of x grid lines will be removed
12481 * chart.xgrids.remove();
12482 */
12483 remove(grids) {
12484 return remove.bind(this)(grids, true);
12485 }
12486});
12487const ygrids = function(grids) {
12488 return grid.bind(this)(grids, "y");
12489};
12490extend(ygrids, {
12491 /**
12492 * Add y grid lines.<br>
12493 * This API adds new y grid lines instead of replacing like ygrids.
12494 * @function ygrids․add
12495 * @instance
12496 * @memberof Chart
12497 * @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.
12498 * @returns {object}
12499 * @example
12500 * // Add a new x grid line
12501 * chart.ygrids.add(
12502 * {value: 400, text: "Label 4"}
12503 * );
12504 *
12505 * // Add new x grid lines
12506 * chart.ygrids.add([
12507 * {value: 200, text: "Label 2"},
12508 * {value: 400, text: "Label 4"}
12509 * ]);
12510 */
12511 add(grids) {
12512 return add.bind(this)(grids, "y");
12513 },
12514 /**
12515 * Remove y grid lines.<br>
12516 * This API removes x grid lines.
12517 * @function ygrids․remove
12518 * @instance
12519 * @memberof Chart
12520 * @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.
12521 * @param {number} [grids.value] target value
12522 * @param {string} [grids.class] target class
12523 * @returns {void}
12524 * @example
12525 * // y grid line on y = 200 will be removed
12526 * chart.ygrids.remove({value: 200});
12527 *
12528 * // y grid lines that have 'grid-A' will be removed
12529 * chart.ygrids.remove({
12530 * class: "grid-A"
12531 * });
12532 *
12533 * // all of y grid lines will be removed
12534 * chart.ygrids.remove();
12535 */
12536 remove(grids) {
12537 return remove.bind(this)(grids, false);
12538 }
12539});
12540/* harmony default export */ var api_grid = ({ xgrids, ygrids });
12541
12542;// ./src/Chart/api/group.ts
12543
12544/* harmony default export */ var group = ({
12545 /**
12546 * Update groups for the targets.
12547 * @function groups
12548 * @instance
12549 * @memberof Chart
12550 * @param {Array} groups This argument needs to be an Array that includes one or more Array that includes target ids to be grouped.
12551 * @returns {Array} Grouped data names array
12552 * @example
12553 * // data1 and data2 will be a new group.
12554 * chart.groups([
12555 * ["data1", "data2"]
12556 * ]);
12557 */
12558 groups(groups) {
12559 const $$ = this.internal;
12560 const { config } = $$;
12561 if (isUndefined(groups)) {
12562 return config.data_groups;
12563 }
12564 config.data_groups = groups;
12565 $$.redraw();
12566 return config.data_groups;
12567 }
12568});
12569
12570;// ./src/Chart/api/regions.ts
12571
12572
12573function regionsFn(regions2, isAdd = false) {
12574 const $$ = this.internal;
12575 const { config } = $$;
12576 const withTransition = config.transition_duration && isTabVisible();
12577 if (!regions2) {
12578 return config.regions;
12579 }
12580 config.regions = isAdd ? config.regions.concat(regions2) : regions2;
12581 $$.updateRegion();
12582 $$.redrawRegion(withTransition);
12583 return isAdd ? config.regions : regions2;
12584}
12585const regions = function(regions2) {
12586 return regionsFn.bind(this)(regions2);
12587};
12588extend(regions, {
12589 /**
12590 * Add new region.<br><br>
12591 * This API adds new region instead of replacing like regions.
12592 * @function regions․add
12593 * @instance
12594 * @memberof Chart
12595 * @param {Array|object} regions New region will be added. The format of this argument is the same as regions and it's possible to give an Object if only one region will be added.
12596 * @returns {Array} regions
12597 * @example
12598 * // Add a new region
12599 * chart.regions.add(
12600 * {
12601 * axis: "x", start: 5, class: "regionX",
12602 * label: {
12603 * text: "Region Text",
12604 * color: "red" // color string
12605 * }
12606 * }
12607 * );
12608 *
12609 * // Add new regions
12610 * chart.regions.add([
12611 * {axis: "x", start: 5, class: "regionX"},
12612 * {
12613 * axis: "y", end: 50, class: "regionY",
12614 * label: {
12615 * text: "Region Text",
12616 * x: 5, // position relative of the initial x coordinate
12617 * y: 5, // position relative of the initial y coordinate
12618 * color: "red", // color string
12619 * rotated: true // make text to show in vertical or horizontal
12620 * }
12621 * }
12622 * ]);
12623 */
12624 add: function(regions2) {
12625 return regionsFn.bind(this)(regions2, true);
12626 },
12627 /**
12628 * Remove regions.<br><br>
12629 * This API removes regions.
12630 * @function regions․remove
12631 * @instance
12632 * @memberof Chart
12633 * @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.
12634 * @returns {Array} regions Removed regions
12635 * @example
12636 * // regions that have 'region-A' or 'region-B' will be removed.
12637 * chart.regions.remove({
12638 * classes: [
12639 * "region-A", "region-B"
12640 * ]
12641 * });
12642 *
12643 * // all of regions will be removed.
12644 * chart.regions.remove();
12645 */
12646 remove: function(optionsValue) {
12647 const $$ = this.internal;
12648 const { config, $T } = $$;
12649 const options = optionsValue || {};
12650 const classes = getOption(options, "classes", [$REGION.region]);
12651 let regions2 = $$.$el.main.select(`.${$REGION.regions}`).selectAll(classes.map((c) => `.${c}`));
12652 $T(regions2).style("opacity", "0").remove();
12653 regions2 = config.regions;
12654 if (Object.keys(options).length) {
12655 regions2 = regions2.filter((region) => {
12656 let found = false;
12657 if (!region.class) {
12658 return true;
12659 }
12660 region.class.split(" ").forEach((c) => {
12661 if (classes.indexOf(c) >= 0) {
12662 found = true;
12663 }
12664 });
12665 return !found;
12666 });
12667 config.regions = regions2;
12668 } else {
12669 config.regions = [];
12670 }
12671 return regions2;
12672 }
12673});
12674/* harmony default export */ var api_regions = ({ regions });
12675
12676;// ./src/Chart/api/x.ts
12677
12678/* harmony default export */ var x = ({
12679 /**
12680 * Get and set x values for the chart.
12681 * @function x
12682 * @instance
12683 * @memberof Chart
12684 * @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.
12685 * @returns {object} xs
12686 * @example
12687 * // Get current x values
12688 * chart.x();
12689 *
12690 * // Update x values for all targets
12691 * chart.x([100, 200, 300, 400, ...]);
12692 */
12693 x(x) {
12694 const $$ = this.internal;
12695 const { axis, data } = $$;
12696 const isCategorized = axis.isCustomX() && axis.isCategorized();
12697 if (isArray(x)) {
12698 if (isCategorized) {
12699 this.categories(x);
12700 } else {
12701 $$.updateTargetX(data.targets, x);
12702 $$.redraw({
12703 withUpdateOrgXDomain: true,
12704 withUpdateXDomain: true
12705 });
12706 }
12707 }
12708 return isCategorized ? this.categories() : data.xs;
12709 },
12710 /**
12711 * Get and set x values for the chart.
12712 * @function xs
12713 * @instance
12714 * @memberof Chart
12715 * @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.
12716 * @returns {object} xs
12717 * @example
12718 * // Get current x values
12719 * chart.xs();
12720 *
12721 * // Update x values for all targets
12722 * chart.xs({
12723 * data1: [10, 20, 30, 40, ...],
12724 * data2: [100, 200, 300, 400, ...]
12725 * });
12726 */
12727 xs(xs) {
12728 const $$ = this.internal;
12729 if (isObject(xs)) {
12730 $$.updateTargetXs($$.data.targets, xs);
12731 $$.redraw({
12732 withUpdateOrgXDomain: true,
12733 withUpdateXDomain: true
12734 });
12735 }
12736 return $$.data.xs;
12737 }
12738});
12739
12740// EXTERNAL MODULE: external {"commonjs":"d3-axis","commonjs2":"d3-axis","amd":"d3-axis","root":"d3"}
12741var external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_ = __webpack_require__(11);
12742;// ./src/ChartInternal/Axis/AxisRendererHelper.ts
12743var AxisRendererHelper_defProp = Object.defineProperty;
12744var AxisRendererHelper_defNormalProp = (obj, key, value) => key in obj ? AxisRendererHelper_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12745var AxisRendererHelper_publicField = (obj, key, value) => AxisRendererHelper_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
12746
12747
12748class AxisRendererHelper {
12749 constructor(owner) {
12750 AxisRendererHelper_publicField(this, "owner");
12751 AxisRendererHelper_publicField(this, "config");
12752 AxisRendererHelper_publicField(this, "scale");
12753 const scale = getScale();
12754 const { config, params } = owner;
12755 this.owner = owner;
12756 this.config = config;
12757 this.scale = scale;
12758 if (config.noTransition || !params.config.transition_duration) {
12759 config.withoutTransition = true;
12760 }
12761 config.range = this.scaleExtent((params.orgXScale || scale).range());
12762 }
12763 /**
12764 * Compute a character dimension
12765 * @param {d3.selection} text SVG text selection
12766 * @param {boolean} memoize memoize the calculated size
12767 * @returns {{w: number, h: number}}
12768 * @private
12769 */
12770 static getSizeFor1Char(text, memoize = true) {
12771 const size = {
12772 w: 5.5,
12773 h: 11.5
12774 };
12775 !text.empty() && text.text("0").call((el) => {
12776 try {
12777 const { width, height } = el.node().getBBox();
12778 if (width && height) {
12779 size.w = width;
12780 size.h = height;
12781 }
12782 } finally {
12783 el.text("");
12784 }
12785 });
12786 if (memoize) {
12787 this.getSizeFor1Char = () => size;
12788 }
12789 return size;
12790 }
12791 /**
12792 * Get tick transform setter function
12793 * @param {string} id Axis id
12794 * @returns {Function} transfrom setter function
12795 * @private
12796 */
12797 getTickTransformSetter(id) {
12798 const { config } = this;
12799 const fn = id === "x" ? (value) => `translate(${value + config.tickOffset},0)` : (value) => `translate(0,${value})`;
12800 return (selection, scale) => {
12801 selection.attr("transform", (d) => {
12802 const x = scale(d);
12803 return isValue(d) ? fn(x) : null;
12804 });
12805 };
12806 }
12807 scaleExtent(domain) {
12808 const start = domain[0];
12809 const stop = domain[domain.length - 1];
12810 return start < stop ? [start, stop] : [stop, start];
12811 }
12812 generateTicks(scale, isYAxes) {
12813 const { tickStepSize } = this.owner.params;
12814 const [start, end] = scale.domain();
12815 let ticks = [];
12816 if (isYAxes && tickStepSize) {
12817 let interval = Math.round(start);
12818 while (interval <= end) {
12819 ticks.push(interval);
12820 interval += tickStepSize;
12821 }
12822 } else if (scale.ticks) {
12823 const { tickArguments } = this.config;
12824 if (scale.type === "log" && !tickArguments) {
12825 const s = getScale("_log").domain([start > 0 ? start : 1, end]).range(scale.range());
12826 ticks = s.ticks();
12827 for (let cnt = end.toFixed().length; ticks.length > 15; cnt--) {
12828 ticks = s.ticks(cnt);
12829 }
12830 ticks.splice(0, 1, start);
12831 ticks.splice(ticks.length - 1, 1, end);
12832 } else {
12833 ticks = scale.ticks(...this.config.tickArguments || []);
12834 }
12835 ticks = ticks.map((v) => {
12836 const r = isString(v) && isNumber(v) && !isNaN(v) && Math.round(v * 10) / 10 || v;
12837 return r;
12838 });
12839 }
12840 return ticks;
12841 }
12842 copyScale() {
12843 const newScale = this.scale.copy();
12844 if (!newScale.domain().length) {
12845 newScale.domain(this.scale.domain());
12846 }
12847 newScale.type = this.scale.type;
12848 return newScale;
12849 }
12850 textFormatted(v) {
12851 const tickFormat = this.config.tickFormat;
12852 const value = /\d+\.\d+0{5,}\d$/.test(v) ? +String(v).replace(/0+\d$/, "") : v;
12853 const formatted = tickFormat ? tickFormat(value) : value;
12854 return isDefined(formatted) ? formatted : "";
12855 }
12856 transitionise(selection) {
12857 const { config } = this;
12858 let transitionSelection = selection;
12859 if (config.withoutTransition) {
12860 transitionSelection = selection.interrupt();
12861 } else if (config.transition || !this.owner.params.noTransition) {
12862 try {
12863 transitionSelection = selection.transition(config.transition);
12864 } catch (e) {
12865 }
12866 }
12867 return transitionSelection;
12868 }
12869}
12870
12871;// ./src/ChartInternal/Axis/AxisRenderer.ts
12872var AxisRenderer_defProp = Object.defineProperty;
12873var AxisRenderer_defNormalProp = (obj, key, value) => key in obj ? AxisRenderer_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12874var AxisRenderer_publicField = (obj, key, value) => AxisRenderer_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
12875
12876
12877
12878class AxisRenderer {
12879 constructor(params = {}) {
12880 AxisRenderer_publicField(this, "helper");
12881 AxisRenderer_publicField(this, "config");
12882 AxisRenderer_publicField(this, "params");
12883 AxisRenderer_publicField(this, "g");
12884 AxisRenderer_publicField(this, "generatedTicks");
12885 const config = {
12886 innerTickSize: 6,
12887 outerTickSize: params.outerTick ? 6 : 0,
12888 orient: "bottom",
12889 range: [],
12890 tickArguments: null,
12891 tickCentered: null,
12892 tickCulling: true,
12893 tickFormat: null,
12894 tickLength: 9,
12895 tickOffset: 0,
12896 tickPadding: 3,
12897 tickValues: null,
12898 transition: null,
12899 noTransition: params.noTransition
12900 };
12901 config.tickLength = Math.max(config.innerTickSize, 0) + config.tickPadding;
12902 this.config = config;
12903 this.params = params;
12904 this.helper = new AxisRendererHelper(this);
12905 }
12906 /**
12907 * Create axis element
12908 * @param {d3.selection} g Axis selection
12909 * @private
12910 */
12911 create(g) {
12912 const ctx = this;
12913 const { config, helper, params } = ctx;
12914 const { scale } = helper;
12915 const { orient } = config;
12916 const splitTickText = this.splitTickText.bind(ctx);
12917 const isLeftRight = /^(left|right)$/.test(orient);
12918 const isTopBottom = /^(top|bottom)$/.test(orient);
12919 const tickTransform = helper.getTickTransformSetter(isTopBottom ? "x" : "y");
12920 const axisPx = tickTransform === helper.axisX ? "y" : "x";
12921 const sign = /^(top|left)$/.test(orient) ? -1 : 1;
12922 const rotate = params.tickTextRotate;
12923 this.config.range = scale.rangeExtent ? scale.rangeExtent() : helper.scaleExtent((params.orgXScale || scale).range());
12924 const { innerTickSize, tickLength, range } = config;
12925 const id = params.id;
12926 const tickTextPos = id && /^(x|y|y2)$/.test(id) ? params.config[`axis_${id}_tick_text_position`] : { x: 0, y: 0 };
12927 const prefix = id === "subX" ? `subchart_axis_x` : `axis_${id}`;
12928 const axisShow = params.config[`${prefix}_show`];
12929 const tickShow = {
12930 tick: axisShow ? params.config[`${prefix}_tick_show`] : false,
12931 text: axisShow ? params.config[`${prefix}_tick_text_show`] : false
12932 };
12933 const evalTextSize = params.config.axis_evalTextSize;
12934 let $g;
12935 g.each(function() {
12936 const g2 = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
12937 let scale0 = this.__chart__ || scale;
12938 let scale1 = helper.copyScale();
12939 $g = g2;
12940 this.__chart__ = scale1;
12941 config.tickOffset = params.isCategory ? (scale1(1) - scale1(0)) / 2 : 0;
12942 const path = g2.selectAll(".domain").data([0]);
12943 path.enter().append("path").attr("class", "domain").merge(path).attr("d", () => {
12944 const outerTickSized = config.outerTickSize * sign;
12945 return isTopBottom ? `M${range[0]},${outerTickSized}V0H${range[1]}V${outerTickSized}` : `M${outerTickSized},${range[0]}H0V${range[1]}H${outerTickSized}`;
12946 });
12947 if (tickShow.tick || tickShow.text) {
12948 const ticks = config.tickValues || helper.generateTicks(scale1, isLeftRight);
12949 ctx.generatedTicks = ticks;
12950 let tick = g2.selectAll(".tick").data(ticks, scale1);
12951 const tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick");
12952 const tickExit = tick.exit().remove();
12953 tick = tickEnter.merge(tick);
12954 tickShow.tick && tickEnter.append("line");
12955 tickShow.text && tickEnter.append("text");
12956 const tickText = tick.select("text");
12957 const sizeFor1Char = isFunction(evalTextSize) ? evalTextSize.bind(ctx.params.owner.api)(tickText.node()) : AxisRendererHelper.getSizeFor1Char(tickText, evalTextSize);
12958 const counts = [];
12959 let tspan = tickText.selectAll("tspan").data((d, index) => {
12960 const split = params.tickMultiline ? splitTickText(d, scale1, ticks, isLeftRight, sizeFor1Char.w) : isArray(helper.textFormatted(d)) ? helper.textFormatted(d).concat() : [helper.textFormatted(d)];
12961 counts[index] = split.length;
12962 return split.map((splitted) => ({ index, splitted }));
12963 });
12964 tspan.exit().remove();
12965 tspan = tspan.enter().append("tspan").merge(tspan).text((d) => d.splitted);
12966 tspan.attr("x", isTopBottom ? 0 : tickLength * sign).attr("dx", (() => {
12967 let dx = 0;
12968 if (/(top|bottom)/.test(orient) && rotate) {
12969 dx = 8 * Math.sin(Math.PI * (rotate / 180)) * (orient === "top" ? -1 : 1);
12970 }
12971 return dx + (tickTextPos.x || 0);
12972 })()).attr("dy", (d, i) => {
12973 const defValue = ".71em";
12974 let dy = 0;
12975 if (orient !== "top") {
12976 dy = sizeFor1Char.h;
12977 if (i === 0) {
12978 dy = isLeftRight ? -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3) : tickTextPos.y === 0 ? defValue : 0;
12979 }
12980 }
12981 return isNumber(dy) && tickTextPos.y ? dy + tickTextPos.y : dy || defValue;
12982 });
12983 const lineUpdate = tick.select("line");
12984 const textUpdate = tick.select("text");
12985 tickEnter.select("line").attr(`${axisPx}2`, innerTickSize * sign);
12986 tickEnter.select("text").attr(axisPx, tickLength * sign);
12987 ctx.setTickLineTextPosition(lineUpdate, textUpdate);
12988 if (params.tickTitle) {
12989 const title = textUpdate.select("title");
12990 (title.empty() ? textUpdate.append("title") : title).text((index) => params.tickTitle[index]);
12991 }
12992 if (scale1.bandwidth) {
12993 const x = scale1;
12994 const dx = x.bandwidth() / 2;
12995 scale0 = (d) => x(d) + dx;
12996 scale1 = scale0;
12997 } else if (scale0.bandwidth) {
12998 scale0 = scale1;
12999 } else {
13000 tickTransform(tickExit, scale1);
13001 }
13002 tick = params.owner.state.flowing ? helper.transitionise(tick) : params.owner.$T(tick);
13003 tickTransform(tickEnter, scale0);
13004 tickTransform(tick.style("opacity", null), scale1);
13005 }
13006 });
13007 this.g = $g;
13008 }
13009 /**
13010 * Get generated ticks
13011 * @param {number} count Count of ticks
13012 * @returns {Array} Generated ticks
13013 * @private
13014 */
13015 getGeneratedTicks(count) {
13016 var _a;
13017 const len = ((_a = this.generatedTicks) == null ? void 0 : _a.length) - 1;
13018 let res = this.generatedTicks;
13019 if (len > count) {
13020 const interval = Math.round(len / count + 0.1);
13021 res = this.generatedTicks.map((v, i) => i % interval === 0 ? v : null).filter((v) => v !== null).splice(0, count);
13022 }
13023 return res;
13024 }
13025 /**
13026 * Get tick x/y coordinate
13027 * @returns {{x: number, y: number}}
13028 * @private
13029 */
13030 getTickXY() {
13031 const { config } = this;
13032 const pos = { x: 0, y: 0 };
13033 if (this.params.isCategory) {
13034 pos.x = config.tickCentered ? 0 : config.tickOffset;
13035 pos.y = config.tickCentered ? config.tickOffset : 0;
13036 }
13037 return pos;
13038 }
13039 /**
13040 * Get tick size
13041 * @param {object} d data object
13042 * @returns {number}
13043 * @private
13044 */
13045 getTickSize(d) {
13046 const { scale } = this.helper;
13047 const { config } = this;
13048 const { innerTickSize, range } = config;
13049 const tickPosition = scale(d) + (config.tickCentered ? 0 : config.tickOffset);
13050 return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;
13051 }
13052 /**
13053 * Set tick's line & text position
13054 * @param {d3.selection} lineUpdate Line selection
13055 * @param {d3.selection} textUpdate Text selection
13056 * @private
13057 */
13058 setTickLineTextPosition(lineUpdate, textUpdate) {
13059 const tickPos = this.getTickXY();
13060 const { innerTickSize, orient, tickLength, tickOffset } = this.config;
13061 const rotate = this.params.tickTextRotate;
13062 const textAnchorForText = (r) => {
13063 const value = ["start", "end"];
13064 orient === "top" && value.reverse();
13065 return !r ? "middle" : value[r > 0 ? 0 : 1];
13066 };
13067 const textTransform = (r) => r ? `rotate(${r})` : null;
13068 const yForText = (r) => {
13069 const r2 = r / (orient === "bottom" ? 15 : 23);
13070 return r ? 11.5 - 2.5 * r2 * (r > 0 ? 1 : -1) : tickLength;
13071 };
13072 const {
13073 config: {
13074 axis_rotated: isRotated,
13075 axis_x_tick_text_inner: inner
13076 }
13077 } = this.params.owner;
13078 switch (orient) {
13079 case "bottom":
13080 lineUpdate.attr("x1", tickPos.x).attr("x2", tickPos.x).attr("y2", this.getTickSize.bind(this));
13081 textUpdate.attr("x", 0).attr("y", yForText(rotate)).style("text-anchor", textAnchorForText(rotate)).style("text-anchor", (d, i, { length }) => {
13082 if (!isRotated && i === 0 && (inner === true || inner.first)) {
13083 return "start";
13084 } else if (!isRotated && i === length - 1 && (inner === true || inner.last)) {
13085 return "end";
13086 }
13087 return textAnchorForText(rotate);
13088 }).attr("transform", textTransform(rotate));
13089 break;
13090 case "top":
13091 lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
13092 textUpdate.attr("x", 0).attr("y", -yForText(rotate) * 2).style("text-anchor", textAnchorForText(rotate)).attr("transform", textTransform(rotate));
13093 break;
13094 case "left":
13095 lineUpdate.attr("x2", -innerTickSize).attr("y1", tickPos.y).attr("y2", tickPos.y);
13096 textUpdate.attr("x", -tickLength).attr("y", tickOffset).style("text-anchor", "end");
13097 break;
13098 case "right":
13099 lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
13100 textUpdate.attr("x", tickLength).attr("y", 0).style("text-anchor", "start");
13101 }
13102 }
13103 // this should be called only when category axis
13104 splitTickText(d, scale, ticks, isLeftRight, charWidth) {
13105 const { params } = this;
13106 const tickText = this.helper.textFormatted(d);
13107 const splitted = isString(tickText) && tickText.indexOf("\n") > -1 ? tickText.split("\n") : [];
13108 if (splitted.length) {
13109 return splitted;
13110 }
13111 if (isArray(tickText)) {
13112 return tickText;
13113 }
13114 let tickWidth = params.tickWidth;
13115 if (!tickWidth || tickWidth <= 0) {
13116 tickWidth = isLeftRight ? 95 : params.isCategory ? (params.isInverted ? scale(ticks[0]) - scale(ticks[1]) : scale(ticks[1]) - scale(ticks[0])) - 12 : 110;
13117 }
13118 function split(splitted2, text) {
13119 let subtext;
13120 let spaceIndex;
13121 let textWidth;
13122 for (let i = 1; i < text.length; i++) {
13123 if (text.charAt(i) === " ") {
13124 spaceIndex = i;
13125 }
13126 subtext = text.substr(0, i + 1);
13127 textWidth = charWidth * subtext.length;
13128 if (tickWidth < textWidth) {
13129 return split(
13130 splitted2.concat(text.substr(0, spaceIndex || i)),
13131 text.slice(spaceIndex ? spaceIndex + 1 : i)
13132 );
13133 }
13134 }
13135 return splitted2.concat(text);
13136 }
13137 return split(splitted, String(tickText));
13138 }
13139 scale(x) {
13140 if (!arguments.length) {
13141 return this.helper.scale;
13142 }
13143 this.helper.scale = x;
13144 return this;
13145 }
13146 orient(x) {
13147 if (!arguments.length) {
13148 return this.config.orient;
13149 }
13150 this.config.orient = x in {
13151 top: 1,
13152 right: 1,
13153 bottom: 1,
13154 left: 1
13155 } ? String(x) : "bottom";
13156 return this;
13157 }
13158 tickFormat(format) {
13159 const { config } = this;
13160 if (!arguments.length) {
13161 return config.tickFormat;
13162 }
13163 config.tickFormat = format;
13164 return this;
13165 }
13166 tickCentered(isCentered) {
13167 const { config } = this;
13168 if (!arguments.length) {
13169 return config.tickCentered;
13170 }
13171 config.tickCentered = isCentered;
13172 return this;
13173 }
13174 /**
13175 * Return tick's offset value.
13176 * The value will be set for 'category' axis type.
13177 * @returns {number}
13178 * @private
13179 */
13180 tickOffset() {
13181 return this.config.tickOffset;
13182 }
13183 /**
13184 * Get tick interval count
13185 * @private
13186 * @param {number} size Total data size
13187 * @returns {number}
13188 */
13189 tickInterval(size) {
13190 var _a;
13191 const { outerTickSize, tickOffset, tickValues } = this.config;
13192 let interval;
13193 if (this.params.isCategory) {
13194 interval = tickOffset * 2;
13195 } else {
13196 const scale = (_a = this.params.owner.scale.zoom) != null ? _a : this.helper.scale;
13197 const length = this.g.select("path.domain").node().getTotalLength() - outerTickSize * 2;
13198 interval = length / (size || this.g.selectAll("line").size());
13199 const intervalByValue = tickValues ? tickValues.map((v, i, arr) => {
13200 const next = i + 1;
13201 return next < arr.length ? scale(arr[next]) - scale(v) : null;
13202 }).filter(Boolean) : [];
13203 interval = Math.min(...intervalByValue, interval);
13204 }
13205 return interval === Infinity ? 0 : interval;
13206 }
13207 ticks(...args) {
13208 const { config } = this;
13209 if (!args.length) {
13210 return config.tickArguments;
13211 }
13212 config.tickArguments = toArray(args);
13213 return this;
13214 }
13215 tickCulling(culling) {
13216 const { config } = this;
13217 if (!arguments.length) {
13218 return config.tickCulling;
13219 }
13220 config.tickCulling = culling;
13221 return this;
13222 }
13223 tickValues(x) {
13224 const { config } = this;
13225 if (isFunction(x)) {
13226 config.tickValues = () => x(this.helper.scale.domain());
13227 } else {
13228 if (!arguments.length) {
13229 return config.tickValues;
13230 }
13231 config.tickValues = x;
13232 }
13233 return this;
13234 }
13235 setTransition(t) {
13236 this.config.transition = t;
13237 return this;
13238 }
13239}
13240
13241;// ./src/ChartInternal/Axis/Axis.ts
13242var Axis_defProp = Object.defineProperty;
13243var Axis_defNormalProp = (obj, key, value) => key in obj ? Axis_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13244var Axis_publicField = (obj, key, value) => Axis_defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13245
13246
13247
13248
13249
13250/* harmony default export */ var Axis = ({
13251 getAxisInstance: function() {
13252 return this.axis || new Axis_Axis(this);
13253 }
13254});
13255class Axis_Axis {
13256 constructor(owner) {
13257 Axis_publicField(this, "owner");
13258 Axis_publicField(this, "x");
13259 Axis_publicField(this, "subX");
13260 Axis_publicField(this, "y");
13261 Axis_publicField(this, "y2");
13262 Axis_publicField(this, "axesList", {});
13263 Axis_publicField(this, "tick", {
13264 x: null,
13265 y: null,
13266 y2: null
13267 });
13268 Axis_publicField(this, "xs", []);
13269 Axis_publicField(this, "orient", {
13270 x: "bottom",
13271 y: "left",
13272 y2: "right",
13273 subX: "bottom"
13274 });
13275 this.owner = owner;
13276 this.setOrient();
13277 }
13278 getAxisClassName(id) {
13279 return `${$AXIS.axis} ${$AXIS[`axis${capitalize(id)}`]}`;
13280 }
13281 isHorizontal($$, forHorizontal) {
13282 const isRotated = $$.config.axis_rotated;
13283 return forHorizontal ? isRotated : !isRotated;
13284 }
13285 isCategorized() {
13286 const { config, state } = this.owner;
13287 return config.axis_x_type.indexOf("category") >= 0 || state.hasRadar;
13288 }
13289 isCustomX() {
13290 const { config } = this.owner;
13291 return !this.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
13292 }
13293 isTimeSeries(id = "x") {
13294 return this.owner.config[`axis_${id}_type`] === "timeseries";
13295 }
13296 isLog(id = "x") {
13297 return this.owner.config[`axis_${id}_type`] === "log";
13298 }
13299 isTimeSeriesY() {
13300 return this.isTimeSeries("y");
13301 }
13302 getAxisType(id = "x") {
13303 let type = "linear";
13304 if (this.isTimeSeries(id)) {
13305 type = this.owner.config.axis_x_localtime ? "time" : "utc";
13306 } else if (this.isLog(id)) {
13307 type = "log";
13308 }
13309 return type;
13310 }
13311 /**
13312 * Get extent value
13313 * @returns {Array} default extent
13314 * @private
13315 */
13316 getExtent() {
13317 const $$ = this.owner;
13318 const { config, scale } = $$;
13319 let extent = config.axis_x_extent;
13320 if (extent) {
13321 if (isFunction(extent)) {
13322 extent = extent.bind($$.api)($$.getXDomain($$.data.targets), scale.subX);
13323 } else if (this.isTimeSeries() && extent.every(isNaN)) {
13324 const fn = parseDate.bind($$);
13325 extent = extent.map((v) => scale.subX(fn(v)));
13326 }
13327 }
13328 return extent;
13329 }
13330 init() {
13331 const $$ = this.owner;
13332 const { config, $el: { main, axis }, state: { clip } } = $$;
13333 const isRotated = config.axis_rotated;
13334 const target = ["x", "y"];
13335 config.axis_y2_show && target.push("y2");
13336 target.forEach((v) => {
13337 const classAxis = this.getAxisClassName(v);
13338 const classLabel = $AXIS[`axis${v.toUpperCase()}Label`];
13339 axis[v] = main.append("g").attr("class", classAxis).attr("clip-path", () => {
13340 let res = null;
13341 if (v === "x") {
13342 res = clip.pathXAxis;
13343 } else if (v === "y") {
13344 res = clip.pathYAxis;
13345 }
13346 return res;
13347 }).attr("transform", $$.getTranslate(v)).style("visibility", config[`axis_${v}_show`] ? null : "hidden");
13348 axis[v].append("text").attr("class", classLabel).attr("transform", ["rotate(-90)", null][v === "x" ? +!isRotated : +isRotated]).style("text-anchor", () => this.textAnchorForAxisLabel(v));
13349 this.generateAxes(v);
13350 });
13351 config.axis_tooltip && this.setAxisTooltip();
13352 }
13353 /**
13354 * Set axis orient according option value
13355 * @private
13356 */
13357 setOrient() {
13358 const $$ = this.owner;
13359 const {
13360 axis_rotated: isRotated,
13361 axis_y_inner: yInner,
13362 axis_y2_inner: y2Inner
13363 } = $$.config;
13364 this.orient = {
13365 x: isRotated ? "left" : "bottom",
13366 y: isRotated ? yInner ? "top" : "bottom" : yInner ? "right" : "left",
13367 y2: isRotated ? y2Inner ? "bottom" : "top" : y2Inner ? "left" : "right",
13368 subX: isRotated ? "left" : "bottom"
13369 };
13370 }
13371 /**
13372 * Generate axes
13373 * It's used when axis' axes option is set
13374 * @param {string} id Axis id
13375 * @private
13376 */
13377 generateAxes(id) {
13378 const $$ = this.owner;
13379 const { config } = $$;
13380 const axes = [];
13381 const axesConfig = config[`axis_${id}_axes`];
13382 const isRotated = config.axis_rotated;
13383 let d3Axis;
13384 if (id === "x") {
13385 d3Axis = isRotated ? external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_.axisLeft : external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_.axisBottom;
13386 } else if (id === "y") {
13387 d3Axis = isRotated ? external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_.axisBottom : external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_.axisLeft;
13388 } else if (id === "y2") {
13389 d3Axis = isRotated ? external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_.axisTop : external_commonjs_d3_axis_commonjs2_d3_axis_amd_d3_axis_root_d3_.axisRight;
13390 }
13391 if (axesConfig.length) {
13392 axesConfig.forEach((v) => {
13393 const tick = v.tick || {};
13394 const scale = $$.scale[id].copy();
13395 v.domain && scale.domain(v.domain);
13396 axes.push(
13397 d3Axis(scale).ticks(tick.count).tickFormat(
13398 isFunction(tick.format) ? tick.format.bind($$.api) : (x) => x
13399 ).tickValues(tick.values).tickSizeOuter(tick.outer === false ? 0 : 6)
13400 );
13401 });
13402 }
13403 this.axesList[id] = axes;
13404 }
13405 /**
13406 * Update axes nodes
13407 * @private
13408 */
13409 updateAxes() {
13410 const $$ = this.owner;
13411 const { config, $el: { main }, $T } = $$;
13412 Object.keys(this.axesList).forEach((id) => {
13413 const axesConfig = config[`axis_${id}_axes`];
13414 const scale = $$.scale[id].copy();
13415 const range = scale.range();
13416 this.axesList[id].forEach((v, i) => {
13417 const axisRange = v.scale().range();
13418 if (!range.every((v2, i2) => v2 === axisRange[i2])) {
13419 v.scale().range(range);
13420 }
13421 const className = `${this.getAxisClassName(id)}-${i + 1}`;
13422 let g = main.select(`.${className.replace(/\s/, ".")}`);
13423 if (g.empty()) {
13424 g = main.append("g").attr("class", className).style("visibility", config[`axis_${id}_show`] ? null : "hidden").call(v);
13425 } else {
13426 axesConfig[i].domain && scale.domain(axesConfig[i].domain);
13427 $T(g).call(v.scale(scale));
13428 }
13429 g.attr("transform", $$.getTranslate(id, i + 1));
13430 });
13431 });
13432 }
13433 /**
13434 * Set Axis & tick values
13435 * called from: updateScales()
13436 * @param {string} id Axis id string
13437 * @param {d3Scale} scale Scale
13438 * @param {boolean} outerTick If show outer tick
13439 * @param {boolean} noTransition If with no transition
13440 * @private
13441 */
13442 setAxis(id, scale, outerTick, noTransition) {
13443 const $$ = this.owner;
13444 if (id !== "subX") {
13445 this.tick[id] = this.getTickValues(id);
13446 }
13447 this[id] = this.getAxis(
13448 id,
13449 scale,
13450 outerTick,
13451 // do not transit x Axis on zoom and resizing
13452 // https://github.com/naver/billboard.js/issues/1949
13453 id === "x" && ($$.scale.zoom || $$.config.subchart_show || $$.state.resizing) ? true : noTransition
13454 );
13455 }
13456 // called from : getMaxTickSize()
13457 getAxis(id, scale, outerTick, noTransition, noTickTextRotate) {
13458 const $$ = this.owner;
13459 const { config } = $$;
13460 const isX = /^(x|subX)$/.test(id);
13461 const type = isX ? "x" : id;
13462 const isCategory = isX && this.isCategorized();
13463 const orient = this.orient[id];
13464 const tickTextRotate = noTickTextRotate ? 0 : $$.getAxisTickRotate(type);
13465 let tickFormat;
13466 if (isX) {
13467 tickFormat = id === "subX" ? $$.format.subXAxisTick : $$.format.xAxisTick;
13468 } else {
13469 const fn = config[`axis_${id}_tick_format`];
13470 if (isFunction(fn)) {
13471 tickFormat = fn.bind($$.api);
13472 }
13473 }
13474 let tickValues = this.tick[type];
13475 const axisParams = mergeObj({
13476 outerTick,
13477 noTransition,
13478 config,
13479 id,
13480 tickTextRotate,
13481 owner: $$
13482 }, isX && {
13483 isCategory,
13484 isInverted: config.axis_x_inverted,
13485 tickMultiline: config.axis_x_tick_multiline,
13486 tickWidth: config.axis_x_tick_width,
13487 tickTitle: isCategory && config.axis_x_tick_tooltip && $$.api.categories(),
13488 orgXScale: $$.scale.x
13489 });
13490 if (!isX) {
13491 axisParams.tickStepSize = config[`axis_${type}_tick_stepSize`];
13492 }
13493 const axis = new AxisRenderer(axisParams).scale(isX && $$.scale.zoom || scale).orient(orient);
13494 if (isX && this.isTimeSeries() && tickValues && !isFunction(tickValues)) {
13495 const fn = parseDate.bind($$);
13496 tickValues = tickValues.map((v) => fn(v));
13497 } else if (!isX && this.isTimeSeriesY()) {
13498 axis.ticks(config.axis_y_tick_time_value);
13499 tickValues = null;
13500 }
13501 tickValues && axis.tickValues(tickValues);
13502 axis.tickFormat(
13503 tickFormat || !isX && ($$.isStackNormalized() && ((x) => `${x}%`))
13504 );
13505 if (isCategory) {
13506 axis.tickCentered(config.axis_x_tick_centered);
13507 if (isEmpty(config.axis_x_tick_culling)) {
13508 config.axis_x_tick_culling = false;
13509 }
13510 }
13511 const tickCount = config[`axis_${type}_tick_count`];
13512 tickCount && axis.ticks(tickCount);
13513 return axis;
13514 }
13515 updateXAxisTickValues(targets, axis) {
13516 var _a;
13517 const $$ = this.owner;
13518 const { config } = $$;
13519 const fit = config.axis_x_tick_fit;
13520 let count = config.axis_x_tick_count;
13521 let values;
13522 if (fit || count && fit) {
13523 values = $$.mapTargetsToUniqueXs(targets);
13524 if (this.isCategorized() && count > values.length) {
13525 count = values.length;
13526 }
13527 values = this.generateTickValues(
13528 values,
13529 count,
13530 this.isTimeSeries()
13531 );
13532 }
13533 if (axis) {
13534 axis.tickValues(values);
13535 } else if (this.x) {
13536 this.x.tickValues(values);
13537 (_a = this.subX) == null ? void 0 : _a.tickValues(values);
13538 }
13539 return values;
13540 }
13541 getId(id) {
13542 const { config, scale } = this.owner;
13543 let axis = config.data_axes[id];
13544 if (!axis || !scale[axis]) {
13545 axis = "y";
13546 }
13547 return axis;
13548 }
13549 getXAxisTickFormat(forSubchart) {
13550 const $$ = this.owner;
13551 const { config, format } = $$;
13552 const tickFormat = forSubchart ? config.subchart_axis_x_tick_format || config.axis_x_tick_format : config.axis_x_tick_format;
13553 const isTimeSeries = this.isTimeSeries();
13554 const isCategorized = this.isCategorized();
13555 let currFormat;
13556 if (tickFormat) {
13557 if (isFunction(tickFormat)) {
13558 currFormat = tickFormat.bind($$.api);
13559 } else if (isTimeSeries) {
13560 currFormat = (date) => date ? format.axisTime(tickFormat)(date) : "";
13561 }
13562 } else {
13563 currFormat = isTimeSeries ? format.defaultAxisTime : isCategorized ? $$.categoryName : (v) => v < 0 ? v.toFixed(0) : v;
13564 }
13565 return isFunction(currFormat) ? (v) => currFormat.apply($$, isCategorized ? [v, $$.categoryName(v)] : [v]) : currFormat;
13566 }
13567 getTickValues(id) {
13568 const $$ = this.owner;
13569 const tickValues = $$.config[`axis_${id}_tick_values`];
13570 const axis = $$[`${id}Axis`];
13571 return (isFunction(tickValues) ? tickValues.call($$.api) : tickValues) || (axis ? axis.tickValues() : void 0);
13572 }
13573 getLabelOptionByAxisId(id) {
13574 return this.owner.config[`axis_${id}_label`];
13575 }
13576 getLabelText(id) {
13577 const option = this.getLabelOptionByAxisId(id);
13578 return isString(option) ? option : option ? option.text : null;
13579 }
13580 setLabelText(id, text) {
13581 const $$ = this.owner;
13582 const { config } = $$;
13583 const option = this.getLabelOptionByAxisId(id);
13584 if (isString(option)) {
13585 config[`axis_${id}_label`] = text;
13586 } else if (option) {
13587 option.text = text;
13588 }
13589 }
13590 getLabelPosition(id, defaultPosition) {
13591 const isRotated = this.owner.config.axis_rotated;
13592 const option = this.getLabelOptionByAxisId(id);
13593 const position = isObjectType(option) && option.position ? option.position : defaultPosition[+!isRotated];
13594 const has = (v) => !!~position.indexOf(v);
13595 return {
13596 isInner: has("inner"),
13597 isOuter: has("outer"),
13598 isLeft: has("left"),
13599 isCenter: has("center"),
13600 isRight: has("right"),
13601 isTop: has("top"),
13602 isMiddle: has("middle"),
13603 isBottom: has("bottom")
13604 };
13605 }
13606 getAxisLabelPosition(id) {
13607 return this.getLabelPosition(
13608 id,
13609 id === "x" ? ["inner-top", "inner-right"] : ["inner-right", "inner-top"]
13610 );
13611 }
13612 getLabelPositionById(id) {
13613 return this.getAxisLabelPosition(id);
13614 }
13615 xForAxisLabel(id) {
13616 const $$ = this.owner;
13617 const { state: { width, height } } = $$;
13618 const position = this.getAxisLabelPosition(id);
13619 let x = position.isMiddle ? -height / 2 : 0;
13620 if (this.isHorizontal($$, id !== "x")) {
13621 x = position.isLeft ? 0 : position.isCenter ? width / 2 : width;
13622 } else if (position.isBottom) {
13623 x = -height;
13624 }
13625 return x;
13626 }
13627 dxForAxisLabel(id) {
13628 const $$ = this.owner;
13629 const position = this.getAxisLabelPosition(id);
13630 let dx = position.isBottom ? "0.5em" : "0";
13631 if (this.isHorizontal($$, id !== "x")) {
13632 dx = position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
13633 } else if (position.isTop) {
13634 dx = "-0.5em";
13635 }
13636 return dx;
13637 }
13638 textAnchorForAxisLabel(id) {
13639 const $$ = this.owner;
13640 const position = this.getAxisLabelPosition(id);
13641 let anchor = position.isMiddle ? "middle" : "end";
13642 if (this.isHorizontal($$, id !== "x")) {
13643 anchor = position.isLeft ? "start" : position.isCenter ? "middle" : "end";
13644 } else if (position.isBottom) {
13645 anchor = "start";
13646 }
13647 return anchor;
13648 }
13649 dyForAxisLabel(id) {
13650 const $$ = this.owner;
13651 const { config } = $$;
13652 const isRotated = config.axis_rotated;
13653 const isInner = this.getAxisLabelPosition(id).isInner;
13654 const tickRotate = config[`axis_${id}_tick_rotate`] ? $$.getHorizontalAxisHeight(id) : 0;
13655 const { width: maxTickWidth } = this.getMaxTickSize(id);
13656 let dy;
13657 if (id === "x") {
13658 const xHeight = config.axis_x_height;
13659 if (isRotated) {
13660 dy = isInner ? "1.2em" : -25 - maxTickWidth;
13661 } else if (isInner) {
13662 dy = "-0.5em";
13663 } else if (xHeight) {
13664 dy = xHeight - 10;
13665 } else if (tickRotate) {
13666 dy = tickRotate - 10;
13667 } else {
13668 dy = "3em";
13669 }
13670 } else {
13671 dy = {
13672 y: ["-0.5em", 10, "3em", "1.2em", 10],
13673 y2: ["1.2em", -20, "-2.2em", "-0.5em", 15]
13674 }[id];
13675 if (isRotated) {
13676 if (isInner) {
13677 dy = dy[0];
13678 } else if (tickRotate) {
13679 dy = tickRotate * (id === "y2" ? -1 : 1) - dy[1];
13680 } else {
13681 dy = dy[2];
13682 }
13683 } else {
13684 dy = isInner ? dy[3] : (dy[4] + (config[`axis_${id}_inner`] ? 0 : maxTickWidth + dy[4])) * (id === "y" ? -1 : 1);
13685 }
13686 }
13687 return dy;
13688 }
13689 /**
13690 * Get max tick size
13691 * @param {string} id axis id string
13692 * @param {boolean} withoutRecompute wheather or not to recompute
13693 * @returns {object} {width, height}
13694 * @private
13695 */
13696 getMaxTickSize(id, withoutRecompute) {
13697 const $$ = this.owner;
13698 const { config, state: { current }, $el: { svg, chart } } = $$;
13699 const currentTickMax = current.maxTickSize[id];
13700 const configPrefix = `axis_${id}`;
13701 const max = {
13702 width: 0,
13703 height: 0
13704 };
13705 if (withoutRecompute || !config[`${configPrefix}_show`] || currentTickMax.width > 0 && $$.filterTargetsToShow().length === 0) {
13706 return currentTickMax;
13707 }
13708 if (svg) {
13709 const isYAxis = /^y2?$/.test(id);
13710 const targetsToShow = $$.filterTargetsToShow($$.data.targets);
13711 const scale = $$.scale[id].copy().domain(
13712 $$[`get${isYAxis ? "Y" : "X"}Domain`](targetsToShow, id)
13713 );
13714 const domain = scale.domain();
13715 const isDomainSame = domain[0] === domain[1] && domain.every((v) => v > 0);
13716 const isCurrentMaxTickDomainSame = isArray(currentTickMax.domain) && currentTickMax.domain[0] === currentTickMax.domain[1] && currentTickMax.domain.every((v) => v > 0);
13717 if (isDomainSame || isCurrentMaxTickDomainSame) {
13718 return currentTickMax.size;
13719 } else {
13720 currentTickMax.domain = domain;
13721 }
13722 if (!isYAxis) {
13723 currentTickMax.ticks.splice(0);
13724 }
13725 const axis = this.getAxis(id, scale, false, false, true);
13726 const tickRotate = config[`${configPrefix}_tick_rotate`];
13727 const tickCount = config[`${configPrefix}_tick_count`];
13728 const tickValues = config[`${configPrefix}_tick_values`];
13729 if (!tickValues && tickCount) {
13730 axis.tickValues(
13731 this.generateTickValues(
13732 domain,
13733 tickCount,
13734 isYAxis ? this.isTimeSeriesY() : this.isTimeSeries()
13735 )
13736 );
13737 }
13738 !isYAxis && this.updateXAxisTickValues(targetsToShow, axis);
13739 const dummy = chart.append("svg").style("visibility", "hidden").style("position", "fixed").style("top", "0").style("left", "0");
13740 axis.create(dummy);
13741 dummy.selectAll("text").attr("transform", isNumber(tickRotate) ? `rotate(${tickRotate})` : null).each(function(d, i) {
13742 const { width, height } = this.getBoundingClientRect();
13743 max.width = Math.max(max.width, width);
13744 max.height = Math.max(max.height, height);
13745 if (!isYAxis) {
13746 currentTickMax.ticks[i] = width;
13747 }
13748 });
13749 dummy.remove();
13750 }
13751 Object.keys(max).forEach((key) => {
13752 if (max[key] > 0) {
13753 currentTickMax[key] = max[key];
13754 }
13755 });
13756 return currentTickMax;
13757 }
13758 getXAxisTickTextY2Overflow(defaultPadding) {
13759 const $$ = this.owner;
13760 const { axis, config, state: { current, isLegendRight, legendItemWidth } } = $$;
13761 const xAxisTickRotate = $$.getAxisTickRotate("x");
13762 const positiveRotation = xAxisTickRotate > 0 && xAxisTickRotate < 90;
13763 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) {
13764 const y2AxisWidth = config.axis_y2_show && current.maxTickSize.y2.width || 0;
13765 const legendWidth = isLegendRight && legendItemWidth || 0;
13766 const widthWithoutCurrentPaddingLeft = current.width - $$.getCurrentPaddingByDirection("left");
13767 const maxOverflow = this.getXAxisTickMaxOverflow(
13768 xAxisTickRotate,
13769 widthWithoutCurrentPaddingLeft - defaultPadding
13770 ) - y2AxisWidth - legendWidth;
13771 const xAxisTickTextY2Overflow = Math.max(0, maxOverflow) + defaultPadding;
13772 return Math.min(xAxisTickTextY2Overflow, widthWithoutCurrentPaddingLeft / 2);
13773 }
13774 return 0;
13775 }
13776 getXAxisTickMaxOverflow(xAxisTickRotate, widthWithoutCurrentPaddingLeft) {
13777 const $$ = this.owner;
13778 const { axis, config, state } = $$;
13779 const isTimeSeries = axis.isTimeSeries();
13780 const tickTextWidths = state.current.maxTickSize.x.ticks;
13781 const tickCount = tickTextWidths.length;
13782 const { left, right } = state.axis.x.padding;
13783 let maxOverflow = 0;
13784 const remaining = tickCount - (isTimeSeries && config.axis_x_tick_fit ? 0.5 : 0);
13785 for (let i = 0; i < tickCount; i++) {
13786 const tickIndex = i + 1;
13787 const rotatedTickTextWidth = Math.cos(Math.PI * xAxisTickRotate / 180) * tickTextWidths[i];
13788 const ticksBeforeTickText = tickIndex - (isTimeSeries ? 1 : 0.5) + left;
13789 if (ticksBeforeTickText <= 0) {
13790 continue;
13791 }
13792 const xAxisLengthWithoutTickTextWidth = widthWithoutCurrentPaddingLeft - rotatedTickTextWidth;
13793 const tickLength = xAxisLengthWithoutTickTextWidth / ticksBeforeTickText;
13794 const remainingTicks = remaining - tickIndex;
13795 const paddingRightLength = right * tickLength;
13796 const remainingTickWidth = remainingTicks * tickLength + paddingRightLength;
13797 const overflow = rotatedTickTextWidth - tickLength / 2 - remainingTickWidth;
13798 maxOverflow = Math.max(maxOverflow, overflow);
13799 }
13800 const filteredTargets = $$.filterTargetsToShow($$.data.targets);
13801 let tickOffset = 0;
13802 if (!isTimeSeries && config.axis_x_tick_count <= filteredTargets.length && filteredTargets[0].values.length) {
13803 const scale = getScale(
13804 $$.axis.getAxisType("x"),
13805 0,
13806 widthWithoutCurrentPaddingLeft - maxOverflow
13807 ).domain([
13808 left * -1,
13809 $$.getXDomainMax($$.data.targets) + 1 + right
13810 ]);
13811 tickOffset = (scale(1) - scale(0)) / 2;
13812 }
13813 return maxOverflow + tickOffset;
13814 }
13815 updateLabels(withTransition) {
13816 const $$ = this.owner;
13817 const { $el: { main }, $T } = $$;
13818 const labels = {
13819 x: main.select(`.${$AXIS.axisX} .${$AXIS.axisXLabel}`),
13820 y: main.select(`.${$AXIS.axisY} .${$AXIS.axisYLabel}`),
13821 y2: main.select(`.${$AXIS.axisY2} .${$AXIS.axisY2Label}`)
13822 };
13823 Object.keys(labels).filter((id) => !labels[id].empty()).forEach((v) => {
13824 const node = labels[v];
13825 $T(node, withTransition).attr("x", () => this.xForAxisLabel(v)).attr("dx", () => this.dxForAxisLabel(v)).attr("dy", () => this.dyForAxisLabel(v)).text(() => this.getLabelText(v));
13826 });
13827 }
13828 /**
13829 * Get axis padding value
13830 * @param {number|object} padding Padding object
13831 * @param {string} key Key string of padding
13832 * @param {Date|number} defaultValue Default value
13833 * @param {number} domainLength Domain length
13834 * @returns {number} Padding value in scale
13835 * @private
13836 */
13837 getPadding(padding, key, defaultValue, domainLength) {
13838 const p = isNumber(padding) ? padding : padding[key];
13839 if (!isValue(p)) {
13840 return defaultValue;
13841 }
13842 return this.owner.convertPixelToScale(
13843 /(bottom|top)/.test(key) ? "y" : "x",
13844 p,
13845 domainLength
13846 );
13847 }
13848 generateTickValues(values, tickCount, forTimeSeries) {
13849 let tickValues = values;
13850 if (tickCount) {
13851 const targetCount = isFunction(tickCount) ? tickCount() : tickCount;
13852 if (targetCount === 1) {
13853 tickValues = [values[0]];
13854 } else if (targetCount === 2) {
13855 tickValues = [values[0], values[values.length - 1]];
13856 } else if (targetCount > 2) {
13857 const isCategorized = this.isCategorized();
13858 const count = targetCount - 2;
13859 const start = values[0];
13860 const end = values[values.length - 1];
13861 const interval = (end - start) / (count + 1);
13862 let tickValue;
13863 tickValues = [start];
13864 for (let i = 0; i < count; i++) {
13865 tickValue = +start + interval * (i + 1);
13866 tickValues.push(
13867 forTimeSeries ? new Date(tickValue) : isCategorized ? Math.round(tickValue) : tickValue
13868 );
13869 }
13870 tickValues.push(end);
13871 }
13872 }
13873 if (!forTimeSeries) {
13874 tickValues = tickValues.sort((a, b) => a - b);
13875 }
13876 return tickValues;
13877 }
13878 generateTransitions(withTransition) {
13879 const $$ = this.owner;
13880 const { $el: { axis }, $T } = $$;
13881 const [axisX, axisY, axisY2, axisSubX] = ["x", "y", "y2", "subX"].map((v) => $T(axis[v], withTransition));
13882 return { axisX, axisY, axisY2, axisSubX };
13883 }
13884 redraw(transitions, isHidden, isInit) {
13885 const $$ = this.owner;
13886 const { config, $el } = $$;
13887 const opacity = isHidden ? "0" : null;
13888 ["x", "y", "y2", "subX"].forEach((id) => {
13889 const axis = this[id];
13890 const $axis = $el.axis[id];
13891 if (axis && $axis) {
13892 if (!isInit && !config.transition_duration) {
13893 axis.config.withoutTransition = true;
13894 }
13895 $axis.style("opacity", opacity);
13896 axis.create(transitions[`axis${capitalize(id)}`]);
13897 }
13898 });
13899 this.updateAxes();
13900 }
13901 /**
13902 * Redraw axis
13903 * @param {Array} targetsToShow targets data to be shown
13904 * @param {object} wth option object
13905 * @param {d3.Transition} transitions Transition object
13906 * @param {object} flow flow object
13907 * @param {boolean} isInit called from initialization
13908 * @private
13909 */
13910 redrawAxis(targetsToShow, wth, transitions, flow, isInit) {
13911 var _a, _b, _c;
13912 const $$ = this.owner;
13913 const { config, scale, $el } = $$;
13914 const hasZoom = !!scale.zoom;
13915 let xDomainForZoom;
13916 if (!hasZoom && this.isCategorized() && targetsToShow.length === 0) {
13917 scale.x.domain([0, $el.axis.x.selectAll(".tick").size()]);
13918 }
13919 if (scale.x && targetsToShow.length) {
13920 !hasZoom && $$.updateXDomain(
13921 targetsToShow,
13922 wth.UpdateXDomain,
13923 wth.UpdateOrgXDomain,
13924 wth.TrimXDomain
13925 );
13926 if (!config.axis_x_tick_values) {
13927 this.updateXAxisTickValues(targetsToShow);
13928 }
13929 } else if (this.x) {
13930 this.x.tickValues([]);
13931 (_a = this.subX) == null ? void 0 : _a.tickValues([]);
13932 }
13933 if (config.zoom_rescale && !flow) {
13934 xDomainForZoom = scale.x.orgDomain();
13935 }
13936 ["y", "y2"].forEach((key) => {
13937 const prefix = `axis_${key}_`;
13938 const axisScale = scale[key];
13939 if (axisScale) {
13940 const tickValues = config[`${prefix}tick_values`];
13941 const tickCount = config[`${prefix}tick_count`];
13942 axisScale.domain($$.getYDomain(targetsToShow, key, xDomainForZoom));
13943 if (!tickValues && tickCount) {
13944 const axis = $$.axis[key];
13945 const domain = axisScale.domain();
13946 axis.tickValues(
13947 this.generateTickValues(
13948 domain,
13949 domain.every((v) => v === 0) ? 1 : tickCount,
13950 this.isTimeSeriesY()
13951 )
13952 );
13953 }
13954 }
13955 });
13956 this.redraw(transitions, $$.hasArcType(), isInit);
13957 this.updateLabels(wth.Transition);
13958 if ((wth.UpdateXDomain || wth.UpdateXAxis || wth.Y) && targetsToShow.length) {
13959 this.setCulling();
13960 }
13961 if (wth.Y) {
13962 (_b = scale.subY) == null ? void 0 : _b.domain($$.getYDomain(targetsToShow, "y"));
13963 (_c = scale.subY2) == null ? void 0 : _c.domain($$.getYDomain(targetsToShow, "y2"));
13964 }
13965 }
13966 /**
13967 * Set manual culling
13968 * @private
13969 */
13970 setCulling() {
13971 const $$ = this.owner;
13972 const { config, state: { clip, current }, $el } = $$;
13973 ["subX", "x", "y", "y2"].forEach((type) => {
13974 const axis = $el.axis[type];
13975 const id = type === "subX" ? "x" : type;
13976 const cullingOptionPrefix = `axis_${id}_tick_culling`;
13977 const toCull = config[cullingOptionPrefix];
13978 if (axis && toCull) {
13979 const tickNodes = axis.selectAll(".tick");
13980 const tickValues = sortValue(tickNodes.data());
13981 const tickSize = tickValues.length;
13982 const cullingMax = config[`${cullingOptionPrefix}_max`];
13983 const lines = config[`${cullingOptionPrefix}_lines`];
13984 let intervalForCulling;
13985 if (tickSize) {
13986 for (let i = 1; i < tickSize; i++) {
13987 if (tickSize / i < cullingMax) {
13988 intervalForCulling = i;
13989 break;
13990 }
13991 }
13992 tickNodes.each(function(d) {
13993 const node = lines ? this.querySelector("text") : this;
13994 if (node) {
13995 node.style.display = tickValues.indexOf(d) % intervalForCulling ? "none" : null;
13996 }
13997 });
13998 } else {
13999 tickNodes.style("display", null);
14000 }
14001 if (type === "x") {
14002 const clipPath = current.maxTickSize.x.clipPath ? clip.pathXAxisTickTexts : null;
14003 $el.svg.selectAll(`.${$AXIS.axisX} .tick text`).attr("clip-path", clipPath);
14004 }
14005 }
14006 });
14007 }
14008 /**
14009 * Set axis tooltip
14010 * @private
14011 */
14012 setAxisTooltip() {
14013 var _a;
14014 const $$ = this.owner;
14015 const { config: { axis_rotated: isRotated, axis_tooltip }, $el: { axis, axisTooltip } } = $$;
14016 const bgColor = (_a = axis_tooltip.backgroundColor) != null ? _a : "black";
14017 $$.generateTextBGColorFilter(
14018 bgColor,
14019 {
14020 x: -0.15,
14021 y: -0.2,
14022 width: 1.3,
14023 height: 1.3
14024 }
14025 );
14026 ["x", "y", "y2"].forEach((v) => {
14027 var _a2, _b, _c;
14028 axisTooltip[v] = (_a2 = axis[v]) == null ? void 0 : _a2.append("text").classed($AXIS[`axis${v.toUpperCase()}Tooltip`], true).attr("filter", $$.updateTextBGColor({ id: v }, bgColor));
14029 if (isRotated) {
14030 const pos = v === "x" ? "x" : "y";
14031 const val = v === "y" ? "1.15em" : v === "x" ? "-0.3em" : "-0.4em";
14032 (_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);
14033 } else {
14034 const pos = v === "x" ? "y" : "x";
14035 const val = v === "x" ? "1.15em" : `${v === "y" ? "-" : ""}0.4em`;
14036 (_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);
14037 }
14038 });
14039 }
14040}
14041
14042;// ./src/ChartInternal/interactions/eventrect.ts
14043
14044
14045/* harmony default export */ var eventrect = ({
14046 /**
14047 * Initialize the area that detects the event.
14048 * Add a container for the zone that detects the event.
14049 * @private
14050 */
14051 initEventRect() {
14052 const $$ = this;
14053 $$.$el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $EVENT.eventRects).style("fill-opacity", "0");
14054 },
14055 /**
14056 * Redraws the area that detects the event.
14057 * @private
14058 */
14059 redrawEventRect() {
14060 var _a;
14061 const $$ = this;
14062 const { config, state, $el } = $$;
14063 const isMultipleX = $$.isMultipleX();
14064 const isInverted = config.axis_x_inverted;
14065 if ($el.eventRect) {
14066 $$.updateEventRect($el.eventRect, true);
14067 } else if ($$.data.targets.length) {
14068 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);
14069 const eventRectUpdate = eventRects.selectAll(`.${$EVENT.eventRect}`).data([0]).enter().append("rect");
14070 $$.updateEventRect(eventRectUpdate);
14071 $$.updateEventType(eventRectUpdate);
14072 eventRectUpdate.call($$.getDraggableSelection());
14073 $el.eventRect = eventRectUpdate;
14074 if ($$.state.inputType === "touch" && !$el.svg.on("touchstart.eventRect") && !$$.hasArcType()) {
14075 $$.bindTouchOnEventRect();
14076 }
14077 state.rendered && $$.updateEventRect($el.eventRect, true);
14078 }
14079 if (!isMultipleX) {
14080 const xAxisTickValues = $$.getMaxDataCountTarget();
14081 if (!config.data_xSort || isInverted) {
14082 xAxisTickValues.sort((a, b) => isInverted ? b.x - a.x : a.x - b.x);
14083 }
14084 $$.updateDataIndexByX(xAxisTickValues);
14085 $$.updateXs(xAxisTickValues);
14086 (_a = $$.updatePointClass) == null ? void 0 : _a.call($$, true);
14087 state.eventReceiver.data = xAxisTickValues;
14088 }
14089 $$.updateEventRectData();
14090 },
14091 bindTouchOnEventRect() {
14092 const $$ = this;
14093 const { config, state, $el: { eventRect, svg } } = $$;
14094 const selectRect = (context) => {
14095 if ($$.isMultipleX()) {
14096 $$.selectRectForMultipleXs(context);
14097 } else {
14098 const index = $$.getDataIndexFromEvent(state.event);
14099 $$.callOverOutForTouch(index);
14100 index === -1 ? $$.unselectRect() : $$.selectRectForSingle(context, index);
14101 }
14102 };
14103 const unselectRect = () => {
14104 $$.unselectRect();
14105 $$.callOverOutForTouch();
14106 };
14107 const preventDefault = config.interaction_inputType_touch.preventDefault;
14108 const isPrevented = isBoolean(preventDefault) && preventDefault || false;
14109 const preventThreshold = !isNaN(preventDefault) && preventDefault || null;
14110 let startPx;
14111 const preventEvent = (event) => {
14112 const eventType = event.type;
14113 const touch = event.changedTouches[0];
14114 const currentXY = touch[`client${config.axis_rotated ? "Y" : "X"}`];
14115 if (eventType === "touchstart") {
14116 if (isPrevented) {
14117 event.preventDefault();
14118 } else if (preventThreshold !== null) {
14119 startPx = currentXY;
14120 }
14121 } else if (eventType === "touchmove") {
14122 if (isPrevented || startPx === true || preventThreshold !== null && Math.abs(startPx - currentXY) >= preventThreshold) {
14123 startPx = true;
14124 event.preventDefault();
14125 }
14126 }
14127 };
14128 eventRect.on("touchstart", (event) => {
14129 state.event = event;
14130 $$.updateEventRect();
14131 }).on("touchstart.eventRect touchmove.eventRect", (event) => {
14132 state.event = event;
14133 if (!eventRect.empty() && eventRect.classed($EVENT.eventRect)) {
14134 if (state.dragging || state.flowing || $$.hasArcType() || event.touches.length > 1) {
14135 return;
14136 }
14137 preventEvent(event);
14138 selectRect(eventRect.node());
14139 } else {
14140 unselectRect();
14141 }
14142 }, true).on("touchend.eventRect", (event) => {
14143 state.event = event;
14144 if (!eventRect.empty() && eventRect.classed($EVENT.eventRect)) {
14145 if ($$.hasArcType() || !$$.toggleShape || state.cancelClick) {
14146 state.cancelClick && (state.cancelClick = false);
14147 }
14148 }
14149 }, true);
14150 svg.on("touchstart", (event) => {
14151 state.event = event;
14152 const { target } = event;
14153 if (target && target !== eventRect.node()) {
14154 unselectRect();
14155 }
14156 });
14157 },
14158 /**
14159 * Update event rect size
14160 * @param {d3Selection} eventRect Event <rect> element
14161 * @param {boolean} force Force to update
14162 * @private
14163 */
14164 updateEventRect(eventRect, force = false) {
14165 const $$ = this;
14166 const { state, $el } = $$;
14167 const { eventReceiver, width, height, rendered, resizing } = state;
14168 const rectElement = eventRect || $el.eventRect;
14169 const updateClientRect = () => {
14170 if (eventReceiver) {
14171 const scrollPos = getScrollPosition($el.chart.node());
14172 eventReceiver.rect = rectElement.node().getBoundingClientRect().toJSON();
14173 eventReceiver.rect.top += scrollPos.y;
14174 eventReceiver.rect.left += scrollPos.x;
14175 }
14176 };
14177 if (!rendered || resizing || force) {
14178 rectElement.attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
14179 if (!rendered || force) {
14180 rectElement.classed($EVENT.eventRect, true);
14181 }
14182 }
14183 updateClientRect();
14184 },
14185 /**
14186 * Update event type (single or multiple x)
14187 * @param {d3Selection | boolean} target Target element or boolean to rebind event
14188 */
14189 updateEventType(target) {
14190 const $$ = this;
14191 const isRebindCall = isBoolean(target);
14192 const eventRect = isRebindCall ? $$.$el.eventRect : target;
14193 const unbindEvent = isRebindCall ? target !== (eventRect == null ? void 0 : eventRect.datum().multipleX) : false;
14194 if (eventRect) {
14195 unbindEvent && (eventRect == null ? void 0 : eventRect.on("mouseover mousemove mouseout click", null));
14196 $$.isMultipleX() ? $$.generateEventRectsForMultipleXs(eventRect) : $$.generateEventRectsForSingleX(eventRect);
14197 }
14198 },
14199 /**
14200 * Updates the location and size of the eventRect.
14201 * @private
14202 */
14203 updateEventRectData() {
14204 const $$ = this;
14205 const { config, scale, state } = $$;
14206 const xScale = scale.zoom || scale.x;
14207 const isRotated = config.axis_rotated;
14208 const isMultipleX = $$.isMultipleX();
14209 let x;
14210 let y;
14211 let w;
14212 let h;
14213 $$.updateEventType(isMultipleX);
14214 if (isMultipleX) {
14215 x = 0;
14216 y = 0;
14217 w = state.width;
14218 h = state.height;
14219 } else {
14220 let rectW;
14221 let rectX;
14222 if ($$.axis.isCategorized()) {
14223 rectW = $$.getEventRectWidth();
14224 rectX = (d) => xScale(d.x) - rectW / 2;
14225 } else {
14226 const getPrevNextX = ({ index }) => ({
14227 prev: $$.getPrevX(index),
14228 next: $$.getNextX(index)
14229 });
14230 rectW = (d) => {
14231 const x2 = getPrevNextX(d);
14232 const xDomain = xScale.domain();
14233 let val;
14234 if (x2.prev === null && x2.next === null) {
14235 val = isRotated ? state.height : state.width;
14236 } else if (x2.prev === null) {
14237 val = (xScale(x2.next) + xScale(d.x)) / 2;
14238 } else if (x2.next === null) {
14239 val = xScale(xDomain[1]) - (xScale(x2.prev) + xScale(d.x)) / 2;
14240 } else {
14241 Object.keys(x2).forEach((key, i) => {
14242 var _a;
14243 x2[key] = (_a = x2[key]) != null ? _a : xDomain[i];
14244 });
14245 val = Math.max(0, (xScale(x2.next) - xScale(x2.prev)) / 2);
14246 }
14247 return val;
14248 };
14249 rectX = (d) => {
14250 const x2 = getPrevNextX(d);
14251 let val;
14252 if (x2.prev === null && x2.next === null) {
14253 val = 0;
14254 } else if (x2.prev === null) {
14255 val = xScale(xScale.domain()[0]);
14256 } else {
14257 val = (xScale(d.x) + xScale(x2.prev)) / 2;
14258 }
14259 return val;
14260 };
14261 }
14262 x = isRotated ? 0 : rectX;
14263 y = isRotated ? rectX : 0;
14264 w = isRotated ? state.width : rectW;
14265 h = isRotated ? rectW : state.height;
14266 }
14267 const { eventReceiver } = state;
14268 const call = (fn, v) => isFunction(fn) ? fn(v) : fn;
14269 eventReceiver.coords.splice(eventReceiver.data.length);
14270 eventReceiver.data.forEach((d, i) => {
14271 eventReceiver.coords[i] = {
14272 x: call(x, d),
14273 y: call(y, d),
14274 w: call(w, d),
14275 h: call(h, d)
14276 };
14277 });
14278 },
14279 /**
14280 * Seletct rect for single x value
14281 * @param {d3Selection} context Event rect element
14282 * @param {number} index x Axis index
14283 * @private
14284 */
14285 selectRectForSingle(context, index) {
14286 var _a, _b;
14287 const $$ = this;
14288 const { config, $el: { main, circle } } = $$;
14289 const isSelectionEnabled = config.data_selection_enabled;
14290 const isSelectionGrouped = config.data_selection_grouped;
14291 const isSelectable = config.data_selection_isselectable;
14292 const isTooltipGrouped = config.tooltip_grouped;
14293 const selectedData = $$.getAllValuesOnIndex(index);
14294 if (isTooltipGrouped) {
14295 $$.showTooltip(selectedData, context);
14296 (_a = $$.showGridFocus) == null ? void 0 : _a.call($$, selectedData);
14297 if (!isSelectionEnabled || isSelectionGrouped) {
14298 return;
14299 }
14300 }
14301 !circle && main.selectAll(`.${$COMMON.EXPANDED}:not(.${$SHAPE.shape}-${index})`).classed(
14302 $COMMON.EXPANDED,
14303 false
14304 );
14305 const shapeAtIndex = main.selectAll(`.${$SHAPE.shape}-${index}`).classed($COMMON.EXPANDED, true).style("cursor", isSelectable ? "pointer" : null).filter(function(d) {
14306 return $$.isWithinShape(this, d);
14307 });
14308 if (shapeAtIndex.empty() && !isTooltipGrouped && config.interaction_onout) {
14309 (_b = $$.hideGridFocus) == null ? void 0 : _b.call($$);
14310 $$.hideTooltip();
14311 !isSelectionGrouped && $$.setExpand(index);
14312 }
14313 shapeAtIndex.call((selected) => {
14314 var _a2, _b2;
14315 const d = selected.data();
14316 if (isSelectionEnabled && (isSelectionGrouped || (isSelectable == null ? void 0 : isSelectable.bind($$.api)(d)))) {
14317 context.style.cursor = "pointer";
14318 }
14319 if (!isTooltipGrouped) {
14320 $$.showTooltip(d, context);
14321 (_a2 = $$.showGridFocus) == null ? void 0 : _a2.call($$, d);
14322 (_b2 = $$.unexpandCircles) == null ? void 0 : _b2.call($$);
14323 selected.each((d2) => $$.setExpand(index, d2.id));
14324 }
14325 });
14326 },
14327 /**
14328 * Select rect for multiple x values
14329 * @param {d3Selection} context Event rect element
14330 * @param {boolean} [triggerEvent=true] Whether trigger event or not
14331 * @private
14332 */
14333 selectRectForMultipleXs(context, triggerEvent = true) {
14334 const $$ = this;
14335 const { config, state } = $$;
14336 const targetsToShow = $$.filterTargetsToShow($$.data.targets);
14337 if (state.dragging || $$.hasArcType(targetsToShow)) {
14338 return;
14339 }
14340 const mouse = getPointer(state.event, context);
14341 const closest = $$.findClosestFromTargets(targetsToShow, mouse);
14342 if (triggerEvent && state.mouseover && (!closest || closest.id !== state.mouseover.id)) {
14343 config.data_onout.call($$.api, state.mouseover);
14344 state.mouseover = void 0;
14345 }
14346 if (!closest) {
14347 $$.unselectRect();
14348 return;
14349 }
14350 const sameXData = $$.isBubbleType(closest) || $$.isScatterType(closest) || !config.tooltip_grouped ? [closest] : $$.filterByX(targetsToShow, closest.x);
14351 const selectedData = sameXData.map((d) => $$.addName(d));
14352 $$.showTooltip(selectedData, context);
14353 $$.setExpand(closest.index, closest.id, true);
14354 $$.showGridFocus(selectedData);
14355 const dist = $$.dist(closest, mouse);
14356 if ($$.isBarType(closest.id) || dist < $$.getPointSensitivity(closest)) {
14357 $$.$el.svg.select(`.${$EVENT.eventRect}`).style("cursor", "pointer");
14358 if (triggerEvent && !state.mouseover) {
14359 config.data_onover.call($$.api, closest);
14360 state.mouseover = closest;
14361 }
14362 }
14363 },
14364 /**
14365 * Unselect EventRect.
14366 * @private
14367 */
14368 unselectRect() {
14369 const $$ = this;
14370 const { $el: { circle, tooltip } } = $$;
14371 $$.$el.svg.select(`.${$EVENT.eventRect}`).style("cursor", null);
14372 $$.hideGridFocus();
14373 if (tooltip) {
14374 $$.hideTooltip();
14375 $$._handleLinkedCharts(false);
14376 }
14377 circle && !$$.isPointFocusOnly() && $$.unexpandCircles();
14378 $$.expandBarTypeShapes(false);
14379 },
14380 /**
14381 * Create eventRect for each data on the x-axis.
14382 * Register touch and drag events.
14383 * @param {object} eventRectEnter d3.select($EVENT.eventRects) object.
14384 * @returns {object} d3.select($EVENT.eventRects) object.
14385 * @private
14386 */
14387 generateEventRectsForSingleX(eventRectEnter) {
14388 const $$ = this;
14389 const { config, state } = $$;
14390 const { eventReceiver } = state;
14391 const rect = eventRectEnter.style(
14392 "cursor",
14393 config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null
14394 ).on("click", function(event) {
14395 state.event = event;
14396 const { currentIdx, data } = eventReceiver;
14397 const d = data[currentIdx === -1 ? $$.getDataIndexFromEvent(event) : currentIdx];
14398 $$.clickHandlerForSingleX.bind(this)(d, $$);
14399 }).datum({ multipleX: false });
14400 if (state.inputType === "mouse") {
14401 const getData = (event) => {
14402 const index = event ? $$.getDataIndexFromEvent(event) : eventReceiver.currentIdx;
14403 return index > -1 ? eventReceiver.data[index] : null;
14404 };
14405 rect.on("mouseover", (event) => {
14406 state.event = event;
14407 $$.updateEventRect();
14408 Object.values($$.$el.axisTooltip).forEach((v) => v == null ? void 0 : v.style("display", null));
14409 }).on("mousemove", function(event) {
14410 const d = getData(event);
14411 state.event = event;
14412 if (!d) {
14413 return;
14414 }
14415 let { index } = d;
14416 const stepType = config.line_step_type;
14417 if (config.line_step_tooltipMatch && $$.hasType("step") && /^step\-(before|after)$/.test(stepType)) {
14418 const scale = $$.scale.zoom || $$.scale.x;
14419 const xs = $$.axis.xs[index];
14420 const inverted = scale.invert(getPointer(event, this)[0]);
14421 if (stepType === "step-after" && inverted < xs) {
14422 index -= 1;
14423 } else if (stepType === "step-before" && inverted > xs) {
14424 index += 1;
14425 }
14426 }
14427 $$.showAxisGridFocus();
14428 const eventOnSameIdx = config.tooltip_grouped && index === eventReceiver.currentIdx;
14429 if (state.dragging || state.flowing || $$.hasArcType() || eventOnSameIdx) {
14430 config.tooltip_show && eventOnSameIdx && $$.setTooltipPosition();
14431 return;
14432 }
14433 if (index !== eventReceiver.currentIdx) {
14434 $$.setOverOut(false, eventReceiver.currentIdx);
14435 eventReceiver.currentIdx = index;
14436 }
14437 index === -1 ? $$.unselectRect() : $$.selectRectForSingle(this, index);
14438 $$.setOverOut(index !== -1, index);
14439 }).on("mouseout", (event) => {
14440 state.event = event;
14441 if (!config || $$.hasArcType() || eventReceiver.currentIdx === -1 || !config.interaction_onout) {
14442 return;
14443 }
14444 $$.hideAxisGridFocus();
14445 $$.unselectRect();
14446 $$.setOverOut(false, eventReceiver.currentIdx);
14447 eventReceiver.currentIdx = -1;
14448 });
14449 }
14450 return rect;
14451 },
14452 clickHandlerForSingleX(d, ctx) {
14453 const $$ = ctx;
14454 const { config, state, $el: { main } } = $$;
14455 if (!d || $$.hasArcType() || state.cancelClick) {
14456 state.cancelClick && (state.cancelClick = false);
14457 return;
14458 }
14459 const { index } = d;
14460 main.selectAll(`.${$SHAPE.shape}-${index}`).each(function(d2) {
14461 var _a;
14462 if (config.data_selection_grouped || $$.isWithinShape(this, d2)) {
14463 (_a = $$.toggleShape) == null ? void 0 : _a.call($$, this, d2, index);
14464 config.data_onclick.bind($$.api)(d2, this);
14465 }
14466 });
14467 },
14468 /**
14469 * Create an eventRect,
14470 * Register touch and drag events.
14471 * @param {object} eventRectEnter d3.select($EVENT.eventRects) object.
14472 * @private
14473 */
14474 generateEventRectsForMultipleXs(eventRectEnter) {
14475 const $$ = this;
14476 const { config, state } = $$;
14477 eventRectEnter.on("click", function(event) {
14478 state.event = event;
14479 $$.clickHandlerForMultipleXS.bind(this)($$);
14480 }).datum({ multipleX: true });
14481 if (state.inputType === "mouse") {
14482 eventRectEnter.on("mouseover mousemove", function(event) {
14483 state.event = event;
14484 $$.selectRectForMultipleXs(this);
14485 }).on("mouseout", (event) => {
14486 state.event = event;
14487 if (!$$.config || $$.hasArcType() || !config.interaction_onout) {
14488 return;
14489 }
14490 $$.unselectRect();
14491 });
14492 }
14493 },
14494 clickHandlerForMultipleXS(ctx) {
14495 const $$ = ctx;
14496 const { config, state } = $$;
14497 const targetsToShow = $$.filterTargetsToShow($$.data.targets);
14498 if ($$.hasArcType(targetsToShow)) {
14499 return;
14500 }
14501 const mouse = getPointer(state.event, this);
14502 const closest = $$.findClosestFromTargets(targetsToShow, mouse);
14503 const sensitivity = $$.getPointSensitivity(closest);
14504 if (!closest) {
14505 return;
14506 }
14507 if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < sensitivity) {
14508 $$.$el.main.selectAll(`.${$SHAPE.shapes}${$$.getTargetSelectorSuffix(closest.id)}`).selectAll(`.${$SHAPE.shape}-${closest.index}`).each(function() {
14509 var _a;
14510 if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
14511 (_a = $$.toggleShape) == null ? void 0 : _a.call($$, this, closest, closest.index);
14512 config.data_onclick.bind($$.api)(closest, this);
14513 }
14514 });
14515 }
14516 }
14517});
14518
14519// EXTERNAL MODULE: external {"commonjs":"d3-ease","commonjs2":"d3-ease","amd":"d3-ease","root":"d3"}
14520var external_commonjs_d3_ease_commonjs2_d3_ease_amd_d3_ease_root_d3_ = __webpack_require__(12);
14521;// ./src/ChartInternal/interactions/flow.ts
14522
14523
14524
14525
14526/* harmony default export */ var interactions_flow = ({
14527 /**
14528 * Generate flow
14529 * @param {object} args option object
14530 * @returns {Function}
14531 * @private
14532 */
14533 generateFlow(args) {
14534 const $$ = this;
14535 const { data, state, $el } = $$;
14536 return function() {
14537 const flowLength = args.flow.length;
14538 state.flowing = true;
14539 data.targets.forEach((d) => {
14540 d.values.splice(0, flowLength);
14541 });
14542 if ($$.updateXGrid) {
14543 $$.updateXGrid(true);
14544 }
14545 const elements = {};
14546 [
14547 "axis.x",
14548 "grid.x",
14549 "gridLines.x",
14550 "region.list",
14551 "text",
14552 "bar",
14553 "line",
14554 "area",
14555 "circle"
14556 ].forEach((v) => {
14557 const name = v.split(".");
14558 let node = $el[name[0]];
14559 if (node && name.length > 1) {
14560 node = node[name[1]];
14561 }
14562 if (node == null ? void 0 : node.size()) {
14563 elements[v] = node;
14564 }
14565 });
14566 $$.hideGridFocus();
14567 $$.setFlowList(elements, args);
14568 };
14569 },
14570 /**
14571 * Set flow list
14572 * @param {object} elements Target elements
14573 * @param {object} args option object
14574 * @private
14575 */
14576 setFlowList(elements, args) {
14577 const $$ = this;
14578 const { flow, targets } = args;
14579 const {
14580 duration = args.duration,
14581 index: flowIndex,
14582 length: flowLength,
14583 orgDataCount
14584 } = flow;
14585 const transform = $$.getFlowTransform(targets, orgDataCount, flowIndex, flowLength);
14586 const wait = generateWait();
14587 let n;
14588 wait.add(Object.keys(elements).map((v) => {
14589 n = elements[v].transition().ease(external_commonjs_d3_ease_commonjs2_d3_ease_amd_d3_ease_root_d3_.easeLinear).duration(duration);
14590 if (v === "axis.x") {
14591 n = n.call((g) => {
14592 $$.axis.x.setTransition(g).create(g);
14593 });
14594 } else if (v === "region.list") {
14595 n = n.filter($$.isRegionOnX).attr("transform", transform);
14596 } else {
14597 n = n.attr("transform", transform);
14598 }
14599 return n;
14600 }));
14601 n.call(wait, () => {
14602 $$.cleanUpFlow(elements, args);
14603 });
14604 },
14605 /**
14606 * Clean up flow
14607 * @param {object} elements Target elements
14608 * @param {object} args option object
14609 * @private
14610 */
14611 cleanUpFlow(elements, args) {
14612 const $$ = this;
14613 const { config, state, $el: { svg } } = $$;
14614 const isRotated = config.axis_rotated;
14615 const { flow, shape, xv } = args;
14616 const { cx, cy, xForText, yForText } = shape.pos;
14617 const {
14618 done = () => {
14619 },
14620 length: flowLength
14621 } = flow;
14622 if (flowLength) {
14623 ["circle", "text", "shape", "eventRect"].forEach((v) => {
14624 const target = [];
14625 for (let i = 0; i < flowLength; i++) {
14626 target.push(`.${classes[v]}-${i}`);
14627 }
14628 svg.selectAll(`.${classes[`${v}s`]}`).selectAll(target).remove();
14629 });
14630 svg.select(`.${classes.xgrid}`).remove();
14631 }
14632 Object.keys(elements).forEach((v) => {
14633 const n = elements[v];
14634 if (v !== "axis.x") {
14635 n.attr("transform", null);
14636 }
14637 if (v === "grid.x") {
14638 n.attr(state.xgridAttr);
14639 } else if (v === "gridLines.x") {
14640 n.attr("x1", isRotated ? 0 : xv).attr("x2", isRotated ? state.width : xv);
14641 n.select("text").attr("x", isRotated ? state.width : 0).attr("y", xv);
14642 } else if (/^(area|bar|line)$/.test(v)) {
14643 n.attr("d", shape.type[v]);
14644 } else if (v === "text") {
14645 n.attr("x", xForText).attr("y", yForText).style("fill-opacity", $$.opacityForText.bind($$));
14646 } else if (v === "circle") {
14647 if ($$.isCirclePoint()) {
14648 n.attr("cx", cx).attr("cy", cy);
14649 } else {
14650 const xFunc = (d) => cx(d) - config.point_r;
14651 const yFunc = (d) => cy(d) - config.point_r;
14652 n.attr("x", xFunc).attr("y", yFunc);
14653 }
14654 } else if (v === "region.list") {
14655 n.select("rect").filter($$.isRegionOnX).attr("x", $$.regionX.bind($$)).attr("width", $$.regionWidth.bind($$));
14656 }
14657 });
14658 config.interaction_enabled && $$.redrawEventRect();
14659 done.call($$.api);
14660 state.flowing = false;
14661 },
14662 /**
14663 * Get flow transform value
14664 * @param {object} targets target
14665 * @param {number} orgDataCount original data count
14666 * @param {number} flowIndex flow index
14667 * @param {number} flowLength flow length
14668 * @returns {string}
14669 * @private
14670 */
14671 getFlowTransform(targets, orgDataCount, flowIndex, flowLength) {
14672 const $$ = this;
14673 const { data, scale: { x } } = $$;
14674 const dataValues = data.targets[0].values;
14675 let flowStart = $$.getValueOnIndex(dataValues, flowIndex);
14676 let flowEnd = $$.getValueOnIndex(dataValues, flowIndex + flowLength);
14677 let translateX;
14678 const orgDomain = x.domain();
14679 const domain = $$.updateXDomain(targets, true, true);
14680 if (!orgDataCount) {
14681 if (dataValues.length !== 1) {
14682 translateX = x(orgDomain[0]) - x(domain[0]);
14683 } else {
14684 if ($$.axis.isTimeSeries()) {
14685 flowStart = $$.getValueOnIndex(dataValues, 0);
14686 flowEnd = $$.getValueOnIndex(dataValues, dataValues.length - 1);
14687 translateX = x(flowStart.x) - x(flowEnd.x);
14688 } else {
14689 translateX = diffDomain(domain) / 2;
14690 }
14691 }
14692 } else if (orgDataCount === 1 || (flowStart == null ? void 0 : flowStart.x) === (flowEnd == null ? void 0 : flowEnd.x)) {
14693 translateX = x(orgDomain[0]) - x(domain[0]);
14694 } else {
14695 translateX = $$.axis.isTimeSeries() ? x(orgDomain[0]) - x(domain[0]) : x((flowStart == null ? void 0 : flowStart.x) || 0) - x(flowEnd.x);
14696 }
14697 const scaleX = diffDomain(orgDomain) / diffDomain(domain);
14698 return `translate(${translateX},0) scale(${scaleX},1)`;
14699 }
14700});
14701
14702;// ./src/ChartInternal/internals/clip.ts
14703/* harmony default export */ var clip = ({
14704 initClip() {
14705 const $$ = this;
14706 const { clip, datetimeId } = $$.state;
14707 clip.id = `${datetimeId}-clip`;
14708 clip.idXAxis = `${clip.id}-xaxis`;
14709 clip.idYAxis = `${clip.id}-yaxis`;
14710 clip.idGrid = `${clip.id}-grid`;
14711 clip.path = $$.getClipPath(clip.id);
14712 clip.pathXAxis = $$.getClipPath(clip.idXAxis);
14713 clip.pathYAxis = $$.getClipPath(clip.idYAxis);
14714 clip.pathGrid = $$.getClipPath(clip.idGrid);
14715 },
14716 getClipPath(id) {
14717 const $$ = this;
14718 const { config } = $$;
14719 if (!config.clipPath && /-clip$/.test(id) || !config.axis_x_clipPath && /-clip-xaxis$/.test(id) || !config.axis_y_clipPath && /-clip-yaxis$/.test(id)) {
14720 return null;
14721 }
14722 return `url(#${id})`;
14723 },
14724 appendClip(parent, id) {
14725 id && parent.append("clipPath").attr("id", id).append("rect");
14726 },
14727 /**
14728 * Set x Axis clipPath dimension
14729 * @param {d3Selecton} node clipPath <rect> selection
14730 * @private
14731 */
14732 setXAxisClipPath(node) {
14733 const $$ = this;
14734 const { config, state: { margin, width, height } } = $$;
14735 const isRotated = config.axis_rotated;
14736 const left = Math.max(30, margin.left) - (isRotated ? 0 : 20);
14737 const h = (isRotated ? margin.top + height + 10 : margin.bottom) + 20;
14738 const x = isRotated ? -(1 + left) : -(left - 1);
14739 const y = -15;
14740 const w = isRotated ? margin.left + 20 : width + 10 + left;
14741 node.attr("x", x).attr("y", y).attr("width", w).attr("height", h);
14742 },
14743 /**
14744 * Set y Axis clipPath dimension
14745 * @param {d3Selection} node clipPath <rect> selection
14746 * @private
14747 */
14748 setYAxisClipPath(node) {
14749 const $$ = this;
14750 const { config, state: { margin, width, height } } = $$;
14751 const isRotated = config.axis_rotated;
14752 const left = Math.max(30, margin.left) - (isRotated ? 20 : 0);
14753 const isInner = config.axis_y_inner;
14754 const x = isInner && !isRotated ? config.axis_y_label.text ? -20 : -1 : isRotated ? -(1 + left) : -(left - 1);
14755 const y = -(isRotated ? 20 : margin.top);
14756 const w = (isRotated ? width + 15 + left : margin.left + 20) + (isInner ? 20 : 0);
14757 const h = (isRotated ? margin.bottom + 10 : margin.top + height) + 10;
14758 node.attr("x", x).attr("y", y).attr("width", w).attr("height", h);
14759 },
14760 updateXAxisTickClip() {
14761 const $$ = this;
14762 const { config, state: { clip, xAxisHeight }, $el: { defs } } = $$;
14763 const newXAxisHeight = $$.getHorizontalAxisHeight("x");
14764 if (defs && !clip.idXAxisTickTexts) {
14765 const clipId = `${clip.id}-xaxisticktexts`;
14766 $$.appendClip(defs, clipId);
14767 clip.pathXAxisTickTexts = $$.getClipPath(clip.idXAxisTickTexts);
14768 clip.idXAxisTickTexts = clipId;
14769 }
14770 if (!config.axis_x_tick_multiline && $$.getAxisTickRotate("x") && newXAxisHeight !== xAxisHeight) {
14771 $$.setXAxisTickClipWidth();
14772 $$.setXAxisTickTextClipPathWidth();
14773 }
14774 $$.state.xAxisHeight = newXAxisHeight;
14775 },
14776 setXAxisTickClipWidth() {
14777 const $$ = this;
14778 const { config, state: { current: { maxTickSize } } } = $$;
14779 const xAxisTickRotate = $$.getAxisTickRotate("x");
14780 if (!config.axis_x_tick_multiline && xAxisTickRotate) {
14781 const sinRotation = Math.sin(Math.PI / 180 * Math.abs(xAxisTickRotate));
14782 maxTickSize.x.clipPath = ($$.getHorizontalAxisHeight("x") - 20) / sinRotation;
14783 } else {
14784 maxTickSize.x.clipPath = null;
14785 }
14786 },
14787 setXAxisTickTextClipPathWidth() {
14788 const $$ = this;
14789 const { state: { clip, current }, $el: { svg } } = $$;
14790 if (svg) {
14791 svg.select(`#${clip.idXAxisTickTexts} rect`).attr("width", current.maxTickSize.x.clipPath).attr("height", 30);
14792 }
14793 }
14794});
14795
14796;// ./src/ChartInternal/internals/grid.ts
14797
14798
14799
14800const getGridTextAnchor = (d) => isValue(d.position) || "end";
14801const getGridTextDx = (d) => d.position === "start" ? 4 : d.position === "middle" ? 0 : -4;
14802function getGridTextX(isX, width, height) {
14803 return (d) => {
14804 let x = isX ? 0 : width;
14805 if (d.position === "start") {
14806 x = isX ? -height : 0;
14807 } else if (d.position === "middle") {
14808 x = (isX ? -height : width) / 2;
14809 }
14810 return x;
14811 };
14812}
14813function smoothLines(el, type) {
14814 if (type === "grid") {
14815 el.each(function() {
14816 const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
14817 ["x1", "x2", "y1", "y2"].forEach((v) => g.attr(v, +g.attr(v)));
14818 });
14819 }
14820}
14821/* harmony default export */ var internals_grid = ({
14822 hasGrid() {
14823 const { config } = this;
14824 return ["x", "y"].some((v) => config[`grid_${v}_show`] || config[`grid_${v}_lines`].length);
14825 },
14826 initGrid() {
14827 const $$ = this;
14828 $$.hasGrid() && $$.initGridLines();
14829 $$.initFocusGrid();
14830 },
14831 initGridLines() {
14832 const $$ = this;
14833 const { config, state: { clip }, $el } = $$;
14834 if (config.grid_x_lines.length || config.grid_y_lines.length) {
14835 $el.gridLines.main = $el.main.insert(
14836 "g",
14837 `.${$COMMON.chart}${config.grid_lines_front ? " + *" : ""}`
14838 ).attr("clip-path", clip.pathGrid).attr("class", `${$GRID.grid} ${$GRID.gridLines}`);
14839 $el.gridLines.main.append("g").attr("class", $GRID.xgridLines);
14840 $el.gridLines.main.append("g").attr("class", $GRID.ygridLines);
14841 $el.gridLines.x = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.selectAll)([]);
14842 }
14843 },
14844 updateXGrid(withoutUpdate) {
14845 const $$ = this;
14846 const { config, scale, state, $el: { main, grid } } = $$;
14847 const isRotated = config.axis_rotated;
14848 const xgridData = $$.generateGridData(config.grid_x_type, scale.x);
14849 const tickOffset = $$.axis.isCategorized() ? $$.axis.x.tickOffset() : 0;
14850 const pos = (d) => (scale.zoom || scale.x)(d) + tickOffset * (isRotated ? -1 : 1);
14851 state.xgridAttr = isRotated ? {
14852 x1: 0,
14853 x2: state.width,
14854 y1: pos,
14855 y2: pos
14856 } : {
14857 x1: pos,
14858 x2: pos,
14859 y1: 0,
14860 y2: state.height
14861 };
14862 grid.x = main.select(`.${$GRID.xgrids}`).selectAll(`.${$GRID.xgrid}`).data(xgridData);
14863 grid.x.exit().remove();
14864 grid.x = grid.x.enter().append("line").attr("class", $GRID.xgrid).merge(grid.x);
14865 if (!withoutUpdate) {
14866 grid.x.each(function() {
14867 const grid2 = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
14868 Object.keys(state.xgridAttr).forEach((id) => {
14869 grid2.attr(id, state.xgridAttr[id]).style("opacity", () => grid2.attr(isRotated ? "y1" : "x1") === (isRotated ? state.height : 0) ? "0" : null);
14870 });
14871 });
14872 }
14873 },
14874 updateYGrid() {
14875 const $$ = this;
14876 const { axis, config, scale, state, $el: { grid, main } } = $$;
14877 const isRotated = config.axis_rotated;
14878 const pos = (d) => scale.y(d);
14879 const gridValues = axis.y.getGeneratedTicks(config.grid_y_ticks) || $$.scale.y.ticks(config.grid_y_ticks);
14880 grid.y = main.select(`.${$GRID.ygrids}`).selectAll(`.${$GRID.ygrid}`).data(gridValues);
14881 grid.y.exit().remove();
14882 grid.y = grid.y.enter().append("line").attr("class", $GRID.ygrid).merge(grid.y);
14883 grid.y.attr("x1", isRotated ? pos : 0).attr("x2", isRotated ? pos : state.width).attr("y1", isRotated ? 0 : pos).attr("y2", isRotated ? state.height : pos);
14884 smoothLines(grid.y, "grid");
14885 },
14886 updateGrid() {
14887 const $$ = this;
14888 const { $el: { grid, gridLines } } = $$;
14889 !gridLines.main && $$.initGridLines();
14890 grid.main.style("visibility", $$.hasArcType() ? "hidden" : null);
14891 $$.hideGridFocus();
14892 $$.updateGridLines("x");
14893 $$.updateGridLines("y");
14894 },
14895 /**
14896 * Update Grid lines
14897 * @param {string} type x | y
14898 * @private
14899 */
14900 updateGridLines(type) {
14901 const $$ = this;
14902 const { config, $el: { gridLines, main }, $T } = $$;
14903 const isRotated = config.axis_rotated;
14904 const isX = type === "x";
14905 config[`grid_${type}_show`] && $$[`update${type.toUpperCase()}Grid`]();
14906 let lines = main.select(`.${$GRID[`${type}gridLines`]}`).selectAll(`.${$GRID[`${type}gridLine`]}`).data(config[`grid_${type}_lines`]);
14907 $T(lines.exit()).style("opacity", "0").remove();
14908 const gridLine = lines.enter().append("g");
14909 gridLine.append("line").style("opacity", "0");
14910 lines = gridLine.merge(lines);
14911 lines.each(function(d) {
14912 const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
14913 if (g.select("text").empty() && d.text) {
14914 g.append("text").style("opacity", "0");
14915 }
14916 });
14917 $T(lines.attr("class", (d) => `${$GRID[`${type}gridLine`]} ${d.class || ""}`.trim()).select("text").attr("text-anchor", getGridTextAnchor).attr(
14918 "transform",
14919 () => isX ? isRotated ? null : "rotate(-90)" : isRotated ? "rotate(-90)" : null
14920 ).attr("dx", getGridTextDx).attr("dy", -5)).text(function(d) {
14921 var _a;
14922 return (_a = d.text) != null ? _a : this.remove();
14923 });
14924 gridLines[type] = lines;
14925 },
14926 redrawGrid(withTransition) {
14927 const $$ = this;
14928 const {
14929 config: { axis_rotated: isRotated },
14930 state: { width, height },
14931 $el: { gridLines },
14932 $T
14933 } = $$;
14934 const xv = $$.xv.bind($$);
14935 const yv = $$.yv.bind($$);
14936 let xLines = gridLines.x.select("line");
14937 let xTexts = gridLines.x.select("text");
14938 let yLines = gridLines.y.select("line");
14939 let yTexts = gridLines.y.select("text");
14940 xLines = $T(xLines, withTransition).attr("x1", isRotated ? 0 : xv).attr("x2", isRotated ? width : xv).attr("y1", isRotated ? xv : 0).attr("y2", isRotated ? xv : height);
14941 xTexts = $T(xTexts, withTransition).attr("x", getGridTextX(!isRotated, width, height)).attr("y", xv);
14942 yLines = $T(yLines, withTransition).attr("x1", isRotated ? yv : 0).attr("x2", isRotated ? yv : width).attr("y1", isRotated ? 0 : yv).attr("y2", isRotated ? height : yv);
14943 yTexts = $T(yTexts, withTransition).attr("x", getGridTextX(isRotated, width, height)).attr("y", yv);
14944 return [
14945 xLines.style("opacity", null),
14946 xTexts.style("opacity", null),
14947 yLines.style("opacity", null),
14948 yTexts.style("opacity", null)
14949 ];
14950 },
14951 initFocusGrid() {
14952 const $$ = this;
14953 const { config, state: { clip }, $el } = $$;
14954 const isFront = config.grid_front;
14955 const className = `.${isFront && $el.gridLines.main ? $GRID.gridLines : $COMMON.chart}${isFront ? " + *" : ""}`;
14956 const grid = $el.main.insert("g", className).attr("clip-path", clip.pathGrid).attr("class", $GRID.grid);
14957 $el.grid.main = grid;
14958 config.grid_x_show && grid.append("g").attr("class", $GRID.xgrids);
14959 config.grid_y_show && grid.append("g").attr("class", $GRID.ygrids);
14960 if (config.axis_tooltip) {
14961 const axis = grid.append("g").attr("class", "bb-axis-tooltip");
14962 axis.append("line").attr("class", "bb-axis-tooltip-x");
14963 axis.append("line").attr("class", "bb-axis-tooltip-y");
14964 }
14965 if (config.interaction_enabled && config.grid_focus_show && !config.axis_tooltip) {
14966 grid.append("g").attr("class", $FOCUS.xgridFocus).append("line").attr("class", $FOCUS.xgridFocus);
14967 if (config.grid_focus_y && !config.tooltip_grouped) {
14968 grid.append("g").attr("class", $FOCUS.ygridFocus).append("line").attr("class", $FOCUS.ygridFocus);
14969 }
14970 }
14971 },
14972 showAxisGridFocus() {
14973 var _a, _b;
14974 const $$ = this;
14975 const { config, format, state: { event, width, height } } = $$;
14976 const isRotated = config.axis_rotated;
14977 const [x, y] = getPointer(event, (_a = $$.$el.eventRect) == null ? void 0 : _a.node());
14978 const pos = { x, y };
14979 for (const [axis, node] of Object.entries($$.$el.axisTooltip)) {
14980 const attr = axis === "x" && !isRotated || axis !== "x" && isRotated ? "x" : "y";
14981 const value = pos[attr];
14982 let scaleText = (_b = $$.scale[axis]) == null ? void 0 : _b.invert(value);
14983 if (scaleText) {
14984 scaleText = axis === "x" && $$.axis.isTimeSeries() ? format.xAxisTick(scaleText) : scaleText == null ? void 0 : scaleText.toFixed(2);
14985 node == null ? void 0 : node.attr(attr, value).text(scaleText);
14986 }
14987 }
14988 $$.$el.main.selectAll(
14989 `line.bb-axis-tooltip-x, line.bb-axis-tooltip-y`
14990 ).style("visibility", null).each(function(d, i) {
14991 const line = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
14992 if (i === 0) {
14993 line.attr("x1", x).attr("x2", x).attr("y1", i ? 0 : height).attr("y2", i ? height : 0);
14994 } else {
14995 line.attr("x1", i ? 0 : width).attr("x2", i ? width : 0).attr("y1", y).attr("y2", y);
14996 }
14997 });
14998 },
14999 hideAxisGridFocus() {
15000 const $$ = this;
15001 $$.$el.main.selectAll(
15002 `line.bb-axis-tooltip-x, line.bb-axis-tooltip-y`
15003 ).style("visibility", "hidden");
15004 Object.values($$.$el.axisTooltip).forEach((v) => v == null ? void 0 : v.style("display", "none"));
15005 },
15006 /**
15007 * Show grid focus line
15008 * @param {Array} data Selected data
15009 * @private
15010 */
15011 showGridFocus(data) {
15012 var _a;
15013 const $$ = this;
15014 const { config, state: { width, height } } = $$;
15015 const isRotated = config.axis_rotated;
15016 const focusEl = $$.$el.main.selectAll(
15017 `line.${$FOCUS.xgridFocus}, line.${$FOCUS.ygridFocus}`
15018 );
15019 const dataToShow = (data || [focusEl.datum()]).filter(
15020 (d) => d && isValue($$.getBaseValue(d))
15021 );
15022 if (!config.tooltip_show || dataToShow.length === 0 || !config.axis_x_forceAsSingle && $$.hasType("bubble") || $$.hasArcType()) {
15023 return;
15024 }
15025 const isEdge = config.grid_focus_edge && !config.tooltip_grouped;
15026 const xx = $$.xx.bind($$);
15027 focusEl.style("visibility", null).data(dataToShow.concat(dataToShow)).each(function(d) {
15028 const el = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
15029 const pos = {
15030 x: xx(d),
15031 y: $$.getYScaleById(d.id)(d.value)
15032 };
15033 let xy;
15034 if (el.classed($FOCUS.xgridFocus)) {
15035 xy = isRotated ? [
15036 null,
15037 // x1
15038 pos.x,
15039 // y1
15040 isEdge ? pos.y : width,
15041 // x2
15042 pos.x
15043 // y2
15044 ] : [
15045 pos.x,
15046 isEdge ? pos.y : null,
15047 pos.x,
15048 height
15049 ];
15050 } else {
15051 const isY2 = $$.axis.getId(d.id) === "y2";
15052 xy = isRotated ? [
15053 pos.y,
15054 // x1
15055 isEdge && !isY2 ? pos.x : null,
15056 // y1
15057 pos.y,
15058 // x2
15059 isEdge && isY2 ? pos.x : height
15060 // y2
15061 ] : [
15062 isEdge && isY2 ? pos.x : null,
15063 pos.y,
15064 isEdge && !isY2 ? pos.x : width,
15065 pos.y
15066 ];
15067 }
15068 ["x1", "y1", "x2", "y2"].forEach((v, i) => el.attr(v, xy[i]));
15069 });
15070 smoothLines(focusEl, "grid");
15071 (_a = $$.showCircleFocus) == null ? void 0 : _a.call($$, data);
15072 },
15073 hideGridFocus() {
15074 var _a;
15075 const $$ = this;
15076 const { state: { inputType, resizing }, $el: { main } } = $$;
15077 if (inputType === "mouse" || !resizing) {
15078 main.selectAll(`line.${$FOCUS.xgridFocus}, line.${$FOCUS.ygridFocus}`).style("visibility", "hidden");
15079 (_a = $$.hideCircleFocus) == null ? void 0 : _a.call($$);
15080 }
15081 },
15082 updateGridFocus() {
15083 var _a;
15084 const $$ = this;
15085 const { state: { inputType, width, height, resizing }, $el: { grid } } = $$;
15086 const xgridFocus = grid.main.select(`line.${$FOCUS.xgridFocus}`);
15087 if (inputType === "touch") {
15088 if (xgridFocus.empty()) {
15089 resizing && ((_a = $$.showCircleFocus) == null ? void 0 : _a.call($$));
15090 } else {
15091 $$.showGridFocus();
15092 }
15093 } else {
15094 const isRotated = $$.config.axis_rotated;
15095 xgridFocus.attr("x1", isRotated ? 0 : -10).attr("x2", isRotated ? width : -10).attr("y1", isRotated ? -10 : 0).attr("y2", isRotated ? -10 : height);
15096 }
15097 return true;
15098 },
15099 generateGridData(type, scale) {
15100 const $$ = this;
15101 const tickNum = $$.$el.main.select(`.${$AXIS.axisX}`).selectAll(".tick").size();
15102 let gridData = [];
15103 if (type === "year") {
15104 const xDomain = $$.getXDomain();
15105 const [firstYear, lastYear] = xDomain.map((v) => v.getFullYear());
15106 for (let i = firstYear; i <= lastYear; i++) {
15107 gridData.push(/* @__PURE__ */ new Date(`${i}-01-01 00:00:00`));
15108 }
15109 } else {
15110 gridData = scale.ticks(10);
15111 if (gridData.length > tickNum) {
15112 gridData = gridData.filter((d) => String(d).indexOf(".") < 0);
15113 }
15114 }
15115 return gridData;
15116 },
15117 getGridFilterToRemove(params) {
15118 return params ? (line) => {
15119 let found = false;
15120 (isArray(params) ? params.concat() : [params]).forEach((param) => {
15121 if ("value" in param && line.value === param.value || "class" in param && line.class === param.class) {
15122 found = true;
15123 }
15124 });
15125 return found;
15126 } : () => true;
15127 },
15128 removeGridLines(params, forX) {
15129 const $$ = this;
15130 const { config, $T } = $$;
15131 const toRemove = $$.getGridFilterToRemove(params);
15132 const toShow = (line) => !toRemove(line);
15133 const classLines = forX ? $GRID.xgridLines : $GRID.ygridLines;
15134 const classLine = forX ? $GRID.xgridLine : $GRID.ygridLine;
15135 $T($$.$el.main.select(`.${classLines}`).selectAll(`.${classLine}`).filter(toRemove)).style("opacity", "0").remove();
15136 const gridLines = `grid_${forX ? "x" : "y"}_lines`;
15137 config[gridLines] = config[gridLines].filter(toShow);
15138 }
15139});
15140
15141;// ./src/ChartInternal/internals/region.ts
15142
15143
15144
15145/* harmony default export */ var region = ({
15146 initRegion() {
15147 const $$ = this;
15148 const { $el } = $$;
15149 $el.region.main = $el.main.insert("g", ":first-child").attr("clip-path", $$.state.clip.path).attr("class", $REGION.regions);
15150 },
15151 updateRegion() {
15152 const $$ = this;
15153 const { config, $el: { region }, $T } = $$;
15154 if (!region.main) {
15155 $$.initRegion();
15156 }
15157 region.main.style("visibility", $$.hasArcType() ? "hidden" : null);
15158 const regions = region.main.selectAll(`.${$REGION.region}`).data(config.regions);
15159 $T(regions.exit()).style("opacity", "0").remove();
15160 const regionsEnter = regions.enter().append("g");
15161 regionsEnter.append("rect").style("fill-opacity", "0");
15162 region.list = regionsEnter.merge(regions).attr("class", $$.classRegion.bind($$));
15163 region.list.each(function(d) {
15164 var _a;
15165 const g = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
15166 if (g.select("text").empty() && ((_a = d.label) == null ? void 0 : _a.text)) {
15167 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).append("text").style("opacity", "0");
15168 }
15169 });
15170 },
15171 redrawRegion(withTransition) {
15172 const $$ = this;
15173 const { $el: { region }, $T } = $$;
15174 let regions = region.list.select("rect");
15175 let label = region.list.selectAll("text");
15176 regions = $T(regions, withTransition).attr("x", $$.regionX.bind($$)).attr("y", $$.regionY.bind($$)).attr("width", $$.regionWidth.bind($$)).attr("height", $$.regionHeight.bind($$));
15177 label = $T(label, withTransition).attr("transform", (d) => {
15178 var _a;
15179 const { x = 0, y = 0, rotated = false } = (_a = d.label) != null ? _a : {};
15180 return `translate(${$$.regionX.bind($$)(d) + x}, ${$$.regionY.bind($$)(d) + y})${rotated ? ` rotate(-90)` : ``}`;
15181 }).attr("text-anchor", (d) => {
15182 var _a;
15183 return ((_a = d.label) == null ? void 0 : _a.rotated) ? "end" : null;
15184 }).attr("dy", "1em").style("fill", (d) => {
15185 var _a, _b;
15186 return (_b = (_a = d.label) == null ? void 0 : _a.color) != null ? _b : null;
15187 }).text((d) => {
15188 var _a;
15189 return (_a = d.label) == null ? void 0 : _a.text;
15190 });
15191 return [
15192 regions.style("fill-opacity", (d) => isValue(d.opacity) ? d.opacity : null).on("end", function() {
15193 (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this.parentNode).selectAll("rect:not([x])").remove();
15194 }),
15195 label.style("opacity", null)
15196 ];
15197 },
15198 getRegionXY(type, d) {
15199 const $$ = this;
15200 const { config, scale } = $$;
15201 const isRotated = config.axis_rotated;
15202 const isX = type === "x";
15203 let key = "start";
15204 let currScale;
15205 let pos = 0;
15206 if (d.axis === "y" || d.axis === "y2") {
15207 if (!isX) {
15208 key = "end";
15209 }
15210 if ((isX ? isRotated : !isRotated) && key in d) {
15211 currScale = scale[d.axis];
15212 pos = currScale(d[key]);
15213 }
15214 } else if ((isX ? !isRotated : isRotated) && key in d) {
15215 currScale = scale.zoom || scale.x;
15216 pos = currScale($$.axis.isTimeSeries() ? parseDate.call($$, d[key]) : d[key]);
15217 }
15218 return pos;
15219 },
15220 regionX(d) {
15221 return this.getRegionXY("x", d);
15222 },
15223 regionY(d) {
15224 return this.getRegionXY("y", d);
15225 },
15226 getRegionSize(type, d) {
15227 const $$ = this;
15228 const { config, scale, state } = $$;
15229 const isRotated = config.axis_rotated;
15230 const isWidth = type === "width";
15231 const start = $$[isWidth ? "regionX" : "regionY"](d);
15232 let currScale;
15233 let key = "end";
15234 let end = state[type];
15235 if (d.axis === "y" || d.axis === "y2") {
15236 if (!isWidth) {
15237 key = "start";
15238 }
15239 if ((isWidth ? isRotated : !isRotated) && key in d) {
15240 currScale = scale[d.axis];
15241 end = currScale(d[key]);
15242 }
15243 } else if ((isWidth ? !isRotated : isRotated) && key in d) {
15244 currScale = scale.zoom || scale.x;
15245 end = currScale($$.axis.isTimeSeries() ? parseDate.call($$, d[key]) : d[key]);
15246 }
15247 return end < start ? 0 : end - start;
15248 },
15249 regionWidth(d) {
15250 return this.getRegionSize("width", d);
15251 },
15252 regionHeight(d) {
15253 return this.getRegionSize("height", d);
15254 },
15255 isRegionOnX(d) {
15256 return !d.axis || d.axis === "x";
15257 }
15258});
15259
15260;// ./src/ChartInternal/internals/size.axis.ts
15261
15262/* harmony default export */ var size_axis = ({
15263 /**
15264 * Get Axis size according its position
15265 * @param {string} id Axis id value - x, y or y2
15266 * @returns {number} size Axis size value
15267 * @private
15268 */
15269 getAxisSize(id) {
15270 const $$ = this;
15271 const isRotated = $$.config.axis_rotated;
15272 return isRotated && id === "x" || !isRotated && /y2?/.test(id) ? $$.getAxisWidthByAxisId(id, true) : $$.getHorizontalAxisHeight(id);
15273 },
15274 getAxisWidthByAxisId(id, withoutRecompute) {
15275 var _a, _b;
15276 const $$ = this;
15277 if ($$.axis) {
15278 const position = (_a = $$.axis) == null ? void 0 : _a.getLabelPositionById(id);
15279 const { width } = $$.axis.getMaxTickSize(id, withoutRecompute);
15280 const gap = width === 0 ? 0.5 : 0;
15281 return width + (((_b = $$.config.padding) == null ? void 0 : _b.mode) === "fit" ? position.isInner ? 10 + gap : 10 : position.isInner ? 20 + gap : 40);
15282 } else {
15283 return 40;
15284 }
15285 },
15286 getHorizontalAxisHeight(id) {
15287 var _a, _b;
15288 const $$ = this;
15289 const { config, state } = $$;
15290 const { rotatedPadding, isLegendRight, isLegendInset } = state;
15291 const isRotated = config.axis_rotated;
15292 const isFitPadding = ((_a = config.padding) == null ? void 0 : _a.mode) === "fit";
15293 const isInner = config[`axis_${id}_inner`];
15294 const hasLabelText = config[`axis_${id}_label`].text;
15295 const defaultHeight = 13;
15296 let h = ((_b = config.padding) == null ? void 0 : _b.mode) === "fit" ? isInner && !hasLabelText ? id === "y" ? 1 : 0 : 20 : 30;
15297 if (id === "x" && !config.axis_x_show) {
15298 return 8;
15299 }
15300 if (id === "x" && isNumber(config.axis_x_height)) {
15301 return config.axis_x_height;
15302 }
15303 if (id === "y" && !config.axis_y_show) {
15304 return config.legend_show && !isLegendRight && !isLegendInset ? 10 : 1;
15305 }
15306 if (id === "y2" && !config.axis_y2_show) {
15307 return isFitPadding ? 0 : rotatedPadding.top;
15308 }
15309 const maxtickSize = $$.axis.getMaxTickSize(id);
15310 const isXAxisTickRotated = Math.abs(config.axis_x_tick_rotate) > 0 && (!config.axis_x_tick_autorotate || $$.needToRotateXAxisTickTexts());
15311 if ((config.axis_x_tick_multiline || isXAxisTickRotated) && maxtickSize.height > defaultHeight) {
15312 h += maxtickSize.height - defaultHeight;
15313 }
15314 return h + ($$.axis.getLabelPositionById(id).isInner ? 0 : 10) + (id === "y2" && !isRotated ? -10 : 0);
15315 },
15316 getEventRectWidth() {
15317 const $$ = this;
15318 const { config, axis } = $$;
15319 const isInverted = config.axis_x_inverted;
15320 const tickInterval = axis.x.tickInterval();
15321 return Math.max(0, isInverted ? Math.abs(tickInterval) : tickInterval);
15322 },
15323 /**
15324 * Get axis tick test rotate value
15325 * @param {string} id Axis id
15326 * @returns {number} rotate value
15327 * @private
15328 */
15329 getAxisTickRotate(id) {
15330 const $$ = this;
15331 const { axis, config, state, $el } = $$;
15332 let rotate = config[`axis_${id}_tick_rotate`];
15333 if (id === "x") {
15334 const allowedXAxisTypes = axis.isCategorized() || axis.isTimeSeries();
15335 if (config.axis_x_tick_fit && allowedXAxisTypes) {
15336 const xTickCount = config.axis_x_tick_count;
15337 const currentXTicksLength = state.current.maxTickSize.x.ticks.length;
15338 let tickCount = 0;
15339 if (xTickCount) {
15340 tickCount = xTickCount > currentXTicksLength ? currentXTicksLength : xTickCount;
15341 } else if (currentXTicksLength) {
15342 tickCount = currentXTicksLength;
15343 }
15344 if (tickCount !== state.axis.x.tickCount) {
15345 const { targets } = $$.data;
15346 state.axis.x.padding = $$.getXDomainPadding([
15347 $$.getXDomainMinMax(targets, "min"),
15348 $$.getXDomainMinMax(targets, "max")
15349 ], tickCount);
15350 }
15351 state.axis.x.tickCount = tickCount;
15352 }
15353 if ($el.svg && config.axis_x_tick_autorotate && config.axis_x_tick_fit && !config.axis_x_tick_multiline && !config.axis_x_tick_culling && allowedXAxisTypes) {
15354 rotate = $$.needToRotateXAxisTickTexts() ? config.axis_x_tick_rotate : 0;
15355 }
15356 }
15357 return rotate;
15358 },
15359 /**
15360 * Check weather axis tick text needs to be rotated
15361 * @returns {boolean}
15362 * @private
15363 */
15364 needToRotateXAxisTickTexts() {
15365 const $$ = this;
15366 const { state: { axis, current, isLegendRight, legendItemWidth } } = $$;
15367 const legendWidth = isLegendRight && legendItemWidth;
15368 const xAxisLength = current.width - legendWidth - $$.getCurrentPaddingByDirection("left") - $$.getCurrentPaddingByDirection("right");
15369 const tickCountWithPadding = axis.x.tickCount + axis.x.padding.left + axis.x.padding.right;
15370 const { width } = $$.axis.getMaxTickSize("x");
15371 const tickLength = tickCountWithPadding ? xAxisLength / tickCountWithPadding : 0;
15372 return width > tickLength;
15373 }
15374});
15375
15376;// ./src/config/Options/axis/x.ts
15377/* harmony default export */ var axis_x = ({
15378 /**
15379 * Set clip-path attribute for x axis element
15380 * @name axis․x․clipPath
15381 * @memberof Options
15382 * @type {boolean}
15383 * @default true
15384 * @see [Demo]()
15385 * @example
15386 * // don't set 'clip-path' attribute
15387 * clipPath: false
15388 */
15389 axis_x_clipPath: true,
15390 /**
15391 * Show or hide x axis.
15392 * @name axis․x․show
15393 * @memberof Options
15394 * @type {boolean}
15395 * @default true
15396 * @example
15397 * axis: {
15398 * x: {
15399 * show: false
15400 * }
15401 * }
15402 */
15403 axis_x_show: true,
15404 /**
15405 * Force the x axis to interact as single rather than multiple x axes.
15406 * - **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:
15407 * - for `bubble` & `scatter` type
15408 * - when `data.xs` is set
15409 * - when `tooltip.grouped=false` is set
15410 * - `tooltip.grouped` options will take precedence over `axis.forceSingleX` option.
15411 * @name axis․x․forceAsSingle
15412 * @memberof Options
15413 * @type {boolean}
15414 * @default false
15415 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.ForceAsSingle)
15416 * @example
15417 * axis: {
15418 * x: {
15419 * // will work as single x axis
15420 * forceAsSingle: true
15421 * }
15422 * }
15423 */
15424 axis_x_forceAsSingle: false,
15425 /**
15426 * Set type of x axis.<br><br>
15427 * **Available Values:**
15428 * - category
15429 * - indexed
15430 * - log
15431 * - timeseries
15432 *
15433 * **NOTE:**<br>
15434 * - **log** type:
15435 * - the x values specified by [`data.x`](#.data%25E2%2580%25A4x)(or by any equivalent option), must be exclusively-positive.
15436 * - x axis min value should be >= 0.
15437 * - for 'category' type, `data.xs` option isn't supported.
15438 * @name axis․x․type
15439 * @memberof Options
15440 * @type {string}
15441 * @default indexed
15442 * @see [Demo: indexed](https://naver.github.io/billboard.js/demo/#Chart.AreaChart)
15443 * @see [Demo: timeseries](https://naver.github.io/billboard.js/demo/#Chart.TimeseriesChart)
15444 * @see [Demo: category](https://naver.github.io/billboard.js/demo/#Data.CategoryData)
15445 * @see [Demo: log](https://naver.github.io/billboard.js/demo/#Axis.LogScales)
15446 * @example
15447 * axis: {
15448 * x: {
15449 * type: "timeseries"
15450 * }
15451 * }
15452 */
15453 axis_x_type: "indexed",
15454 /**
15455 * Set how to treat the timezone of x values.<br>
15456 * If true, treat x value as localtime. If false, convert to UTC internally.
15457 * @name axis․x․localtime
15458 * @memberof Options
15459 * @type {boolean}
15460 * @default true
15461 * @example
15462 * axis: {
15463 * x: {
15464 * localtime: false
15465 * }
15466 * }
15467 */
15468 axis_x_localtime: true,
15469 /**
15470 * Set category names on category axis.
15471 * 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.
15472 * @name axis․x․categories
15473 * @memberof Options
15474 * @type {Array}
15475 * @default []
15476 * @example
15477 * axis: {
15478 * x: {
15479 * categories: ["Category 1", "Category 2", ...]
15480 * }
15481 * }
15482 */
15483 axis_x_categories: [],
15484 /**
15485 * centerize ticks on category axis.
15486 * @name axis․x․tick․centered
15487 * @memberof Options
15488 * @type {boolean}
15489 * @default false
15490 * @example
15491 * axis: {
15492 * x: {
15493 * tick: {
15494 * centered: true
15495 * }
15496 * }
15497 * }
15498 */
15499 axis_x_tick_centered: false,
15500 /**
15501 * A function to format tick value. Format string is also available for timeseries data.
15502 * @name axis․x․tick․format
15503 * @memberof Options
15504 * @type {Function|string}
15505 * @default undefined
15506 * @see [D3's time specifier](https://d3js.org/d3-time-format#locale_format)
15507 * @example
15508 * axis: {
15509 * x: {
15510 * tick: {
15511 * // for timeseries, a 'datetime' object is given as parameter
15512 * format: function(x) {
15513 * return x.getFullYear();
15514 * }
15515 *
15516 * // for category, index(Number) and categoryName(String) are given as parameter
15517 * format: function(index, categoryName) {
15518 * return categoryName.substr(0, 10);
15519 * },
15520 *
15521 * // for timeseries format specifier
15522 * format: "%Y-%m-%d %H:%M:%S"
15523 * }
15524 * }
15525 * }
15526 */
15527 axis_x_tick_format: void 0,
15528 /**
15529 * Setting for culling ticks.
15530 * - `true`: the ticks will be culled, then only limited tick text will be shown.<br>
15531 * This option does not hide the tick lines by default, if want to hide tick lines, set `axis.x.tick.culling.lines=false`.
15532 * - `false`: all of ticks will be shown.<br><br>
15533 * The number of ticks to be shown can be chaned by `axis.x.tick.culling.max`.
15534 * @name axis․x․tick․culling
15535 * @memberof Options
15536 * @type {boolean}
15537 * @default
15538 * `true` for indexed axis and timeseries axis, `false` for category axis
15539 * @example
15540 * axis: {
15541 * x: {
15542 * tick: {
15543 * culling: false
15544 * }
15545 * }
15546 * }
15547 */
15548 axis_x_tick_culling: {},
15549 /**
15550 * The number of tick texts will be adjusted to less than this value.
15551 * @name axis․x․tick․culling․max
15552 * @memberof Options
15553 * @type {number}
15554 * @default 10
15555 * @example
15556 * axis: {
15557 * x: {
15558 * tick: {
15559 * culling: {
15560 * max: 5
15561 * }
15562 * }
15563 * }
15564 * }
15565 */
15566 axis_x_tick_culling_max: 10,
15567 /**
15568 * Control visibility of tick lines within culling option, along with tick text.
15569 * @name axis․x․tick․culling․lines
15570 * @memberof Options
15571 * @type {boolean}
15572 * @default true
15573 * @example
15574 * axis: {
15575 * x: {
15576 * tick: {
15577 * culling: {
15578 * lines: false,
15579 * }
15580 * }
15581 * }
15582 * }
15583 */
15584 axis_x_tick_culling_lines: true,
15585 /**
15586 * The number of x axis ticks to show.<br><br>
15587 * 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).
15588 * @name axis․x․tick․count
15589 * @memberof Options
15590 * @type {number}
15591 * @default undefined
15592 * @example
15593 * axis: {
15594 * x: {
15595 * tick: {
15596 * count: 5
15597 * }
15598 * }
15599 * }
15600 */
15601 axis_x_tick_count: void 0,
15602 /**
15603 * Show or hide x axis tick line.
15604 * @name axis․x․tick․show
15605 * @memberof Options
15606 * @type {boolean}
15607 * @default true
15608 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
15609 * @example
15610 * axis: {
15611 * x: {
15612 * tick: {
15613 * show: false
15614 * }
15615 * }
15616 * }
15617 */
15618 axis_x_tick_show: true,
15619 /**
15620 * Show or hide x axis tick text.
15621 * @name axis․x․tick․text․show
15622 * @memberof Options
15623 * @type {boolean}
15624 * @default true
15625 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
15626 * @example
15627 * axis: {
15628 * x: {
15629 * tick: {
15630 * text: {
15631 * show: false
15632 * }
15633 * }
15634 * }
15635 * }
15636 */
15637 axis_x_tick_text_show: true,
15638 /**
15639 * Set the first/last axis tick text to be positioned inside of the chart on non-rotated axis.
15640 * @name axis․x․tick․text․inner
15641 * @memberof Options
15642 * @type {boolean|object}
15643 * @default false
15644 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickInner)
15645 * @example
15646 * axis: {
15647 * x: {
15648 * tick: {
15649 * text: {
15650 * inner: true,
15651 *
15652 * // or specify each position of the first and last tick text
15653 * inner: {
15654 * first: true,
15655 * last: true
15656 * }
15657 * }
15658 * }
15659 * }
15660 * }
15661 */
15662 axis_x_tick_text_inner: false,
15663 /**
15664 * Set the x Axis tick text's position relatively its original position
15665 * @name axis․x․tick․text․position
15666 * @memberof Options
15667 * @type {object}
15668 * @default {x: 0, y:0}
15669 * @example
15670 * axis: {
15671 * x: {
15672 * tick: {
15673 * text: {
15674 * position: {
15675 * x: 10,
15676 * y: 10
15677 * }
15678 * }
15679 * }
15680 * }
15681 * }
15682 */
15683 axis_x_tick_text_position: { x: 0, y: 0 },
15684 /**
15685 * Fit x axis ticks.
15686 * - **true**: ticks will be shown according to x value of the data points.
15687 * - **false**: ticks will be shown as to have same intervals.
15688 * @name axis․x․tick․fit
15689 * @memberof Options
15690 * @type {boolean}
15691 * @default true
15692 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickFitting)
15693 * @see [Demo: for timeseries zoom](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickTimeseries)
15694 * @example
15695 * axis: {
15696 * x: {
15697 * tick: {
15698 * fit: false
15699 * }
15700 * }
15701 * }
15702 */
15703 axis_x_tick_fit: true,
15704 /**
15705 * Set the x values of ticks manually.<br><br>
15706 * If this option is provided, the position of the ticks will be determined based on those values.<br>
15707 * This option works with `timeseries` data and the x values will be parsed accoding to the type of the value and data.xFormat option.
15708 * @name axis․x․tick․values
15709 * @memberof Options
15710 * @type {Array|Function}
15711 * @default null
15712 * @example
15713 * axis: {
15714 * x: {
15715 * tick: {
15716 * values: [1, 2, 4, 8, 16, 32, ...],
15717 *
15718 * // an Array value should be returned
15719 * values: function() {
15720 * return [ ... ];
15721 * }
15722 * }
15723 * }
15724 * }
15725 */
15726 axis_x_tick_values: null,
15727 /**
15728 * Rotate x axis tick text if there is not enough space for 'category' and 'timeseries' type axis.
15729 * - **NOTE:** The conditions where `autorotate` is enabled are:
15730 * - axis.x.type='category' or 'timeseries
15731 * - axis.x.tick.multiline=false
15732 * - axis.x.tick.culling=false
15733 * - axis.x.tick.fit=true
15734 * - **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
15735 * @name axis․x․tick․autorotate
15736 * @memberof Options
15737 * @type {boolean}
15738 * @default false
15739 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickAutorotate)
15740 * @example
15741 * axis: {
15742 * x: {
15743 * tick: {
15744 * rotate: 15,
15745 * autorotate: true,
15746 * multiline: false,
15747 * culling: false,
15748 * fit: true
15749 * },
15750 * clipPath: false
15751 * }
15752 * }
15753 */
15754 axis_x_tick_autorotate: false,
15755 /**
15756 * Rotate x axis tick text.
15757 * - If you set negative value, it will rotate to opposite direction.
15758 * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `false`.
15759 * - 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.
15760 * @name axis․x․tick․rotate
15761 * @memberof Options
15762 * @type {number}
15763 * @default 0
15764 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.RotateXAxisTickText)
15765 * @example
15766 * axis: {
15767 * x: {
15768 * tick: {
15769 * rotate: 60
15770 * }
15771 * }
15772 * }
15773 */
15774 axis_x_tick_rotate: 0,
15775 /**
15776 * Show x axis outer tick.
15777 * @name axis․x․tick․outer
15778 * @memberof Options
15779 * @type {boolean}
15780 * @default true
15781 * @example
15782 * axis: {
15783 * x: {
15784 * tick: {
15785 * outer: false
15786 * }
15787 * }
15788 * }
15789 */
15790 axis_x_tick_outer: true,
15791 /**
15792 * Set tick text to be multiline
15793 * - **NOTE:**
15794 * > When x tick text contains `\n`, it's used as line break and 'axis.x.tick.width' option is ignored.
15795 * @name axis․x․tick․multiline
15796 * @memberof Options
15797 * @type {boolean}
15798 * @default true
15799 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickMultiline)
15800 * @example
15801 * axis: {
15802 * x: {
15803 * tick: {
15804 * multiline: false
15805 * }
15806 * }
15807 * }
15808 * @example
15809 * // example of line break with '\n'
15810 * // In this case, 'axis.x.tick.width' is ignored
15811 * data: {
15812 * x: "x",
15813 * columns: [
15814 * ["x", "long\ntext", "Another\nLong\nText"],
15815 * ...
15816 * ],
15817 * }
15818 */
15819 axis_x_tick_multiline: true,
15820 /**
15821 * Set tick width
15822 * - **NOTE:**
15823 * > When x tick text contains `\n`, this option is ignored.
15824 * @name axis․x․tick․width
15825 * @memberof Options
15826 * @type {number}
15827 * @default null
15828 * @example
15829 * axis: {
15830 * x: {
15831 * tick: {
15832 * width: 50
15833 * }
15834 * }
15835 * }
15836 */
15837 axis_x_tick_width: null,
15838 /**
15839 * Set to display system tooltip(via `<title>` element) for tick text
15840 * - **NOTE:** Only available for category axis type (`axis.x.type='category'`)
15841 * @name axis․x․tick․tooltip
15842 * @memberof Options
15843 * @type {boolean}
15844 * @default false
15845 * @example
15846 * axis: {
15847 * x: {
15848 * tick: {
15849 * tooltip: true
15850 * }
15851 * }
15852 * }
15853 */
15854 axis_x_tick_tooltip: false,
15855 /**
15856 * Set max value of x axis range.
15857 * @name axis․x․max
15858 * @memberof Options
15859 * @property {number} max Set the max value
15860 * @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.
15861 * - **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`.
15862 * @property {number} [max.value] Set the max value
15863 * @example
15864 * axis: {
15865 * x: {
15866 * max: 100,
15867 *
15868 * max: {
15869 * // 'fit=true' will make x axis max to be limited as the bound data value max when 'max.value' is greater.
15870 * // - when bound data max is '10' and max.value: '100' ==> x axis max will be '10'
15871 * // - when bound data max is '1000' and max.value: '100' ==> x axis max will be '100'
15872 * fit: true,
15873 * value: 100
15874 * }
15875 * }
15876 * }
15877 */
15878 axis_x_max: void 0,
15879 /**
15880 * Set min value of x axis range.
15881 * @name axis․x․min
15882 * @memberof Options
15883 * @property {number} min Set the min value
15884 * @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.
15885 * - **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`.
15886 * @property {number} [min.value] Set the min value
15887 * @example
15888 * axis: {
15889 * x: {
15890 * min: -100,
15891 *
15892 * min: {
15893 * // 'fit=true' will make x axis min to be limited as the bound data value min when 'min.value' is lower.
15894 * // - when bound data min is '-10' and min.value: '-100' ==> x axis min will be '-10'
15895 * // - when bound data min is '-1000' and min.value: '-100' ==> x axis min will be '-100'
15896 * fit: true,
15897 * value: -100
15898 * }
15899 * }
15900 * }
15901 */
15902 axis_x_min: void 0,
15903 /**
15904 * Change the direction of x axis.<br><br>
15905 * If true set, the direction will be `right -> left`.
15906 * @name axis․x․inverted
15907 * @memberof Options
15908 * @type {boolean}
15909 * @default false
15910 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.InvertedAxis)
15911 * @example
15912 * axis: {
15913 * x: {
15914 * inverted: true
15915 * }
15916 * }
15917 */
15918 axis_x_inverted: false,
15919 /**
15920 * Set padding for x axis.<br><br>
15921 * If this option is set, the range of x axis will increase/decrease according to the values.
15922 * If no padding is needed in the rage of x axis, 0 should be set.
15923 * By default, left/right padding are set depending on x axis type or chart types.
15924 * - **NOTE:**
15925 * - The meaning of padding values, differs according axis types:<br>
15926 * - **category/indexed:** The unit of tick value
15927 * ex. the given value `1`, is same as the width of 1 tick width
15928 * - **timeseries:** Numeric time value
15929 * 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
15930 * - If want values to be treated as pixels, specify `unit:"px"`.
15931 * - The pixel value will be convered based on the scale values. Hence can not reflect accurate padding result.
15932 * @name axis․x․padding
15933 * @memberof Options
15934 * @type {object|number}
15935 * @default {}
15936 * @example
15937 * axis: {
15938 * x: {
15939 * padding: {
15940 * // when axis type is 'category'
15941 * left: 1, // set left padding width of equivalent value of a tick's width
15942 * right: 0.5 // set right padding width as half of equivalent value of tick's width
15943 *
15944 * // when axis type is 'timeseries'
15945 * left: 1000*60*60*24, // set left padding width of equivalent value of a day tick's width
15946 * right: 1000*60*60*12 // set right padding width as half of equivalent value of a day tick's width
15947 * },
15948 *
15949 * // or set both values at once.
15950 * padding: 10,
15951 *
15952 * // or set padding values as pixel unit.
15953 * padding: {
15954 * left: 100,
15955 * right: 50,
15956 * unit: "px"
15957 * },
15958 * }
15959 * }
15960 */
15961 axis_x_padding: {},
15962 /**
15963 * Set height of x axis.<br><br>
15964 * 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.
15965 * @name axis․x․height
15966 * @memberof Options
15967 * @type {number}
15968 * @default undefined
15969 * @example
15970 * axis: {
15971 * x: {
15972 * height: 20
15973 * }
15974 * }
15975 */
15976 axis_x_height: void 0,
15977 /**
15978 * Set extent for subchart and zoom(drag only). This can be an array or function that returns an array.
15979 * - **NOTE:** Specifying value, will limit the zoom scope selection within.
15980 * @name axis․x․extent
15981 * @memberof Options
15982 * @type {Array|Function}
15983 * @default undefined
15984 * @example
15985 * axis: {
15986 * x: {
15987 * // extent range as a pixel value
15988 * extent: [0, 200],
15989 *
15990 * // when axis is 'timeseries', parsable datetime string
15991 * extent: ["2019-03-01", "2019-03-05"],
15992 *
15993 * // return extent value
15994 * extent: function(domain, scale) {
15995 * var extent = domain.map(function(v) {
15996 * return scale(v);
15997 * });
15998 *
15999 * // it should return a format of array
16000 * // ex) [0, 584]
16001 * return extent;
16002 * }
16003 * }
16004 * }
16005 */
16006 axis_x_extent: void 0,
16007 /**
16008 * Set label on x axis.<br><br>
16009 * You can set x axis label and change its position by this option.
16010 * `string` and `object` can be passed and we can change the poisiton by passing object that has position key.<br>
16011 * Available position differs according to the axis direction (vertical or horizontal).
16012 * If string set, the position will be the default.
16013 *
16014 * - **If it's horizontal axis:**
16015 * - inner-right [default]
16016 * - inner-center
16017 * - inner-left
16018 * - outer-right
16019 * - outer-center
16020 * - outer-left
16021 * - **If it's vertical axis:**
16022 * - inner-top [default]
16023 * - inner-middle
16024 * - inner-bottom
16025 * - outer-top
16026 * - outer-middle
16027 * - outer-bottom
16028 * @name axis․x․label
16029 * @memberof Options
16030 * @type {string|object}
16031 * @default undefined
16032 * @example
16033 * axis: {
16034 * x: {
16035 * label: "Your X Axis"
16036 * }
16037 * }
16038 *
16039 * axis: {
16040 * x: {
16041 * label: {
16042 * text: "Your X Axis",
16043 * position: "outer-center"
16044 * }
16045 * }
16046 * }
16047 */
16048 axis_x_label: {},
16049 /**
16050 * Set additional axes for x Axis.
16051 * - **NOTE:** Axis' scale is based on x Axis value if domain option isn't set.
16052 *
16053 * Each axis object should consist with following options:
16054 *
16055 * | Name | Type | Default | Description |
16056 * | --- | --- | --- | --- |
16057 * | domain | Array | - | Set the domain value |
16058 * | tick.outer | boolean | true | Show outer tick |
16059 * | tick.format | Function | - | Set formatter for tick text |
16060 * | tick.count | Number | - | Set the number of y axis ticks |
16061 * | tick.values | Array | - | Set tick values manually |
16062 * @name axis․x․axes
16063 * @memberof Options
16064 * @type {Array}
16065 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)
16066 * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)
16067 * @example
16068 * x: {
16069 * axes: [
16070 * {
16071 * // if set, will not be correlated with the main x Axis domain value
16072 * domain: [0, 1000],
16073 * tick: {
16074 * outer: false,
16075 * format: function(x) {
16076 * return x + "%";
16077 * },
16078 * count: 2,
16079 * values: [10, 20, 30]
16080 * }
16081 * },
16082 * ...
16083 * ]
16084 * }
16085 */
16086 axis_x_axes: []
16087});
16088
16089;// ./src/config/Options/axis/y.ts
16090/* harmony default export */ var y = ({
16091 /**
16092 * Set clip-path attribute for y axis element
16093 * - **NOTE**: `clip-path` attribute for y Axis is set only when `axis.y.inner` option is true.
16094 * @name axis․y․clipPath
16095 * @memberof Options
16096 * @type {boolean}
16097 * @default true
16098 * @example
16099 * // don't set 'clip-path' attribute
16100 * clipPath: false
16101 */
16102 axis_y_clipPath: true,
16103 /**
16104 * Show or hide y axis.
16105 * @name axis․y․show
16106 * @memberof Options
16107 * @type {boolean}
16108 * @default true
16109 * @example
16110 * axis: {
16111 * y: {
16112 * show: false
16113 * }
16114 * }
16115 */
16116 axis_y_show: true,
16117 /**
16118 * Set type of y axis.<br><br>
16119 * **Available Values:**
16120 * - indexed
16121 * - log
16122 * - timeseries
16123 *
16124 * **NOTE:**<br>
16125 * - **log** type:
16126 * - the bound data values must be exclusively-positive.
16127 * - y axis min value should be >= 0.
16128 * - [`data.groups`](#.data%25E2%2580%25A4groups)(stacked data) option aren't supported.
16129 *
16130 * @name axis․y․type
16131 * @memberof Options
16132 * @type {string}
16133 * @default "indexed"
16134 * @see [Demo: log](https://naver.github.io/billboard.js/demo/#Axis.LogScales)
16135 * @example
16136 * axis: {
16137 * y: {
16138 * type: "log"
16139 * }
16140 * }
16141 */
16142 axis_y_type: "indexed",
16143 /**
16144 * Set max value of y axis.
16145 * - **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).
16146 * @name axis․y․max
16147 * @memberof Options
16148 * @type {number}
16149 * @default undefined
16150 * @example
16151 * axis: {
16152 * y: {
16153 * max: 1000
16154 * }
16155 * }
16156 */
16157 axis_y_max: void 0,
16158 /**
16159 * Set min value of y axis.
16160 * - **NOTE:**
16161 * 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).
16162 * @name axis․y․min
16163 * @memberof Options
16164 * @type {number}
16165 * @default undefined
16166 * @example
16167 * axis: {
16168 * y: {
16169 * min: 1000
16170 * }
16171 * }
16172 */
16173 axis_y_min: void 0,
16174 /**
16175 * Change the direction of y axis.<br><br>
16176 * If true set, the direction will be `top -> bottom`.
16177 * @name axis․y․inverted
16178 * @memberof Options
16179 * @type {boolean}
16180 * @default false
16181 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.InvertedAxis)
16182 * @example
16183 * axis: {
16184 * y: {
16185 * inverted: true
16186 * }
16187 * }
16188 */
16189 axis_y_inverted: false,
16190 /**
16191 * Set center value of y axis.
16192 * @name axis․y․center
16193 * @memberof Options
16194 * @type {number}
16195 * @default undefined
16196 * @example
16197 * axis: {
16198 * y: {
16199 * center: 0
16200 * }
16201 * }
16202 */
16203 axis_y_center: void 0,
16204 /**
16205 * Show y axis inside of the chart.
16206 * @name axis․y․inner
16207 * @memberof Options
16208 * @type {boolean}
16209 * @default false
16210 * @example
16211 * axis: {
16212 * y: {
16213 * inner: true
16214 * }
16215 * }
16216 */
16217 axis_y_inner: false,
16218 /**
16219 * Set label on y axis.<br><br>
16220 * 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).
16221 * @name axis․y․label
16222 * @memberof Options
16223 * @type {string|object}
16224 * @default {}
16225 * @see [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label) for position string value.
16226 * @example
16227 * axis: {
16228 * y: {
16229 * label: "Your Y Axis"
16230 * }
16231 * }
16232 *
16233 * axis: {
16234 * y: {
16235 * label: {
16236 * text: "Your Y Axis",
16237 * position: "outer-middle"
16238 * }
16239 * }
16240 * }
16241 */
16242 axis_y_label: {},
16243 /**
16244 * Set formatter for y axis tick text.<br><br>
16245 * This option accepts d3.format object as well as a function you define.
16246 * @name axis․y․tick․format
16247 * @memberof Options
16248 * @type {Function}
16249 * @default undefined
16250 * @example
16251 * axis: {
16252 * y: {
16253 * tick: {
16254 * format: function(x) {
16255 * return x.getFullYear();
16256 * }
16257 * }
16258 * }
16259 * }
16260 */
16261 axis_y_tick_format: void 0,
16262 /**
16263 * Setting for culling ticks.
16264 * - `true`: the ticks will be culled, then only limited tick text will be shown.<br>
16265 * This option does not hide the tick lines by default, if want to hide tick lines, set `axis.y.tick.culling.lines=false`.
16266 * - `false`: all of ticks will be shown.<br><br>
16267 * The number of ticks to be shown can be chaned by `axis.y.tick.culling.max`.
16268 * @name axis․y․tick․culling
16269 * @memberof Options
16270 * @type {boolean}
16271 * @default false
16272 * @example
16273 * axis: {
16274 * y: {
16275 * tick: {
16276 * culling: false
16277 * }
16278 * }
16279 * }
16280 */
16281 axis_y_tick_culling: false,
16282 /**
16283 * The number of tick texts will be adjusted to less than this value.
16284 * @name axis․y․tick․culling․max
16285 * @memberof Options
16286 * @type {number}
16287 * @default 5
16288 * @example
16289 * axis: {
16290 * y: {
16291 * tick: {
16292 * culling: {
16293 * max: 5
16294 * }
16295 * }
16296 * }
16297 * }
16298 */
16299 axis_y_tick_culling_max: 5,
16300 /**
16301 * Control visibility of tick lines within culling option, along with tick text.
16302 * @name axis․y․tick․culling․lines
16303 * @memberof Options
16304 * @type {boolean}
16305 * @default true
16306 * @example
16307 * axis: {
16308 * y: {
16309 * tick: {
16310 * culling: {
16311 * lines: false,
16312 * }
16313 * }
16314 * }
16315 * }
16316 */
16317 axis_y_tick_culling_lines: true,
16318 /**
16319 * Show y axis outer tick.
16320 * @name axis․y․tick․outer
16321 * @memberof Options
16322 * @type {boolean}
16323 * @default true
16324 * @example
16325 * axis: {
16326 * y: {
16327 * tick: {
16328 * outer: false
16329 * }
16330 * }
16331 * }
16332 */
16333 axis_y_tick_outer: true,
16334 /**
16335 * Set y axis tick values manually.
16336 * @name axis․y․tick․values
16337 * @memberof Options
16338 * @type {Array|Function}
16339 * @default null
16340 * @example
16341 * axis: {
16342 * y: {
16343 * tick: {
16344 * values: [100, 1000, 10000],
16345 *
16346 * // an Array value should be returned
16347 * values: function() {
16348 * return [ ... ];
16349 * }
16350 * }
16351 * }
16352 * }
16353 */
16354 axis_y_tick_values: null,
16355 /**
16356 * Rotate y axis tick text.
16357 * - If you set negative value, it will rotate to opposite direction.
16358 * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `true`.
16359 * @name axis․y․tick․rotate
16360 * @memberof Options
16361 * @type {number}
16362 * @default 0
16363 * @example
16364 * axis: {
16365 * y: {
16366 * tick: {
16367 * rotate: 60
16368 * }
16369 * }
16370 * }
16371 */
16372 axis_y_tick_rotate: 0,
16373 /**
16374 * Set the number of y axis ticks.<br><br>
16375 * - **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.
16376 * @name axis․y․tick․count
16377 * @memberof Options
16378 * @type {number}
16379 * @default undefined
16380 * @example
16381 * axis: {
16382 * y: {
16383 * tick: {
16384 * count: 5
16385 * }
16386 * }
16387 * }
16388 */
16389 axis_y_tick_count: void 0,
16390 /**
16391 * Show or hide y axis tick line.
16392 * @name axis․y․tick․show
16393 * @memberof Options
16394 * @type {boolean}
16395 * @default true
16396 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
16397 * @example
16398 * axis: {
16399 * y: {
16400 * tick: {
16401 * show: false
16402 * }
16403 * }
16404 * }
16405 */
16406 axis_y_tick_show: true,
16407 /**
16408 * Set axis tick step(interval) size.
16409 * - **NOTE:** Will be ignored if `axis.y.tick.count` or `axis.y.tick.values` options are set.
16410 * @name axis․y․tick․stepSize
16411 * @memberof Options
16412 * @type {number}
16413 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.StepSizeForYAxis)
16414 * @example
16415 * axis: {
16416 * y: {
16417 * tick: {
16418 * // tick value will step as indicated interval value.
16419 * // ex) 'stepSize=15' ==> [0, 15, 30, 45, 60]
16420 * stepSize: 15
16421 * }
16422 * }
16423 * }
16424 */
16425 axis_y_tick_stepSize: null,
16426 /**
16427 * Show or hide y axis tick text.
16428 * @name axis․y․tick․text․show
16429 * @memberof Options
16430 * @type {boolean}
16431 * @default true
16432 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
16433 * @example
16434 * axis: {
16435 * y: {
16436 * tick: {
16437 * text: {
16438 * show: false
16439 * }
16440 * }
16441 * }
16442 * }
16443 */
16444 axis_y_tick_text_show: true,
16445 /**
16446 * Set the y Axis tick text's position relatively its original position
16447 * @name axis․y․tick․text․position
16448 * @memberof Options
16449 * @type {object}
16450 * @default {x: 0, y:0}
16451 * @example
16452 * axis: {
16453 * y: {
16454 * tick: {
16455 * text: {
16456 * position: {
16457 * x: 10,
16458 * y: 10
16459 * }
16460 * }
16461 * }
16462 * }
16463 * }
16464 */
16465 axis_y_tick_text_position: { x: 0, y: 0 },
16466 /**
16467 * Set the number of y axis ticks.<br><br>
16468 * - **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.
16469 * @name axis․y․tick․time
16470 * @memberof Options
16471 * @private
16472 * @type {object}
16473 * @property {object} time time object
16474 * @property {Function} [time.value] D3's time interval function (https://github.com/d3/d3-time#intervals)
16475 * @example
16476 * axis: {
16477 * y: {
16478 * tick: {
16479 * time: {
16480 * // ticks at 15-minute intervals
16481 * // https://github.com/d3/d3-scale/blob/master/README.md#time_ticks
16482 * value: d3.timeMinute.every(15)
16483 * }
16484 * }
16485 * }
16486 * }
16487 */
16488 // @TODO: not fully implemented yet
16489 axis_y_tick_time_value: void 0,
16490 /**
16491 * Set padding for y axis.<br><br>
16492 * You can set padding for y axis to create more space on the edge of the axis.
16493 * This option accepts object and it can include top and bottom. top, bottom will be treated as pixels.
16494 *
16495 * - **NOTE:**
16496 * - Given values are translated relative to the y Axis domain value for padding
16497 * - For area and bar type charts, [area.zerobased](#.area) or [bar.zerobased](#.bar) options should be set to 'false` to get padded bottom.
16498 * @name axis․y․padding
16499 * @memberof Options
16500 * @type {object|number}
16501 * @default {}
16502 * @example
16503 * axis: {
16504 * y: {
16505 * padding: {
16506 * top: 0,
16507 * bottom: 0
16508 * },
16509 *
16510 * // or set both values at once.
16511 * padding: 10
16512 * }
16513 * }
16514 */
16515 axis_y_padding: {},
16516 /**
16517 * Set default range of y axis.<br><br>
16518 * This option set the default value for y axis when there is no data on init.
16519 * @name axis․y․default
16520 * @memberof Options
16521 * @type {Array}
16522 * @default undefined
16523 * @example
16524 * axis: {
16525 * y: {
16526 * default: [0, 1000]
16527 * }
16528 * }
16529 */
16530 axis_y_default: void 0,
16531 /**
16532 * Set additional axes for y Axis.
16533 * - **NOTE:** Axis' scale is based on y Axis value if domain option isn't set.
16534 *
16535 * Each axis object should consist with following options:
16536 *
16537 * | Name | Type | Default | Description |
16538 * | --- | --- | --- | --- |
16539 * | domain | Array | - | Set the domain value |
16540 * | tick.outer | boolean | true | Show outer tick |
16541 * | tick.format | Function | - | Set formatter for tick text |
16542 * | tick.count | Number | - | Set the number of y axis ticks |
16543 * | tick.values | Array | - | Set tick values manually |
16544 * @name axis․y․axes
16545 * @memberof Options
16546 * @type {Array}
16547 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)
16548 * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)
16549 * @example
16550 * y: {
16551 * axes: [
16552 * {
16553 * // if set, will not be correlated with the main y Axis domain value
16554 * domain: [0, 1000],
16555 * tick: {
16556 * outer: false,
16557 * format: function(x) {
16558 * return x + "%";
16559 * },
16560 * count: 2,
16561 * values: [10, 20, 30]
16562 * }
16563 * },
16564 * ...
16565 * ]
16566 * }
16567 */
16568 axis_y_axes: []
16569});
16570
16571;// ./src/config/Options/axis/y2.ts
16572/* harmony default export */ var y2 = ({
16573 /**
16574 * Show or hide y2 axis.
16575 * - **NOTE**:
16576 * - When set to `false` will not generate y2 axis node. In this case, all 'y2' axis related functionality won't work properly.
16577 * - If need to use 'y2' related options while y2 isn't visible, set the value `true` and control visibility by css display property.
16578 * @name axis․y2․show
16579 * @memberof Options
16580 * @type {boolean}
16581 * @default false
16582 * @example
16583 * axis: {
16584 * y2: {
16585 * show: true
16586 * }
16587 * }
16588 */
16589 axis_y2_show: false,
16590 /**
16591 * Set type of y2 axis.<br><br>
16592 * **Available Values:**
16593 * - indexed
16594 * - log
16595 * - timeseries
16596 *
16597 * **NOTE:**<br>
16598 * - **log** type:
16599 * - the bound data values must be exclusively-positive.
16600 * - y2 axis min value should be >= 0.
16601 * - [`data.groups`](#.data%25E2%2580%25A4groups)(stacked data) option aren't supported.
16602 *
16603 * @name axis․y2․type
16604 * @memberof Options
16605 * @type {string}
16606 * @default "indexed"
16607 * @see [Demo: log](https://naver.github.io/billboard.js/demo/#Axis.LogScales)
16608 * @example
16609 * axis: {
16610 * y2: {
16611 * type: "indexed"
16612 * }
16613 * }
16614 */
16615 axis_y2_type: "indexed",
16616 /**
16617 * Set max value of y2 axis.
16618 * @name axis․y2․max
16619 * @memberof Options
16620 * @type {number}
16621 * @default undefined
16622 * @example
16623 * axis: {
16624 * y2: {
16625 * max: 1000
16626 * }
16627 * }
16628 */
16629 axis_y2_max: void 0,
16630 /**
16631 * Set min value of y2 axis.
16632 * @name axis․y2․min
16633 * @memberof Options
16634 * @type {number}
16635 * @default undefined
16636 * @example
16637 * axis: {
16638 * y2: {
16639 * min: -1000
16640 * }
16641 * }
16642 */
16643 axis_y2_min: void 0,
16644 /**
16645 * Change the direction of y2 axis.<br><br>
16646 * If true set, the direction will be `top -> bottom`.
16647 * @name axis․y2․inverted
16648 * @memberof Options
16649 * @type {boolean}
16650 * @default false
16651 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.InvertedAxis)
16652 * @example
16653 * axis: {
16654 * y2: {
16655 * inverted: true
16656 * }
16657 * }
16658 */
16659 axis_y2_inverted: false,
16660 /**
16661 * Set center value of y2 axis.
16662 * @name axis․y2․center
16663 * @memberof Options
16664 * @type {number}
16665 * @default undefined
16666 * @example
16667 * axis: {
16668 * y2: {
16669 * center: 0
16670 * }
16671 * }
16672 */
16673 axis_y2_center: void 0,
16674 /**
16675 * Show y2 axis inside of the chart.
16676 * @name axis․y2․inner
16677 * @memberof Options
16678 * @type {boolean}
16679 * @default false
16680 * @example
16681 * axis: {
16682 * y2: {
16683 * inner: true
16684 * }
16685 * }
16686 */
16687 axis_y2_inner: false,
16688 /**
16689 * Set label on y2 axis.<br><br>
16690 * 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).
16691 * @name axis․y2․label
16692 * @memberof Options
16693 * @type {string|object}
16694 * @default {}
16695 * @see [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label) for position string value.
16696 * @example
16697 * axis: {
16698 * y2: {
16699 * label: "Your Y2 Axis"
16700 * }
16701 * }
16702 *
16703 * axis: {
16704 * y2: {
16705 * label: {
16706 * text: "Your Y2 Axis",
16707 * position: "outer-middle"
16708 * }
16709 * }
16710 * }
16711 */
16712 axis_y2_label: {},
16713 /**
16714 * Set formatter for y2 axis tick text.<br><br>
16715 * This option works in the same way as axis.y.format.
16716 * @name axis․y2․tick․format
16717 * @memberof Options
16718 * @type {Function}
16719 * @default undefined
16720 * @example
16721 * axis: {
16722 * y2: {
16723 * tick: {
16724 * format: d3.format("$,")
16725 * //or format: function(d) { return "$" + d; }
16726 * }
16727 * }
16728 * }
16729 */
16730 axis_y2_tick_format: void 0,
16731 /**
16732 * Setting for culling ticks.
16733 * - `true`: the ticks will be culled, then only limited tick text will be shown.<br>
16734 * This option does not hide the tick lines by default, if want to hide tick lines, set `axis.y2.tick.culling.lines=false`.
16735 * - `false`: all of ticks will be shown.<br><br>
16736 * The number of ticks to be shown can be chaned by `axis.y2.tick.culling.max`.
16737 * @name axis․y2․tick․culling
16738 * @memberof Options
16739 * @type {boolean}
16740 * @default false
16741 * @example
16742 * axis: {
16743 * y2: {
16744 * tick: {
16745 * culling: false
16746 * }
16747 * }
16748 * }
16749 */
16750 axis_y2_tick_culling: false,
16751 /**
16752 * The number of tick texts will be adjusted to less than this value.
16753 * @name axis․y2․tick․culling․max
16754 * @memberof Options
16755 * @type {number}
16756 * @default 5
16757 * @example
16758 * axis: {
16759 * y2: {
16760 * tick: {
16761 * culling: {
16762 * max: 5
16763 * }
16764 * }
16765 * }
16766 * }
16767 */
16768 axis_y2_tick_culling_max: 5,
16769 /**
16770 * Control visibility of tick lines within culling option, along with tick text.
16771 * @name axis․y2․tick․culling․lines
16772 * @memberof Options
16773 * @type {boolean}
16774 * @default true
16775 * @example
16776 * axis: {
16777 * y2: {
16778 * tick: {
16779 * culling: {
16780 * lines: false,
16781 * }
16782 * }
16783 * }
16784 * }
16785 */
16786 axis_y2_tick_culling_lines: true,
16787 /**
16788 * Show or hide y2 axis outer tick.
16789 * @name axis․y2․tick․outer
16790 * @memberof Options
16791 * @type {boolean}
16792 * @default true
16793 * @example
16794 * axis: {
16795 * y2: {
16796 * tick: {
16797 * outer: false
16798 * }
16799 * }
16800 * }
16801 */
16802 axis_y2_tick_outer: true,
16803 /**
16804 * Set y2 axis tick values manually.
16805 * @name axis․y2․tick․values
16806 * @memberof Options
16807 * @type {Array|Function}
16808 * @default null
16809 * @example
16810 * axis: {
16811 * y2: {
16812 * tick: {
16813 * values: [100, 1000, 10000],
16814 *
16815 * // an Array value should be returned
16816 * values: function() {
16817 * return [ ... ];
16818 * }
16819 * }
16820 * }
16821 * }
16822 */
16823 axis_y2_tick_values: null,
16824 /**
16825 * Rotate y2 axis tick text.
16826 * - If you set negative value, it will rotate to opposite direction.
16827 * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `true`.
16828 * @name axis․y2․tick․rotate
16829 * @memberof Options
16830 * @type {number}
16831 * @default 0
16832 * @example
16833 * axis: {
16834 * y2: {
16835 * tick: {
16836 * rotate: 60
16837 * }
16838 * }
16839 * }
16840 */
16841 axis_y2_tick_rotate: 0,
16842 /**
16843 * Set the number of y2 axis ticks.
16844 * - **NOTE:** This works in the same way as axis.y.tick.count.
16845 * @name axis․y2․tick․count
16846 * @memberof Options
16847 * @type {number}
16848 * @default undefined
16849 * @example
16850 * axis: {
16851 * y2: {
16852 * tick: {
16853 * count: 5
16854 * }
16855 * }
16856 * }
16857 */
16858 axis_y2_tick_count: void 0,
16859 /**
16860 * Show or hide y2 axis tick line.
16861 * @name axis․y2․tick․show
16862 * @memberof Options
16863 * @type {boolean}
16864 * @default true
16865 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
16866 * @example
16867 * axis: {
16868 * y2: {
16869 * tick: {
16870 * show: false
16871 * }
16872 * }
16873 * }
16874 */
16875 axis_y2_tick_show: true,
16876 /**
16877 * Set axis tick step(interval) size.
16878 * - **NOTE:** Will be ignored if `axis.y2.tick.count` or `axis.y2.tick.values` options are set.
16879 * @name axis․y2․tick․stepSize
16880 * @memberof Options
16881 * @type {number}
16882 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.StepSizeForYAxis)
16883 * @example
16884 * axis: {
16885 * y2: {
16886 * tick: {
16887 * // tick value will step as indicated interval value.
16888 * // ex) 'stepSize=15' ==> [0, 15, 30, 45, 60]
16889 * stepSize: 15
16890 * }
16891 * }
16892 * }
16893 */
16894 axis_y2_tick_stepSize: null,
16895 /**
16896 * Show or hide y2 axis tick text.
16897 * @name axis․y2․tick․text․show
16898 * @memberof Options
16899 * @type {boolean}
16900 * @default true
16901 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)
16902 * @example
16903 * axis: {
16904 * y2: {
16905 * tick: {
16906 * text: {
16907 * show: false
16908 * }
16909 * }
16910 * }
16911 * }
16912 */
16913 axis_y2_tick_text_show: true,
16914 /**
16915 * Set the y2 Axis tick text's position relatively its original position
16916 * @name axis․y2․tick․text․position
16917 * @memberof Options
16918 * @type {object}
16919 * @default {x: 0, y:0}
16920 * @example
16921 * axis: {
16922 * y2: {
16923 * tick: {
16924 * text: {
16925 * position: {
16926 * x: 10,
16927 * y: 10
16928 * }
16929 * }
16930 * }
16931 * }
16932 * }
16933 */
16934 axis_y2_tick_text_position: { x: 0, y: 0 },
16935 /**
16936 * Set padding for y2 axis.<br><br>
16937 * You can set padding for y2 axis to create more space on the edge of the axis.
16938 * This option accepts object and it can include top and bottom. top, bottom will be treated as pixels.
16939 *
16940 * - **NOTE:**
16941 * - Given values are translated relative to the y2 Axis domain value for padding
16942 * - For area and bar type charts, [area.zerobased](#.area) or [bar.zerobased](#.bar) options should be set to 'false` to get padded bottom.
16943 * @name axis․y2․padding
16944 * @memberof Options
16945 * @type {object|number}
16946 * @default {}
16947 * @example
16948 * axis: {
16949 * y2: {
16950 * padding: {
16951 * top: 100,
16952 * bottom: 100
16953 * }
16954 *
16955 * // or set both values at once.
16956 * padding: 10
16957 * }
16958 */
16959 axis_y2_padding: {},
16960 /**
16961 * Set default range of y2 axis.<br><br>
16962 * This option set the default value for y2 axis when there is no data on init.
16963 * @name axis․y2․default
16964 * @memberof Options
16965 * @type {Array}
16966 * @default undefined
16967 * @example
16968 * axis: {
16969 * y2: {
16970 * default: [0, 1000]
16971 * }
16972 * }
16973 */
16974 axis_y2_default: void 0,
16975 /**
16976 * Set additional axes for y2 Axis.
16977 * - **NOTE:** Axis' scale is based on y2 Axis value if domain option isn't set.
16978 *
16979 * Each axis object should consist with following options:
16980 *
16981 * | Name | Type | Default | Description |
16982 * | --- | --- | --- | --- |
16983 * | domain | Array | - | Set the domain value |
16984 * | tick.outer | boolean | true | Show outer tick |
16985 * | tick.format | Function | - | Set formatter for tick text |
16986 * | tick.count | Number | - | Set the number of y axis ticks |
16987 * | tick.values | Array | - | Set tick values manually |
16988 * @name axis․y2․axes
16989 * @memberof Options
16990 * @type {Array}
16991 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)
16992 * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)
16993 * @example
16994 * y2: {
16995 * axes: [
16996 * {
16997 * // if set, will not be correlated with the main y2 Axis domain value
16998 * domain: [0, 1000],
16999 * tick: {
17000 * outer: false,
17001 * format: function(x) {
17002 * return x + "%";
17003 * },
17004 * count: 2,
17005 * values: [10, 20, 30]
17006 * }
17007 * },
17008 * ...
17009 * ]
17010 * }
17011 */
17012 axis_y2_axes: []
17013});
17014
17015;// ./src/config/Options/axis/axis.ts
17016var axis_defProp = Object.defineProperty;
17017var axis_getOwnPropSymbols = Object.getOwnPropertySymbols;
17018var axis_hasOwnProp = Object.prototype.hasOwnProperty;
17019var axis_propIsEnum = Object.prototype.propertyIsEnumerable;
17020var axis_defNormalProp = (obj, key, value) => key in obj ? axis_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17021var axis_spreadValues = (a, b) => {
17022 for (var prop in b || (b = {}))
17023 if (axis_hasOwnProp.call(b, prop))
17024 axis_defNormalProp(a, prop, b[prop]);
17025 if (axis_getOwnPropSymbols)
17026 for (var prop of axis_getOwnPropSymbols(b)) {
17027 if (axis_propIsEnum.call(b, prop))
17028 axis_defNormalProp(a, prop, b[prop]);
17029 }
17030 return a;
17031};
17032
17033
17034
17035/* harmony default export */ var axis_axis = (axis_spreadValues(axis_spreadValues(axis_spreadValues({
17036 /**
17037 * Setup the way to evaluate tick text size.
17038 * - **NOTE:**
17039 * - Setting `false` or custom evaluator, highly recommended to memoize evaluated text dimension value to not degrade performance.
17040 * @name axis․evalTextSize
17041 * @memberof Options
17042 * @type {boolean|Function}
17043 * @default true
17044 * @example
17045 * axis: {
17046 * // will evaluate getting text size every time.
17047 * evalTextSize: false.
17048 *
17049 * // set a custom evaluator
17050 * evalTextSize: function(textElement) {
17051 * // set some character to be evaluated
17052 * text.textContent = "0";
17053 *
17054 * // get the size
17055 * const box = text.getBBox();
17056 *
17057 * // clear text
17058 * text.textContent = "";
17059 *
17060 * return { w: 7, h: 12};
17061 * }
17062 * }
17063 */
17064 axis_evalTextSize: true,
17065 /**
17066 * Switch x and y axis position.
17067 * @name axis․rotated
17068 * @memberof Options
17069 * @type {boolean}
17070 * @default false
17071 * @example
17072 * axis: {
17073 * rotated: true
17074 * }
17075 */
17076 axis_rotated: false,
17077 /**
17078 * Set axis tooltip.
17079 * - **NOTE:**
17080 * - When enabled, will disable default focus grid line.
17081 * - For `timeseries` x Axis, tootlip will be formatted using x Axis' tick format.
17082 * - For `category` x Axis, tootlip will be displaying scales' value text.
17083 * @name axis․tooltip
17084 * @memberof Options
17085 * @type {boolean}
17086 * @default false
17087 * @property {object} axis Axis object
17088 * @property {boolean} [axis.tooltip=false] Show tooltip or not.
17089 * @property {string|object} [axis.tooltip.backgroundColor] Set axis tooltip text background colors.
17090 * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.AxisTooltip)
17091 * @example
17092 * axis: {
17093 * tooltip: true, // default background color is
17094 *
17095 * // set backgound color for axis tooltip texts
17096 * tooltip: {
17097 * backgroundColor: "red",
17098 *
17099 * // set differenct backround colors per axes
17100 * // NOTE: In this case, only specified axes tooltip will appear.
17101 * backgroundColor: {
17102 * x: "green",
17103 * y: "yellow",
17104 * y2: "red"
17105 * }
17106 * }
17107 * }
17108 */
17109 axis_tooltip: false
17110}, axis_x), y), y2));
17111
17112;// ./src/config/Options/common/grid.ts
17113/* harmony default export */ var common_grid = ({
17114 /**
17115 * Set related options
17116 * @name grid
17117 * @memberof Options
17118 * @type {object}
17119 * @property {boolean} [front=false] Set 'grid & focus lines' to be positioned over grid lines and chart elements.
17120 * @property {object} x Grid x object
17121 * @property {boolean} [x.show=false] Show grids along x axis.
17122 * @property {Array} [x.lines=[]] Show additional grid lines along x axis.<br>
17123 * 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.
17124 * 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.
17125 * @property {object} y Grid y object
17126 * @property {boolean} [y.show=false] Show grids along x axis.
17127 * @property {Array} [y.lines=[]] Show additional grid lines along y axis.<br>
17128 * This option accepts array including object that has value, text, position and class.
17129 * @property {number} [y.ticks=undefined] Number of y grids to be shown.
17130 * @property {object} focus Grid focus object
17131 * @property {boolean} [focus.edge=false] Show edged focus grid line.<br>**NOTE:** Available when [`tooltip.grouped=false`](#.tooltip) option is set.
17132 * @property {boolean} [focus.show=true] Show grid line when focus.
17133 * @property {boolean} [focus.y=false] Show y coordinate focus grid line.<br>**NOTE:** Available when [`tooltip.grouped=false`](#.tooltip) option is set.
17134 * @property {object} lines Grid lines object
17135 * @property {boolean} [lines.front=true] Set grid lines to be positioned over chart elements.
17136 * @default undefined
17137 * @see [Demo](https://naver.github.io/billboard.js/demo/#Grid.GridLines)
17138 * @see [Demo: X Grid Lines](https://naver.github.io/billboard.js/demo/#Grid.OptionalXGridLines)
17139 * @see [Demo: Y Grid Lines](https://naver.github.io/billboard.js/demo/#Grid.OptionalYGridLines)
17140 * @example
17141 * grid: {
17142 * x: {
17143 * show: true,
17144 * lines: [
17145 * {value: 2, text: "Label on 2"},
17146 * {value: 5, text: "Label on 5", class: "label-5"},
17147 * {value: 6, text: "Label on 6", position: "start"}
17148 * ]
17149 * },
17150 * y: {
17151 * show: true,
17152 * lines: [
17153 * {value: 100, text: "Label on 100"},
17154 * {value: 200, text: "Label on 200", class: "label-200"},
17155 * {value: 300, text: "Label on 300", position: 'middle'}
17156 * ],
17157 * ticks: 5
17158 * },
17159 * front: true,
17160 * focus: {
17161 * show: false,
17162 *
17163 * // Below options are available when 'tooltip.grouped=false' option is set
17164 * edge: true,
17165 * y: true
17166 * },
17167 * lines: {
17168 * front: false
17169 * }
17170 * }
17171 */
17172 grid_x_show: false,
17173 grid_x_type: "tick",
17174 grid_x_lines: [],
17175 grid_y_show: false,
17176 grid_y_lines: [],
17177 grid_y_ticks: void 0,
17178 grid_focus_edge: false,
17179 grid_focus_show: true,
17180 grid_focus_y: false,
17181 grid_front: false,
17182 grid_lines_front: true
17183});
17184
17185;// ./src/config/Options/data/axis.ts
17186/* harmony default export */ var data_axis = ({
17187 /**
17188 * Specify the keys of the x values for each data.<br><br>
17189 * This option can be used if we want to show the data that has different x values.
17190 * @name data․xs
17191 * @memberof Options
17192 * @type {object}
17193 * @default {}
17194 * @example
17195 * data: {
17196 * xs: {
17197 * data1: "x1",
17198 * data2: "x2"
17199 * }
17200 * }
17201 */
17202 data_xs: {},
17203 /**
17204 * Set a format specifier to parse string specifed as x.
17205 * @name data․xFormat
17206 * @memberof Options
17207 * @type {string}
17208 * @default %Y-%m-%d
17209 * @example
17210 * data: {
17211 * x: "x",
17212 * columns: [
17213 * ["x", "01012019", "02012019", "03012019"],
17214 * ["data1", 30, 200, 100]
17215 * ],
17216 * // Format specifier to parse as datetime for given 'x' string value
17217 * xFormat: "%m%d%Y"
17218 * },
17219 * axis: {
17220 * x: {
17221 * type: "timeseries"
17222 * }
17223 * }
17224 * @see [D3's time specifier](https://d3js.org/d3-time-format#locale_format)
17225 */
17226 data_xFormat: "%Y-%m-%d",
17227 /**
17228 * Set localtime format to parse x axis.
17229 * @name data․xLocaltime
17230 * @memberof Options
17231 * @type {boolean}
17232 * @default true
17233 * @example
17234 * data: {
17235 * xLocaltime: false
17236 * }
17237 */
17238 data_xLocaltime: true,
17239 /**
17240 * Sort on x axis.
17241 * - **NOTE:** This option works for lineish(area/line/spline/step) types only.
17242 * @name data․xSort
17243 * @memberof Options
17244 * @type {boolean}
17245 * @default true
17246 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataXSort)
17247 * @example
17248 * data: {
17249 * xSort: false,
17250 * x: "x",
17251 * columns: [
17252 * // The line graph will start to be drawn following the x axis sequence
17253 * // Below data, wil start drawing x=1: 200, x=2: 300, x=3: 100
17254 * ["x", 3, 1, 2],
17255 * ["data1", 100, 200, 300]
17256 * ]
17257 * }
17258 */
17259 data_xSort: true,
17260 /**
17261 * Set y axis the data related to. y and y2 can be used.
17262 * - **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
17263 * @name data․axes
17264 * @memberof Options
17265 * @type {object}
17266 * @default {}
17267 * @example
17268 * data: {
17269 * axes: {
17270 * data1: "y",
17271 * data2: "y2"
17272 * }
17273 * }
17274 */
17275 data_axes: {},
17276 /**
17277 * Define regions for each data.<br>
17278 * The values must be an array for each data and it should include an object that has `start`, `end` and `style`.
17279 * - The object type should be as:
17280 * - start {number}: Start data point number. If not set, the start will be the first data point.
17281 * - [end] {number}: End data point number. If not set, the end will be the last data point.
17282 * - [style.dasharray="2 2"] {string}: The first number specifies a distance for the filled area, and the second a distance for the unfilled area.
17283 * - **NOTE:**
17284 * - Supports only line type.
17285 * - `start` and `end` values should be in the exact x value range.
17286 * - Dashes will be applied using `stroke-dasharray` css property when data doesn't contain nullish value(or nullish value with `line.connectNull=true` set).
17287 * - Dashes will be applied via path command when data contains nullish value.
17288 * @name data․regions
17289 * @memberof Options
17290 * @type {object}
17291 * @default {}
17292 * @example
17293 * data: {
17294 * regions: {
17295 * data1: [{
17296 * start: 1,
17297 * end: 2,
17298 * style: {
17299 * dasharray: "5 2"
17300 * }
17301 * }, {
17302 * start: 3
17303 * }],
17304 * ...
17305 * }
17306 * }
17307 */
17308 data_regions: {},
17309 /**
17310 * Set the stacking to be normalized
17311 * - **NOTE:**
17312 * - For stacking, '[data.groups](#.data%25E2%2580%25A4groups)' option should be set
17313 * - y Axis will be set in percentage value (0 ~ 100%)
17314 * - Must have postive values
17315 * @name data․stack․normalize
17316 * @memberof Options
17317 * @type {boolean}
17318 * @default false
17319 * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataStackNormalized)
17320 * @example
17321 * data: {
17322 * stack: {
17323 * normalize: true
17324 * }
17325 * }
17326 */
17327 data_stack_normalize: false
17328});
17329
17330;// ./src/config/resolver/axis.ts
17331
17332
17333
17334
17335
17336
17337
17338
17339
17340
17341
17342
17343
17344
17345
17346
17347
17348const api = [
17349 api_axis,
17350 api_category,
17351 flow,
17352 api_grid,
17353 group,
17354 api_regions,
17355 x
17356];
17357const internal = {
17358 axis: Axis,
17359 clip: clip,
17360 eventrect: eventrect,
17361 flow: interactions_flow,
17362 grid: internals_grid,
17363 region: region,
17364 sizeAxis: size_axis
17365};
17366const options = {
17367 optDataAxis: data_axis,
17368 optAxis: axis_axis,
17369 optGrid: common_grid
17370};
17371
17372// EXTERNAL MODULE: external {"commonjs":"d3-interpolate","commonjs2":"d3-interpolate","amd":"d3-interpolate","root":"d3"}
17373var external_commonjs_d3_interpolate_commonjs2_d3_interpolate_amd_d3_interpolate_root_d3_ = __webpack_require__(13);
17374;// ./src/ChartInternal/shape/arc.ts
17375var arc_defProp = Object.defineProperty;
17376var arc_defProps = Object.defineProperties;
17377var arc_getOwnPropDescs = Object.getOwnPropertyDescriptors;
17378var arc_getOwnPropSymbols = Object.getOwnPropertySymbols;
17379var arc_hasOwnProp = Object.prototype.hasOwnProperty;
17380var arc_propIsEnum = Object.prototype.propertyIsEnumerable;
17381var arc_defNormalProp = (obj, key, value) => key in obj ? arc_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17382var arc_spreadValues = (a, b) => {
17383 for (var prop in b || (b = {}))
17384 if (arc_hasOwnProp.call(b, prop))
17385 arc_defNormalProp(a, prop, b[prop]);
17386 if (arc_getOwnPropSymbols)
17387 for (var prop of arc_getOwnPropSymbols(b)) {
17388 if (arc_propIsEnum.call(b, prop))
17389 arc_defNormalProp(a, prop, b[prop]);
17390 }
17391 return a;
17392};
17393var arc_spreadProps = (a, b) => arc_defProps(a, arc_getOwnPropDescs(b));
17394
17395
17396
17397
17398
17399
17400function getRadiusFn(expandRate = 0) {
17401 const $$ = this;
17402 const { config, state } = $$;
17403 const hasMultiArcGauge = $$.hasMultiArcGauge();
17404 const singleArcWidth = state.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length;
17405 const expandWidth = expandRate ? Math.min(
17406 state.radiusExpanded * expandRate - state.radius,
17407 singleArcWidth * 0.8 - (1 - expandRate) * 100
17408 ) : 0;
17409 return {
17410 /**
17411 * Getter of arc innerRadius value
17412 * @param {IArcData} d Data object
17413 * @returns {number} innerRadius value
17414 * @private
17415 */
17416 inner(d) {
17417 const { innerRadius } = $$.getRadius(d);
17418 return hasMultiArcGauge ? state.radius - singleArcWidth * (d.index + 1) : isNumber(innerRadius) ? innerRadius : 0;
17419 },
17420 /**
17421 * Getter of arc outerRadius value
17422 * @param {IArcData} d Data object
17423 * @returns {number} outerRadius value
17424 * @private
17425 */
17426 outer(d) {
17427 const { outerRadius } = $$.getRadius(d);
17428 let radius;
17429 if (hasMultiArcGauge) {
17430 radius = state.radius - singleArcWidth * d.index + expandWidth;
17431 } else if ($$.hasType("polar") && !expandRate) {
17432 radius = $$.getPolarOuterRadius(d, outerRadius);
17433 } else {
17434 radius = outerRadius;
17435 if (expandRate) {
17436 let { radiusExpanded } = state;
17437 if (state.radius !== outerRadius) {
17438 radiusExpanded -= Math.abs(state.radius - outerRadius);
17439 }
17440 radius = radiusExpanded * expandRate;
17441 }
17442 }
17443 return radius;
17444 },
17445 /**
17446 * Getter of arc cornerRadius value
17447 * @param {IArcData} d Data object
17448 * @param {number} outerRadius outer radius value
17449 * @returns {number} cornerRadius value
17450 * @private
17451 */
17452 corner(d, outerRadius) {
17453 const {
17454 arc_cornerRadius_ratio: ratio = 0,
17455 arc_cornerRadius: cornerRadius = 0
17456 } = config;
17457 const { data: { id }, value } = d;
17458 let corner = 0;
17459 if (ratio) {
17460 corner = ratio * outerRadius;
17461 } else {
17462 corner = isNumber(cornerRadius) ? cornerRadius : cornerRadius.call($$.api, id, value, outerRadius);
17463 }
17464 return corner;
17465 }
17466 };
17467}
17468function getAttrTweenFn(fn) {
17469 return function(d) {
17470 const getAngleKeyValue = ({ startAngle = 0, endAngle = 0, padAngle = 0 }) => ({
17471 startAngle,
17472 endAngle,
17473 padAngle
17474 });
17475 const interpolate = (0,external_commonjs_d3_interpolate_commonjs2_d3_interpolate_amd_d3_interpolate_root_d3_.interpolate)(
17476 getAngleKeyValue(this._current),
17477 getAngleKeyValue(d)
17478 );
17479 this._current = d;
17480 return function(t) {
17481 const interpolated = interpolate(t);
17482 const { data, index, value } = d;
17483 return fn(arc_spreadProps(arc_spreadValues({}, interpolated), { data, index, value }));
17484 };
17485 };
17486}
17487/* harmony default export */ var arc = ({
17488 initPie() {
17489 const $$ = this;
17490 const { config } = $$;
17491 const dataType = config.data_type;
17492 const padding = config[`${dataType}_padding`];
17493 const startingAngle = config[`${dataType}_startingAngle`] || 0;
17494 const padAngle = (padding ? padding * 0.01 : config[`${dataType}_padAngle`]) || 0;
17495 $$.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) => {
17496 var _a, _b;
17497 return (_b = (_a = d.values) == null ? void 0 : _a.reduce((a, b) => a + b.value, 0)) != null ? _b : d;
17498 }).sort($$.getSortCompareFn.bind($$)(true));
17499 },
17500 updateRadius() {
17501 const $$ = this;
17502 const { config, state } = $$;
17503 const dataType = config.data_type;
17504 const padding = config[`${dataType}_padding`];
17505 const w = config.gauge_width || config.donut_width;
17506 const gaugeArcWidth = $$.filterTargetsToShow($$.data.targets).length * config.gauge_arcs_minWidth;
17507 state.radiusExpanded = Math.min(state.arcWidth, state.arcHeight) / 2 * ($$.hasMultiArcGauge() && config.gauge_label_show ? 0.85 : 1);
17508 state.radius = state.radiusExpanded * 0.95;
17509 state.innerRadiusRatio = w ? (state.radius - w) / state.radius : 0.6;
17510 state.gaugeArcWidth = w || (gaugeArcWidth <= state.radius - state.innerRadius ? state.radius - state.innerRadius : gaugeArcWidth <= state.radius ? gaugeArcWidth : state.radius);
17511 const innerRadius = config.pie_innerRadius || (padding ? padding * (state.innerRadiusRatio + 0.1) : 0);
17512 state.outerRadius = config.pie_outerRadius;
17513 state.innerRadius = $$.hasType("donut") || $$.hasType("gauge") ? state.radius * state.innerRadiusRatio : innerRadius;
17514 },
17515 /**
17516 * Get pie's inner & outer radius value
17517 * @param {object|undefined} d Data object
17518 * @returns {object}
17519 * @private
17520 */
17521 getRadius(d) {
17522 const $$ = this;
17523 const data = d == null ? void 0 : d.data;
17524 let { innerRadius, outerRadius } = $$.state;
17525 if (!isNumber(innerRadius) && data) {
17526 innerRadius = innerRadius[data.id] || 0;
17527 }
17528 if (isObject(outerRadius) && data && data.id in outerRadius) {
17529 outerRadius = outerRadius[data.id];
17530 } else if (!isNumber(outerRadius)) {
17531 outerRadius = $$.state.radius;
17532 }
17533 return { innerRadius, outerRadius };
17534 },
17535 updateArc() {
17536 const $$ = this;
17537 $$.updateRadius();
17538 $$.svgArc = $$.getSvgArc();
17539 $$.svgArcExpanded = $$.getSvgArcExpanded();
17540 },
17541 getArcLength() {
17542 const $$ = this;
17543 const { config } = $$;
17544 const arcLengthInPercent = config.gauge_arcLength * 3.6;
17545 let len = 2 * (arcLengthInPercent / 360);
17546 if (arcLengthInPercent < -360) {
17547 len = -2;
17548 } else if (arcLengthInPercent > 360) {
17549 len = 2;
17550 }
17551 return len * Math.PI;
17552 },
17553 getStartingAngle() {
17554 const $$ = this;
17555 const { config } = $$;
17556 const dataType = config.data_type;
17557 const isFullCircle = $$.hasType("gauge") ? config.gauge_fullCircle : false;
17558 const defaultStartAngle = -1 * Math.PI / 2;
17559 const defaultEndAngle = Math.PI / 2;
17560 let startAngle = config[`${dataType}_startingAngle`] || 0;
17561 if (!isFullCircle && startAngle <= defaultStartAngle) {
17562 startAngle = defaultStartAngle;
17563 } else if (!isFullCircle && startAngle >= defaultEndAngle) {
17564 startAngle = defaultEndAngle;
17565 } else if (startAngle > Math.PI || startAngle < -1 * Math.PI) {
17566 startAngle = Math.PI;
17567 }
17568 return startAngle;
17569 },
17570 /**
17571 * Update angle data
17572 * @param {object} dValue Data object
17573 * @param {boolean} forRange Weather is for ranged text option(arc.rangeText.values)
17574 * @returns {object|null} Updated angle data
17575 * @private
17576 */
17577 updateAngle(dValue, forRange = false) {
17578 var _a;
17579 const $$ = this;
17580 const { config, state } = $$;
17581 const hasGauge = forRange && $$.hasType("gauge");
17582 let { pie } = $$;
17583 let d = dValue;
17584 let found = false;
17585 if (!config) {
17586 return null;
17587 }
17588 const gStart = $$.getStartingAngle();
17589 const radius = config.gauge_fullCircle || forRange && !hasGauge ? $$.getArcLength() : gStart * -2;
17590 if (d.data && $$.isGaugeType(d.data) && !$$.hasMultiArcGauge()) {
17591 const { gauge_min: gMin, gauge_max: gMax } = config;
17592 const totalSum = $$.getTotalDataSum(state.rendered);
17593 const gEnd = radius * ((totalSum - gMin) / (gMax - gMin));
17594 pie = pie.startAngle(gStart).endAngle(gEnd + gStart);
17595 }
17596 if (forRange === false) {
17597 pie($$.filterTargetsToShow()).forEach((t, i) => {
17598 var _a2;
17599 if (!found && t.data.id === ((_a2 = d.data) == null ? void 0 : _a2.id)) {
17600 found = true;
17601 d = t;
17602 d.index = i;
17603 }
17604 });
17605 }
17606 if (isNaN(d.startAngle)) {
17607 d.startAngle = 0;
17608 }
17609 if (isNaN(d.endAngle)) {
17610 d.endAngle = d.startAngle;
17611 }
17612 if (forRange || d.data && (config.gauge_enforceMinMax || $$.hasMultiArcGauge())) {
17613 const { gauge_min: gMin, gauge_max: gMax } = config;
17614 const max = forRange && !hasGauge ? $$.getTotalDataSum(state.rendered) : gMax;
17615 const gTic = radius / (max - gMin);
17616 const value = (_a = d.value) != null ? _a : 0;
17617 const gValue = value < gMin ? 0 : value < max ? value - gMin : max - gMin;
17618 d.startAngle = gStart;
17619 d.endAngle = gStart + gTic * gValue;
17620 }
17621 return found || forRange ? d : null;
17622 },
17623 getSvgArc() {
17624 const $$ = this;
17625 const { inner, outer, corner } = getRadiusFn.call($$);
17626 const arc = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.arc)().innerRadius(inner).outerRadius(outer);
17627 const newArc = function(d, withoutUpdate) {
17628 var _a;
17629 let path = "M 0 0";
17630 if (d.value || d.data) {
17631 const data = withoutUpdate ? d : (_a = $$.updateAngle(d)) != null ? _a : null;
17632 if (data) {
17633 path = arc.cornerRadius(
17634 corner(data, outer(data))
17635 )(data);
17636 }
17637 }
17638 return path;
17639 };
17640 newArc.centroid = arc.centroid;
17641 return newArc;
17642 },
17643 /**
17644 * Get expanded arc path function
17645 * @param {number} rate Expand rate
17646 * @returns {Function} Expanded arc path getter function
17647 * @private
17648 */
17649 getSvgArcExpanded(rate = 1) {
17650 const $$ = this;
17651 const { inner, outer, corner } = getRadiusFn.call($$, rate);
17652 const arc = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.arc)().innerRadius(inner).outerRadius(outer);
17653 return (d) => {
17654 const updated = $$.updateAngle(d);
17655 const outerR = outer(updated);
17656 let cornerR = 0;
17657 if (updated) {
17658 cornerR = corner(updated, outerR);
17659 }
17660 return updated ? arc.cornerRadius(cornerR)(updated) : "M 0 0";
17661 };
17662 },
17663 getArc(d, withoutUpdate, force) {
17664 return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
17665 },
17666 /**
17667 * Render range value text
17668 * @private
17669 */
17670 redrawArcRangeText() {
17671 const $$ = this;
17672 const { config, $el: { arcs }, state, $T } = $$;
17673 const format = config.arc_rangeText_format;
17674 const fixed = $$.hasType("gauge") && config.arc_rangeText_fixed;
17675 let values = config.arc_rangeText_values;
17676 if (values == null ? void 0 : values.length) {
17677 const isPercent = config.arc_rangeText_unit === "%";
17678 const totalSum = $$.getTotalDataSum(state.rendered);
17679 if (isPercent) {
17680 values = values.map((v) => totalSum / 100 * v);
17681 }
17682 const pieData = $$.pie(values).map((d, i) => (d.index = i, d));
17683 let rangeText = arcs.selectAll(`.${$ARC.arcRange}`).data(values);
17684 rangeText.exit();
17685 rangeText = $T(rangeText.enter().append("text").attr("class", $ARC.arcRange).style("text-anchor", "middle").style("pointer-events", "none").style("opacity", "0").text((v) => {
17686 const range = isPercent ? v / totalSum * 100 : v;
17687 return isFunction(format) ? format(range) : `${range}${isPercent ? "%" : ""}`;
17688 }).merge(rangeText));
17689 if ((!state.rendered || state.rendered && !fixed) && totalSum > 0) {
17690 rangeText.attr("transform", (d, i) => $$.transformForArcLabel(pieData[i], true));
17691 }
17692 rangeText.style(
17693 "opacity",
17694 (d) => !fixed && (d > totalSum || totalSum === 0) ? "0" : null
17695 );
17696 }
17697 },
17698 /**
17699 * Set transform attributes to arc label text
17700 * @param {object} d Data object
17701 * @param {boolean} forRange Weather is for ranged text option(arc.rangeText.values)
17702 * @returns {string} Translate attribute string
17703 * @private
17704 */
17705 transformForArcLabel(d, forRange = false) {
17706 var _a, _b, _c;
17707 const $$ = this;
17708 const { config, state: { radiusExpanded } } = $$;
17709 const updated = $$.updateAngle(d, forRange);
17710 let translate = "";
17711 if (updated) {
17712 if (forRange || $$.hasMultiArcGauge()) {
17713 const y1 = Math.sin(updated.endAngle - Math.PI / 2);
17714 const rangeTextPosition = config.arc_rangeText_position;
17715 let x = Math.cos(updated.endAngle - Math.PI / 2) * (radiusExpanded + (forRange ? 5 : 25));
17716 let y = y1 * (radiusExpanded + 15 - Math.abs(y1 * 10)) + 3;
17717 if (forRange && rangeTextPosition) {
17718 const rangeValues = config.arc_rangeText_values;
17719 const pos = isFunction(rangeTextPosition) ? rangeTextPosition(rangeValues[d.index]) : rangeTextPosition;
17720 x += (_a = pos == null ? void 0 : pos.x) != null ? _a : 0;
17721 y += (_b = pos == null ? void 0 : pos.y) != null ? _b : 0;
17722 }
17723 translate = `translate(${x},${y})`;
17724 } else if (!$$.hasType("gauge") || $$.data.targets.length > 1) {
17725 let { outerRadius } = $$.getRadius(d);
17726 if ($$.hasType("polar")) {
17727 outerRadius = $$.getPolarOuterRadius(d, outerRadius);
17728 }
17729 const c = this.svgArc.centroid(updated);
17730 const [x, y] = c.map((v) => isNaN(v) ? 0 : v);
17731 const h = Math.sqrt(x * x + y * y);
17732 let ratio = (_c = ["donut", "gauge", "pie", "polar"].filter($$.hasType.bind($$)).map((v) => config[`${v}_label_ratio`])) == null ? void 0 : _c[0];
17733 if (ratio) {
17734 ratio = isFunction(ratio) ? ratio.bind($$.api)(d, outerRadius, h) : ratio;
17735 } else {
17736 ratio = outerRadius && (h ? (36 / outerRadius > 0.375 ? 1.175 - 36 / outerRadius : 0.8) * outerRadius / h : 0);
17737 }
17738 translate = `translate(${x * ratio},${y * ratio})`;
17739 }
17740 }
17741 return translate;
17742 },
17743 convertToArcData(d) {
17744 return this.addName({
17745 id: "data" in d ? d.data.id : d.id,
17746 value: d.value,
17747 ratio: this.getRatio("arc", d),
17748 index: d.index
17749 });
17750 },
17751 textForArcLabel(selection) {
17752 const $$ = this;
17753 const hasGauge = $$.hasType("gauge");
17754 if ($$.shouldShowArcLabel()) {
17755 selection.style("fill", $$.updateTextColor.bind($$)).attr("filter", (d) => $$.updateTextBGColor.bind($$)(d, $$.config.data_labels_backgroundColors)).each(function(d) {
17756 var _a;
17757 const node = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
17758 const updated = $$.updateAngle(d);
17759 const ratio = $$.getRatio("arc", updated);
17760 const isUnderThreshold = $$.meetsLabelThreshold(
17761 ratio,
17762 (_a = ["donut", "gauge", "pie", "polar"].filter($$.hasType.bind($$))) == null ? void 0 : _a[0]
17763 );
17764 if (isUnderThreshold) {
17765 const { value } = updated || d;
17766 const text = ($$.getArcLabelFormat() || $$.defaultArcValueFormat)(value, ratio, d.data.id).toString();
17767 setTextValue(node, text, [-1, 1], hasGauge);
17768 } else {
17769 node.text("");
17770 }
17771 });
17772 }
17773 },
17774 expandArc(targetIds) {
17775 const $$ = this;
17776 const { state: { transiting }, $el } = $$;
17777 if (transiting) {
17778 const interval = setInterval(() => {
17779 if (!transiting) {
17780 clearInterval(interval);
17781 $el.legend.selectAll(`.${$FOCUS.legendItemFocused}`).size() > 0 && $$.expandArc(targetIds);
17782 }
17783 }, 10);
17784 return;
17785 }
17786 const newTargetIds = $$.mapToTargetIds(targetIds);
17787 $el.svg.selectAll($$.selectorTargets(newTargetIds, `.${$ARC.chartArc}`)).each(function(d) {
17788 if (!$$.shouldExpand(d.data.id)) {
17789 return;
17790 }
17791 const expandDuration = $$.getExpandConfig(d.data.id, "duration");
17792 const svgArcExpandedSub = $$.getSvgArcExpanded(
17793 $$.getExpandConfig(d.data.id, "rate")
17794 );
17795 (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($$)));
17796 });
17797 },
17798 unexpandArc(targetIds) {
17799 const $$ = this;
17800 const { state: { transiting }, $el: { svg } } = $$;
17801 if (transiting) {
17802 return;
17803 }
17804 const newTargetIds = $$.mapToTargetIds(targetIds);
17805 svg.selectAll($$.selectorTargets(newTargetIds, `.${$ARC.chartArc}`)).selectAll("path").transition().duration((d) => $$.getExpandConfig(d.data.id, "duration")).attrTween("d", getAttrTweenFn($$.svgArc.bind($$)));
17806 svg.selectAll(`${$ARC.arc}`).style("opacity", null);
17807 },
17808 /**
17809 * Get expand config value
17810 * @param {string} id data ID
17811 * @param {string} key config key: 'duration | rate'
17812 * @returns {number}
17813 * @private
17814 */
17815 getExpandConfig(id, key) {
17816 const $$ = this;
17817 const { config } = $$;
17818 const def = {
17819 duration: 50,
17820 rate: 0.98
17821 };
17822 let type;
17823 if ($$.isDonutType(id)) {
17824 type = "donut";
17825 } else if ($$.isGaugeType(id)) {
17826 type = "gauge";
17827 } else if ($$.isPieType(id)) {
17828 type = "pie";
17829 }
17830 return type ? config[`${type}_expand_${key}`] : def[key];
17831 },
17832 shouldExpand(id) {
17833 const $$ = this;
17834 const { config } = $$;
17835 return $$.isDonutType(id) && config.donut_expand || $$.isGaugeType(id) && config.gauge_expand || $$.isPieType(id) && config.pie_expand;
17836 },
17837 shouldShowArcLabel() {
17838 const $$ = this;
17839 const { config } = $$;
17840 return ["donut", "gauge", "pie", "polar"].some((v) => $$.hasType(v) && config[`${v}_label_show`]);
17841 },
17842 getArcLabelFormat() {
17843 const $$ = this;
17844 const { config } = $$;
17845 let format = (v) => v;
17846 ["donut", "gauge", "pie", "polar"].filter($$.hasType.bind($$)).forEach((v) => {
17847 format = config[`${v}_label_format`];
17848 });
17849 return isFunction(format) ? format.bind($$.api) : format;
17850 },
17851 updateTargetsForArc(targets) {
17852 const $$ = this;
17853 const { $el } = $$;
17854 const hasGauge = $$.hasType("gauge");
17855 const classChartArc = $$.getChartClass("Arc");
17856 const classArcs = $$.getClass("arcs", true);
17857 const classFocus = $$.classFocus.bind($$);
17858 const chartArcs = $el.main.select(`.${$ARC.chartArcs}`);
17859 const mainPieUpdate = chartArcs.selectAll(`.${$ARC.chartArc}`).data($$.pie(targets)).attr("class", (d) => classChartArc(d) + classFocus(d.data));
17860 const mainPieEnter = mainPieUpdate.enter().append("g").attr("class", classChartArc).call(
17861 this.setCssRule(false, `.${$ARC.chartArcs} text`, [
17862 "pointer-events:none",
17863 "text-anchor:middle"
17864 ])
17865 );
17866 mainPieEnter.append("g").attr("class", classArcs).merge(mainPieUpdate);
17867 mainPieEnter.append("text").attr("dy", hasGauge && !$$.hasMultiTargets() ? "-.1em" : ".35em").style("opacity", "0").style("text-anchor", $$.getStylePropValue("middle")).style("pointer-events", $$.getStylePropValue("none"));
17868 $el.text = chartArcs.selectAll(`.${$COMMON.target} text`);
17869 },
17870 initArc() {
17871 const $$ = this;
17872 const { $el } = $$;
17873 $el.arcs = $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $ARC.chartArcs).attr("transform", $$.getTranslate("arc"));
17874 $$.setArcTitle();
17875 },
17876 /**
17877 * Set arc title text
17878 * @param {string} str Title text
17879 * @private
17880 */
17881 setArcTitle(str) {
17882 const $$ = this;
17883 const title = str || $$.getArcTitle();
17884 const hasGauge = $$.hasType("gauge");
17885 if (title) {
17886 const className = hasGauge ? $GAUGE.chartArcsGaugeTitle : $ARC.chartArcsTitle;
17887 let text = $$.$el.arcs.select(`.${className}`);
17888 if (text.empty()) {
17889 text = $$.$el.arcs.append("text").attr("class", className).style("text-anchor", "middle");
17890 }
17891 hasGauge && text.attr("dy", "-0.3em");
17892 setTextValue(text, title, hasGauge ? void 0 : [-0.6, 1.35], true);
17893 }
17894 },
17895 /**
17896 * Return arc title text
17897 * @returns {string} Arc title text
17898 * @private
17899 */
17900 getArcTitle() {
17901 const $$ = this;
17902 const type = $$.hasType("donut") && "donut" || $$.hasType("gauge") && "gauge";
17903 return type ? $$.config[`${type}_title`] : "";
17904 },
17905 /**
17906 * Get arc title text with needle value
17907 * @returns {string|boolean} When title contains needle template string will return processed string, otherwise false
17908 * @private
17909 */
17910 getArcTitleWithNeedleValue() {
17911 const $$ = this;
17912 const { config, state } = $$;
17913 const title = $$.getArcTitle();
17914 if (title && $$.config.arc_needle_show && /{=[A-Z_]+}/.test(title)) {
17915 let value = state.current.needle;
17916 if (!isNumber(value)) {
17917 value = config.arc_needle_value;
17918 }
17919 return tplProcess(title, {
17920 NEEDLE_VALUE: isNumber(value) ? value : 0
17921 });
17922 }
17923 return false;
17924 },
17925 redrawArc(duration, durationForExit, withTransform) {
17926 const $$ = this;
17927 const { config, state, $el: { main } } = $$;
17928 const hasInteraction = config.interaction_enabled;
17929 const isSelectable = hasInteraction && config.data_selection_isselectable;
17930 let mainArc = main.selectAll(`.${$ARC.arcs}`).selectAll(`.${$ARC.arc}`).data($$.arcData.bind($$));
17931 mainArc.exit().transition().duration(durationForExit).style("opacity", "0").remove();
17932 mainArc = mainArc.enter().append("path").attr("class", $$.getClass("arc", true)).style("fill", (d) => $$.color(d.data)).style("cursor", (d) => {
17933 var _a;
17934 return ((_a = isSelectable == null ? void 0 : isSelectable.bind) == null ? void 0 : _a.call(isSelectable, $$.api)(d)) ? "pointer" : null;
17935 }).style("opacity", "0").each(function(d) {
17936 if ($$.isGaugeType(d.data)) {
17937 d.startAngle = config.gauge_startingAngle;
17938 d.endAngle = config.gauge_startingAngle;
17939 }
17940 this._current = d;
17941 }).merge(mainArc);
17942 if ($$.hasType("gauge")) {
17943 $$.updateGaugeMax();
17944 $$.hasMultiArcGauge() && $$.redrawArcGaugeLine();
17945 }
17946 mainArc.attr("transform", (d) => !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : "").style("opacity", function(d) {
17947 return d === this._current ? "0" : null;
17948 }).each(() => {
17949 state.transiting = true;
17950 }).transition().duration(duration).attrTween("d", function(d) {
17951 const updated = $$.updateAngle(d);
17952 if (!updated) {
17953 return () => "M 0 0";
17954 }
17955 if (isNaN(this._current.startAngle)) {
17956 this._current.startAngle = 0;
17957 }
17958 if (isNaN(this._current.endAngle)) {
17959 this._current.endAngle = this._current.startAngle;
17960 }
17961 const interpolate = (0,external_commonjs_d3_interpolate_commonjs2_d3_interpolate_amd_d3_interpolate_root_d3_.interpolate)(this._current, updated);
17962 this._current = interpolate(0);
17963 return function(t) {
17964 const interpolated = interpolate(t);
17965 interpolated.data = d.data;
17966 return $$.getArc(interpolated, true);
17967 };
17968 }).attr("transform", withTransform ? "scale(1)" : "").style("fill", (d) => {
17969 let color;
17970 if ($$.levelColor) {
17971 color = $$.levelColor(d.data.values[0].value);
17972 config.data_colors[d.data.id] = color;
17973 } else {
17974 color = $$.color(d.data);
17975 }
17976 return color;
17977 }).style("opacity", null).call(endall, function() {
17978 if ($$.levelColor) {
17979 const path = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
17980 const d = path.datum(this._current);
17981 $$.updateLegendItemColor(d.data.id, path.style("fill"));
17982 }
17983 state.transiting = false;
17984 callFn(config.onrendered, $$.api);
17985 });
17986 hasInteraction && $$.bindArcEvent(mainArc);
17987 $$.hasType("polar") && $$.redrawPolar();
17988 $$.hasType("gauge") && $$.redrawBackgroundArcs();
17989 config.arc_needle_show && $$.redrawNeedle();
17990 $$.redrawArcText(duration);
17991 $$.redrawArcRangeText();
17992 },
17993 /**
17994 * Update needle element
17995 * @private
17996 */
17997 redrawNeedle() {
17998 const $$ = this;
17999 const { $el, config, state: { hiddenTargetIds, radius } } = $$;
18000 const length = (radius - 1) / 100 * config.arc_needle_length;
18001 const hasDataToShow = hiddenTargetIds.length !== $$.data.targets.length;
18002 let needle = $$.$el.arcs.select(`.${$ARC.needle}`);
18003 const pathFn = config.arc_needle_path;
18004 const baseWidth = config.arc_needle_bottom_width / 2;
18005 const topWidth = config.arc_needle_top_width / 2;
18006 const topRx = config.arc_needle_top_rx;
18007 const topRy = config.arc_needle_top_ry;
18008 const bottomLen = config.arc_needle_bottom_len;
18009 const bottomRx = config.arc_needle_bottom_rx;
18010 const bottomRy = config.arc_needle_bottom_ry;
18011 const needleAngle = $$.getNeedleAngle();
18012 const updateNeedleValue = () => {
18013 const title = $$.getArcTitleWithNeedleValue();
18014 title && $$.setArcTitle(title);
18015 };
18016 updateNeedleValue();
18017 if (needle.empty()) {
18018 needle = $el.arcs.append("path").classed($ARC.needle, true);
18019 $el.needle = needle;
18020 $el.needle.updateHelper = (v, updateConfig = false) => {
18021 if ($el.needle.style("display") !== "none") {
18022 $$.$T($el.needle).style("transform", `rotate(${$$.getNeedleAngle(v)}deg)`).call(endall, () => {
18023 updateConfig && (config.arc_needle_value = v);
18024 updateNeedleValue();
18025 });
18026 }
18027 };
18028 }
18029 if (hasDataToShow) {
18030 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`;
18031 $$.$T(needle).attr("d", path).style("fill", config.arc_needle_color).style("display", null).style("transform", `rotate(${needleAngle}deg)`);
18032 } else {
18033 needle.style("display", "none");
18034 }
18035 },
18036 /**
18037 * Get needle angle value relative given value
18038 * @param {number} v Value to be calculated angle
18039 * @returns {number} angle value
18040 * @private
18041 */
18042 getNeedleAngle(v) {
18043 const $$ = this;
18044 const { config, state } = $$;
18045 const arcLength = $$.getArcLength();
18046 const hasGauge = $$.hasType("gauge");
18047 const total = $$.getTotalDataSum(true);
18048 let value = isDefined(v) ? v : config.arc_needle_value;
18049 let startingAngle = config[`${config.data_type}_startingAngle`] || 0;
18050 let radian = 0;
18051 if (!isNumber(value)) {
18052 value = hasGauge && $$.data.targets.length === 1 ? total : 0;
18053 }
18054 state.current.needle = value;
18055 if (hasGauge) {
18056 startingAngle = $$.getStartingAngle();
18057 const radius = config.gauge_fullCircle ? arcLength : startingAngle * -2;
18058 const { gauge_min: min, gauge_max: max } = config;
18059 radian = radius * ((value - min) / (max - min));
18060 } else {
18061 radian = arcLength * (value / total);
18062 }
18063 return (startingAngle + radian) * (180 / Math.PI);
18064 },
18065 redrawBackgroundArcs() {
18066 const $$ = this;
18067 const { config, state } = $$;
18068 const hasMultiArcGauge = $$.hasMultiArcGauge();
18069 const isFullCircle = config.gauge_fullCircle;
18070 const showEmptyTextLabel = $$.filterTargetsToShow($$.data.targets).length === 0 && !!config.data_empty_label_text;
18071 const startAngle = $$.getStartingAngle();
18072 const endAngle = isFullCircle ? startAngle + $$.getArcLength() : startAngle * -1;
18073 let backgroundArc = $$.$el.arcs.select(
18074 `${hasMultiArcGauge ? "g" : ""}.${$ARC.chartArcsBackground}`
18075 );
18076 if (hasMultiArcGauge) {
18077 let index = 0;
18078 backgroundArc = backgroundArc.selectAll(`path.${$ARC.chartArcsBackground}`).data($$.data.targets);
18079 backgroundArc.enter().append("path").attr("class", (d, i) => `${$ARC.chartArcsBackground} ${$ARC.chartArcsBackground}-${i}`).merge(backgroundArc).style("fill", config.gauge_background || null).attr("d", ({ id }) => {
18080 if (showEmptyTextLabel || state.hiddenTargetIds.indexOf(id) >= 0) {
18081 return "M 0 0";
18082 }
18083 const d = {
18084 data: [{ value: config.gauge_max }],
18085 startAngle,
18086 endAngle,
18087 index: index++
18088 };
18089 return $$.getArc(d, true, true);
18090 });
18091 backgroundArc.exit().remove();
18092 } else {
18093 backgroundArc.attr("d", showEmptyTextLabel ? "M 0 0" : () => {
18094 const d = {
18095 data: [{ value: config.gauge_max }],
18096 startAngle,
18097 endAngle
18098 };
18099 return $$.getArc(d, true, true);
18100 });
18101 }
18102 },
18103 bindArcEvent(arc) {
18104 const $$ = this;
18105 const { config, state } = $$;
18106 const isTouch = state.inputType === "touch";
18107 const isMouse = state.inputType === "mouse";
18108 function selectArc(_this, arcData, id) {
18109 $$.expandArc(id);
18110 $$.api.focus(id);
18111 $$.toggleFocusLegend(id, true);
18112 $$.showTooltip([arcData], _this);
18113 }
18114 function unselectArc(arcData) {
18115 const id = (arcData == null ? void 0 : arcData.id) || void 0;
18116 $$.unexpandArc(id);
18117 $$.api.revert();
18118 $$.revertLegend();
18119 $$.hideTooltip();
18120 }
18121 arc.on("click", function(event, d, i) {
18122 var _a;
18123 const updated = $$.updateAngle(d);
18124 let arcData;
18125 if (updated) {
18126 arcData = $$.convertToArcData(updated);
18127 (_a = $$.toggleShape) == null ? void 0 : _a.call($$, this, arcData, i);
18128 config.data_onclick.bind($$.api)(arcData, this);
18129 }
18130 });
18131 if (isMouse) {
18132 arc.on("mouseover", function(event, d) {
18133 if (state.transiting) {
18134 return;
18135 }
18136 state.event = event;
18137 const updated = $$.updateAngle(d);
18138 const arcData = updated ? $$.convertToArcData(updated) : null;
18139 const id = (arcData == null ? void 0 : arcData.id) || void 0;
18140 selectArc(this, arcData, id);
18141 $$.setOverOut(true, arcData);
18142 }).on("mouseout", (event, d) => {
18143 if (state.transiting || !config.interaction_onout) {
18144 return;
18145 }
18146 state.event = event;
18147 const updated = $$.updateAngle(d);
18148 const arcData = updated ? $$.convertToArcData(updated) : null;
18149 unselectArc();
18150 $$.setOverOut(false, arcData);
18151 }).on("mousemove", function(event, d) {
18152 const updated = $$.updateAngle(d);
18153 const arcData = updated ? $$.convertToArcData(updated) : null;
18154 state.event = event;
18155 $$.showTooltip([arcData], this);
18156 });
18157 }
18158 if (isTouch && $$.hasArcType() && !$$.radars) {
18159 const getEventArc = (event) => {
18160 var _a, _b;
18161 const { clientX, clientY } = (_b = (_a = event.changedTouches) == null ? void 0 : _a[0]) != null ? _b : { clientX: 0, clientY: 0 };
18162 const eventArc = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(browser_doc.elementFromPoint(clientX, clientY));
18163 return eventArc;
18164 };
18165 $$.$el.svg.on("touchstart touchmove", function(event) {
18166 if (state.transiting) {
18167 return;
18168 }
18169 state.event = event;
18170 const eventArc = getEventArc(event);
18171 const datum = eventArc.datum();
18172 const updated = (datum == null ? void 0 : datum.data) && datum.data.id ? $$.updateAngle(datum) : null;
18173 const arcData = updated ? $$.convertToArcData(updated) : null;
18174 const id = (arcData == null ? void 0 : arcData.id) || void 0;
18175 $$.callOverOutForTouch(arcData);
18176 isUndefined(id) ? unselectArc() : selectArc(this, arcData, id);
18177 });
18178 }
18179 },
18180 redrawArcText(duration) {
18181 const $$ = this;
18182 const { config, state, $el: { main, arcs } } = $$;
18183 const hasGauge = $$.hasType("gauge");
18184 const hasMultiArcGauge = $$.hasMultiArcGauge();
18185 let text;
18186 if (!(hasGauge && $$.data.targets.length === 1 && config.gauge_title)) {
18187 text = main.selectAll(`.${$ARC.chartArc}`).select("text").style("opacity", "0").attr("class", (d) => $$.isGaugeType(d.data) ? $GAUGE.gaugeValue : null).call($$.textForArcLabel.bind($$)).attr("transform", (d) => $$.transformForArcLabel.bind($$)(d)).style("font-size", (d) => $$.isGaugeType(d.data) && $$.data.targets.length === 1 && !hasMultiArcGauge ? `${Math.round(state.radius / 5)}px` : null).transition().duration(duration).style(
18188 "opacity",
18189 (d) => $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? null : "0"
18190 );
18191 hasMultiArcGauge && text.attr("dy", "-.1em");
18192 }
18193 main.select(`.${$ARC.chartArcsTitle}`).style("opacity", $$.hasType("donut") || hasGauge ? null : "0");
18194 if (hasGauge) {
18195 const isFullCircle = config.gauge_fullCircle;
18196 isFullCircle && (text == null ? void 0 : text.attr("dy", `${hasMultiArcGauge ? 0 : Math.round(state.radius / 14)}`));
18197 if (config.gauge_label_show) {
18198 arcs.select(`.${$GAUGE.chartArcsGaugeUnit}`).attr("dy", `${isFullCircle ? 1.5 : 0.75}em`).text(config.gauge_units);
18199 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));
18200 !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));
18201 }
18202 }
18203 },
18204 /**
18205 * Get Arc element by id or index
18206 * @param {string|number} value id or index of Arc
18207 * @returns {d3Selection} Arc path element
18208 * @private
18209 */
18210 getArcElementByIdOrIndex(value) {
18211 const $$ = this;
18212 const { $el: { arcs } } = $$;
18213 const filterFn = isNumber(value) ? (d) => d.index === value : (d) => d.data.id === value;
18214 return arcs == null ? void 0 : arcs.selectAll(`.${$COMMON.target} path`).filter(filterFn);
18215 }
18216});
18217
18218;// ./src/ChartInternal/shape/area.ts
18219
18220
18221
18222
18223/* harmony default export */ var shape_area = ({
18224 initArea(mainLine) {
18225 const $$ = this;
18226 const { config } = $$;
18227 mainLine.insert("g", `.${config.area_front ? $CIRCLE.circles : $LINE.lines}`).attr("class", $$.getClass("areas", true));
18228 },
18229 /**
18230 * Update area color
18231 * @param {object} d Data object
18232 * @returns {string} Color string
18233 * @private
18234 */
18235 updateAreaColor(d) {
18236 const $$ = this;
18237 return $$.config.area_linearGradient ? $$.getGradienColortUrl(d.id) : $$.color(d);
18238 },
18239 /**
18240 * Generate/Update elements
18241 * @param {boolean} withTransition Transition for exit elements
18242 * @param {boolean} isSub Subchart draw
18243 * @private
18244 */
18245 updateArea(withTransition, isSub = false) {
18246 const $$ = this;
18247 const { config, state, $el, $T } = $$;
18248 const $root = isSub ? $el.subchart : $el;
18249 config.area_linearGradient && $$.updateLinearGradient();
18250 const area = $root.main.selectAll(`.${$AREA.areas}`).selectAll(`.${$AREA.area}`).data($$.lineData.bind($$));
18251 $T(area.exit(), withTransition).style("opacity", "0").remove();
18252 $root.area = area.enter().append("path").attr("class", $$.getClass("area", true)).style("fill", $$.updateAreaColor.bind($$)).style("opacity", function() {
18253 state.orgAreaOpacity = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).style("opacity");
18254 return "0";
18255 }).merge(area);
18256 area.style("opacity", state.orgAreaOpacity);
18257 $$.setRatioForGroupedData($root.area.data());
18258 },
18259 /**
18260 * Redraw function
18261 * @param {Function} drawFn Retuned functino from .generateDrawCandlestick()
18262 * @param {boolean} withTransition With or without transition
18263 * @param {boolean} isSub Subchart draw
18264 * @returns {Array}
18265 */
18266 redrawArea(drawFn, withTransition, isSub = false) {
18267 const $$ = this;
18268 const { area } = isSub ? this.$el.subchart : this.$el;
18269 const { orgAreaOpacity } = $$.state;
18270 return [
18271 $$.$T(area, withTransition, getRandom()).attr("d", drawFn).style("fill", $$.updateAreaColor.bind($$)).style(
18272 "opacity",
18273 (d) => String($$.isAreaRangeType(d) ? orgAreaOpacity / 1.75 : orgAreaOpacity)
18274 )
18275 ];
18276 },
18277 /**
18278 * Generate area path data
18279 * @param {object} areaIndices Indices
18280 * @param {boolean} isSub Weather is sub axis
18281 * @returns {Function}
18282 * @private
18283 */
18284 generateDrawArea(areaIndices, isSub) {
18285 const $$ = this;
18286 const { config } = $$;
18287 const lineConnectNull = config.line_connectNull;
18288 const isRotated = config.axis_rotated;
18289 const getPoints = $$.generateGetAreaPoints(areaIndices, isSub);
18290 const yScale = $$.getYScaleById.bind($$);
18291 const xValue = (d) => (isSub ? $$.subxx : $$.xx).call($$, d);
18292 const value0 = (d, i) => $$.isGrouped(d.id) ? getPoints(d, i)[0][1] : yScale(d.id, isSub)(
18293 $$.isAreaRangeType(d) ? $$.getRangedData(d, "high") : $$.getShapeYMin(d.id)
18294 );
18295 const value1 = (d, i) => $$.isGrouped(d.id) ? getPoints(d, i)[1][1] : yScale(d.id, isSub)(
18296 $$.isAreaRangeType(d) ? $$.getRangedData(d, "low") : d.value
18297 );
18298 return (d) => {
18299 let values = lineConnectNull ? $$.filterRemoveNull(d.values) : d.values;
18300 let x0 = 0;
18301 let y0 = 0;
18302 let path;
18303 if ($$.isAreaType(d)) {
18304 let area = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.area)();
18305 area = isRotated ? area.y(xValue).x0(value0).x1(value1) : area.x(xValue).y0(config.area_above ? 0 : config.area_below ? $$.state.height : value0).y1(value1);
18306 if (!lineConnectNull) {
18307 area = area.defined((d2) => $$.getBaseValue(d2) !== null);
18308 }
18309 if ($$.isStepType(d)) {
18310 values = $$.convertValuesToStep(values);
18311 }
18312 path = area.curve($$.getCurve(d))(values);
18313 } else {
18314 if (values[0]) {
18315 x0 = $$.scale.x(values[0].x);
18316 y0 = $$.getYScaleById(d.id)(values[0].value);
18317 }
18318 path = isRotated ? `M ${y0} ${x0}` : `M ${x0} ${y0}`;
18319 }
18320 return path || "M 0 0";
18321 };
18322 },
18323 generateGetAreaPoints(areaIndices, isSub) {
18324 const $$ = this;
18325 const { config } = $$;
18326 const x = $$.getShapeX(0, areaIndices, isSub);
18327 const y = $$.getShapeY(!!isSub);
18328 const areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, isSub);
18329 const yScale = $$.getYScaleById.bind($$);
18330 return function(d, i) {
18331 const y0 = yScale.call($$, d.id, isSub)($$.getShapeYMin(d.id));
18332 const offset = areaOffset(d, i) || y0;
18333 const posX = x(d);
18334 const value = d.value;
18335 let posY = y(d);
18336 if (config.axis_rotated && (value > 0 && posY < y0 || value < 0 && y0 < posY)) {
18337 posY = y0;
18338 }
18339 return [
18340 [posX, offset],
18341 [posX, posY - (y0 - offset)],
18342 [posX, posY - (y0 - offset)],
18343 // needed for compatibility
18344 [posX, offset]
18345 // needed for compatibility
18346 ];
18347 };
18348 }
18349});
18350
18351;// ./src/ChartInternal/shape/bar.ts
18352
18353
18354/* harmony default export */ var bar = ({
18355 initBar() {
18356 const { $el, config, state: { clip } } = this;
18357 $el.bar = $el.main.select(`.${$COMMON.chart}`);
18358 $el.bar = config.bar_front ? $el.bar.append("g") : $el.bar.insert("g", ":first-child");
18359 $el.bar.attr("class", $BAR.chartBars).call(this.setCssRule(false, `.${$BAR.chartBars}`, ["pointer-events:none"]));
18360 if (config.clipPath === false && (config.bar_radius || config.bar_radius_ratio)) {
18361 $el.bar.attr("clip-path", clip.pathXAxis.replace(/#[^)]*/, `#${clip.id}`));
18362 }
18363 },
18364 updateTargetsForBar(targets) {
18365 const $$ = this;
18366 const { config, $el } = $$;
18367 const classChartBar = $$.getChartClass("Bar");
18368 const classBars = $$.getClass("bars", true);
18369 const classFocus = $$.classFocus.bind($$);
18370 const isSelectable = config.interaction_enabled && config.data_selection_isselectable;
18371 if (!$el.bar) {
18372 $$.initBar();
18373 }
18374 const mainBarUpdate = $el.main.select(`.${$BAR.chartBars}`).selectAll(`.${$BAR.chartBar}`).data(
18375 // remove
18376 targets.filter(
18377 (v) => v.values.some((d) => isNumber(d.value) || $$.isBarRangeType(d))
18378 )
18379 ).attr("class", (d) => classChartBar(d) + classFocus(d));
18380 const mainBarEnter = mainBarUpdate.enter().append("g").attr("class", classChartBar).style("opacity", "0").style("pointer-events", $$.getStylePropValue("none"));
18381 mainBarEnter.append("g").attr("class", classBars).style("cursor", (d) => {
18382 var _a;
18383 return ((_a = isSelectable == null ? void 0 : isSelectable.bind) == null ? void 0 : _a.call(isSelectable, $$.api)(d)) ? "pointer" : null;
18384 }).call($$.setCssRule(true, ` .${$BAR.bar}`, ["fill"], $$.color));
18385 },
18386 /**
18387 * Generate/Update elements
18388 * @param {boolean} withTransition Transition for exit elements
18389 * @param {boolean} isSub Subchart draw
18390 * @private
18391 */
18392 updateBar(withTransition, isSub = false) {
18393 const $$ = this;
18394 const { config, $el, $T } = $$;
18395 const $root = isSub ? $el.subchart : $el;
18396 const classBar = $$.getClass("bar", true);
18397 const initialOpacity = $$.initialOpacity.bind($$);
18398 config.bar_linearGradient && $$.updateLinearGradient();
18399 const bar = $root.main.selectAll(`.${$BAR.bars}`).selectAll(`.${$BAR.bar}`).data($$.labelishData.bind($$));
18400 $T(bar.exit(), withTransition).style("opacity", "0").remove();
18401 $root.bar = bar.enter().append("path").attr("class", classBar).style("fill", $$.updateBarColor.bind($$)).merge(bar).style("opacity", initialOpacity);
18402 $$.setRatioForGroupedData($root.bar.data());
18403 },
18404 /**
18405 * Update bar color
18406 * @param {object} d Data object
18407 * @returns {string} Color string
18408 * @private
18409 */
18410 updateBarColor(d) {
18411 const $$ = this;
18412 const fn = $$.getStylePropValue($$.color);
18413 return $$.config.bar_linearGradient ? $$.getGradienColortUrl(d.id) : fn ? fn(d) : null;
18414 },
18415 /**
18416 * Redraw function
18417 * @param {Function} drawFn Retuned function from .getDrawShape() => .generateDrawBar()
18418 * @param {boolean} withTransition With or without transition
18419 * @param {boolean} isSub Subchart draw
18420 * @returns {Array}
18421 * @private
18422 */
18423 redrawBar(drawFn, withTransition, isSub = false) {
18424 const $$ = this;
18425 const { bar } = isSub ? $$.$el.subchart : $$.$el;
18426 return [
18427 $$.$T(bar, withTransition, getRandom()).attr("d", (d) => (isNumber(d.value) || $$.isBarRangeType(d)) && drawFn(d)).style("fill", $$.updateBarColor.bind($$)).style("clip-path", (d) => d.clipPath).style("opacity", null)
18428 ];
18429 },
18430 /**
18431 * Generate draw function
18432 * @param {object} barIndices data order within x axis.
18433 * barIndices ==> {data1: 0, data2: 0, data3: 1, data4: 1, __max__: 1}
18434 *
18435 * When gropus given as:
18436 * groups: [
18437 * ["data1", "data2"],
18438 * ["data3", "data4"]
18439 * ],
18440 *
18441 * Will be rendered as:
18442 * data1 data3 data1 data3
18443 * data2 data4 data2 data4
18444 * -------------------------
18445 * 0 1
18446 * @param {boolean} isSub If is for subchart
18447 * @returns {Function}
18448 * @private
18449 */
18450 generateDrawBar(barIndices, isSub) {
18451 const $$ = this;
18452 const { config } = $$;
18453 const getPoints = $$.generateGetBarPoints(barIndices, isSub);
18454 const isRotated = config.axis_rotated;
18455 const barRadius = config.bar_radius;
18456 const barRadiusRatio = config.bar_radius_ratio;
18457 const getRadius = isNumber(barRadius) && barRadius > 0 ? () => barRadius : isNumber(barRadiusRatio) ? (w) => w * barRadiusRatio : null;
18458 return (d, i) => {
18459 const points = getPoints(d, i);
18460 const indexX = +isRotated;
18461 const indexY = +!indexX;
18462 const isUnderZero = d.value < 0;
18463 const isInverted = config[`axis_${$$.axis.getId(d.id)}_inverted`];
18464 const isNegative = !isInverted && isUnderZero || isInverted && !isUnderZero;
18465 const pathRadius = ["", ""];
18466 const isGrouped = $$.isGrouped(d.id);
18467 const isRadiusData = getRadius && isGrouped ? $$.isStackingRadiusData(d) : false;
18468 const init = [
18469 points[0][indexX],
18470 points[0][indexY]
18471 ];
18472 let radius = 0;
18473 d.clipPath = null;
18474 if (getRadius) {
18475 const index = isRotated ? indexY : indexX;
18476 const barW = points[2][index] - points[0][index];
18477 radius = !isGrouped || isRadiusData ? getRadius(barW) : 0;
18478 const arc = `a${radius} ${radius} ${isNegative ? `1 0 0` : `0 0 1`} `;
18479 pathRadius[+!isRotated] = `${arc}${radius},${radius}`;
18480 pathRadius[+isRotated] = `${arc}${[-radius, radius][isRotated ? "sort" : "reverse"]()}`;
18481 isNegative && pathRadius.reverse();
18482 }
18483 const pos = isRotated ? points[1][indexX] + (isNegative ? radius : -radius) : points[1][indexY] + (isNegative ? -radius : radius);
18484 if (radius) {
18485 let clipPath = "";
18486 if (isRotated) {
18487 if (isNegative && init[0] < pos) {
18488 clipPath = `0 ${pos - init[0]}px 0 0`;
18489 } else if (!isNegative && init[0] > pos) {
18490 clipPath = `0 0 0 ${init[0] - pos}px`;
18491 }
18492 } else {
18493 if (isNegative && init[1] > pos) {
18494 clipPath = `${init[1] - pos}px 0 0 0`;
18495 } else if (!isNegative && init[1] < pos) {
18496 clipPath = `0 0 ${pos - init[1]}px 0`;
18497 }
18498 }
18499 if (clipPath) {
18500 d.clipPath = `inset(${clipPath})`;
18501 }
18502 }
18503 const path = isRotated ? `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]}`;
18504 return `M${points[0][indexX]},${points[0][indexY]}${path}z`;
18505 };
18506 },
18507 /**
18508 * Determine if given stacking bar data is radius type
18509 * @param {object} d Data row
18510 * @returns {boolean}
18511 */
18512 isStackingRadiusData(d) {
18513 const $$ = this;
18514 const { $el, config, data, state } = $$;
18515 const { id, index, value } = d;
18516 if (state.hiddenTargetIds.indexOf(id) > -1) {
18517 const target = $el.bar.filter((d2) => d2.id === id && d2.value === value);
18518 return !target.empty() && /a\d+/i.test(target.attr("d"));
18519 }
18520 const keys = config.data_groups.find((v) => v.indexOf(id) > -1);
18521 const sortedList = $$.orderTargets(
18522 $$.filterTargetsToShow(data.targets.filter($$.isBarType, $$))
18523 ).filter((v) => keys.indexOf(v.id) > -1);
18524 const sortedIds = sortedList.map(
18525 (v) => v.values.filter(
18526 (v2) => v2.index === index && (isNumber(value) && value > 0 ? v2.value > 0 : v2.value < 0)
18527 )[0]
18528 ).filter(Boolean).map((v) => v.id);
18529 return value !== 0 && sortedIds.indexOf(id) === sortedIds.length - 1;
18530 },
18531 /**
18532 * Generate bar coordinate points data
18533 * @param {object} barIndices Data order within x axis.
18534 * @param {boolean} isSub If is for subchart
18535 * @returns {Array} Array of coordinate points
18536 * @private
18537 */
18538 generateGetBarPoints(barIndices, isSub) {
18539 const $$ = this;
18540 const { config } = $$;
18541 const axis = isSub ? $$.axis.subX : $$.axis.x;
18542 const barTargetsNum = $$.getIndicesMax(barIndices) + 1;
18543 const barW = $$.getBarW("bar", axis, barTargetsNum);
18544 const barX = $$.getShapeX(barW, barIndices, !!isSub);
18545 const barY = $$.getShapeY(!!isSub);
18546 const barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub);
18547 const yScale = $$.getYScaleById.bind($$);
18548 return (d, i) => {
18549 const { id } = d;
18550 const y0 = yScale.call($$, id, isSub)($$.getShapeYMin(id));
18551 const offset = barOffset(d, i) || y0;
18552 const width = isNumber(barW) ? barW : barW[d.id] || barW._$width;
18553 const isInverted = config[`axis_${$$.axis.getId(id)}_inverted`];
18554 const value = d.value;
18555 const posX = barX(d);
18556 let posY = barY(d);
18557 if (config.axis_rotated && !isInverted && (value > 0 && posY < y0 || value < 0 && y0 < posY)) {
18558 posY = y0;
18559 }
18560 if (!$$.isBarRangeType(d)) {
18561 posY -= y0 - offset;
18562 }
18563 const startPosX = posX + width;
18564 return [
18565 [posX, offset],
18566 [posX, posY],
18567 [startPosX, posY],
18568 [startPosX, offset]
18569 ];
18570 };
18571 }
18572});
18573
18574;// ./src/ChartInternal/shape/bubble.ts
18575
18576
18577/* harmony default export */ var bubble = ({
18578 /**
18579 * Initializer
18580 * @private
18581 */
18582 initBubble() {
18583 const $$ = this;
18584 const { config } = $$;
18585 if ($$.hasType("bubble")) {
18586 config.point_show = true;
18587 config.point_type = "circle";
18588 }
18589 },
18590 /**
18591 * Get user agent's computed value
18592 * @returns {number}
18593 * @private
18594 */
18595 getBaseLength() {
18596 const $$ = this;
18597 const { width, height } = $$.state;
18598 const cacheKey = KEY.bubbleBaseLength;
18599 let baseLength = $$.cache.get(cacheKey);
18600 if (!baseLength) {
18601 $$.cache.add(cacheKey, baseLength = getMinMax("min", [width, height]));
18602 }
18603 return baseLength;
18604 },
18605 /**
18606 * Get the radius value for bubble circle
18607 * @param {object} d Data object
18608 * @returns {number}
18609 * @private
18610 */
18611 getBubbleR(d) {
18612 const $$ = this;
18613 let maxR = $$.config.bubble_maxR;
18614 if (isFunction(maxR)) {
18615 maxR = maxR.bind($$.api)(d);
18616 } else if (!isNumber(maxR)) {
18617 maxR = $$.getBaseLength() / ($$.getMaxDataCount() * 2) + 12;
18618 }
18619 const max = getMinMax("max", $$.getMinMaxData().max.map((d2) => $$.isBubbleZType(d2) ? $$.getBubbleZData(d2.value, "y") : isObject(d2.value) ? d2.value.mid : d2.value));
18620 const maxArea = maxR * maxR * Math.PI;
18621 const area = ($$.isBubbleZType(d) ? $$.getBubbleZData(d.value, "z") : d.value) * (maxArea / max);
18622 return Math.sqrt(area / Math.PI);
18623 },
18624 /**
18625 * Get bubble dimension data
18626 * @param {object|Array} d data value
18627 * @param {string} type - y or z
18628 * @returns {number}
18629 * @private
18630 */
18631 getBubbleZData(d, type) {
18632 return isObject(d) ? d[type] : d[type === "y" ? 0 : 1];
18633 }
18634});
18635
18636;// ./src/ChartInternal/shape/candlestick.ts
18637var candlestick_defProp = Object.defineProperty;
18638var candlestick_getOwnPropSymbols = Object.getOwnPropertySymbols;
18639var candlestick_hasOwnProp = Object.prototype.hasOwnProperty;
18640var candlestick_propIsEnum = Object.prototype.propertyIsEnumerable;
18641var candlestick_defNormalProp = (obj, key, value) => key in obj ? candlestick_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
18642var candlestick_spreadValues = (a, b) => {
18643 for (var prop in b || (b = {}))
18644 if (candlestick_hasOwnProp.call(b, prop))
18645 candlestick_defNormalProp(a, prop, b[prop]);
18646 if (candlestick_getOwnPropSymbols)
18647 for (var prop of candlestick_getOwnPropSymbols(b)) {
18648 if (candlestick_propIsEnum.call(b, prop))
18649 candlestick_defNormalProp(a, prop, b[prop]);
18650 }
18651 return a;
18652};
18653
18654
18655
18656/* harmony default export */ var candlestick = ({
18657 initCandlestick() {
18658 const { $el } = this;
18659 $el.candlestick = $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $CANDLESTICK.chartCandlesticks);
18660 },
18661 /**
18662 * Update targets by its data
18663 * called from: ChartInternal.updateTargets()
18664 * @param {Array} targets Filtered target by type
18665 * @private
18666 */
18667 updateTargetsForCandlestick(targets) {
18668 const $$ = this;
18669 const { $el } = $$;
18670 const classChart = $$.getChartClass("Candlestick");
18671 if (!$el.candlestick) {
18672 $$.initCandlestick();
18673 }
18674 const mainUpdate = $$.$el.main.select(`.${$CANDLESTICK.chartCandlesticks}`).selectAll(`.${$CANDLESTICK.chartCandlestick}`).data(targets);
18675 mainUpdate.enter().append("g").attr("class", classChart).style("pointer-events", "none");
18676 },
18677 /**
18678 * Generate/Update elements
18679 * @param {boolean} withTransition Transition for exit elements
18680 * @param {boolean} isSub Subchart draw
18681 * @private
18682 */
18683 updateCandlestick(withTransition, isSub = false) {
18684 const $$ = this;
18685 const { $el, $T } = $$;
18686 const $root = isSub ? $el.subchart : $el;
18687 const classSetter = $$.getClass("candlestick", true);
18688 const initialOpacity = $$.initialOpacity.bind($$);
18689 const candlestick = $root.main.selectAll(`.${$CANDLESTICK.chartCandlestick}`).selectAll(`.${$CANDLESTICK.candlestick}`).data($$.labelishData.bind($$));
18690 $T(candlestick.exit(), withTransition).style("opacity", "0").remove();
18691 const candlestickEnter = candlestick.enter().filter((d) => d.value).append("g").attr("class", classSetter);
18692 candlestickEnter.append("line");
18693 candlestickEnter.append("path");
18694 $root.candlestick = candlestick.merge(candlestickEnter).style("opacity", initialOpacity);
18695 },
18696 /**
18697 * Get draw function
18698 * @param {object} indices Indice data
18699 * @param {boolean} isSub Subchart draw
18700 * @returns {Function}
18701 * @private
18702 */
18703 generateDrawCandlestick(indices, isSub) {
18704 const $$ = this;
18705 const { config } = $$;
18706 const getPoints = $$.generateGetCandlestickPoints(indices, isSub);
18707 const isRotated = config.axis_rotated;
18708 const downColor = config.candlestick_color_down;
18709 return (d, i, g) => {
18710 const points = getPoints(d, i);
18711 const value = $$.getCandlestickData(d);
18712 const isUp = value == null ? void 0 : value._isUp;
18713 const indexX = +isRotated;
18714 const indexY = +!indexX;
18715 if (g.classed) {
18716 g.classed($CANDLESTICK[isUp ? "valueUp" : "valueDown"], true);
18717 }
18718 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]}`;
18719 g.select("path").attr("d", `M${points[0][indexX]},${points[0][indexY]}${path}z`).style("fill", (d2) => {
18720 const color = isUp ? $$.color(d2) : isObject(downColor) ? downColor[d2.id] : downColor;
18721 return color || $$.color(d2);
18722 });
18723 const line = g.select("line");
18724 const pos = isRotated ? {
18725 x1: points[2][1],
18726 x2: points[2][2],
18727 y1: points[2][0],
18728 y2: points[2][0]
18729 } : {
18730 x1: points[2][0],
18731 x2: points[2][0],
18732 y1: points[2][1],
18733 y2: points[2][2]
18734 };
18735 for (const x in pos) {
18736 line.attr(x, pos[x]);
18737 }
18738 };
18739 },
18740 /**
18741 * Generate shape drawing points
18742 * @param {object} indices Indice data
18743 * @param {boolean} isSub Subchart draw
18744 * @returns {Function}
18745 */
18746 generateGetCandlestickPoints(indices, isSub = false) {
18747 const $$ = this;
18748 const axis = isSub ? $$.axis.subX : $$.axis.x;
18749 const targetsNum = $$.getIndicesMax(indices) + 1;
18750 const barW = $$.getBarW("candlestick", axis, targetsNum);
18751 const x = $$.getShapeX(barW, indices, !!isSub);
18752 const y = $$.getShapeY(!!isSub);
18753 const shapeOffset = $$.getShapeOffset($$.isBarType, indices, !!isSub);
18754 const yScale = $$.getYScaleById.bind($$);
18755 return (d, i) => {
18756 const y0 = yScale.call($$, d.id, isSub)($$.getShapeYMin(d.id));
18757 const offset = shapeOffset(d, i) || y0;
18758 const width = isNumber(barW) ? barW : barW[d.id] || barW._$width;
18759 const value = $$.getCandlestickData(d);
18760 let points;
18761 if (value && isNumber(value.open) && isNumber(value.close)) {
18762 const posX = {
18763 start: x(d),
18764 end: 0
18765 };
18766 posX.end = posX.start + width;
18767 const posY = {
18768 start: y(value.open),
18769 end: y(value.close)
18770 };
18771 const posLine = {
18772 x: posX.start + width / 2,
18773 high: y(value.high),
18774 low: y(value.low)
18775 };
18776 posY.start -= y0 - offset;
18777 points = [
18778 [posX.start, posY.start],
18779 [posX.end, posY.end],
18780 [posLine.x, posLine.low, posLine.high]
18781 ];
18782 } else {
18783 points = [[0, 0], [0, 0], [0, 0, 0]];
18784 }
18785 return points;
18786 };
18787 },
18788 /**
18789 * Redraw function
18790 * @param {Function} drawFn Retuned functino from .generateDrawCandlestick()
18791 * @param {boolean} withTransition With or without transition
18792 * @param {boolean} isSub Subchart draw
18793 * @returns {Array}
18794 */
18795 redrawCandlestick(drawFn, withTransition, isSub = false) {
18796 const $$ = this;
18797 const { $el, $T } = $$;
18798 const { candlestick } = isSub ? $el.subchart : $el;
18799 const rand = getRandom(true);
18800 return [
18801 candlestick.each(function(d, i) {
18802 const g = $T((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this), withTransition, rand);
18803 drawFn(d, i, g);
18804 }).style("opacity", null)
18805 ];
18806 },
18807 /**
18808 * Get candlestick data as object
18809 * @param {object} param Data object
18810 * @param {Array|object} param.value Data value
18811 * @returns {object|null} Converted data object
18812 * @private
18813 */
18814 getCandlestickData({ value }) {
18815 let d;
18816 if (isArray(value)) {
18817 const [open, high, low, close, volume = false] = value;
18818 d = { open, high, low, close };
18819 if (volume !== false) {
18820 d.volume = volume;
18821 }
18822 } else if (isObject(value)) {
18823 d = candlestick_spreadValues({}, value);
18824 }
18825 if (d) {
18826 d._isUp = d.close >= d.open;
18827 }
18828 return d || null;
18829 }
18830});
18831
18832;// ./src/ChartInternal/shape/funnel.ts
18833var funnel_defProp = Object.defineProperty;
18834var funnel_getOwnPropSymbols = Object.getOwnPropertySymbols;
18835var funnel_hasOwnProp = Object.prototype.hasOwnProperty;
18836var funnel_propIsEnum = Object.prototype.propertyIsEnumerable;
18837var funnel_defNormalProp = (obj, key, value) => key in obj ? funnel_defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
18838var funnel_spreadValues = (a, b) => {
18839 for (var prop in b || (b = {}))
18840 if (funnel_hasOwnProp.call(b, prop))
18841 funnel_defNormalProp(a, prop, b[prop]);
18842 if (funnel_getOwnPropSymbols)
18843 for (var prop of funnel_getOwnPropSymbols(b)) {
18844 if (funnel_propIsEnum.call(b, prop))
18845 funnel_defNormalProp(a, prop, b[prop]);
18846 }
18847 return a;
18848};
18849
18850
18851
18852function getSize(checkNeck = false) {
18853 const $$ = this;
18854 const { config, state: { current: { width, height } } } = $$;
18855 const padding = $$.getCurrentPadding();
18856 const size = funnel_spreadValues({
18857 width: width - (padding.left + padding.right),
18858 height: height - (config.legend_show ? $$.getLegendHeight() + 10 : 0) - (padding.top + padding.bottom)
18859 }, padding);
18860 if (checkNeck) {
18861 const { width: neckWidth, height: neckHeight } = getNecklSize.call($$, {
18862 width: size.width,
18863 height: size.height
18864 });
18865 if (size.width < neckWidth) {
18866 size.width = neckWidth;
18867 }
18868 if (size.height < neckHeight) {
18869 size.height = neckHeight;
18870 }
18871 }
18872 return size;
18873}
18874function getNecklSize(current) {
18875 const $$ = this;
18876 const { config } = $$;
18877 let width = config.funnel_neck_width;
18878 let height = config.funnel_neck_height;
18879 [width, height] = [width, height].map((v, i) => {
18880 let size = v;
18881 if (isObject(v)) {
18882 size = current[i ? "height" : "width"] * v.ratio;
18883 }
18884 return size;
18885 });
18886 return {
18887 width,
18888 height
18889 };
18890}
18891function getCoord(d) {
18892 const $$ = this;
18893 const { top, left, width } = getSize.call($$, true);
18894 const coords = [];
18895 d.forEach((d2, i) => {
18896 const { ratio } = d2;
18897 const y = i > 0 ? coords[i - 1][2][1] : top;
18898 coords.push(d2.coords = [
18899 [left, y],
18900 // M
18901 [left + width, y],
18902 // 1
18903 [left + width, i > 0 ? ratio + y : ratio + top],
18904 // 2
18905 [left, i > 0 ? ratio + y : ratio + top],
18906 // 3
18907 [left, y]
18908 // 4
18909 ]);
18910 });
18911 return coords;
18912}
18913function getClipPath(forBackground = false) {
18914 const $$ = this;
18915 const { width, height, top, left } = getSize.call($$, true);
18916 const neck = getNecklSize.call($$, { width, height });
18917 const leftX = (width - neck.width) / 2;
18918 const rightX = (width + neck.width) / 2;
18919 const bodyHeigth = height - neck.height;
18920 const coords = [
18921 [0, 0],
18922 // M
18923 [width, 0],
18924 // 1
18925 [rightX, bodyHeigth],
18926 // 2
18927 [rightX, height],
18928 // 3
18929 [leftX, height],
18930 // 4
18931 [leftX, bodyHeigth],
18932 // 5
18933 [0, 0]
18934 // 6
18935 ];
18936 if (forBackground) {
18937 coords.forEach((d) => {
18938 d[0] += left;
18939 d[1] += top;
18940 });
18941 }
18942 return `M${coords.join("L")}z`;
18943}
18944function getFunnelData(d) {
18945 const $$ = this;
18946 const { config } = $$;
18947 const data = d.map((d2) => ({
18948 id: d2.id,
18949 value: d2.values.reduce((a, b) => a + b.value, 0)
18950 }));
18951 if (config.data_order) {
18952 data.sort($$.getSortCompareFn.bind($$)(true));
18953 }
18954 return updateRatio.call($$, data);
18955}
18956function updateRatio(data) {
18957 const $$ = this;
18958 const { height } = getSize.call($$);
18959 const total = $$.getTotalDataSum(true);
18960 data.forEach((d) => {
18961 d.ratio = d.value / total * height;
18962 });
18963 return data;
18964}
18965/* harmony default export */ var funnel = ({
18966 /**
18967 * Initialize polar
18968 * @private
18969 */
18970 initFunnel() {
18971 const $$ = this;
18972 const { $el } = $$;
18973 $el.funnel = $el.main.select(`.${$COMMON.chart}`).append("g").classed($FUNNEL.chartFunnels, true);
18974 $el.funnel.background = $el.funnel.append("path").classed($FUNNEL.funnelBackground, true);
18975 $$.bindFunnelEvent();
18976 },
18977 /**
18978 * Bind events
18979 * @private
18980 */
18981 bindFunnelEvent() {
18982 const $$ = this;
18983 const { $el: { funnel }, config, state } = $$;
18984 const getTarget = (event) => {
18985 var _a;
18986 const target = event.isTrusted ? event.target : (_a = state.eventReceiver.rect) == null ? void 0 : _a.node();
18987 let data;
18988 if (/^path$/i.test(target.tagName)) {
18989 state.event = event;
18990 data = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
18991 }
18992 return data;
18993 };
18994 if (config.interaction_enabled) {
18995 const isTouch = state.inputType === "touch";
18996 funnel.on(isTouch ? "touchstart" : "mouseover mousemove", (event) => {
18997 const data = getTarget(event);
18998 if (data) {
18999 $$.showTooltip([data], event.target);
19000 /^(touchstart|mouseover)$/.test(event.type) && $$.setOverOut(true, data);
19001 }
19002 }).on(isTouch ? "touchend" : "mouseout", (event) => {
19003 const data = getTarget(event);
19004 if (config.interaction_onout) {
19005 $$.hideTooltip();
19006 $$.setOverOut(false, data);
19007 }
19008 });
19009 }
19010 },
19011 /**
19012 * Update polar based on given data array
19013 * @param {object} t Data object
19014 * @private
19015 */
19016 updateTargetsForFunnel(t) {
19017 const $$ = this;
19018 const { $el: { funnel } } = $$;
19019 const classChartFunnel = $$.getChartClass("Funnel");
19020 const classFunnel = $$.getClass("funnel", true);
19021 if (!funnel) {
19022 $$.initFunnel();
19023 }
19024 const targets = getFunnelData.call($$, t.filter($$.isFunnelType.bind($$)));
19025 const mainFunnelUpdate = funnel.selectAll(`.${$FUNNEL.chartFunnel}`).data(targets);
19026 mainFunnelUpdate.exit().remove();
19027 const mainFunnelEnter = mainFunnelUpdate.enter().insert("g", `.${$FUNNEL.funnelBackground}`);
19028 mainFunnelEnter.append("path");
19029 funnel.path = mainFunnelEnter.merge(mainFunnelUpdate).attr("class", (d) => classChartFunnel(d)).select("path").attr("class", classFunnel).style("opacity", "0").style("fill", $$.color);
19030 },
19031 /**
19032 * Update funnel path selection
19033 * @param {object} targets Updated target data
19034 * @private
19035 */
19036 updateFunnel(targets) {
19037 const $$ = this;
19038 const { $el: { funnel } } = $$;
19039 const targetIds = targets.map(({ id }) => id);
19040 funnel.path = funnel.path.filter((d) => targetIds.indexOf(d.id) >= 0);
19041 },
19042 /**
19043 * Generate treemap coordinate points data
19044 * @returns {Array} Array of coordinate points
19045 * @private
19046 */
19047 generateGetFunnelPoints() {
19048 const $$ = this;
19049 const { $el: { funnel } } = $$;
19050 const targets = $$.filterTargetsToShow(funnel.path);
19051 const { top, left, right } = getSize.call($$);
19052 const center = (left - right) / 2;
19053 const points = {};
19054 let accumulatedHeight = top != null ? top : 0;
19055 targets.each((d, i) => {
19056 var _a;
19057 points[d.id] = [
19058 [center, accumulatedHeight],
19059 [center, accumulatedHeight += ((_a = targets == null ? void 0 : targets[i]) != null ? _a : d).ratio]
19060 ];
19061 });
19062 return (d) => points[d.id];
19063 },
19064 /**
19065 * Called whenever redraw happens
19066 * @private
19067 */
19068 redrawFunnel() {
19069 const $$ = this;
19070 const { $T, $el: { funnel } } = $$;
19071 const targets = $$.filterTargetsToShow(funnel.path);
19072 const coords = getCoord.call($$, updateRatio.call($$, targets.data()));
19073 funnel.attr("clip-path", `path('${getClipPath.bind($$)()}')`);
19074 funnel.background.attr("d", getClipPath.call($$, true));
19075 $T(targets).attr("d", (d, i) => `M${coords[i].join("L")}z`).style("opacity", "1");
19076 funnel.selectAll("g").style("opacity", null);
19077 }
19078});
19079
19080;// ./src/ChartInternal/shape/gauge.ts
19081
19082
19083
19084/* harmony default export */ var gauge = ({
19085 initGauge() {
19086 const $$ = this;
19087 const { config, $el: { arcs } } = $$;
19088 const appendText = (className = null, value = "") => {
19089 arcs.append("text").attr("class", className).style("text-anchor", "middle").style("pointer-events", "none").text(value);
19090 };
19091 if ($$.hasType("gauge")) {
19092 const hasMulti = $$.hasMultiArcGauge();
19093 arcs.append(hasMulti ? "g" : "path").attr("class", $ARC.chartArcsBackground).style("fill", !hasMulti && config.gauge_background || null);
19094 config.gauge_units && appendText($GAUGE.chartArcsGaugeUnit);
19095 if (config.gauge_label_show) {
19096 appendText($GAUGE.chartArcsGaugeMin);
19097 !config.gauge_fullCircle && appendText($GAUGE.chartArcsGaugeMax);
19098 }
19099 }
19100 },
19101 updateGaugeMax() {
19102 const $$ = this;
19103 const { config, state } = $$;
19104 const hasMultiGauge = $$.hasMultiArcGauge();
19105 const max = hasMultiGauge ? $$.getMinMaxData().max[0].value : $$.getTotalDataSum(state.rendered);
19106 if (!config.gauge_enforceMinMax && max + config.gauge_min * (config.gauge_min > 0 ? -1 : 1) > config.gauge_max) {
19107 config.gauge_max = max - config.gauge_min;
19108 }
19109 },
19110 redrawArcGaugeLine() {
19111 const $$ = this;
19112 const { config, state, $el } = $$;
19113 const { hiddenTargetIds } = $$.state;
19114 const arcLabelLines = $el.main.selectAll(`.${$ARC.arcs}`).selectAll(`.${$ARC.arcLabelLine}`).data($$.arcData.bind($$));
19115 const mainArcLabelLine = arcLabelLines.enter().append("rect").attr(
19116 "class",
19117 (d) => `${$ARC.arcLabelLine} ${$COMMON.target} ${$COMMON.target}-${d.data.id}`
19118 ).merge(arcLabelLines);
19119 mainArcLabelLine.style(
19120 "fill",
19121 (d) => $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data)
19122 ).style("display", config.gauge_label_show ? null : "none").each(function(d) {
19123 let lineLength = 0;
19124 const lineThickness = 2;
19125 let x = 0;
19126 let y = 0;
19127 let transform = "";
19128 if (hiddenTargetIds.indexOf(d.data.id) < 0) {
19129 const updated = $$.updateAngle(d);
19130 const innerLineLength = state.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length * (updated.index + 1);
19131 const lineAngle = updated.endAngle - Math.PI / 2;
19132 const arcInnerRadius = state.radius - innerLineLength;
19133 const linePositioningAngle = lineAngle - (arcInnerRadius === 0 ? 0 : 1 / arcInnerRadius);
19134 lineLength = state.radiusExpanded - state.radius + innerLineLength;
19135 x = Math.cos(linePositioningAngle) * arcInnerRadius;
19136 y = Math.sin(linePositioningAngle) * arcInnerRadius;
19137 transform = `rotate(${lineAngle * 180 / Math.PI}, ${x}, ${y})`;
19138 }
19139 (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`);
19140 });
19141 },
19142 textForGaugeMinMax(value, isMax) {
19143 const $$ = this;
19144 const { config } = $$;
19145 const format = config.gauge_label_extents;
19146 return isFunction(format) ? format.bind($$.api)(value, isMax) : value;
19147 },
19148 getGaugeLabelHeight() {
19149 const { config } = this;
19150 return this.config.gauge_label_show && !config.gauge_fullCircle ? 20 : 0;
19151 },
19152 getPaddingBottomForGauge() {
19153 const $$ = this;
19154 return $$.getGaugeLabelHeight() * ($$.config.gauge_label_show ? 2 : 2.5);
19155 }
19156});
19157
19158;// ./src/ChartInternal/shape/line.ts
19159
19160
19161
19162
19163function getStrokeDashArray(start, end, pattern, isLastX = false) {
19164 const dash = start ? [start, 0] : pattern;
19165 for (let i = start ? start : pattern.reduce((a, c) => a + c); i <= end; ) {
19166 pattern.forEach((v) => {
19167 if (i + v <= end) {
19168 dash.push(v);
19169 }
19170 i += v;
19171 });
19172 }
19173 dash.length % 2 !== 0 && dash.push(isLastX ? pattern[1] : 0);
19174 return {
19175 dash: dash.join(" "),
19176 length: dash.reduce((a, b) => a + b, 0)
19177 };
19178}
19179function getRegions(d, _regions, isTimeSeries) {
19180 const $$ = this;
19181 const regions = [];
19182 const dasharray = "2 2";
19183 if (isDefined(_regions)) {
19184 const getValue = (v, def) => isUndefined(v) ? def : isTimeSeries ? parseDate.call($$, v) : v;
19185 for (let i = 0, reg; reg = _regions[i]; i++) {
19186 const start = getValue(reg.start, d[0].x);
19187 const end = getValue(reg.end, d[d.length - 1].x);
19188 const style = reg.style || { dasharray };
19189 regions[i] = { start, end, style };
19190 }
19191 }
19192 return regions;
19193}
19194/* harmony default export */ var line = ({
19195 initLine() {
19196 const { $el } = this;
19197 $el.line = $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $LINE.chartLines).call(this.setCssRule(false, `.${$LINE.chartLines}`, ["pointer-events:none"]));
19198 },
19199 updateTargetsForLine(t) {
19200 const $$ = this;
19201 const { $el: { area, line, main } } = $$;
19202 const classChartLine = $$.getChartClass("Line");
19203 const classLines = $$.getClass("lines", true);
19204 const classFocus = $$.classFocus.bind($$);
19205 if (!line) {
19206 $$.initLine();
19207 }
19208 const targets = t.filter((d) => !($$.isScatterType(d) || $$.isBubbleType(d)));
19209 const mainLineUpdate = main.select(`.${$LINE.chartLines}`).selectAll(`.${$LINE.chartLine}`).data(targets).attr("class", (d) => classChartLine(d) + classFocus(d));
19210 const mainLineEnter = mainLineUpdate.enter().append("g").attr("class", classChartLine).style("opacity", "0").style("pointer-events", $$.getStylePropValue("none"));
19211 mainLineEnter.append("g").attr("class", classLines);
19212 if ($$.hasTypeOf("Area")) {
19213 const mainLine = (!area && mainLineEnter.empty() ? mainLineUpdate : mainLineEnter).filter($$.isAreaType.bind($$));
19214 $$.initArea(mainLine);
19215 }
19216 $$.updateTargetForCircle(targets, mainLineEnter);
19217 },
19218 /**
19219 * Generate/Update elements
19220 * @param {boolean} withTransition Transition for exit elements
19221 * @param {boolean} isSub Subchart draw
19222 * @private
19223 */
19224 updateLine(withTransition, isSub = false) {
19225 const $$ = this;
19226 const { format: { extraLineClasses }, $el, $T } = $$;
19227 const $root = isSub ? $el.subchart : $el;
19228 const line = $root.main.selectAll(`.${$LINE.lines}`).selectAll(`.${$LINE.line}`).data($$.lineData.bind($$));
19229 $T(line.exit(), withTransition).style("opacity", "0").remove();
19230 $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);
19231 },
19232 /**
19233 * Redraw function
19234 * @param {Function} drawFn Retuned functino from .generateDrawCandlestick()
19235 * @param {boolean} withTransition With or without transition
19236 * @param {boolean} isSub Subchart draw
19237 * @returns {Array}
19238 * @private
19239 */
19240 redrawLine(drawFn, withTransition, isSub = false) {
19241 const $$ = this;
19242 const { $el, $T } = $$;
19243 const { line } = isSub ? $el.subchart : $el;
19244 return [
19245 $T(line, withTransition, getRandom()).attr("d", drawFn).style("stroke", this.color).style("opacity", null)
19246 ];
19247 },
19248 /**
19249 * Get the curve interpolate
19250 * @param {Array} d Data object
19251 * @returns {Function}
19252 * @private
19253 */
19254 getCurve(d) {
19255 const $$ = this;
19256 const isRotatedStepType = $$.config.axis_rotated && $$.isStepType(d);
19257 return isRotatedStepType ? (context) => {
19258 const step = $$.getInterpolate(d)(context);
19259 step.orgPoint = step.point;
19260 step.pointRotated = function(x, y) {
19261 this._point === 1 && (this._point = 2);
19262 const y1 = this._y * (1 - this._t) + y * this._t;
19263 this._context.lineTo(this._x, y1);
19264 this._context.lineTo(x, y1);
19265 this._x = x;
19266 this._y = y;
19267 };
19268 step.point = function(x, y) {
19269 this._point === 0 ? this.orgPoint(x, y) : this.pointRotated(x, y);
19270 };
19271 return step;
19272 } : $$.getInterpolate(d);
19273 },
19274 generateDrawLine(lineIndices, isSub) {
19275 const $$ = this;
19276 const { config, scale } = $$;
19277 const lineConnectNull = config.line_connectNull;
19278 const isRotated = config.axis_rotated;
19279 const getPoints = $$.generateGetLinePoints(lineIndices, isSub);
19280 const yScale = $$.getYScaleById.bind($$);
19281 const xValue = (d) => (isSub ? $$.subxx : $$.xx).call($$, d);
19282 const yValue = (d, i) => $$.isGrouped(d.id) ? getPoints(d, i)[0][1] : yScale(d.id, isSub)($$.getBaseValue(d));
19283 let line = (0,external_commonjs_d3_shape_commonjs2_d3_shape_amd_d3_shape_root_d3_.line)();
19284 line = isRotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
19285 if (!lineConnectNull) {
19286 line = line.defined((d) => $$.getBaseValue(d) !== null);
19287 }
19288 const x = isSub ? scale.subX : scale.x;
19289 return (d) => {
19290 const y = yScale(d.id, isSub);
19291 let values = lineConnectNull ? $$.filterRemoveNull(d.values) : d.values;
19292 let x0 = 0;
19293 let y0 = 0;
19294 let path;
19295 if ($$.isLineType(d)) {
19296 const regions = config.data_regions[d.id];
19297 if (regions) {
19298 path = $$.lineWithRegions(values, scale.zoom || x, y, regions);
19299 } else {
19300 if ($$.isStepType(d)) {
19301 values = $$.convertValuesToStep(values);
19302 }
19303 path = line.curve($$.getCurve(d))(values);
19304 }
19305 } else {
19306 if (values[0]) {
19307 x0 = x(values[0].x);
19308 y0 = y(values[0].value);
19309 }
19310 path = isRotated ? `M ${y0} ${x0}` : `M ${x0} ${y0}`;
19311 }
19312 return path || "M 0 0";
19313 };
19314 },
19315 /**
19316 * Set regions dasharray and get path
19317 * @param {Array} d Data object
19318 * @param {Function} x x scale function
19319 * @param {Function} y y scale function
19320 * @param {object} _regions regions to be set
19321 * @returns {stirng} Path string
19322 * @private
19323 */
19324 lineWithRegions(d, x, y, _regions) {
19325 const $$ = this;
19326 const { config } = $$;
19327 const isRotated = config.axis_rotated;
19328 const isTimeSeries = $$.axis.isTimeSeries();
19329 const dasharray = "2 2";
19330 const regions = getRegions.bind($$)(d, _regions, isTimeSeries);
19331 const hasNullDataValue = $$.hasNullDataValue(d);
19332 let xp;
19333 let yp;
19334 let diff;
19335 let diffx2;
19336 const xValue = isRotated ? (dt) => y(dt.value) : (dt) => x(dt.x);
19337 const yValue = isRotated ? (dt) => x(dt.x) : (dt) => y(dt.value);
19338 const generateM = (points) => `M${points[0][0]},${points[0][1]}L${points[1][0]},${points[1][1]}`;
19339 const sWithRegion = isTimeSeries ? (d0, d1, k, timeseriesDiff) => {
19340 const x0 = d0.x.getTime();
19341 const xDiff = d1.x - d0.x;
19342 const xv0 = new Date(x0 + xDiff * k);
19343 const xv1 = new Date(x0 + xDiff * (k + timeseriesDiff));
19344 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))]];
19345 return generateM(points);
19346 } : (d0, d1, k, otherDiff) => {
19347 const x0 = x(d1.x, !isRotated);
19348 const y0 = y(d1.value, isRotated);
19349 const gap = k + otherDiff;
19350 const xValue2 = x(xp(k), !isRotated);
19351 const yValue2 = y(yp(k), isRotated);
19352 let xDiff = x(xp(gap), !isRotated);
19353 let yDiff = y(yp(gap), isRotated);
19354 if (xDiff > x0) {
19355 xDiff = x0;
19356 }
19357 if (d0.value > d1.value && (isRotated ? yDiff < y0 : yDiff > y0)) {
19358 yDiff = y0;
19359 }
19360 const points = [
19361 [xValue2, yValue2],
19362 [xDiff, yDiff]
19363 ];
19364 isRotated && points.forEach((v) => v.reverse());
19365 return generateM(points);
19366 };
19367 const axisType = { x: $$.axis.getAxisType("x"), y: $$.axis.getAxisType("y") };
19368 let path = "";
19369 const target = $$.$el.line.filter(({ id }) => id === d[0].id);
19370 const tempNode = target.clone().style("display", "none");
19371 const getLength = (node, path2) => node.attr("d", path2).node().getTotalLength();
19372 const dashArray = {
19373 dash: [],
19374 lastLength: 0
19375 };
19376 let isLastX = false;
19377 for (let i = 0, data; data = d[i]; i++) {
19378 const prevData = d[i - 1];
19379 const hasPrevData = prevData && isValue(prevData.value);
19380 let style = $$.isWithinRegions(data.x, regions);
19381 if (!isValue(data.value)) {
19382 continue;
19383 }
19384 if (isUndefined(regions) || !style || !hasPrevData) {
19385 path += `${i && hasPrevData ? "L" : "M"}${xValue(data)},${yValue(data)}`;
19386 } else if (hasPrevData) {
19387 style = ((style == null ? void 0 : style.dasharray) || dasharray).split(" ").map(Number);
19388 xp = getScale(axisType.x, prevData.x, data.x);
19389 yp = getScale(axisType.y, prevData.value, data.value);
19390 if (hasNullDataValue) {
19391 const dx = x(data.x) - x(prevData.x);
19392 const dy = y(data.value) - y(prevData.value);
19393 const dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
19394 diff = style[0] / dd;
19395 diffx2 = diff * style[1];
19396 for (let j = diff; j <= 1; j += diffx2) {
19397 path += sWithRegion(prevData, data, j, diff);
19398 if (j + diffx2 >= 1) {
19399 path += sWithRegion(prevData, data, 1, 0);
19400 }
19401 }
19402 } else {
19403 let points = [];
19404 isLastX = data.x === d[d.length - 1].x;
19405 if (isTimeSeries) {
19406 const x0 = +prevData.x;
19407 const xv0 = new Date(x0);
19408 const xv1 = new Date(x0 + (+data.x - x0));
19409 points = [
19410 [x(xv0), y(yp(0))],
19411 // M
19412 [x(xv1), y(yp(1))]
19413 // L
19414 ];
19415 } else {
19416 points = [
19417 [x(xp(0)), y(yp(0))],
19418 // M
19419 [x(xp(1)), y(yp(1))]
19420 // L
19421 ];
19422 }
19423 isRotated && points.forEach((v) => v.reverse());
19424 const startLength = getLength(tempNode, path);
19425 const endLength = getLength(tempNode, path += `L${points[1].join(",")}`);
19426 const strokeDashArray = getStrokeDashArray(
19427 startLength - dashArray.lastLength,
19428 endLength - dashArray.lastLength,
19429 style,
19430 isLastX
19431 );
19432 dashArray.lastLength += strokeDashArray.length;
19433 dashArray.dash.push(strokeDashArray.dash);
19434 }
19435 }
19436 }
19437 if (dashArray.dash.length) {
19438 !isLastX && dashArray.dash.push(getLength(tempNode, path));
19439 tempNode.remove();
19440 target.attr("stroke-dasharray", dashArray.dash.join(" "));
19441 }
19442 return path;
19443 },
19444 isWithinRegions(withinX, withinRegions) {
19445 for (let i = 0, reg; reg = withinRegions[i]; i++) {
19446 if (reg.start < withinX && withinX <= reg.end) {
19447 return reg.style;
19448 }
19449 }
19450 return false;
19451 },
19452 isWithinStep(that, y) {
19453 return Math.abs(y - getPointer(this.state.event, that)[1]) < 30;
19454 },
19455 shouldDrawPointsForLine(d) {
19456 const linePoint = this.config.line_point;
19457 return linePoint === true || isArray(linePoint) && linePoint.indexOf(d.id) !== -1;
19458 }
19459});
19460
19461;// ./src/ChartInternal/shape/point.ts
19462
19463
19464
19465const getTransitionName = () => getRandom();
19466/* harmony default export */ var point = ({
19467 initialOpacityForCircle(d) {
19468 const { config, state: { withoutFadeIn } } = this;
19469 let opacity = config.point_opacity;
19470 if (isUndefined(opacity)) {
19471 opacity = this.getBaseValue(d) !== null && withoutFadeIn[d.id] ? this.opacityForCircle(d) : "0";
19472 }
19473 return opacity;
19474 },
19475 opacityForCircle(d) {
19476 var _a;
19477 const { config } = this;
19478 let opacity = config.point_opacity;
19479 if (isUndefined(opacity)) {
19480 opacity = config.point_show && !((_a = this.isPointFocusOnly) == null ? void 0 : _a.call(this)) ? null : "0";
19481 opacity = isValue(this.getBaseValue(d)) ? this.isBubbleType(d) || this.isScatterType(d) ? "0.5" : opacity : "0";
19482 }
19483 return opacity;
19484 },
19485 initCircle() {
19486 const $$ = this;
19487 const { $el: { main } } = $$;
19488 !$$.point && ($$.point = $$.generatePoint());
19489 if (($$.hasType("bubble") || $$.hasType("scatter")) && main.select(`.${$COMMON.chart} > .${$CIRCLE.chartCircles}`).empty()) {
19490 main.select(`.${$COMMON.chart}`).append("g").attr("class", $CIRCLE.chartCircles);
19491 }
19492 },
19493 updateTargetForCircle(targetsValue, enterNodeValue) {
19494 const $$ = this;
19495 const { config, data, $el } = $$;
19496 const selectionEnabled = config.interaction_enabled && config.data_selection_enabled;
19497 const isSelectable = selectionEnabled && config.data_selection_isselectable;
19498 const classCircles = $$.getClass("circles", true);
19499 if (!config.point_show) {
19500 return;
19501 }
19502 $$.initCircle();
19503 let targets = targetsValue;
19504 let enterNode = enterNodeValue;
19505 if (!targets) {
19506 targets = data.targets.filter((d) => this.isScatterType(d) || this.isBubbleType(d));
19507 const mainCircle = $el.main.select(`.${$CIRCLE.chartCircles}`).style("pointer-events", "none").selectAll(`.${$CIRCLE.circles}`).data(targets);
19508 mainCircle.exit().remove();
19509 enterNode = mainCircle.enter();
19510 }
19511 selectionEnabled && enterNode.append("g").attr("class", (d) => $$.generateClass($SELECT.selectedCircles, d.id));
19512 enterNode.append("g").attr("class", classCircles).call((selection) => {
19513 $$.setCssRule(true, `.${$CIRCLE.circles}`, ["cursor:pointer"], isSelectable)(
19514 selection
19515 );
19516 $$.setCssRule(true, ` .${$CIRCLE.circle}`, ["fill", "stroke"], $$.color)(selection);
19517 }).style("opacity", function() {
19518 const parent = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this.parentNode);
19519 return parent.attr("class").indexOf($CIRCLE.chartCircles) > -1 ? "0" : null;
19520 });
19521 selectionEnabled && targets.forEach((t) => {
19522 $el.main.selectAll(`.${$SELECT.selectedCircles}${$$.getTargetSelectorSuffix(t.id)}`).selectAll(`${$SELECT.selectedCircle}`).each((d) => {
19523 d.value = t.values[d.index].value;
19524 });
19525 });
19526 },
19527 updateCircle(isSub = false) {
19528 const $$ = this;
19529 const { config, state, $el } = $$;
19530 const focusOnly = $$.isPointFocusOnly();
19531 const $root = isSub ? $el.subchart : $el;
19532 if (config.point_show && !state.toggling) {
19533 config.point_radialGradient && $$.updateLinearGradient();
19534 const circles = $root.main.selectAll(`.${$CIRCLE.circles}`).selectAll(`.${$CIRCLE.circle}`).data((d) => $$.isLineType(d) && $$.shouldDrawPointsForLine(d) || $$.isBubbleType(d) || $$.isRadarType(d) || $$.isScatterType(d) ? focusOnly ? [d.values[0]] : d.values : []);
19535 circles.exit().remove();
19536 circles.enter().filter(Boolean).append(
19537 $$.point("create", this, $$.pointR.bind($$), $$.updateCircleColor.bind($$))
19538 );
19539 $root.circle = $root.main.selectAll(`.${$CIRCLE.circles} .${$CIRCLE.circle}`).style("stroke", $$.getStylePropValue($$.color)).style("opacity", $$.initialOpacityForCircle.bind($$));
19540 }
19541 },
19542 /**
19543 * Update circle color
19544 * @param {object} d Data object
19545 * @returns {string} Color string
19546 * @private
19547 */
19548 updateCircleColor(d) {
19549 const $$ = this;
19550 const fn = $$.getStylePropValue($$.color);
19551 return $$.config.point_radialGradient ? $$.getGradienColortUrl(d.id) : fn ? fn(d) : null;
19552 },
19553 redrawCircle(cx, cy, withTransition, flow, isSub = false) {
19554 const $$ = this;
19555 const { state: { rendered }, $el, $T } = $$;
19556 const $root = isSub ? $el.subchart : $el;
19557 const selectedCircles = $root.main.selectAll(`.${$SELECT.selectedCircle}`);
19558 if (!$$.config.point_show) {
19559 return [];
19560 }
19561 const fn = $$.point(
19562 "update",
19563 $$,
19564 cx,
19565 cy,
19566 $$.updateCircleColor.bind($$),
19567 withTransition,
19568 flow,
19569 selectedCircles
19570 );
19571 const posAttr = $$.isCirclePoint() ? "c" : "";
19572 const t = getRandom();
19573 const opacityStyleFn = $$.opacityForCircle.bind($$);
19574 const mainCircles = [];
19575 $root.circle.each(function(d) {
19576 let result = fn.bind(this)(d);
19577 result = $T(result, withTransition || !rendered, t).style("opacity", opacityStyleFn);
19578 mainCircles.push(result);
19579 });
19580 return [
19581 mainCircles,
19582 $T(selectedCircles, withTransition).attr(`${posAttr}x`, cx).attr(`${posAttr}y`, cy)
19583 ];
19584 },
19585 /**
19586 * Show focused data point circle
19587 * @param {object} d Selected data
19588 * @private
19589 */
19590 showCircleFocus(d) {
19591 const $$ = this;
19592 const { state: { hasRadar, resizing, toggling, transiting }, $el } = $$;
19593 let { circle } = $el;
19594 if (transiting === false && circle && $$.isPointFocusOnly()) {
19595 const cx = (hasRadar ? $$.radarCircleX : $$.circleX).bind($$);
19596 const cy = (hasRadar ? $$.radarCircleY : $$.circleY).bind($$);
19597 const withTransition = toggling || isUndefined(d);
19598 const fn = $$.point(
19599 "update",
19600 $$,
19601 cx,
19602 cy,
19603 $$.getStylePropValue($$.color),
19604 resizing ? false : withTransition
19605 );
19606 if (d) {
19607 circle = circle.filter(function(t) {
19608 var _a;
19609 const data = (_a = d.filter) == null ? void 0 : _a.call(d, (v) => v.id === t.id);
19610 return data.length ? (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).datum(data[0]) : false;
19611 });
19612 }
19613 circle.attr("class", this.updatePointClass.bind(this)).style("opacity", null).each(function(d2) {
19614 const { id, index, value } = d2;
19615 let visibility = "hidden";
19616 if (isValue(value)) {
19617 fn.bind(this)(d2);
19618 $$.expandCircles(index, id);
19619 visibility = "";
19620 }
19621 this.style.visibility = visibility;
19622 });
19623 }
19624 },
19625 /**
19626 * Hide focused data point circle
19627 * @private
19628 */
19629 hideCircleFocus() {
19630 const $$ = this;
19631 const { $el: { circle } } = $$;
19632 if ($$.isPointFocusOnly() && circle) {
19633 $$.unexpandCircles();
19634 circle.style("visibility", "hidden");
19635 }
19636 },
19637 circleX(d) {
19638 return this.xx(d);
19639 },
19640 updateCircleY(isSub = false) {
19641 const $$ = this;
19642 const getPoints = $$.generateGetLinePoints($$.getShapeIndices($$.isLineType), isSub);
19643 return (d, i) => {
19644 const id = d.id;
19645 return $$.isGrouped(id) ? getPoints(d, i)[0][1] : $$.getYScaleById(id, isSub)($$.getBaseValue(d));
19646 };
19647 },
19648 expandCircles(i, id, reset) {
19649 const $$ = this;
19650 const r = $$.pointExpandedR.bind($$);
19651 reset && $$.unexpandCircles();
19652 const circles = $$.getShapeByIndex("circle", i, id).classed($COMMON.EXPANDED, true);
19653 const scale = r(circles) / $$.config.point_r;
19654 const ratio = 1 - scale;
19655 if ($$.isCirclePoint()) {
19656 circles.attr("r", r);
19657 } else {
19658 circles.each(function() {
19659 const point = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
19660 if (this.tagName === "circle") {
19661 point.attr("r", r);
19662 } else {
19663 const { width, height } = this.getBBox();
19664 const x = ratio * (+point.attr("x") + width / 2);
19665 const y = ratio * (+point.attr("y") + height / 2);
19666 point.attr("transform", `translate(${x} ${y}) scale(${scale})`);
19667 }
19668 });
19669 }
19670 },
19671 unexpandCircles(i) {
19672 const $$ = this;
19673 const r = $$.pointR.bind($$);
19674 const circles = $$.getShapeByIndex("circle", i).filter(function() {
19675 return (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this).classed($COMMON.EXPANDED);
19676 }).classed($COMMON.EXPANDED, false);
19677 circles.attr("r", r);
19678 if (!$$.isCirclePoint()) {
19679 const scale = r(circles) / $$.config.point_r;
19680 circles.attr("transform", scale !== 1 ? `scale(${scale})` : null);
19681 }
19682 },
19683 pointR(d) {
19684 const $$ = this;
19685 const { config } = $$;
19686 const pointR = config.point_r;
19687 let r = pointR;
19688 if ($$.isBubbleType(d)) {
19689 r = $$.getBubbleR(d);
19690 } else if (isFunction(pointR)) {
19691 r = pointR.bind($$.api)(d);
19692 }
19693 d.r = r;
19694 return r;
19695 },
19696 pointExpandedR(d) {
19697 const $$ = this;
19698 const { config } = $$;
19699 const scale = $$.isBubbleType(d) ? 1.15 : 1.75;
19700 return config.point_focus_expand_enabled ? config.point_focus_expand_r || $$.pointR(d) * scale : $$.pointR(d);
19701 },
19702 pointSelectR(d) {
19703 const $$ = this;
19704 const selectR = $$.config.point_select_r;
19705 return isFunction(selectR) ? selectR(d) : selectR || $$.pointR(d) * 4;
19706 },
19707 /**
19708 * Check if point.focus.only option can be applied.
19709 * @returns {boolean}
19710 * @private
19711 */
19712 isPointFocusOnly() {
19713 const $$ = this;
19714 return $$.config.point_focus_only && !$$.hasType("bubble") && !$$.hasType("scatter") && !$$.hasArcType(null, ["radar"]);
19715 },
19716 isWithinCircle(node, r) {
19717 const { state } = this;
19718 const mouse = getPointer(state.event, node);
19719 const element = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(node);
19720 const prefix = this.isCirclePoint(node) ? "c" : "";
19721 const pointSensitivity = this.getPointSensitivity(element == null ? void 0 : element.datum());
19722 let cx = +element.attr(`${prefix}x`);
19723 let cy = +element.attr(`${prefix}y`);
19724 if (!(cx || cy) && node.nodeType === 1) {
19725 const { x, y } = getBoundingRect(node);
19726 cx = x;
19727 cy = y;
19728 }
19729 return Math.sqrt(
19730 Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)
19731 ) < (r || pointSensitivity);
19732 },
19733 /**
19734 * Get data point sensitivity radius
19735 * @param {object} d Data point object
19736 * @returns {number} return the sensitivity value
19737 */
19738 getPointSensitivity(d) {
19739 const $$ = this;
19740 let sensitivity = $$.config.point_sensitivity;
19741 if (!d) {
19742 return sensitivity;
19743 } else if (isFunction(sensitivity)) {
19744 sensitivity = sensitivity.call($$.api, d);
19745 } else if (sensitivity === "radius") {
19746 sensitivity = d.r;
19747 }
19748 return sensitivity;
19749 },
19750 updatePointClass(d) {
19751 const $$ = this;
19752 const { circle } = $$.$el;
19753 let pointClass = false;
19754 if (isObject(d) || circle) {
19755 pointClass = d === true ? circle.each(function(d2) {
19756 let className = $$.getClass("circle", true)(d2);
19757 if (this.getAttribute("class").indexOf($COMMON.EXPANDED) > -1) {
19758 className += ` ${$COMMON.EXPANDED}`;
19759 }
19760 this.setAttribute("class", className);
19761 }) : $$.getClass("circle", true)(d);
19762 }
19763 return pointClass;
19764 },
19765 generateGetLinePoints(lineIndices, isSub) {
19766 const $$ = this;
19767 const { config } = $$;
19768 const x = $$.getShapeX(0, lineIndices, isSub);
19769 const y = $$.getShapeY(isSub);
19770 const lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, isSub);
19771 const yScale = $$.getYScaleById.bind($$);
19772 return (d, i) => {
19773 const y0 = yScale.call($$, d.id, isSub)($$.getShapeYMin(d.id));
19774 const offset = lineOffset(d, i) || y0;
19775 const posX = x(d);
19776 let posY = y(d);
19777 if (config.axis_rotated && (d.value > 0 && posY < y0 || d.value < 0 && y0 < posY)) {
19778 posY = y0;
19779 }
19780 const point = [posX, posY - (y0 - offset)];
19781 return [
19782 point,
19783 point,
19784 // from here and below, needed for compatibility
19785 point,
19786 point
19787 ];
19788 };
19789 },
19790 custom: {
19791 create(element, id, fillStyleFn) {
19792 return element.append("use").attr("xlink:href", `#${id}`).attr("class", this.updatePointClass.bind(this)).style("fill", fillStyleFn).node();
19793 },
19794 update(element, xPosFn, yPosFn, fillStyleFn, withTransition, flow, selectedCircles) {
19795 const $$ = this;
19796 const { width, height } = element.node().getBBox();
19797 const xPosFn2 = (d) => isValue(d.value) ? xPosFn(d) - width / 2 : 0;
19798 const yPosFn2 = (d) => isValue(d.value) ? yPosFn(d) - height / 2 : 0;
19799 let mainCircles = element;
19800 if (withTransition) {
19801 flow && mainCircles.attr("x", xPosFn2);
19802 mainCircles = $$.$T(mainCircles, withTransition, getTransitionName());
19803 selectedCircles && $$.$T(selectedCircles, withTransition, getTransitionName());
19804 }
19805 return mainCircles.attr("x", xPosFn2).attr("y", yPosFn2).style("fill", fillStyleFn);
19806 }
19807 },
19808 // 'circle' data point
19809 circle: {
19810 create(element, sizeFn, fillStyleFn) {
19811 return element.append("circle").attr("class", this.updatePointClass.bind(this)).attr("r", sizeFn).style("fill", fillStyleFn).node();
19812 },
19813 update(element, xPosFn, yPosFn, fillStyleFn, withTransition, flow, selectedCircles) {
19814 const $$ = this;
19815 let mainCircles = element;
19816 if ($$.hasType("bubble")) {
19817 mainCircles.attr("r", $$.pointR.bind($$));
19818 }
19819 if (withTransition) {
19820 flow && mainCircles.attr("cx", xPosFn);
19821 if (mainCircles.attr("cx")) {
19822 mainCircles = $$.$T(mainCircles, withTransition, getTransitionName());
19823 }
19824 selectedCircles && $$.$T(mainCircles, withTransition, getTransitionName());
19825 }
19826 return mainCircles.attr("cx", xPosFn).attr("cy", yPosFn).style("fill", fillStyleFn);
19827 }
19828 },
19829 // 'rectangle' data point
19830 rectangle: {
19831 create(element, sizeFn, fillStyleFn) {
19832 const rectSizeFn = (d) => sizeFn(d) * 2;
19833 return element.append("rect").attr("class", this.updatePointClass.bind(this)).attr("width", rectSizeFn).attr("height", rectSizeFn).style("fill", fillStyleFn).node();
19834 },
19835 update(element, xPosFn, yPosFn, fillStyleFn, withTransition, flow, selectedCircles) {
19836 const $$ = this;
19837 const r = $$.config.point_r;
19838 const rectXPosFn = (d) => xPosFn(d) - r;
19839 const rectYPosFn = (d) => yPosFn(d) - r;
19840 let mainCircles = element;
19841 if (withTransition) {
19842 flow && mainCircles.attr("x", rectXPosFn);
19843 mainCircles = $$.$T(mainCircles, withTransition, getTransitionName());
19844 selectedCircles && $$.$T(selectedCircles, withTransition, getTransitionName());
19845 }
19846 return mainCircles.attr("x", rectXPosFn).attr("y", rectYPosFn).style("fill", fillStyleFn);
19847 }
19848 }
19849});
19850
19851;// ./src/ChartInternal/shape/point.common.ts
19852
19853
19854
19855function hasValidPointDrawMethods(point) {
19856 return isObjectType(point) && isFunction(point.create) && isFunction(point.update);
19857}
19858function insertPointInfoDefs(point, id) {
19859 var _a;
19860 const $$ = this;
19861 const copyAttr = (from, target) => {
19862 const attribs = from.attributes;
19863 for (let i = 0, name; name = attribs[i]; i++) {
19864 name = name.name;
19865 target.setAttribute(name, from.getAttribute(name));
19866 }
19867 };
19868 const doc = new DOMParser().parseFromString(point, "image/svg+xml");
19869 const node = doc.documentElement;
19870 const clone = browser_doc.createElementNS(external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.namespaces.svg, node.nodeName.toLowerCase());
19871 clone.id = id;
19872 clone.style.fill = "inherit";
19873 clone.style.stroke = "inherit";
19874 copyAttr(node, clone);
19875 if ((_a = node.childNodes) == null ? void 0 : _a.length) {
19876 const parent = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(clone);
19877 if ("innerHTML" in clone) {
19878 parent.html(node.innerHTML);
19879 } else {
19880 toArray(node.childNodes).forEach((v) => {
19881 copyAttr(v, parent.append(v.tagName).node());
19882 });
19883 }
19884 }
19885 $$.$el.defs.node().appendChild(clone);
19886}
19887/* harmony default export */ var point_common = ({
19888 /**
19889 * Check if point type option is valid
19890 * @param {string} type point type
19891 * @returns {boolean}
19892 * @private
19893 */
19894 hasValidPointType(type) {
19895 return /^(circle|rect(angle)?|polygon|ellipse|use)$/i.test(type || this.config.point_type);
19896 },
19897 /**
19898 * Check if pattern point is set to be used on legend
19899 * @returns {boolean}
19900 * @private
19901 */
19902 hasLegendDefsPoint() {
19903 var _a;
19904 const { config } = this;
19905 return config.legend_show && ((_a = config.point_pattern) == null ? void 0 : _a.length) && config.legend_usePoint;
19906 },
19907 getDefsPointId(id) {
19908 const { state: { datetimeId } } = this;
19909 return `${datetimeId}-point${id}`;
19910 },
19911 /**
19912 * Get generate point function
19913 * @returns {Function}
19914 * @private
19915 */
19916 generatePoint() {
19917 const $$ = this;
19918 const { $el, config } = $$;
19919 const ids = [];
19920 const pattern = notEmpty(config.point_pattern) ? config.point_pattern : [config.point_type];
19921 return function(method, context, ...args) {
19922 return function(d) {
19923 var _a, _b, _c, _d;
19924 const id = $$.getTargetSelectorSuffix(d.id || ((_a = d.data) == null ? void 0 : _a.id) || d);
19925 const element = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this);
19926 ids.indexOf(id) < 0 && ids.push(id);
19927 let point = pattern[ids.indexOf(id) % pattern.length];
19928 if ($$.hasValidPointType(point)) {
19929 point = $$[point];
19930 } else if (!hasValidPointDrawMethods(point || config.point_type)) {
19931 const pointId = $$.getDefsPointId(id);
19932 const defsPoint = $el.defs.select(`#${pointId}`);
19933 if (defsPoint.size() < 1) {
19934 insertPointInfoDefs.bind($$)(point, pointId);
19935 }
19936 if (method === "create") {
19937 return (_b = $$.custom) == null ? void 0 : _b.create.bind(context)(element, pointId, ...args);
19938 } else if (method === "update") {
19939 return (_c = $$.custom) == null ? void 0 : _c.update.bind(context)(element, ...args);
19940 }
19941 }
19942 return (_d = point[method]) == null ? void 0 : _d.bind(context)(element, ...args);
19943 };
19944 };
19945 }
19946});
19947
19948;// ./src/ChartInternal/shape/polar.ts
19949
19950
19951function getDataMax($$) {
19952 const levelMax = $$.config.polar_level_max;
19953 let dataMax = $$.getMinMaxData().max[0].value;
19954 if (levelMax && levelMax > dataMax) {
19955 dataMax = levelMax;
19956 }
19957 return dataMax;
19958}
19959/* harmony default export */ var polar = ({
19960 /**
19961 * Initialize polar
19962 * @private
19963 */
19964 initPolar() {
19965 const $$ = this;
19966 const { $el: { arcs }, config } = $$;
19967 const levelTextShow = config.polar_level_text_show;
19968 const levelTextBgColor = config.polar_level_text_backgroundColor;
19969 arcs.levels = arcs.append("g").attr("class", $LEVEL.levels);
19970 if (levelTextShow && levelTextBgColor) {
19971 $$.generateTextBGColorFilter(levelTextBgColor);
19972 }
19973 },
19974 /**
19975 * Get polar outer radius according to the data value
19976 * @param {object} d Data object
19977 * @param {numbet} outerRadius Outer radius
19978 * @returns {number} outer radius
19979 * @private
19980 */
19981 getPolarOuterRadius(d, outerRadius) {
19982 var _a;
19983 const dataMax = getDataMax(this);
19984 return ((_a = d == null ? void 0 : d.data.values[0].value) != null ? _a : 0) / dataMax * outerRadius;
19985 },
19986 /**
19987 * Update polar based on given data array
19988 * @param {object} targets Data object
19989 * @private
19990 */
19991 updateTargetsForPolar(targets) {
19992 this.updateTargetsForArc(targets);
19993 },
19994 /**
19995 * Called whenever redraw happens
19996 * @private
19997 */
19998 redrawPolar() {
19999 const $$ = this;
20000 const { config } = $$;
20001 config.polar_level_show && $$.updatePolarLevel();
20002 },
20003 /**
20004 * Update polar level circle
20005 * @private
20006 */
20007 updatePolarLevel() {
20008 const $$ = this;
20009 const { config, state, $el: { arcs: { levels } } } = $$;
20010 const depth = config.polar_level_depth;
20011 const dataMax = getDataMax($$);
20012 const levelData = getRange(0, depth);
20013 const outerRadius = state.radius;
20014 const levelRatio = levelData.map((l) => outerRadius * ((l + 1) / depth));
20015 const levelTextFormat = (config.polar_level_text_format || function() {
20016 }).bind($$.api);
20017 const level = levels.selectAll(`.${$LEVEL.level}`).data(levelData);
20018 level.exit().remove();
20019 const levelEnter = level.enter().append("g").attr("class", (d, i) => `${$LEVEL.level} ${$LEVEL.level}-${i}`);
20020 levelEnter.append("circle");
20021 levelEnter.merge(level).selectAll("circle").style("visibility", config.polar_level_show ? null : "hidden").attr("cx", 0).attr("cy", 0).attr("r", (d) => levelRatio[d]);
20022 if (config.polar_level_text_show) {
20023 const levelTextBackgroundColor = config.polar_level_text_backgroundColor;
20024 const defsId = `#${state.datetimeId}-labels-bg${$$.getTargetSelectorSuffix(levelTextBackgroundColor)}`;
20025 levelEnter.append("text").style("text-anchor", "middle");
20026 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)));
20027 }
20028 }
20029});
20030
20031;// ./src/ChartInternal/shape/radar.ts
20032
20033
20034
20035
20036function getPosition(isClockwise, type, edge, pos, range, ratio) {
20037 const index = isClockwise && pos > 0 ? edge - pos : pos;
20038 const r = 2 * Math.PI;
20039 const func = type === "x" ? Math.sin : Math.cos;
20040 return range * (1 - ratio * func(index * r / edge));
20041}
20042const cacheKeyPoints = KEY.radarPoints;
20043const cacheKeyTextWidth = KEY.radarTextWidth;
20044/* harmony default export */ var radar = ({
20045 initRadar() {
20046 const $$ = this;
20047 const { config, state: { current }, $el } = $$;
20048 if ($$.hasType("radar")) {
20049 $el.radar = $el.main.select(`.${$COMMON.chart}`).append("g").attr("class", $RADAR.chartRadars);
20050 $el.radar.levels = $el.radar.append("g").attr("class", $LEVEL.levels);
20051 $el.radar.axes = $el.radar.append("g").attr("class", $AXIS.axis);
20052 $el.radar.shapes = $el.radar.append("g").attr("class", $SHAPE.shapes);
20053 current.dataMax = config.radar_axis_max || $$.getMinMaxData().max[0].value;
20054 if (config.radar_axis_text_show) {
20055 config.interaction_enabled && $$.bindRadarEvent();
20056 $$.updateRadarLevel();
20057 $$.updateRadarAxes();
20058 }
20059 }
20060 },
20061 getRadarSize() {
20062 const $$ = this;
20063 const { config, state: { arcWidth, arcHeight } } = $$;
20064 const padding = config.axis_x_categories.length < 4 ? -20 : 10;
20065 const size = (Math.min(arcWidth, arcHeight) - padding) / 2;
20066 return [size, size];
20067 },
20068 updateTargetsForRadar(targets) {
20069 const $$ = this;
20070 const { config } = $$;
20071 if (isEmpty(config.axis_x_categories)) {
20072 config.axis_x_categories = getRange(0, getMinMax("max", targets.map(
20073 (v) => v.values.length
20074 )));
20075 }
20076 $$.generateRadarPoints();
20077 },
20078 getRadarPosition(type, index, range, ratio) {
20079 const $$ = this;
20080 const { config } = $$;
20081 const [width, height] = $$.getRadarSize();
20082 const edge = config.axis_x_categories.length;
20083 const isClockwise = config.radar_direction_clockwise;
20084 const pos = toArray(type).map(
20085 (v) => getPosition(
20086 isClockwise,
20087 v,
20088 edge,
20089 index,
20090 isDefined(range) ? range : type === "x" ? width : height,
20091 isNumber(ratio) ? ratio : config.radar_size_ratio
20092 )
20093 );
20094 return pos.length === 1 ? pos[0] : pos;
20095 },
20096 /**
20097 * Generate data points
20098 * @private
20099 */
20100 generateRadarPoints() {
20101 const $$ = this;
20102 const targets = $$.data.targets;
20103 const [width, height] = $$.getRadarSize();
20104 const points = $$.cache.get(cacheKeyPoints) || {};
20105 const size = points._size;
20106 if (!size || size.width !== width && size.height !== height) {
20107 targets.forEach((d) => {
20108 points[d.id] = d.values.map((v, i) => $$.getRadarPosition(["x", "y"], i, void 0, $$.getRatio("radar", v)));
20109 });
20110 points._size = { width, height };
20111 $$.cache.add(cacheKeyPoints, points);
20112 }
20113 },
20114 redrawRadar() {
20115 const $$ = this;
20116 const { radar, main } = $$.$el;
20117 const translate = $$.getTranslate("radar");
20118 if (translate) {
20119 radar.attr("transform", translate);
20120 main.select(`.${$TEXT.chartTexts}`).attr("transform", translate);
20121 $$.generateRadarPoints();
20122 $$.updateRadarLevel();
20123 $$.updateRadarAxes();
20124 $$.updateRadarShape();
20125 }
20126 },
20127 generateGetRadarPoints() {
20128 const points = this.cache.get(cacheKeyPoints);
20129 return (d, i) => {
20130 const point = points[d.id][i];
20131 return [
20132 point,
20133 point,
20134 point,
20135 point
20136 ];
20137 };
20138 },
20139 updateRadarLevel() {
20140 const $$ = this;
20141 const { config, state, $el: { radar } } = $$;
20142 const [width, height] = $$.getRadarSize();
20143 const depth = config.radar_level_depth;
20144 const edge = config.axis_x_categories.length;
20145 const showText = config.radar_level_text_show;
20146 const radarLevels = radar.levels;
20147 const levelData = getRange(0, depth);
20148 const radius = config.radar_size_ratio * Math.min(width, height);
20149 const levelRatio = levelData.map((l) => radius * ((l + 1) / depth));
20150 const levelTextFormat = (config.radar_level_text_format || function() {
20151 }).bind($$.api);
20152 const points = levelData.map((v) => {
20153 const range = levelRatio[v];
20154 const pos = getRange(0, edge).map(
20155 (i) => $$.getRadarPosition(["x", "y"], i, range, 1).join(",")
20156 );
20157 return pos.join(" ");
20158 });
20159 const level = radarLevels.selectAll(`.${$LEVEL.level}`).data(levelData);
20160 level.exit().remove();
20161 const levelEnter = level.enter().append("g").attr("class", (d, i) => `${$LEVEL.level} ${$LEVEL.level}-${i}`);
20162 levelEnter.append("polygon").style("visibility", config.radar_level_show ? null : "hidden");
20163 if (showText) {
20164 if (radarLevels.select("text").empty()) {
20165 radarLevels.append("text").attr("dx", "-.5em").attr("dy", "-.7em").style("text-anchor", "end").text(() => levelTextFormat(0));
20166 }
20167 levelEnter.append("text").attr("dx", "-.5em").style("text-anchor", "end").text(
20168 (d) => levelTextFormat(
20169 state.current.dataMax / levelData.length * (d + 1)
20170 )
20171 );
20172 }
20173 levelEnter.merge(level).attr(
20174 "transform",
20175 (d) => `translate(${width - levelRatio[d]}, ${height - levelRatio[d]})`
20176 ).selectAll("polygon").attr("points", (d) => points[d]);
20177 if (showText) {
20178 radarLevels.selectAll("text").attr("x", (d) => isUndefined(d) ? width : points[d].split(",")[0]).attr("y", (d) => isUndefined(d) ? height : 0);
20179 }
20180 },
20181 updateRadarAxes() {
20182 const $$ = this;
20183 const { config, $el: { radar } } = $$;
20184 const [width, height] = $$.getRadarSize();
20185 const categories = config.axis_x_categories;
20186 let axis = radar.axes.selectAll("g").data(categories);
20187 axis.exit().remove();
20188 const axisEnter = axis.enter().append("g").attr("class", (d, i) => `${$AXIS.axis}-${i}`);
20189 config.radar_axis_line_show && axisEnter.append("line");
20190 config.radar_axis_text_show && axisEnter.append("text");
20191 axis = axisEnter.merge(axis);
20192 if (config.radar_axis_line_show) {
20193 axis.select("line").attr("x1", width).attr("y1", height).attr("x2", (d, i) => $$.getRadarPosition("x", i)).attr("y2", (d, i) => $$.getRadarPosition("y", i));
20194 }
20195 if (config.radar_axis_text_show) {
20196 const { x = 0, y = 0 } = config.radar_axis_text_position;
20197 const textWidth = $$.cache.get(cacheKeyTextWidth) || 0;
20198 axis.select("text").style("text-anchor", "middle").attr("dy", ".5em").call((selection) => {
20199 selection.each(function(d) {
20200 setTextValue((0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(this), String(d), [-0.6, 1.2]);
20201 });
20202 }).datum((d, i) => ({ index: i })).attr("transform", function(d) {
20203 if (isUndefined(this.width)) {
20204 this.width = this.getBoundingClientRect().width / 2;
20205 }
20206 let posX = $$.getRadarPosition("x", d.index, void 0, 1);
20207 let posY = Math.round($$.getRadarPosition("y", d.index, void 0, 1));
20208 if (posX > width) {
20209 posX += this.width + x;
20210 } else if (Math.round(posX) < width) {
20211 posX -= this.width + x;
20212 }
20213 if (posY > height) {
20214 if (posY / 2 === height && this.firstChild.tagName === "tspan") {
20215 this.firstChild.setAttribute("dy", "0em");
20216 }
20217 posY += y;
20218 } else if (posY < height) {
20219 posY -= y;
20220 }
20221 return `translate(${posX} ${posY})`;
20222 });
20223 if (!textWidth) {
20224 const widths = [radar.axes, radar.levels].map((v) => getPathBox(v.node()).width);
20225 if (widths.every((v) => v > 0)) {
20226 $$.cache.add(cacheKeyTextWidth, widths[0] - widths[1]);
20227 }
20228 }
20229 }
20230 },
20231 bindRadarEvent() {
20232 const $$ = this;
20233 const { config, state, $el: { radar, svg } } = $$;
20234 const focusOnly = $$.isPointFocusOnly();
20235 const { inputType, transiting } = state;
20236 const isMouse = inputType === "mouse";
20237 const hide = (event) => {
20238 state.event = event;
20239 if (!config.interaction_onout) {
20240 return;
20241 }
20242 const index = $$.getDataIndexFromEvent(event);
20243 const noIndex = isUndefined(index);
20244 if (isMouse || noIndex) {
20245 $$.hideTooltip();
20246 focusOnly ? $$.hideCircleFocus() : $$.unexpandCircles();
20247 if (isMouse) {
20248 $$.setOverOut(false, index);
20249 } else if (noIndex) {
20250 $$.callOverOutForTouch();
20251 }
20252 }
20253 };
20254 radar.axes.on(isMouse ? "mouseover " : "touchstart", (event) => {
20255 if (transiting) {
20256 return;
20257 }
20258 state.event = event;
20259 const index = $$.getDataIndexFromEvent(event);
20260 $$.selectRectForSingle(svg.node(), index);
20261 isMouse ? $$.setOverOut(true, index) : $$.callOverOutForTouch(index);
20262 }).on("mouseout", isMouse ? hide : null);
20263 if (!isMouse) {
20264 svg.on("touchstart", hide);
20265 }
20266 },
20267 updateRadarShape() {
20268 const $$ = this;
20269 const targets = $$.data.targets.filter((d) => $$.isRadarType(d));
20270 const points = $$.cache.get(cacheKeyPoints);
20271 const areas = $$.$el.radar.shapes.selectAll("polygon").data(targets);
20272 const areasEnter = areas.enter().append("g").attr("class", $$.getChartClass("Radar"));
20273 $$.$T(areas.exit()).remove();
20274 areasEnter.append("polygon").merge(areas).style("fill", $$.color).style("stroke", $$.color).attr("points", (d) => points[d.id].join(" "));
20275 $$.updateTargetForCircle(targets, areasEnter);
20276 },
20277 /**
20278 * Get data point x coordinate
20279 * @param {object} d Data object
20280 * @returns {number}
20281 * @private
20282 */
20283 radarCircleX(d) {
20284 return this.cache.get(cacheKeyPoints)[d.id][d.index][0];
20285 },
20286 /**
20287 * Get data point y coordinate
20288 * @param {object} d Data object
20289 * @returns {number}
20290 * @private
20291 */
20292 radarCircleY(d) {
20293 return this.cache.get(cacheKeyPoints)[d.id][d.index][1];
20294 }
20295});
20296
20297// EXTERNAL MODULE: external {"commonjs":"d3-hierarchy","commonjs2":"d3-hierarchy","amd":"d3-hierarchy","root":"d3"}
20298var external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_ = __webpack_require__(14);
20299;// ./src/ChartInternal/shape/treemap.ts
20300
20301
20302
20303
20304function position(group, root) {
20305 const $$ = this;
20306 const { scale: { x, y }, state: { width } } = $$;
20307 group.selectAll("g").attr("transform", (d) => `translate(${d === root ? "0,0" : `${x(d.x0)},${y(d.y0)}`})`).select("rect").attr("width", (d) => d === root ? width : x(d.x1) - x(d.x0)).attr("height", (d) => d === root ? 0 : y(d.y1) - y(d.y0));
20308}
20309function convertDataToTreemapData(data) {
20310 const $$ = this;
20311 return data.map((d) => {
20312 const { id, values } = d;
20313 const { value } = values[0];
20314 return {
20315 name: id,
20316 id,
20317 // needed to keep compatibility on whole code logic
20318 value,
20319 ratio: $$.getRatio("treemap", values[0])
20320 };
20321 });
20322}
20323function getHierachyData(data) {
20324 const $$ = this;
20325 const hierarchyData = (0,external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.hierarchy)(data).sum((d) => d.value);
20326 const sortFn = $$.getSortCompareFn(true);
20327 return [
20328 $$.treemap(
20329 sortFn ? hierarchyData.sort(sortFn) : hierarchyData
20330 )
20331 ];
20332}
20333/* harmony default export */ var treemap = ({
20334 initTreemap() {
20335 const $$ = this;
20336 const {
20337 $el,
20338 state: {
20339 current: { width, height },
20340 clip,
20341 datetimeId
20342 }
20343 } = $$;
20344 clip.id = `${datetimeId}-clip`;
20345 $$.treemap = (0,external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemap)().tile($$.getTreemapTile());
20346 $el.defs.append("clipPath").attr("id", clip.id).append("rect").attr("width", width).attr("height", height);
20347 $el.treemap = $el.main.select(`.${$COMMON.chart}`).attr("clip-path", `url(#${clip.id})`).append("g").classed($TREEMAP.chartTreemaps, true);
20348 $$.bindTreemapEvent();
20349 },
20350 /**
20351 * Bind events
20352 * @private
20353 */
20354 bindTreemapEvent() {
20355 const $$ = this;
20356 const { $el, config, state } = $$;
20357 const getTarget = (event) => {
20358 var _a;
20359 const target = event.isTrusted ? event.target : (_a = state.eventReceiver.rect) == null ? void 0 : _a.node();
20360 let data;
20361 if (/^rect$/i.test(target.tagName)) {
20362 state.event = event;
20363 data = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.select)(target).datum();
20364 }
20365 return data == null ? void 0 : data.data;
20366 };
20367 if (config.interaction_enabled) {
20368 const isTouch = state.inputType === "touch";
20369 $el.treemap.on(isTouch ? "touchstart" : "mouseover mousemove", (event) => {
20370 const data = getTarget(event);
20371 if (data) {
20372 $$.showTooltip([data], event.currentTarget);
20373 /^(touchstart|mouseover)$/.test(event.type) && $$.setOverOut(true, data);
20374 }
20375 }).on(isTouch ? "touchend" : "mouseout", (event) => {
20376 const data = getTarget(event);
20377 if (config.interaction_onout) {
20378 $$.hideTooltip();
20379 $$.setOverOut(false, data);
20380 }
20381 });
20382 }
20383 },
20384 /**
20385 * Get tiling function
20386 * @returns {Function}
20387 * @private
20388 */
20389 getTreemapTile() {
20390 var _a, _b;
20391 const $$ = this;
20392 const { config, state: { current: { width, height } } } = $$;
20393 const tile = (_b = {
20394 binary: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapBinary,
20395 dice: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapDice,
20396 slice: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapSlice,
20397 sliceDice: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapSliceDice,
20398 squarify: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapSquarify,
20399 resquarify: external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapResquarify
20400 }[(_a = config.treemap_tile) != null ? _a : "binary"]) != null ? _b : external_commonjs_d3_hierarchy_commonjs2_d3_hierarchy_amd_d3_hierarchy_root_d3_.treemapBinary;
20401 return (node, x0, y0, x1, y1) => {
20402 tile(node, 0, 0, width, height);
20403 for (const child of node.children) {
20404 child.x0 = x0 + child.x0 / width * (x1 - x0);
20405 child.x1 = x0 + child.x1 / width * (x1 - x0);
20406 child.y0 = y0 + child.y0 / height * (y1 - y0);
20407 child.y1 = y0 + child.y1 / height * (y1 - y0);
20408 }
20409 };
20410 },
20411 /**
20412 * Get treemap hierarchy data
20413 * @param {Array} targets Data targets
20414 * @returns {object}
20415 * @private
20416 */
20417 getTreemapData(targets) {
20418 const $$ = this;
20419 return {
20420 name: "root",
20421 children: convertDataToTreemapData.bind($$)(
20422 $$.filterTargetsToShow(targets.filter($$.isTreemapType, $$))
20423 )
20424 };
20425 },
20426 /**
20427 * Update treemap data
20428 * @param {Array} targets Data targets
20429 * @private
20430 */
20431 updateTargetsForTreemap(targets) {
20432 const $$ = this;
20433 const { $el: { treemap } } = $$;
20434 const treemapData = getHierachyData.call($$, $$.getTreemapData(targets != null ? targets : $$.data.targets));
20435 treemap.data(treemapData);
20436 },
20437 /**
20438 * Render treemap
20439 * @param {number} durationForExit Duration for exit transition
20440 * @private
20441 */
20442 updateTreemap(durationForExit) {
20443 const $$ = this;
20444 const { $el, $T } = $$;
20445 const data = $el.treemap.datum();
20446 const classChartTreemap = $$.getChartClass("Treemap");
20447 const classTreemap = $$.getClass("treemap", true);
20448 const treemap = $el.treemap.selectAll("g").data(data.children);
20449 $T(treemap.exit(), durationForExit).style("opacity", "0").remove();
20450 treemap.enter().append("g").append("rect");
20451 $el.treemap.selectAll("g").attr("class", classChartTreemap).select("rect").attr("class", classTreemap).attr("fill", (d) => $$.color(d.data.name));
20452 },
20453 /**
20454 * Generate treemap coordinate points data
20455 * @returns {Array} Array of coordinate points
20456 * @private
20457 */
20458 generateGetTreemapPoints() {
20459 const $$ = this;
20460 const { $el, scale: { x, y } } = $$;
20461 const points = {};
20462 $el.treemap.selectAll("g").each((d) => {
20463 points[d.data.name] = [
20464 [x(d.x0), y(d.y0)],
20465 [x(d.x1), y(d.y1)]
20466 ];
20467 });
20468 return (d) => points[d.id];
20469 },
20470 /**
20471 * Redraw treemap
20472 * @param {boolean} withTransition With or without transition
20473 * @returns {Array} Selections
20474 * @private
20475 */
20476 redrawTreemap(withTransition) {
20477 const $$ = this;
20478 const { $el, state: { current: { width, height } } } = $$;
20479 $el.defs.select("rect").attr("width", width).attr("height", height);
20480 return [
20481 $$.$T($el.treemap, withTransition, getRandom()).call(position.bind($$), $el.treemap.datum())
20482 ];
20483 },
20484 /**
20485 * Get treemap data label format function
20486 * @param {object} d Data object
20487 * @returns {Function}
20488 * @private
20489 */
20490 treemapDataLabelFormat(d) {
20491 const $$ = this;
20492 const { config } = $$;
20493 const { id, value } = d;
20494 const format = config.treemap_label_format;
20495 const ratio = $$.getRatio("treemap", d);
20496 const percentValue = (ratio * 100).toFixed(2);
20497 const meetLabelThreshold = config.treemap_label_show && $$.meetsLabelThreshold(
20498 ratio,
20499 "treemap"
20500 ) ? null : "0";
20501 return function(node) {
20502 node.style("opacity", meetLabelThreshold);
20503 return isFunction(format) ? format.bind($$.api)(value, ratio, id) : `${id}
20504${percentValue}%`;
20505 };
20506 }
20507});
20508
20509;// ./src/config/Options/common/point.ts
20510/* harmony default export */ var common_point = ({
20511 /**
20512 * Set point options
20513 * @name point
20514 * @memberof Options
20515 * @type {object}
20516 * @property {object} point Point object
20517 * @property {boolean} [point.show=true] Whether to show each point in line.
20518 * @property {number|Function} [point.r=2.5] The radius size of each point.
20519 * - **NOTE:** Disabled for 'bubble' type
20520 * @property {boolean|object} [point.radialGradient=false] Set the radial gradient on point.<br><br>
20521 * Or customize by giving below object value:
20522 * - cx {number}: `cx` value (default: `0.3`)
20523 * - cy {number}: `cy` value (default: `0.3`)
20524 * - r {number}: `r` value (default: `0.7`)
20525 * - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.
20526 * - (default: `[[0.1, $DATA_COLOR, 1], [0.9, $DATA_COLOR, 0]]`)
20527 * @property {boolean} [point.focus.expand.enabled=true] Whether to expand each point on focus.
20528 * @property {number} [point.focus.expand.r=point.r*1.75] The radius size of each point on focus.
20529 * - **NOTE:** For 'bubble' type, the default is `bubbleSize*1.15`
20530 * @property {boolean} [point.focus.only=false] Show point only when is focused.
20531 * @property {number|null} [point.opacity=undefined] Set point opacity value.
20532 * - **NOTE:**
20533 * - `null` will make to not set inline 'opacity' css prop.
20534 * - when no value(or undefined) is set, it defaults to set opacity value according its chart types.
20535 * @property {number|string|Function} [point.sensitivity=10] The senstivity value for interaction boundary.
20536 * - **Available Values:**
20537 * - {number}: Absolute sensitivity value which is the distance from the data point in pixel.
20538 * - "radius": sensitivity based on point's radius
20539 * - Function: callback for each point to determine the sensitivity<br>
20540 * ```js
20541 * sensitivity: function(d) {
20542 * // ex. of argument d:
20543 * // ==> {x: 2, value: 55, id: 'data3', index: 2, r: 19.820624179302296}
20544 *
20545 * // returning d.r, will make sensitivity same as point's radius value.
20546 * return d.r;
20547 * }
20548 * ```
20549 * @property {number} [point.select.r=point.r*4] The radius size of each point on selected.
20550 * @property {string} [point.type="circle"] The type of point to be drawn
20551 * - **NOTE:**
20552 * - If chart has 'bubble' type, only circle can be used.
20553 * - For IE, non circle point expansions are not supported due to lack of transform support.
20554 * - **Available Values:**
20555 * - circle
20556 * - rectangle
20557 * @property {Array} [point.pattern=[]] The type of point or svg shape as string, to be drawn for each line
20558 * - **NOTE:**
20559 * - This is an `experimental` feature and can have some unexpected behaviors.
20560 * - If chart has 'bubble' type, only circle can be used.
20561 * - For IE, non circle point expansions are not supported due to lack of transform support.
20562 * - **Available Values:**
20563 * - circle
20564 * - rectangle
20565 * - svg shape tag interpreted as string<br>
20566 * (ex. `<polygon points='2.5 0 0 5 5 5'></polygon>`)
20567 * @see [Demo: point type](https://naver.github.io/billboard.js/demo/#Point.RectanglePoints)
20568 * @see [Demo: point focus only](https://naver.github.io/billboard.js/demo/#Point.FocusOnly)
20569 * @see [Demo: point radialGradient](https://naver.github.io/billboard.js/demo/#Point.RadialGradientPoint)
20570 * @see [Demo: point sensitivity](https://naver.github.io/billboard.js/demo/#Point.PointSensitivity)
20571 * @example
20572 * point: {
20573 * show: false,
20574 * r: 5,
20575 *
20576 * // or customize the radius
20577 * r: function(d) {
20578 * ...
20579 * return r;
20580 * },
20581 *
20582 * // will generate follwing radialGradient:
20583 * // for more info: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/radialGradient
20584 * // <radualGradient cx="0.3" cy="0.3" r="0.7">
20585 * // <stop offset="0.1" stop-color="$DATA_COLOR" stop-opacity="1"></stop>
20586 * // <stop offset="0.9" stop-color="$DATA_COLOR" stop-opacity="0"></stop>
20587 * // </radialrGradient>
20588 * radialGradient: true,
20589 *
20590 * // Or customized gradient
20591 * radialGradient: {
20592 * cx: 0.3, // cx attributes
20593 * cy: 0.5, // cy attributes
20594 * r: 0.7, // r attributes
20595 * stops: [
20596 * // offset, stop-color, stop-opacity
20597 * [0, "#7cb5ec", 1],
20598 *
20599 * // setting 'null' for stop-color, will set its original data color
20600 * [0.5, null, 0],
20601 *
20602 * // setting 'function' for stop-color, will pass data id as argument.
20603 * // It should return color string or null value
20604 * [1, function(id) { return id === "data1" ? "red" : "blue"; }, 0],
20605 * ]
20606 * },
20607 *
20608 * focus: {
20609 * expand: {
20610 * enabled: true,
20611 * r: 1
20612 * },
20613 * only: true
20614 * },
20615 *
20616 * // do not set inline 'opacity' css prop setting
20617 * opacity: null,
20618 *
20619 * // set every data point's opacity value
20620 * opacity: 0.7,
20621 *
20622 * select: {
20623 * r: 3
20624 * },
20625 *
20626 * // having lower value, means how closer to be for interaction
20627 * sensitivity: 3,
20628 *
20629 * // sensitivity based on point's radius
20630 * sensitivity: "radius",
20631 *
20632 * // callback for each point to determine the sensitivity
20633 * sensitivity: function(d) {
20634 * // ex. of argument d:
20635 * // ==> {x: 2, value: 55, id: 'data3', index: 2, r: 19.820624179302296}
20636 *
20637 * // returning d.r, will make sensitivity same as point's radius value.
20638 * return d.r;
20639 * }
20640 *
20641 * // valid values are "circle" or "rectangle"
20642 * type: "rectangle",
20643 *
20644 * // or indicate as pattern
20645 * pattern: [
20646 * "circle",
20647 * "rectangle",
20648 * "<polygon points='0 6 4 0 -4 0'></polygon>"
20649 * ],
20650 * }
20651 */
20652 point_show: true,
20653 point_r: 2.5,
20654 point_radialGradient: false,
20655 point_sensitivity: 10,
20656 point_focus_expand_enabled: true,
20657 point_focus_expand_r: void 0,
20658 point_focus_only: false,
20659 point_opacity: void 0,
20660 point_pattern: [],
20661 point_select_r: void 0,
20662 point_type: "circle"
20663});
20664
20665;// ./src/config/Options/shape/area.ts
20666/* harmony default export */ var Options_shape_area = ({
20667 /**
20668 * Set area options
20669 * @name area
20670 * @memberof Options
20671 * @type {object}
20672 * @property {object} area Area object
20673 * @property {boolean} [area.above=false] Set background area `above` the data chart line.
20674 * @property {boolean} [area.below=false] Set background area `below` the data chart line.
20675 * - **NOTE**: Can't be used along with `above` option. When above & below options are set to true, `above` will be prioritized.
20676 * @property {boolean} [area.front=true] Set area node to be positioned over line node.
20677 * @property {boolean|object} [area.linearGradient=false] Set the linear gradient on area.<br><br>
20678 * Or customize by giving below object value:
20679 * - x {Array}: `x1`, `x2` value (default: `[0, 0]`)
20680 * - y {Array}: `y1`, `y2` value (default: `[0, 1]`)
20681 * - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.
20682 * - (default: `[[0, $DATA_COLOR, 1], [1, $DATA_COLOR, 0]]`)
20683 * @property {boolean} [area.zerobased=true] Set if min or max value will be 0 on area chart.
20684 * @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)
20685 * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.AreaChart)
20686 * @see [Demo: above](https://naver.github.io/billboard.js/demo/#AreaChartOptions.Above)
20687 * @see [Demo: below](https://naver.github.io/billboard.js/demo/#AreaChartOptions.Below)
20688 * @see [Demo: linearGradient](https://naver.github.io/billboard.js/demo/#AreaChartOptions.LinearGradient)
20689 * @example
20690 * area: {
20691 * above: true,
20692 * below: false,
20693 * zerobased: false,
20694 *
20695 * // <g class='bb-areas'> will be positioned behind the line <g class='bb-lines'> in stacking order
20696 * front: false,
20697 *
20698 * // will generate follwing linearGradient:
20699 * // for more info: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
20700 * // <linearGradient x1="0" x2="0" y1="0" y2="1">
20701 * // <stop offset="0" stop-color="$DATA_COLOR" stop-opacity="1"></stop>
20702 * // <stop offset="1" stop-color="$DATA_COLOR" stop-opacity="0"></stop>
20703 * // </linearGradient>
20704 * linearGradient: true,
20705 *
20706 * // Or customized gradient
20707 * linearGradient: {
20708 * x: [0, 0], // x1, x2 attributes
20709 * y: [0, 0], // y1, y2 attributes
20710 * stops: [
20711 * // offset, stop-color, stop-opacity
20712 * [0, "#7cb5ec", 1],
20713 *
20714 * // setting 'null' for stop-color, will set its original data color
20715 * [0.5, null, 0],
20716 *
20717 * // setting 'function' for stop-color, will pass data id as argument.
20718 * // It should return color string or null value
20719 * [1, function(id) { return id === "data1" ? "red" : "blue"; }, 0],
20720 * ]
20721 * }
20722 * }
20723 */
20724 area_above: false,
20725 area_below: false,
20726 area_front: true,
20727 area_linearGradient: false,
20728 area_zerobased: true
20729});
20730
20731;// ./src/config/Options/shape/bar.ts
20732/* harmony default export */ var shape_bar = ({
20733 /**
20734 * Set bar options
20735 * @name bar
20736 * @memberof Options
20737 * @type {object}
20738 * @property {object} bar Bar object
20739 * @property {boolean} [bar.front=false] Set 'bar' to be positioned over(on the top) other shapes elements.
20740 * @property {number} [bar.indices.removeNull=false] Remove nullish data on bar indices positions.
20741 * @property {number} [bar.label.threshold=0] Set threshold ratio to show/hide labels.
20742 * @property {boolean|object} [bar.linearGradient=false] Set the linear gradient on bar.<br><br>
20743 * Or customize by giving below object value:
20744 * - x {Array}: `x1`, `x2` value (default: `[0, 0]`)
20745 * - y {Array}: `y1`, `y2` value (default: `[0, 1]`)
20746 * - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.
20747 * - (default: `[[0, $DATA_COLOR, 1], [1, $DATA_COLOR, 0]]`)
20748 * @property {boolean} [bar.overlap=false] Bars will be rendered at same position, which will be overlapped each other. (for non-grouped bars only)
20749 * @property {number} [bar.padding=0] The padding pixel value between each bar.
20750 * @property {number} [bar.radius] Set the radius of bar edge in pixel.
20751 * @property {number} [bar.radius.ratio] Set the radius ratio of bar edge in relative the bar's width.
20752 * @property {number} [bar.sensitivity=2] The senstivity offset value for interaction boundary.
20753 * @property {number|Function|object} [bar.width] Change the width of bar chart.
20754 * @property {number} [bar.width.ratio=0.6] Change the width of bar chart by ratio.
20755 * - **NOTE:** Criteria for ratio.
20756 * - When x ticks count is same with the data count, the baseline for ratio is the minimum interval value of x ticks.
20757 * - 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`
20758 * - if the minimum interval is 30px, then ratio=1 means 30px.
20759 * - When x ticks count is lower than the data count, the baseline will be calculated as `chart width / data count`.
20760 * - ex. when chart width is 500, data count is 5, then ratio=1 means 100px.
20761 * @property {number} [bar.width.max] The maximum width value for ratio.
20762 * @property {number} [bar.width.dataname] Change the width of bar for indicated dataset only.
20763 * @property {number} [bar.width.dataname.ratio=0.6] Change the width of bar chart by ratio.
20764 * - **NOTE:**
20765 * - Works only for non-stacked bar
20766 * @property {number} [bar.width.dataname.max] The maximum width value for ratio.
20767 * @property {boolean} [bar.zerobased=true] Set if min or max value will be 0 on bar chart.
20768 * @see [Demo: bar front](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarFront)
20769 * @see [Demo: bar indices](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarIndices)
20770 * @see [Demo: bar overlap](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarOverlap)
20771 * @see [Demo: bar padding](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarPadding)
20772 * @see [Demo: bar radius](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarRadius)
20773 * @see [Demo: bar width](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidth)
20774 * @see [Demo: bar width variant](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidthVariant)
20775 * @example
20776 * bar: {
20777 * // make bar shape to be positioned over the other shape elements
20778 * front: true,
20779 *
20780 * // remove nullish data on bar indices postions
20781 * indices: {
20782 * removeNull: true
20783 * },
20784 *
20785 * // will generate follwing linearGradient:
20786 * // for more info: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
20787 * // <linearGradient x1="0" x2="0" y1="0" y2="1">
20788 * // <stop offset="0" stop-color="$DATA_COLOR" stop-opacity="1"></stop>
20789 * // <stop offset="1" stop-color="$DATA_COLOR" stop-opacity="0"></stop>
20790 * // </linearGradient>
20791 * linearGradient: true,
20792 *
20793 * // Or customized gradient
20794 * linearGradient: {
20795 * x: [0, 0], // x1, x2 attributes
20796 * y: [0, 0], // y1, y2 attributes
20797 * stops: [
20798 * // offset, stop-color, stop-opacity
20799 * [0, "#7cb5ec", 1],
20800 *
20801 * // setting 'null' for stop-color, will set its original data color
20802 * [0.5, null, 0],
20803 *
20804 * // setting 'function' for stop-color, will pass data id as argument.
20805 * // It should return color string or null value
20806 * [1, function(id) { return id === "data1" ? "red" : "blue"; }, 0],
20807 * ]
20808 * },
20809 *
20810 * // remove nullish da
20811 * overlap: true,
20812 *
20813 * padding: 1,
20814 *
20815 * // bar radius
20816 * radius: 10,
20817 * // or
20818 * radius: {
20819 * ratio: 0.5
20820 * }
20821 *
20822 * label: {
20823 * // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the y Axis domain range value.
20824 * // if data value is below than 0.1, text label will be hidden.
20825 * threshold: 0.1,
20826 * },
20827 *
20828 * // will not have offset between each bar elements for interaction
20829 * sensitivity: 0,
20830 *
20831 * width: 10,
20832 *
20833 * // or specify width callback. The callback will receive width, targetsNum, maxDataCount as arguments.
20834 * // - width: chart area width
20835 * // - targetsNum: number of targets
20836 * // - maxDataCount: maximum data count among targets
20837 * width: function(width, targetsNum, maxDataCount) {
20838 * return width / (targetsNum * maxDataCount);
20839 * }
20840 *
20841 * // or specify ratio & max
20842 * width: {
20843 * ratio: 0.2,
20844 * max: 20
20845 * },
20846 *
20847 * // or specify width per dataset
20848 * width: {
20849 * data1: 20,
20850 * data2: {
20851 * ratio: 0.2,
20852 * max: 20
20853 * }
20854 * },
20855 *
20856 * zerobased: false
20857 * }
20858 */
20859 bar_front: false,
20860 bar_indices_removeNull: false,
20861 bar_label_threshold: 0,
20862 bar_linearGradient: false,
20863 bar_overlap: false,
20864 bar_padding: 0,
20865 bar_radius: void 0,
20866 bar_radius_ratio: void 0,
20867 bar_sensitivity: 2,
20868 bar_width: void 0,
20869 bar_width_ratio: 0.6,
20870 bar_width_max: void 0,
20871 bar_zerobased: true
20872});
20873
20874;// ./src/config/Options/shape/bubble.ts
20875/* harmony default export */ var shape_bubble = ({
20876 /**
20877 * Set bubble options
20878 * @name bubble
20879 * @memberof Options
20880 * @type {object}
20881 * @property {object} bubble bubble object
20882 * @property {number|Function} [bubble.maxR=35] Set the max bubble radius value
20883 * @property {boolean} [bubble.zerobased=false] Set if min or max value will be 0 on bubble chart.
20884 * @example
20885 * bubble: {
20886 * // ex) If 100 is the highest value among data bound, the representation bubble of 100 will have radius of 50.
20887 * // And the lesser will have radius relatively from tha max value.
20888 * maxR: 50,
20889 *
20890 * // or set radius callback
20891 * maxR: function(d) {
20892 * // ex. of d param - {x: Fri Oct 06 2017 00:00:00 GMT+0900, value: 80, id: "data2", index: 5}
20893 * ...
20894 * return Math.sqrt(d.value * 2);
20895 * },
20896 * zerobased: false
20897 * }
20898 */
20899 bubble_maxR: 35,
20900 bubble_zerobased: false
20901});
20902
20903;// ./src/config/Options/shape/candlestick.ts
20904/* harmony default export */ var shape_candlestick = ({
20905 /**
20906 * Set candlestick options
20907 * @name candlestick
20908 * @memberof Options
20909 * @type {object}
20910 * @property {object} candlestick Candlestick object
20911 * @property {number} [candlestick.width] Change the width.
20912 * @property {number} [candlestick.width.ratio=0.6] Change the width by ratio.
20913 * @property {number} [candlestick.width.max] The maximum width value for ratio.
20914 * @property {number} [candlestick.width.dataname] Change the width for indicated dataset only.
20915 * @property {number} [candlestick.width.dataname.ratio=0.6] Change the width of bar chart by ratio.
20916 * @property {number} [candlestick.width.dataname.max] The maximum width value for ratio.
20917 * @property {object} [candlestick.color] Color setting.
20918 * @property {string|object} [candlestick.color.down] Change down(bearish) value color.
20919 * @property {string} [candlestick.color.down.dataname] Change down value color for indicated dataset only.
20920 *
20921 * @see [Demo](https://naver.github.io/billboard.js/demo/##Chart.CandlestickChart)
20922 * @example
20923 * candlestick: {
20924 * width: 10,
20925 *
20926 * // or
20927 * width: {
20928 * ratio: 0.2,
20929 * max: 20
20930 * },
20931 *
20932 * // or specify width per dataset
20933 * width: {
20934 * data1: 20,
20935 * data2: {
20936 * ratio: 0.2,
20937 * max: 20
20938 * }
20939 * },
20940 * color: {
20941 * // spcify bearish color
20942 * down: "red",
20943 *
20944 * // or specify color per dataset
20945 * down: {
20946 * data1: "red",
20947 * data2: "blue",
20948 * }
20949 * }
20950 * }
20951 */
20952 candlestick_width: void 0,
20953 candlestick_width_ratio: 0.6,
20954 candlestick_width_max: void 0,
20955 candlestick_color_down: "red"
20956});
20957
20958;// ./src/config/Options/shape/line.ts
20959/* harmony default export */ var shape_line = ({
20960 /**
20961 * Set line options
20962 * @name line
20963 * @memberof Options
20964 * @type {object}
20965 * @property {object} line Line object
20966 * @property {boolean} [line.connectNull=false] Set if null data point will be connected or not.<br>
20967 * 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.
20968 * @property {Array} [line.classes=undefined] If set, used to set a css class on each line.
20969 * @property {boolean} [line.step.type=step] Change step type for step chart.<br>
20970 * **Available values:**
20971 * - step
20972 * - step-before
20973 * - step-after
20974 * @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.
20975 * @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.
20976 * @property {boolean} [line.zerobased=false] Set if min or max value will be 0 on line chart.
20977 * @example
20978 * line: {
20979 * connectNull: true,
20980 * classes: [
20981 * "line-class1",
20982 * "line-class2"
20983 * ],
20984 * step: {
20985 * type: "step-after",
20986 *
20987 * // to have cursor/tooltip match to hovered step's point instead of nearest point.
20988 * tooltipMatch: true
20989 * },
20990 *
20991 * // hide all data points ('point.show=false' also has similar effect)
20992 * point: false,
20993 *
20994 * // show data points for only indicated datas
20995 * point: [
20996 * "data1", "data3"
20997 * ],
20998 *
20999 * zerobased: false
21000 * }
21001 */
21002 line_connectNull: false,
21003 line_step_type: "step",
21004 line_step_tooltipMatch: false,
21005 line_zerobased: false,
21006 line_classes: void 0,
21007 line_point: true
21008});
21009
21010;// ./src/config/Options/shape/scatter.ts
21011/* harmony default export */ var scatter = ({
21012 /**
21013 * Set scatter options
21014 * @name scatter
21015 * @memberof Options
21016 * @type {object}
21017 * @property {object} [scatter] scatter object
21018 * @property {boolean} [scatter.zerobased=false] Set if min or max value will be 0 on scatter chart.
21019 * @example
21020 * scatter: {
21021 * connectNull: true,
21022 * step: {
21023 * type: "step-after"
21024 * },
21025 *
21026 * // hide all data points ('point.show=false' also has similar effect)
21027 * point: false,
21028 *
21029 * // show data points for only indicated datas
21030 * point: [
21031 * "data1", "data3"
21032 * ],
21033 *
21034 * zerobased: false
21035 * }
21036 */
21037 scatter_zerobased: false
21038});
21039
21040;// ./src/config/Options/shape/spline.ts
21041/* harmony default export */ var spline = ({
21042 /**
21043 * Set spline options
21044 * - **Available interpolation type values:**
21045 * - basis (d3.curveBasis)
21046 * - basis-closed (d3.curveBasisClosed)
21047 * - basis-open (d3.curveBasisOpen)
21048 * - bundle (d3.curveBundle)
21049 * - cardinal (d3.curveCardinal)
21050 * - cardinal-closed (d3.curveCardinalClosed)
21051 * - cardinal-open (d3.curveCardinalOpen)
21052 * - catmull-rom (d3.curveCatmullRom)
21053 * - catmull-rom-closed (d3.curveCatmullRomClosed)
21054 * - catmull-rom-open (d3.curveCatmullRomOpen)
21055 * - monotone-x (d3.curveMonotoneX)
21056 * - monotone-y (d3.curveMonotoneY)
21057 * - natural (d3.curveNatural)
21058 * - linear-closed (d3.curveLinearClosed)
21059 * - linear (d3.curveLinear)
21060 * - step (d3.curveStep)
21061 * - step-after (d3.curveStepAfter)
21062 * - step-before (d3.curveStepBefore)
21063 * @name spline
21064 * @memberof Options
21065 * @type {object}
21066 * @property {object} spline Spline object
21067 * @property {object} spline.interpolation Spline interpolation object
21068 * @property {string} [spline.interpolation.type="cardinal"] Interpolation type
21069 * @see [Interpolation (d3 v4)](http://bl.ocks.org/emmasaunders/c25a147970def2b02d8c7c2719dc7502)
21070 * @example
21071 * spline: {
21072 * interpolation: {
21073 * type: "cardinal"
21074 * }
21075 * }
21076 */
21077 spline_interpolation_type: "cardinal"
21078});
21079
21080;// ./src/config/Options/shape/arc.ts
21081/* harmony default export */ var shape_arc = ({
21082 /**
21083 * Set arc options
21084 * @name arc
21085 * @memberof Options
21086 * @type {object}
21087 * @property {object} arc Arc object
21088 * @property {number|Function} [arc.cornerRadius=0] Set corner radius of Arc(donut/gauge/pie/polar) shape.
21089 * - **NOTE:**
21090 * - Corner radius can't surpass the `(outerRadius - innerRadius) /2` of indicated shape.
21091 * @property {number} [arc.cornerRadius.ratio=0] Set ratio relative of outer radius.
21092 * @property {object} [arc.needle] Set needle options.
21093 * @property {boolean} [arc.needle.show=false] Show or hide needle.
21094 * @property {string} [arc.needle.color] Set needle filled color.
21095 * @property {Function} [arc.needle.path] Set custom needle path function.
21096 * - **NOTE:**
21097 * - The path should be starting from 0,0 (which is center) to top center coordinate.
21098 * - The function will receive, `length`{number} parameter which indicating the needle length in pixel relative to radius.
21099 * @property {number} [arc.needle.value] Set needle value.
21100 * - **NOTE:**
21101 * - For single gauge chart, needle will point the data value by default, otherwise will point 0(zero).
21102 * @property {number} [arc.needle.length=100] Set needle length in percentages relative to radius.
21103 * @property {object} [arc.needle.top] Set needle top options.
21104 * @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).
21105 * @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).
21106 * @property {number} [arc.needle.top.width=0] Set needle top width in pixel.
21107 * @property {object} [arc.needle.bottom] Set needle bottom options.
21108 * @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).
21109 * @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).
21110 * @property {number} [arc.needle.bottom.width=15] Set needle bottom width in pixel.
21111 * @property {number} [arc.needle.bottom.len=0] Set needle bottom length in pixel. Setting this value, will make bottom larger starting from center.
21112 * @property {object} [arc.rangeText] Set rangeText options.
21113 * @property {Array} [arc.rangeText.values] Set range text values to be shown around Arc.
21114 * - When `unit: 'absolute'`: Given values are treated as absolute values.
21115 * - When `unit: '%'`: Given values are treated as percentages.
21116 * @property {string} [arc.rangeText.unit="absolute"] Specify the range text unit.
21117 * - "absolute": Show absolute value
21118 * - "%": Show percentage value
21119 * @property {boolean} [arc.rangeText.fiexed=false] Set if range text shown will be fixed w/o data toggle update. Only available for gauge chart.
21120 * @property {Function} [arc.rangeText.format] Set format function for the range text.
21121 * @property {number} [arc.rangeText.position] Set position function or object for the range text.
21122 * @see [Demo: Donut corner radius](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutCornerRadius)
21123 * @see [Demo: Donut corner radius](https://naver.github.io/billboard.js/demo/#PieChartOptions.CornerRadius)
21124 * @see [Demo: Donut needle](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutNeedle)
21125 * @see [Demo: Donut RangeText](https://naver.github.io/billboard.js/demo/#DonutChartOptions.DonutRangeText)
21126 * @see [Demo: Gauge corner radius](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeCornerRadius)
21127 * @see [Demo: Gauge needle](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeNeedle)
21128 * @see [Demo: Gauge RangeText](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeRangeText)
21129 * @example
21130 * arc: {
21131 * cornerRadius: 12,
21132 *
21133 * // can customize corner radius for each data with function callback
21134 * //
21135 * // The function will receive:
21136 * // - id {string}: Data id
21137 * // - value {number}: Data value
21138 * // - outerRadius {number}: Outer radius value
21139 * cornerRadius: function(id, value, outerRadius) {
21140 * return (id === "data1" && value > 10) ?
21141 * 50 : outerRadius * 1.2;
21142 * },
21143 *
21144 * // set ratio relative of outer radius
21145 * cornerRadius: {
21146 * ratio: 0.5
21147 * },
21148 *
21149 * needle: {
21150 * show: true,
21151 * color: "red", // any valid CSS color
21152 * path: function(length) {
21153 * const len = length - 20;
21154 *
21155 * // will return upper arrow shape path
21156 * // Note: The path should begun from '0,0' coordinate to top center.
21157 * const path = `M 0 -${len + 20}
21158 * L -12 -${len}
21159 * L -5 -${len}
21160 * L -5 0
21161 * A 1 1 0 0 0 5 0
21162 * L 5 -${len}
21163 * L 12 -${len} Z`;
21164 *
21165 * return path;
21166 * },
21167 * value: 40, // will make needle to point value 40.
21168 * length: 80, // needle length in percentages relative to radius.
21169 *
21170 * top: {
21171 * // rx and ry are the two radii of the ellipse;
21172 * // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve
21173 * rx: 1,
21174 * ry: 1,
21175 * width: 5
21176 * },
21177 * bottom: {
21178 * // rx and ry are the two radii of the ellipse;
21179 * // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#elliptical_arc_curve
21180 * rx: 1,
21181 * ry: 1,
21182 * width: 10
21183 * len: 10
21184 * }
21185 * },
21186 *
21187 * rangeText: {
21188 * values: [15, 30, 50, 75, 95],
21189 * unit: "%",
21190 * fixed: false, // only available for gauge chart
21191 * format: function(v) {
21192 * return v === 15 ? "Fifteen" : v;
21193 * },
21194 *
21195 * position: function(v) {
21196 * return v === 15 ? {x: 20, y: 10} : null; // can return one props value also.
21197 * },
21198 * position: {x: 10, y: 15},
21199 * position: {x: 10}
21200 * }
21201 * }
21202 */
21203 arc_cornerRadius: 0,
21204 arc_cornerRadius_ratio: 0,
21205 arc_needle_show: false,
21206 arc_needle_color: void 0,
21207 arc_needle_value: void 0,
21208 arc_needle_path: void 0,
21209 arc_needle_length: 100,
21210 arc_needle_top_rx: 0,
21211 arc_needle_top_ry: 0,
21212 arc_needle_top_width: 0,
21213 arc_needle_bottom_rx: 1,
21214 arc_needle_bottom_ry: 1,
21215 arc_needle_bottom_width: 15,
21216 arc_needle_bottom_len: 0,
21217 arc_rangeText_values: void 0,
21218 arc_rangeText_unit: "absolute",
21219 arc_rangeText_fixed: false,
21220 arc_rangeText_format: void 0,
21221 arc_rangeText_position: void 0
21222});
21223
21224;// ./src/config/Options/shape/donut.ts
21225/* harmony default export */ var donut = ({
21226 /**
21227 * Set donut options
21228 * @name donut
21229 * @memberof Options
21230 * @type {object}
21231 * @property {object} donut Donut object
21232 * @property {boolean} [donut.label.show=true] Show or hide label on each donut piece.
21233 * @property {Function} [donut.label.format] Set formatter for the label on each donut piece.
21234 * @property {number} [donut.label.threshold=0.05] Set threshold ratio to show/hide labels.
21235 * @property {number|Function} [donut.label.ratio=undefined] Set ratio of labels position.
21236 * @property {boolean} [donut.expand=true] Enable or disable expanding donut pieces.
21237 * @property {number} [donut.expand.rate=0.98] Set expand rate.
21238 * @property {number} [donut.expand.duration=50] Set expand transition time in ms.
21239 * @property {number} [donut.width] Set width of donut chart.
21240 * @property {string} [donut.title=""] Set title of donut chart. Use `\n` character for line break.
21241 * - **NOTE:**
21242 * - When `arc.needle.show=true` is set, special template `{=NEEDLE_VALUE}` can be used inside the title text to show current needle value.
21243 * @property {number} [donut.padAngle=0] Set padding between data.
21244 * @property {number} [donut.startingAngle=0] Set starting angle where data draws.
21245 * @example
21246 * donut: {
21247 * label: {
21248 * show: false,
21249 * format: function(value, ratio, id) {
21250 * return d3.format("$")(value);
21251 *
21252 * // to multiline, return with '\n' character
21253 * // return value +"%\nLine1\n2Line2";
21254 * },
21255 *
21256 * // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
21257 * // if data value is below than 0.1, text label will be hidden.
21258 * threshold: 0.1,
21259 *
21260 * // set ratio callback. Should return ratio value
21261 * ratio: function(d, radius, h) {
21262 * ...
21263 * return ratio;
21264 * },
21265 * // or set ratio number
21266 * ratio: 0.5
21267 * },
21268 *
21269 * // disable expand transition for interaction
21270 * expand: false,
21271 *
21272 * expand: {
21273 * // set duration of expand transition to 500ms.
21274 * duration: 500,
21275 *
21276 * // set expand area rate
21277 * rate: 1
21278 * },
21279 *
21280 * width: 10,
21281 * padAngle: 0.2,
21282 * startingAngle: 1,
21283 * title: "Donut Title"
21284 *
21285 * // when 'arc.needle.show=true' is set, can show current needle value.
21286 * title: "Needle value:\n{=NEEDLE_VALUE}",
21287 *
21288 * // title with line break
21289 * title: "Title1\nTitle2"
21290 * }
21291 */
21292 donut_label_show: true,
21293 donut_label_format: void 0,
21294 donut_label_threshold: 0.05,
21295 donut_label_ratio: void 0,
21296 donut_width: void 0,
21297 donut_title: "",
21298 donut_expand: {},
21299 donut_expand_rate: 0.98,
21300 donut_expand_duration: 50,
21301 donut_padAngle: 0,
21302 donut_startingAngle: 0
21303});
21304
21305;// ./src/config/Options/shape/funnel.ts
21306/* harmony default export */ var shape_funnel = ({
21307 /**
21308 * Set funnel options
21309 * @name funnel
21310 * @memberof Options
21311 * @type {object}
21312 * @property {object} funnel Funnel object
21313 * @property {number} [funnel.neck.width=0] Set funnel neck width.
21314 * @property {number} [funnel.neck.height=0] Set funnel neck height.
21315 * @property {number} [funnel.neck.width.ratio] Set funnel neck width in ratio.
21316 * @property {number} [funnel.neck.height.ratio] Set funnel neck height in ratio.
21317 * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.PolarChart)
21318 * @example
21319 * funnel: {
21320 * neck: {
21321 * width: 200,
21322 * height: 100,
21323 *
21324 * // or specify as ratio value (relative to the chart size)
21325 * width: {
21326 * ratio: 0.5
21327 * },
21328 * height: {
21329 * ratio: 0.5
21330 * }
21331 * }
21332 * }
21333 */
21334 funnel_neck_width: 0,
21335 funnel_neck_height: 0
21336});
21337
21338;// ./src/config/Options/shape/gauge.ts
21339/* harmony default export */ var shape_gauge = ({
21340 /**
21341 * Set gauge options
21342 * @name gauge
21343 * @memberof Options
21344 * @type {object}
21345 * @property {object} gauge Gauge object
21346 * @property {boolean} [gauge.background=""] Set background color. (The `.bb-chart-arcs-background` element)
21347 * @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.
21348 * @property {boolean} [gauge.label.show=true] Show or hide label on gauge.
21349 * @property {Function} [gauge.label.extents] Set customized min/max label text.
21350 * @property {Function} [gauge.label.format] Set formatter for the label on gauge. Label text can be multilined with `\n` character.<br>
21351 * Will pass following arguments to the given function:
21352 * - value {number}: absolute value
21353 * - ratio {number}: value's ratio
21354 * - id {string}: data's id value
21355 * @property {number|Function} [gauge.label.ratio=undefined] Set ratio of labels position.
21356 * @property {number} [gauge.label.threshold=0] Set threshold ratio to show/hide labels.
21357 * @property {boolean} [gauge.expand=true] Enable or disable expanding gauge.
21358 * @property {number} [gauge.expand.rate=0.98] Set expand rate.
21359 * @property {number} [gauge.expand.duration=50] Set the expand transition time in milliseconds.
21360 * @property {boolean} [gauge.enforceMinMax=false] Enforce to given min/max value.
21361 * - When `gauge.min=50` and given value is `30`, gauge will render as empty value.
21362 * - When `gauge.max=100` and given value is `120`, gauge will render till 100, not surpassing max value.
21363 * @property {number} [gauge.min=0] Set min value of the gauge.
21364 * @property {number} [gauge.max=100] Set max value of the gauge.
21365 * @property {number} [gauge.startingAngle=-1 * Math.PI / 2] Set starting angle where data draws.
21366 *
21367 * **Limitations:**
21368 * - when `gauge.fullCircle=false`:
21369 * - -1 * Math.PI / 2 <= startingAngle <= Math.PI / 2
21370 * - `startingAngle <= -1 * Math.PI / 2` defaults to `-1 * Math.PI / 2`
21371 * - `startingAngle >= Math.PI / 2` defaults to `Math.PI / 2`
21372 * - when `gauge.fullCircle=true`:
21373 * - -1 * Math.PI < startingAngle < Math.PI
21374 * - `startingAngle < -1 * Math.PI` defaults to `Math.PI`
21375 * - `startingAngle > Math.PI` defaults to `Math.PI`
21376 * @property {number} [gauge.arcLength=100] Set the length of the arc to be drawn in percent from -100 to 100.<br>
21377 * Negative value will draw the arc **counterclockwise**. Need to be used in conjunction with `gauge.fullCircle=true`.
21378 *
21379 * **Limitations:**
21380 * - -100 <= arcLength (in percent) <= 100
21381 * - 'arcLength < -100' defaults to -100
21382 * - 'arcLength > 100' defaults to 100
21383 * @property {string} [gauge.title=""] Set title of gauge chart. Use `\n` character for line break.
21384 * - **NOTE:**
21385 * - When `arc.needle.show=true` is set, special template `{=NEEDLE_VALUE}` can be used inside the title text to show current needle value.
21386 * @property {string} [gauge.units] Set units of the gauge.
21387 * @property {number} [gauge.width] Set width of gauge chart.
21388 * @property {string} [gauge.type="single"] Set type of gauge to be displayed.<br><br>
21389 * **Available Values:**
21390 * - single
21391 * - multi
21392 * @property {number} [gauge.arcs.minWidth=5] Set minimal width of gauge arcs until the innerRadius disappears.
21393 * @see [Demo: enforceMinMax, min/max](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeMinMax)
21394 * @see [Demo: archLength](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeArcLength)
21395 * @see [Demo: startingAngle](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeStartingAngle)
21396 * @see [Demo: labelRatio](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeLabelRatio)
21397 * @example
21398 * gauge: {
21399 * background: "#eee", // will set 'fill' css prop for '.bb-chart-arcs-background' classed element.
21400 * fullCircle: false,
21401 * label: {
21402 * show: false,
21403 * format: function(value, ratio, id) {
21404 * return value;
21405 *
21406 * // to multiline, return with '\n' character
21407 * // return value +"%\nLine1\n2Line2";
21408 * },
21409 *
21410 * extents: function(value, isMax) {
21411 * return (isMax ? "Max:" : "Min:") + value;
21412 * },
21413 *
21414 * // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
21415 * // if data value is below than 0.1, text label will be hidden.
21416 * threshold: 0.1,
21417 *
21418 * // set ratio callback. Should return ratio value
21419 * ratio: function(d, radius, h) {
21420 * ...
21421 * return ratio;
21422 * },
21423 * // or set ratio number
21424 * ratio: 0.5
21425 * },
21426 *
21427 * // disable expand transition for interaction
21428 * expand: false,
21429 *
21430 * expand: {
21431 * // set duration of expand transition to 500ms.
21432 * duration: 500,
21433 *
21434 * // set expand area rate
21435 * rate: 1
21436 * },
21437 *
21438 * // enforce min/max value.
21439 * // when given value < min, will render as empty value.
21440 * // when value > max, will render to given max value not surpassing it.
21441 * enforceMinMax: true,
21442 *
21443 * min: -100,
21444 * max: 200,
21445 * type: "single" // or 'multi'
21446 * title: "Title Text",
21447 *
21448 * // when 'arc.needle.show=true' is set, can show current needle value.
21449 * title: "Needle value:\n{=NEEDLE_VALUE}",
21450 *
21451 * units: "%",
21452 * width: 10,
21453 * startingAngle: -1 * Math.PI / 2,
21454 * arcLength: 100,
21455 * arcs: {
21456 * minWidth: 5
21457 * }
21458 * }
21459 */
21460 gauge_background: "",
21461 gauge_fullCircle: false,
21462 gauge_label_show: true,
21463 gauge_label_extents: void 0,
21464 gauge_label_format: void 0,
21465 gauge_label_ratio: void 0,
21466 gauge_label_threshold: 0,
21467 gauge_enforceMinMax: false,
21468 gauge_min: 0,
21469 gauge_max: 100,
21470 gauge_type: "single",
21471 gauge_startingAngle: -1 * Math.PI / 2,
21472 gauge_arcLength: 100,
21473 gauge_title: "",
21474 gauge_units: void 0,
21475 gauge_width: void 0,
21476 gauge_arcs_minWidth: 5,
21477 gauge_expand: {},
21478 gauge_expand_rate: 0.98,
21479 gauge_expand_duration: 50
21480});
21481
21482;// ./src/config/Options/shape/pie.ts
21483/* harmony default export */ var pie = ({
21484 /**
21485 * Set pie options
21486 * @name pie
21487 * @memberof Options
21488 * @type {object}
21489 * @property {object} pie Pie object
21490 * @property {boolean} [pie.label.show=true] Show or hide label on each pie piece.
21491 * @property {Function} [pie.label.format] Set formatter for the label on each pie piece.
21492 * @property {number|Function} [pie.label.ratio=undefined] Set ratio of labels position.
21493 * @property {number} [pie.label.threshold=0.05] Set threshold ratio to show/hide labels.
21494 * @property {boolean|object} [pie.expand=true] Enable or disable expanding pie pieces.
21495 * @property {number} [pie.expand.rate=0.98] Set expand rate.
21496 * @property {number} [pie.expand.duration=50] Set expand transition time in ms.
21497 * @property {number|object} [pie.innerRadius=0] Sets the inner radius of pie arc.
21498 * @property {number|object|undefined} [pie.outerRadius=undefined] Sets the outer radius of pie arc.
21499 * @property {number} [pie.padAngle=0] Set padding between data.
21500 * @property {number} [pie.padding=0] Sets the gap between pie arcs.
21501 * @property {number} [pie.startingAngle=0] Set starting angle where data draws.
21502 * @see [Demo: expand.rate](https://naver.github.io/billboard.js/demo/#PieChartOptions.ExpandRate)
21503 * @see [Demo: innerRadius](https://naver.github.io/billboard.js/demo/#PieChartOptions.InnerRadius)
21504 * @see [Demo: outerRadius](https://naver.github.io/billboard.js/demo/#PieChartOptions.OuterRadius)
21505 * @see [Demo: startingAngle](https://naver.github.io/billboard.js/demo/#PieChartOptions.StartingAngle)
21506 * @example
21507 * pie: {
21508 * label: {
21509 * show: false,
21510 * format: function(value, ratio, id) {
21511 * return d3.format("$")(value);
21512 *
21513 * // to multiline, return with '\n' character
21514 * // return value +"%\nLine1\n2Line2";
21515 * },
21516 *
21517 * // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
21518 * // if data value is below than 0.1, text label will be hidden.
21519 * threshold: 0.1,
21520 *
21521 * // set ratio callback. Should return ratio value
21522 * ratio: function(d, radius, h) {
21523 * ...
21524 * return ratio;
21525 * },
21526 * // or set ratio number
21527 * ratio: 0.5
21528 * },
21529 *
21530 * // disable expand transition for interaction
21531 * expand: false,
21532 *
21533 * expand: {
21534 * // set duration of expand transition to 500ms.
21535 * duration: 500,
21536 *
21537 * // set expand area rate
21538 * rate: 1
21539 * },
21540 *
21541 * innerRadius: 0,
21542 *
21543 * // set different innerRadius for each data
21544 * innerRadius: {
21545 * data1: 10,
21546 * data2: 0
21547 * },
21548 *
21549 * outerRadius: 100,
21550 *
21551 * // set different outerRadius for each data
21552 * outerRadius: {
21553 * data1: 50,
21554 * data2: 100
21555 * }
21556 *
21557 * padAngle: 0.1,
21558 * padding: 0,
21559 * startingAngle: 1
21560 * }
21561 */
21562 pie_label_show: true,
21563 pie_label_format: void 0,
21564 pie_label_ratio: void 0,
21565 pie_label_threshold: 0.05,
21566 pie_expand: {},
21567 pie_expand_rate: 0.98,
21568 pie_expand_duration: 50,
21569 pie_innerRadius: 0,
21570 pie_outerRadius: void 0,
21571 pie_padAngle: 0,
21572 pie_padding: 0,
21573 pie_startingAngle: 0
21574});
21575
21576;// ./src/config/Options/shape/polar.ts
21577/* harmony default export */ var shape_polar = ({
21578 /**
21579 * Set polar options
21580 * @name polar
21581 * @memberof Options
21582 * @type {object}
21583 * @property {object} polar Polar object
21584 * @property {boolean} [polar.label.show=true] Show or hide label on each polar piece.
21585 * @property {Function} [polar.label.format] Set formatter for the label on each polar piece.
21586 * @property {number} [polar.label.threshold=0.05] Set threshold ratio to show/hide labels.
21587 * @property {number|Function} [polar.label.ratio=undefined] Set ratio of labels position.
21588 * @property {number} [polar.level.depth=3] Set the level depth.
21589 * @property {boolean} [polar.level.show=true] Show or hide level.
21590 * @property {string} [polar.level.text.backgroundColor="#fff"] Set label text's background color.
21591 * @property {Function} [polar.level.text.format] Set format function for the level value.<br>- Default value: `(x) => x % 1 === 0 ? x : x.toFixed(2)`
21592 * @property {boolean} [polar.level.text.show=true] Show or hide level text.
21593 * @property {number} [polar.padAngle=0] Set padding between data.
21594 * @property {number} [polar.padding=0] Sets the gap between pie arcs.
21595 * @property {number} [polar.startingAngle=0] Set starting angle where data draws.
21596 * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.PolarChart)
21597 * @example
21598 * polar: {
21599 * label: {
21600 * show: false,
21601 * format: function(value, ratio, id) {
21602 * return d3.format("$")(value);
21603 *
21604 * // to multiline, return with '\n' character
21605 * // return value +"%\nLine1\n2Line2";
21606 * },
21607 *
21608 * // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value.
21609 * // if data value is below than 0.1, text label will be hidden.
21610 * threshold: 0.1,
21611 *
21612 * // set ratio callback. Should return ratio value
21613 * ratio: function(d, radius, h) {
21614 * ...
21615 * return ratio;
21616 * },
21617 * // or set ratio number
21618 * ratio: 0.5
21619 * },
21620 * level: {
21621 * depth: 3,
21622 * max: 500,
21623 * show: true,
21624 * text: {
21625 * format: function(x) {
21626 * return x + "%";
21627 * },
21628 * show: true,
21629 * backgroundColor: "red"
21630 * }
21631 * },
21632 * padAngle: 0.1,
21633 * padding: 0,
21634 * startingAngle: 1
21635 * }
21636 */
21637 polar_label_show: true,
21638 polar_label_format: void 0,
21639 polar_label_threshold: 0.05,
21640 polar_label_ratio: void 0,
21641 polar_level_depth: 3,
21642 polar_level_max: void 0,
21643 polar_level_show: true,
21644 polar_level_text_backgroundColor: "#fff",
21645 polar_level_text_format: (x) => x % 1 === 0 ? x : x.toFixed(2),
21646 polar_level_text_show: true,
21647 polar_padAngle: 0,
21648 polar_padding: 0,
21649 polar_startingAngle: 0
21650});
21651
21652;// ./src/config/Options/shape/radar.ts
21653/* harmony default export */ var shape_radar = ({
21654 /**
21655 * Set radar options
21656 * - **NOTE:**
21657 * > When x tick text contains `\n`, it's used as line break.
21658 * @name radar
21659 * @memberof Options
21660 * @type {object}
21661 * @property {object} radar Radar object
21662 * @property {number} [radar.axis.max=undefined] The max value of axis. If not given, it'll take the max value from the given data.
21663 * @property {boolean} [radar.axis.line.show=true] Show or hide axis line.
21664 * @property {number} [radar.axis.text.position.x=0] x coordinate position, relative the original.
21665 * @property {number} [radar.axis.text.position.y=0] y coordinate position, relative the original.
21666 * @property {boolean} [radar.axis.text.show=true] Show or hide axis text.
21667 * @property {boolean} [radar.direction.clockwise=false] Set the direction to be drawn.
21668 * @property {number} [radar.level.depth=3] Set the level depth.
21669 * @property {boolean} [radar.level.show=true] Show or hide level.
21670 * @property {Function} [radar.level.text.format] Set format function for the level value.<br>- Default value: `(x) => x % 1 === 0 ? x : x.toFixed(2)`
21671 * @property {boolean} [radar.level.text.show=true] Show or hide level text.
21672 * @property {number} [radar.size.ratio=0.87] Set size ratio.
21673 * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.RadarChart)
21674 * @see [Demo: radar axis](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarAxis)
21675 * @see [Demo: radar level](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarLevel)
21676 * @see [Demo: radar size](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarSize)
21677 * @see [Demo: radar axis multiline](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarAxisMultiline)
21678 * @example
21679 * radar: {
21680 * axis: {
21681 * max: 50,
21682 * line: {
21683 * show: false
21684 * },
21685 * text: {
21686 * position: {
21687 * x: 0,
21688 * y: 0
21689 * },
21690 * show: false
21691 * }
21692 * },
21693 * direction: {
21694 * clockwise: true
21695 * },
21696 * level: {
21697 * show: false,
21698 * text: {
21699 * format: function(x) {
21700 * return x + "%";
21701 * },
21702 * show: true
21703 * }
21704 * },
21705 * size: {
21706 * ratio: 0.7
21707 * }
21708 * }
21709 */
21710 radar_axis_max: void 0,
21711 radar_axis_line_show: true,
21712 radar_axis_text_show: true,
21713 radar_axis_text_position: {},
21714 radar_level_depth: 3,
21715 radar_level_show: true,
21716 radar_level_text_format: (x) => x % 1 === 0 ? x : x.toFixed(2),
21717 radar_level_text_show: true,
21718 radar_size_ratio: 0.87,
21719 radar_direction_clockwise: false
21720});
21721
21722;// ./src/config/Options/shape/treemap.ts
21723/* harmony default export */ var shape_treemap = ({
21724 /**
21725 * Set treemap options
21726 * @name treemap
21727 * @memberof Options
21728 * @type {object}
21729 * @property {object} treemap Treemap object
21730 * @property {string} [treemap.tile="binary"] Treemap tile type
21731 * - **Available tile type values:**
21732 * - binary ([d3.treemapBinary](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapBinary))
21733 * - dice ([d3.treemapDice](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapDice))
21734 * - slice ([d3.treemapSlice](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapSlice))
21735 * - sliceDice ([d3.treemapSliceDice](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapSliceDice))
21736 * - squrify ([d3.treemapSquarify](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapSquarify))
21737 * - resquarify ([d3.treemapResquarify](https://github.com/d3/d3-hierarchy/blob/main/README.md#treemapResquarify))
21738 * @property {Function} [treemap.label.format] Set formatter for the label text.
21739 * @property {number} [treemap.label.threshold=0.05] Set threshold ratio to show/hide labels text.
21740 * @property {number} [treemap.label.show=true] Show or hide label text.
21741 * @see [Demo: treemap](https://naver.github.io/billboard.js/demo/#Chart.TreemapChart)
21742 * @example
21743 * treemap: {
21744 * // "binary", "dice", "slice", "sliceDice", "squrify", "resquarify"
21745 * tile: "dice",
21746 *
21747 * label: {
21748 * // show or hide label text
21749 * show: false,
21750 *
21751 * // set label text formatter
21752 * format: function(value, ratio, id) {
21753 * return d3.format("$")(value);
21754 *
21755 * // to multiline, return with '\n' character
21756 * // return value +"%\nLine1\n2Line2";
21757 * },
21758 *
21759 * // set ratio number
21760 * ratio: 0.05
21761 * }
21762 * }
21763 */
21764 treemap_tile: "binary",
21765 treemap_label_format: void 0,
21766 treemap_label_threshold: 0.05,
21767 treemap_label_show: true
21768});
21769
21770;// ./src/config/resolver/shape.ts
21771
21772
21773
21774
21775
21776
21777
21778
21779
21780
21781
21782
21783
21784
21785
21786
21787
21788
21789
21790
21791
21792
21793
21794
21795
21796
21797
21798
21799
21800
21801
21802
21803
21804
21805
21806
21807function extendAxis(module, option) {
21808 extend(ChartInternal.prototype, Object.values(internal).concat(module));
21809 extend(Chart.prototype, api);
21810 Options.setOptions(Object.values(options).concat(option || []));
21811}
21812function extendLine(module, option) {
21813 extendAxis([point_common, point, line].concat(module || []));
21814 Options.setOptions([common_point, shape_line].concat(option || []));
21815}
21816function extendArc(module, option) {
21817 extend(ChartInternal.prototype, [arc, point_common].concat(module || []));
21818 Options.setOptions([common_point].concat(option || []));
21819}
21820let resolver_shape_area = () => (extendLine(shape_area, [Options_shape_area]), (resolver_shape_area = () => TYPE.AREA)());
21821let areaLineRange = () => (extendLine(shape_area, [Options_shape_area]), (areaLineRange = () => TYPE.AREA_LINE_RANGE)());
21822let areaStepRange = () => (extendLine(shape_area, [Options_shape_area]), (areaStepRange = () => TYPE.AREA_STEP_RANGE)());
21823let areaSpline = () => (extendLine(shape_area, [Options_shape_area, spline]), (areaSpline = () => TYPE.AREA_SPLINE)());
21824let areaSplineRange = () => (extendLine(shape_area, [Options_shape_area, spline]), (areaSplineRange = () => TYPE.AREA_SPLINE_RANGE)());
21825let areaStep = () => (extendLine(shape_area, [Options_shape_area]), (areaStep = () => TYPE.AREA_STEP)());
21826let resolver_shape_line = () => (extendLine(), (resolver_shape_line = () => TYPE.LINE)());
21827let shape_spline = () => (extendLine(void 0, [spline]), (shape_spline = () => TYPE.SPLINE)());
21828let step = () => (extendLine(), (step = () => TYPE.STEP)());
21829let shape_donut = () => (extendArc(void 0, [shape_arc, donut]), (shape_donut = () => TYPE.DONUT)());
21830let resolver_shape_gauge = () => (extendArc([gauge], [shape_arc, shape_gauge]), (resolver_shape_gauge = () => TYPE.GAUGE)());
21831let shape_pie = () => (extendArc(void 0, [shape_arc, pie]), (shape_pie = () => TYPE.PIE)());
21832let resolver_shape_polar = () => (extendArc([polar], [shape_arc, shape_polar]), (resolver_shape_polar = () => TYPE.POLAR)());
21833let resolver_shape_radar = () => (extendArc(
21834 [internal.eventrect, point, radar],
21835 [common_point, shape_radar, { axis_x_categories: options.optAxis.axis_x_categories }]
21836), (resolver_shape_radar = () => TYPE.RADAR)());
21837let resolver_shape_bar = () => (extendAxis([bar, point_common], [shape_bar, common_point]), (resolver_shape_bar = () => TYPE.BAR)());
21838let resolver_shape_bubble = () => (extendAxis(
21839 [point_common, point, bubble],
21840 [shape_bubble, common_point]
21841), (resolver_shape_bubble = () => TYPE.BUBBLE)());
21842let resolver_shape_candlestick = () => (extendAxis(
21843 [candlestick, point_common],
21844 [shape_candlestick, common_point]
21845), (resolver_shape_candlestick = () => TYPE.CANDLESTICK)());
21846let shape_scatter = () => (extendAxis(
21847 [point_common, point],
21848 [common_point, scatter]
21849), (shape_scatter = () => TYPE.SCATTER)());
21850let resolver_shape_funnel = () => (extendArc([funnel], [shape_funnel]), (resolver_shape_funnel = () => TYPE.FUNNEL)());
21851let resolver_shape_treemap = () => (extendAxis([treemap], [shape_treemap]), (resolver_shape_treemap = () => TYPE.TREEMAP)());
21852
21853;// ./src/core.ts
21854
21855
21856let defaults = {};
21857const bb = {
21858 /**
21859 * Version information
21860 * @property {string} version version
21861 * @example
21862 * bb.version; // "1.0.0"
21863 * @memberof bb
21864 */
21865 version: "3.14.2",
21866 /**
21867 * Generate chart
21868 * - **NOTE:** Bear in mind for the possiblity of ***throwing an error***, during the generation when:
21869 * - Unused option value is given.
21870 * - ex) For `data.type="pie"` option, setting 'axis' option can cause unexpected generation error.
21871 * - Insufficient value is given for certain option used.
21872 * - ex) `data: { x: "x", columns: [["x"], ["data1", 30, 200, 100]] }`
21873 * @param {Options} config chart options
21874 * @memberof bb
21875 * @returns {Chart}
21876 * @see {@link Options} for different generation options
21877 * @see {@link Chart} for different methods API
21878 * @example
21879 * <!-- chart holder -->
21880 * <div id="LineChart"></div>
21881 * @example
21882 * // Generate chart with options
21883 * var chart = bb.generate({
21884 * "bindto": "#LineChart"
21885 * "data": {
21886 * "columns": [
21887 * ["data1", 30, 200, 100, 400, 150, 250],
21888 * ["data2", 50, 20, 10, 40, 15, 25]
21889 * ],
21890 * "type": "line"
21891 * }
21892 * });
21893 *
21894 * // call some API
21895 * // ex) get the data of 'data1'
21896 * chart.data("data1");
21897 * @example
21898 * // Generate chart by importing ESM
21899 * // Import types to be used only, where this will make smaller bundle size.
21900 * import bb, {
21901 * area,
21902 * areaLineRange,
21903 * areaSpline,
21904 * areaSplineRange,
21905 * areaStep,
21906 * bar,
21907 * bubble,
21908 * donut,
21909 * gauge,
21910 * line,
21911 * pie,
21912 * polar,
21913 * radar,
21914 * scatter,
21915 * spline,
21916 * step
21917 * }
21918 *
21919 * bb.generate({
21920 * "bindto": "#LineChart"
21921 * "data": {
21922 * "columns": [
21923 * ["data1", 30, 200, 100, 400, 150, 250],
21924 * ["data2", 50, 20, 10, 40, 15, 25]
21925 * ]
21926 * },
21927 * type: line(),
21928 *
21929 * // or
21930 * types: {
21931 * data1: bar(),
21932 * data2: step()
21933 * }
21934 * });
21935 */
21936 generate(config) {
21937 const options = mergeObj({}, defaults, config);
21938 const inst = new Chart(options);
21939 inst.internal.charts = this.instance;
21940 this.instance.push(inst);
21941 return inst;
21942 },
21943 /**
21944 * Set or get global default options.
21945 * - **NOTE:**
21946 * - The options values settings are valid within page context only.
21947 * - If is called multiple times, will override the last value.
21948 * @param {Options} options chart options
21949 * @memberof bb
21950 * @returns {Options}
21951 * @see {@link Options}
21952 * @example
21953 * // Set same option value as for `.generate()`
21954 * bb.defaults({
21955 * data: {
21956 * type: "bar"
21957 * }
21958 * });
21959 *
21960 * bb.defaults(); // {data:{type: "bar"}}
21961 *
21962 * // data.type defaults to 'bar'
21963 * var chart = bb.generate({ ... });
21964 */
21965 defaults(options) {
21966 if (isObject(options)) {
21967 defaults = options;
21968 }
21969 return defaults;
21970 },
21971 /**
21972 * An array containing instance created
21973 * @property {Array} instance instance array
21974 * @example
21975 * // generate charts
21976 * var chart1 = bb.generate(...);
21977 * var chart2 = bb.generate(...);
21978 *
21979 * bb.instance; // [ chart1, chart2, ... ]
21980 * @memberof bb
21981 */
21982 instance: [],
21983 /**
21984 * Namespace for plugins
21985 * @property {object} plugin plugin namespace
21986 * @example
21987 * // Stanford diagram plugin
21988 * bb.plugin.stanford;
21989 * @memberof bb
21990 */
21991 plugin: {}
21992};
21993
21994
21995;// ./src/index.ts
21996
21997
21998Object.keys(resolver_shape_namespaceObject).forEach((v) => resolver_shape_namespaceObject[v]());
21999Object.keys(resolver_interaction_namespaceObject).forEach((v) => resolver_interaction_namespaceObject[v]());
22000
22001
22002}();
22003/******/ return __webpack_exports__;
22004/******/ })()
22005;
22006});
\No newline at end of file