(function (g, f) {
    if ("object" == typeof exports && "object" == typeof module) {
      module.exports = f();
    } else if ("function" == typeof define && define.amd) {
      define("agCharts", [], f);
    } else if ("object" == typeof exports) {
      exports["agCharts"] = f();
    } else {
      g["agCharts"] = f();
    }
  }(this, () => {
var exports = {};
var module = { exports };
if (typeof require === 'undefined') {
    function require(name) {
        
        throw new Error('Unknown module: ' + name);
    }
}
        
"use strict";

// packages/ag-charts-community/dist/package/main.cjs.js
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from3, except, desc) => {
  if (from3 && typeof from3 === "object" || typeof from3 === "function") {
    for (let key of __getOwnPropNames(from3))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from3[key], enumerable: !(desc = __getOwnPropDesc(from3, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result)
    __defProp(target, key, result);
  return result;
};
var main_exports = {};
__export(main_exports, {
  AG_CHARTS_LOCALE_EN_US: () => AG_CHARTS_LOCALE_EN_US,
  AgCharts: () => AgCharts,
  AgChartsCommunityModule: () => AgChartsCommunityModule,
  AgErrorBarSupportedSeriesTypes: () => AgErrorBarSupportedSeriesTypes,
  AgTooltipPositionType: () => AgTooltipPositionType,
  Marker: () => Marker,
  VERSION: () => VERSION,
  _ModuleSupport: () => module_support_exports,
  _Scene: () => integrated_charts_scene_exports,
  _Theme: () => integrated_charts_theme_exports,
  _Util: () => integrated_charts_util_exports,
  _Widget: () => exports_exports,
  setupCommunityModules: () => registerInbuiltModules,
  time: () => time_exports
});
module.exports = __toCommonJS(main_exports);
var AG_CHARTS_LOCALE_EN_US = {
  // Screen reader announcement when focusing an item in the chart
  ariaAnnounceHoverDatum: "${datum}",
  // Screen reader announcement when focusing a chart
  ariaAnnounceChart: "chart, ${seriesCount}[number] series",
  // Screen reader announcement when focusing a hierarchy chart
  ariaAnnounceHierarchyChart: "hierarchy chart, ${caption}",
  // Screen reader announcement when focusing a gauge chart
  ariaAnnounceGaugeChart: "gauge chart, ${caption}",
  // Screen reader announcement when focusing an item in a treemap or sunburst chart
  ariaAnnounceHierarchyDatum: "level ${level}[number], ${count}[number] children, ${description}",
  // Screen reader announcement when focusing a link in a Sankey or chord chart
  ariaAnnounceFlowProportionLink: "link ${index} of ${count}, from ${from} to ${to}, ${sizeName} ${size}",
  // Screen reader announcement when focusing a node in a Sankey or chord chart
  ariaAnnounceFlowProportionNode: "node ${index} of ${count}, ${description}",
  // Screen reader description for legend items
  ariaDescriptionLegendItem: "Press Space or Enter to toggle visibility",
  // Screen reader for the '+' horizontal line button on the Y-axis
  ariaLabelAddHorizontalLine: "Add Horizontal Line",
  // Screen reader text for annotation-options toolbar
  ariaLabelAnnotationOptionsToolbar: "Annotation Options",
  // Screen reader text for annotation-settings dialog
  ariaLabelAnnotationSettingsDialog: "Annotation Settings",
  // Screen reader text for the color picker dialog
  ariaLabelColorPicker: "Color picker",
  // Screen reader text for the financial charts toolbar
  ariaLabelFinancialCharts: "Financial Charts",
  // Screen reader text for the legend toolbar
  ariaLabelLegend: "Legend",
  // Screen reader text for the legend pagination button
  ariaLabelLegendPagination: "Legend Pagination",
  // Screen reader text for the previous legend page button
  ariaLabelLegendPagePrevious: "Previous Legend Page",
  // Screen reader text for the next legend page button
  ariaLabelLegendPageNext: "Next Legend Page",
  // Screen reader text for the an item in the legend
  ariaLabelLegendItem: "${label}, Legend item ${index}[number] of ${count}[number]",
  // Screen reader text for the an unknown item in the legend
  ariaLabelLegendItemUnknown: "Unknown legend item",
  // Screen reader text for the navigator element
  ariaLabelNavigator: "Navigator",
  // Screen reader text for an accessibility control that changes the position of the navigator's range
  ariaLabelNavigatorRange: "Range",
  // Screen reader text for an accessibility control that changes the start of the navigator's range
  ariaLabelNavigatorMinimum: "Minimum",
  // Screen reader text for an accessibility control that changes the end of the navigator's range
  ariaLabelNavigatorMaximum: "Maximum",
  // Screen reader text for ranges toolbar
  ariaLabelRangesToolbar: "Ranges",
  // Screen reader text for the settings dialog tab-bar
  ariaLabelSettingsTabBar: "Settings",
  // Screen reader text for zoom toolbar
  ariaLabelZoomToolbar: "Zoom",
  // Screen reader text for the value of the navigator's range
  ariaValuePanRange: "${min}[percent] to ${max}[percent]",
  // Alt-text for the solid line dash style menu item icon
  iconAltTextLineStyleSolid: "Solid",
  // Alt-text for the long-dashed line dash style menu item icon
  iconAltTextLineStyleDashed: "Long-dashed",
  // Alt-text for the short-dashed line dash style menu item icon
  iconAltTextLineStyleDotted: "Short-dashed",
  // Alt-text for the 'position-top' icon
  iconAltTextPositionTop: "Top",
  // Alt-text for the 'position-center' icon
  iconAltTextPositionCenter: "Center",
  // Alt-text for the 'position-bottom' icon
  iconAltTextPositionBottom: "Bottom",
  // Alt-text for the 'position-left' icon
  iconAltTextAlignLeft: "Left",
  // Alt-text for the 'align-center' icon
  iconAltTextAlignCenter: "Center",
  // Alt-text for the 'position-right' icon
  iconAltTextAlignRight: "Right",
  // Alt-text for the 'close' icon
  iconAltTextClose: "Close",
  // Default text for the 'loading data' overlay
  overlayLoadingData: "Loading data...",
  // Default text for the 'no data' overlay
  overlayNoData: "No data to display",
  // Default text for the 'no visible series' overlay
  overlayNoVisibleSeries: "No visible series",
  // Default text for the 'unsupported browser' overlay
  overlayUnsupportedBrowser: "Incompatible browser version. Please upgrade your browser.",
  // Text for frequency label in Histogram Series tooltip
  seriesHistogramTooltipFrequency: "Frequency",
  // Text for sum label in Histogram Series tooltip
  seriesHistogramTooltipSum: "${yName} (sum)",
  // Text for sum label in Histogram Series tooltip
  seriesHistogramTooltipCount: "${yName} (count)",
  // Text for sum label in Histogram Series tooltip
  seriesHistogramTooltipMean: "${yName} (mean)",
  // Text for the series type toolbar's chart type button
  toolbarSeriesTypeDropdown: "Chart Type",
  // Text for the series type toolbar's OHLC chart type button
  toolbarSeriesTypeOHLC: "OHLC",
  // Text for the series type toolbar's HLC chart type button
  toolbarSeriesTypeHLC: "HLC",
  // Text for the series type toolbar's high low chart type button
  toolbarSeriesTypeHighLow: "High Low",
  // Text for the series type toolbar's candles chart type button
  toolbarSeriesTypeCandles: "Candles",
  // Text for the series type toolbar's hollow candles chart type button
  toolbarSeriesTypeHollowCandles: "Hollow Candles",
  // Text for the series type toolbar's line chart type button
  toolbarSeriesTypeLine: "Line",
  // Text for the series type toolbar's line with markers chart type button
  toolbarSeriesTypeLineWithMarkers: "Line with Markers",
  // Text for the series type toolbar's line with step line chart type button
  toolbarSeriesTypeStepLine: "Step Line",
  // Text for the annotation toolbar's trend line button
  toolbarAnnotationsTrendLine: "Trend Line",
  // Text for the annotation toolbar's Fibonacci Retracement button
  toolbarAnnotationsFibonacciRetracement: "Fib Retracement",
  // Text for the annotation toolbar's horizontal line button
  toolbarAnnotationsHorizontalLine: "Horizontal Line",
  // Text for the annotation toolbar's vertical line button
  toolbarAnnotationsVerticalLine: "Vertical Line",
  // Text for the annotation toolbar's parallel channel button
  toolbarAnnotationsParallelChannel: "Parallel Channel",
  // Text for the annotation toolbar's disjoint channel button
  toolbarAnnotationsDisjointChannel: "Disjoint Channel",
  // Text for the annotation toolbar's clear all button
  toolbarAnnotationsClearAll: "Clear All",
  // Text for the annotation toolbar's fill color picker annotation button
  toolbarAnnotationsFillColor: "Fill Color",
  // Text for the annotation toolbar's line color picker annotation button
  toolbarAnnotationsLineColor: "Line Color",
  // Text for the annotation toolbar's line style type button
  toolbarAnnotationsLineStyle: "Line Style",
  // Text for the annotation toolbar's line stroke width button
  toolbarAnnotationsLineStrokeWidth: "Line Stroke Width",
  // Text for the annotation toolbar's settings annotation button
  toolbarAnnotationsSettings: "Settings",
  // Text for the annotation toolbar's text color picker annotation button
  toolbarAnnotationsTextColor: "Text Color",
  // Text for the annotation toolbar's text size picker annotation button
  toolbarAnnotationsTextSize: "Text Size",
  // Text for the annotation toolbar's lock annotation button
  toolbarAnnotationsLock: "Lock",
  // Text for the annotation toolbar's unlock annotation button
  toolbarAnnotationsUnlock: "Unlock",
  // Text for the annotation toolbar's delete annotation button
  toolbarAnnotationsDelete: "Delete",
  // Text for the annotation toolbar's drag handle
  toolbarAnnotationsDragHandle: "Drag Toolbar",
  // Text for the annotation toolbar's line drawings menu button
  toolbarAnnotationsLineAnnotations: "Trend Lines",
  // Text for the annotation toolbar's Fibonacci drawings menu button
  toolbarAnnotationsFibonacciAnnotations: "Fibonacci",
  // Text for the annotation toolbar's text annotations menu button
  toolbarAnnotationsTextAnnotations: "Text Annotations",
  // Text for the annotation toolbar's shapes menu button
  toolbarAnnotationsShapeAnnotations: "Arrows",
  // Text for the annotation toolbar's measurers menu button
  toolbarAnnotationsMeasurerAnnotations: "Measurers",
  // Text for the annotation toolbar's callout button
  toolbarAnnotationsCallout: "Callout",
  // Text for the annotation toolbar's comment button
  toolbarAnnotationsComment: "Comment",
  // Text for the annotation toolbar's note button
  toolbarAnnotationsNote: "Note",
  // Text for the annotation toolbar's text button
  toolbarAnnotationsText: "Text",
  // Text for the annotation toolbar's arrow button
  toolbarAnnotationsArrow: "Arrow",
  // Text for the annotation toolbar's arrow up button
  toolbarAnnotationsArrowUp: "Arrow Up",
  // Text for the annotation toolbar's arrow down button
  toolbarAnnotationsArrowDown: "Arrow Down",
  // Text for the annotation toolbar's date range button
  toolbarAnnotationsDateRange: "Date Range",
  // Text for the annotation toolbar's price range button
  toolbarAnnotationsPriceRange: "Price Range",
  // Text for the annotation toolbar's date and price range button
  toolbarAnnotationsDatePriceRange: "Date and Price",
  // Text for the annotation toolbar's quick date and price range button
  toolbarAnnotationsQuickDatePriceRange: "Measure",
  // Text for the range toolbar's 1 month button
  toolbarRange1Month: "1M",
  // Aria label for the range toolbar's 1 month button
  toolbarRange1MonthAria: "1 month",
  // Text for the range toolbar's 3 month button
  toolbarRange3Months: "3M",
  // Aria label for the range toolbar's 3 month button
  toolbarRange3MonthsAria: "3 months",
  // Text for the range toolbar's 6 month button
  toolbarRange6Months: "6M",
  // Aria label for the range toolbar's 6 month button
  toolbarRange6MonthsAria: "6 months",
  // Text for the range toolbar's year to date button
  toolbarRangeYearToDate: "YTD",
  // Aria label for the range toolbar's year to date month button
  toolbarRangeYearToDateAria: "Year to date",
  // Text for the range toolbar's 1 year button
  toolbarRange1Year: "1Y",
  // Aria label for the range toolbar's 1 year button
  toolbarRange1YearAria: "1 year",
  // Text for the range toolbar's full range button
  toolbarRangeAll: "All",
  // Aria label for the range toolbar's full range button
  toolbarRangeAllAria: "All",
  // Text for the zoom toolbar's zoom out button
  toolbarZoomZoomOut: "Zoom out",
  // Text for the zoom toolbar's zoom in button
  toolbarZoomZoomIn: "Zoom in",
  // Text for the zoom toolbar's pan left button
  toolbarZoomPanLeft: "Pan left",
  // Text for the zoom toolbar's pan right button
  toolbarZoomPanRight: "Pan right",
  // Text for the zoom toolbar's pan to the start button
  toolbarZoomPanStart: "Pan to the start",
  // Text for the zoom toolbar's pan to the end button
  toolbarZoomPanEnd: "Pan to the end",
  // Text for the zoom toolbar's pan reset button
  toolbarZoomReset: "Reset the zoom",
  // Text for the context menu's download button
  contextMenuDownload: "Download",
  // Text for the context menu's toggle series visibility button
  contextMenuToggleSeriesVisibility: "Toggle Visibility",
  // Text for the context menu's toggle other series visibility button
  contextMenuToggleOtherSeries: "Toggle Other Series",
  // Text for the context menu's zoom to point button
  contextMenuZoomToCursor: "Zoom to here",
  // Text for the context menu's pan to point button
  contextMenuPanToCursor: "Pan to here",
  // Text for the annotation dialog's header channel tab label
  dialogHeaderChannel: "Channel",
  // Text for the annotation dialog's header line tab label
  dialogHeaderLine: "Line",
  // Text for the annotation dialog's header fibonacci retracement line tab label
  dialogHeaderFibonacciRange: "Fib Retracement",
  // Text for the annotation dialog's header date range tab label
  dialogHeaderDateRange: "Date Range",
  // Text for the annotation dialog's header price range tab label
  dialogHeaderPriceRange: "Price Range",
  // Text for the annotation dialog's header date and price range tab label
  dialogHeaderDatePriceRange: "Date and Price",
  // Text for the annotation dialog's header text tab label
  dialogHeaderText: "Text",
  // Text for the annotation dialog's text alignment radio label
  dialogInputAlign: "Align",
  // Text for the annotation dialog's color picker label
  dialogInputColorPicker: "Color",
  // Text for the annotation dialog's color picker alt text
  dialogInputColorPickerAltText: "Text Color",
  // Text for the annotation dialog's fill color picker label
  dialogInputFillColorPicker: "Fill",
  // Text for the annotation dialog's fill color picker alt text
  dialogInputFillColorPickerAltText: "Fill Color",
  // Text for the annotation dialog's extend channel start checkbox
  dialogInputExtendChannelStart: "Extend channel start",
  // Text for the annotation dialog's extend channel end checkbox
  dialogInputExtendChannelEnd: "Extend channel end",
  // Text for the annotation dialog's extend line start checkbox
  dialogInputExtendLineStart: "Extend line start",
  // Text for the annotation dialog's extend line end checkbox
  dialogInputExtendLineEnd: "Extend line end",
  // Text for the annotation dialog's extend above checkbox
  dialogInputExtendAbove: "Extend above",
  // Text for the annotation dialog's extend below checkbox
  dialogInputExtendBelow: "Extend below",
  // Text for the annotation dialog's extend left checkbox
  dialogInputExtendLeft: "Extend left",
  // Text for the annotation dialog's extend right checkbox
  dialogInputExtendRight: "Extend right",
  // Text for the annotation dialog's reverse checkbox
  dialogInputReverse: "Reverse",
  // Text for the annotation dialog's show fill checkbox
  dialogInputShowFill: "Show Fill",
  // Text for the annotation dialog's font size select box label
  dialogInputFontSize: "Size",
  // Text for the annotation dialog's font size select box alt text
  dialogInputFontSizeAltText: "Font Size",
  // Text for the annotation dialog's line style radio label
  dialogInputLineStyle: "Dash",
  // Text for the annotation dialog's text position radio label
  dialogInputPosition: "Position",
  // Text for the annotation dialog's stroke width label
  dialogInputStrokeWidth: "Weight",
  // Text for the annotation dialog's stroke width label
  dialogInputStrokeWidthAltText: "Line Weight",
  // Text for the annotation dialog's Fibonacci bands label
  dialogInputFibonacciBands: "Bands",
  // Text for the annotation dialog's Fibonacci bands label
  dialogInputFibonacciBandsAltText: "Fibonacci Bands",
  // Text for text area input placeholders
  inputTextareaPlaceholder: "Add Text",
  // Text for the measurer statistics date range bars value
  measurerDateRangeBars: "${value}[number] bars",
  // Text for the measurer statistics price range value
  measurerPriceRangeValue: "${value}[number]",
  // Text for the measurer statistics price range percentage
  measurerPriceRangePercent: "${value}[percent]",
  // Text for the measurer statistics volume value
  measurerVolume: "Vol ${value}"
};
var AgErrorBarSupportedSeriesTypes = ["bar", "line", "scatter"];
var __MINI_CHART_SERIES_OPTIONS = void 0;
var __VERIFY_MINI_CHART_SERIES_OPTIONS = void 0;
__VERIFY_MINI_CHART_SERIES_OPTIONS = __MINI_CHART_SERIES_OPTIONS;
var __THEME_OVERRIDES = void 0;
var __VERIFY_THEME_OVERRIDES = void 0;
__VERIFY_THEME_OVERRIDES = __THEME_OVERRIDES;
var AgTooltipPositionType = /* @__PURE__ */ ((AgTooltipPositionType2) => {
  AgTooltipPositionType2["POINTER"] = "pointer";
  AgTooltipPositionType2["NODE"] = "node";
  AgTooltipPositionType2["TOP"] = "top";
  AgTooltipPositionType2["RIGHT"] = "right";
  AgTooltipPositionType2["BOTTOM"] = "bottom";
  AgTooltipPositionType2["LEFT"] = "left";
  AgTooltipPositionType2["TOP_LEFT"] = "top-left";
  AgTooltipPositionType2["TOP_RIGHT"] = "top-right";
  AgTooltipPositionType2["BOTTOM_RIGHT"] = "bottom-right";
  AgTooltipPositionType2["BOTTOM_LEFT"] = "bottom-left";
  return AgTooltipPositionType2;
})(AgTooltipPositionType || {});
var __THEMEABLE_OPTIONS = void 0;
var __VERIFY_THEMEABLE_OPTIONS = void 0;
__VERIFY_THEMEABLE_OPTIONS = __THEMEABLE_OPTIONS;
var __AXIS_LABEL_OPTIONS = void 0;
var __VERIFY_AXIS_LABEL_OPTIONS = void 0;
__VERIFY_AXIS_LABEL_OPTIONS = __AXIS_LABEL_OPTIONS;
var fromToMotion_exports = {};
__export(fromToMotion_exports, {
  NODE_UPDATE_STATE_TO_PHASE_MAPPING: () => NODE_UPDATE_STATE_TO_PHASE_MAPPING,
  fromToMotion: () => fromToMotion,
  staticFromToMotion: () => staticFromToMotion
});
var ID_MAP = /* @__PURE__ */ new Map();
function resetIds() {
  ID_MAP.clear();
}
function createId(instance) {
  const constructor = instance.constructor;
  const className = Object.hasOwn(constructor, "className") ? constructor.className : constructor.name;
  if (!className) {
    throw new Error(`The ${constructor} is missing the 'className' property.`);
  }
  const nextId = (ID_MAP.get(className) ?? 0) + 1;
  ID_MAP.set(className, nextId);
  return `${className}-${nextId}`;
}
function generateUUID() {
  return crypto.randomUUID?.() ?? generateUUIDv4();
}
function generateUUIDv4() {
  const uuidArray = new Uint8Array(16);
  crypto.getRandomValues(uuidArray);
  uuidArray[6] = uuidArray[6] & 15 | 64;
  uuidArray[8] = uuidArray[8] & 63 | 128;
  let uuid = "";
  for (let i = 0; i < uuidArray.length; i++) {
    if (i === 4 || i === 6 || i === 8 || i === 10) {
      uuid += "-";
    }
    uuid += uuidArray[i].toString(16).padStart(2, "0");
  }
  return uuid;
}
function* iterate(...iterators) {
  for (const iterator of iterators) {
    yield* iterator;
  }
}
function toIterable(value) {
  return value != null && typeof value === "object" && Symbol.iterator in value ? value : [value];
}
var BBoxValues = { containsPoint, isEmpty, normalize };
function containsPoint(bbox, x, y) {
  return x >= bbox.x && x <= bbox.x + bbox.width && y >= bbox.y && y <= bbox.y + bbox.height;
}
function isEmpty(bbox) {
  return bbox == null || bbox.height === 0 || bbox.width === 0 || isNaN(bbox.height) || isNaN(bbox.width);
}
function normalize(bbox) {
  let { x, y, width: width2, height: height2 } = bbox;
  if ((width2 == null || width2 > 0) && (height2 == null || height2 > 0))
    return bbox;
  if (x != null && width2 != null && width2 < 0) {
    width2 = -width2;
    x = x - width2;
  }
  if (y != null && height2 != null && height2 < 0) {
    height2 = -height2;
    y = y - height2;
  }
  return { x, y, width: width2, height: height2 };
}
var interpolate = Symbol("interpolate");
var isInterpolating = (x) => x[interpolate] != null;
function nearestSquared(x, y, objects, maxDistanceSquared = Infinity) {
  const result = { nearest: void 0, distanceSquared: maxDistanceSquared };
  for (const obj of objects) {
    const thisDistance = obj.distanceSquared(x, y);
    if (thisDistance === 0) {
      return { nearest: obj, distanceSquared: 0 };
    } else if (thisDistance < result.distanceSquared) {
      result.nearest = obj;
      result.distanceSquared = thisDistance;
    }
  }
  return result;
}
function nearestSquaredInContainer(x, y, container, maxDistanceSquared = Infinity) {
  const { x: tx = x, y: ty = y } = container.transformPoint?.(x, y) ?? {};
  const result = { nearest: void 0, distanceSquared: maxDistanceSquared };
  for (const child of container.children) {
    const { nearest, distanceSquared: distanceSquared3 } = child.nearestSquared(tx, ty, result.distanceSquared);
    if (distanceSquared3 === 0) {
      return { nearest, distanceSquared: distanceSquared3 };
    } else if (distanceSquared3 < result.distanceSquared) {
      result.nearest = nearest;
      result.distanceSquared = distanceSquared3;
    }
  }
  return result;
}
function clamp(min, value, max) {
  return Math.min(max, Math.max(min, value));
}
function clampArray(value, array2) {
  const [min, max] = findMinMax(array2);
  return clamp(min, value, max);
}
function findMinMax(array2) {
  if (array2.length === 0)
    return [];
  const result = [Infinity, -Infinity];
  for (const val of array2) {
    if (val < result[0])
      result[0] = val;
    if (val > result[1])
      result[1] = val;
  }
  return result;
}
function findRangeExtent(array2) {
  const [min, max] = findMinMax(array2);
  return max - min;
}
function inRange(value, range3, epsilon2 = 1e-10) {
  return value >= range3[0] - epsilon2 && value <= range3[1] + epsilon2;
}
function isNumberEqual(a, b, epsilon2 = 1e-10) {
  return Math.abs(a - b) < epsilon2;
}
function isNegative(value) {
  return Math.sign(value) === -1 || Object.is(value, -0);
}
function isInteger(value) {
  return value % 1 === 0;
}
function round(value, decimals = 2) {
  const base = 10 ** decimals;
  return Math.round(value * base) / base;
}
function mod(n, m) {
  return Math.floor(n % m + (n < 0 ? m : 0));
}
function countFractionDigits(value) {
  if (Math.floor(value) === value)
    return 0;
  let valueString = String(value);
  let exponent = 0;
  if (value < 1e-6 || value >= 1e21) {
    let exponentString;
    [valueString, exponentString] = valueString.split("e");
    if (exponentString != null) {
      exponent = Number(exponentString);
    }
  }
  const decimalPlaces2 = valueString.split(".")[1]?.length ?? 0;
  return Math.max(decimalPlaces2 - exponent, 0);
}
var _BBox = class _BBox2 {
  constructor(x, y, width2, height2) {
    this.x = x;
    this.y = y;
    this.width = width2;
    this.height = height2;
  }
  static fromDOMRect({ x, y, width: width2, height: height2 }) {
    return new _BBox2(x, y, width2, height2);
  }
  static merge(boxes) {
    let left = Infinity;
    let top = Infinity;
    let right = -Infinity;
    let bottom = -Infinity;
    for (const box of boxes) {
      if (box.x < left) {
        left = box.x;
      }
      if (box.y < top) {
        top = box.y;
      }
      if (box.x + box.width > right) {
        right = box.x + box.width;
      }
      if (box.y + box.height > bottom) {
        bottom = box.y + box.height;
      }
    }
    return new _BBox2(left, top, right - left, bottom - top);
  }
  static nearestBox(x, y, boxes) {
    return nearestSquared(x, y, boxes);
  }
  toDOMRect() {
    return {
      x: this.x,
      y: this.y,
      width: this.width,
      height: this.height,
      top: this.y,
      left: this.x,
      right: this.x + this.width,
      bottom: this.y + this.height,
      toJSON() {
        return {};
      }
    };
  }
  clone() {
    const { x, y, width: width2, height: height2 } = this;
    return new _BBox2(x, y, width2, height2);
  }
  equals(other) {
    return this.x === other.x && this.y === other.y && this.width === other.width && this.height === other.height;
  }
  containsPoint(x, y) {
    return BBoxValues.containsPoint(this, x, y);
  }
  containsBBox(other) {
    const [ax0, ax1] = [this.x, this.x + this.width];
    const [ay0, ay1] = [this.y, this.y + this.height];
    const [bx0, bx1] = [other.x, other.x + other.width];
    const [by0, by1] = [other.y, other.y + other.height];
    return Math.min(ax0, bx0) === ax0 && Math.max(ax1, bx1) === ax1 && Math.min(ay0, by0) === ay0 && Math.max(ay1, by1) === ay1;
  }
  intersection(other) {
    if (!this.collidesBBox(other))
      return;
    const newX1 = clamp(other.x, this.x, other.x + other.width);
    const newY1 = clamp(other.y, this.y, other.y + other.height);
    const newX2 = clamp(other.x, this.x + this.width, other.x + other.width);
    const newY2 = clamp(other.y, this.y + this.height, other.y + other.height);
    return new _BBox2(newX1, newY1, newX2 - newX1, newY2 - newY1);
  }
  collidesBBox(other) {
    return this.x < other.x + other.width && this.x + this.width > other.x && this.y < other.y + other.height && this.y + this.height > other.y;
  }
  computeCenter() {
    return { x: this.x + this.width / 2, y: this.y + this.height / 2 };
  }
  isFinite() {
    return Number.isFinite(this.x) && Number.isFinite(this.y) && Number.isFinite(this.width) && Number.isFinite(this.height);
  }
  distanceSquared(x, y) {
    if (this.containsPoint(x, y)) {
      return 0;
    }
    const dx = x - clamp(this.x, x, this.x + this.width);
    const dy = y - clamp(this.y, y, this.y + this.height);
    return dx * dx + dy * dy;
  }
  shrink(amount, position) {
    if (typeof amount === "number") {
      this.applyMargin(amount, position);
    } else {
      for (const [key, value] of Object.entries(amount)) {
        this.applyMargin(value, key);
      }
    }
    if (this.width < 0) {
      this.width = 0;
    }
    if (this.height < 0) {
      this.height = 0;
    }
    return this;
  }
  grow(amount, position) {
    if (typeof amount === "number") {
      this.applyMargin(-amount, position);
    } else {
      for (const [key, value] of Object.entries(amount)) {
        this.applyMargin(-value, key);
      }
    }
    return this;
  }
  applyMargin(value, position) {
    switch (position) {
      case "top":
        this.y += value;
      case "bottom":
        this.height -= value;
        break;
      case "left":
        this.x += value;
      case "right":
        this.width -= value;
        break;
      case "vertical":
        this.y += value;
        this.height -= value * 2;
        break;
      case "horizontal":
        this.x += value;
        this.width -= value * 2;
        break;
      case void 0:
        this.x += value;
        this.y += value;
        this.width -= value * 2;
        this.height -= value * 2;
        break;
    }
  }
  translate(x, y) {
    this.x += x;
    this.y += y;
    return this;
  }
  combine(other) {
    const { x, y, width: width2, height: height2 } = this;
    this.x = Math.min(x, other.x);
    this.y = Math.min(y, other.y);
    this.width = Math.max(x + width2, other.x + other.width) - this.x;
    this.height = Math.max(y + height2, other.y + other.height) - this.y;
  }
  [interpolate](other, d) {
    return new _BBox2(
      this.x * (1 - d) + other.x * d,
      this.y * (1 - d) + other.y * d,
      this.width * (1 - d) + other.width * d,
      this.height * (1 - d) + other.height * d
    );
  }
};
_BBox.zero = Object.freeze(new _BBox(0, 0, 0, 0));
_BBox.NaN = Object.freeze(new _BBox(NaN, NaN, NaN, NaN));
var BBox = _BBox;
function SceneChangeDetection(opts) {
  return function(target, key) {
    const privateKey = `__${key}`;
    if (target[key]) {
      return;
    }
    prepareGetSet(target, key, privateKey, opts);
  };
}
function prepareGetSet(target, key, privateKey, opts) {
  const { type = "normal", changeCb, convertor, checkDirtyOnAssignment = false } = opts ?? {};
  const requiredOpts = { type, changeCb, checkDirtyOnAssignment, convertor };
  let setter;
  switch (type) {
    case "normal":
      setter = buildNormalSetter(privateKey, requiredOpts);
      break;
    case "transform":
      setter = buildTransformSetter(privateKey);
      break;
    case "path":
      setter = buildPathSetter(privateKey);
      break;
  }
  setter = buildCheckDirtyChain(
    buildChangeCallbackChain(buildConvertorChain(setter, requiredOpts), requiredOpts),
    requiredOpts
  );
  const getter = function() {
    return this[privateKey];
  };
  Object.defineProperty(target, key, {
    set: setter,
    get: getter,
    enumerable: true,
    configurable: true
  });
}
function buildConvertorChain(setterFn, opts) {
  const { convertor } = opts;
  if (convertor) {
    return function(value) {
      setterFn.call(this, convertor(value));
    };
  }
  return setterFn;
}
var NO_CHANGE = Symbol("no-change");
function buildChangeCallbackChain(setterFn, opts) {
  const { changeCb } = opts;
  if (changeCb) {
    return function(value) {
      const change = setterFn.call(this, value);
      if (change !== NO_CHANGE) {
        changeCb.call(this, this);
      }
      return change;
    };
  }
  return setterFn;
}
function buildCheckDirtyChain(setterFn, opts) {
  const { checkDirtyOnAssignment } = opts;
  if (checkDirtyOnAssignment) {
    return function(value) {
      const change = setterFn.call(this, value);
      if (change !== NO_CHANGE && value?._dirty === true) {
        this.markDirty();
      }
      return change;
    };
  }
  return setterFn;
}
function buildNormalSetter(privateKey, opts) {
  const { changeCb } = opts;
  return function(value) {
    const oldValue = this[privateKey];
    if (value !== oldValue) {
      this[privateKey] = value;
      this.markDirty();
      changeCb?.(this);
      return value;
    }
    return NO_CHANGE;
  };
}
function buildTransformSetter(privateKey) {
  return function(value) {
    const oldValue = this[privateKey];
    if (value !== oldValue) {
      this[privateKey] = value;
      this.markDirtyTransform();
      return value;
    }
    return NO_CHANGE;
  };
}
function buildPathSetter(privateKey) {
  return function(value) {
    const oldValue = this[privateKey];
    if (value !== oldValue) {
      this[privateKey] = value;
      if (!this._dirtyPath) {
        this._dirtyPath = true;
        this.markDirty();
      }
      return value;
    }
    return NO_CHANGE;
  };
}
var PointerEvents = /* @__PURE__ */ ((PointerEvents2) => {
  PointerEvents2[PointerEvents2["All"] = 0] = "All";
  PointerEvents2[PointerEvents2["None"] = 1] = "None";
  return PointerEvents2;
})(PointerEvents || {});
var _Node = class _Node2 {
  constructor(options) {
    this.serialNumber = _Node2._nextSerialNumber++;
    this.childNodeCounts = { groups: 0, nonGroups: 0, thisComplexity: 0, complexity: 0 };
    this.id = createId(this);
    this.pointerEvents = 0;
    this._dirty = true;
    this.dirtyZIndex = false;
    this.isContainerNode = false;
    this.visible = true;
    this.zIndex = 0;
    this.name = options?.name;
    this.tag = options?.tag ?? NaN;
    this.zIndex = options?.zIndex ?? 0;
  }
  static toSVG(node, width2, height2) {
    const svg = node?.toSVG();
    if (svg == null || !svg.elements.length && !svg.defs?.length)
      return;
    const root = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    root.setAttribute("width", String(width2));
    root.setAttribute("height", String(height2));
    root.setAttribute("viewBox", `0 0 ${width2} ${height2}`);
    if (svg.defs?.length) {
      const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
      defs.append(...svg.defs);
      root.append(defs);
    }
    root.append(...svg.elements);
    return root.outerHTML;
  }
  static *extractBBoxes(nodes, skipInvisible) {
    for (const n of nodes) {
      if (!skipInvisible || n.visible && !n.transitionOut) {
        const bbox = n.getBBox();
        if (bbox)
          yield bbox;
      }
    }
  }
  /**
   * Some arbitrary data bound to the node.
   */
  get datum() {
    return this._datum ?? this.parentNode?.datum;
  }
  set datum(datum) {
    if (this._datum !== datum) {
      this._previousDatum = this._datum;
      this._datum = datum;
    }
  }
  get previousDatum() {
    return this._previousDatum;
  }
  get layerManager() {
    return this._layerManager;
  }
  get dirty() {
    return this._dirty;
  }
  /** Perform any pre-rendering initialization. */
  preRender(thisComplexity = 1) {
    this.childNodeCounts.groups = 0;
    this.childNodeCounts.nonGroups = 1;
    this.childNodeCounts.complexity = thisComplexity;
    this.childNodeCounts.thisComplexity = thisComplexity;
    for (const child of this.children()) {
      const childCounts = child.preRender();
      this.childNodeCounts.groups += childCounts.groups;
      this.childNodeCounts.nonGroups += childCounts.nonGroups;
      this.childNodeCounts.complexity += childCounts.complexity;
    }
    return this.childNodeCounts;
  }
  render(renderCtx) {
    const { stats } = renderCtx;
    this._dirty = false;
    if (renderCtx.debugNodeSearch) {
      const idOrName = this.name ?? this.id;
      if (renderCtx.debugNodeSearch.some((v) => typeof v === "string" ? v === idOrName : v.test(idOrName))) {
        renderCtx.debugNodes[this.name ?? this.id] = this;
      }
    }
    if (stats) {
      stats.nodesRendered++;
      stats.opsPerformed += this.childNodeCounts.thisComplexity;
    }
  }
  _setLayerManager(value) {
    this._layerManager = value;
    this._debug = value?.debug;
    for (const child of this.children()) {
      child._setLayerManager(value);
    }
  }
  sortChildren(compareFn) {
    this.dirtyZIndex = false;
    if (!this.childNodes)
      return;
    const sortedChildren = [...this.childNodes].sort(compareFn);
    this.childNodes.clear();
    for (const child of sortedChildren) {
      this.childNodes.add(child);
    }
  }
  *traverseUp(includeSelf) {
    let node = this;
    if (includeSelf) {
      yield node;
    }
    while (node = node.parentNode) {
      yield node;
    }
  }
  *children() {
    if (!this.childNodes)
      return;
    for (const child of this.childNodes) {
      yield child;
    }
  }
  /**
   * Checks if the node is a leaf (has no children).
   */
  isLeaf() {
    return !this.childNodes?.size;
  }
  /**
   * Checks if the node is the root (has no parent).
   */
  isRoot() {
    return !this.parentNode;
  }
  /**
   * Appends one or more new node instances to this parent.
   * If one needs to:
   * - move a child to the end of the list of children
   * - move a child from one parent to another (including parents in other scenes)
   * one should use the {@link insertBefore} method instead.
   * @param nodes A node or nodes to append.
   */
  append(nodes) {
    this.childNodes ?? (this.childNodes = /* @__PURE__ */ new Set());
    for (const node of toIterable(nodes)) {
      node.parentNode?.removeChild(node);
      this.childNodes.add(node);
      node.parentNode = this;
      node._setLayerManager(this.layerManager);
    }
    this.invalidateCachedBBox();
    this.dirtyZIndex = true;
    this.markDirty();
  }
  appendChild(node) {
    this.append(node);
    return node;
  }
  removeChild(node) {
    if (!this.childNodes?.delete(node)) {
      return false;
    }
    delete node.parentNode;
    node._setLayerManager();
    this.invalidateCachedBBox();
    this.dirtyZIndex = true;
    this.markDirty();
    return true;
  }
  remove() {
    return this.parentNode?.removeChild(this) ?? false;
  }
  clear() {
    for (const child of this.children()) {
      delete child.parentNode;
      child._setLayerManager();
    }
    this.childNodes?.clear();
    this.invalidateCachedBBox();
  }
  destroy() {
    this.parentNode?.removeChild(this);
  }
  setProperties(styles, pickKeys) {
    if (pickKeys) {
      for (const key of pickKeys) {
        this[key] = styles[key];
      }
    } else {
      Object.assign(this, styles);
    }
    return this;
  }
  containsPoint(_x, _y) {
    return false;
  }
  /**
   * Hit testing method.
   * Recursively checks if the given point is inside this node or any of its children.
   * Returns the first matching node or `undefined`.
   * Nodes that render later (show on top) are hit tested first.
   */
  pickNode(x, y, _localCoords = false) {
    if (!this.visible || this.pointerEvents === 1 || !this.containsPoint(x, y)) {
      return;
    }
    const children = [...this.children()];
    if (children.length > 1e3) {
      for (let i = children.length - 1; i >= 0; i--) {
        const child = children[i];
        const containsPoint3 = child.containsPoint(x, y);
        const hit = containsPoint3 ? child.pickNode(x, y) : void 0;
        if (hit) {
          return hit;
        }
      }
    } else if (children.length) {
      for (let i = children.length - 1; i >= 0; i--) {
        const hit = children[i].pickNode(x, y);
        if (hit) {
          return hit;
        }
      }
    } else if (!this.isContainerNode) {
      return this;
    }
  }
  invalidateCachedBBox() {
    if (this.cachedBBox != null) {
      this.cachedBBox = void 0;
      this.parentNode?.invalidateCachedBBox();
    }
  }
  getBBox() {
    if (this.cachedBBox == null) {
      this.cachedBBox = Object.freeze(this.computeBBox());
    }
    return this.cachedBBox;
  }
  computeBBox() {
    return;
  }
  markDirty() {
    const { _dirty } = this;
    const noParentCachedBBox = this.cachedBBox == null;
    if (noParentCachedBBox && _dirty)
      return;
    this.invalidateCachedBBox();
    this._dirty = true;
    if (this.parentNode) {
      this.parentNode.markDirty();
    }
  }
  markClean() {
    if (!this._dirty)
      return;
    this._dirty = false;
    for (const child of this.children()) {
      child.markClean();
    }
  }
  onZIndexChange() {
    const { parentNode } = this;
    if (parentNode) {
      parentNode.dirtyZIndex = true;
    }
  }
  toSVG() {
    return;
  }
};
_Node._nextSerialNumber = 0;
__decorateClass([
  SceneChangeDetection()
], _Node.prototype, "visible", 2);
__decorateClass([
  SceneChangeDetection({
    changeCb: (target) => target.onZIndexChange()
  })
], _Node.prototype, "zIndex", 2);
var Node = _Node;
var lerp = (x, y, t) => x * (1 - t) + y * t;
var srgbToLinear = (value) => {
  const sign = value < 0 ? -1 : 1;
  const abs = Math.abs(value);
  if (abs <= 0.04045)
    return value / 12.92;
  return sign * ((abs + 0.055) / 1.055) ** 2.4;
};
var srgbFromLinear = (value) => {
  const sign = value < 0 ? -1 : 1;
  const abs = Math.abs(value);
  if (abs > 31308e-7) {
    return sign * (1.055 * abs ** (1 / 2.4) - 0.055);
  }
  return 12.92 * value;
};
var _Color = class _Color2 {
  /**
   * Every color component should be in the [0, 1] range.
   * Some easing functions (such as elastic easing) can overshoot the target value by some amount.
   * So, when animating colors, if the source or target color components are already near
   * or at the edge of the allowed [0, 1] range, it is possible for the intermediate color
   * component value to end up outside of that range mid-animation. For this reason the constructor
   * performs range checking/constraining.
   * @param r Red component.
   * @param g Green component.
   * @param b Blue component.
   * @param a Alpha (opacity) component.
   */
  constructor(r, g, b, a = 1) {
    this.r = clamp(0, r || 0, 1);
    this.g = clamp(0, g || 0, 1);
    this.b = clamp(0, b || 0, 1);
    this.a = clamp(0, a || 0, 1);
  }
  /**
   * A color string can be in one of the following formats to be valid:
   * - #rgb
   * - #rrggbb
   * - rgb(r, g, b)
   * - rgba(r, g, b, a)
   * - CSS color name such as 'white', 'orange', 'cyan', etc.
   */
  static validColorString(str) {
    if (str.indexOf("#") >= 0) {
      return !!_Color2.parseHex(str);
    }
    if (str.indexOf("rgb") >= 0) {
      return !!_Color2.stringToRgba(str);
    }
    return !!_Color2.nameToHex.has(str.toLowerCase());
  }
  /**
   * The given string can be in one of the following formats:
   * - #rgb
   * - #rrggbb
   * - rgb(r, g, b)
   * - rgba(r, g, b, a)
   * - CSS color name such as 'white', 'orange', 'cyan', etc.
   * @param str
   */
  static fromString(str) {
    if (str.indexOf("#") >= 0) {
      return _Color2.fromHexString(str);
    }
    const hex = _Color2.nameToHex.get(str.toLowerCase());
    if (hex) {
      return _Color2.fromHexString(hex);
    }
    if (str.indexOf("rgb") >= 0) {
      return _Color2.fromRgbaString(str);
    }
    throw new Error(`Invalid color string: '${str}'`);
  }
  // See https://drafts.csswg.org/css-color/#hex-notation
  static parseHex(input) {
    input = input.replace(/ /g, "").slice(1);
    let parts;
    switch (input.length) {
      case 6:
      case 8:
        parts = [];
        for (let i = 0; i < input.length; i += 2) {
          parts.push(parseInt(`${input[i]}${input[i + 1]}`, 16));
        }
        break;
      case 3:
      case 4:
        parts = input.split("").map((p) => parseInt(p, 16)).map((p) => p + p * 16);
        break;
    }
    if (parts?.length >= 3 && parts.every((p) => p >= 0)) {
      if (parts.length === 3) {
        parts.push(255);
      }
      return parts;
    }
  }
  static fromHexString(str) {
    const values = _Color2.parseHex(str);
    if (values) {
      const [r, g, b, a] = values;
      return new _Color2(r / 255, g / 255, b / 255, a / 255);
    }
    throw new Error(`Malformed hexadecimal color string: '${str}'`);
  }
  static stringToRgba(str) {
    let po = -1;
    let pc = -1;
    for (let i = 0; i < str.length; i++) {
      const c = str[i];
      if (po === -1 && c === "(") {
        po = i;
      } else if (c === ")") {
        pc = i;
        break;
      }
    }
    if (po === -1 || pc === -1)
      return;
    const contents = str.substring(po + 1, pc);
    const parts = contents.split(",");
    const rgba = [];
    for (let i = 0; i < parts.length; i++) {
      const part = parts[i];
      let value = parseFloat(part);
      if (!Number.isFinite(value)) {
        return;
      }
      if (part.indexOf("%") >= 0) {
        value = clamp(0, value, 100);
        value /= 100;
      } else if (i === 3) {
        value = clamp(0, value, 1);
      } else {
        value = clamp(0, value, 255);
        value /= 255;
      }
      rgba.push(value);
    }
    return rgba;
  }
  static fromRgbaString(str) {
    const rgba = _Color2.stringToRgba(str);
    if (rgba) {
      if (rgba.length === 3) {
        return new _Color2(rgba[0], rgba[1], rgba[2]);
      } else if (rgba.length === 4) {
        return new _Color2(rgba[0], rgba[1], rgba[2], rgba[3]);
      }
    }
    throw new Error(`Malformed rgb/rgba color string: '${str}'`);
  }
  static fromArray(arr) {
    if (arr.length === 4) {
      return new _Color2(arr[0], arr[1], arr[2], arr[3]);
    }
    if (arr.length === 3) {
      return new _Color2(arr[0], arr[1], arr[2]);
    }
    throw new Error("The given array should contain 3 or 4 color components (numbers).");
  }
  static fromHSB(h, s, b, alpha = 1) {
    const rgb = _Color2.HSBtoRGB(h, s, b);
    return new _Color2(rgb[0], rgb[1], rgb[2], alpha);
  }
  static fromHSL(h, s, l, alpha = 1) {
    const rgb = _Color2.HSLtoRGB(h, s, l);
    return new _Color2(rgb[0], rgb[1], rgb[2], alpha);
  }
  static fromOKLCH(l, c, h, alpha = 1) {
    const rgb = _Color2.OKLCHtoRGB(l, c, h);
    return new _Color2(rgb[0], rgb[1], rgb[2], alpha);
  }
  static padHex(str) {
    return str.length === 1 ? "0" + str : str;
  }
  toHexString() {
    let hex = "#" + _Color2.padHex(Math.round(this.r * 255).toString(16)) + _Color2.padHex(Math.round(this.g * 255).toString(16)) + _Color2.padHex(Math.round(this.b * 255).toString(16));
    if (this.a < 1) {
      hex += _Color2.padHex(Math.round(this.a * 255).toString(16));
    }
    return hex;
  }
  toRgbaString(fractionDigits = 3) {
    const components = [Math.round(this.r * 255), Math.round(this.g * 255), Math.round(this.b * 255)];
    const k = Math.pow(10, fractionDigits);
    if (this.a !== 1) {
      components.push(Math.round(this.a * k) / k);
      return `rgba(${components.join(", ")})`;
    }
    return `rgb(${components.join(", ")})`;
  }
  toString() {
    if (this.a === 1) {
      return this.toHexString();
    }
    return this.toRgbaString();
  }
  toHSB() {
    return _Color2.RGBtoHSB(this.r, this.g, this.b);
  }
  static RGBtoOKLCH(r, g, b) {
    const LSRGB0 = srgbToLinear(r);
    const LSRGB1 = srgbToLinear(g);
    const LSRGB2 = srgbToLinear(b);
    const LMS0 = Math.cbrt(0.4122214708 * LSRGB0 + 0.5363325363 * LSRGB1 + 0.0514459929 * LSRGB2);
    const LMS1 = Math.cbrt(0.2119034982 * LSRGB0 + 0.6806995451 * LSRGB1 + 0.1073969566 * LSRGB2);
    const LMS2 = Math.cbrt(0.0883024619 * LSRGB0 + 0.2817188376 * LSRGB1 + 0.6299787005 * LSRGB2);
    const OKLAB0 = 0.2104542553 * LMS0 + 0.793617785 * LMS1 - 0.0040720468 * LMS2;
    const OKLAB1 = 1.9779984951 * LMS0 - 2.428592205 * LMS1 + 0.4505937099 * LMS2;
    const OKLAB2 = 0.0259040371 * LMS0 + 0.7827717662 * LMS1 - 0.808675766 * LMS2;
    const hue = Math.atan2(OKLAB2, OKLAB1) * 180 / Math.PI;
    const OKLCH0 = OKLAB0;
    const OKLCH1 = Math.hypot(OKLAB1, OKLAB2);
    const OKLCH2 = hue >= 0 ? hue : hue + 360;
    return [OKLCH0, OKLCH1, OKLCH2];
  }
  static OKLCHtoRGB(l, c, h) {
    const OKLAB0 = l;
    const OKLAB1 = c * Math.cos(h * Math.PI / 180);
    const OKLAB2 = c * Math.sin(h * Math.PI / 180);
    const LMS0 = (OKLAB0 + 0.3963377774 * OKLAB1 + 0.2158037573 * OKLAB2) ** 3;
    const LMS1 = (OKLAB0 - 0.1055613458 * OKLAB1 - 0.0638541728 * OKLAB2) ** 3;
    const LMS2 = (OKLAB0 - 0.0894841775 * OKLAB1 - 1.291485548 * OKLAB2) ** 3;
    const LSRGB0 = 4.0767416621 * LMS0 - 3.3077115913 * LMS1 + 0.2309699292 * LMS2;
    const LSRGB1 = -1.2684380046 * LMS0 + 2.6097574011 * LMS1 - 0.3413193965 * LMS2;
    const LSRGB2 = -0.0041960863 * LMS0 - 0.7034186147 * LMS1 + 1.707614701 * LMS2;
    const SRGB0 = srgbFromLinear(LSRGB0);
    const SRGB1 = srgbFromLinear(LSRGB1);
    const SRGB2 = srgbFromLinear(LSRGB2);
    return [SRGB0, SRGB1, SRGB2];
  }
  static RGBtoHSL(r, g, b) {
    const min = Math.min(r, g, b);
    const max = Math.max(r, g, b);
    const l = (max + min) / 2;
    let h;
    let s;
    if (max === min) {
      h = 0;
      s = 0;
    } else {
      const delta4 = max - min;
      s = l > 0.5 ? delta4 / (2 - max - min) : delta4 / (max + min);
      if (max === r) {
        h = (g - b) / delta4 + (g < b ? 6 : 0);
      } else if (max === g) {
        h = (b - r) / delta4 + 2;
      } else {
        h = (r - g) / delta4 + 4;
      }
      h *= 360 / 6;
    }
    return [h, s, l];
  }
  static HSLtoRGB(h, s, l) {
    h = (h % 360 + 360) % 360;
    if (s === 0) {
      return [l, l, l];
    }
    const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    const p = 2 * l - q;
    function hueToRgb(t) {
      if (t < 0)
        t += 1;
      if (t > 1)
        t -= 1;
      if (t < 1 / 6)
        return p + (q - p) * 6 * t;
      if (t < 1 / 2)
        return q;
      if (t < 2 / 3)
        return p + (q - p) * (2 / 3 - t) * 6;
      return p;
    }
    const r = hueToRgb(h / 360 + 1 / 3);
    const g = hueToRgb(h / 360);
    const b = hueToRgb(h / 360 - 1 / 3);
    return [r, g, b];
  }
  /**
   * Converts the given RGB triple to an array of HSB (HSV) components.
   */
  static RGBtoHSB(r, g, b) {
    const min = Math.min(r, g, b);
    const max = Math.max(r, g, b);
    const S = max === 0 ? 0 : (max - min) / max;
    let H = 0;
    if (min !== max) {
      const delta4 = max - min;
      const rc = (max - r) / delta4;
      const gc = (max - g) / delta4;
      const bc = (max - b) / delta4;
      if (r === max) {
        H = bc - gc;
      } else if (g === max) {
        H = 2 + rc - bc;
      } else {
        H = 4 + gc - rc;
      }
      H /= 6;
      if (H < 0) {
        H = H + 1;
      }
    }
    return [H * 360, S, max];
  }
  /**
   * Converts the given HSB (HSV) triple to an array of RGB components.
   */
  static HSBtoRGB(H, S, B) {
    H = (H % 360 + 360) % 360 / 360;
    let r = 0;
    let g = 0;
    let b = 0;
    if (S === 0) {
      r = g = b = B;
    } else {
      const h = (H - Math.floor(H)) * 6;
      const f = h - Math.floor(h);
      const p = B * (1 - S);
      const q = B * (1 - S * f);
      const t = B * (1 - S * (1 - f));
      switch (h >> 0) {
        case 0:
          r = B;
          g = t;
          b = p;
          break;
        case 1:
          r = q;
          g = B;
          b = p;
          break;
        case 2:
          r = p;
          g = B;
          b = t;
          break;
        case 3:
          r = p;
          g = q;
          b = B;
          break;
        case 4:
          r = t;
          g = p;
          b = B;
          break;
        case 5:
          r = B;
          g = p;
          b = q;
          break;
      }
    }
    return [r, g, b];
  }
  static mix(c0, c1, t) {
    return new _Color2(lerp(c0.r, c1.r, t), lerp(c0.g, c1.g, t), lerp(c0.b, c1.b, t), lerp(c0.a, c1.a, t));
  }
};
_Color.nameToHex = /* @__PURE__ */ new Map([
  ["aliceblue", "#F0F8FF"],
  ["antiquewhite", "#FAEBD7"],
  ["aqua", "#00FFFF"],
  ["aquamarine", "#7FFFD4"],
  ["azure", "#F0FFFF"],
  ["beige", "#F5F5DC"],
  ["bisque", "#FFE4C4"],
  ["black", "#000000"],
  ["blanchedalmond", "#FFEBCD"],
  ["blue", "#0000FF"],
  ["blueviolet", "#8A2BE2"],
  ["brown", "#A52A2A"],
  ["burlywood", "#DEB887"],
  ["cadetblue", "#5F9EA0"],
  ["chartreuse", "#7FFF00"],
  ["chocolate", "#D2691E"],
  ["coral", "#FF7F50"],
  ["cornflowerblue", "#6495ED"],
  ["cornsilk", "#FFF8DC"],
  ["crimson", "#DC143C"],
  ["cyan", "#00FFFF"],
  ["darkblue", "#00008B"],
  ["darkcyan", "#008B8B"],
  ["darkgoldenrod", "#B8860B"],
  ["darkgray", "#A9A9A9"],
  ["darkgreen", "#006400"],
  ["darkgrey", "#A9A9A9"],
  ["darkkhaki", "#BDB76B"],
  ["darkmagenta", "#8B008B"],
  ["darkolivegreen", "#556B2F"],
  ["darkorange", "#FF8C00"],
  ["darkorchid", "#9932CC"],
  ["darkred", "#8B0000"],
  ["darksalmon", "#E9967A"],
  ["darkseagreen", "#8FBC8F"],
  ["darkslateblue", "#483D8B"],
  ["darkslategray", "#2F4F4F"],
  ["darkslategrey", "#2F4F4F"],
  ["darkturquoise", "#00CED1"],
  ["darkviolet", "#9400D3"],
  ["deeppink", "#FF1493"],
  ["deepskyblue", "#00BFFF"],
  ["dimgray", "#696969"],
  ["dimgrey", "#696969"],
  ["dodgerblue", "#1E90FF"],
  ["firebrick", "#B22222"],
  ["floralwhite", "#FFFAF0"],
  ["forestgreen", "#228B22"],
  ["fuchsia", "#FF00FF"],
  ["gainsboro", "#DCDCDC"],
  ["ghostwhite", "#F8F8FF"],
  ["gold", "#FFD700"],
  ["goldenrod", "#DAA520"],
  ["gray", "#808080"],
  ["green", "#008000"],
  ["greenyellow", "#ADFF2F"],
  ["grey", "#808080"],
  ["honeydew", "#F0FFF0"],
  ["hotpink", "#FF69B4"],
  ["indianred", "#CD5C5C"],
  ["indigo", "#4B0082"],
  ["ivory", "#FFFFF0"],
  ["khaki", "#F0E68C"],
  ["lavender", "#E6E6FA"],
  ["lavenderblush", "#FFF0F5"],
  ["lawngreen", "#7CFC00"],
  ["lemonchiffon", "#FFFACD"],
  ["lightblue", "#ADD8E6"],
  ["lightcoral", "#F08080"],
  ["lightcyan", "#E0FFFF"],
  ["lightgoldenrodyellow", "#FAFAD2"],
  ["lightgray", "#D3D3D3"],
  ["lightgreen", "#90EE90"],
  ["lightgrey", "#D3D3D3"],
  ["lightpink", "#FFB6C1"],
  ["lightsalmon", "#FFA07A"],
  ["lightseagreen", "#20B2AA"],
  ["lightskyblue", "#87CEFA"],
  ["lightslategray", "#778899"],
  ["lightslategrey", "#778899"],
  ["lightsteelblue", "#B0C4DE"],
  ["lightyellow", "#FFFFE0"],
  ["lime", "#00FF00"],
  ["limegreen", "#32CD32"],
  ["linen", "#FAF0E6"],
  ["magenta", "#FF00FF"],
  ["maroon", "#800000"],
  ["mediumaquamarine", "#66CDAA"],
  ["mediumblue", "#0000CD"],
  ["mediumorchid", "#BA55D3"],
  ["mediumpurple", "#9370DB"],
  ["mediumseagreen", "#3CB371"],
  ["mediumslateblue", "#7B68EE"],
  ["mediumspringgreen", "#00FA9A"],
  ["mediumturquoise", "#48D1CC"],
  ["mediumvioletred", "#C71585"],
  ["midnightblue", "#191970"],
  ["mintcream", "#F5FFFA"],
  ["mistyrose", "#FFE4E1"],
  ["moccasin", "#FFE4B5"],
  ["navajowhite", "#FFDEAD"],
  ["navy", "#000080"],
  ["oldlace", "#FDF5E6"],
  ["olive", "#808000"],
  ["olivedrab", "#6B8E23"],
  ["orange", "#FFA500"],
  ["orangered", "#FF4500"],
  ["orchid", "#DA70D6"],
  ["palegoldenrod", "#EEE8AA"],
  ["palegreen", "#98FB98"],
  ["paleturquoise", "#AFEEEE"],
  ["palevioletred", "#DB7093"],
  ["papayawhip", "#FFEFD5"],
  ["peachpuff", "#FFDAB9"],
  ["peru", "#CD853F"],
  ["pink", "#FFC0CB"],
  ["plum", "#DDA0DD"],
  ["powderblue", "#B0E0E6"],
  ["purple", "#800080"],
  ["rebeccapurple", "#663399"],
  ["red", "#FF0000"],
  ["rosybrown", "#BC8F8F"],
  ["royalblue", "#4169E1"],
  ["saddlebrown", "#8B4513"],
  ["salmon", "#FA8072"],
  ["sandybrown", "#F4A460"],
  ["seagreen", "#2E8B57"],
  ["seashell", "#FFF5EE"],
  ["sienna", "#A0522D"],
  ["silver", "#C0C0C0"],
  ["skyblue", "#87CEEB"],
  ["slateblue", "#6A5ACD"],
  ["slategray", "#708090"],
  ["slategrey", "#708090"],
  ["snow", "#FFFAFA"],
  ["springgreen", "#00FF7F"],
  ["steelblue", "#4682B4"],
  ["tan", "#D2B48C"],
  ["teal", "#008080"],
  ["thistle", "#D8BFD8"],
  ["tomato", "#FF6347"],
  ["transparent", "#00000000"],
  ["turquoise", "#40E0D0"],
  ["violet", "#EE82EE"],
  ["wheat", "#F5DEB3"],
  ["white", "#FFFFFF"],
  ["whitesmoke", "#F5F5F5"],
  ["yellow", "#FFFF00"],
  ["yellowgreen", "#9ACD32"]
]);
var Color = _Color;
function interpolateNumber(a, b) {
  return (d) => Number(a) * (1 - d) + Number(b) * d;
}
function interpolateColor(a, b) {
  if (typeof a === "string") {
    try {
      a = Color.fromString(a);
    } catch {
      a = Color.fromArray([0, 0, 0]);
    }
  }
  if (typeof b === "string") {
    try {
      b = Color.fromString(b);
    } catch {
      b = Color.fromArray([0, 0, 0]);
    }
  }
  return (d) => Color.mix(a, b, d).toRgbaString();
}
var BREAK_TRANSFORM_CHAIN = Symbol("BREAK");
var CONFIG_KEY = "__decorator_config";
function initialiseConfig(target, propertyKeyOrSymbol) {
  if (Object.getOwnPropertyDescriptor(target, CONFIG_KEY) == null) {
    Object.defineProperty(target, CONFIG_KEY, { value: {} });
  }
  const config = target[CONFIG_KEY];
  const propertyKey = propertyKeyOrSymbol.toString();
  if (typeof config[propertyKey] !== "undefined") {
    return config[propertyKey];
  }
  const valuesMap = /* @__PURE__ */ new WeakMap();
  config[propertyKey] = { setters: [], getters: [], observers: [], valuesMap };
  const descriptor = Object.getOwnPropertyDescriptor(target, propertyKeyOrSymbol);
  const prevSet = descriptor?.set;
  const prevGet = descriptor?.get;
  const getter = function() {
    let value = prevGet ? prevGet.call(this) : valuesMap.get(this);
    for (const transformFn of config[propertyKey].getters) {
      value = transformFn(this, propertyKeyOrSymbol, value);
      if (value === BREAK_TRANSFORM_CHAIN) {
        return;
      }
    }
    return value;
  };
  const setter = function(value) {
    const { setters, observers } = config[propertyKey];
    let oldValue;
    if (setters.some((f) => f.length > 2)) {
      oldValue = prevGet ? prevGet.call(this) : valuesMap.get(this);
    }
    for (const transformFn of setters) {
      value = transformFn(this, propertyKeyOrSymbol, value, oldValue);
      if (value === BREAK_TRANSFORM_CHAIN) {
        return;
      }
    }
    if (prevSet) {
      prevSet.call(this, value);
    } else {
      valuesMap.set(this, value);
    }
    for (const observerFn of observers) {
      observerFn(this, value, oldValue);
    }
  };
  Object.defineProperty(target, propertyKeyOrSymbol, {
    set: setter,
    get: getter,
    enumerable: true,
    configurable: false
  });
  return config[propertyKey];
}
function addTransformToInstanceProperty(setTransform, getTransform, configMetadata) {
  return (target, propertyKeyOrSymbol) => {
    const config = initialiseConfig(target, propertyKeyOrSymbol);
    config.setters.push(setTransform);
    if (getTransform) {
      config.getters.unshift(getTransform);
    }
    if (configMetadata) {
      Object.assign(config, configMetadata);
    }
  };
}
function addObserverToInstanceProperty(setObserver) {
  return (target, propertyKeyOrSymbol) => {
    initialiseConfig(target, propertyKeyOrSymbol).observers.push(setObserver);
  };
}
function isDecoratedObject(target) {
  return typeof target !== "undefined" && CONFIG_KEY in target;
}
function listDecoratedProperties(target) {
  const targets = /* @__PURE__ */ new Set();
  while (isDecoratedObject(target)) {
    targets.add(target?.[CONFIG_KEY]);
    target = Object.getPrototypeOf(target);
  }
  return Array.from(targets).flatMap((configMap) => Object.keys(configMap));
}
function extractDecoratedProperties(target) {
  return listDecoratedProperties(target).reduce((result, key) => {
    result[key] = target[key] ?? null;
    return result;
  }, {});
}
function extractDecoratedPropertyMetadata(target, propertyKeyOrSymbol) {
  const propertyKey = propertyKeyOrSymbol.toString();
  while (isDecoratedObject(target)) {
    const config = target[CONFIG_KEY];
    if (Object.hasOwn(config, propertyKey)) {
      return config[propertyKey];
    }
    target = Object.getPrototypeOf(target);
  }
}
function isDefined(val) {
  return val != null;
}
function isArray(value) {
  return Array.isArray(value);
}
function isBoolean(value) {
  return typeof value === "boolean";
}
function isDate(value) {
  return value instanceof Date;
}
function isValidDate(value) {
  return isDate(value) && !isNaN(Number(value));
}
function isRegExp(value) {
  return value instanceof RegExp;
}
function isFunction(value) {
  return typeof value === "function";
}
function isObject(value) {
  return typeof value === "object" && value !== null && !isArray(value);
}
function isObjectLike(value) {
  return isArray(value) || isPlainObject(value);
}
function isPlainObject(value) {
  return typeof value === "object" && value !== null && Object.getPrototypeOf(value) === Object.prototype;
}
function isString(value) {
  return typeof value === "string";
}
function isNumber(value) {
  return typeof value === "number";
}
function isFiniteNumber(value) {
  return Number.isFinite(value);
}
function isHtmlElement(value) {
  return typeof window !== "undefined" && value instanceof HTMLElement;
}
function isEnumKey(enumObject, enumKey) {
  return isString(enumKey) && Object.keys(enumObject).includes(enumKey);
}
function isEnumValue(enumObject, enumValue) {
  return Object.values(enumObject).includes(enumValue);
}
function isSymbol(value) {
  return typeof value === "symbol";
}
function excludesType(obj, excluded) {
  return obj.type !== excluded;
}
function objectsEqual(a, b) {
  if (Array.isArray(a)) {
    if (!Array.isArray(b))
      return false;
    if (a.length !== b.length)
      return false;
    return a.every((av, i) => objectsEqual(av, b[i]));
  } else if (isPlainObject(a)) {
    if (!isPlainObject(b))
      return false;
    return objectsEqualWith(a, b, objectsEqual);
  }
  return a === b;
}
function objectsEqualWith(a, b, cmp2) {
  for (const key of Object.keys(b)) {
    if (!(key in a))
      return false;
  }
  for (const key of Object.keys(a)) {
    if (!(key in b))
      return false;
    if (!cmp2(a[key], b[key]))
      return false;
  }
  return true;
}
function deepMerge(...sources) {
  return mergeDefaults(...sources.reverse());
}
function mergeDefaults(...sources) {
  const target = {};
  for (const source of sources) {
    if (!isObject(source))
      continue;
    const keys = isDecoratedObject(source) ? listDecoratedProperties(source) : Object.keys(source);
    for (const key of keys) {
      if (isPlainObject(target[key]) && isPlainObject(source[key])) {
        target[key] = mergeDefaults(target[key], source[key]);
      } else {
        target[key] ?? (target[key] = source[key]);
      }
    }
  }
  return target;
}
function mergeArrayDefaults(dataArray, ...itemDefaults) {
  if (itemDefaults && isArray(dataArray)) {
    return dataArray.map((item) => mergeDefaults(item, ...itemDefaults));
  }
  return dataArray;
}
function mapValues(object2, mapper) {
  return Object.entries(object2).reduce(
    (result, [key, value]) => {
      result[key] = mapper(value, key, object2);
      return result;
    },
    {}
  );
}
function without(object2, keys) {
  const clone2 = { ...object2 };
  for (const key of keys) {
    delete clone2[key];
  }
  return clone2;
}
function getPath(object2, path) {
  const pathArray = isArray(path) ? path : path.split(".");
  return pathArray.reduce((value, pathKey) => value[pathKey], object2);
}
var SKIP_JS_BUILTINS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
function setPath(object2, path, newValue) {
  const pathArray = isArray(path) ? path.slice() : path.split(".");
  const lastKey = pathArray.pop();
  if (pathArray.some((p) => SKIP_JS_BUILTINS.has(p)))
    return;
  const lastObject = pathArray.reduce((value, pathKey) => value[pathKey], object2);
  lastObject[lastKey] = newValue;
  return lastObject[lastKey];
}
function partialAssign(keysToCopy, target, source) {
  if (source === void 0) {
    return target;
  }
  for (const key of keysToCopy) {
    const value = source[key];
    if (value !== void 0) {
      target[key] = value;
    }
  }
  return target;
}
function deepFreeze(obj) {
  Object.freeze(obj);
  Object.getOwnPropertyNames(obj).forEach((prop) => {
    const value = obj[prop];
    if (value !== null && (typeof value === "object" || typeof value === "function") && !Object.isFrozen(value)) {
      deepFreeze(value);
    }
  });
  return obj;
}
var easing_exports = {};
__export(easing_exports, {
  easeIn: () => easeIn,
  easeInOut: () => easeInOut,
  easeInOutQuad: () => easeInOutQuad,
  easeInQuad: () => easeInQuad,
  easeOut: () => easeOut,
  easeOutQuad: () => easeOutQuad,
  inverseEaseOut: () => inverseEaseOut,
  linear: () => linear
});
var linear = (n) => n;
var easeIn = (n) => 1 - Math.cos(n * Math.PI / 2);
var easeOut = (n) => Math.sin(n * Math.PI / 2);
var easeInOut = (n) => -(Math.cos(n * Math.PI) - 1) / 2;
var easeInQuad = (n) => n * n;
var easeOutQuad = (n) => 1 - (1 - n) ** 2;
var easeInOutQuad = (n) => n < 0.5 ? 2 * n * n : 1 - (-2 * n + 2) ** 2 / 2;
var inverseEaseOut = (x) => 2 * Math.asin(x) / Math.PI;
var QUICK_TRANSITION = 0.2;
var PHASE_ORDER = ["initial", "remove", "update", "add", "trailing", "end", "none"];
var PHASE_METADATA = {
  initial: {
    animationDuration: 1,
    animationDelay: 0
  },
  add: {
    animationDuration: 0.25,
    animationDelay: 0.75
  },
  remove: {
    animationDuration: 0.25,
    animationDelay: 0
  },
  update: {
    animationDuration: 0.5,
    animationDelay: 0.25
  },
  trailing: {
    animationDuration: QUICK_TRANSITION,
    animationDelay: 1,
    skipIfNoEarlierAnimations: true
  },
  end: {
    animationDelay: 1 + QUICK_TRANSITION,
    animationDuration: 0,
    skipIfNoEarlierAnimations: true
  },
  none: {
    animationDuration: 0,
    animationDelay: 0
  }
};
var RepeatType = /* @__PURE__ */ ((RepeatType2) => {
  RepeatType2["Loop"] = "loop";
  RepeatType2["Reverse"] = "reverse";
  return RepeatType2;
})(RepeatType || {});
function isNodeArray(array2) {
  return array2.every((n) => n instanceof Node);
}
function deconstructSelectionsOrNodes(selectionsOrNodes) {
  return isNodeArray(selectionsOrNodes) ? { nodes: selectionsOrNodes, selections: [] } : { nodes: [], selections: selectionsOrNodes };
}
function animationValuesEqual(a, b) {
  if (a === b) {
    return true;
  } else if (Array.isArray(a) && Array.isArray(b)) {
    return a.length === b.length && a.every((v, i) => animationValuesEqual(v, b[i]));
  } else if (isInterpolating(a) && isInterpolating(b)) {
    return a.equals(b);
  } else if (isPlainObject(a) && isPlainObject(b)) {
    return objectsEqualWith(a, b, animationValuesEqual);
  }
  return false;
}
var Animation = class {
  constructor(opts) {
    this.isComplete = false;
    this.elapsed = 0;
    this.iteration = 0;
    this.isPlaying = false;
    this.isReverse = false;
    this.id = opts.id;
    this.groupId = opts.groupId;
    this.autoplay = opts.autoplay ?? true;
    this.ease = opts.ease ?? linear;
    this.phase = opts.phase;
    const durationProportion = opts.duration ?? PHASE_METADATA[this.phase].animationDuration;
    this.duration = durationProportion * opts.defaultDuration;
    this.delay = (opts.delay ?? 0) * opts.defaultDuration;
    this.onComplete = opts.onComplete;
    this.onPlay = opts.onPlay;
    this.onStop = opts.onStop;
    this.onUpdate = opts.onUpdate;
    this.interpolate = this.createInterpolator(opts.from, opts.to);
    this.from = opts.from;
    if (opts.skip === true) {
      this.onUpdate?.(opts.to, false, this);
      this.onStop?.(this);
      this.onComplete?.(this);
      this.isComplete = true;
    }
    if (opts.collapsable !== false) {
      this.duration = this.checkCollapse(opts, this.duration);
    }
  }
  checkCollapse(opts, calculatedDuration) {
    return animationValuesEqual(opts.from, opts.to) ? 0 : calculatedDuration;
  }
  play(initialUpdate = false) {
    if (this.isPlaying || this.isComplete)
      return;
    this.isPlaying = true;
    this.onPlay?.(this);
    if (!this.autoplay)
      return;
    this.autoplay = false;
    if (!initialUpdate)
      return;
    this.onUpdate?.(this.from, true, this);
  }
  pause() {
    this.isPlaying = false;
  }
  stop() {
    this.isPlaying = false;
    if (!this.isComplete) {
      this.isComplete = true;
      this.onStop?.(this);
    }
  }
  update(time2) {
    if (this.isComplete)
      return time2;
    if (!this.isPlaying && this.autoplay) {
      this.play(true);
    }
    const previousElapsed = this.elapsed;
    this.elapsed += time2;
    if (this.delay > this.elapsed)
      return 0;
    const value = this.interpolate(this.isReverse ? 1 - this.delta : this.delta);
    this.onUpdate?.(value, false, this);
    const totalDuration = this.delay + this.duration;
    if (this.elapsed >= totalDuration) {
      this.stop();
      this.isComplete = true;
      this.onComplete?.(this);
      return time2 - (totalDuration - previousElapsed);
    }
    return 0;
  }
  get delta() {
    return this.ease(clamp(0, (this.elapsed - this.delay) / this.duration, 1));
  }
  createInterpolator(from3, to) {
    if (typeof to !== "object" || isInterpolating(to)) {
      return this.interpolateValue(from3, to);
    }
    const interpolatorEntries = [];
    for (const key of Object.keys(to)) {
      const interpolator = this.interpolateValue(from3[key], to[key]);
      if (interpolator != null) {
        interpolatorEntries.push([key, interpolator]);
      }
    }
    return (d) => {
      const result = {};
      for (const [key, interpolator] of interpolatorEntries) {
        result[key] = interpolator(d);
      }
      return result;
    };
  }
  interpolateValue(a, b) {
    if (a == null || b == null) {
      return;
    } else if (isInterpolating(a)) {
      return (d) => a[interpolate](b, d);
    }
    try {
      switch (typeof a) {
        case "number":
          return interpolateNumber(a, b);
        case "string":
          return interpolateColor(a, b);
        case "boolean":
          if (a === b) {
            return () => a;
          }
          break;
      }
    } catch {
    }
    throw new Error(`Unable to interpolate values: ${a}, ${b}`);
  }
};
var NODE_UPDATE_STATE_TO_PHASE_MAPPING = {
  added: "add",
  updated: "update",
  removed: "remove",
  unknown: "initial",
  "no-op": "none"
};
function fromToMotion(groupId, subId, animationManager, selectionsOrNodes, fns, getDatumId, diff2) {
  const { fromFn, toFn, applyFn = (node, props) => node.setProperties(props) } = fns;
  const { nodes, selections } = deconstructSelectionsOrNodes(selectionsOrNodes);
  const processNodes = (liveNodes, subNodes) => {
    let prevFromProps;
    let liveNodeIndex = 0;
    let nodeIndex = 0;
    for (const node of subNodes) {
      const isLive = liveNodes[liveNodeIndex] === node;
      const ctx = {
        last: nodeIndex >= subNodes.length - 1,
        lastLive: liveNodeIndex >= liveNodes.length - 1,
        prev: subNodes[nodeIndex - 1],
        prevFromProps,
        prevLive: liveNodes[liveNodeIndex - 1],
        next: subNodes[nodeIndex + 1],
        nextLive: liveNodes[liveNodeIndex + (isLive ? 1 : 0)]
      };
      const animationId = `${groupId}_${subId}_${node.id}`;
      animationManager.stopByAnimationId(animationId);
      let status = "unknown";
      if (!isLive) {
        status = "removed";
      } else if (getDatumId && diff2) {
        status = calculateStatus(node, node.datum, getDatumId, diff2);
      }
      node.transitionOut = status === "removed";
      const { phase, start: start2, finish, delay, duration, ...from3 } = fromFn(node, node.datum, status, ctx);
      const {
        phase: toPhase,
        start: toStart,
        finish: toFinish,
        delay: toDelay,
        duration: toDuration,
        ...to
      } = toFn(node, node.datum, status, ctx);
      const collapsable = finish == null;
      animationManager.animate({
        id: animationId,
        groupId,
        phase: phase ?? toPhase ?? "update",
        duration: duration ?? toDuration,
        delay: delay ?? toDelay,
        from: from3,
        to,
        ease: easeOut,
        collapsable,
        onPlay: () => {
          applyFn(node, { ...start2, ...toStart, ...from3 });
        },
        onUpdate(props) {
          applyFn(node, props);
        },
        onStop: () => {
          applyFn(node, {
            ...start2,
            ...toStart,
            ...from3,
            ...to,
            ...finish,
            ...toFinish
          });
        }
      });
      if (isLive) {
        liveNodeIndex++;
      }
      nodeIndex++;
      prevFromProps = from3;
    }
  };
  let selectionIndex = 0;
  for (const selection of selections) {
    const selectionNodes = selection.nodes();
    const liveNodes = selectionNodes.filter((n) => !selection.isGarbage(n));
    processNodes(liveNodes, selectionNodes);
    animationManager.animate({
      id: `${groupId}_${subId}_selection_${selectionIndex}`,
      groupId,
      phase: "end",
      from: 0,
      to: 1,
      ease: easeOut,
      onStop() {
        selection.cleanup();
      }
    });
    selectionIndex++;
  }
  processNodes(nodes, nodes);
}
function staticFromToMotion(groupId, subId, animationManager, selectionsOrNodes, from3, to, extraOpts) {
  const { nodes, selections } = deconstructSelectionsOrNodes(selectionsOrNodes);
  const { start: start2, finish, phase } = extraOpts;
  animationManager.animate({
    id: `${groupId}_${subId}`,
    groupId,
    phase: phase ?? "update",
    from: from3,
    to,
    ease: easeOut,
    onPlay: () => {
      if (!start2)
        return;
      for (const node of nodes) {
        node.setProperties(start2);
      }
      for (const selection of selections) {
        for (const node of selection.nodes()) {
          node.setProperties(start2);
        }
      }
    },
    onUpdate(props) {
      for (const node of nodes) {
        node.setProperties(props);
      }
      for (const selection of selections) {
        for (const node of selection.nodes()) {
          node.setProperties(props);
        }
      }
    },
    onStop: () => {
      for (const node of nodes) {
        node.setProperties({ ...to, ...finish });
      }
      for (const selection of selections) {
        for (const node of selection.nodes()) {
          node.setProperties({ ...to, ...finish });
        }
        selection.cleanup();
      }
    }
  });
}
function calculateStatus(node, datum, getDatumId, diff2) {
  const id = getDatumId(node, datum);
  if (diff2.added.has(id)) {
    return "added";
  }
  if (diff2.removed.has(id)) {
    return "removed";
  }
  return "updated";
}
var doOnceState = /* @__PURE__ */ new Map();
function doOnce(func, key) {
  if (doOnceState.has(key))
    return;
  doOnceState.set(key, true);
  func();
}
doOnce.clear = () => doOnceState.clear();
function identity(x) {
  return x;
}
function debounce(callback2, waitMs = 0, options) {
  const { leading = false, trailing = true, maxWait = Infinity } = options ?? {};
  let timerId;
  let startTime;
  if (maxWait < waitMs) {
    throw new Error("Value of maxWait cannot be lower than waitMs.");
  }
  function debounceCallback(...args) {
    if (leading && !startTime) {
      startTime = Date.now();
      timerId = setTimeout(() => startTime = null, waitMs);
      callback2(...args);
      return;
    }
    let adjustedWaitMs = waitMs;
    if (maxWait !== Infinity && startTime) {
      const elapsedTime = Date.now() - startTime;
      if (waitMs > maxWait - elapsedTime) {
        adjustedWaitMs = maxWait - elapsedTime;
      }
    }
    clearTimeout(timerId);
    startTime ?? (startTime = Date.now());
    timerId = setTimeout(() => {
      startTime = null;
      if (trailing) {
        callback2(...args);
      }
    }, adjustedWaitMs);
  }
  return Object.assign(debounceCallback, {
    cancel() {
      clearTimeout(timerId);
      startTime = null;
    }
  });
}
function throttle(callback2, waitMs, options) {
  const { leading = true, trailing = true } = options ?? {};
  let timerId;
  let lastArgs;
  let shouldWait = false;
  function timeoutHandler() {
    if (trailing && lastArgs) {
      timerId = setTimeout(timeoutHandler, waitMs);
      callback2(...lastArgs);
    } else {
      shouldWait = false;
    }
    lastArgs = null;
  }
  function throttleCallback(...args) {
    if (shouldWait) {
      lastArgs = args;
    } else {
      shouldWait = true;
      timerId = setTimeout(timeoutHandler, waitMs);
      if (leading) {
        callback2(...args);
      } else {
        lastArgs = args;
      }
    }
  }
  return Object.assign(throttleCallback, {
    cancel() {
      clearTimeout(timerId);
      shouldWait = false;
      lastArgs = null;
    }
  });
}
var Logger = {
  log(...logContent) {
    console.log(...logContent);
  },
  warn(message, ...logContent) {
    console.warn(`AG Charts - ${message}`, ...logContent);
  },
  error(message, ...logContent) {
    if (typeof message === "object") {
      console.error(`AG Charts error`, message, ...logContent);
    } else {
      console.error(`AG Charts - ${message}`, ...logContent);
    }
  },
  table(...logContent) {
    console.table(...logContent);
  },
  warnOnce(message, ...logContent) {
    doOnce(() => Logger.warn(message, ...logContent), `Logger.warn: ${message}`);
  },
  errorOnce(message, ...logContent) {
    doOnce(() => Logger.error(message, ...logContent), `Logger.error: ${message}`);
  }
};
var Invalidating = (target, propertyKey) => {
  const mappedProperty = Symbol(String(propertyKey));
  target[mappedProperty] = void 0;
  Object.defineProperty(target, propertyKey, {
    get() {
      return this[mappedProperty];
    },
    set(newValue) {
      const oldValue = this[mappedProperty];
      if (oldValue !== newValue) {
        this[mappedProperty] = newValue;
        this.invalid = true;
      }
    },
    enumerable: true,
    configurable: false
  });
};
var _ContinuousScale = class _ContinuousScale2 {
  constructor(domain, range3) {
    this.invalid = true;
    this.nice = false;
    this.interval = void 0;
    this.tickCount = _ContinuousScale2.defaultTickCount;
    this.minTickCount = 0;
    this.maxTickCount = Infinity;
    this.niceDomain = [];
    this.defaultClamp = false;
    this.domain = domain;
    this.range = range3;
  }
  static is(value) {
    return value instanceof _ContinuousScale2;
  }
  transform(x) {
    return x;
  }
  transformInvert(x) {
    return x;
  }
  calcBandwidth(smallestInterval = 1) {
    const domain = this.getDomain();
    const rangeDistance = this.getPixelRange();
    const intervals = Math.abs(domain[1] - domain[0]) / smallestInterval + 1;
    const maxBands = Math.floor(rangeDistance);
    const bands = Math.min(intervals, maxBands);
    return rangeDistance / Math.max(1, bands);
  }
  getDomain() {
    if (this.nice) {
      this.refresh();
      if (this.niceDomain.length) {
        return this.niceDomain;
      }
    }
    return this.domain;
  }
  convert(x, clamp2) {
    if (!this.domain || this.domain.length < 2) {
      return NaN;
    }
    this.refresh();
    const domain = this.getDomain().map((d) => this.transform(d));
    const [d0, d1] = domain;
    const { range: range3 } = this;
    const [r0, r1] = range3;
    x = this.transform(x);
    if (clamp2 ?? this.defaultClamp) {
      const [start2, stop] = findMinMax(domain.map(Number));
      if (Number(x) < start2) {
        return r0;
      } else if (Number(x) > stop) {
        return r1;
      }
    }
    if (d0 === d1) {
      return (r0 + r1) / 2;
    } else if (x === d0) {
      return r0;
    } else if (x === d1) {
      return r1;
    }
    return r0 + (Number(x) - Number(d0)) / (Number(d1) - Number(d0)) * (r1 - r0);
  }
  invert(x, clamp2) {
    this.refresh();
    const domain = this.getDomain().map((d2) => this.transform(d2));
    const [d0, d1] = domain;
    const { range: range3 } = this;
    const [r0, r1] = range3;
    const isReversed = r0 > r1;
    const rMin = isReversed ? r1 : r0;
    const rMax = isReversed ? r0 : r1;
    if (clamp2 ?? this.defaultClamp) {
      if (x < rMin) {
        return isReversed ? d1 : d0;
      } else if (x > rMax) {
        return isReversed ? d0 : d1;
      }
    }
    let d;
    if (r0 === r1) {
      d = this.toDomain((Number(d0) + Number(d1)) / 2);
    } else {
      d = this.toDomain(Number(d0) + (x - r0) / (r1 - r0) * (Number(d1) - Number(d0)));
    }
    return this.transformInvert(d);
  }
  refresh() {
    if (!this.invalid)
      return;
    this.invalid = false;
    this.update();
    if (this.invalid) {
      Logger.warnOnce("Expected update to not invalidate scale");
    }
  }
  getPixelRange() {
    const [a, b] = this.range;
    return Math.abs(b - a);
  }
};
_ContinuousScale.defaultTickCount = 5;
_ContinuousScale.defaultMaxTickCount = 6;
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "domain", 2);
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "range", 2);
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "nice", 2);
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "interval", 2);
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "tickCount", 2);
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "minTickCount", 2);
__decorateClass([
  Invalidating
], _ContinuousScale.prototype, "maxTickCount", 2);
var ContinuousScale = _ContinuousScale;
function extent(values) {
  if (values.length === 0) {
    return null;
  }
  let min = Infinity;
  let max = -Infinity;
  for (let n of values) {
    if (n instanceof Date) {
      n = n.getTime();
    }
    if (typeof n !== "number") {
      continue;
    }
    if (n < min) {
      min = n;
    }
    if (n > max) {
      max = n;
    }
  }
  const result = [min, max];
  return result.every(isFinite) ? result : null;
}
function normalisedExtentWithMetadata(d, min, max) {
  let clipped = false;
  if (d.length > 2) {
    d = extent(d) ?? [NaN, NaN];
  }
  if (!isNaN(min)) {
    clipped || (clipped = min > d[0]);
    d = [min, d[1]];
  }
  if (!isNaN(max)) {
    clipped || (clipped = max < d[1]);
    d = [d[0], max];
  }
  if (d[0] > d[1]) {
    d = [];
  }
  return { extent: d, clipped };
}
function arraysEqual(a, b) {
  if (a == null || b == null || a.length !== b.length) {
    return false;
  }
  for (let i = 0; i < a.length; i++) {
    if (Array.isArray(a[i]) && Array.isArray(b[i])) {
      if (!arraysEqual(a[i], b[i])) {
        return false;
      }
    } else if (a[i] !== b[i]) {
      return false;
    }
  }
  return true;
}
function toArray(value) {
  if (typeof value === "undefined") {
    return [];
  }
  return Array.isArray(value) ? value : [value];
}
function unique(array2) {
  return Array.from(new Set(array2));
}
function groupBy(array2, iteratee) {
  return array2.reduce((result, item) => {
    const groupKey = iteratee(item);
    result[groupKey] ?? (result[groupKey] = []);
    result[groupKey].push(item);
    return result;
  }, {});
}
function circularSliceArray(data, size, offset4 = 0) {
  if (data.length === 0) {
    return [];
  }
  const result = [];
  for (let i = 0; i < size; i++) {
    result.push(data.at((i + offset4) % data.length));
  }
  return result;
}
function sortBasedOnArray(baseArray, orderArray) {
  const orderMap = /* @__PURE__ */ new Map();
  orderArray.forEach((item, index) => {
    orderMap.set(item, index);
  });
  return baseArray.sort((a, b) => {
    const indexA = orderMap.get(a) ?? Infinity;
    const indexB = orderMap.get(b) ?? Infinity;
    return indexA - indexB;
  });
}
function includes(array2, item) {
  return array2.includes(item);
}
var durationSecond = 1e3;
var durationMinute = durationSecond * 60;
var durationHour = durationMinute * 60;
var durationDay = durationHour * 24;
var durationWeek = durationDay * 7;
var durationMonth = durationDay * 30;
var durationYear = durationDay * 365;
var TimeInterval = class {
  constructor(_encode, _decode, _rangeCallback) {
    this._encode = _encode;
    this._decode = _decode;
    this._rangeCallback = _rangeCallback;
  }
  /**
   * Returns a new date representing the latest interval boundary date before or equal to date.
   * For example, `day.floor(date)` typically returns 12:00 AM local time on the given date.
   * @param date
   */
  floor(date) {
    const d = new Date(date);
    const e = this._encode(d);
    return this._decode(e);
  }
  /**
   * Returns a new date representing the earliest interval boundary date after or equal to date.
   * @param date
   */
  ceil(date) {
    const d = new Date(Number(date) - 1);
    const e = this._encode(d);
    return this._decode(e + 1);
  }
  /**
   * Returns an array of dates representing every interval boundary after or equal to start (inclusive) and before stop (exclusive).
   * @param start Range start.
   * @param stop Range end.
   * @param extend If specified, the requested range will be extended to the closest "nice" values.
   */
  range(start2, stop, extend) {
    const rangeCallback = this._rangeCallback?.(start2, stop);
    const e0 = this._encode(extend ? this.floor(start2) : this.ceil(start2));
    const e1 = this._encode(extend ? this.ceil(stop) : this.floor(stop));
    if (e1 < e0) {
      return [];
    }
    const range3 = [];
    for (let e = e0; e <= e1; e++) {
      const d = this._decode(e);
      range3.push(d);
    }
    rangeCallback?.();
    return range3;
  }
};
var CountableTimeInterval = class extends TimeInterval {
  getOffset(snapTo, step) {
    const s = typeof snapTo === "number" || snapTo instanceof Date ? this._encode(new Date(snapTo)) : 0;
    return Math.floor(s) % step;
  }
  /**
   * Returns a filtered view of this interval representing every step'th date.
   * It can be a number of minutes, hours, days etc.
   * Must be a positive integer.
   * @param step
   */
  every(step, options) {
    let offset4 = 0;
    let rangeCallback;
    const unsafeStep = step;
    step = Math.max(1, Math.round(step));
    if (unsafeStep !== step) {
      Logger.warnOnce(`interval step of [${unsafeStep}] rounded to [${step}].`);
    }
    const { snapTo = "start" } = options ?? {};
    if (typeof snapTo === "string") {
      const initialOffset = offset4;
      rangeCallback = (start2, stop) => {
        const s = snapTo === "start" ? start2 : stop;
        offset4 = this.getOffset(s, step);
        return () => offset4 = initialOffset;
      };
    } else if (typeof snapTo === "number") {
      offset4 = this.getOffset(new Date(snapTo), step);
    } else if (snapTo instanceof Date) {
      offset4 = this.getOffset(snapTo, step);
    }
    const encode13 = (date) => {
      const e = this._encode(date);
      return Math.floor((e - offset4) / step);
    };
    const decode13 = (encoded) => {
      return this._decode(encoded * step + offset4);
    };
    return new TimeInterval(encode13, decode13, rangeCallback);
  }
};
function encode(date) {
  const tzOffsetMs = date.getTimezoneOffset() * durationMinute;
  return Math.floor((date.getTime() - tzOffsetMs) / durationDay);
}
function decode(encoded) {
  const d = new Date(1970, 0, 1);
  d.setDate(d.getDate() + encoded);
  return d;
}
var day = new CountableTimeInterval(encode, decode);
var offset = (/* @__PURE__ */ new Date()).getTimezoneOffset() * durationMinute;
function encode2(date) {
  return Math.floor((date.getTime() - offset) / durationHour);
}
function decode2(encoded) {
  return new Date(offset + encoded * durationHour);
}
var hour = new CountableTimeInterval(encode2, decode2);
var offset2 = (/* @__PURE__ */ new Date()).getTimezoneOffset() * durationMinute;
function encode3(date) {
  return Math.floor((date.getTime() - offset2) / durationMinute);
}
function decode3(encoded) {
  return new Date(offset2 + encoded * durationMinute);
}
var minute = new CountableTimeInterval(encode3, decode3);
function encode4(date) {
  return date.getFullYear() * 12 + date.getMonth();
}
function decode4(encoded) {
  const year2 = Math.floor(encoded / 12);
  const month2 = encoded - year2 * 12;
  return new Date(year2, month2, 1);
}
var month = new CountableTimeInterval(encode4, decode4);
var offset3 = (/* @__PURE__ */ new Date()).getTimezoneOffset() * durationMinute;
function encode5(date) {
  return Math.floor((date.getTime() - offset3) / durationSecond);
}
function decode5(encoded) {
  return new Date(offset3 + encoded * durationSecond);
}
var second = new CountableTimeInterval(encode5, decode5);
function weekday(weekStart) {
  const thursday2 = 4;
  const dayShift = (7 + weekStart - thursday2) % 7;
  function encode13(date) {
    const tzOffsetMs = date.getTimezoneOffset() * durationMinute;
    return Math.floor((date.getTime() - tzOffsetMs) / durationWeek - dayShift / 7);
  }
  function decode13(encoded) {
    const d = new Date(1970, 0, 1);
    d.setDate(d.getDate() + encoded * 7 + dayShift);
    return d;
  }
  return new CountableTimeInterval(encode13, decode13);
}
var sunday = weekday(0);
var monday = weekday(1);
var tuesday = weekday(2);
var wednesday = weekday(3);
var thursday = weekday(4);
var friday = weekday(5);
var saturday = weekday(6);
function encode6(date) {
  return date.getFullYear();
}
function decode6(encoded) {
  const d = /* @__PURE__ */ new Date();
  d.setFullYear(encoded);
  d.setMonth(0, 1);
  d.setHours(0, 0, 0, 0);
  return d;
}
var year = new CountableTimeInterval(encode6, decode6);
var CONSTANTS = {
  periods: ["AM", "PM"],
  days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
  months: [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December"
  ],
  shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
};
function dayOfYear(date, startOfYear = new Date(date.getFullYear(), 0, 1)) {
  const startOffset = date.getTimezoneOffset() - startOfYear.getTimezoneOffset();
  const timeDiff = date.getTime() - startOfYear.getTime() + startOffset * 6e4;
  const timeOneDay = 36e5 * 24;
  return Math.floor(timeDiff / timeOneDay);
}
function weekOfYear(date, startDay) {
  const startOfYear = new Date(date.getFullYear(), 0, 1);
  const startOfYearDay = startOfYear.getDay();
  const firstWeekStartOffset = (startDay - startOfYearDay + 7) % 7;
  const startOffset = new Date(date.getFullYear(), 0, firstWeekStartOffset + 1);
  if (startOffset <= date) {
    return Math.floor(dayOfYear(date, startOffset) / 7) + 1;
  }
  return 0;
}
var SUNDAY = 0;
var MONDAY = 1;
var THURSDAY = 4;
function isoWeekOfYear(date, year2 = date.getFullYear()) {
  const firstOfYear = new Date(year2, 0, 1);
  const firstOfYearDay = firstOfYear.getDay();
  const firstThursdayOffset = (THURSDAY - firstOfYearDay + 7) % 7;
  const startOffset = new Date(year2, 0, firstThursdayOffset - (THURSDAY - MONDAY) + 1);
  if (startOffset <= date) {
    return Math.floor(dayOfYear(date, startOffset) / 7) + 1;
  }
  return isoWeekOfYear(date, year2 - 1);
}
function timezone(date) {
  const offset4 = date.getTimezoneOffset();
  const unsignedOffset = Math.abs(offset4);
  const sign = offset4 > 0 ? "-" : "+";
  return `${sign}${pad(Math.floor(unsignedOffset / 60), 2, "0")}${pad(Math.floor(unsignedOffset % 60), 2, "0")}`;
}
var FORMATTERS = {
  a: (d) => CONSTANTS.shortDays[d.getDay()],
  A: (d) => CONSTANTS.days[d.getDay()],
  b: (d) => CONSTANTS.shortMonths[d.getMonth()],
  B: (d) => CONSTANTS.months[d.getMonth()],
  c: "%x, %X",
  d: (d, p) => pad(d.getDate(), 2, p ?? "0"),
  e: "%_d",
  f: (d, p) => pad(d.getMilliseconds() * 1e3, 6, p ?? "0"),
  H: (d, p) => pad(d.getHours(), 2, p ?? "0"),
  I: (d, p) => {
    const hours = d.getHours() % 12;
    return hours === 0 ? "12" : pad(hours, 2, p ?? "0");
  },
  j: (d, p) => pad(dayOfYear(d) + 1, 3, p ?? "0"),
  m: (d, p) => pad(d.getMonth() + 1, 2, p ?? "0"),
  M: (d, p) => pad(d.getMinutes(), 2, p ?? "0"),
  L: (d, p) => pad(d.getMilliseconds(), 3, p ?? "0"),
  p: (d) => d.getHours() < 12 ? "AM" : "PM",
  Q: (d) => String(d.getTime()),
  s: (d) => String(Math.floor(d.getTime() / 1e3)),
  S: (d, p) => pad(d.getSeconds(), 2, p ?? "0"),
  u: (d) => {
    let day2 = d.getDay();
    if (day2 < 1)
      day2 += 7;
    return String(day2 % 7);
  },
  U: (d, p) => pad(weekOfYear(d, SUNDAY), 2, p ?? "0"),
  V: (d, p) => pad(isoWeekOfYear(d), 2, p ?? "0"),
  w: (d, p) => pad(d.getDay(), 2, p ?? "0"),
  W: (d, p) => pad(weekOfYear(d, MONDAY), 2, p ?? "0"),
  x: "%-m/%-d/%Y",
  X: "%-I:%M:%S %p",
  y: (d, p) => pad(d.getFullYear() % 100, 2, p ?? "0"),
  Y: (d, p) => pad(d.getFullYear(), 4, p ?? "0"),
  Z: (d) => timezone(d),
  "%": () => "%"
};
var PADS = {
  _: " ",
  "0": "0",
  "-": ""
};
function pad(value, size, padChar) {
  const output = String(Math.floor(value));
  if (output.length >= size) {
    return output;
  }
  return `${padChar.repeat(size - output.length)}${output}`;
}
function buildFormatter(formatString) {
  const formatParts = [];
  while (formatString.length > 0) {
    let nextEscapeIdx = formatString.indexOf("%");
    if (nextEscapeIdx !== 0) {
      const literalPart = nextEscapeIdx > 0 ? formatString.substring(0, nextEscapeIdx) : formatString;
      formatParts.push(literalPart);
    }
    if (nextEscapeIdx < 0)
      break;
    const maybePadSpecifier = formatString[nextEscapeIdx + 1];
    const maybePad = PADS[maybePadSpecifier];
    if (maybePad != null) {
      nextEscapeIdx++;
    }
    const maybeFormatterSpecifier = formatString[nextEscapeIdx + 1];
    const maybeFormatter = FORMATTERS[maybeFormatterSpecifier];
    if (typeof maybeFormatter === "function") {
      formatParts.push([maybeFormatter, maybePad]);
    } else if (typeof maybeFormatter === "string") {
      const formatter = buildFormatter(maybeFormatter);
      formatParts.push([formatter, maybePad]);
    } else {
      formatParts.push(`${maybePad ?? ""}${maybeFormatterSpecifier}`);
    }
    formatString = formatString.substring(nextEscapeIdx + 2);
  }
  return (dateTime) => {
    const dateTimeAsDate = typeof dateTime === "number" ? new Date(dateTime) : dateTime;
    return formatParts.map((c) => typeof c === "string" ? c : c[0](dateTimeAsDate, c[1])).join("");
  };
}
function dateToNumber(value) {
  return value instanceof Date ? value.getTime() : value;
}
function defaultTimeTickFormat(ticks, domain, formatOffset) {
  const formatString = calculateDefaultTimeTickFormat(ticks, domain, formatOffset);
  const formatter = buildFormatter(formatString);
  return (date) => formatter(date);
}
function calculateDefaultTimeTickFormat(ticks = [], domain = ticks, formatOffset = 0) {
  let minInterval = Infinity;
  for (let i = 1; i < ticks.length; i++) {
    minInterval = Math.min(minInterval, Math.abs(ticks[i] - ticks[i - 1]));
  }
  const startYear = new Date(domain[0]).getFullYear();
  const stopYear = new Date(domain.at(-1)).getFullYear();
  const yearChange = stopYear - startYear > 0;
  const timeFormat = isFinite(minInterval) ? getIntervalLowestGranularityFormat(minInterval, ticks) : getLowestGranularityFormat(ticks[0]);
  return formatStringBuilder(Math.max(timeFormat - formatOffset, 0), yearChange, ticks);
}
function getIntervalLowestGranularityFormat(value, ticks) {
  if (value < durationSecond) {
    return 0;
  } else if (value < durationMinute) {
    return 1;
  } else if (value < durationHour) {
    return 2;
  } else if (value < durationDay) {
    return 3;
  } else if (value < durationWeek) {
    return 4;
  } else if (value < durationDay * 28 || value < durationDay * 31 && hasDuplicateMonth(ticks)) {
    return 5;
  } else if (value < durationYear) {
    return 6;
  }
  return 7;
}
function getLowestGranularityFormat(value) {
  if (second.floor(value) < value) {
    return 0;
  } else if (minute.floor(value) < value) {
    return 1;
  } else if (hour.floor(value) < value) {
    return 2;
  } else if (day.floor(value) < value) {
    return 3;
  } else if (month.floor(value) < value) {
    if (sunday.floor(value) < value) {
      return 4;
    }
    return 5;
  } else if (year.floor(value) < value) {
    return 6;
  }
  return 7;
}
function hasDuplicateMonth(ticks) {
  let prevMonth = new Date(ticks[0]).getMonth();
  for (let i = 1; i < ticks.length; i++) {
    const tickMonth = new Date(ticks[i]).getMonth();
    if (prevMonth === tickMonth) {
      return true;
    }
    prevMonth = tickMonth;
  }
  return false;
}
function formatStringBuilder(defaultTimeFormat, yearChange, ticks) {
  const firstTick = dateToNumber(ticks[0]);
  const lastTick = dateToNumber(ticks.at(-1));
  const extent2 = Math.abs(lastTick - firstTick);
  const activeYear = yearChange || defaultTimeFormat === 7;
  const activeDate = extent2 === 0;
  const parts = [
    ["hour", 6 * durationHour, 14 * durationDay, 3, "%I %p"],
    ["hour", durationMinute, 6 * durationHour, 3, "%I:%M"],
    ["second", 1e3, 6 * durationHour, 1, ":%S"],
    ["ms", 0, 6 * durationHour, 0, ".%L"],
    ["am/pm", durationMinute, 6 * durationHour, 3, "%p"],
    " ",
    ["day", durationDay, durationWeek, 4, "%a"],
    ["month", activeDate ? 0 : durationWeek, 52 * durationWeek, 5, "%b %d"],
    ["month", 5 * durationWeek, 10 * durationYear, 6, "%B"],
    " ",
    ["year", activeYear ? 0 : durationYear, Infinity, 7, "%Y"]
  ];
  const formatParts = parts.filter((v) => {
    if (typeof v === "string") {
      return true;
    }
    const [_, min, max, format] = v;
    return format >= defaultTimeFormat && min <= extent2 && extent2 < max;
  }).reduce(
    (r, next) => {
      if (typeof next === "string") {
        r.result.push(next);
      } else if (!r.used.has(next[0])) {
        r.result.push(next);
        r.used.add(next[0]);
      }
      return r;
    },
    { result: [], used: /* @__PURE__ */ new Set() }
  ).result;
  const firstFormat = formatParts.findIndex((v) => typeof v !== "string");
  const lastFormat = formatParts.findLastIndex((v) => typeof v !== "string");
  return formatParts.slice(firstFormat, lastFormat + 1).map((v) => typeof v === "string" ? v : v[4]).join("").replaceAll(/\s+/g, " ").trim();
}
var _BandScale = class _BandScale2 {
  constructor() {
    this.type = "band";
    this.invalid = true;
    this.range = [0, 1];
    this.round = false;
    this.interval = void 0;
    this.index = /* @__PURE__ */ new Map();
    this._domain = [];
    this._bandwidth = 1;
    this._step = 1;
    this._inset = 1;
    this._rawBandwidth = 1;
    this._paddingInner = 0;
    this._paddingOuter = 0;
  }
  static is(value) {
    return value instanceof _BandScale2;
  }
  refresh() {
    if (!this.invalid)
      return;
    this.invalid = false;
    this.update();
    if (this.invalid) {
      Logger.warnOnce("Expected update to not invalidate scale");
    }
  }
  set domain(values) {
    this.index = /* @__PURE__ */ new Map();
    this.invalid = true;
    this._domain = [];
    for (const value of values) {
      const key = dateToNumber(value);
      if (this.getIndex(key) === void 0) {
        this.index.set(key, this._domain.push(value) - 1);
      }
    }
  }
  get domain() {
    return this._domain;
  }
  getDomain() {
    return this._domain;
  }
  ticks() {
    this.refresh();
    return this._domain;
  }
  convert(d) {
    this.refresh();
    const i = this.getIndex(d);
    if (i == null || i < 0 || i >= this.domain.length) {
      return NaN;
    }
    return this.ordinalRange(i);
  }
  invertNearestIndex(position) {
    this.refresh();
    const { domain } = this;
    if (domain.length === 0)
      return -1;
    let low = 0;
    let high = domain.length - 1;
    let closestDistance = Infinity;
    let closestIndex = 0;
    while (low <= high) {
      const mid = (high + low) / 2 | 0;
      const p = this.ordinalRange(mid);
      const distance3 = Math.abs(p - position);
      if (distance3 === 0)
        return mid;
      if (distance3 < closestDistance) {
        closestDistance = distance3;
        closestIndex = mid;
      }
      if (p < position) {
        low = mid + 1;
      } else {
        high = mid - 1;
      }
    }
    return closestIndex;
  }
  invert(position) {
    this.refresh();
    const index = this.invertNearestIndex(position);
    const p = this.ordinalRange(index);
    return position === p ? this.domain[index] : void 0;
  }
  invertNearest(position) {
    const index = this.invertNearestIndex(position);
    return this.domain[index];
  }
  get bandwidth() {
    this.refresh();
    return this._bandwidth;
  }
  get step() {
    this.refresh();
    return this._step;
  }
  get inset() {
    this.refresh();
    return this._inset;
  }
  get rawBandwidth() {
    this.refresh();
    return this._rawBandwidth;
  }
  set padding(value) {
    value = clamp(0, value, 1);
    this._paddingInner = value;
    this._paddingOuter = value;
  }
  get padding() {
    return this._paddingInner;
  }
  set paddingInner(value) {
    this._paddingInner = clamp(0, value, 1);
  }
  get paddingInner() {
    return this._paddingInner;
  }
  set paddingOuter(value) {
    this._paddingOuter = clamp(0, value, 1);
  }
  get paddingOuter() {
    return this._paddingOuter;
  }
  update() {
    const count = this._domain.length;
    if (count === 0)
      return;
    const [r0, r1] = this.range;
    let { _paddingInner: paddingInner } = this;
    const { _paddingOuter: paddingOuter, round: round5 } = this;
    const rangeDistance = r1 - r0;
    let rawStep;
    if (count === 1) {
      paddingInner = 0;
      rawStep = rangeDistance * (1 - paddingOuter * 2);
    } else {
      rawStep = rangeDistance / Math.max(1, count - paddingInner + paddingOuter * 2);
    }
    const step = round5 ? Math.floor(rawStep) : rawStep;
    let inset = r0 + (rangeDistance - step * (count - paddingInner)) / 2;
    let bandwidth = step * (1 - paddingInner);
    if (round5) {
      inset = Math.round(inset);
      bandwidth = Math.round(bandwidth);
    }
    this._step = step;
    this._inset = inset;
    this._bandwidth = bandwidth;
    this._rawBandwidth = rawStep * (1 - paddingInner);
  }
  ordinalRange(i) {
    const { _inset: inset, _step: step } = this;
    return inset + step * i;
  }
  getIndex(value) {
    return this.index.get(value instanceof Date ? value.getTime() : value);
  }
};
__decorateClass([
  Invalidating
], _BandScale.prototype, "range", 2);
__decorateClass([
  Invalidating
], _BandScale.prototype, "round", 2);
__decorateClass([
  Invalidating
], _BandScale.prototype, "interval", 2);
var BandScale = _BandScale;
var BaseProperties = class {
  set(properties) {
    const { className = this.constructor.name } = this.constructor;
    if (typeof properties !== "object") {
      Logger.warn(`unable to set ${className} - expecting a properties object`);
      return this;
    }
    const keys = new Set(Object.keys(properties));
    for (const propertyKey of listDecoratedProperties(this)) {
      if (keys.has(propertyKey)) {
        const value = properties[propertyKey];
        const self = this;
        if (isProperties(self[propertyKey])) {
          if (self[propertyKey] instanceof PropertiesArray) {
            const array2 = self[propertyKey].reset(value);
            if (array2 != null) {
              self[propertyKey] = array2;
            } else {
              Logger.warn(`unable to set [${propertyKey}] - expecting a properties array`);
            }
          } else {
            self[propertyKey].set(value);
          }
        } else {
          self[propertyKey] = value;
        }
        keys.delete(propertyKey);
      }
    }
    for (const unknownKey of keys) {
      Logger.warn(`unable to set [${unknownKey}] in ${className} - property is unknown`);
    }
    return this;
  }
  isValid(warningPrefix) {
    return listDecoratedProperties(this).every((propertyKey) => {
      const { optional } = extractDecoratedPropertyMetadata(this, propertyKey);
      const valid = optional === true || typeof this[propertyKey] !== "undefined";
      if (!valid) {
        Logger.warnOnce(`${warningPrefix ?? ""}[${propertyKey}] is required.`);
      }
      return valid;
    });
  }
  toJson() {
    return listDecoratedProperties(this).reduce((object2, propertyKey) => {
      const propertyValue = this[propertyKey];
      object2[propertyKey] = isProperties(propertyValue) ? propertyValue.toJson() : propertyValue;
      return object2;
    }, {});
  }
};
var PropertiesArray = class _PropertiesArray extends Array {
  constructor(itemFactory, ...properties) {
    super(properties.length);
    const isConstructor = (value2) => Boolean(value2?.prototype?.constructor?.name);
    const value = isConstructor(itemFactory) ? (params) => new itemFactory().set(params) : itemFactory;
    Object.defineProperty(this, "itemFactory", { value, enumerable: false, configurable: false });
    this.set(properties);
  }
  set(properties) {
    if (isArray(properties)) {
      this.length = properties.length;
      for (let i = 0; i < properties.length; i++) {
        this[i] = this.itemFactory(properties[i]);
      }
    }
    return this;
  }
  reset(properties) {
    if (Array.isArray(properties)) {
      return new _PropertiesArray(this.itemFactory, ...properties);
    }
  }
  toJson() {
    return this.map((value) => value?.toJson?.() ?? value);
  }
};
function isProperties(value) {
  return value instanceof BaseProperties || value instanceof PropertiesArray;
}
function Validate(predicate, options = {}) {
  const { optional = false, property: overrideProperty } = options;
  return addTransformToInstanceProperty(
    (target, property, value) => {
      const context = { ...options, target, property };
      if (optional && typeof value === "undefined" || predicate(value, context)) {
        if (isProperties(target[property]) && !isProperties(value)) {
          target[property].set(value);
          return target[property];
        }
        return value;
      }
      const cleanKey = overrideProperty ?? String(property).replace(/^_*/, "");
      const targetName = target.constructor.className ?? target.constructor.name.replace(/Properties$/, "");
      let valueString = stringify(value);
      const maxLength = 50;
      if (valueString != null && valueString.length > maxLength) {
        const excessCharacters = valueString.length - maxLength;
        valueString = valueString.slice(0, maxLength) + `... (+${excessCharacters} characters)`;
      }
      Logger.warn(
        `Property [${cleanKey}] of [${targetName}] cannot be set to [${valueString}]${predicate.message ? `; expecting ${getPredicateMessage(predicate, context)}` : ""}, ignoring.`
      );
      return BREAK_TRANSFORM_CHAIN;
    },
    void 0,
    { optional }
  );
}
var AND = (...predicates) => {
  const messages = [];
  return predicateWithMessage(
    (value, ctx) => {
      messages.length = 0;
      return predicates.every((predicate) => {
        const isValid2 = predicate(value, ctx);
        if (!isValid2) {
          messages.push(getPredicateMessage(predicate, ctx));
        }
        return isValid2;
      });
    },
    () => messages.filter(Boolean).join(" AND ")
  );
};
var OR = (...predicates) => predicateWithMessage(
  (value, ctx) => predicates.some((predicate) => predicate(value, ctx)),
  (ctx) => predicates.map(getPredicateMessageMapper(ctx)).filter(Boolean).join(" OR ")
);
var OBJECT = attachObjectRestrictions(
  predicateWithMessage(
    (value, ctx) => isProperties(value) || isObject(value) && isProperties(ctx.target[ctx.property]),
    "a properties object"
  )
);
var PLAIN_OBJECT = attachObjectRestrictions(predicateWithMessage((value) => isObject(value), "an object"));
var BOOLEAN = predicateWithMessage(isBoolean, "a boolean");
var FUNCTION = predicateWithMessage(isFunction, "a function");
var STRING = predicateWithMessage(isString, "a string");
var NUMBER = attachNumberRestrictions(predicateWithMessage(isFiniteNumber, "a number"));
var REAL_NUMBER = predicateWithMessage((value) => isNumber(value) && !isNaN(value), "a real number");
var NAN = predicateWithMessage((value) => isNumber(value) && isNaN(value), "NaN");
var POSITIVE_NUMBER = NUMBER.restrict({ min: 0 });
var RATIO = NUMBER.restrict({ min: 0, max: 1 });
var NUMBER_OR_NAN = OR(NUMBER, NAN);
var ARRAY = attachArrayRestrictions(predicateWithMessage(isArray, "an array"));
var ARRAY_OF = (predicate, message) => predicateWithMessage(
  (value, ctx) => isArray(value) && value.every((item) => predicate(item, ctx)),
  (ctx) => {
    const arrayMessage = getPredicateMessage(ARRAY, ctx) ?? "";
    if (typeof message === "function") {
      return `${arrayMessage} of ${message(ctx)}`;
    }
    return message ? `${arrayMessage} of ${message}` : arrayMessage;
  }
);
var isComparable = (value) => isFiniteNumber(value) || isValidDate(value);
var LESS_THAN = (otherField) => predicateWithMessage(
  (v, ctx) => !isComparable(v) || !isComparable(ctx.target[otherField]) || v < ctx.target[otherField],
  `to be less than ${otherField}`
);
var GREATER_THAN = (otherField) => predicateWithMessage(
  (v, ctx) => !isComparable(v) || !isComparable(ctx.target[otherField]) || v > ctx.target[otherField],
  `to be greater than ${otherField}`
);
var DATE = predicateWithMessage(isValidDate, "Date object");
var DATE_OR_DATETIME_MS = OR(DATE, POSITIVE_NUMBER);
var colorMessage = `A color string can be in one of the following formats to be valid: #rgb, #rrggbb, rgb(r, g, b), rgba(r, g, b, a) or a CSS color name such as 'white', 'orange', 'cyan', etc`;
var COLOR_STRING = predicateWithMessage(
  (v) => isString(v) && Color.validColorString(v),
  `color String. ${colorMessage}`
);
var COLOR_STRING_ARRAY = predicateWithMessage(ARRAY_OF(COLOR_STRING), `color strings. ${colorMessage}`);
var BOOLEAN_ARRAY = ARRAY_OF(BOOLEAN, "boolean values");
var NUMBER_ARRAY = ARRAY_OF(NUMBER, "numbers");
var STRING_ARRAY = ARRAY_OF(STRING, "strings");
var DATE_ARRAY = predicateWithMessage(ARRAY_OF(DATE), "Date objects");
var OBJECT_ARRAY = predicateWithMessage(ARRAY_OF(OBJECT), "objects");
var LINE_CAP = UNION(["butt", "round", "square"], "a line cap");
var LINE_JOIN = UNION(["round", "bevel", "miter"], "a line join");
var LINE_STYLE = UNION(["solid", "dashed", "dotted"], "a line style");
var LINE_DASH = predicateWithMessage(
  ARRAY_OF(POSITIVE_NUMBER),
  "numbers specifying the length in pixels of alternating dashes and gaps, for example, [6, 3] means dashes with a length of 6 pixels with gaps between of 3 pixels."
);
var POSITION = UNION(["top", "right", "bottom", "left"], "a position");
var FONT_STYLE = UNION(["normal", "italic", "oblique"], "a font style");
var FONT_WEIGHT = OR(
  UNION(["normal", "bold", "bolder", "lighter"], "a font weight"),
  NUMBER.restrict({ min: 1, max: 1e3 })
);
var TEXT_WRAP = UNION(["never", "always", "hyphenate", "on-space"], "a text wrap strategy");
var TEXT_ALIGN = UNION(["left", "center", "right"], "a text align");
var VERTICAL_ALIGN = UNION(["top", "middle", "bottom"], "a vertical align");
var OVERFLOW_STRATEGY = UNION(["ellipsis", "hide"], "an overflow strategy");
var DIRECTION = UNION(["horizontal", "vertical"], "a direction");
var PLACEMENT = UNION(["inside", "outside"], "a placement");
var INTERACTION_RANGE = OR(UNION(["exact", "nearest"], "interaction range"), NUMBER);
var LABEL_PLACEMENT = UNION(["top", "bottom", "left", "right"]);
function UNION(options, message = "a") {
  return predicateWithMessage(
    (v, ctx) => {
      const option = options.find((o) => {
        const value = typeof o === "string" ? o : o.value;
        return v === value;
      });
      if (option == null)
        return false;
      if (typeof option !== "string" && (option.deprecated === true || option.deprecatedTo != null)) {
        const messages = [`Property [%s] with value '${option.value}' is deprecated.`];
        if (option.deprecatedTo) {
          messages.push(`Use ${option.deprecatedTo} instead.`);
        }
        Logger.warnOnce(messages.join(" "), ctx.property);
      }
      return true;
    },
    `${message} keyword such as ${joinUnionOptions(options)}`
  );
}
var MIN_SPACING = OR(AND(NUMBER.restrict({ min: 1 }), LESS_THAN("maxSpacing")), NAN);
var MAX_SPACING = OR(AND(NUMBER.restrict({ min: 1 }), GREATER_THAN("minSpacing")), NAN);
function predicateWithMessage(predicate, message) {
  predicate.message = message;
  return predicate;
}
function joinUnionOptions(options) {
  const values = options.filter((option) => typeof option === "string" || option.undocumented !== true).map((option) => `'${typeof option === "string" ? option : option.value}'`);
  if (values.length === 1) {
    return values[0];
  }
  const lastValue = values.pop();
  return `${values.join(", ")} or ${lastValue}`;
}
function getPredicateMessage(predicate, ctx) {
  return isFunction(predicate.message) ? predicate.message(ctx) : predicate.message;
}
function getPredicateMessageMapper(ctx) {
  return (predicate) => getPredicateMessage(predicate, ctx);
}
function attachArrayRestrictions(predicate) {
  return Object.assign(predicate, {
    restrict({ length: length2, minLength } = {}) {
      let message = "an array";
      if (isNumber(minLength) && minLength > 0) {
        message = "a non-empty array";
      } else if (isNumber(length2)) {
        message = `an array of length ${length2}`;
      }
      return predicateWithMessage(
        (value) => isArray(value) && (isNumber(length2) ? value.length === length2 : true) && (isNumber(minLength) ? value.length >= minLength : true),
        message
      );
    }
  });
}
function attachNumberRestrictions(predicate) {
  return Object.assign(predicate, {
    restrict({ min, max } = {}) {
      const message = ["a number"];
      const hasMin = isNumber(min);
      const hasMax = isNumber(max);
      if (hasMin && hasMax) {
        message.push(`between ${min} and ${max} inclusive`);
      } else if (hasMin) {
        message.push(`greater than or equal to ${min}`);
      } else if (hasMax) {
        message.push(`less than or equal to ${max}`);
      }
      return predicateWithMessage(
        (value) => isFiniteNumber(value) && (hasMin ? value >= min : true) && (hasMax ? value <= max : true),
        message.join(" ")
      );
    }
  });
}
function attachObjectRestrictions(predicate) {
  return Object.assign(predicate, {
    restrict(objectType) {
      return predicateWithMessage(
        (value) => value instanceof objectType,
        (ctx) => getPredicateMessage(predicate, ctx) ?? `an instance of ${objectType.name}`
      );
    }
  });
}
function stringify(value) {
  if (typeof value === "number") {
    if (isNaN(value))
      return "NaN";
    if (value === Infinity)
      return "Infinity";
    if (value === -Infinity)
      return "-Infinity";
  }
  return JSON.stringify(value);
}
var ChartAxisDirection = /* @__PURE__ */ ((ChartAxisDirection2) => {
  ChartAxisDirection2["X"] = "x";
  ChartAxisDirection2["Y"] = "y";
  return ChartAxisDirection2;
})(ChartAxisDirection || {});
var ModuleMap = class {
  constructor() {
    this.moduleMap = /* @__PURE__ */ new Map();
  }
  *modules() {
    for (const m of this.moduleMap.values()) {
      yield m.moduleInstance;
    }
  }
  addModule(module2, moduleFactory) {
    if (this.moduleMap.has(module2.optionsKey)) {
      throw new Error(`AG Charts - module already initialised: ${module2.optionsKey}`);
    }
    this.moduleMap.set(module2.optionsKey, { module: module2, moduleInstance: moduleFactory(module2) });
  }
  removeModule(module2) {
    const moduleKey = isString(module2) ? module2 : module2.optionsKey;
    this.moduleMap.get(moduleKey)?.moduleInstance.destroy();
    this.moduleMap.delete(moduleKey);
  }
  getModule(module2) {
    return this.moduleMap.get(isString(module2) ? module2 : module2.optionsKey)?.moduleInstance;
  }
  isEnabled(module2) {
    return this.moduleMap.has(isString(module2) ? module2 : module2.optionsKey);
  }
  mapModules(callback2) {
    return Array.from(this.moduleMap.values(), (m, i) => callback2(m.moduleInstance, i));
  }
  destroy() {
    for (const moduleKey of this.moduleMap.keys()) {
      this.moduleMap.get(moduleKey)?.moduleInstance.destroy();
    }
    this.moduleMap.clear();
  }
};
var resetMotion_exports = {};
__export(resetMotion_exports, {
  resetMotion: () => resetMotion
});
function resetMotion(selectionsOrNodes, propsFn) {
  const { nodes, selections } = deconstructSelectionsOrNodes(selectionsOrNodes);
  for (const selection of selections) {
    for (const node of selection.nodes()) {
      const from3 = propsFn(node, node.datum);
      node.setProperties(from3);
    }
    selection.cleanup();
  }
  for (const node of nodes) {
    const from3 = propsFn(node, node.datum);
    node.setProperties(from3);
  }
}
function parseFormat(format) {
  let prefix;
  let suffix;
  const surrounded = surroundedRegEx.exec(format);
  if (surrounded) {
    [, prefix, format, suffix] = surrounded;
  }
  const match = formatRegEx.exec(format);
  if (!match) {
    throw new Error(`The number formatter is invalid: ${format}`);
  }
  const [, fill, align, sign, symbol, zero, width2, comma, precision, trim, type] = match;
  return {
    fill,
    align,
    sign,
    symbol,
    zero,
    width: parseInt(width2),
    comma,
    precision: parseInt(precision),
    trim: Boolean(trim),
    type,
    prefix,
    suffix
  };
}
function numberFormat(format) {
  const options = typeof format === "string" ? parseFormat(format) : format;
  const { fill, align, sign = "-", symbol, zero, width: width2, comma, type, prefix = "", suffix = "", precision } = options;
  let { trim } = options;
  const precisionIsNaN = precision == null || isNaN(precision);
  let formatBody;
  if (!type) {
    formatBody = decimalTypes["g"];
    trim = true;
  } else if (type in decimalTypes && type in integerTypes) {
    formatBody = precisionIsNaN ? integerTypes[type] : decimalTypes[type];
  } else if (type in decimalTypes) {
    formatBody = decimalTypes[type];
  } else if (type in integerTypes) {
    formatBody = integerTypes[type];
  } else {
    throw new Error(`The number formatter type is invalid: ${type}`);
  }
  let formatterPrecision;
  if (precision == null || precisionIsNaN) {
    formatterPrecision = type ? 6 : 12;
  } else {
    formatterPrecision = precision;
  }
  return (n) => {
    let result = formatBody(n, formatterPrecision);
    if (trim) {
      result = removeTrailingZeros(result);
    }
    if (comma) {
      result = insertSeparator(result, comma);
    }
    result = addSign(n, result, sign);
    if (symbol && symbol !== "#") {
      result = `${symbol}${result}`;
    }
    if (symbol === "#" && type === "x") {
      result = `0x${result}`;
    }
    if (type === "s") {
      result = `${result}${getSIPrefix(n)}`;
    }
    if (type === "%" || type === "p") {
      result = `${result}%`;
    }
    if (width2 != null && !isNaN(width2)) {
      result = addPadding(result, width2, fill ?? zero, align);
    }
    result = `${prefix}${result}${suffix}`;
    return result;
  };
}
var formatRegEx = /^(?:(.)?([<>=^]))?([+\-( ])?([$€£¥₣₹#])?(0)?(\d+)?(,)?(?:\.(\d+))?(~)?([%a-z])?$/i;
var surroundedRegEx = /^((?:[^#]|#[^{])*)#{([^}]+)}(.*)$/;
var integerTypes = {
  b: (n) => absFloor(n).toString(2),
  c: (n) => String.fromCharCode(n),
  d: (n) => Math.round(Math.abs(n)).toFixed(0),
  o: (n) => absFloor(n).toString(8),
  x: (n) => absFloor(n).toString(16),
  X: (n) => integerTypes.x(n).toUpperCase(),
  n: (n) => integerTypes.d(n),
  "%": (n) => `${absFloor(n * 100).toFixed(0)}`
};
var decimalTypes = {
  e: (n, f) => Math.abs(n).toExponential(f),
  E: (n, f) => decimalTypes.e(n, f).toUpperCase(),
  f: (n, f) => Math.abs(n).toFixed(f),
  F: (n, f) => decimalTypes.f(n, f).toUpperCase(),
  g: (n, f) => {
    if (n === 0) {
      return "0";
    }
    const a = Math.abs(n);
    const p = Math.floor(Math.log10(a));
    if (p >= -4 && p < f) {
      return a.toFixed(f - 1 - p);
    }
    return a.toExponential(f - 1);
  },
  G: (n, f) => decimalTypes.g(n, f).toUpperCase(),
  n: (n, f) => decimalTypes.g(n, f),
  p: (n, f) => decimalTypes.r(n * 100, f),
  r: (n, f) => {
    if (n === 0) {
      return "0";
    }
    const a = Math.abs(n);
    const p = Math.floor(Math.log10(a));
    const q = p - (f - 1);
    if (q <= 0) {
      return a.toFixed(-q);
    }
    const x = 10 ** q;
    return (Math.round(a / x) * x).toFixed();
  },
  s: (n, f) => {
    const p = getSIPrefixPower(n);
    return decimalTypes.r(n / 10 ** p, f);
  },
  "%": (n, f) => decimalTypes.f(n * 100, f)
};
var minSIPrefix = -24;
var maxSIPrefix = 24;
var siPrefixes = {
  [minSIPrefix]: "y",
  [-21]: "z",
  [-18]: "a",
  [-15]: "f",
  [-12]: "p",
  [-9]: "n",
  [-6]: "\xB5",
  [-3]: "m",
  [0]: "",
  [3]: "k",
  [6]: "M",
  [9]: "G",
  [12]: "T",
  [15]: "P",
  [18]: "E",
  [21]: "Z",
  [maxSIPrefix]: "Y"
};
var minusSign = "\u2212";
function absFloor(n) {
  return Math.floor(Math.abs(n));
}
function removeTrailingZeros(numString) {
  return numString.replace(/\.0+$/, "").replace(/(\.[1-9])0+$/, "$1");
}
function insertSeparator(numString, separator) {
  let dotIndex = numString.indexOf(".");
  if (dotIndex < 0) {
    dotIndex = numString.length;
  }
  const integerChars = numString.substring(0, dotIndex).split("");
  const fractionalPart = numString.substring(dotIndex);
  for (let i = integerChars.length - 3; i > 0; i -= 3) {
    integerChars.splice(i, 0, separator);
  }
  return `${integerChars.join("")}${fractionalPart}`;
}
function getSIPrefix(n) {
  return siPrefixes[getSIPrefixPower(n)];
}
function getSIPrefixPower(n) {
  return clamp(minSIPrefix, n ? Math.floor(Math.log10(Math.abs(n)) / 3) * 3 : 0, maxSIPrefix);
}
function addSign(num, numString, signType = "") {
  if (signType === "(") {
    return num >= 0 ? numString : `(${numString})`;
  }
  const plusSign = signType === "+" ? "+" : "";
  return `${num >= 0 ? plusSign : minusSign}${numString}`;
}
function addPadding(numString, width2, fill = " ", align = ">") {
  let result = numString;
  if (align === ">" || !align) {
    result = result.padStart(width2, fill);
  } else if (align === "<") {
    result = result.padEnd(width2, fill);
  } else if (align === "^") {
    const padWidth = Math.max(0, width2 - result.length);
    const padLeft = Math.ceil(padWidth / 2);
    const padRight = Math.floor(padWidth / 2);
    result = result.padStart(padLeft + result.length, fill);
    result = result.padEnd(padRight + result.length, fill);
  }
  return result;
}
function encode7(date) {
  return date.getTime();
}
function decode7(encoded) {
  return new Date(encoded);
}
var millisecond = new CountableTimeInterval(encode7, decode7);
var tInterval = (timeInterval, baseDuration, step) => ({
  duration: baseDuration * step,
  timeInterval,
  step
});
var TickIntervals = [
  tInterval(second, durationSecond, 1),
  tInterval(second, durationSecond, 5),
  tInterval(second, durationSecond, 15),
  tInterval(second, durationSecond, 30),
  tInterval(minute, durationMinute, 1),
  tInterval(minute, durationMinute, 5),
  tInterval(minute, durationMinute, 15),
  tInterval(minute, durationMinute, 30),
  tInterval(hour, durationHour, 1),
  tInterval(hour, durationHour, 3),
  tInterval(hour, durationHour, 6),
  tInterval(hour, durationHour, 12),
  tInterval(day, durationDay, 1),
  tInterval(day, durationDay, 2),
  tInterval(sunday, durationWeek, 1),
  tInterval(sunday, durationWeek, 2),
  tInterval(sunday, durationWeek, 3),
  tInterval(month, durationMonth, 1),
  tInterval(month, durationMonth, 2),
  tInterval(month, durationMonth, 3),
  tInterval(month, durationMonth, 4),
  tInterval(month, durationMonth, 6),
  tInterval(year, durationYear, 1)
];
var TickMultipliers = [1, 2, 5, 10];
function isCloseToInteger(n, delta4) {
  return Math.abs(Math.round(n) - n) < delta4;
}
function createTicks(start2, stop, count, minCount, maxCount) {
  if (count < 2) {
    return [start2, stop];
  }
  const step = tickStep(start2, stop, count, minCount, maxCount);
  if (!Number.isFinite(step)) {
    return [];
  }
  if (!isCloseToInteger(start2 / step, 1e-12)) {
    start2 = Math.ceil(start2 / step) * step;
  }
  if (!isCloseToInteger(stop / step, 1e-12)) {
    stop = Math.floor(stop / step) * step;
  }
  return range(start2, stop, step);
}
function getTickInterval(start2, stop, count, minCount, maxCount, targetInterval) {
  const target = targetInterval ?? Math.abs(stop - start2) / Math.max(count, 1);
  let i = 0;
  for (const tickInterval of TickIntervals) {
    if (target <= tickInterval.duration)
      break;
    i++;
  }
  if (i === 0) {
    const step2 = Math.max(tickStep(start2, stop, count, minCount, maxCount), 1);
    return millisecond.every(step2);
  } else if (i === TickIntervals.length) {
    const step2 = targetInterval == null ? tickStep(start2 / durationYear, stop / durationYear, count, minCount, maxCount) : 1;
    return year.every(step2);
  }
  const i0 = TickIntervals[i - 1];
  const i1 = TickIntervals[i];
  const { timeInterval, step } = target - i0.duration < i1.duration - target ? i0 : i1;
  return timeInterval.every(step);
}
function tickStep(start2, end2, count, minCount = 0, maxCount = Infinity) {
  if (start2 === end2) {
    return clamp(1, minCount, maxCount);
  } else if (count < 1) {
    return NaN;
  }
  const extent2 = Math.abs(end2 - start2);
  const step = 10 ** Math.floor(Math.log10(extent2 / count));
  let m = NaN, minDiff = Infinity, isInBounds = false;
  for (const multiplier of TickMultipliers) {
    const c = Math.ceil(extent2 / (multiplier * step));
    const validBounds = c >= minCount && c <= maxCount;
    if (isInBounds && !validBounds)
      continue;
    const diffCount = Math.abs(c - count);
    if (minDiff > diffCount || isInBounds !== validBounds) {
      isInBounds || (isInBounds = validBounds);
      minDiff = diffCount;
      m = multiplier;
    }
  }
  return m * step;
}
function decimalPlaces(decimal) {
  for (let i = decimal.length - 1; i >= 0; i -= 1) {
    if (decimal[i] !== "0") {
      return i + 1;
    }
  }
  return 0;
}
function tickFormat(ticks, format) {
  const options = parseFormat(format ?? ",f");
  if (options.precision == null || isNaN(options.precision)) {
    if (!options.type || "eEFgGnprs".includes(options.type)) {
      options.precision = Math.max(
        ...ticks.map((x) => {
          if (!Number.isFinite(x))
            return 0;
          const [integer, decimal] = x.toExponential((options.type ? 6 : 12) - 1).split(/[.e]/g);
          return (integer !== "1" && integer !== "-1" ? 1 : 0) + decimalPlaces(decimal) + 1;
        })
      );
    } else if ("f%".includes(options.type)) {
      options.precision = Math.max(
        ...ticks.map((x) => {
          if (!Number.isFinite(x) || x === 0)
            return 0;
          const l = Math.floor(Math.log10(Math.abs(x)));
          const digits = options.type ? 6 : 12;
          const decimal = x.toExponential(digits - 1).split(/[.e]/g)[1];
          const decimalLength = decimalPlaces(decimal);
          return Math.max(0, decimalLength - l);
        })
      );
    }
  }
  const formatter = numberFormat(options);
  return (n) => formatter(Number(n));
}
function range(start2, end2, step) {
  if (!Number.isFinite(step) || step <= 0) {
    return [];
  }
  const f = 10 ** countFractionDigits(step);
  const d0 = Math.min(start2, end2);
  const d1 = Math.max(start2, end2);
  const out = [];
  for (let i = 0; ; i += 1) {
    const p = Math.round((d0 + step * i) * f) / f;
    if (p > d1)
      break;
    out.push(p);
  }
  return out;
}
function isDenseInterval(count, availableRange) {
  if (count >= availableRange) {
    Logger.warnOnce(
      `the configured interval results in more than 1 item per pixel, ignoring. Supply a larger interval or omit this configuration`
    );
    return true;
  }
  return false;
}
function niceTicksDomain(start2, end2) {
  const extent2 = Math.abs(end2 - start2);
  const step = 10 ** Math.floor(Math.log10(extent2));
  let minError = Infinity, ticks = [start2, end2];
  for (const multiplier of TickMultipliers) {
    const m = multiplier * step;
    const d0 = Math.floor(start2 / m) * m;
    const d1 = Math.ceil(end2 / m) * m;
    const error = 1 - extent2 / Math.abs(d1 - d0);
    if (minError > error) {
      minError = error;
      ticks = [d0, d1];
    }
  }
  return ticks;
}
function estimateTickCount(rangeExtent, minSpacing, maxSpacing, defaultTickCount, defaultMinSpacing) {
  defaultMinSpacing = Math.max(defaultMinSpacing, rangeExtent / (defaultTickCount + 1));
  if (isNaN(minSpacing)) {
    minSpacing = defaultMinSpacing;
  }
  if (isNaN(maxSpacing)) {
    maxSpacing = rangeExtent;
  }
  if (minSpacing > maxSpacing) {
    if (minSpacing === defaultMinSpacing) {
      minSpacing = maxSpacing;
    } else {
      maxSpacing = minSpacing;
    }
  }
  const maxTickCount = Math.max(1, Math.floor(rangeExtent / minSpacing));
  const minTickCount = Math.min(maxTickCount, Math.ceil(rangeExtent / maxSpacing));
  const tickCount = clamp(minTickCount, defaultTickCount, maxTickCount);
  return { minTickCount, maxTickCount, tickCount };
}
var _LogScale = class _LogScale2 extends ContinuousScale {
  constructor() {
    super([1, 10], [0, 1]);
    this.type = "log";
    this.base = 10;
    this.baseLog = identity;
    this.basePow = identity;
    this.log = (x) => {
      const start2 = Math.min(...this.domain);
      return start2 >= 0 ? this.baseLog(x) : -this.baseLog(-x);
    };
    this.pow = (x) => {
      const start2 = Math.min(...this.domain);
      return start2 >= 0 ? this.basePow(x) : -this.basePow(-x);
    };
    this.defaultClamp = true;
  }
  toDomain(d) {
    return d;
  }
  transform(x) {
    const start2 = Math.min(...this.domain);
    return start2 >= 0 ? Math.log(x) : -Math.log(-x);
  }
  transformInvert(x) {
    const start2 = Math.min(...this.domain);
    return start2 >= 0 ? Math.exp(x) : -Math.exp(-x);
  }
  refresh() {
    if (this.base <= 0) {
      this.base = 0;
      Logger.warnOnce("expecting a finite Number greater than to 0");
    }
    super.refresh();
  }
  update() {
    if (!this.domain || this.domain.length < 2) {
      return;
    }
    this.baseLog = _LogScale2.getBaseLogMethod(this.base);
    this.basePow = _LogScale2.getBasePowerMethod(this.base);
    if (this.nice) {
      this.updateNiceDomain();
    }
  }
  updateNiceDomain() {
    const [d0, d1] = this.domain;
    const roundStart = d0 > d1 ? Math.ceil : Math.floor;
    const roundStop = d0 > d1 ? Math.floor : Math.ceil;
    const n0 = this.pow(roundStart(this.log(d0)));
    const n1 = this.pow(roundStop(this.log(d1)));
    this.niceDomain = [n0, n1];
  }
  ticks() {
    const count = this.tickCount ?? 10;
    if (!this.domain || this.domain.length < 2 || count < 1) {
      return [];
    }
    this.refresh();
    const base = this.base;
    const [d0, d1] = this.getDomain();
    const start2 = Math.min(d0, d1);
    const stop = Math.max(d0, d1);
    let p0 = this.log(start2);
    let p1 = this.log(stop);
    if (this.interval) {
      const inBounds = (tick) => tick >= start2 && tick <= stop;
      const step = Math.min(Math.abs(this.interval), Math.abs(p1 - p0));
      const ticks2 = range(p0, p1, step).map(this.pow).filter(inBounds);
      if (!isDenseInterval(ticks2.length, this.getPixelRange())) {
        return ticks2;
      }
    }
    if (!isInteger(base) || p1 - p0 >= count) {
      return createTicks(p0, p1, Math.min(p1 - p0, count)).map(this.pow);
    }
    const ticks = [];
    const isPositive = start2 > 0;
    p0 = Math.floor(p0) - 1;
    p1 = Math.round(p1) + 1;
    const availableSpacing = findRangeExtent(this.range) / count;
    let lastTickPosition = Infinity;
    for (let p = p0; p <= p1; p++) {
      const nextMagnitudeTickPosition = this.convert(this.pow(p + 1));
      for (let k = 1; k < base; k++) {
        const q = isPositive ? k : base - k + 1;
        const t = this.pow(p) * q;
        const tickPosition = this.convert(t);
        const prevSpacing = Math.abs(lastTickPosition - tickPosition);
        const nextSpacing = Math.abs(tickPosition - nextMagnitudeTickPosition);
        const fits = prevSpacing >= availableSpacing && nextSpacing >= availableSpacing;
        if (t >= start2 && t <= stop && (k === 1 || fits || ticks.length === 0)) {
          ticks.push(t);
          lastTickPosition = tickPosition;
        }
      }
    }
    return ticks;
  }
  tickFormat({ specifier }) {
    specifier ?? (specifier = this.base === 10 ? ".0e" : ",");
    return isString(specifier) ? numberFormat(specifier) : specifier;
  }
  static getBaseLogMethod(base) {
    switch (base) {
      case 10:
        return Math.log10;
      case Math.E:
        return Math.log;
      case 2:
        return Math.log2;
      default:
        return (x) => Math.log(x) / Math.log(base);
    }
  }
  static getBasePowerMethod(base) {
    switch (base) {
      case 10:
        return (x) => x >= 0 ? 10 ** x : 1 / 10 ** -x;
      case Math.E:
        return Math.exp;
      default:
        return (x) => base ** x;
    }
  }
};
__decorateClass([
  Invalidating
], _LogScale.prototype, "base", 2);
var LogScale = _LogScale;
function findMaxIndex(min, max, iteratee) {
  if (min > max)
    return;
  let found;
  while (max >= min) {
    const index = Math.floor((max + min) / 2);
    const value = iteratee(index);
    if (value) {
      found = index;
      min = index + 1;
    } else {
      max = index - 1;
    }
  }
  return found;
}
function findMinIndex(min, max, iteratee) {
  if (min > max)
    return;
  let found;
  while (max >= min) {
    const index = Math.floor((max + min) / 2);
    const value = iteratee(index);
    if (value) {
      found = index;
      max = index - 1;
    } else {
      min = index + 1;
    }
  }
  return found;
}
function findMaxValue(min, max, iteratee) {
  if (min > max)
    return;
  let found;
  while (max >= min) {
    const index = Math.floor((max + min) / 2);
    const value = iteratee(index);
    if (value == null) {
      max = index - 1;
    } else {
      found = value;
      min = index + 1;
    }
  }
  return found;
}
function findMinValue(min, max, iteratee) {
  if (min > max)
    return;
  let found;
  while (max >= min) {
    const index = Math.floor((max + min) / 2);
    const value = iteratee(index);
    if (value == null) {
      min = index + 1;
    } else {
      found = value;
      max = index - 1;
    }
  }
  return found;
}
function compareDates(a, b) {
  return a.valueOf() - b.valueOf();
}
function deduplicateSortedArray(values) {
  let v0 = NaN;
  const out = [];
  for (const v of values) {
    const v1 = v.valueOf();
    if (v0 !== v1)
      out.push(v);
    v0 = v1;
  }
  return out;
}
function sortAndUniqueDates(values) {
  const sortedValues = values.slice().sort(compareDates);
  return datesSortOrder(values) == null ? deduplicateSortedArray(sortedValues) : sortedValues;
}
function datesSortOrder(d) {
  if (d.length === 0)
    return 1;
  const sign = Number(d[d.length - 1]) > Number(d[0]) ? 1 : -1;
  let v0 = -Infinity * sign;
  for (const v of d) {
    const v1 = v.valueOf();
    if (Math.sign(v1 - v0) !== sign)
      return;
    v0 = v1;
  }
  return sign;
}
var TimeScale = class _TimeScale extends ContinuousScale {
  constructor() {
    super([], [0, 1]);
    this.type = "time";
  }
  toDomain(d) {
    return new Date(d);
  }
  convert(value, clamp2) {
    if (!(value instanceof Date))
      value = new Date(value);
    return super.convert(value, clamp2);
  }
  invert(value) {
    return new Date(super.invert(value));
  }
  /**
   * Returns uniformly-spaced dates that represent the scale's domain.
   */
  ticks() {
    if (!this.domain || this.domain.length < 2) {
      return [];
    }
    this.refresh();
    const { interval, nice, tickCount, minTickCount, maxTickCount } = this;
    const [start2, stop] = findMinMax(this.getDomain().map(dateToNumber));
    if (interval != null) {
      return _TimeScale.getTicksForInterval({ start: start2, stop, interval, availableRange: this.getPixelRange() }) ?? _TimeScale.getDefaultTicks({ start: start2, stop, tickCount, minTickCount, maxTickCount });
    } else if (nice && tickCount === 2) {
      return this.niceDomain;
    } else if (nice && tickCount === 1) {
      return this.niceDomain.slice(0, 1);
    }
    return _TimeScale.getDefaultTicks({ start: start2, stop, tickCount, minTickCount, maxTickCount });
  }
  static getDefaultTicks({
    start: start2,
    stop,
    tickCount,
    minTickCount,
    maxTickCount
  }) {
    const t = getTickInterval(start2, stop, tickCount, minTickCount, maxTickCount);
    return t ? t.range(new Date(start2), new Date(stop)) : [];
  }
  static getTicksForInterval({
    start: start2,
    stop,
    interval,
    availableRange
  }) {
    if (!interval) {
      return [];
    }
    if (interval instanceof TimeInterval) {
      const ticks2 = interval.range(new Date(start2), new Date(stop));
      if (isDenseInterval(ticks2.length, availableRange)) {
        return;
      }
      return ticks2;
    }
    const absInterval = Math.abs(interval);
    if (isDenseInterval((stop - start2) / absInterval, availableRange))
      return;
    const timeInterval = TickIntervals.findLast((tickInterval) => absInterval % tickInterval.duration === 0);
    if (timeInterval) {
      const i = timeInterval.timeInterval.every(absInterval / (timeInterval.duration / timeInterval.step));
      return i.range(new Date(start2), new Date(stop));
    }
    let date = new Date(start2);
    const stopDate = new Date(stop);
    const ticks = [];
    while (date <= stopDate) {
      ticks.push(date);
      date = new Date(date);
      date.setMilliseconds(date.getMilliseconds() + absInterval);
    }
    return ticks;
  }
  /**
   * Returns a time format function suitable for displaying tick values.
   *
   * @param ticks Optional array of tick values for custom formatting.
   * @param domain Optional array representing the [min, max] values of the time axis.
   * @param specifier Optional format specifier string for custom date formatting (e.g., `%Y`, `%m`, `%d`).
   * @param formatOffset Optional number for applying an offset to the format (e.g., timezone shifts).
   * @returns A function that formats a `Date` object into a string based on the provided specifier or default format.
   */
  tickFormat({
    ticks,
    domain,
    specifier,
    formatOffset
  }) {
    return specifier == null ? defaultTimeTickFormat(ticks, domain, formatOffset) : buildFormatter(specifier);
  }
  update() {
    if (!this.domain || this.domain.length < 2) {
      return;
    }
    if (this.nice) {
      this.updateNiceDomain();
    }
  }
  /**
   * Extends the domain so that it starts and ends on nice round values.
   * This method typically modifies the scale’s domain, and may only extend the bounds to the nearest round value.
   */
  updateNiceDomain() {
    const maxAttempts = 4;
    let [d0, d1] = this.domain;
    for (let i = 0; i < maxAttempts; i++) {
      this.updateNiceDomainIteration(d0, d1);
      const [n0, n1] = this.niceDomain;
      if (dateToNumber(d0) === dateToNumber(n0) && dateToNumber(d1) === dateToNumber(n1)) {
        break;
      }
      d0 = n0;
      d1 = n1;
    }
  }
  updateNiceDomainIteration(d0, d1) {
    const start2 = Math.min(dateToNumber(d0), dateToNumber(d1));
    const stop = Math.max(dateToNumber(d0), dateToNumber(d1));
    const isReversed = d0 > d1;
    const { interval } = this;
    let i;
    if (interval instanceof TimeInterval) {
      i = interval;
    } else {
      const tickCount = typeof interval === "number" ? (stop - start2) / Math.max(interval, 1) : this.tickCount;
      i = getTickInterval(start2, stop, tickCount, this.minTickCount, this.maxTickCount);
    }
    if (i) {
      const intervalRange = i.range(new Date(start2), new Date(stop), true);
      const domain = isReversed ? [...intervalRange].reverse() : intervalRange;
      const n0 = domain[0];
      const n1 = domain.at(-1);
      this.niceDomain = [n0, n1];
    }
  }
};
var _OrdinalTimeScale = class _OrdinalTimeScale2 extends BandScale {
  constructor() {
    super(...arguments);
    this.type = "ordinal-time";
    this.tickCount = ContinuousScale.defaultTickCount;
    this.minTickCount = 0;
    this.maxTickCount = Infinity;
    this.interval = void 0;
    this._domain = [];
    this.sortedTimestamps = [];
    this.visibleRange = [0, 1];
    this.isReversed = false;
    this._values = void 0;
  }
  static is(value) {
    return value instanceof _OrdinalTimeScale2;
  }
  setVisibleRange(visibleRange) {
    this.visibleRange = visibleRange;
  }
  set domain(values) {
    if (values === this._values)
      return;
    this.invalid = true;
    const sortOrder = datesSortOrder(values);
    const domain = sortOrder == null ? sortAndUniqueDates(values) : values;
    const isReversed = sortOrder === -1;
    const sortedTimestamps = domain.map(dateToNumber);
    if (isReversed)
      sortedTimestamps.reverse();
    this._values = values;
    this._domain = domain;
    this.isReversed = isReversed;
    this.sortedTimestamps = sortedTimestamps;
    this.precomputedSteps = void 0;
    const computedStepCount = values.length < 1e4 ? sortedTimestamps.length : Math.ceil(sortedTimestamps.length / 16);
    if (computedStepCount <= 1)
      return;
    this.refresh();
    const computedSteps = new Int32Array(computedStepCount);
    const d0 = sortedTimestamps[0].valueOf();
    const d1 = sortedTimestamps[sortedTimestamps.length - 1].valueOf();
    const dRange = d1 - d0;
    for (let i = 0; i < computedSteps.length; i += 1) {
      computedSteps[i] = this.findInterval(d0 + i / computedStepCount * dRange);
    }
    this.precomputedSteps = computedSteps;
  }
  get domain() {
    return this._domain;
  }
  ticks() {
    if (!this._domain.length) {
      return [];
    }
    this.refresh();
    const { domain, isReversed, interval } = this;
    const [t0, t1] = [domain[0].valueOf(), domain.at(-1).valueOf()];
    const start2 = Math.min(t0, t1);
    const stop = Math.max(t0, t1);
    if (interval == null) {
      return this.getDefaultTicks(this.maxTickCount, isReversed);
    }
    const [r0, r1] = this.range;
    const availableRange = Math.abs(r1 - r0);
    const ticks = TimeScale.getTicksForInterval({ start: start2, stop, interval, availableRange }) ?? [];
    let lastIndex = -1;
    return ticks.filter((tick) => {
      const index = this.findInterval(tick.valueOf());
      const duplicated = index === lastIndex;
      lastIndex = index;
      return !duplicated;
    });
  }
  getDefaultTicks(maxTickCount, isReversed) {
    const { domain, visibleRange } = this;
    const ticks = [];
    const tickEvery = Math.ceil(domain.length * (visibleRange[1] - visibleRange[0]) / maxTickCount);
    const tickOffset = Math.floor(tickEvery / 2);
    for (let index = 0; index < domain.length; index += 1) {
      const value = domain[index];
      const tickIndex = isReversed ? domain.length - 1 - index : index;
      if (tickEvery <= 0 || (tickIndex + tickOffset) % tickEvery === 0) {
        ticks.push(value);
      }
    }
    if (isReversed) {
      ticks.reverse();
    }
    return ticks;
  }
  convert(d) {
    this.refresh();
    const n = Number(d);
    if (n < this.sortedTimestamps[0]) {
      return NaN;
    }
    let i = this.findInterval(n);
    if (this.isReversed) {
      i = this.domain.length - i - 1;
    }
    return this.ordinalRange(i);
  }
  findInterval(target) {
    const { sortedTimestamps, precomputedSteps } = this;
    let low;
    let high;
    if (precomputedSteps == null) {
      low = 0;
      high = sortedTimestamps.length - 1;
    } else {
      const d0 = sortedTimestamps[0].valueOf();
      const d1 = sortedTimestamps[sortedTimestamps.length - 1].valueOf();
      const i = Math.min(
        (target - d0) / (d1 - d0) * precomputedSteps.length | 0,
        precomputedSteps.length - 1 | 0
      );
      low = precomputedSteps[i];
      high = i < precomputedSteps.length - 2 ? precomputedSteps[i + 1] : sortedTimestamps.length - 1;
    }
    while (low <= high) {
      const mid = (low + high) / 2 | 0;
      if (sortedTimestamps[mid] === target) {
        return mid;
      } else if (sortedTimestamps[mid] < target) {
        low = mid + 1;
      } else {
        high = mid - 1;
      }
    }
    return low;
  }
  /**
   * Returns a time format function suitable for displaying tick values.
   * @param specifier If the specifier string is provided, this method is equivalent to
   * the {@link TimeLocaleObject.format} method.
   * If no specifier is provided, this method returns the default time format function.
   */
  tickFormat({
    ticks,
    domain,
    specifier
  }) {
    return specifier == null ? defaultTimeTickFormat(ticks, domain) : buildFormatter(specifier);
  }
  invert(position) {
    this.refresh();
    const { domain } = this;
    const closest = findMinValue(0, domain.length - 1, (i) => {
      const p = this.ordinalRange(i);
      return p >= position ? domain[i] : void 0;
    });
    return closest ?? domain[0];
  }
  invertNearest(position) {
    return super.invertNearest(position);
  }
};
__decorateClass([
  Invalidating
], _OrdinalTimeScale.prototype, "tickCount", 2);
__decorateClass([
  Invalidating
], _OrdinalTimeScale.prototype, "minTickCount", 2);
__decorateClass([
  Invalidating
], _OrdinalTimeScale.prototype, "maxTickCount", 2);
__decorateClass([
  Invalidating
], _OrdinalTimeScale.prototype, "interval", 2);
var OrdinalTimeScale = _OrdinalTimeScale;
function ascendingStringNumberUndefined(a, b) {
  if (typeof a === "number" && typeof b === "number") {
    return a - b;
  } else if (typeof a === "string" && typeof b === "string") {
    return a.localeCompare(b);
  } else if (a == null && b == null) {
    return 0;
  } else if (a == null) {
    return -1;
  } else if (b == null) {
    return 1;
  }
  return String(a).localeCompare(String(b));
}
var IDENTITY_MATRIX_ELEMENTS = [1, 0, 0, 1, 0, 0];
function closeValue(val, ref, errorMargin = 1e-8) {
  return val === ref || Math.abs(ref - val) < errorMargin;
}
var _Matrix = class _Matrix2 {
  get e() {
    return [...this.elements];
  }
  constructor(elements = [...IDENTITY_MATRIX_ELEMENTS]) {
    this.elements = elements;
  }
  setElements(elements) {
    const e = this.elements;
    e[0] = elements[0];
    e[1] = elements[1];
    e[2] = elements[2];
    e[3] = elements[3];
    e[4] = elements[4];
    e[5] = elements[5];
    return this;
  }
  get identity() {
    const e = this.elements;
    return closeValue(e[0], 1) && closeValue(e[1], 0) && closeValue(e[2], 0) && closeValue(e[3], 1) && closeValue(e[4], 0) && closeValue(e[5], 0);
  }
  /**
   * Performs the AxB matrix multiplication and saves the result
   * to `C`, if given, or to `A` otherwise.
   */
  AxB(A, B, C2) {
    const a = A[0] * B[0] + A[2] * B[1], b = A[1] * B[0] + A[3] * B[1], c = A[0] * B[2] + A[2] * B[3], d = A[1] * B[2] + A[3] * B[3], e = A[0] * B[4] + A[2] * B[5] + A[4], f = A[1] * B[4] + A[3] * B[5] + A[5];
    C2 = C2 ?? A;
    C2[0] = a;
    C2[1] = b;
    C2[2] = c;
    C2[3] = d;
    C2[4] = e;
    C2[5] = f;
  }
  /**
   * The `other` matrix gets post-multiplied to the current matrix.
   * Returns the current matrix.
   * @param other
   */
  multiplySelf(other) {
    this.AxB(this.elements, other.elements);
    return this;
  }
  /**
   * The `other` matrix gets post-multiplied to the current matrix.
   * Returns a new matrix.
   * @param other
   */
  multiply(other) {
    const elements = new Array(6);
    if (other instanceof _Matrix2) {
      this.AxB(this.elements, other.elements, elements);
    } else {
      this.AxB(this.elements, [other.a, other.b, other.c, other.d, other.e, other.f], elements);
    }
    return new _Matrix2(elements);
  }
  preMultiplySelf(other) {
    this.AxB(other.elements, this.elements, this.elements);
    return this;
  }
  /**
   * Returns the inverse of this matrix as a new matrix.
   */
  inverse() {
    const el = this.elements;
    let a = el[0], b = el[1], c = el[2], d = el[3];
    const e = el[4], f = el[5];
    const rD = 1 / (a * d - b * c);
    a *= rD;
    b *= rD;
    c *= rD;
    d *= rD;
    return new _Matrix2([d, -b, -c, a, c * f - d * e, b * e - a * f]);
  }
  /**
   * Save the inverse of this matrix to the given matrix.
   */
  inverseTo(other) {
    const el = this.elements;
    let a = el[0], b = el[1], c = el[2], d = el[3];
    const e = el[4], f = el[5];
    const rD = 1 / (a * d - b * c);
    a *= rD;
    b *= rD;
    c *= rD;
    d *= rD;
    other.setElements([d, -b, -c, a, c * f - d * e, b * e - a * f]);
    return this;
  }
  invertSelf() {
    const el = this.elements;
    let a = el[0], b = el[1], c = el[2], d = el[3];
    const e = el[4], f = el[5];
    const rD = 1 / (a * d - b * c);
    a *= rD;
    b *= rD;
    c *= rD;
    d *= rD;
    el[0] = d;
    el[1] = -b;
    el[2] = -c;
    el[3] = a;
    el[4] = c * f - d * e;
    el[5] = b * e - a * f;
    return this;
  }
  transformPoint(x, y) {
    const e = this.elements;
    return {
      x: x * e[0] + y * e[2] + e[4],
      y: x * e[1] + y * e[3] + e[5]
    };
  }
  transformBBox(bbox, target) {
    const el = this.elements;
    const xx = el[0];
    const xy = el[1];
    const yx = el[2];
    const yy = el[3];
    const h_w = bbox.width * 0.5;
    const h_h = bbox.height * 0.5;
    const cx = bbox.x + h_w;
    const cy = bbox.y + h_h;
    const w = Math.abs(h_w * xx) + Math.abs(h_h * yx);
    const h = Math.abs(h_w * xy) + Math.abs(h_h * yy);
    target ?? (target = new BBox(0, 0, 0, 0));
    target.x = cx * xx + cy * yx + el[4] - w;
    target.y = cx * xy + cy * yy + el[5] - h;
    target.width = w + w;
    target.height = h + h;
    return target;
  }
  toContext(ctx) {
    if (this.identity) {
      return;
    }
    const e = this.elements;
    ctx.transform(e[0], e[1], e[2], e[3], e[4], e[5]);
  }
  static flyweight(sourceMatrix) {
    return _Matrix2.instance.setElements(sourceMatrix.elements);
  }
  static updateTransformMatrix(matrix, scalingX, scalingY, rotation, translationX, translationY, opts) {
    const sx = scalingX;
    const sy = scalingY;
    let scx;
    let scy;
    if (sx === 1 && sy === 1) {
      scx = 0;
      scy = 0;
    } else {
      scx = opts?.scalingCenterX ?? 0;
      scy = opts?.scalingCenterY ?? 0;
    }
    const r = rotation;
    const cos = Math.cos(r);
    const sin = Math.sin(r);
    let rcx;
    let rcy;
    if (r === 0) {
      rcx = 0;
      rcy = 0;
    } else {
      rcx = opts?.rotationCenterX ?? 0;
      rcy = opts?.rotationCenterY ?? 0;
    }
    const tx = translationX;
    const ty = translationY;
    const tx4 = scx * (1 - sx) - rcx;
    const ty4 = scy * (1 - sy) - rcy;
    matrix.setElements([
      cos * sx,
      sin * sx,
      -sin * sy,
      cos * sy,
      cos * tx4 - sin * ty4 + rcx + tx,
      sin * tx4 + cos * ty4 + rcy + ty
    ]);
    return matrix;
  }
  static fromContext(ctx) {
    const domMatrix = ctx.getTransform();
    return new _Matrix2([domMatrix.a, domMatrix.b, domMatrix.c, domMatrix.d, domMatrix.e, domMatrix.f]);
  }
};
_Matrix.instance = new _Matrix();
var Matrix = _Matrix;
function isMatrixTransform(node) {
  return isMatrixTransformType(node.constructor);
}
var MATRIX_TRANSFORM_TYPE = Symbol("isMatrixTransform");
function isMatrixTransformType(cstr) {
  return cstr[MATRIX_TRANSFORM_TYPE] === true;
}
function MatrixTransform(Parent) {
  var _a, _b;
  const ParentNode = Parent;
  if (isMatrixTransformType(Parent)) {
    return Parent;
  }
  const TRANSFORM_MATRIX = Symbol("matrix_combined_transform");
  class MatrixTransformInternal extends ParentNode {
    constructor() {
      super(...arguments);
      this[_b] = new Matrix();
      this._dirtyTransform = true;
    }
    markDirtyTransform() {
      this._dirtyTransform = true;
      super.markDirty();
    }
    updateMatrix(_matrix) {
    }
    computeTransformMatrix() {
      if (!this._dirtyTransform)
        return;
      this[TRANSFORM_MATRIX].setElements(IDENTITY_MATRIX_ELEMENTS);
      this.updateMatrix(this[TRANSFORM_MATRIX]);
      this._dirtyTransform = false;
    }
    toParent(bbox) {
      this.computeTransformMatrix();
      if (this[TRANSFORM_MATRIX].identity)
        return bbox.clone();
      return this[TRANSFORM_MATRIX].transformBBox(bbox);
    }
    toParentPoint(x, y) {
      this.computeTransformMatrix();
      if (this[TRANSFORM_MATRIX].identity)
        return { x, y };
      return this[TRANSFORM_MATRIX].transformPoint(x, y);
    }
    fromParent(bbox) {
      this.computeTransformMatrix();
      if (this[TRANSFORM_MATRIX].identity)
        return bbox.clone();
      return this[TRANSFORM_MATRIX].inverse().transformBBox(bbox);
    }
    fromParentPoint(x, y) {
      this.computeTransformMatrix();
      if (this[TRANSFORM_MATRIX].identity)
        return { x, y };
      return this[TRANSFORM_MATRIX].inverse().transformPoint(x, y);
    }
    computeBBox() {
      const bbox = super.computeBBox();
      if (!bbox)
        return bbox;
      return this.toParent(bbox);
    }
    computeBBoxWithoutTransforms() {
      return super.computeBBox();
    }
    pickNode(x, y, localCoords = false) {
      if (!localCoords) {
        ({ x, y } = this.fromParentPoint(x, y));
      }
      return super.pickNode(x, y);
    }
    render(renderCtx) {
      this.computeTransformMatrix();
      const { ctx } = renderCtx;
      const matrix = this[TRANSFORM_MATRIX];
      let performRestore = false;
      if (!matrix.identity) {
        ctx.save();
        performRestore = true;
        matrix.toContext(ctx);
      }
      super.render(renderCtx);
      if (performRestore) {
        ctx.restore();
      }
    }
    toSVG() {
      this.computeTransformMatrix();
      const svg = super.toSVG();
      const matrix = this[TRANSFORM_MATRIX];
      if (matrix.identity || svg == null)
        return svg;
      const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
      g.append(...svg.elements);
      const [a, b, c, d, e, f] = matrix.e;
      g.setAttribute("transform", `matrix(${a} ${b} ${c} ${d} ${e} ${f})`);
      return {
        elements: [g],
        defs: svg.defs
      };
    }
  }
  _a = MATRIX_TRANSFORM_TYPE, _b = TRANSFORM_MATRIX;
  MatrixTransformInternal[_a] = true;
  return MatrixTransformInternal;
}
function Rotatable(Parent) {
  var _a;
  const ParentNode = Parent;
  const ROTATABLE_MATRIX = Symbol("matrix_rotation");
  class RotatableInternal extends MatrixTransform(ParentNode) {
    constructor() {
      super(...arguments);
      this[_a] = new Matrix();
      this.rotationCenterX = null;
      this.rotationCenterY = null;
      this.rotation = 0;
    }
    updateMatrix(matrix) {
      super.updateMatrix(matrix);
      const { rotation, rotationCenterX, rotationCenterY } = this;
      if (rotation === 0)
        return;
      Matrix.updateTransformMatrix(this[ROTATABLE_MATRIX], 1, 1, rotation, 0, 0, {
        rotationCenterX,
        rotationCenterY
      });
      matrix.multiplySelf(this[ROTATABLE_MATRIX]);
    }
  }
  _a = ROTATABLE_MATRIX;
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], RotatableInternal.prototype, "rotationCenterX", 2);
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], RotatableInternal.prototype, "rotationCenterY", 2);
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], RotatableInternal.prototype, "rotation", 2);
  return RotatableInternal;
}
function Scalable(Parent) {
  var _a;
  const ParentNode = Parent;
  const SCALABLE_MATRIX = Symbol("matrix_scale");
  class ScalableInternal extends MatrixTransform(ParentNode) {
    constructor() {
      super(...arguments);
      this[_a] = new Matrix();
      this.scalingX = 1;
      this.scalingY = 1;
      this.scalingCenterX = null;
      this.scalingCenterY = null;
    }
    updateMatrix(matrix) {
      super.updateMatrix(matrix);
      const { scalingX, scalingY, scalingCenterX, scalingCenterY } = this;
      if (scalingX === 1 && scalingY === 1)
        return;
      Matrix.updateTransformMatrix(this[SCALABLE_MATRIX], scalingX, scalingY, 0, 0, 0, {
        scalingCenterX,
        scalingCenterY
      });
      matrix.multiplySelf(this[SCALABLE_MATRIX]);
    }
  }
  _a = SCALABLE_MATRIX;
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], ScalableInternal.prototype, "scalingX", 2);
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], ScalableInternal.prototype, "scalingY", 2);
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], ScalableInternal.prototype, "scalingCenterX", 2);
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], ScalableInternal.prototype, "scalingCenterY", 2);
  return ScalableInternal;
}
function Translatable(Parent) {
  var _a;
  const ParentNode = Parent;
  const TRANSLATABLE_MATRIX = Symbol("matrix_translation");
  class TranslatableInternal extends MatrixTransform(ParentNode) {
    constructor() {
      super(...arguments);
      this[_a] = new Matrix();
      this.translationX = 0;
      this.translationY = 0;
    }
    updateMatrix(matrix) {
      super.updateMatrix(matrix);
      const { translationX, translationY } = this;
      if (translationX === 0 && translationY === 0)
        return;
      Matrix.updateTransformMatrix(this[TRANSLATABLE_MATRIX], 1, 1, 0, translationX, translationY);
      matrix.multiplySelf(this[TRANSLATABLE_MATRIX]);
    }
  }
  _a = TRANSLATABLE_MATRIX;
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], TranslatableInternal.prototype, "translationX", 2);
  __decorateClass([
    SceneChangeDetection({ type: "transform" })
  ], TranslatableInternal.prototype, "translationY", 2);
  return TranslatableInternal;
}
var Transformable = class {
  /**
   * Converts a BBox from canvas coordinate space into the coordinate space of the given Node.
   */
  static fromCanvas(node, bbox) {
    const parents = [];
    for (const parent of node.traverseUp()) {
      if (isMatrixTransform(parent)) {
        parents.unshift(parent);
      }
    }
    for (const parent of parents) {
      bbox = parent.fromParent(bbox);
    }
    if (isMatrixTransform(node)) {
      bbox = node.fromParent(bbox);
    }
    return bbox;
  }
  /**
   * Converts a Nodes BBox (or an arbitrary BBox if supplied) from local Node coordinate space
   * into the Canvas coordinate space.
   */
  static toCanvas(node, bbox) {
    if (bbox == null) {
      bbox = node.getBBox();
    } else if (isMatrixTransform(node)) {
      bbox = node.toParent(bbox);
    }
    for (const parent of node.traverseUp()) {
      if (isMatrixTransform(parent)) {
        bbox = parent.toParent(bbox);
      }
    }
    return bbox;
  }
  /**
   * Converts a point from canvas coordinate space into the coordinate space of the given Node.
   */
  static fromCanvasPoint(node, x, y) {
    const parents = [];
    for (const parent of node.traverseUp()) {
      if (isMatrixTransform(parent)) {
        parents.unshift(parent);
      }
    }
    for (const parent of parents) {
      ({ x, y } = parent.fromParentPoint(x, y));
    }
    if (isMatrixTransform(node)) {
      ({ x, y } = node.fromParentPoint(x, y));
    }
    return { x, y };
  }
  /**
   * Converts a point from a Nodes local coordinate space into the Canvas coordinate space.
   */
  static toCanvasPoint(node, x, y) {
    if (isMatrixTransform(node)) {
      ({ x, y } = node.toParentPoint(x, y));
    }
    for (const parent of node.traverseUp()) {
      if (isMatrixTransform(parent)) {
        ({ x, y } = parent.toParentPoint(x, y));
      }
    }
    return { x, y };
  }
};
var cmp = (a, b) => Math.sign(a - b);
function compareZIndex(a, b) {
  if (typeof a === "number" && typeof b === "number") {
    return cmp(a, b);
  }
  const aArray = typeof a === "number" ? [a] : a;
  const bArray = typeof b === "number" ? [b] : b;
  const length2 = Math.min(aArray.length, bArray.length);
  for (let i = 0; i < length2; i += 1) {
    const diff2 = cmp(aArray[i], bArray[i]);
    if (diff2 !== 0)
      return diff2;
  }
  return cmp(aArray.length, bArray.length);
}
var _Group = class _Group2 extends Node {
  constructor(opts) {
    super(opts);
    this.opacity = 1;
    this.layer = void 0;
    this.renderToOffscreenCanvas = false;
    this.isContainerNode = true;
    this.renderToOffscreenCanvas = opts?.renderToOffscreenCanvas === true;
  }
  static is(value) {
    return value instanceof _Group2;
  }
  static computeChildrenBBox(nodes, skipInvisible = true) {
    return BBox.merge(Node.extractBBoxes(nodes, skipInvisible));
  }
  static compareChildren(a, b) {
    return compareZIndex(a.zIndex, b.zIndex) || ascendingStringNumberUndefined(a.serialNumber, b.serialNumber);
  }
  // We consider a group to be boundless, thus any point belongs to it.
  containsPoint(_x, _y) {
    return true;
  }
  computeBBox() {
    return _Group2.computeChildrenBBox(this.children());
  }
  isDirty(renderCtx) {
    const { resized } = renderCtx;
    const { dirty, dirtyZIndex } = this;
    if (dirty || dirtyZIndex || resized)
      return true;
    for (const child of this.children()) {
      if (child.dirty)
        return true;
    }
    return false;
  }
  preRender() {
    const counts = super.preRender(0);
    counts.groups += 1;
    counts.nonGroups -= 1;
    if (this.renderToOffscreenCanvas && counts.nonGroups > 0 && this.getVisibility()) {
      this.layer ?? (this.layer = this._layerManager?.addLayer({ name: this.name }));
    } else if (this.layer != null) {
      this._layerManager?.removeLayer(this.layer);
      this.layer = void 0;
    }
    return counts;
  }
  render(renderCtx) {
    const { layer } = this;
    const childRenderCtx = { ...renderCtx };
    if (layer == null) {
      this.renderInContext(childRenderCtx);
      super.render(childRenderCtx);
      return;
    }
    const { ctx, stats } = renderCtx;
    if (this.isDirty(renderCtx)) {
      const transform = ctx.getTransform();
      const { globalAlpha } = ctx;
      const layerCtx = layer.context;
      childRenderCtx.ctx = layerCtx;
      layer.clear();
      layerCtx.save();
      layerCtx.setTransform(transform);
      layerCtx.globalAlpha = globalAlpha;
      this.renderInContext(childRenderCtx);
      layerCtx.restore();
      layerCtx.verifyDepthZero?.();
      if (stats)
        stats.layersRendered++;
    } else {
      this.skipRender(childRenderCtx);
      if (stats)
        stats.layersSkipped++;
    }
    ctx.save();
    ctx.resetTransform();
    layer.drawImage(ctx);
    ctx.restore();
    super.render(childRenderCtx);
  }
  skipRender(childRenderCtx) {
    const { stats } = childRenderCtx;
    for (const child of this.children()) {
      child.markClean();
      if (stats) {
        stats.nodesSkipped += this.childNodeCounts.groups + this.childNodeCounts.nonGroups;
        stats.opsSkipped += this.childNodeCounts.complexity;
      }
    }
  }
  applyClip(ctx, clipRect) {
    const { x, y, width: width2, height: height2 } = clipRect;
    ctx.beginPath();
    ctx.rect(x, y, width2, height2);
    ctx.clip();
  }
  renderInContext(childRenderCtx) {
    const { ctx, stats } = childRenderCtx;
    if (this.dirtyZIndex) {
      this.sortChildren(_Group2.compareChildren);
    }
    ctx.save();
    ctx.globalAlpha *= this.opacity;
    if (this.clipRect != null) {
      this.applyClip(ctx, this.clipRect);
      childRenderCtx.clipBBox = Transformable.toCanvas(this, this.clipRect);
    }
    for (const child of this.children()) {
      if (!child.visible) {
        child.markClean();
        if (stats) {
          stats.nodesSkipped += child.childNodeCounts.nonGroups + child.childNodeCounts.groups;
          stats.opsSkipped += child.childNodeCounts.complexity;
        }
        continue;
      }
      ctx.save();
      child.render(childRenderCtx);
      ctx.restore();
    }
    ctx.restore();
  }
  /**
   * Transforms bbox given in the canvas coordinate space to bbox in this group's coordinate space and
   * sets this group's clipRect to the transformed bbox.
   * @param bbox clipRect bbox in the canvas coordinate space.
   */
  setClipRect(bbox) {
    this.clipRect = bbox ? Transformable.fromCanvas(this, bbox) : void 0;
  }
  /**
   * Set the clip rect within the canvas coordinate space.
   * @param bbox clipRect bbox in the canvas coordinate space.
   */
  setClipRectCanvasSpace(bbox) {
    this.clipRect = bbox;
  }
  _setLayerManager(layersManager) {
    if (this.layer) {
      this._layerManager?.removeLayer(this.layer);
      this.layer = void 0;
    }
    super._setLayerManager(layersManager);
  }
  getVisibility() {
    for (const node of this.traverseUp(true)) {
      if (!node.visible) {
        return false;
      }
    }
    return true;
  }
  toSVG() {
    if (!this.visible)
      return;
    const defs = [];
    const elements = [];
    for (const child of this.children()) {
      const svg = child.toSVG();
      if (svg != null) {
        elements.push(...svg.elements);
        if (svg.defs != null) {
          defs.push(...svg.defs);
        }
      }
    }
    return { elements, defs };
  }
};
_Group.className = "Group";
__decorateClass([
  SceneChangeDetection({ convertor: (v) => clamp(0, v, 1) })
], _Group.prototype, "opacity", 2);
var Group = _Group;
var ScalableGroup = class extends Scalable(Group) {
};
var RotatableGroup = class extends Rotatable(Group) {
};
var TranslatableGroup = class extends Translatable(Group) {
};
var TransformableGroup = class extends Rotatable(Translatable(Group)) {
};
var verifiedGlobals = {};
if (typeof window !== "undefined") {
  verifiedGlobals.window = window;
} else if (typeof global !== "undefined") {
  verifiedGlobals.window = global.window;
}
if (typeof document !== "undefined") {
  verifiedGlobals.document = document;
} else if (typeof global !== "undefined") {
  verifiedGlobals.document = global.document;
}
function getDocument(propertyName) {
  return propertyName ? verifiedGlobals.document?.[propertyName] : verifiedGlobals.document;
}
function getWindow(propertyName) {
  return propertyName ? verifiedGlobals.window?.[propertyName] : verifiedGlobals.window;
}
function createElement(tagName, className, style) {
  const element2 = getDocument().createElement(tagName);
  if (typeof className === "object") {
    style = className;
    className = void 0;
  }
  if (className) {
    for (const name of className.split(" ")) {
      element2.classList.add(name);
    }
  }
  if (style) {
    Object.assign(element2.style, style);
  }
  return element2;
}
function createElementNS(namespaceURI, qualifiedName) {
  return getDocument().createElementNS(namespaceURI, qualifiedName);
}
function downloadUrl(dataUrl, fileName) {
  const { body } = getDocument();
  const element2 = createElement("a", { display: "none" });
  element2.href = dataUrl;
  element2.download = fileName;
  body.appendChild(element2);
  element2.click();
  setTimeout(() => body.removeChild(element2));
}
function setDocument(document2) {
  verifiedGlobals.document = document2;
}
function setWindow(window2) {
  verifiedGlobals.window = window2;
}
function setElementBBox(element2, bbox) {
  if (!element2)
    return;
  bbox = BBoxValues.normalize(bbox);
  if (bbox.width == null) {
    element2.style.removeProperty("width");
  } else {
    element2.style.width = `${bbox.width}px`;
  }
  if (bbox.height == null) {
    element2.style.removeProperty("height");
  } else {
    element2.style.height = `${bbox.height}px`;
  }
  if (bbox.x == null) {
    element2.style.removeProperty("left");
  } else {
    element2.style.left = `${bbox.x}px`;
  }
  if (bbox.y == null) {
    element2.style.removeProperty("top");
  } else {
    element2.style.top = `${bbox.y}px`;
  }
}
function getElementBBox(element2) {
  const width2 = parseFloat(element2.style.width) || element2.offsetWidth;
  const height2 = parseFloat(element2.style.height) || element2.offsetHeight;
  const x = parseFloat(element2.style.left) || element2.offsetLeft;
  const y = parseFloat(element2.style.top) || element2.offsetTop;
  return { x, y, width: width2, height: height2 };
}
function focusCursorAtEnd(element2) {
  element2.focus({ preventScroll: true });
  if (element2.lastChild?.textContent == null)
    return;
  const range3 = getDocument().createRange();
  range3.setStart(element2.lastChild, element2.lastChild.textContent.length);
  range3.setEnd(element2.lastChild, element2.lastChild.textContent.length);
  const selection = getWindow().getSelection();
  selection?.removeAllRanges();
  selection?.addRange(range3);
}
var _id = 0;
function createElementId(label) {
  return `${label ?? "ag-charts-element"}-${_id++}`;
}
function isInputPending() {
  const navigator = getWindow().navigator;
  if ("scheduling" in navigator) {
    const scheduling = navigator.scheduling;
    if ("isInputPending" in scheduling) {
      return scheduling.isInputPending({ includeContinuous: true });
    }
  }
  return false;
}
function getIconClassNames(icon) {
  return `ag-charts-icon ag-charts-icon-${icon}`;
}
var LONG_TIME_PERIOD_THRESHOLD = 2e3;
var timeOfLastLog = Date.now();
var logTimeGap = () => {
  const timeSinceLastLog = Date.now() - timeOfLastLog;
  if (timeSinceLastLog > LONG_TIME_PERIOD_THRESHOLD) {
    const prettyDuration = (Math.floor(timeSinceLastLog / 100) / 10).toFixed(1);
    Logger.log(`**** ${prettyDuration}s since last log message ****`);
  }
  timeOfLastLog = Date.now();
};
var Debug = {
  create(...debugSelectors) {
    const resultFn = (...logContent) => {
      if (Debug.check(...debugSelectors)) {
        if (typeof logContent[0] === "function") {
          logContent = toArray(logContent[0]());
        }
        logTimeGap();
        Logger.log(...logContent);
      }
    };
    return Object.assign(resultFn, { check: () => Debug.check(...debugSelectors) });
  },
  check(...debugSelectors) {
    if (debugSelectors.length === 0) {
      debugSelectors.push(true);
    }
    const chartDebug = toArray(getWindow("agChartsDebug"));
    return chartDebug.some((selector) => debugSelectors.includes(selector));
  }
};
var Selection = class _Selection {
  constructor(parentNode, classOrFactory, autoCleanup = true) {
    this.parentNode = parentNode;
    this.autoCleanup = autoCleanup;
    this.garbageBin = /* @__PURE__ */ new Set();
    this._nodesMap = /* @__PURE__ */ new Map();
    this._nodes = [];
    this.data = [];
    this.debug = Debug.create(true, "scene", "scene:selections");
    this.nodeFactory = Object.prototype.isPrototypeOf.call(Node, classOrFactory) ? () => new classOrFactory() : classOrFactory;
  }
  static select(parent, classOrFactory, garbageCollection = true) {
    return new _Selection(parent, classOrFactory, garbageCollection);
  }
  static selectAll(parent, predicate) {
    const results = [];
    const traverse = (node) => {
      if (predicate(node)) {
        results.push(node);
      }
      for (const child of node.children()) {
        traverse(child);
      }
    };
    traverse(parent);
    return results;
  }
  static selectByClass(node, ...Classes) {
    return _Selection.selectAll(node, (n) => Classes.some((C2) => n instanceof C2));
  }
  static selectByTag(node, tag) {
    return _Selection.selectAll(node, (n) => n.tag === tag);
  }
  createNode(datum, initializer, idx) {
    const node = this.nodeFactory(datum);
    node.datum = datum;
    initializer?.(node);
    if (idx == null) {
      this._nodes.push(node);
    } else {
      this._nodes.splice(idx, 0, node);
    }
    this.parentNode.appendChild(node);
    return node;
  }
  /**
   * Update the data in a selection. If an `getDatumId()` function is provided, maintain a list of ids related to
   * the nodes. Otherwise, take the more efficient route of simply creating and destroying nodes at the end
   * of the array.
   */
  update(data, initializer, getDatumId) {
    if (this.garbageBin.size > 0) {
      this.debug(`Selection - update() called with pending garbage`, data);
    }
    if (getDatumId) {
      const dataMap = new Map(
        data.map((datum, idx) => [getDatumId(datum), [datum, idx]])
      );
      for (const [node, datumId] of this._nodesMap.entries()) {
        if (dataMap.has(datumId)) {
          const [newDatum] = dataMap.get(datumId);
          node.datum = newDatum;
          this.garbageBin.delete(node);
          dataMap.delete(datumId);
        } else {
          this.garbageBin.add(node);
        }
      }
      for (const [datumId, [datum, idx]] of dataMap.entries()) {
        this._nodesMap.set(this.createNode(datum, initializer, idx), datumId);
      }
    } else {
      const maxLength = Math.max(data.length, this.data.length);
      for (let i = 0; i < maxLength; i++) {
        if (i >= data.length) {
          this.garbageBin.add(this._nodes[i]);
        } else if (i >= this._nodes.length) {
          this.createNode(data[i], initializer);
        } else {
          this._nodes[i].datum = data[i];
          this.garbageBin.delete(this._nodes[i]);
        }
      }
    }
    this.data = data.slice();
    if (this.autoCleanup) {
      this.cleanup();
    }
    return this;
  }
  cleanup() {
    if (this.garbageBin.size === 0) {
      return this;
    }
    this._nodes = this._nodes.filter((node) => {
      if (this.garbageBin.has(node)) {
        this._nodesMap.delete(node);
        this.garbageBin.delete(node);
        node.destroy();
        return false;
      }
      return true;
    });
    return this;
  }
  clear() {
    this.update([]);
    return this;
  }
  isGarbage(node) {
    return this.garbageBin.has(node);
  }
  hasGarbage() {
    return this.garbageBin.size > 0;
  }
  each(iterate2) {
    for (const entry of this._nodes.entries()) {
      iterate2(entry[1], entry[1].datum, entry[0]);
    }
    return this;
  }
  *[Symbol.iterator]() {
    for (let index = 0; index < this._nodes.length; index++) {
      const node = this._nodes[index];
      yield { node, datum: node.datum, index };
    }
  }
  select(predicate) {
    return _Selection.selectAll(this.parentNode, predicate);
  }
  selectByClass(Class) {
    return _Selection.selectByClass(this.parentNode, Class);
  }
  selectByTag(tag) {
    return _Selection.selectByTag(this.parentNode, tag);
  }
  nodes() {
    return this._nodes;
  }
  at(index) {
    return this._nodes.at(index);
  }
  get length() {
    return this._nodes.length;
  }
};
var twoPi = Math.PI * 2;
var halfPi = Math.PI / 2;
function normalizeAngle360(radians) {
  radians %= twoPi;
  radians += twoPi;
  radians %= twoPi;
  return radians;
}
function normalizeAngle360Inclusive(radians) {
  radians %= twoPi;
  radians += twoPi;
  if (radians !== twoPi) {
    radians %= twoPi;
  }
  return radians;
}
function normalizeAngle180(radians) {
  radians %= twoPi;
  if (radians < -Math.PI) {
    radians += twoPi;
  } else if (radians >= Math.PI) {
    radians -= twoPi;
  }
  return radians;
}
function isBetweenAngles(targetAngle, startAngle, endAngle) {
  const t = normalizeAngle360(targetAngle);
  const a0 = normalizeAngle360(startAngle);
  const a1 = normalizeAngle360(endAngle);
  if (a0 < a1) {
    return a0 <= t && t <= a1;
  } else if (a0 > a1) {
    return a0 <= t || t <= a1;
  } else {
    return true;
  }
}
function toRadians(degrees) {
  return degrees / 180 * Math.PI;
}
function toDegrees(radians) {
  return radians / Math.PI * 180;
}
function angleDiff(angle0, angle1, counterClockwise) {
  if (counterClockwise) {
    [angle0, angle1] = [angle1, angle0];
  }
  const a0 = normalizeAngle360(angle0);
  const a1 = normalizeAngle360(angle1) + twoPi;
  return (a1 - a0) % twoPi;
}
function angleBetween(angle0, angle1) {
  angle0 = normalizeAngle360(angle0);
  angle1 = normalizeAngle360(angle1);
  return angle1 - angle0 + (angle0 > angle1 ? twoPi : 0);
}
function displacePointFromVector(centerX, centerY, radius, angle2) {
  const x = centerX + radius * Math.cos(angle2);
  const y = centerY + radius * Math.sin(angle2);
  return { x, y };
}
var delta = 1e-6;
function clockwiseAngle(angle2, relativeToStartAngle) {
  if (angleBetween(angle2, relativeToStartAngle) < delta) {
    return relativeToStartAngle;
  } else {
    return normalizeAngle360(angle2 - relativeToStartAngle) + relativeToStartAngle;
  }
}
function clockwiseAngles(startAngle, endAngle, relativeToStartAngle = 0) {
  const fullPie = Math.abs(endAngle - startAngle) >= twoPi;
  const sweepAngle = fullPie ? twoPi : normalizeAngle360(endAngle - startAngle);
  startAngle = clockwiseAngle(startAngle, relativeToStartAngle);
  endAngle = startAngle + sweepAngle;
  return { startAngle, endAngle };
}
function getAngleRatioRadians(angle2) {
  const normalizedAngle = normalizeAngle360(angle2);
  if (normalizedAngle <= halfPi) {
    return normalizedAngle / halfPi;
  } else if (normalizedAngle <= Math.PI) {
    return (Math.PI - normalizedAngle) / halfPi;
  } else if (normalizedAngle <= 1.5 * Math.PI) {
    return (normalizedAngle - Math.PI) / halfPi;
  } else {
    return (twoPi - normalizedAngle) / halfPi;
  }
}
function pointsDistanceSquared(x1, y1, x2, y2) {
  const dx = x1 - x2;
  const dy = y1 - y2;
  return dx * dx + dy * dy;
}
function lineDistanceSquared(x, y, x1, y1, x2, y2, best) {
  if (x1 === x2 && y1 === y2) {
    return Math.min(best, pointsDistanceSquared(x, y, x1, y1));
  }
  const dx = x2 - x1;
  const dy = y2 - y1;
  const t = Math.max(0, Math.min(1, ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy)));
  const ix = x1 + t * dx;
  const iy = y1 + t * dy;
  return Math.min(best, pointsDistanceSquared(x, y, ix, iy));
}
function arcDistanceSquared(x, y, cx, cy, radius, startAngle, endAngle, counterClockwise, best) {
  if (counterClockwise) {
    [endAngle, startAngle] = [startAngle, endAngle];
  }
  const angle2 = Math.atan2(y - cy, x - cx);
  if (!isBetweenAngles(angle2, startAngle, endAngle)) {
    const startX = cx + Math.cos(startAngle) * radius;
    const startY = cy + Math.sin(startAngle) * radius;
    const endX = cx + Math.cos(startAngle) * radius;
    const endY = cy + Math.sin(startAngle) * radius;
    return Math.min(best, pointsDistanceSquared(x, y, startX, startY), pointsDistanceSquared(x, y, endX, endY));
  }
  const distToArc = radius - Math.sqrt(pointsDistanceSquared(x, y, cx, cy));
  return Math.min(best, distToArc * distToArc);
}
var convertColorStringToOklcha = (v) => {
  const color = Color.fromString(v);
  const [l, c, h] = Color.RGBtoOKLCH(color.r, color.g, color.b);
  return { l, c, h, a: color.a };
};
var delta2 = 1e-6;
var isAchromatic = (x) => x.c < delta2 || x.l < delta2 || x.l > 1 - delta2;
var interpolateOklch = (x, y, d) => {
  d = clamp(0, d, 1);
  let h;
  if (isAchromatic(x)) {
    h = y.h;
  } else if (isAchromatic(y)) {
    h = x.h;
  } else {
    const xH = x.h;
    let yH = y.h;
    const deltaH = y.h - x.h;
    if (deltaH > 180) {
      yH -= 360;
    } else if (deltaH < -180) {
      yH += 360;
    }
    h = xH * (1 - d) + yH * d;
  }
  const c = x.c * (1 - d) + y.c * d;
  const l = x.l * (1 - d) + y.l * d;
  const a = x.a * (1 - d) + y.a * d;
  return Color.fromOKLCH(l, c, h, a);
};
var ColorScale = class {
  constructor() {
    this.type = "color";
    this.invalid = true;
    this.domain = [0, 1];
    this.range = ["red", "blue"];
    this.parsedRange = this.range.map(convertColorStringToOklcha);
  }
  update() {
    const { domain, range: range3 } = this;
    if (domain.length < 2) {
      Logger.warnOnce("`colorDomain` should have at least 2 values.");
      if (domain.length === 0) {
        domain.push(0, 1);
      } else if (domain.length === 1) {
        domain.push(domain[0] + 1);
      }
    }
    for (let i = 1; i < domain.length; i++) {
      const a = domain[i - 1];
      const b = domain[i];
      if (a >= b) {
        Logger.warnOnce("`colorDomain` values should be supplied in ascending order.");
        domain.sort((a2, b2) => a2 - b2);
        break;
      }
    }
    if (range3.length < domain.length) {
      for (let i = range3.length; i < domain.length; i++) {
        range3.push(range3.length > 0 ? range3[0] : "black");
      }
    }
    this.parsedRange = this.range.map(convertColorStringToOklcha);
  }
  convert(x) {
    this.refresh();
    const { domain, range: range3, parsedRange } = this;
    const d0 = domain[0];
    const d1 = domain.at(-1);
    const r0 = range3[0];
    const r1 = range3[range3.length - 1];
    if (x <= d0) {
      return r0;
    }
    if (x >= d1) {
      return r1;
    }
    let index;
    let q;
    if (domain.length === 2) {
      const t = (x - d0) / (d1 - d0);
      const step = 1 / (range3.length - 1);
      index = range3.length <= 2 ? 0 : Math.min(Math.floor(t * (range3.length - 1)), range3.length - 2);
      q = (t - index * step) / step;
    } else {
      for (index = 0; index < domain.length - 2; index++) {
        if (x < domain[index + 1]) {
          break;
        }
      }
      const a = domain[index];
      const b = domain[index + 1];
      q = (x - a) / (b - a);
    }
    const c0 = parsedRange[index];
    const c1 = parsedRange[index + 1];
    return interpolateOklch(c0, c1, q).toRgbaString();
  }
  refresh() {
    if (!this.invalid)
      return;
    this.invalid = false;
    this.update();
    if (this.invalid) {
      Logger.warnOnce("Expected update to not invalidate scale");
    }
  }
};
__decorateClass([
  Invalidating
], ColorScale.prototype, "domain", 2);
__decorateClass([
  Invalidating
], ColorScale.prototype, "range", 2);
var Gradient = class {
  constructor(colorSpace, stops = [], bbox) {
    this.colorSpace = colorSpace;
    this.stops = stops;
    this.bbox = bbox;
    this._cache = void 0;
  }
  createGradient(ctx, shapeBbox) {
    const bbox = this.bbox ?? shapeBbox;
    if (this._cache != null && this._cache.ctx === ctx && this._cache.bbox.equals(bbox)) {
      return this._cache.gradient;
    }
    const { stops, colorSpace } = this;
    if (stops.length === 0)
      return;
    if (stops.length === 1)
      return stops[0].color;
    let gradient2 = this.createCanvasGradient(ctx, bbox);
    if (gradient2 == null)
      return;
    const isOkLch = colorSpace === "oklch";
    const step = 0.05;
    let c0 = stops[0];
    gradient2.addColorStop(c0.offset, c0.color);
    for (let i = 1; i < stops.length; i += 1) {
      const c1 = stops[i];
      if (isOkLch) {
        const scale2 = new ColorScale();
        scale2.domain = [c0.offset, c1.offset];
        scale2.range = [c0.color, c1.color];
        for (let offset4 = c0.offset + step; offset4 < c1.offset; offset4 += step) {
          gradient2.addColorStop(offset4, scale2.convert(offset4));
        }
      }
      gradient2.addColorStop(c1.offset, c1.color);
      c0 = c1;
    }
    if ("createPattern" in gradient2) {
      gradient2 = gradient2.createPattern();
    }
    this._cache = { ctx, bbox, gradient: gradient2 };
    return gradient2;
  }
};
var LinearGradient = class extends Gradient {
  constructor(colorSpace, stops, angle2 = 0, bbox) {
    super(colorSpace, stops, bbox);
    this.angle = angle2;
  }
  createCanvasGradient(ctx, bbox) {
    const angleOffset = 90;
    const { angle: angle2 } = this;
    const radians = normalizeAngle360(toRadians(angle2 + angleOffset));
    const cos = Math.cos(radians);
    const sin = Math.sin(radians);
    const w = bbox.width;
    const h = bbox.height;
    const cx = bbox.x + w * 0.5;
    const cy = bbox.y + h * 0.5;
    const diagonal = Math.sqrt(h * h + w * w) / 2;
    const diagonalAngle = Math.atan2(h, w);
    let quarteredAngle;
    if (radians < Math.PI / 2) {
      quarteredAngle = radians;
    } else if (radians < Math.PI) {
      quarteredAngle = Math.PI - radians;
    } else if (radians < 1.5 * Math.PI) {
      quarteredAngle = radians - Math.PI;
    } else {
      quarteredAngle = 2 * Math.PI - radians;
    }
    const l = diagonal * Math.abs(Math.cos(quarteredAngle - diagonalAngle));
    return ctx.createLinearGradient(cx + cos * l, cy + sin * l, cx - cos * l, cy - sin * l);
  }
};
var LINEAR_GRADIENT_REGEXP = /^linear-gradient\((-?[\d.]+)deg,(.*?)\)$/i;
var _Shape = class _Shape2 extends Node {
  constructor() {
    super(...arguments);
    this.fillOpacity = 1;
    this.strokeOpacity = 1;
    this.fill = _Shape2.defaultStyles.fill;
    this.stroke = _Shape2.defaultStyles.stroke;
    this.strokeWidth = _Shape2.defaultStyles.strokeWidth;
    this.lineDash = _Shape2.defaultStyles.lineDash;
    this.lineDashOffset = _Shape2.defaultStyles.lineDashOffset;
    this.lineCap = _Shape2.defaultStyles.lineCap;
    this.lineJoin = _Shape2.defaultStyles.lineJoin;
    this.miterLimit = void 0;
    this.opacity = _Shape2.defaultStyles.opacity;
    this.fillShadow = _Shape2.defaultStyles.fillShadow;
  }
  /**
   * Restores the default styles introduced by this subclass.
   */
  restoreOwnStyles() {
    const { defaultStyles } = this.constructor;
    Object.assign(this, defaultStyles);
  }
  getGradient(pattern) {
    let linearGradientMatch;
    if (pattern instanceof Gradient) {
      return pattern;
    } else if (pattern?.startsWith("linear-gradient") && (linearGradientMatch = LINEAR_GRADIENT_REGEXP.exec(pattern))) {
      const angle2 = parseFloat(linearGradientMatch[1]);
      const colors = [];
      const colorsPart = linearGradientMatch[2];
      const colorRegex = /(#[0-9a-f]+)|(rgba?\(.+?\))|([a-z]+)/gi;
      let c;
      while (c = colorRegex.exec(colorsPart)) {
        colors.push(c[0]);
      }
      return new LinearGradient(
        "rgb",
        colors.map((color, index) => ({ color, offset: index / (colors.length - 1) })),
        angle2
      );
    } else {
      return void 0;
    }
  }
  onFillChange() {
    this.fillGradient = this.getGradient(this.fill);
  }
  onStrokeChange() {
    this.strokeGradient = this.getGradient(this.stroke);
  }
  /**
   * Returns a device-pixel aligned coordinate (or length if length is supplied).
   *
   * NOTE: Not suitable for strokes, since the stroke needs to be offset to the middle
   * of a device pixel.
   */
  align(start2, length2) {
    const pixelRatio = this.layerManager?.canvas?.pixelRatio ?? 1;
    const alignedStart = Math.round(start2 * pixelRatio) / pixelRatio;
    if (length2 == null) {
      return alignedStart;
    } else if (length2 === 0) {
      return 0;
    } else if (length2 < 1) {
      return Math.ceil(length2 * pixelRatio) / pixelRatio;
    }
    return Math.round((length2 + start2) * pixelRatio) / pixelRatio - alignedStart;
  }
  fillStroke(ctx, path) {
    this.renderFill(ctx, path);
    this.renderStroke(ctx, path);
  }
  renderFill(ctx, path) {
    if (this.fill) {
      const { globalAlpha } = ctx;
      this.applyFill(ctx);
      this.applyFillAlpha(ctx);
      this.applyShadow(ctx);
      this.executeFill(ctx, path);
      ctx.globalAlpha = globalAlpha;
    }
    ctx.shadowColor = "rgba(0, 0, 0, 0)";
  }
  executeFill(ctx, path) {
    if (path) {
      ctx.fill(path);
    } else {
      ctx.fill();
    }
  }
  applyFill(ctx) {
    ctx.fillStyle = this.fillGradient?.createGradient(ctx, this.getBBox()) ?? (typeof this.fill === "string" ? this.fill : void 0) ?? "black";
  }
  applyStroke(ctx) {
    ctx.strokeStyle = this.strokeGradient?.createGradient(ctx, this.getBBox()) ?? (typeof this.stroke === "string" ? this.stroke : void 0) ?? "black";
  }
  applyFillAlpha(ctx) {
    ctx.globalAlpha *= this.opacity * this.fillOpacity;
  }
  applyShadow(ctx) {
    const pixelRatio = this.layerManager?.canvas.pixelRatio ?? 1;
    const fillShadow = this.fillShadow;
    if (fillShadow?.enabled) {
      ctx.shadowColor = fillShadow.color;
      ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio;
      ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio;
      ctx.shadowBlur = fillShadow.blur * pixelRatio;
    }
  }
  renderStroke(ctx, path) {
    if (this.stroke && this.strokeWidth) {
      const { globalAlpha } = ctx;
      this.applyStroke(ctx);
      ctx.globalAlpha *= this.opacity * this.strokeOpacity;
      ctx.lineWidth = this.strokeWidth;
      if (this.lineDash) {
        ctx.setLineDash(this.lineDash);
      }
      if (this.lineDashOffset) {
        ctx.lineDashOffset = this.lineDashOffset;
      }
      if (this.lineCap) {
        ctx.lineCap = this.lineCap;
      }
      if (this.lineJoin) {
        ctx.lineJoin = this.lineJoin;
      }
      if (this.miterLimit != null) {
        ctx.miterLimit = this.miterLimit;
      }
      this.executeStroke(ctx, path);
      ctx.globalAlpha = globalAlpha;
    }
  }
  executeStroke(ctx, path) {
    if (path) {
      ctx.stroke(path);
    } else {
      ctx.stroke();
    }
  }
  containsPoint(x, y) {
    return this.isPointInPath(x, y);
  }
  applySvgFillAttributes(element2) {
    element2.setAttribute("fill", typeof this.fill === "string" ? this.fill : "none");
    element2.setAttribute("fill-opacity", String(this.fillOpacity));
  }
  applySvgStrokeAttributes(element2) {
    if (this.stroke != null) {
      element2.setAttribute("stroke", typeof this.stroke === "string" ? this.stroke : "none");
      element2.setAttribute("stroke-opacity", String(this.strokeOpacity));
      element2.setAttribute("stroke-width", String(this.strokeWidth));
    }
    if (this.lineDash != null) {
      element2.setAttribute("stroke-dasharray", this.lineDash.join(" "));
    }
  }
};
_Shape.defaultStyles = {
  fill: "black",
  stroke: void 0,
  strokeWidth: 0,
  lineDash: void 0,
  lineDashOffset: 0,
  lineCap: void 0,
  lineJoin: void 0,
  opacity: 1,
  fillShadow: void 0
};
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "fillOpacity", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "strokeOpacity", 2);
__decorateClass([
  SceneChangeDetection({ changeCb: (s) => s.onFillChange() })
], _Shape.prototype, "fill", 2);
__decorateClass([
  SceneChangeDetection({ changeCb: (s) => s.onStrokeChange() })
], _Shape.prototype, "stroke", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "strokeWidth", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "lineDash", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "lineDashOffset", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "lineCap", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "lineJoin", 2);
__decorateClass([
  SceneChangeDetection()
], _Shape.prototype, "miterLimit", 2);
__decorateClass([
  SceneChangeDetection({ convertor: (v) => clamp(0, v, 1) })
], _Shape.prototype, "opacity", 2);
__decorateClass([
  SceneChangeDetection({ checkDirtyOnAssignment: true })
], _Shape.prototype, "fillShadow", 2);
var Shape = _Shape;
var Line = class extends Shape {
  constructor(opts = {}) {
    super(opts);
    this.x1 = 0;
    this.y1 = 0;
    this.x2 = 0;
    this.y2 = 0;
    this.restoreOwnStyles();
  }
  set x(value) {
    this.x1 = value;
    this.x2 = value;
  }
  set y(value) {
    this.y1 = value;
    this.y2 = value;
  }
  get midPoint() {
    return { x: (this.x1 + this.x2) / 2, y: (this.y1 + this.y2) / 2 };
  }
  computeBBox() {
    return new BBox(
      Math.min(this.x1, this.x2),
      Math.min(this.y1, this.y2),
      Math.abs(this.x2 - this.x1),
      Math.abs(this.y2 - this.y1)
    );
  }
  isPointInPath(x, y) {
    if (this.x1 === this.x2 || this.y1 === this.y2) {
      return this.getBBox().clone().grow(this.strokeWidth / 2).containsPoint(x, y);
    }
    return false;
  }
  distanceSquared(px, py) {
    const { x1, y1, x2, y2 } = this;
    return lineDistanceSquared(px, py, x1, y1, x2, y2, Infinity);
  }
  render(renderCtx) {
    const { ctx, devicePixelRatio } = renderCtx;
    let { x1, y1, x2, y2 } = this;
    if (x1 === x2) {
      const { strokeWidth } = this;
      const x = Math.round(x1 * devicePixelRatio) / devicePixelRatio + Math.trunc(strokeWidth * devicePixelRatio) % 2 / (devicePixelRatio * 2);
      x1 = x;
      x2 = x;
    } else if (y1 === y2) {
      const { strokeWidth } = this;
      const y = Math.round(y1 * devicePixelRatio) / devicePixelRatio + Math.trunc(strokeWidth * devicePixelRatio) % 2 / (devicePixelRatio * 2);
      y1 = y;
      y2 = y;
    }
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    this.fillStroke(ctx);
    this.fillShadow?.markClean();
    super.render(renderCtx);
  }
  toSVG() {
    if (!this.visible)
      return;
    const element2 = document.createElementNS("http://www.w3.org/2000/svg", "line");
    element2.setAttribute("x1", String(this.x1));
    element2.setAttribute("y1", String(this.y1));
    element2.setAttribute("x2", String(this.x2));
    element2.setAttribute("y2", String(this.y2));
    this.applySvgStrokeAttributes(element2);
    return {
      elements: [element2]
    };
  }
};
Line.className = "Line";
Line.defaultStyles = { ...Shape.defaultStyles, fill: void 0, strokeWidth: 1 };
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "x1", 2);
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "y1", 2);
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "x2", 2);
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "y2", 2);
function createCanvasContext(width2 = 0, height2 = 0) {
  return new OffscreenCanvas(width2, height2).getContext("2d");
}
var LRUCache = class {
  constructor(maxCacheSize = 5) {
    this.maxCacheSize = maxCacheSize;
    this.store = /* @__PURE__ */ new Map();
  }
  get(key) {
    if (!this.store.has(key))
      return void 0;
    const hit = this.store.get(key);
    this.store.delete(key);
    this.store.set(key, hit);
    return hit;
  }
  has(key) {
    return this.store.has(key);
  }
  set(key, value) {
    this.store.set(key, value);
    if (this.store.size > this.maxCacheSize) {
      const iterator = this.store.keys();
      let evictCount = this.store.size - this.maxCacheSize;
      while (evictCount > 0) {
        const evictKeyIterator = iterator.next();
        if (!evictKeyIterator.done) {
          this.store.delete(evictKeyIterator.value);
        }
        evictCount--;
      }
    }
    return value;
  }
  clear() {
    this.store.clear();
  }
};
var CachedTextMeasurerPool = class {
  // Measures the dimensions of the provided text, handling multiline if needed.
  static measureText(text, options) {
    const textMeasurer = this.getMeasurer(options);
    return textMeasurer.measureText(text);
  }
  static measureLines(text, options) {
    const textMeasurer = this.getMeasurer(options);
    return textMeasurer.measureLines(text);
  }
  // Gets a TextMeasurer instance, configuring text alignment and baseline if provided.
  static getMeasurer(options) {
    const font = typeof options.font === "string" ? options.font : TextUtils.toFontString(options.font);
    const key = `${font}-${options.textAlign ?? "start"}-${options.textBaseline ?? "alphabetic"}`;
    return this.instanceMap.get(key) ?? this.createFontMeasurer(font, options, key);
  }
  // Creates or retrieves a TextMeasurer instance for a specific font.
  static createFontMeasurer(font, options, key) {
    const ctx = createCanvasContext();
    ctx.font = font;
    ctx.textAlign = options.textAlign ?? "start";
    ctx.textBaseline = options.textBaseline ?? "alphabetic";
    const measurer = new CachedTextMeasurer(ctx, options);
    this.instanceMap.set(key, measurer);
    return measurer;
  }
};
CachedTextMeasurerPool.instanceMap = new LRUCache(10);
var CachedTextMeasurer = class {
  constructor(ctx, options) {
    this.ctx = ctx;
    this.measureMap = new LRUCache(100);
    if (options.textAlign) {
      ctx.textAlign = options.textAlign;
    }
    if (options.textBaseline) {
      ctx.textBaseline = options.textBaseline;
    }
    ctx.font = typeof options.font === "string" ? options.font : TextUtils.toFontString(options.font);
    this.textMeasurer = new SimpleTextMeasurer(
      (t) => this.cachedCtxMeasureText(t),
      options.textBaseline ?? "alphabetic"
    );
  }
  textWidth(text, estimate) {
    return this.textMeasurer.textWidth(text, estimate);
  }
  measureText(text) {
    return this.textMeasurer.measureText(text);
  }
  measureLines(text) {
    return this.textMeasurer.measureLines(text);
  }
  cachedCtxMeasureText(text) {
    if (!this.measureMap.has(text)) {
      const rawResult = this.ctx.measureText(text);
      this.measureMap.set(text, {
        actualBoundingBoxAscent: rawResult.actualBoundingBoxAscent,
        emHeightAscent: rawResult.emHeightAscent,
        emHeightDescent: rawResult.emHeightDescent,
        actualBoundingBoxDescent: rawResult.actualBoundingBoxDescent,
        actualBoundingBoxLeft: rawResult.actualBoundingBoxLeft,
        actualBoundingBoxRight: rawResult.actualBoundingBoxRight,
        alphabeticBaseline: rawResult.alphabeticBaseline,
        fontBoundingBoxAscent: rawResult.fontBoundingBoxAscent,
        fontBoundingBoxDescent: rawResult.fontBoundingBoxDescent,
        hangingBaseline: rawResult.hangingBaseline,
        ideographicBaseline: rawResult.ideographicBaseline,
        width: rawResult.width
      });
    }
    return this.measureMap.get(text);
  }
};
var TextUtils = class {
  static toFontString({ fontSize = 10, fontStyle, fontWeight, fontFamily, lineHeight }) {
    let fontString = "";
    if (fontStyle) {
      fontString += `${fontStyle} `;
    }
    if (fontWeight) {
      fontString += `${fontWeight} `;
    }
    fontString += `${fontSize}px`;
    if (lineHeight) {
      fontString += `/${lineHeight}px`;
    }
    fontString += ` ${fontFamily}`;
    return fontString.trim();
  }
  static getLineHeight(fontSize) {
    return Math.ceil(fontSize * this.defaultLineHeight);
  }
  // Determines vertical offset modifier based on text baseline.
  static getVerticalModifier(textBaseline) {
    switch (textBaseline) {
      case "hanging":
      case "top":
        return 0;
      case "middle":
        return 0.5;
      case "alphabetic":
      case "bottom":
      case "ideographic":
      default:
        return 1;
    }
  }
};
TextUtils.EllipsisChar = "\u2026";
TextUtils.defaultLineHeight = 1.15;
TextUtils.lineSplitter = /\r?\n/g;
var SimpleTextMeasurer = class {
  constructor(measureTextFn, textBaseline = "alphabetic") {
    this.measureTextFn = measureTextFn;
    this.textBaseline = textBaseline;
    this.charMap = /* @__PURE__ */ new Map();
  }
  // Measures metrics for a single line of text.
  getMetrics(text) {
    const m = this.measureTextFn(text);
    m.fontBoundingBoxAscent ?? (m.fontBoundingBoxAscent = m.emHeightAscent);
    m.fontBoundingBoxDescent ?? (m.fontBoundingBoxDescent = m.emHeightDescent);
    return {
      width: m.width,
      height: m.actualBoundingBoxAscent + m.actualBoundingBoxDescent,
      lineHeight: m.fontBoundingBoxAscent + m.fontBoundingBoxDescent,
      offsetTop: m.actualBoundingBoxAscent,
      offsetLeft: m.actualBoundingBoxLeft
    };
  }
  // Calculates aggregated metrics for multiline text.
  getMultilineMetrics(lines) {
    let width2 = 0;
    let height2 = 0;
    let offsetTop = 0;
    let offsetLeft = 0;
    let baselineDistance = 0;
    const verticalModifier = TextUtils.getVerticalModifier(this.textBaseline);
    const lineMetrics = [];
    let index = 0;
    const length2 = lines.length;
    for (const line of lines) {
      const m = this.measureTextFn(line);
      m.fontBoundingBoxAscent ?? (m.fontBoundingBoxAscent = m.emHeightAscent);
      m.fontBoundingBoxDescent ?? (m.fontBoundingBoxDescent = m.emHeightDescent);
      if (width2 < m.width) {
        width2 = m.width;
      }
      if (offsetLeft < m.actualBoundingBoxLeft) {
        offsetLeft = m.actualBoundingBoxLeft;
      }
      if (index === 0) {
        height2 += m.actualBoundingBoxAscent;
        offsetTop += m.actualBoundingBoxAscent;
      } else {
        baselineDistance += m.fontBoundingBoxAscent;
      }
      if (index === length2 - 1) {
        height2 += m.actualBoundingBoxDescent;
      } else {
        baselineDistance += m.fontBoundingBoxDescent;
      }
      lineMetrics.push({
        text: line,
        width: m.width,
        height: m.actualBoundingBoxAscent + m.actualBoundingBoxDescent,
        lineHeight: m.fontBoundingBoxAscent + m.fontBoundingBoxDescent,
        offsetTop: m.actualBoundingBoxAscent,
        offsetLeft: m.actualBoundingBoxLeft
      });
      index++;
    }
    height2 += baselineDistance;
    offsetTop += baselineDistance * verticalModifier;
    return { width: width2, height: height2, offsetTop, offsetLeft, lineMetrics };
  }
  textWidth(text, estimate) {
    if (estimate) {
      let estimatedWidth = 0;
      for (let i = 0; i < text.length; i++) {
        estimatedWidth += this.textWidth(text.charAt(i));
      }
      return estimatedWidth;
    }
    if (text.length > 1) {
      return this.measureTextFn(text).width;
    }
    return this.charMap.get(text) ?? this.charWidth(text);
  }
  measureText(text) {
    return this.getMetrics(text);
  }
  // Measures the dimensions of the provided text, handling multiline if needed.
  measureLines(text) {
    const lines = typeof text === "string" ? text.split(TextUtils.lineSplitter) : text;
    return this.getMultilineMetrics(lines);
  }
  charWidth(char) {
    const { width: width2 } = this.measureTextFn(char);
    this.charMap.set(char, width2);
    return width2;
  }
};
var _Text = class _Text2 extends Shape {
  constructor() {
    super(...arguments);
    this.x = 0;
    this.y = 0;
    this.lines = [];
    this.text = void 0;
    this.fontSize = 10;
    this.fontFamily = "sans-serif";
    this.textAlign = _Text2.defaultStyles.textAlign;
    this.textBaseline = _Text2.defaultStyles.textBaseline;
  }
  onTextChange() {
    this.lines = this.text?.split("\n").map((s) => s.trim()) ?? [];
  }
  static computeBBox(lines, x, y, opts) {
    const { offsetTop, offsetLeft, width: width2, height: height2 } = CachedTextMeasurerPool.measureLines(lines, opts);
    return new BBox(x - offsetLeft, y - offsetTop, width2, height2);
  }
  computeBBox() {
    const { x, y, lines, textBaseline, textAlign } = this;
    return _Text2.computeBBox(lines, x, y, { font: this, textBaseline, textAlign });
  }
  isPointInPath(x, y) {
    const bbox = this.getBBox();
    return bbox ? bbox.containsPoint(x, y) : false;
  }
  render(renderCtx) {
    const { ctx, stats } = renderCtx;
    if (!this.lines.length || !this.layerManager) {
      if (stats)
        stats.nodesSkipped += 1;
      return super.render(renderCtx);
    }
    const { fill, stroke, strokeWidth } = this;
    const { pixelRatio } = this.layerManager.canvas;
    ctx.font = TextUtils.toFontString(this);
    ctx.textAlign = this.textAlign;
    ctx.textBaseline = this.textBaseline;
    if (fill) {
      this.applyFill(ctx);
      ctx.globalAlpha *= this.opacity * this.fillOpacity;
      const { fillShadow } = this;
      if (fillShadow?.enabled) {
        ctx.shadowColor = fillShadow.color;
        ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio;
        ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio;
        ctx.shadowBlur = fillShadow.blur * pixelRatio;
      }
      this.renderLines((line, x, y) => ctx.fillText(line, x, y));
    }
    if (stroke && strokeWidth) {
      this.applyStroke(ctx);
      ctx.lineWidth = strokeWidth;
      ctx.globalAlpha *= this.opacity * this.strokeOpacity;
      const { lineDash, lineDashOffset, lineCap, lineJoin } = this;
      if (lineDash) {
        ctx.setLineDash(lineDash);
      }
      if (lineDashOffset) {
        ctx.lineDashOffset = lineDashOffset;
      }
      if (lineCap) {
        ctx.lineCap = lineCap;
      }
      if (lineJoin) {
        ctx.lineJoin = lineJoin;
      }
      this.renderLines((line, x, y) => ctx.strokeText(line, x, y));
    }
    super.render(renderCtx);
  }
  renderLines(renderCallback) {
    const { lines, x, y } = this;
    const lineHeight = this.lineHeight ?? TextUtils.getLineHeight(this.fontSize);
    let offsetY = (lineHeight - lineHeight * lines.length) * TextUtils.getVerticalModifier(this.textBaseline);
    for (const line of lines) {
      renderCallback(line, x, y + offsetY);
      offsetY += lineHeight;
    }
  }
  setFont(props) {
    this.fontFamily = props.fontFamily;
    this.fontSize = props.fontSize;
    this.fontStyle = props.fontStyle;
    this.fontWeight = props.fontWeight;
  }
  setAlign(props) {
    this.textAlign = props.textAlign;
    this.textBaseline = props.textBaseline;
  }
  toSVG() {
    if (!this.visible || !this.text)
      return;
    const element2 = document.createElementNS("http://www.w3.org/2000/svg", "text");
    this.applySvgFillAttributes(element2);
    element2.setAttribute("font-family", this.fontFamily?.split(",")[0] ?? "");
    element2.setAttribute("font-size", String(this.fontSize));
    element2.setAttribute("font-style", this.fontStyle ?? "");
    element2.setAttribute("font-weight", String(this.fontWeight ?? ""));
    element2.setAttribute(
      "text-anchor",
      {
        center: "middle",
        left: "start",
        right: "end",
        start: "start",
        end: "end"
      }[this.textAlign ?? "start"]
    );
    element2.setAttribute(
      "alignment-baseline",
      {
        alphabetic: "alphabetic",
        top: "top",
        bottom: "bottom",
        hanging: "hanging",
        middle: "middle",
        ideographic: "ideographic"
      }[this.textBaseline ?? "alphabetic"]
    );
    element2.setAttribute("x", String(this.x));
    element2.setAttribute("y", String(this.y));
    element2.textContent = this.text ?? "";
    return { elements: [element2] };
  }
};
_Text.className = "Text";
_Text.defaultStyles = {
  ...Shape.defaultStyles,
  textAlign: "start",
  fontStyle: void 0,
  fontWeight: void 0,
  fontSize: 10,
  fontFamily: "sans-serif",
  textBaseline: "alphabetic"
};
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "x", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "y", 2);
__decorateClass([
  SceneChangeDetection({ changeCb: (o) => o.onTextChange() })
], _Text.prototype, "text", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "fontStyle", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "fontWeight", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "fontSize", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "fontFamily", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "textAlign", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "textBaseline", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "lineHeight", 2);
var Text = _Text;
var RotatableText = class extends Rotatable(Text) {
};
var TransformableText = class extends Rotatable(Translatable(Text)) {
};
function circleRectOverlap(c, unitCenter, x, y, w, h) {
  if (c.size === 0) {
    return false;
  }
  let cx = c.x;
  let cy = c.y;
  if (unitCenter != null) {
    cx -= (unitCenter.x - 0.5) * c.size;
    cy -= (unitCenter.y - 0.5) * c.size;
  }
  let edgeX = cx;
  if (cx < x) {
    edgeX = x;
  } else if (cx > x + w) {
    edgeX = x + w;
  }
  let edgeY = cy;
  if (cy < y) {
    edgeY = y;
  } else if (cy > y + h) {
    edgeY = y + h;
  }
  const dx = cx - edgeX;
  const dy = cy - edgeY;
  const d = Math.sqrt(dx * dx + dy * dy);
  return d <= c.size * 0.5;
}
function rectRectOverlap(r1, x2, y2, w2, h2) {
  const xOverlap = r1.x + r1.width > x2 && r1.x < x2 + w2;
  const yOverlap = r1.y + r1.height > y2 && r1.y < y2 + h2;
  return xOverlap && yOverlap;
}
function rectContainsRect(r1, r2x, r2y, r2w, r2h) {
  return r2x + r2w < r1.x + r1.width && r2x > r1.x && r2y > r1.y && r2y + r2h < r1.y + r1.height;
}
function isPointLabelDatum(x) {
  return x != null && typeof x.point === "object" && typeof x.label === "object";
}
var labelPlacements = {
  top: { x: 0, y: -1 },
  bottom: { x: 0, y: 1 },
  left: { x: -1, y: 0 },
  right: { x: 1, y: 0 },
  "top-left": { x: -1, y: -1 },
  "top-right": { x: 1, y: -1 },
  "bottom-left": { x: -1, y: 1 },
  "bottom-right": { x: 1, y: 1 }
};
function placeLabels(data, bounds, padding = 5) {
  const result = /* @__PURE__ */ new Map();
  const previousResults = [];
  const sortedDataClone = new Map(
    [...data.entries()].map(([k, d]) => [k, d.toSorted((a, b) => b.point.size - a.point.size)])
  );
  const dataValues = [...sortedDataClone.values()].flat();
  for (const [seriesId, datums] of sortedDataClone.entries()) {
    const labels = [];
    if (!datums[0]?.label)
      continue;
    for (let index = 0, ln = datums.length; index < ln; index++) {
      const d = datums[index];
      const { point, label, marker } = d;
      const { text, width: width2, height: height2 } = label;
      const r = point.size * 0.5;
      let dx = 0;
      let dy = 0;
      if (r > 0 && d.placement != null) {
        const placement = labelPlacements[d.placement];
        dx = (width2 * 0.5 + r + padding) * placement.x;
        dy = (height2 * 0.5 + r + padding) * placement.y;
      }
      const x = point.x - width2 * 0.5 + dx - ((marker?.center.x ?? 0.5) - 0.5) * point.size;
      const y = point.y - height2 * 0.5 + dy - ((marker?.center.y ?? 0.5) - 0.5) * point.size;
      const withinBounds = !bounds || rectContainsRect(bounds, x, y, width2, height2);
      if (!withinBounds)
        continue;
      const overlapPoints = dataValues.some(
        (dataDatum) => circleRectOverlap(dataDatum.point, dataDatum.marker?.center, x, y, width2, height2)
      );
      if (overlapPoints)
        continue;
      const overlapLabels = previousResults.some((pr) => rectRectOverlap(pr, x, y, width2, height2));
      if (overlapLabels)
        continue;
      const resultDatum = { index, text, x, y, width: width2, height: height2, datum: d };
      labels.push(resultDatum);
      previousResults.push(resultDatum);
    }
    result.set(seriesId, labels);
  }
  return result;
}
function axisLabelsOverlap(data, padding = 0) {
  const result = [];
  for (let index = 0; index < data.length; index++) {
    const datum = data[index];
    const {
      point: { x, y },
      label: { text }
    } = datum;
    let { width: width2, height: height2 } = datum.label;
    width2 += padding;
    height2 += padding;
    if (result.some((l) => rectRectOverlap(l, x, y, width2, height2))) {
      return true;
    }
    result.push({ index, text, x, y, width: width2, height: height2, datum });
  }
  return false;
}
function diffArrays(previous, current) {
  const size = Math.max(previous.length, current.length);
  const added = /* @__PURE__ */ new Set();
  const removed = /* @__PURE__ */ new Set();
  for (let i = 0; i < size; i++) {
    const prev = previous[i];
    const curr = current[i];
    if (prev === curr)
      continue;
    if (removed.has(curr)) {
      removed.delete(curr);
    } else if (curr) {
      added.add(curr);
    }
    if (added.has(prev)) {
      added.delete(prev);
    } else if (prev) {
      removed.add(prev);
    }
  }
  return { changed: added.size > 0 || removed.size > 0, added, removed };
}
var defaultNumberFormatter = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2, useGrouping: false });
var percentFormatter = new Intl.NumberFormat("en-US", { style: "percent" });
function formatValue(value, maximumFractionDigits = 2) {
  if (typeof value === "number") {
    return formatNumber(value, maximumFractionDigits);
  }
  return String(value ?? "");
}
function formatPercent(value) {
  return percentFormatter.format(value);
}
function formatNumber(value, maximumFractionDigits) {
  if (maximumFractionDigits === 2) {
    return defaultNumberFormatter.format(value);
  }
  return new Intl.NumberFormat("en-US", { maximumFractionDigits, useGrouping: false }).format(value);
}
var CLASS_INSTANCE_TYPE = "class-instance";
function jsonDiff(source, target, skip) {
  if (isArray(target)) {
    if (!isArray(source) || source.length !== target.length || target.some((v, i) => jsonDiff(source[i], v) != null)) {
      return target;
    }
  } else if (isPlainObject(target)) {
    if (!isPlainObject(source)) {
      return target;
    }
    const result = {};
    const allKeys = /* @__PURE__ */ new Set([
      ...Object.keys(source),
      ...Object.keys(target)
    ]);
    for (const key of allKeys) {
      if (source[key] === target[key] || skip?.includes(key)) {
        continue;
      }
      if (typeof source[key] === typeof target[key]) {
        const diff2 = jsonDiff(source[key], target[key]);
        if (diff2 !== null) {
          result[key] = diff2;
        }
      } else {
        result[key] = target[key];
      }
    }
    return Object.keys(result).length ? result : null;
  } else if (source !== target) {
    return target;
  }
  return null;
}
function jsonPropertyCompare(source, target) {
  for (const key of Object.keys(source)) {
    if (source[key] === target?.[key])
      continue;
    return false;
  }
  return true;
}
function deepClone(source, shallow) {
  if (isArray(source)) {
    return source.map((item) => deepClone(item, shallow));
  }
  if (isPlainObject(source)) {
    return clonePlainObject(source, shallow);
  }
  if (source instanceof Map) {
    return new Map(deepClone(Array.from(source)));
  }
  return shallowClone(source);
}
function clonePlainObject(source, shallow) {
  const target = {};
  for (const key of Object.keys(source)) {
    target[key] = shallow?.has(key) ? shallowClone(source[key]) : deepClone(source[key], shallow);
  }
  return target;
}
function shallowClone(source) {
  if (isArray(source)) {
    return source.slice(0);
  }
  if (isPlainObject(source)) {
    return { ...source };
  }
  if (isDate(source)) {
    return new Date(source);
  }
  if (isRegExp(source)) {
    return new RegExp(source.source, source.flags);
  }
  return source;
}
function jsonWalk(json, visit, skip, parallelJson, ctx) {
  if (isArray(json)) {
    visit(json, parallelJson, ctx);
    let index = 0;
    for (const node of json) {
      jsonWalk(node, visit, skip, parallelJson?.[index], ctx);
      index++;
    }
  } else if (isPlainObject(json)) {
    visit(json, parallelJson, ctx);
    for (const key of Object.keys(json)) {
      if (skip?.has(key)) {
        continue;
      }
      const value = json[key];
      jsonWalk(value, visit, skip, parallelJson?.[key], ctx);
    }
  }
}
function jsonApply(target, source, params = {}) {
  const { path, matcherPath = path?.replace(/(\[[0-9+]+])/i, "[]"), skip = [] } = params;
  if (target == null) {
    throw new Error(`AG Charts - target is uninitialised: ${path ?? "<root>"}`);
  }
  if (source == null) {
    return target;
  }
  if (isProperties(target)) {
    return target.set(source);
  }
  const targetAny = target;
  const targetType = classify(target);
  for (const property of Object.keys(source)) {
    if (SKIP_JS_BUILTINS.has(property))
      continue;
    const propertyMatcherPath = `${matcherPath ? matcherPath + "." : ""}${property}`;
    if (skip.includes(propertyMatcherPath))
      continue;
    const newValue = source[property];
    const propertyPath = `${path ? path + "." : ""}${property}`;
    const targetClass = targetAny.constructor;
    const currentValue = targetAny[property];
    try {
      const currentValueType = classify(currentValue);
      const newValueType = classify(newValue);
      if (targetType === CLASS_INSTANCE_TYPE && !(property in target)) {
        if (newValue === void 0)
          continue;
        Logger.warn(`unable to set [${propertyPath}] in ${targetClass?.name} - property is unknown`);
        continue;
      }
      if (currentValueType != null && newValueType != null && newValueType !== currentValueType && (currentValueType !== CLASS_INSTANCE_TYPE || newValueType !== "object")) {
        Logger.warn(
          `unable to set [${propertyPath}] in ${targetClass?.name} - can't apply type of [${newValueType}], allowed types are: [${currentValueType}]`
        );
        continue;
      }
      if (isProperties(currentValue)) {
        targetAny[property].set(newValue);
      } else if (newValueType === "object") {
        if (currentValue == null) {
          targetAny[property] = {};
        }
        jsonApply(currentValue ?? targetAny[property], newValue, {
          ...params,
          path: propertyPath,
          matcherPath: propertyMatcherPath
        });
      } else {
        targetAny[property] = newValue;
      }
    } catch (error) {
      Logger.warn(`unable to set [${propertyPath}] in [${targetClass?.name}]; nested error is: ${error.message}`);
    }
  }
  return target;
}
function classify(value) {
  if (value == null) {
    return null;
  }
  if (isHtmlElement(value) || isDate(value)) {
    return "primitive";
  }
  if (isArray(value)) {
    return "array";
  }
  if (isObject(value)) {
    return isPlainObject(value) ? "object" : CLASS_INSTANCE_TYPE;
  }
  if (isFunction(value)) {
    return "function";
  }
  return "primitive";
}
function ProxyProperty(proxyPath, configMetadata) {
  const pathArray = isArray(proxyPath) ? proxyPath : proxyPath.split(".");
  if (pathArray.length === 1) {
    const [property] = pathArray;
    return addTransformToInstanceProperty(
      (target, _, value) => target[property] = value,
      (target) => target[property],
      configMetadata
    );
  }
  return addTransformToInstanceProperty(
    (target, _, value) => setPath(target, pathArray, value),
    (target) => getPath(target, pathArray),
    configMetadata
  );
}
function ProxyOnWrite(proxyProperty) {
  return addTransformToInstanceProperty((target, _, value) => target[proxyProperty] = value);
}
function ProxyPropertyOnWrite(childName, childProperty) {
  return addTransformToInstanceProperty((target, key, value) => target[childName][childProperty ?? key] = value);
}
function ActionOnSet(opts) {
  const { newValue: newValueFn, oldValue: oldValueFn, changeValue: changeValueFn } = opts;
  return addTransformToInstanceProperty((target, _, newValue, oldValue) => {
    if (newValue !== oldValue) {
      if (oldValue !== void 0) {
        oldValueFn?.call(target, oldValue);
      }
      if (newValue !== void 0) {
        newValueFn?.call(target, newValue);
      }
      changeValueFn?.call(target, newValue, oldValue);
    }
    return newValue;
  });
}
function ObserveChanges(observerFn) {
  return addObserverToInstanceProperty(observerFn);
}
var debugColor = "color: green";
var debugQuietColor = "color: grey";
function StateMachineProperty() {
  return addObserverToInstanceProperty(() => {
  });
}
function applyProperties(parentState, childState) {
  const childProperties = listDecoratedProperties(childState);
  if (childProperties.length === 0)
    return;
  const properties = extractDecoratedProperties(parentState);
  for (const property of childProperties) {
    if (property in properties) {
      childState[property] = properties[property];
    }
  }
}
var AbstractStateMachine = class {
  transitionRoot(event, data) {
    if (this.parent) {
      this.parent.transitionRoot(event, data);
    } else {
      this.transition(event, data);
    }
  }
};
var _StateMachine = class _StateMachine2 extends AbstractStateMachine {
  constructor(defaultState, states, enterEach) {
    super();
    this.defaultState = defaultState;
    this.states = states;
    this.enterEach = enterEach;
    this.debug = Debug.create(true, "animation");
    this.state = defaultState;
    this.debug(`%c${this.constructor.name} | init -> ${defaultState}`, debugColor);
  }
  // TODO: handle events which do not require data without requiring `undefined` to be passed as as parameter, while
  // also still requiring data to be passed to those events which do require it.
  transition(event, data) {
    const shouldTransitionSelf = this.transitionChild(event, data);
    if (!shouldTransitionSelf || this.state === _StateMachine2.child || this.state === _StateMachine2.parent) {
      return;
    }
    const currentState = this.state;
    const currentStateConfig = this.states[this.state];
    let destination = currentStateConfig[event];
    const debugPrefix = `%c${this.constructor.name} | ${this.state} -> ${event} ->`;
    if (Array.isArray(destination)) {
      destination = destination.find((transition) => {
        if (!transition.guard)
          return true;
        const valid = transition.guard(data);
        if (!valid) {
          this.debug(`${debugPrefix} (guarded)`, transition.target, debugQuietColor);
        }
        return valid;
      });
    } else if (typeof destination === "object" && !(destination instanceof _StateMachine2) && destination.guard && !destination.guard(data)) {
      this.debug(`${debugPrefix} (guarded)`, destination.target, debugQuietColor);
      return;
    }
    if (!destination) {
      this.debug(`${debugPrefix} ${this.state}`, debugQuietColor);
      return;
    }
    const destinationState = this.getDestinationState(destination);
    const exitFn = destinationState === this.state ? void 0 : currentStateConfig.onExit;
    this.debug(`${debugPrefix} ${destinationState}`, debugColor);
    this.state = destinationState;
    if (typeof destination === "function") {
      destination(data);
    } else if (typeof destination === "object" && !(destination instanceof _StateMachine2)) {
      destination.action?.(data);
    }
    exitFn?.();
    this.enterEach?.(currentState, destinationState);
    if (destinationState !== currentState && destinationState !== _StateMachine2.child && destinationState !== _StateMachine2.parent) {
      this.states[destinationState].onEnter?.(currentState, data);
    }
  }
  transitionAsync(event, data) {
    setTimeout(() => {
      this.transition(event, data);
    }, 0);
  }
  is(value) {
    if (this.state === _StateMachine2.child && this.childState) {
      return this.childState.is(value);
    }
    return this.state === value;
  }
  resetHierarchy() {
    this.debug(
      `%c${this.constructor.name} | ${this.state} -> [resetHierarchy] -> ${this.defaultState}`,
      "color: green"
    );
    this.state = this.defaultState;
  }
  transitionChild(event, data) {
    if (this.state !== _StateMachine2.child || !this.childState)
      return true;
    applyProperties(this, this.childState);
    this.childState.transition(event, data);
    if (!this.childState.is(_StateMachine2.parent))
      return true;
    this.debug(`%c${this.constructor.name} | ${this.state} -> ${event} -> ${this.defaultState}`, debugColor);
    this.state = this.defaultState;
    this.states[this.state].onEnter?.();
    this.childState.resetHierarchy();
    return false;
  }
  getDestinationState(destination) {
    let state = this.state;
    if (typeof destination === "string") {
      state = destination;
    } else if (destination instanceof _StateMachine2) {
      this.childState = destination;
      this.childState.parent = this;
      state = _StateMachine2.child;
    } else if (typeof destination === "object") {
      if (destination.target instanceof _StateMachine2) {
        this.childState = destination.target;
        this.childState.parent = this;
        state = _StateMachine2.child;
      } else if (destination.target != null) {
        state = destination.target;
      }
    }
    return state;
  }
};
_StateMachine.child = "__child";
_StateMachine.parent = "__parent";
var StateMachine = _StateMachine;
var ParallelStateMachine = class extends AbstractStateMachine {
  constructor(...stateMachines) {
    super();
    this.stateMachines = stateMachines;
    for (const stateMachine of stateMachines) {
      stateMachine.parent = this;
    }
  }
  transition(event, data) {
    for (const stateMachine of this.stateMachines) {
      applyProperties(this, stateMachine);
      stateMachine.transition(event, data);
    }
  }
  transitionAsync(event, data) {
    for (const stateMachine of this.stateMachines) {
      applyProperties(this, stateMachine);
      stateMachine.transitionAsync(event, data);
    }
  }
};
function createIdsGenerator() {
  const idsCounter = /* @__PURE__ */ new Map();
  return (name) => {
    const counter = idsCounter.get(name);
    if (counter) {
      idsCounter.set(name, counter + 1);
      return `${name}_${counter}`;
    }
    idsCounter.set(name, 1);
    return name;
  };
}
var TextWrapper = class {
  static wrapText(text, options) {
    return this.wrapLines(text, options).join("\n");
  }
  static wrapLines(text, options) {
    const clippedResult = this.textWrap(text, options);
    if (options.overflow === "hide" && clippedResult.some((l) => l.endsWith(TextUtils.EllipsisChar))) {
      return [];
    }
    return clippedResult;
  }
  static appendEllipsis(text) {
    return text.replace(/[.,]{1,5}$/, "") + TextUtils.EllipsisChar;
  }
  static truncateLine(text, measurer, maxWidth, ellipsisForce) {
    const ellipsisWidth = measurer.textWidth(TextUtils.EllipsisChar);
    let estimatedWidth = 0;
    let i = 0;
    for (; i < text.length; i++) {
      const charWidth = measurer.textWidth(text.charAt(i));
      if (estimatedWidth + charWidth > maxWidth)
        break;
      estimatedWidth += charWidth;
    }
    if (text.length === i && (!ellipsisForce || estimatedWidth + ellipsisWidth <= maxWidth)) {
      return ellipsisForce ? text + TextUtils.EllipsisChar : text;
    }
    text = text.slice(0, i).trimEnd();
    while (text.length && measurer.textWidth(text) + ellipsisWidth > maxWidth) {
      text = text.slice(0, -1).trimEnd();
    }
    return text + TextUtils.EllipsisChar;
  }
  static textWrap(text, options) {
    const lines = text.split(TextUtils.lineSplitter);
    const measurer = CachedTextMeasurerPool.getMeasurer(options);
    if (options.textWrap === "never") {
      return lines.map((line) => this.truncateLine(line.trimEnd(), measurer, options.maxWidth));
    }
    const result = [];
    const wrapHyphenate = options.textWrap === "hyphenate";
    const wrapOnSpace = options.textWrap == null || options.textWrap === "on-space";
    for (const untrimmedLine of lines) {
      let line = untrimmedLine.trimEnd();
      if (line === "") {
        result.push(line);
        continue;
      }
      for (let i = 0, estimatedWidth = 0, lastSpaceIndex = 0; i < line.length; i++) {
        const char = line.charAt(i);
        estimatedWidth += measurer.textWidth(char);
        if (char === " ") {
          lastSpaceIndex = i;
        }
        if (estimatedWidth > options.maxWidth) {
          if (i === 0)
            break;
          const actualWidth = measurer.textWidth(line.slice(0, i + 1));
          if (actualWidth <= options.maxWidth) {
            estimatedWidth = actualWidth;
            continue;
          }
          if (lastSpaceIndex) {
            const nextWord = this.getWordAt(line, lastSpaceIndex + 1);
            const textWidth = measurer.textWidth(nextWord);
            if (textWidth <= options.maxWidth) {
              result.push(line.slice(0, lastSpaceIndex).trimEnd());
              line = line.slice(lastSpaceIndex).trimStart();
              i = -1;
              estimatedWidth = 0;
              lastSpaceIndex = 0;
              continue;
            } else if (wrapOnSpace && textWidth > options.maxWidth) {
              result.push(
                line.slice(0, lastSpaceIndex).trimEnd(),
                this.truncateLine(
                  line.slice(lastSpaceIndex).trimStart(),
                  measurer,
                  options.maxWidth,
                  true
                )
              );
            }
          } else if (wrapOnSpace) {
            result.push(this.truncateLine(line, measurer, options.maxWidth, true));
          }
          if (wrapOnSpace) {
            line = "";
            break;
          }
          const postfix = wrapHyphenate ? "-" : "";
          let newLine = line.slice(0, i).trim();
          while (newLine.length && measurer.textWidth(newLine + postfix) > options.maxWidth) {
            newLine = newLine.slice(0, -1).trimEnd();
          }
          result.push(newLine + postfix);
          if (!newLine.length) {
            line = "";
            break;
          }
          line = line.slice(newLine.length).trimStart();
          i = -1;
          estimatedWidth = 0;
          lastSpaceIndex = 0;
        }
      }
      if (line) {
        result.push(line);
      }
    }
    this.avoidOrphans(result, measurer, options);
    return this.clipLines(result, measurer, options);
  }
  static getWordAt(text, position) {
    const nextSpaceIndex = text.indexOf(" ", position);
    return nextSpaceIndex === -1 ? text.slice(position) : text.slice(position, nextSpaceIndex);
  }
  static clipLines(lines, measurer, options) {
    if (!options.maxHeight) {
      return lines;
    }
    const { height: height2, lineMetrics } = measurer.measureLines(lines);
    if (height2 <= options.maxHeight) {
      return lines;
    }
    for (let i = 0, cumulativeHeight = 0; i < lineMetrics.length; i++) {
      const { lineHeight } = lineMetrics[i];
      cumulativeHeight += lineHeight;
      if (cumulativeHeight > options.maxHeight) {
        if (options.overflow === "hide") {
          return [];
        }
        const clippedResults = lines.slice(0, i || 1);
        const lastLine = clippedResults.pop();
        return clippedResults.concat(this.truncateLine(lastLine, measurer, options.maxWidth, true));
      }
    }
    return lines;
  }
  static avoidOrphans(lines, measurer, options) {
    if (options.avoidOrphans === false || lines.length < 2)
      return;
    const { length: length2 } = lines;
    const lastLine = lines[length2 - 1];
    const beforeLast = lines[length2 - 2];
    if (beforeLast.length < lastLine.length)
      return;
    const lastSpaceIndex = beforeLast.lastIndexOf(" ");
    if (lastSpaceIndex === -1 || lastSpaceIndex === beforeLast.indexOf(" ") || lastLine.includes(" "))
      return;
    const lastWord = beforeLast.slice(lastSpaceIndex + 1);
    if (measurer.textWidth(lastLine + lastWord) <= options.maxWidth) {
      lines[length2 - 2] = beforeLast.slice(0, lastSpaceIndex);
      lines[length2 - 1] = lastWord + " " + lastLine;
    }
  }
};
var Caption = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.id = createId(this);
    this.node = new RotatableText({ zIndex: 1 }).setProperties({
      textAlign: "center",
      pointerEvents: 1
      /* None */
    });
    this.enabled = false;
    this.textAlign = "center";
    this.fontSize = 10;
    this.fontFamily = "sans-serif";
    this.wrapping = "always";
    this.padding = 0;
    this.layoutStyle = "block";
    this.truncated = false;
  }
  registerInteraction(moduleCtx, where) {
    return moduleCtx.layoutManager.addListener("layout:complete", () => this.updateA11yText(moduleCtx, where));
  }
  computeTextWrap(containerWidth, containerHeight) {
    const { text, padding, wrapping } = this;
    const maxWidth = Math.min(this.maxWidth ?? Infinity, containerWidth) - padding * 2;
    const maxHeight = this.maxHeight ?? containerHeight - padding * 2;
    if (!isFinite(maxWidth) && !isFinite(maxHeight)) {
      this.node.text = text;
      return;
    }
    const wrappedText = TextWrapper.wrapText(text ?? "", { maxWidth, maxHeight, font: this, textWrap: wrapping });
    this.node.text = wrappedText;
    this.truncated = wrappedText.includes(TextUtils.EllipsisChar);
  }
  updateA11yText(moduleCtx, where) {
    const { proxyInteractionService } = moduleCtx;
    if (this.enabled && this.text) {
      const bbox = Transformable.toCanvas(this.node);
      if (bbox) {
        const { id: domManagerId } = this;
        this.proxyText ?? (this.proxyText = proxyInteractionService.createProxyElement({ type: "text", domManagerId, where }));
        this.proxyText.textContent = this.text;
        this.proxyText.setBounds(bbox);
        this.proxyText.addListener("mousemove", (ev) => this.handleMouseMove(moduleCtx, ev));
        this.proxyText.addListener("mouseleave", (ev) => this.handleMouseLeave(moduleCtx, ev));
      }
    } else {
      this.proxyText?.destroy();
      this.proxyText = void 0;
    }
  }
  handleMouseMove(moduleCtx, event) {
    if (event != null && this.enabled && this.node.visible && this.truncated) {
      const { x, y } = Transformable.toCanvas(this.node);
      const canvasX = event.sourceEvent.offsetX + x;
      const canvasY = event.sourceEvent.offsetY + y;
      const lastPointerEvent = { type: "hover", canvasX, canvasY };
      moduleCtx.tooltipManager.updateTooltip(
        this.id,
        { canvasX, canvasY, lastPointerEvent, showArrow: false },
        { title: this.text }
      );
    }
  }
  handleMouseLeave(moduleCtx, _event) {
    moduleCtx.tooltipManager.removeTooltip(this.id);
  }
};
Caption.SMALL_PADDING = 10;
Caption.LARGE_PADDING = 20;
__decorateClass([
  Validate(BOOLEAN),
  ProxyPropertyOnWrite("node", "visible")
], Caption.prototype, "enabled", 2);
__decorateClass([
  Validate(STRING, { optional: true }),
  ProxyPropertyOnWrite("node")
], Caption.prototype, "text", 2);
__decorateClass([
  Validate(TEXT_ALIGN, { optional: true }),
  ProxyPropertyOnWrite("node")
], Caption.prototype, "textAlign", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true }),
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true }),
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontWeight", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER),
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING),
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontFamily", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true }),
  ProxyPropertyOnWrite("node", "fill")
], Caption.prototype, "color", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], Caption.prototype, "spacing", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], Caption.prototype, "maxWidth", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], Caption.prototype, "maxHeight", 2);
__decorateClass([
  Validate(TEXT_WRAP)
], Caption.prototype, "wrapping", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Caption.prototype, "padding", 2);
__decorateClass([
  Validate(STRING)
], Caption.prototype, "layoutStyle", 2);
var Range = class extends Shape {
  constructor(opts = {}) {
    super(opts);
    this.x1 = 0;
    this.y1 = 0;
    this.x2 = 0;
    this.y2 = 0;
    this.startLine = false;
    this.endLine = false;
    this.isRange = false;
    this.restoreOwnStyles();
  }
  computeBBox() {
    return new BBox(this.x1, this.y1, this.x2 - this.x1, this.y2 - this.y1);
  }
  isPointInPath(_x, _y) {
    return false;
  }
  render(renderCtx) {
    const { ctx } = renderCtx;
    let { x1, y1, x2, y2 } = this;
    x1 = this.align(x1);
    y1 = this.align(y1);
    x2 = this.align(x2);
    y2 = this.align(y2);
    const { fill, opacity, isRange } = this;
    const fillActive = !!(isRange && fill);
    if (fillActive) {
      const { fillOpacity } = this;
      this.applyFill(ctx);
      ctx.globalAlpha = opacity * fillOpacity;
      ctx.beginPath();
      ctx.moveTo(x1, y1);
      ctx.lineTo(x2, y1);
      ctx.lineTo(x2, y2);
      ctx.lineTo(x1, y2);
      ctx.closePath();
      ctx.fill();
    }
    const { stroke, strokeWidth, startLine, endLine } = this;
    const strokeActive = !!((startLine || endLine) && stroke && strokeWidth);
    if (strokeActive) {
      const { strokeOpacity, lineDash, lineDashOffset, lineCap, lineJoin } = this;
      this.applyStroke(ctx);
      ctx.globalAlpha = opacity * strokeOpacity;
      ctx.lineWidth = strokeWidth;
      if (lineDash) {
        ctx.setLineDash(lineDash);
      }
      if (lineDashOffset) {
        ctx.lineDashOffset = lineDashOffset;
      }
      if (lineCap) {
        ctx.lineCap = lineCap;
      }
      if (lineJoin) {
        ctx.lineJoin = lineJoin;
      }
      ctx.beginPath();
      if (startLine) {
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y1);
      }
      if (endLine) {
        ctx.moveTo(x2, y2);
        ctx.lineTo(x1, y2);
      }
      ctx.stroke();
    }
    this.fillShadow?.markClean();
    super.render(renderCtx);
  }
};
Range.className = "Range";
Range.defaultStyles = {
  ...Shape.defaultStyles,
  strokeWidth: 1
};
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "x1", 2);
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "y1", 2);
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "x2", 2);
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "y2", 2);
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "startLine", 2);
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "endLine", 2);
__decorateClass([
  SceneChangeDetection()
], Range.prototype, "isRange", 2);
var Label = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
    this.fontSize = 12;
    this.fontFamily = "Verdana, sans-serif";
  }
  getFont() {
    return TextUtils.toFontString(this);
  }
};
__decorateClass([
  Validate(BOOLEAN)
], Label.prototype, "enabled", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], Label.prototype, "color", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], Label.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], Label.prototype, "fontWeight", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Label.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING)
], Label.prototype, "fontFamily", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], Label.prototype, "formatter", 2);
function calculateLabelRotation(opts) {
  const { parallelFlipRotation = 0, regularFlipRotation = 0 } = opts;
  const configuredRotation = opts.rotation ? normalizeAngle360(toRadians(opts.rotation)) : 0;
  const parallelFlipFlag = !configuredRotation && parallelFlipRotation >= 0 && parallelFlipRotation <= Math.PI ? -1 : 1;
  const regularFlipFlag = !configuredRotation && regularFlipRotation >= 0 && regularFlipRotation <= Math.PI ? -1 : 1;
  let defaultRotation = 0;
  if (opts.parallel) {
    defaultRotation = parallelFlipFlag * Math.PI / 2;
  } else if (regularFlipFlag === -1) {
    defaultRotation = Math.PI;
  }
  return { configuredRotation, defaultRotation, parallelFlipFlag, regularFlipFlag };
}
function getLabelSpacing(minSpacing, rotated) {
  if (!isNaN(minSpacing)) {
    return minSpacing;
  }
  return rotated ? 0 : 10;
}
function getTextBaseline(parallel, labelRotation, sideFlag, parallelFlipFlag) {
  if (parallel && !labelRotation) {
    return sideFlag * parallelFlipFlag === -1 ? "hanging" : "bottom";
  }
  return "middle";
}
function getTextAlign(parallel, labelRotation, labelAutoRotation, sideFlag, regularFlipFlag) {
  const labelRotated = labelRotation > 0 && labelRotation <= Math.PI;
  const labelAutoRotated = labelAutoRotation > 0 && labelAutoRotation <= Math.PI;
  const alignFlag = labelRotated || labelAutoRotated ? -1 : 1;
  if (parallel) {
    if (labelRotation || labelAutoRotation) {
      if (sideFlag * alignFlag === -1) {
        return "end";
      }
    } else {
      return "center";
    }
  } else if (sideFlag * regularFlipFlag === -1) {
    return "end";
  }
  return "start";
}
function createLabelData(tickData, labelX, labelMatrix, textMeasurer) {
  const labelData = [];
  for (const { tickLabel: text, translationY } of tickData) {
    if (!text)
      continue;
    const { width: width2, height: height2 } = textMeasurer.measureLines(text);
    const bbox = new BBox(labelX, translationY, width2, height2);
    const translatedBBox = new BBox(labelX, translationY, 0, 0);
    labelMatrix.transformBBox(translatedBBox, bbox);
    const { x, y } = bbox;
    labelData.push({
      point: { x, y },
      label: { text, width: width2, height: height2 }
    });
  }
  return labelData;
}
function isStringObject(value) {
  return value != null && Object.hasOwn(value, "toString") && isString(value.toString());
}
function isNumberObject(value) {
  return value != null && Object.hasOwn(value, "valueOf") && isFiniteNumber(value.valueOf());
}
function isContinuous(value) {
  return isFiniteNumber(value) || isValidDate(value) || isNumberObject(value);
}
function checkDatum(value, isContinuousScale) {
  return value != null && (!isContinuousScale || isContinuous(value));
}
function transformIntegratedCategoryValue(value) {
  if (isStringObject(value) && Object.hasOwn(value, "id")) {
    return value.id;
  }
  return value;
}
var MATCHING_CROSSLINE_TYPE = (property) => {
  return property === "value" ? predicateWithMessage(
    (_, ctx) => ctx.target["type"] === "line",
    (ctx) => ctx.target["type"] === "range" ? `crossLine type 'range' to have a 'range' property instead of 'value'` : `crossLine property 'type' to be 'line'`
  ) : predicateWithMessage(
    (_, ctx) => ctx.target["type"] === "range",
    (ctx) => ctx.target.type === "line" ? `crossLine type 'line' to have a 'value' property instead of 'range'` : `crossLine property 'type' to be 'range'`
  );
};
var validateCrossLineValues = (type, value, range3, scale2, visibilityCheck) => {
  const lineCrossLine = type === "line" && value !== void 0;
  const rangeCrossLine = type === "range" && range3 !== void 0;
  if (!lineCrossLine && !rangeCrossLine) {
    return true;
  }
  const [start2, end2] = range3 ?? [value, void 0];
  const isContinuous2 = ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2);
  const validStart = checkDatum(start2, isContinuous2) && !isNaN(scale2.convert(start2));
  const validEnd = checkDatum(end2, isContinuous2) && !isNaN(scale2.convert(end2));
  if (lineCrossLine && validStart || rangeCrossLine && validStart && validEnd) {
    return visibilityCheck?.() ?? true;
  }
  const message = [`Expecting crossLine`];
  if (rangeCrossLine) {
    if (!validStart) {
      message.push(`range start ${stringify(start2)}`);
    }
    if (!validEnd) {
      message.push(`${validStart ? "" : "and "}range end ${stringify(end2)}`);
    }
  } else {
    message.push(`value ${stringify(start2)}`);
  }
  message.push(`to match the axis scale domain.`);
  Logger.warnOnce(message.join(" "));
  return false;
};
var horizontalCrosslineTranslationDirections = {
  top: { xTranslationDirection: 0, yTranslationDirection: -1 },
  bottom: { xTranslationDirection: 0, yTranslationDirection: 1 },
  left: { xTranslationDirection: -1, yTranslationDirection: 0 },
  right: { xTranslationDirection: 1, yTranslationDirection: 0 },
  "top-left": { xTranslationDirection: 1, yTranslationDirection: -1 },
  "top-right": { xTranslationDirection: -1, yTranslationDirection: -1 },
  "bottom-left": { xTranslationDirection: 1, yTranslationDirection: 1 },
  "bottom-right": { xTranslationDirection: -1, yTranslationDirection: 1 },
  inside: { xTranslationDirection: 0, yTranslationDirection: 0 },
  "inside-left": { xTranslationDirection: 1, yTranslationDirection: 0 },
  "inside-right": { xTranslationDirection: -1, yTranslationDirection: 0 },
  "inside-top": { xTranslationDirection: 0, yTranslationDirection: 1 },
  "inside-bottom": { xTranslationDirection: 0, yTranslationDirection: -1 },
  "inside-top-left": { xTranslationDirection: 1, yTranslationDirection: 1 },
  "inside-bottom-left": { xTranslationDirection: 1, yTranslationDirection: -1 },
  "inside-top-right": { xTranslationDirection: -1, yTranslationDirection: 1 },
  "inside-bottom-right": { xTranslationDirection: -1, yTranslationDirection: -1 }
};
var verticalCrossLineTranslationDirections = {
  top: { xTranslationDirection: 1, yTranslationDirection: 0 },
  bottom: { xTranslationDirection: -1, yTranslationDirection: 0 },
  left: { xTranslationDirection: 0, yTranslationDirection: -1 },
  right: { xTranslationDirection: 0, yTranslationDirection: 1 },
  "top-left": { xTranslationDirection: -1, yTranslationDirection: -1 },
  "top-right": { xTranslationDirection: -1, yTranslationDirection: 1 },
  "bottom-left": { xTranslationDirection: 1, yTranslationDirection: -1 },
  "bottom-right": { xTranslationDirection: 1, yTranslationDirection: 1 },
  inside: { xTranslationDirection: 0, yTranslationDirection: 0 },
  "inside-left": { xTranslationDirection: 0, yTranslationDirection: 1 },
  "inside-right": { xTranslationDirection: 0, yTranslationDirection: -1 },
  "inside-top": { xTranslationDirection: -1, yTranslationDirection: 0 },
  "inside-bottom": { xTranslationDirection: 1, yTranslationDirection: 0 },
  "inside-top-left": { xTranslationDirection: -1, yTranslationDirection: 1 },
  "inside-bottom-left": { xTranslationDirection: 1, yTranslationDirection: 1 },
  "inside-top-right": { xTranslationDirection: -1, yTranslationDirection: -1 },
  "inside-bottom-right": { xTranslationDirection: 1, yTranslationDirection: -1 }
};
function calculateLabelTranslation({
  yDirection,
  padding = 0,
  position = "top",
  bbox
}) {
  const crossLineTranslationDirections = yDirection ? horizontalCrosslineTranslationDirections : verticalCrossLineTranslationDirections;
  const { xTranslationDirection, yTranslationDirection } = crossLineTranslationDirections[position];
  const xTranslation = xTranslationDirection * (padding + bbox.width / 2);
  const yTranslation = yTranslationDirection * (padding + bbox.height / 2);
  return {
    xTranslation,
    yTranslation
  };
}
function calculateLabelChartPadding({
  yDirection,
  bbox,
  padding = 0,
  position = "top"
}) {
  const chartPadding = {};
  if (position.startsWith("inside"))
    return chartPadding;
  if (position === "top" && !yDirection) {
    chartPadding.top = padding + bbox.height;
  } else if (position === "bottom" && !yDirection) {
    chartPadding.bottom = padding + bbox.height;
  } else if (position === "left" && yDirection) {
    chartPadding.left = padding + bbox.width;
  } else if (position === "right" && yDirection) {
    chartPadding.right = padding + bbox.width;
  }
  return chartPadding;
}
var POSITION_TOP_COORDINATES = ({ direction, xEnd, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xEnd / 2, y: yStart };
  } else {
    return { x: xEnd, y: isNaN(yEnd) ? yStart : (yStart + yEnd) / 2 };
  }
};
var POSITION_LEFT_COORDINATES = ({ direction, xStart, xEnd, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xStart, y: isNaN(yEnd) ? yStart : (yStart + yEnd) / 2 };
  } else {
    return { x: xEnd / 2, y: yStart };
  }
};
var POSITION_RIGHT_COORDINATES = ({ direction, xEnd, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xEnd, y: isNaN(yEnd) ? yStart : (yStart + yEnd) / 2 };
  } else {
    return { x: xEnd / 2, y: isNaN(yEnd) ? yStart : yEnd };
  }
};
var POSITION_BOTTOM_COORDINATES = ({ direction, xStart, xEnd, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xEnd / 2, y: isNaN(yEnd) ? yStart : yEnd };
  } else {
    return { x: xStart, y: isNaN(yEnd) ? yStart : (yStart + yEnd) / 2 };
  }
};
var POSITION_INSIDE_COORDINATES = ({ xEnd, yStart, yEnd }) => {
  return { x: xEnd / 2, y: isNaN(yEnd) ? yStart : (yStart + yEnd) / 2 };
};
var POSITION_TOP_LEFT_COORDINATES = ({ direction, xStart, xEnd, yStart }) => {
  if (direction === "y") {
    return { x: xStart / 2, y: yStart };
  } else {
    return { x: xEnd, y: yStart };
  }
};
var POSITION_BOTTOM_LEFT_COORDINATES = ({ direction, xStart, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xStart, y: isNaN(yEnd) ? yStart : yEnd };
  } else {
    return { x: xStart, y: yStart };
  }
};
var POSITION_TOP_RIGHT_COORDINATES = ({ direction, xEnd, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xEnd, y: yStart };
  } else {
    return { x: xEnd, y: isNaN(yEnd) ? yStart : yEnd };
  }
};
var POSITION_BOTTOM_RIGHT_COORDINATES = ({ direction, xStart, xEnd, yStart, yEnd }) => {
  if (direction === "y") {
    return { x: xEnd, y: isNaN(yEnd) ? yStart : yEnd };
  } else {
    return { x: xStart, y: isNaN(yEnd) ? yStart : yEnd };
  }
};
var labelDirectionHandling = {
  top: { c: POSITION_TOP_COORDINATES },
  bottom: { c: POSITION_BOTTOM_COORDINATES },
  left: { c: POSITION_LEFT_COORDINATES },
  right: { c: POSITION_RIGHT_COORDINATES },
  "top-left": { c: POSITION_TOP_LEFT_COORDINATES },
  "top-right": { c: POSITION_TOP_RIGHT_COORDINATES },
  "bottom-left": { c: POSITION_BOTTOM_LEFT_COORDINATES },
  "bottom-right": { c: POSITION_BOTTOM_RIGHT_COORDINATES },
  inside: { c: POSITION_INSIDE_COORDINATES },
  "inside-left": { c: POSITION_LEFT_COORDINATES },
  "inside-right": { c: POSITION_RIGHT_COORDINATES },
  "inside-top": { c: POSITION_TOP_COORDINATES },
  "inside-bottom": { c: POSITION_BOTTOM_COORDINATES },
  "inside-top-left": { c: POSITION_TOP_LEFT_COORDINATES },
  "inside-bottom-left": { c: POSITION_BOTTOM_LEFT_COORDINATES },
  "inside-top-right": { c: POSITION_TOP_RIGHT_COORDINATES },
  "inside-bottom-right": { c: POSITION_BOTTOM_RIGHT_COORDINATES }
};
var CROSSLINE_LABEL_POSITION = UNION(
  [
    "top",
    "left",
    "right",
    "bottom",
    "top-left",
    "top-right",
    "bottom-left",
    "bottom-right",
    "inside",
    "inside-left",
    "inside-right",
    "inside-top",
    "inside-bottom",
    "inside-top-left",
    "inside-bottom-left",
    "inside-top-right",
    "inside-bottom-right"
  ],
  "crossLine label position"
);
var CartesianCrossLineLabel = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.fontSize = 14;
    this.fontFamily = "Verdana, sans-serif";
    this.padding = 5;
    this.color = "rgba(87, 87, 87, 1)";
  }
};
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], CartesianCrossLineLabel.prototype, "enabled", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], CartesianCrossLineLabel.prototype, "text", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], CartesianCrossLineLabel.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], CartesianCrossLineLabel.prototype, "fontWeight", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], CartesianCrossLineLabel.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING)
], CartesianCrossLineLabel.prototype, "fontFamily", 2);
__decorateClass([
  Validate(NUMBER)
], CartesianCrossLineLabel.prototype, "padding", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], CartesianCrossLineLabel.prototype, "color", 2);
__decorateClass([
  Validate(CROSSLINE_LABEL_POSITION, { optional: true })
], CartesianCrossLineLabel.prototype, "position", 2);
__decorateClass([
  Validate(NUMBER, { optional: true })
], CartesianCrossLineLabel.prototype, "rotation", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], CartesianCrossLineLabel.prototype, "parallel", 2);
var CartesianCrossLine = class extends BaseProperties {
  constructor() {
    super();
    this.id = createId(this);
    this.label = new CartesianCrossLineLabel();
    this.scale = void 0;
    this.clippedRange = [-Infinity, Infinity];
    this.gridLength = 0;
    this.sideFlag = -1;
    this.parallelFlipRotation = 0;
    this.regularFlipRotation = 0;
    this.direction = "x";
    this.rangeGroup = new Group({ name: this.id });
    this.lineGroup = new Group({ name: this.id });
    this.labelGroup = new Group({ name: this.id });
    this.crossLineRange = new Range();
    this.crossLineLabel = new TransformableText();
    this.labelPoint = void 0;
    this.data = [];
    this.startLine = false;
    this.endLine = false;
    this.isRange = false;
    this._isRange = void 0;
    this.lineGroup.append(this.crossLineRange);
    this.labelGroup.append(this.crossLineLabel);
    this.crossLineRange.pointerEvents = 1;
  }
  update(visible) {
    const { enabled, data, type, value, range: range3, scale: scale2 } = this;
    if (!type || !scale2 || !enabled || !visible || !validateCrossLineValues(type, value, range3, scale2) || data.length === 0) {
      this.rangeGroup.visible = false;
      this.lineGroup.visible = false;
      this.labelGroup.visible = false;
      return;
    }
    this.rangeGroup.visible = visible;
    this.lineGroup.visible = visible;
    this.labelGroup.visible = visible;
    this.updateNodes();
    const { isRange } = this;
    if (isRange !== this._isRange) {
      if (isRange) {
        this.rangeGroup.appendChild(this.crossLineRange);
      } else {
        this.lineGroup.appendChild(this.crossLineRange);
      }
    }
    this._isRange = isRange;
  }
  calculateLayout(visible, reversedAxis) {
    if (!visible)
      return;
    const {
      scale: scale2,
      gridLength,
      sideFlag,
      direction,
      label: { position = "top" },
      clippedRange,
      strokeWidth = 0
    } = this;
    this.data = [];
    if (!scale2)
      return;
    const bandwidth = scale2.bandwidth ?? 0;
    const step = scale2.step ?? 0;
    const padding = (reversedAxis ? -1 : 1) * (scale2 instanceof BandScale ? (step - bandwidth) / 2 : 0);
    const [xStart, xEnd] = [0, sideFlag * gridLength];
    let [yStart, yEnd] = this.getRange();
    const ordinalTimeScalePadding = yEnd === void 0 && OrdinalTimeScale.is(scale2) ? bandwidth / 2 + padding : 0;
    let [clampedYStart, clampedYEnd] = [
      Number(scale2.convert(yStart, true)) - padding + ordinalTimeScalePadding,
      scale2.convert(yEnd, true) + bandwidth + padding
    ];
    clampedYStart = clampArray(clampedYStart, clippedRange);
    clampedYEnd = clampArray(clampedYEnd, clippedRange);
    [yStart, yEnd] = [Number(scale2.convert(yStart)) + ordinalTimeScalePadding, scale2.convert(yEnd) + bandwidth];
    const validRange = (yStart === clampedYStart || yEnd === clampedYEnd || clampedYStart !== clampedYEnd) && Math.abs(clampedYEnd - clampedYStart) > 0;
    if (validRange && clampedYStart > clampedYEnd) {
      [clampedYStart, clampedYEnd] = [clampedYEnd, clampedYStart];
      [yStart, yEnd] = [yEnd, yStart];
    }
    if (yStart - padding >= clampedYStart)
      yStart -= padding;
    if (yEnd + padding <= clampedYEnd)
      yEnd += padding;
    this.isRange = validRange;
    this.startLine = strokeWidth > 0 && yStart >= clampedYStart && yStart <= clampedYStart + padding;
    this.endLine = strokeWidth > 0 && yEnd >= clampedYEnd - bandwidth - padding && yEnd <= clampedYEnd;
    if (!validRange && !this.startLine && !this.endLine)
      return;
    this.data = [clampedYStart, clampedYEnd];
    if (!this.label.enabled)
      return;
    const { c = POSITION_TOP_COORDINATES } = labelDirectionHandling[position] ?? {};
    const { x: labelX, y: labelY } = c({
      direction,
      xStart,
      xEnd,
      yStart: clampedYStart,
      yEnd: clampedYEnd
    });
    this.labelPoint = {
      x: labelX,
      y: labelY
    };
  }
  updateNodes() {
    this.updateRangeNode();
    if (this.label.enabled) {
      this.updateLabel();
      this.positionLabel();
    }
  }
  updateRangeNode() {
    const {
      crossLineRange,
      sideFlag,
      gridLength,
      data,
      startLine,
      endLine,
      isRange,
      fill,
      fillOpacity,
      stroke,
      strokeWidth,
      lineDash
    } = this;
    crossLineRange.x1 = 0;
    crossLineRange.x2 = sideFlag * gridLength;
    crossLineRange.y1 = data[0];
    crossLineRange.y2 = data[1];
    crossLineRange.startLine = startLine;
    crossLineRange.endLine = endLine;
    crossLineRange.isRange = isRange;
    crossLineRange.fill = fill;
    crossLineRange.fillOpacity = fillOpacity ?? 1;
    crossLineRange.stroke = stroke;
    crossLineRange.strokeWidth = strokeWidth ?? 1;
    crossLineRange.strokeOpacity = this.strokeOpacity ?? 1;
    crossLineRange.lineDash = lineDash;
  }
  updateLabel() {
    const { crossLineLabel, label } = this;
    if (!label.text)
      return;
    crossLineLabel.fontStyle = label.fontStyle;
    crossLineLabel.fontWeight = label.fontWeight;
    crossLineLabel.fontSize = label.fontSize;
    crossLineLabel.fontFamily = label.fontFamily;
    crossLineLabel.fill = label.color;
    crossLineLabel.text = label.text;
  }
  positionLabel() {
    const {
      crossLineLabel,
      labelPoint: { x = void 0, y = void 0 } = {},
      label: { parallel, rotation, position = "top", padding = 0 },
      direction,
      parallelFlipRotation,
      regularFlipRotation
    } = this;
    if (x === void 0 || y === void 0)
      return;
    const { defaultRotation, configuredRotation } = calculateLabelRotation({
      rotation,
      parallel,
      regularFlipRotation,
      parallelFlipRotation
    });
    crossLineLabel.rotation = defaultRotation + configuredRotation;
    crossLineLabel.textBaseline = "middle";
    crossLineLabel.textAlign = "center";
    const bbox = crossLineLabel.getBBox();
    if (!bbox)
      return;
    const yDirection = direction === "y";
    const { xTranslation, yTranslation } = calculateLabelTranslation({
      yDirection,
      padding,
      position,
      bbox
    });
    crossLineLabel.translationX = x + xTranslation;
    crossLineLabel.translationY = y + yTranslation;
  }
  getRange() {
    const { value, range: range3, scale: scale2 } = this;
    const isContinuous2 = ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2);
    const start2 = range3?.[0] ?? value;
    let end2 = range3?.[1];
    if (!isContinuous2 && end2 === void 0) {
      end2 = start2;
    }
    if (isContinuous2 && start2 === end2) {
      end2 = void 0;
    }
    return [start2, end2];
  }
  computeLabelBBox() {
    const { label } = this;
    if (!label.enabled)
      return;
    const tempText = new TransformableText();
    tempText.fontFamily = label.fontFamily;
    tempText.fontSize = label.fontSize;
    tempText.fontStyle = label.fontStyle;
    tempText.fontWeight = label.fontWeight;
    tempText.text = label.text;
    const {
      labelPoint: { x = void 0, y = void 0 } = {},
      label: { parallel, rotation, position = "top", padding = 0 },
      direction,
      parallelFlipRotation,
      regularFlipRotation
    } = this;
    if (x === void 0 || y === void 0)
      return;
    const { configuredRotation } = calculateLabelRotation({
      rotation,
      parallel,
      regularFlipRotation,
      parallelFlipRotation
    });
    tempText.rotation = configuredRotation;
    tempText.textBaseline = "middle";
    tempText.textAlign = "center";
    const bbox = tempText.getBBox();
    if (!bbox)
      return;
    const yDirection = direction === "y";
    const { xTranslation, yTranslation } = calculateLabelTranslation({
      yDirection,
      padding,
      position,
      bbox
    });
    tempText.x = x + xTranslation;
    tempText.y = y + yTranslation;
    return tempText.getBBox();
  }
  calculatePadding(padding) {
    const {
      isRange,
      startLine,
      endLine,
      direction,
      label: { padding: labelPadding = 0, position = "top" }
    } = this;
    if (!isRange && !startLine && !endLine)
      return;
    const crossLineLabelBBox = this.computeLabelBBox();
    if (crossLineLabelBBox?.x == null || crossLineLabelBBox?.y == null)
      return;
    const chartPadding = calculateLabelChartPadding({
      yDirection: direction === "y",
      padding: labelPadding,
      position,
      bbox: crossLineLabelBBox
    });
    padding.left = Math.max(padding.left ?? 0, chartPadding.left ?? 0);
    padding.right = Math.max(padding.right ?? 0, chartPadding.right ?? 0);
    padding.top = Math.max(padding.top ?? 0, chartPadding.top ?? 0);
    padding.bottom = Math.max(padding.bottom ?? 0, chartPadding.bottom ?? 0);
  }
};
CartesianCrossLine.className = "CrossLine";
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], CartesianCrossLine.prototype, "enabled", 2);
__decorateClass([
  Validate(UNION(["range", "line"], "a crossLine type"), { optional: true })
], CartesianCrossLine.prototype, "type", 2);
__decorateClass([
  Validate(AND(MATCHING_CROSSLINE_TYPE("range"), ARRAY.restrict({ length: 2 })), {
    optional: true
  })
], CartesianCrossLine.prototype, "range", 2);
__decorateClass([
  Validate(MATCHING_CROSSLINE_TYPE("value"), { optional: true })
], CartesianCrossLine.prototype, "value", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], CartesianCrossLine.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], CartesianCrossLine.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], CartesianCrossLine.prototype, "stroke", 2);
__decorateClass([
  Validate(NUMBER, { optional: true })
], CartesianCrossLine.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], CartesianCrossLine.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH, { optional: true })
], CartesianCrossLine.prototype, "lineDash", 2);
__decorateClass([
  Validate(OBJECT)
], CartesianCrossLine.prototype, "label", 2);
var ZIndexMap = /* @__PURE__ */ ((ZIndexMap2) => {
  ZIndexMap2[ZIndexMap2["CHART_BACKGROUND"] = 0] = "CHART_BACKGROUND";
  ZIndexMap2[ZIndexMap2["AXIS_GRID"] = 1] = "AXIS_GRID";
  ZIndexMap2[ZIndexMap2["AXIS"] = 2] = "AXIS";
  ZIndexMap2[ZIndexMap2["SERIES_CROSSLINE_RANGE"] = 3] = "SERIES_CROSSLINE_RANGE";
  ZIndexMap2[ZIndexMap2["SERIES_LAYER"] = 4] = "SERIES_LAYER";
  ZIndexMap2[ZIndexMap2["AXIS_FOREGROUND"] = 5] = "AXIS_FOREGROUND";
  ZIndexMap2[ZIndexMap2["SERIES_CROSSHAIR"] = 6] = "SERIES_CROSSHAIR";
  ZIndexMap2[ZIndexMap2["SERIES_CROSSLINE_LINE"] = 7] = "SERIES_CROSSLINE_LINE";
  ZIndexMap2[ZIndexMap2["SERIES_ANNOTATION"] = 8] = "SERIES_ANNOTATION";
  ZIndexMap2[ZIndexMap2["CHART_ANNOTATION"] = 9] = "CHART_ANNOTATION";
  ZIndexMap2[ZIndexMap2["CHART_ANNOTATION_FOCUSED"] = 10] = "CHART_ANNOTATION_FOCUSED";
  ZIndexMap2[ZIndexMap2["STATUS_BAR"] = 11] = "STATUS_BAR";
  ZIndexMap2[ZIndexMap2["SERIES_LABEL"] = 12] = "SERIES_LABEL";
  ZIndexMap2[ZIndexMap2["LEGEND"] = 13] = "LEGEND";
  ZIndexMap2[ZIndexMap2["NAVIGATOR"] = 14] = "NAVIGATOR";
  ZIndexMap2[ZIndexMap2["FOREGROUND"] = 15] = "FOREGROUND";
  return ZIndexMap2;
})(ZIndexMap || {});
var GRID_STYLE_KEYS = ["stroke", "lineDash"];
var GRID_STYLE = ARRAY_OF(
  (value) => isObject(value) && Object.keys(value).every((key) => GRID_STYLE_KEYS.includes(key)),
  "objects with gridline style properties such as 'stroke' or 'lineDash'"
);
var AxisGridLine = class {
  constructor() {
    this.enabled = true;
    this.width = 1;
    this.style = [
      {
        stroke: void 0,
        lineDash: []
      }
    ];
  }
};
__decorateClass([
  Validate(BOOLEAN)
], AxisGridLine.prototype, "enabled", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AxisGridLine.prototype, "width", 2);
__decorateClass([
  Validate(GRID_STYLE)
], AxisGridLine.prototype, "style", 2);
function Default(defaultValue, replaces = [void 0]) {
  return addTransformToInstanceProperty((_, __, v) => {
    if (replaces.includes(v)) {
      return isFunction(defaultValue) ? defaultValue(v) : defaultValue;
    }
    return v;
  });
}
var time_exports = {};
__export(time_exports, {
  TimeInterval: () => TimeInterval,
  day: () => day,
  friday: () => friday,
  hour: () => hour,
  millisecond: () => millisecond,
  minute: () => minute,
  monday: () => monday,
  month: () => month,
  saturday: () => saturday,
  second: () => second,
  sunday: () => sunday,
  thursday: () => thursday,
  tuesday: () => tuesday,
  utcDay: () => utcDay,
  utcHour: () => utcHour,
  utcMinute: () => utcMinute,
  utcMonth: () => utcMonth,
  utcYear: () => utcYear,
  wednesday: () => wednesday,
  year: () => year
});
function encode8(date) {
  return Math.floor(date.getTime() / durationMinute);
}
function decode8(encoded) {
  return new Date(encoded * durationMinute);
}
var utcMinute = new CountableTimeInterval(encode8, decode8);
function encode9(date) {
  return Math.floor(date.getTime() / durationHour);
}
function decode9(encoded) {
  return new Date(encoded * durationHour);
}
var utcHour = new CountableTimeInterval(encode9, decode9);
function encode10(date) {
  return Math.floor(date.getTime() / durationDay);
}
function decode10(encoded) {
  const d = /* @__PURE__ */ new Date(0);
  d.setUTCDate(d.getUTCDate() + encoded);
  d.setUTCHours(0, 0, 0, 0);
  return d;
}
var utcDay = new CountableTimeInterval(encode10, decode10);
function encode11(date) {
  return date.getUTCFullYear() * 12 + date.getUTCMonth();
}
function decode11(encoded) {
  const year2 = Math.floor(encoded / 12);
  const month2 = encoded - year2 * 12;
  return new Date(Date.UTC(year2, month2, 1));
}
var utcMonth = new CountableTimeInterval(encode11, decode11);
function encode12(date) {
  return date.getUTCFullYear();
}
function decode12(encoded) {
  const d = /* @__PURE__ */ new Date();
  d.setUTCFullYear(encoded);
  d.setUTCMonth(0, 1);
  d.setUTCHours(0, 0, 0, 0);
  return d;
}
var utcYear = new CountableTimeInterval(encode12, decode12);
var TICK_INTERVAL = predicateWithMessage(
  (value) => isFiniteNumber(value) && value > 0 || value instanceof TimeInterval,
  `a non-zero positive Number value or, for a time axis, a Time Interval such as 'agCharts.time.month'`
);
var AxisInterval = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.minSpacing = NaN;
    this.maxSpacing = NaN;
  }
};
__decorateClass([
  Validate(TICK_INTERVAL, { optional: true })
], AxisInterval.prototype, "step", 2);
__decorateClass([
  Validate(ARRAY, { optional: true })
], AxisInterval.prototype, "values", 2);
__decorateClass([
  Validate(MIN_SPACING),
  Default(NaN)
], AxisInterval.prototype, "minSpacing", 2);
__decorateClass([
  Validate(MAX_SPACING),
  Default(NaN)
], AxisInterval.prototype, "maxSpacing", 2);
var AxisLabel = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
    this.fontSize = 12;
    this.fontFamily = "Verdana, sans-serif";
    this.spacing = 5;
    this.minSpacing = NaN;
    this.color = "#575757";
    this.avoidCollisions = true;
    this.mirrored = false;
    this.parallel = false;
  }
  /**
   * The side of the axis line to position the labels on.
   * -1 = left (default)
   * 1 = right
   */
  getSideFlag() {
    return this.mirrored ? 1 : -1;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], AxisLabel.prototype, "enabled", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], AxisLabel.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], AxisLabel.prototype, "fontWeight", 2);
__decorateClass([
  Validate(NUMBER.restrict({ min: 1 }))
], AxisLabel.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING)
], AxisLabel.prototype, "fontFamily", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AxisLabel.prototype, "spacing", 2);
__decorateClass([
  Validate(NUMBER_OR_NAN),
  Default(NaN)
], AxisLabel.prototype, "minSpacing", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], AxisLabel.prototype, "color", 2);
__decorateClass([
  Validate(NUMBER, { optional: true })
], AxisLabel.prototype, "rotation", 2);
__decorateClass([
  Validate(BOOLEAN)
], AxisLabel.prototype, "avoidCollisions", 2);
__decorateClass([
  Validate(BOOLEAN)
], AxisLabel.prototype, "mirrored", 2);
__decorateClass([
  Validate(BOOLEAN)
], AxisLabel.prototype, "parallel", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], AxisLabel.prototype, "itemStyler", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], AxisLabel.prototype, "formatter", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], AxisLabel.prototype, "format", 2);
var AxisLine = class {
  constructor() {
    this.enabled = true;
    this.width = 1;
    this.stroke = void 0;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], AxisLine.prototype, "enabled", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AxisLine.prototype, "width", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], AxisLine.prototype, "stroke", 2);
var AxisTick = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
    this.width = 1;
    this.size = 6;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], AxisTick.prototype, "enabled", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AxisTick.prototype, "width", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AxisTick.prototype, "size", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], AxisTick.prototype, "stroke", 2);
var AxisTitle = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.caption = new Caption();
    this.enabled = false;
    this.spacing = Caption.SMALL_PADDING;
    this.fontSize = 10;
    this.fontFamily = "sans-serif";
    this.wrapping = "always";
  }
};
__decorateClass([
  Validate(BOOLEAN)
], AxisTitle.prototype, "enabled", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], AxisTitle.prototype, "text", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], AxisTitle.prototype, "spacing", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], AxisTitle.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], AxisTitle.prototype, "fontWeight", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AxisTitle.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING)
], AxisTitle.prototype, "fontFamily", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], AxisTitle.prototype, "color", 2);
__decorateClass([
  Validate(TEXT_WRAP)
], AxisTitle.prototype, "wrapping", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], AxisTitle.prototype, "formatter", 2);
function prepareAxisAnimationContext(axis) {
  const [requestedRangeMin, requestedRangeMax] = findMinMax(axis.range);
  const min = Math.floor(requestedRangeMin);
  const max = Math.ceil(requestedRangeMax);
  return { min, max, visible: min !== max };
}
var fullCircle = Math.PI * 2;
var halfCircle = fullCircle / 2;
function normaliseEndRotation(start2, end2) {
  const directDistance = Math.abs(end2 - start2);
  if (directDistance < halfCircle) {
    return end2;
  } else if (start2 > end2) {
    return end2 + fullCircle;
  }
  return end2 - fullCircle;
}
function prepareAxisAnimationFunctions(ctx) {
  const outOfBounds = (y, range3) => {
    const [min = ctx.min, max = ctx.max] = findMinMax(range3 ?? []);
    return y < min || y > max;
  };
  const tick = {
    fromFn(node, datum, status) {
      let y = node.y1 + node.translationY;
      let opacity = node.opacity;
      if (status === "added" || outOfBounds(node.datum.translationY, node.datum.range)) {
        y = datum.translationY;
        opacity = 0;
      }
      return { y: 0, translationY: y, opacity, phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[status] };
    },
    toFn(_node, datum, status) {
      const y = datum.translationY;
      let opacity = 1;
      if (status === "removed") {
        opacity = 0;
      }
      return {
        y: 0,
        translationY: y,
        opacity,
        finish: {
          // Set explicit y after animation so it's pixel aligned
          y,
          translationY: 0
        }
      };
    },
    applyFn(node, props) {
      node.setProperties(props);
      node.visible = !outOfBounds(node.y);
    }
  };
  const label = {
    fromFn(node, newDatum, status) {
      const datum = node.previousDatum ?? newDatum;
      const x = datum.x;
      const y = datum.y;
      const rotationCenterX = datum.rotationCenterX;
      let translationY = Math.round(node.translationY);
      let rotation = datum.rotation;
      let opacity = node.opacity;
      if (status === "removed" || outOfBounds(datum.y, datum.range)) {
        rotation = newDatum.rotation;
      } else if (status === "added" || outOfBounds(node.datum.y, node.datum.range)) {
        translationY = Math.round(datum.translationY);
        opacity = 0;
        rotation = newDatum.rotation;
      }
      return {
        x,
        y,
        rotationCenterX,
        translationY,
        rotation,
        opacity,
        phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[status]
      };
    },
    toFn(node, datum, status) {
      const x = datum.x;
      const y = datum.y;
      const rotationCenterX = datum.rotationCenterX;
      const translationY = Math.round(datum.translationY);
      let rotation = 0;
      let opacity = 1;
      if (status === "added") {
        rotation = datum.rotation;
      } else if (status === "removed") {
        opacity = 0;
        rotation = datum.rotation;
      } else {
        rotation = normaliseEndRotation(node.previousDatum?.rotation ?? datum.rotation, datum.rotation);
      }
      return { x, y, rotationCenterX, translationY, rotation, opacity, finish: { rotation: datum.rotation } };
    }
  };
  const line = {
    fromFn(node, datum) {
      return {
        ...node.previousDatum ?? datum,
        phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING["updated"]
      };
    },
    toFn(_node, datum) {
      return { ...datum };
    }
  };
  const group = {
    fromFn(node, _datum) {
      const { rotation, translationX, translationY } = node;
      return {
        rotation,
        translationX,
        translationY,
        phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING["updated"]
      };
    },
    toFn(_node, datum) {
      const { rotation, translationX, translationY } = datum;
      return {
        rotation,
        translationX,
        translationY
      };
    }
  };
  return { tick, line, label, group };
}
function resetAxisGroupFn() {
  return (_node, datum) => {
    return {
      rotation: datum.rotation,
      rotationCenterX: datum.rotationCenterX,
      rotationCenterY: datum.rotationCenterY,
      translationX: datum.translationX,
      translationY: datum.translationY
    };
  };
}
function resetAxisSelectionFn(ctx) {
  const { visible: rangeVisible, min, max } = ctx;
  return (_node, datum) => {
    const y = datum.translationY;
    const visible = rangeVisible && y >= min && y <= max;
    return {
      y,
      translationY: 0,
      opacity: 1,
      visible
    };
  };
}
function resetAxisLabelSelectionFn() {
  return (_node, datum) => {
    return {
      x: datum.x,
      y: datum.y,
      translationY: datum.translationY,
      rotation: datum.rotation,
      rotationCenterX: datum.rotationCenterX
    };
  };
}
function resetAxisLineSelectionFn() {
  return (_node, datum) => {
    return { ...datum };
  };
}
var NO_LABELS_AND_TICKS = Object.freeze({
  tickData: { ticks: [], rawTicks: [], labelCount: 0, fractionDigits: 0 },
  combinedRotation: 0,
  textAlign: "center",
  textBaseline: "bottom",
  labelData: []
});
var TranslatableLine = class extends Translatable(Line) {
};
var _Axis = class _Axis2 {
  constructor(moduleCtx, scale2) {
    this.moduleCtx = moduleCtx;
    this.scale = scale2;
    this.id = createId(this);
    this.nice = true;
    this.reverse = false;
    this.keys = [];
    this.interval = new AxisInterval();
    this.dataDomain = { domain: [], clipped: false };
    this.layoutConstraints = {
      stacked: true,
      align: "start",
      width: 100,
      unit: "percent"
    };
    this.boundSeries = [];
    this.includeInvisibleDomains = false;
    this.interactionEnabled = true;
    this.axisGroup = new TransformableGroup({ name: `${this.id}-axis` });
    this.tickLineGroup = this.axisGroup.appendChild(new Group({ name: `${this.id}-Axis-tick-lines` }));
    this.lineNode = this.axisGroup.appendChild(new TranslatableLine({ name: `${this.id}-Axis-line` }));
    this.tickLabelGroup = this.axisGroup.appendChild(new Group({ name: `${this.id}-Axis-tick-labels` }));
    this.labelGroup = new Group({
      name: `${this.id}-Labels`,
      zIndex: 8
      /* SERIES_ANNOTATION */
    });
    this.gridGroup = new TransformableGroup({
      name: `${this.id}-Axis-grid`,
      zIndex: 1
      /* AXIS_GRID */
    });
    this.gridLineGroup = this.gridGroup.appendChild(new Group({ name: `${this.id}-gridLines` }));
    this.crossLineRangeGroup = new TransformableGroup({
      name: `${this.id}-CrossLines-Range`,
      zIndex: 3
      /* SERIES_CROSSLINE_RANGE */
    });
    this.crossLineLineGroup = new TransformableGroup({
      name: `${this.id}-CrossLines-Line`,
      zIndex: 7
      /* SERIES_CROSSLINE_LINE */
    });
    this.crossLineLabelGroup = new TransformableGroup({
      name: `${this.id}-CrossLines-Label`,
      zIndex: 12
      /* SERIES_LABEL */
    });
    this.tickLineGroupSelection = Selection.select(this.tickLineGroup, TranslatableLine, false);
    this.tickLabelGroupSelection = Selection.select(
      this.tickLabelGroup,
      TransformableText,
      false
    );
    this.gridLineGroupSelection = Selection.select(this.gridLineGroup, TranslatableLine, false);
    this._crossLines = [];
    this.line = new AxisLine();
    this.tick = new AxisTick();
    this.gridLine = new AxisGridLine();
    this.label = this.createLabel();
    this.tempText = new TransformableText();
    this.tempCaption = new Caption();
    this.defaultTickMinSpacing = _Axis2.defaultTickMinSpacing;
    this.translation = { x: 0, y: 0 };
    this.rotation = 0;
    this.layout = {
      label: {
        fractionDigits: 0,
        spacing: this.label.spacing,
        format: this.label.format
      }
    };
    this.destroyFns = [];
    this.range = [0, 1];
    this.visibleRange = [0, 1];
    this.title = new AxisTitle();
    this.gridLength = 0;
    this.gridPadding = 0;
    this.seriesAreaPadding = 0;
    this.tickGenerationResult = void 0;
    this._domainCalculated = false;
    this.moduleMap = new ModuleMap();
    this.range = this.scale.range.slice();
    this.crossLines.forEach((crossLine) => this.initCrossLine(crossLine));
    this.axisGroup.appendChild(this.title.caption.node);
    this.animationManager = moduleCtx.animationManager;
    this.animationState = new StateMachine("empty", {
      empty: {
        update: {
          target: "ready",
          action: () => this.resetSelectionNodes()
        },
        reset: "empty"
      },
      ready: {
        update: (data) => this.animateReadyUpdate(data),
        resize: () => this.resetSelectionNodes(),
        reset: "empty"
      }
    });
    let previousSize = void 0;
    this.destroyFns.push(
      this.title.caption.registerInteraction(this.moduleCtx, "afterend"),
      moduleCtx.layoutManager.addListener("layout:complete", (e) => {
        if (previousSize != null && jsonDiff(e.chart, previousSize) != null) {
          this.animationState.transition("resize");
        }
        previousSize = { ...e.chart };
      })
    );
  }
  get type() {
    return this.constructor.type ?? "";
  }
  set crossLines(value) {
    const { CrossLineConstructor } = this.constructor;
    this._crossLines.forEach((crossLine) => this.detachCrossLine(crossLine));
    this._crossLines = value.map((crossLine) => {
      const instance = new CrossLineConstructor();
      instance.set(crossLine);
      return instance;
    });
    this._crossLines.forEach((crossLine) => {
      this.attachCrossLine(crossLine);
      this.initCrossLine(crossLine);
    });
  }
  get crossLines() {
    return this._crossLines;
  }
  resetAnimation(phase) {
    if (phase === "initial") {
      this.animationState.transition("reset");
    }
  }
  attachCrossLine(crossLine) {
    this.crossLineRangeGroup.appendChild(crossLine.rangeGroup);
    this.crossLineLineGroup.appendChild(crossLine.lineGroup);
    this.crossLineLabelGroup.appendChild(crossLine.labelGroup);
  }
  detachCrossLine(crossLine) {
    this.crossLineRangeGroup.removeChild(crossLine.rangeGroup);
    this.crossLineLineGroup.removeChild(crossLine.lineGroup);
    this.crossLineLabelGroup.removeChild(crossLine.labelGroup);
  }
  destroy() {
    this.moduleMap.destroy();
    this.destroyFns.forEach((f) => f());
  }
  updateRange() {
    const { range: rr, visibleRange: vr, scale: scale2 } = this;
    const span = (rr[1] - rr[0]) / (vr[1] - vr[0]);
    const shift = span * vr[0];
    const start2 = rr[0] - shift;
    scale2.setVisibleRange?.(vr);
    scale2.range = [start2, start2 + span];
    this.crossLines.forEach((crossLine) => {
      crossLine.clippedRange = [rr[0], rr[1]];
    });
  }
  setCrossLinesVisible(visible) {
    this.crossLineRangeGroup.visible = visible;
    this.crossLineLineGroup.visible = visible;
    this.crossLineLabelGroup.visible = visible;
  }
  attachAxis(groups) {
    groups.gridNode.appendChild(this.gridGroup);
    groups.axisNode.appendChild(this.axisGroup);
    groups.labelNode.appendChild(this.labelGroup);
    groups.crossLineRangeNode.appendChild(this.crossLineRangeGroup);
    groups.crossLineLineNode.appendChild(this.crossLineLineGroup);
    groups.crossLineLabelNode.appendChild(this.crossLineLabelGroup);
  }
  detachAxis(groups) {
    groups.gridNode.removeChild(this.gridGroup);
    groups.axisNode.removeChild(this.axisGroup);
    groups.labelNode.removeChild(this.labelGroup);
    groups.crossLineRangeNode.removeChild(this.crossLineRangeGroup);
    groups.crossLineLineNode.removeChild(this.crossLineLineGroup);
    groups.crossLineLabelNode.removeChild(this.crossLineLabelGroup);
  }
  attachLabel(axisLabelNode) {
    this.labelGroup.append(axisLabelNode);
  }
  /**
   * Checks if a point or an object is in range.
   * @param value A point (or object's starting point).
   * @param tolerance Expands the range on both ends by this amount.
   */
  inRange(value, tolerance = 0) {
    const [min, max] = findMinMax(this.range);
    return value >= min - tolerance && value <= max + tolerance;
  }
  onFormatChange(ticks, fractionDigits, _domain, format) {
    const { scale: scale2 } = this;
    const logScale = scale2 instanceof LogScale;
    if (format && scale2?.tickFormat) {
      try {
        const formatter = scale2.tickFormat({ ticks, specifier: format });
        this.labelFormatter = formatter;
        this.datumFormatter = formatter;
        return;
      } catch {
        Logger.warnOnce(`the axis label format string ${format} is invalid. No formatting will be applied`);
      }
    }
    this.labelFormatter = logScale ? String : (x) => formatValue(x, fractionDigits);
    this.datumFormatter = logScale ? String : (x) => formatValue(x, fractionDigits + 1);
  }
  onGridLengthChange(value, prevValue) {
    if (prevValue ^ value) {
      this.onGridVisibilityChange();
    }
    this.crossLines.forEach((crossLine) => this.initCrossLine(crossLine));
  }
  onGridVisibilityChange() {
    this.gridLineGroupSelection.clear();
  }
  createLabel() {
    return new AxisLabel();
  }
  /**
   * Creates/removes/updates the scene graph nodes that constitute the axis.
   */
  update(animated = true) {
    if (!this.tickGenerationResult)
      return;
    this.updatePosition();
    const lineData = this.getAxisLineCoordinates();
    const { tickData, combinedRotation, textBaseline, textAlign } = this.tickGenerationResult;
    const previousTicks = this.tickLabelGroupSelection.nodes().slice();
    this.updateSelections(lineData, tickData.ticks, {
      combinedRotation,
      textAlign,
      textBaseline,
      range: this.scale.range
    });
    if (!animated || this.animationManager.isSkipped()) {
      this.resetSelectionNodes();
    } else {
      const diff2 = diffArrays(
        previousTicks.map((node) => node.datum.tickId),
        tickData.ticks.map((datum) => datum.tickId)
      );
      this.animationState.transition("update", diff2);
    }
    this.tickLineGroup.visible = this.tick.enabled;
    this.gridLineGroup.visible = this.gridLine.enabled;
    this.tickLabelGroup.visible = this.label.enabled;
    const { enabled, stroke, width: width2 } = this.line;
    this.lineNode.setProperties({ stroke, strokeWidth: enabled ? width2 : 0 });
    this.updateLabels();
    this.updateGridLines();
    this.updateTickLines();
    this.updateTitle(!tickData.ticks.length);
    this.updateCrossLines();
  }
  getAxisLineCoordinates() {
    const [min, max] = findMinMax(this.range);
    return { x: 0, y1: min, y2: max };
  }
  getTickLineCoordinates(datum) {
    const sideFlag = this.label.getSideFlag();
    const x = sideFlag * this.getTickSize();
    const x1 = Math.min(0, x);
    const x2 = x1 + Math.abs(x);
    const y = datum.translationY;
    return { x1, x2, y };
  }
  getLabelStyles(params, additionalStyles) {
    const { label } = this;
    const defaultStyle = {
      color: label.color,
      spacing: label.spacing,
      fontFamily: label.fontFamily,
      fontSize: label.fontSize,
      fontStyle: label.fontStyle,
      fontWeight: label.fontWeight
    };
    let stylerOutput;
    if (label.itemStyler) {
      stylerOutput = this.moduleCtx.callbackCache.call(label.itemStyler, {
        ...params,
        ...defaultStyle
      });
    }
    const {
      color: fill,
      fontFamily,
      fontSize,
      fontStyle,
      fontWeight,
      spacing
    } = mergeDefaults(stylerOutput, additionalStyles, defaultStyle);
    return { fill, fontFamily, fontSize, fontStyle, fontWeight, spacing };
  }
  getTickLabelProps(datum, params) {
    const { label } = this;
    const { combinedRotation, textBaseline, textAlign, range: range3 } = params;
    const text = datum.tickLabel;
    const sideFlag = label.getSideFlag();
    const labelX = sideFlag * (this.getTickSize() + label.spacing + this.seriesAreaPadding);
    const visible = text !== "" && text != null;
    return {
      ...this.getLabelStyles({ value: datum.tickLabel }),
      tickId: datum.tickId,
      rotation: combinedRotation,
      rotationCenterX: labelX,
      translationY: datum.translationY,
      text,
      textAlign,
      textBaseline,
      visible,
      x: labelX,
      y: 0,
      range: range3
    };
  }
  getTickSize() {
    return this.tick.enabled ? this.tick.size : 0;
  }
  setTitleProps(caption, params) {
    const { title } = this;
    if (!title.enabled) {
      caption.enabled = false;
      caption.node.visible = false;
      return;
    }
    caption.color = title.color;
    caption.fontFamily = title.fontFamily;
    caption.fontSize = title.fontSize;
    caption.fontStyle = title.fontStyle;
    caption.fontWeight = title.fontWeight;
    caption.enabled = title.enabled;
    caption.wrapping = title.wrapping;
    const titleNode = caption.node;
    const padding = (title.spacing ?? 0) + params.spacing;
    const sideFlag = this.label.getSideFlag();
    const parallelFlipRotation = normalizeAngle360(this.rotation);
    const titleRotationFlag = sideFlag === -1 && parallelFlipRotation > Math.PI && parallelFlipRotation < Math.PI * 2 ? -1 : 1;
    const rotation = titleRotationFlag * sideFlag * Math.PI / 2;
    const textBaseline = titleRotationFlag === 1 ? "bottom" : "top";
    const { range: range3 } = this;
    const x = Math.floor(titleRotationFlag * sideFlag * (range3[0] + range3[1]) / 2);
    const y = sideFlag === -1 ? Math.floor(titleRotationFlag * -padding) : Math.floor(-padding);
    const { callbackCache } = this.moduleCtx;
    const { formatter = (p) => p.defaultValue } = title;
    const text = callbackCache.call(formatter, this.getTitleFormatterParams());
    caption.text = text;
    titleNode.setProperties({ visible: true, text, textBaseline, x, y, rotation });
  }
  processData() {
    this._domainCalculated = false;
  }
  calculateLayout(domain, primaryTickCount) {
    const { rotation, parallelFlipRotation, regularFlipRotation } = this.calculateRotations();
    const sideFlag = this.label.getSideFlag();
    this.updateScale({ domain, skipDomainCalculation: this._domainCalculated });
    this._domainCalculated = domain == null;
    const tickResult = this.processTicks(primaryTickCount, parallelFlipRotation, regularFlipRotation);
    this.tickGenerationResult = tickResult.tickGenerationResult;
    const bbox = BBox.merge(tickResult.boxes);
    const transformedBBox = this.getTransformBox(bbox);
    const anySeriesActive = this.isAnySeriesActive();
    this.crossLines.forEach((crossLine) => {
      var _a;
      crossLine.sideFlag = -sideFlag;
      crossLine.direction = rotation === -Math.PI / 2 ? "x" : "y";
      if (crossLine instanceof CartesianCrossLine) {
        (_a = crossLine.label).parallel ?? (_a.parallel = this.label.parallel);
      }
      crossLine.parallelFlipRotation = parallelFlipRotation;
      crossLine.regularFlipRotation = regularFlipRotation;
      crossLine.calculateLayout?.(anySeriesActive, this.reverse);
    });
    return {
      primaryTickCount: tickResult.tickGenerationResult?.primaryTickCount ?? primaryTickCount,
      bbox: transformedBBox
    };
  }
  processTicks(primaryTickCount, parallelFlipRotation, regularFlipRotation) {
    const sideFlag = this.label.getSideFlag();
    const labelX = sideFlag * (this.getTickSize() + this.label.spacing + this.seriesAreaPadding);
    const ticksEnabled = this.label.enabled || this.tick.enabled || this.gridLine.enabled;
    const tickGenerationResult = ticksEnabled ? this.generateTicks({
      primaryTickCount,
      parallelFlipRotation,
      regularFlipRotation,
      labelX,
      sideFlag
    }) : NO_LABELS_AND_TICKS;
    const { tickData, combinedRotation, textBaseline, textAlign } = tickGenerationResult;
    this.updateLayoutState(tickData.fractionDigits);
    const boxes = [];
    const { x, y1, y2 } = this.getAxisLineCoordinates();
    const lineBox = new BBox(
      x + Math.min(sideFlag * this.seriesAreaPadding, 0),
      y1,
      this.seriesAreaPadding,
      y2 - y1
    );
    boxes.push(lineBox);
    if (this.tick.enabled) {
      tickData.ticks.forEach((datum) => {
        const { x1, x2, y } = this.getTickLineCoordinates(datum);
        const tickLineBox = new BBox(x1, y, x2 - x1, 0);
        boxes.push(tickLineBox);
      });
    }
    const { tempText } = this;
    if (this.label.enabled) {
      tickData.ticks.forEach((datum) => {
        const labelProps = this.getTickLabelProps(datum, {
          combinedRotation,
          textAlign,
          textBaseline,
          range: this.scale.range
        });
        if (!labelProps.visible) {
          return;
        }
        tempText.setProperties({
          ...labelProps,
          translationY: Math.round(datum.translationY)
        });
        const box = tempText.getBBox();
        if (box) {
          boxes.push(box);
        }
      });
    }
    if (this.title?.enabled) {
      const spacing = BBox.merge(boxes).width;
      this.setTitleProps(this.tempCaption, { spacing });
      const titleBox = this.tempCaption.node.getBBox();
      if (titleBox) {
        boxes.push(titleBox);
      }
    }
    return { tickGenerationResult, boxes };
  }
  updateLayoutState(fractionDigits) {
    this.layout.label = {
      fractionDigits,
      spacing: this.label.spacing,
      format: this.label.format
    };
  }
  getTransformBox(bbox) {
    const matrix = new Matrix();
    const { rotation, translationX, translationY } = this.getAxisTransform();
    Matrix.updateTransformMatrix(matrix, 1, 1, rotation, translationX, translationY);
    return matrix.transformBBox(bbox);
  }
  setDomain(domain) {
    this.dataDomain = this.normaliseDataDomain(domain);
    if (this.reverse) {
      this.dataDomain.domain.reverse();
    }
    this.scale.domain = this.dataDomain.domain;
  }
  updateScale(opts) {
    const domain = opts?.domain;
    const skipDomainCalculation = opts?.skipDomainCalculation ?? false;
    if (!skipDomainCalculation) {
      if (domain) {
        this.setDomain(domain);
      } else {
        this.calculateDomain();
      }
    }
    this.updateRange();
    this.scale.interval = this.interval.step;
    if (ContinuousScale.is(this.scale)) {
      this.scale.nice = this.nice;
      this.scale.update();
    }
  }
  calculateRotations() {
    const rotation = toRadians(this.rotation);
    const parallelFlipRotation = normalizeAngle360(rotation);
    const regularFlipRotation = normalizeAngle360(rotation - Math.PI / 2);
    return { rotation, parallelFlipRotation, regularFlipRotation };
  }
  generateTicks({
    primaryTickCount,
    parallelFlipRotation,
    regularFlipRotation,
    labelX,
    sideFlag
  }) {
    const {
      scale: scale2,
      interval: { minSpacing, maxSpacing },
      label: { parallel, rotation, fontFamily, fontSize, fontStyle, fontWeight }
    } = this;
    const secondaryAxis = primaryTickCount !== void 0;
    const { defaultRotation, configuredRotation, parallelFlipFlag, regularFlipFlag } = calculateLabelRotation({
      rotation,
      parallel,
      regularFlipRotation,
      parallelFlipRotation
    });
    const initialRotation = configuredRotation + defaultRotation;
    const labelMatrix = new Matrix();
    const { maxTickCount } = this.estimateTickCount(minSpacing, maxSpacing);
    const continuous = ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2);
    const maxIterations = !continuous || isNaN(maxTickCount) ? 10 : maxTickCount;
    let textAlign = getTextAlign(parallel, configuredRotation, 0, sideFlag, regularFlipFlag);
    const textBaseline = getTextBaseline(parallel, configuredRotation, sideFlag, parallelFlipFlag);
    const font = TextUtils.toFontString({ fontFamily, fontSize, fontStyle, fontWeight });
    const textMeasurer = CachedTextMeasurerPool.getMeasurer({ font });
    const textProps = {
      fontFamily,
      fontSize,
      fontStyle,
      fontWeight,
      textBaseline,
      textAlign
    };
    let tickData = {
      ticks: [],
      rawTicks: [],
      fractionDigits: 0,
      labelCount: 0
    };
    let index = 0;
    let autoRotation = 0;
    let labelOverlap = true;
    let labelData = [];
    let terminate = false;
    while (labelOverlap && index <= maxIterations) {
      if (terminate)
        break;
      autoRotation = 0;
      textAlign = getTextAlign(parallel, configuredRotation, 0, sideFlag, regularFlipFlag);
      const tickStrategies = this.getTickStrategies({ secondaryAxis, index });
      for (const strategy of tickStrategies) {
        ({ tickData, index, autoRotation, terminate } = strategy({
          index,
          tickData,
          textProps,
          labelOverlap,
          terminate,
          primaryTickCount
        }));
        const rotated = configuredRotation !== 0 || autoRotation !== 0;
        const labelRotation = initialRotation + autoRotation;
        const labelSpacing = getLabelSpacing(this.label.minSpacing, rotated);
        Matrix.updateTransformMatrix(labelMatrix, 1, 1, labelRotation, 0, 0);
        textAlign = getTextAlign(parallel, configuredRotation, autoRotation, sideFlag, regularFlipFlag);
        labelData = createLabelData(tickData.ticks, labelX, labelMatrix, textMeasurer);
        labelOverlap = this.label.avoidCollisions ? axisLabelsOverlap(labelData, labelSpacing) : false;
      }
    }
    const combinedRotation = defaultRotation + configuredRotation + autoRotation;
    if (!secondaryAxis && tickData.rawTicks.length > 0) {
      primaryTickCount = tickData.rawTicks.length;
    }
    return { tickData, primaryTickCount, combinedRotation, textBaseline, textAlign, labelData };
  }
  getTickStrategies({
    index: iteration,
    secondaryAxis
  }) {
    const { scale: scale2, label } = this;
    const { minSpacing } = this.interval;
    const continuous = ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2);
    const avoidLabelCollisions = label.enabled && label.avoidCollisions;
    const filterTicks = !continuous && iteration !== 0 && avoidLabelCollisions;
    const autoRotate = label.autoRotate === true && label.rotation === void 0;
    const strategies = [];
    let tickGenerationType;
    if (this.interval.values) {
      tickGenerationType = 3;
    } else if (secondaryAxis) {
      tickGenerationType = 1;
    } else if (filterTicks) {
      tickGenerationType = 2;
    } else {
      tickGenerationType = 0;
    }
    const tickGenerationStrategy = ({ index, tickData, primaryTickCount, terminate }) => this.createTickData(tickGenerationType, index, tickData, terminate, primaryTickCount);
    strategies.push(tickGenerationStrategy);
    if (!continuous && !isNaN(minSpacing)) {
      const tickFilterStrategy = ({ index, tickData, primaryTickCount, terminate }) => this.createTickData(2, index, tickData, terminate, primaryTickCount);
      strategies.push(tickFilterStrategy);
    }
    if (avoidLabelCollisions && autoRotate) {
      const autoRotateStrategy = ({ index, tickData, labelOverlap, terminate }) => ({
        index,
        tickData,
        autoRotation: labelOverlap ? normalizeAngle360(toRadians(this.label.autoRotateAngle ?? 0)) : 0,
        terminate
      });
      strategies.push(autoRotateStrategy);
    }
    return strategies;
  }
  createTickData(tickGenerationType, index, tickData, terminate, primaryTickCount) {
    const { scale: scale2 } = this;
    const { step, values, minSpacing, maxSpacing } = this.interval;
    const { maxTickCount, minTickCount, tickCount } = this.estimateTickCount(minSpacing, maxSpacing);
    const continuous = ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2);
    const maxIterations = !continuous || isNaN(maxTickCount) ? 10 : maxTickCount;
    const countTicks = (i) => continuous ? Math.max(tickCount - i, minTickCount) : maxTickCount;
    const regenerateTicks = step == null && values == null && countTicks(index) > minTickCount && (continuous || tickGenerationType === 2);
    while (index <= maxIterations) {
      const previousTicks = tickData.rawTicks;
      tickData = this.getTicks({
        tickGenerationType,
        previousTicks,
        minTickCount,
        maxTickCount,
        primaryTickCount,
        tickCount: countTicks(index)
      });
      index++;
      if (!regenerateTicks || !arraysEqual(tickData.rawTicks, previousTicks))
        break;
    }
    terminate || (terminate = step != null || values != null);
    return { tickData, index, autoRotation: 0, terminate };
  }
  getTicks({
    tickGenerationType,
    previousTicks,
    tickCount,
    minTickCount,
    maxTickCount,
    primaryTickCount
  }) {
    const { range: range3, scale: scale2, visibleRange } = this;
    const idGenerator = createIdsGenerator();
    let rawTicks;
    switch (tickGenerationType) {
      case 3:
        rawTicks = this.interval.values;
        if (ContinuousScale.is(scale2)) {
          const [d0, d1] = findMinMax(scale2.getDomain().map(Number));
          rawTicks = rawTicks.filter((value) => value >= d0 && value <= d1).sort((a, b) => a - b);
        }
        break;
      case 1:
        if (ContinuousScale.is(scale2)) {
          rawTicks = this.updateSecondaryAxisTicks(primaryTickCount);
        } else {
          rawTicks = this.createTicks(tickCount, minTickCount, maxTickCount);
        }
        break;
      case 2:
        rawTicks = this.filterTicks(previousTicks, tickCount);
        break;
      default:
        rawTicks = this.createTicks(tickCount, minTickCount, maxTickCount);
        break;
    }
    const fractionDigits = rawTicks.reduce(
      (max, tick) => Math.max(max, typeof tick === "number" ? countFractionDigits(tick) : 0),
      0
    );
    const halfBandwidth = (scale2.bandwidth ?? 0) / 2;
    const ticks = [];
    let labelCount = 0;
    const start2 = Math.max(0, Math.floor(visibleRange[0] * rawTicks.length));
    const end2 = Math.min(rawTicks.length, Math.ceil(visibleRange[1] * rawTicks.length));
    const filteredTicks = rawTicks.slice(start2, end2);
    this.onFormatChange(filteredTicks, fractionDigits, rawTicks, this.label.format);
    for (let i = 0; i < filteredTicks.length; i++) {
      const tick = filteredTicks[i];
      const translationY = scale2.convert(tick) + halfBandwidth;
      if (range3.length > 0 && !this.inRange(translationY, 1e-3))
        continue;
      const tickLabel = this.formatTick(tick, start2 + i, fractionDigits);
      ticks.push({ tick, tickId: idGenerator(tickLabel), tickLabel, translationY: Math.floor(translationY) });
      if (tickLabel === "" || tickLabel == null) {
        continue;
      }
      labelCount++;
    }
    return { rawTicks, fractionDigits, ticks, labelCount };
  }
  filterTicks(ticks, tickCount) {
    const { minSpacing, maxSpacing } = this.interval;
    const tickSpacing = !isNaN(minSpacing) || !isNaN(maxSpacing);
    const keepEvery = tickSpacing ? Math.ceil(ticks.length / tickCount) : 2;
    return ticks.filter((_, i) => i % keepEvery === 0);
  }
  createTicks(tickCount, minTickCount, maxTickCount) {
    const { scale: scale2 } = this;
    if (tickCount && (ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2))) {
      scale2.tickCount = tickCount;
      scale2.minTickCount = minTickCount ?? 0;
      scale2.maxTickCount = maxTickCount ?? Infinity;
    }
    return scale2.ticks?.() ?? [];
  }
  estimateTickCount(minSpacing, maxSpacing) {
    return estimateTickCount(
      this.calculateRangeWithBleed(),
      minSpacing,
      maxSpacing,
      ContinuousScale.defaultTickCount,
      this.defaultTickMinSpacing
    );
  }
  updateCrossLines() {
    const anySeriesActive = this.isAnySeriesActive();
    this.crossLines.forEach((crossLine) => {
      crossLine.update(anySeriesActive);
    });
  }
  updateTickLines() {
    const { tick, label } = this;
    const sideFlag = label.getSideFlag();
    this.tickLineGroupSelection.each((line, datum) => {
      line.strokeWidth = datum.tickWidth ?? tick.width;
      line.stroke = datum.tickStroke ?? tick.stroke;
      line.x1 = sideFlag * (datum.tickSize ?? this.getTickSize());
      line.x2 = 0;
    });
  }
  calculateAvailableRange() {
    return findRangeExtent(this.range);
  }
  /**
   * Calculates the available range with an additional "bleed" beyond the canvas that encompasses the full axis when
   * the visible range is only a portion of the axis.
   */
  calculateRangeWithBleed() {
    return round(this.calculateAvailableRange() / findRangeExtent(this.visibleRange), 2);
  }
  calculateDomain() {
    const { includeInvisibleDomains, boundSeries, direction } = this;
    const visibleSeries = includeInvisibleDomains ? boundSeries : boundSeries.filter((s) => s.isEnabled());
    const domains = visibleSeries.length === 1 ? visibleSeries[0].getDomain(direction) : visibleSeries.flatMap((series) => series.getDomain(direction));
    this.setDomain(domains);
  }
  getAxisTransform() {
    return {
      rotation: toRadians(this.rotation),
      translationX: Math.floor(this.translation.x),
      translationY: Math.floor(this.translation.y)
    };
  }
  updatePosition() {
    const { crossLineRangeGroup, crossLineLineGroup, crossLineLabelGroup, axisGroup, gridGroup, translation } = this;
    const { rotation } = this.calculateRotations();
    const translationX = Math.floor(translation.x);
    const translationY = Math.floor(translation.y);
    crossLineRangeGroup.setProperties({ rotation, translationX, translationY });
    crossLineLineGroup.setProperties({ rotation, translationX, translationY });
    crossLineLabelGroup.setProperties({ rotation, translationX, translationY });
    gridGroup.setProperties({ rotation, translationX, translationY });
    axisGroup.datum = this.getAxisTransform();
  }
  updateSecondaryAxisTicks(_primaryTickCount) {
    throw new Error("AG Charts - unexpected call to updateSecondaryAxisTicks() - check axes configuration.");
  }
  updateSelections(lineData, data, params) {
    const getDatumId = (datum) => datum.tickId;
    const labelsData = data.map((d) => this.getTickLabelProps(d, params));
    this.lineNode.datum = lineData;
    this.gridLineGroupSelection.update(this.gridLength ? data : [], void 0, getDatumId);
    this.tickLineGroupSelection.update(data, void 0, getDatumId);
    this.tickLabelGroupSelection.update(labelsData, void 0, getDatumId);
  }
  updateGridLines() {
    const sideFlag = this.label.getSideFlag();
    const {
      gridLine: { style, width: width2 },
      gridPadding,
      gridLength
    } = this;
    if (gridLength === 0 || style.length === 0) {
      return;
    }
    this.gridLineGroupSelection.each((line, _, index) => {
      const { stroke, lineDash } = style[index % style.length];
      line.setProperties({
        x1: gridPadding,
        x2: -sideFlag * gridLength + gridPadding,
        stroke,
        strokeWidth: width2,
        lineDash
      });
    });
  }
  updateLabels() {
    if (!this.label.enabled)
      return;
    this.tickLabelGroupSelection.each((node, datum) => {
      node.setProperties(datum, [
        "fill",
        "fontFamily",
        "fontSize",
        "fontStyle",
        "fontWeight",
        "text",
        "textAlign",
        "textBaseline"
      ]);
    });
  }
  updateTitle(noVisibleTicks, spacing) {
    const { title, lineNode, tickLineGroup, tickLabelGroup } = this;
    if (title.enabled && !noVisibleTicks && spacing == null) {
      const tickBBox = Group.computeChildrenBBox([tickLineGroup, tickLabelGroup, lineNode]);
      spacing = tickBBox.width + (this.tickLabelGroup.visible ? 0 : this.seriesAreaPadding);
    }
    spacing ?? (spacing = 0);
    this.setTitleProps(title.caption, { spacing });
  }
  // For formatting (nice rounded) tick values.
  formatTick(value, index, fractionDigits) {
    const {
      labelFormatter,
      label: { formatter },
      moduleCtx: { callbackCache }
    } = this;
    let result;
    if (formatter) {
      result = callbackCache.call(formatter, { value, index, fractionDigits });
    } else if (labelFormatter) {
      result = callbackCache.call(labelFormatter, value);
    }
    return String(result ?? value);
  }
  // For formatting arbitrary values between the ticks.
  formatDatum(value) {
    const {
      label: { formatter },
      moduleCtx: { callbackCache },
      datumFormatter: valueFormatter = this.labelFormatter
    } = this;
    let result;
    if (formatter) {
      result = callbackCache.call(formatter, { value, index: NaN });
    } else if (valueFormatter) {
      result = callbackCache.call(valueFormatter, value);
    } else if (isArray(value)) {
      result = value.filter(Boolean).join(" - ");
    }
    return String(result ?? value);
  }
  getScaleValueFormatter(format) {
    if (format && this.scale.tickFormat) {
      try {
        return this.scale.tickFormat({ specifier: format });
      } catch {
        Logger.warnOnce(`the format string ${format} is invalid, ignoring.`);
      }
    }
    return (value) => this.formatDatum(value);
  }
  getBBox() {
    return this.axisGroup.getBBox();
  }
  initCrossLine(crossLine) {
    crossLine.scale = this.scale;
    crossLine.gridLength = this.gridLength;
  }
  isAnySeriesActive() {
    return this.boundSeries.some((s) => this.includeInvisibleDomains || s.isEnabled());
  }
  clipTickLines(x, y, width2, height2) {
    this.tickLineGroup.setClipRect(new BBox(x, y, width2, height2));
  }
  clipGrid(x, y, width2, height2) {
    this.gridGroup.setClipRect(new BBox(x, y, width2, height2));
  }
  getTitleFormatterParams() {
    const { direction } = this;
    const boundSeries = [];
    for (const series of this.boundSeries) {
      const keys = series.getKeys(direction);
      const names = series.getNames(direction);
      for (let idx = 0; idx < keys.length; idx++) {
        boundSeries.push({ key: keys[idx], name: names[idx] });
      }
    }
    return { direction, boundSeries, defaultValue: this.title?.text };
  }
  normaliseDataDomain(d) {
    return { domain: [...d], clipped: false };
  }
  getLayoutState() {
    return {
      id: this.id,
      rect: this.getBBox(),
      gridPadding: this.gridPadding,
      seriesAreaPadding: this.seriesAreaPadding,
      tickSize: this.getTickSize(),
      direction: this.direction,
      domain: this.dataDomain.domain,
      scale: this.scale,
      ...this.layout
    };
  }
  getModuleMap() {
    return this.moduleMap;
  }
  createModuleContext() {
    this.axisContext ?? (this.axisContext = this.createAxisContext());
    return { ...this.moduleCtx, parent: this.axisContext };
  }
  createAxisContext() {
    const { scale: scale2 } = this;
    return {
      axisId: this.id,
      scale: this.scale,
      direction: this.direction,
      continuous: ContinuousScale.is(scale2) || OrdinalTimeScale.is(scale2),
      getCanvasBounds: () => {
        return Transformable.toCanvas(this.axisGroup);
      },
      seriesKeyProperties: () => this.boundSeries.reduce((keys, series) => {
        const seriesKeys = series.getKeyProperties(this.direction);
        seriesKeys.forEach((key) => {
          if (keys.indexOf(key) < 0) {
            keys.push(key);
          }
        });
        return keys;
      }, []),
      scaleValueFormatter: (specifier) => this.getScaleValueFormatter(specifier),
      scaleInvert: OrdinalTimeScale.is(scale2) ? (val) => scale2.invertNearest?.(val) : (val) => scale2.invert?.(val),
      scaleInvertNearest: (val) => scale2.invertNearest?.(val),
      attachLabel: (node) => this.attachLabel(node),
      inRange: (x, tolerance) => this.inRange(x, tolerance)
    };
  }
  animateReadyUpdate(diff2) {
    const { animationManager } = this.moduleCtx;
    const selectionCtx = prepareAxisAnimationContext(this);
    const fns = prepareAxisAnimationFunctions(selectionCtx);
    fromToMotion(this.id, "axis-group", animationManager, [this.axisGroup], fns.group);
    fromToMotion(this.id, "line", animationManager, [this.lineNode], fns.line);
    fromToMotion(
      this.id,
      "line-paths",
      animationManager,
      [this.gridLineGroupSelection, this.tickLineGroupSelection],
      fns.tick,
      (_, d) => d.tickId,
      diff2
    );
    fromToMotion(
      this.id,
      "tick-labels",
      animationManager,
      [this.tickLabelGroupSelection],
      fns.label,
      (_, d) => d.tickId,
      diff2
    );
  }
  resetSelectionNodes() {
    const selectionCtx = prepareAxisAnimationContext(this);
    resetMotion([this.axisGroup], resetAxisGroupFn());
    resetMotion([this.gridLineGroupSelection, this.tickLineGroupSelection], resetAxisSelectionFn(selectionCtx));
    resetMotion([this.tickLabelGroupSelection], resetAxisLabelSelectionFn());
    resetMotion([this.lineNode], resetAxisLineSelectionFn());
  }
  isReversed() {
    return this.reverse;
  }
};
_Axis.defaultTickMinSpacing = 50;
_Axis.CrossLineConstructor = CartesianCrossLine;
__decorateClass([
  Validate(BOOLEAN)
], _Axis.prototype, "nice", 2);
__decorateClass([
  Validate(BOOLEAN)
], _Axis.prototype, "reverse", 2);
__decorateClass([
  Validate(STRING_ARRAY)
], _Axis.prototype, "keys", 2);
__decorateClass([
  Validate(OBJECT)
], _Axis.prototype, "interval", 2);
__decorateClass([
  Validate(OBJECT)
], _Axis.prototype, "title", 2);
__decorateClass([
  ObserveChanges((target, value, oldValue) => target.onGridLengthChange(value, oldValue))
], _Axis.prototype, "gridLength", 2);
var Axis = _Axis;
var CartesianAxisLabel = class extends AxisLabel {
  constructor() {
    super(...arguments);
    this.autoRotateAngle = 335;
  }
};
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], CartesianAxisLabel.prototype, "autoRotate", 2);
__decorateClass([
  Validate(NUMBER)
], CartesianAxisLabel.prototype, "autoRotateAngle", 2);
var _CartesianAxis = class _CartesianAxis2 extends Axis {
  static is(value) {
    return value instanceof _CartesianAxis2;
  }
  get direction() {
    return this.position === "top" || this.position === "bottom" ? "x" : "y";
  }
  updateDirection() {
    switch (this.position) {
      case "top":
        this.rotation = -90;
        this.label.mirrored = true;
        this.label.parallel = true;
        break;
      case "right":
        this.rotation = 0;
        this.label.mirrored = true;
        this.label.parallel = false;
        break;
      case "bottom":
        this.rotation = -90;
        this.label.mirrored = false;
        this.label.parallel = true;
        break;
      case "left":
        this.rotation = 0;
        this.label.mirrored = false;
        this.label.parallel = false;
        break;
    }
    if (this.axisContext) {
      this.axisContext.position = this.position;
      this.axisContext.direction = this.direction;
    }
  }
  update(animated) {
    this.updateDirection();
    super.update(animated);
  }
  calculateLayout(domain, primaryTickCount) {
    this.updateDirection();
    return super.calculateLayout(domain, primaryTickCount);
  }
  createAxisContext() {
    return { ...super.createAxisContext(), position: this.position };
  }
  createLabel() {
    return new CartesianAxisLabel();
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], _CartesianAxis.prototype, "thickness", 2);
__decorateClass([
  Validate(POSITION)
], _CartesianAxis.prototype, "position", 2);
var CartesianAxis = _CartesianAxis;
var _CategoryAxis = class _CategoryAxis2 extends CartesianAxis {
  constructor(moduleCtx, scale2 = new BandScale()) {
    super(moduleCtx, scale2);
    this.groupPaddingInner = 0.1;
    this.categoryAnimatable = true;
    this.includeInvisibleDomains = true;
  }
  static is(value) {
    return value instanceof _CategoryAxis2;
  }
  domainOrderedToNormalizedDomain(seriesDomain, normalizedDomain) {
    let normalizedIndex = -1;
    for (const value of seriesDomain) {
      const normalizedNextIndex = normalizedDomain.indexOf(value);
      if (normalizedNextIndex === -1) {
        normalizedIndex = Infinity;
      } else if (normalizedNextIndex <= normalizedIndex) {
        return false;
      } else {
        normalizedIndex = normalizedNextIndex;
      }
    }
    return true;
  }
  calculateDomain() {
    let normalizedDomain = void 0;
    const seenDomains = /* @__PURE__ */ new Set();
    let categoryAnimatable = true;
    for (const series of this.boundSeries) {
      if (!this.includeInvisibleDomains && !series.isEnabled())
        continue;
      const seriesDomain = series.getDomain(this.direction);
      if (seenDomains.has(seriesDomain))
        continue;
      seenDomains.add(seriesDomain);
      if (normalizedDomain == null) {
        normalizedDomain = this.normaliseDataDomain(seriesDomain).domain;
      } else {
        categoryAnimatable && (categoryAnimatable = this.domainOrderedToNormalizedDomain(seriesDomain, normalizedDomain));
        normalizedDomain = this.normaliseDataDomain([...normalizedDomain, ...seriesDomain]).domain;
      }
    }
    normalizedDomain ?? (normalizedDomain = []);
    this.setDomain(normalizedDomain);
    this.categoryAnimatable = categoryAnimatable;
  }
  update() {
    super.update();
    if (!this.categoryAnimatable) {
      this.moduleCtx.animationManager.skip();
    }
  }
  normaliseDataDomain(d) {
    const domain = [];
    const uniqueValues = /* @__PURE__ */ new Set();
    for (const v of d) {
      const key = v instanceof Date ? v.getTime() : v;
      if (!uniqueValues.has(key)) {
        uniqueValues.add(key);
        domain.push(v);
      }
    }
    return { domain, clipped: false };
  }
  updateScale(opts) {
    let { paddingInner, paddingOuter } = this;
    if (!isFiniteNumber(paddingInner) || !isFiniteNumber(paddingOuter)) {
      const padding = this.reduceBandScalePadding();
      paddingInner ?? (paddingInner = padding.inner);
      paddingOuter ?? (paddingOuter = padding.outer);
    }
    this.scale.paddingInner = paddingInner ?? 0;
    this.scale.paddingOuter = paddingOuter ?? 0;
    super.updateScale(opts);
  }
  reduceBandScalePadding() {
    return this.boundSeries.reduce(
      (result, series) => {
        const padding = series.getBandScalePadding?.();
        if (padding) {
          if (result.inner > padding.inner) {
            result.inner = padding.inner;
          }
          if (result.outer < padding.outer) {
            result.outer = padding.outer;
          }
        }
        return result;
      },
      { inner: Infinity, outer: -Infinity }
    );
  }
};
_CategoryAxis.className = "CategoryAxis";
_CategoryAxis.type = "category";
__decorateClass([
  Validate(RATIO)
], _CategoryAxis.prototype, "groupPaddingInner", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], _CategoryAxis.prototype, "paddingInner", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], _CategoryAxis.prototype, "paddingOuter", 2);
var CategoryAxis = _CategoryAxis;
var BaseModuleInstance = class {
  constructor() {
    this.destroyFns = [];
  }
  destroy() {
    for (const destroyFn of this.destroyFns) {
      destroyFn();
    }
  }
};
var ModuleRegistry = class {
  constructor() {
    this.modules = [];
    this.dependencies = /* @__PURE__ */ new Map();
    this.modulesByOptionKey = /* @__PURE__ */ new Map();
  }
  register(...modules) {
    for (const module2 of modules) {
      this.registerDependencies(module2);
      const otherModule = this.modules.find(
        (other) => module2.type === other.type && ("optionsKey" in module2 && "optionsKey" in other ? module2.optionsKey === other.optionsKey : true) && module2.identifier === other.identifier
      );
      if (otherModule) {
        if (module2.packageType === "enterprise" && otherModule.packageType === "community") {
          const index = this.modules.indexOf(otherModule);
          this.modules.splice(index, 1, module2);
          if ("optionsKey" in module2) {
            this.modulesByOptionKey.set(module2.optionsKey, module2);
          }
        }
      } else {
        this.modules.push(module2);
        if ("optionsKey" in module2) {
          this.modulesByOptionKey.set(module2.optionsKey, module2);
        }
      }
    }
  }
  hasEnterpriseModules() {
    return this.modules.some((m) => m.packageType === "enterprise");
  }
  *byType(...types) {
    const yielded = /* @__PURE__ */ new Set();
    const modulesByType = this.modules.filter((module2) => types.includes(module2.type));
    const calculateDependencies = (module2) => {
      const deps = this.dependencies.get(module2);
      return deps?.flatMap(calculateDependencies).concat(deps) ?? [];
    };
    const unresolvable = [];
    for (const module2 of modulesByType) {
      const uniqueKey = "optionsKey" in module2 ? module2.optionsKey : module2.contextKey;
      if (yielded.has(uniqueKey))
        continue;
      for (const dependency of calculateDependencies(uniqueKey)) {
        if (yielded.has(dependency))
          continue;
        const dependencyModule = this.modulesByOptionKey.get(dependency);
        if (!dependencyModule) {
          unresolvable.push(dependency);
          continue;
        }
        if (!types.includes(dependencyModule.type))
          continue;
        yield dependencyModule;
        yielded.add(dependency);
      }
      yield module2;
      yielded.add(uniqueKey);
    }
    if (unresolvable.length > 0) {
      throw new Error(`Could not resolve module dependencies: ${unresolvable}`);
    }
  }
  registerDependencies(module2) {
    if (module2.dependencies == null || module2.dependencies.length === 0)
      return;
    const uniqueKey = "optionsKey" in module2 ? module2.optionsKey : module2.contextKey;
    this.dependencies.set(uniqueKey, module2.dependencies);
  }
};
var moduleRegistry = new ModuleRegistry();
var AsyncAwaitQueue = class {
  constructor() {
    this.queue = [];
  }
  await(timeout = 50) {
    return new Promise((resolve) => {
      const successFn = () => {
        clearTimeout(timeoutHandle);
        resolve(true);
      };
      const timeoutFn = () => {
        const queueIndex = this.queue.indexOf(successFn);
        if (queueIndex < 0)
          return;
        this.queue.splice(queueIndex, 1);
        resolve(false);
      };
      const timeoutHandle = setTimeout(timeoutFn, timeout);
      this.queue.push(successFn);
    });
  }
  notify() {
    this.queue.splice(0).forEach((cb) => cb());
  }
};
function pause() {
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}
var Mutex = class {
  constructor() {
    this.available = true;
    this.acquireQueue = [];
  }
  acquire(cb) {
    return new Promise((resolve) => {
      this.acquireQueue.push([cb, resolve]);
      if (this.available) {
        this.dispatchNext().catch((e) => Logger.errorOnce(e));
      }
    });
  }
  async acquireImmediately(cb) {
    if (!this.available) {
      return false;
    }
    await this.acquire(cb);
    return true;
  }
  async waitForClearAcquireQueue() {
    return this.acquire(() => Promise.resolve(void 0));
  }
  async dispatchNext() {
    this.available = false;
    let [next, done] = this.acquireQueue.shift() ?? [];
    while (next) {
      try {
        await next();
        done?.();
      } catch (error) {
        Logger.error("mutex callback error", error);
        done?.();
      }
      [next, done] = this.acquireQueue.shift() ?? [];
    }
    this.available = true;
  }
};
var Observable = class {
  constructor() {
    this.eventListeners = /* @__PURE__ */ new Map();
  }
  addEventListener(eventType, listener) {
    if (typeof listener !== "function") {
      throw new Error("AG Charts - listener must be a Function");
    }
    const eventTypeListeners = this.eventListeners.get(eventType);
    if (eventTypeListeners) {
      eventTypeListeners.add(listener);
    } else {
      this.eventListeners.set(eventType, /* @__PURE__ */ new Set([listener]));
    }
  }
  removeEventListener(type, listener) {
    this.eventListeners.get(type)?.delete(listener);
    if (this.eventListeners.size === 0) {
      this.eventListeners.delete(type);
    }
  }
  hasEventListener(type) {
    return this.eventListeners.has(type);
  }
  clearEventListeners() {
    this.eventListeners.clear();
  }
  fireEvent(event) {
    this.eventListeners.get(event.type)?.forEach((listener) => listener(event));
  }
};
var Padding = class extends BaseProperties {
  constructor(top = 0, right = top, bottom = top, left = right) {
    super();
    this.top = top;
    this.right = right;
    this.bottom = bottom;
    this.left = left;
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Padding.prototype, "top", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Padding.prototype, "right", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Padding.prototype, "bottom", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Padding.prototype, "left", 2);
function debouncedAnimationFrame(cb) {
  return buildScheduler((innerCb, _delayMs) => getWindow().requestAnimationFrame(innerCb), cb);
}
function debouncedCallback(cb) {
  return buildScheduler((innerCb, delayMs = 0) => {
    if (delayMs === 0) {
      queueMicrotask(innerCb);
    } else {
      setTimeout(innerCb, delayMs);
    }
  }, cb);
}
function buildScheduler(scheduleFn, cb) {
  let scheduleCount = 0;
  let promiseRunning = false;
  let awaitingPromise;
  let awaitingDone;
  const busy = () => {
    return promiseRunning;
  };
  const done = () => {
    promiseRunning = false;
    awaitingDone?.();
    awaitingDone = void 0;
    awaitingPromise = void 0;
    if (scheduleCount > 0) {
      scheduleFn(scheduleCb);
    }
  };
  const scheduleCb = () => {
    const count = scheduleCount;
    scheduleCount = 0;
    promiseRunning = true;
    const maybePromise = cb({ count });
    if (!maybePromise) {
      done();
      return;
    }
    maybePromise.then(done, done);
  };
  return {
    schedule(delayMs) {
      if (scheduleCount === 0 && !busy()) {
        scheduleFn(scheduleCb, delayMs);
      }
      scheduleCount++;
    },
    async await() {
      if (!busy()) {
        return;
      }
      if (awaitingPromise == null) {
        awaitingPromise = new Promise((resolve) => {
          awaitingDone = resolve;
        });
      }
      while (busy()) {
        await awaitingPromise;
      }
    }
  };
}
var EventEmitter = class {
  constructor() {
    this.events = /* @__PURE__ */ new Map();
  }
  /**
   * Registers an event listener.
   * @param eventName The event name to listen for.
   * @param listener The callback to be invoked on the event.
   * @returns A function to unregister the listener.
   */
  on(eventName, listener) {
    if (!this.events.has(eventName)) {
      this.events.set(eventName, /* @__PURE__ */ new Set());
    }
    this.events.get(eventName)?.add(listener);
    return () => this.off(eventName, listener);
  }
  /**
   * Unregisters an event listener.
   * @param eventName The event name to stop listening for.
   * @param listener The callback to be removed.
   */
  off(eventName, listener) {
    const eventListeners = this.events.get(eventName);
    if (eventListeners) {
      eventListeners.delete(listener);
      if (eventListeners.size === 0) {
        this.events.delete(eventName);
      }
    }
  }
  /**
   * Emits an event to all registered listeners.
   * @param eventName The name of the event to emit.
   * @param event The event payload.
   */
  emit(eventName, event) {
    for (const callback2 of this.events.get(eventName) ?? []) {
      const result = callback2(event);
      if (result) {
        result.catch((e) => Logger.error(e));
      }
    }
  }
  /**
   * Clears all listeners for a specific event or all events if no event name is provided.
   * @param eventName (Optional) The name of the event to clear listeners for. If not provided, all listeners for all events are cleared.
   */
  clear(eventName) {
    if (eventName) {
      this.events.delete(eventName);
    } else {
      this.events.clear();
    }
  }
};
var LayoutElement = /* @__PURE__ */ ((LayoutElement2) => {
  LayoutElement2[LayoutElement2["Caption"] = 0] = "Caption";
  LayoutElement2[LayoutElement2["Legend"] = 1] = "Legend";
  LayoutElement2[LayoutElement2["ToolbarLeft"] = 2] = "ToolbarLeft";
  LayoutElement2[LayoutElement2["ToolbarBottom"] = 3] = "ToolbarBottom";
  LayoutElement2[LayoutElement2["Navigator"] = 4] = "Navigator";
  LayoutElement2[LayoutElement2["Overlay"] = 5] = "Overlay";
  return LayoutElement2;
})(LayoutElement || {});
var LayoutManager = class {
  constructor() {
    this.events = new EventEmitter();
    this.elements = /* @__PURE__ */ new Map();
  }
  addListener(eventName, listener) {
    return this.events.on(eventName, listener);
  }
  registerElement(element2, listener) {
    if (this.elements.has(element2)) {
      this.elements.get(element2).add(listener);
    } else {
      this.elements.set(element2, /* @__PURE__ */ new Set([listener]));
    }
    return () => this.elements.get(element2)?.delete(listener);
  }
  createContext(width2, height2) {
    const context = new LayoutContext(width2, height2);
    for (const element2 of Object.values(LayoutElement)) {
      if (typeof element2 !== "number")
        continue;
      this.elements.get(element2)?.forEach((listener) => {
        listener(context)?.catch((e) => Logger.error(e));
      });
    }
    return context;
  }
  emitLayoutComplete(context, options) {
    const eventType = "layout:complete";
    const { width: width2, height: height2 } = context;
    this.events.emit(eventType, {
      type: eventType,
      axes: options.axes ?? [],
      chart: { width: width2, height: height2 },
      clipSeries: options.clipSeries ?? false,
      series: options.series
    });
  }
};
var LayoutContext = class {
  constructor(width2, height2) {
    this.width = width2;
    this.height = height2;
    this.layoutBox = new BBox(0, 0, width2, height2);
  }
};
var ChartCaptions = class {
  constructor() {
    this.title = new Caption();
    this.subtitle = new Caption();
    this.footnote = new Caption();
  }
  positionCaptions(ctx) {
    const { title, subtitle, footnote } = this;
    const maxHeight = ctx.layoutBox.height / 10;
    if (title.enabled) {
      const { spacing = subtitle.enabled ? Caption.SMALL_PADDING : Caption.LARGE_PADDING } = title;
      this.positionCaption("top", title, ctx.layoutBox, maxHeight);
      this.shrinkLayoutByCaption("top", title, ctx.layoutBox, spacing);
    }
    if (subtitle.enabled) {
      this.positionCaption("top", subtitle, ctx.layoutBox, maxHeight);
      this.shrinkLayoutByCaption("top", subtitle, ctx.layoutBox, subtitle.spacing);
    }
    if (footnote.enabled) {
      this.positionCaption("bottom", footnote, ctx.layoutBox, maxHeight);
      this.shrinkLayoutByCaption("bottom", footnote, ctx.layoutBox, footnote.spacing);
    }
  }
  positionAbsoluteCaptions(ctx) {
    const { title, subtitle, footnote } = this;
    const { rect } = ctx.series;
    for (const caption of [title, subtitle, footnote]) {
      if (caption.layoutStyle !== "overlay")
        continue;
      if (caption.textAlign === "left") {
        caption.node.x = rect.x + caption.padding;
      } else if (caption.textAlign === "right") {
        const bbox = caption.node.getBBox();
        caption.node.x = rect.x + rect.width - bbox.width - caption.padding;
      }
    }
  }
  computeX(align, layoutBox) {
    if (align === "left") {
      return layoutBox.x;
    } else if (align === "right") {
      return layoutBox.x + layoutBox.width;
    }
    return layoutBox.x + layoutBox.width / 2;
  }
  positionCaption(vAlign, caption, layoutBox, maxHeight) {
    const containerHeight = Math.max(TextUtils.getLineHeight(caption.fontSize), maxHeight);
    caption.node.x = this.computeX(caption.textAlign, layoutBox) + caption.padding;
    caption.node.y = layoutBox.y + (vAlign === "top" ? 0 : layoutBox.height) + caption.padding;
    caption.node.textBaseline = vAlign;
    caption.computeTextWrap(layoutBox.width, containerHeight);
  }
  shrinkLayoutByCaption(vAlign, caption, layoutBox, spacing = 0) {
    if (caption.layoutStyle === "block") {
      const bbox = caption.node.getBBox();
      layoutBox.shrink(
        vAlign === "top" ? Math.ceil(bbox.y - layoutBox.y + bbox.height + spacing) : Math.ceil(layoutBox.y + layoutBox.height - bbox.y + spacing),
        vAlign
      );
    }
  }
};
__decorateClass([
  Validate(OBJECT)
], ChartCaptions.prototype, "title", 2);
__decorateClass([
  Validate(OBJECT)
], ChartCaptions.prototype, "subtitle", 2);
__decorateClass([
  Validate(OBJECT)
], ChartCaptions.prototype, "footnote", 2);
var chartTypes = [
  "candlestick",
  "hollow-candlestick",
  "ohlc",
  "line",
  "step-line",
  "hlc",
  "high-low"
];
var ChartTypeOriginator = class {
  constructor(chartService) {
    this.chartService = chartService;
    this.mementoOriginatorKey = "chartType";
  }
  createMemento() {
    let chartType2 = this.chartService.publicApi?.getOptions()?.chartType;
    if (chartType2 == null)
      chartType2 = "candlestick";
    return chartType2;
  }
  guardMemento(blob) {
    return blob == null || isString(blob) && includes(chartTypes, blob);
  }
  restoreMemento(_version, _mementoVersion, memento) {
    if (memento == null)
      return;
    const options = { chartType: memento };
    this.chartService.publicApi?.updateDelta(options).catch((e) => Logger.error("error restoring state", e));
  }
};
var Listeners = class {
  constructor() {
    this.registeredListeners = /* @__PURE__ */ new Map();
  }
  addListener(eventType, handler) {
    const record = { symbol: Symbol(eventType), handler };
    if (this.registeredListeners.has(eventType)) {
      this.registeredListeners.get(eventType).push(record);
    } else {
      this.registeredListeners.set(eventType, [record]);
    }
    return () => this.removeListener(record.symbol);
  }
  removeListener(eventSymbol) {
    for (const [type, listeners] of this.registeredListeners.entries()) {
      const matchIndex = listeners.findIndex((listener) => listener.symbol === eventSymbol);
      if (matchIndex >= 0) {
        listeners.splice(matchIndex, 1);
        if (listeners.length === 0) {
          this.registeredListeners.delete(type);
        }
        break;
      }
    }
  }
  dispatch(eventType, ...params) {
    for (const listener of this.getListenersByType(eventType)) {
      try {
        listener.handler(...params);
      } catch (e) {
        Logger.errorOnce(e);
      }
    }
  }
  dispatchWrapHandlers(eventType, wrapFn, ...params) {
    for (const listener of this.getListenersByType(eventType)) {
      try {
        wrapFn(listener.handler, ...params);
      } catch (e) {
        Logger.errorOnce(e);
      }
    }
  }
  getListenersByType(eventType) {
    return this.registeredListeners.get(eventType) ?? [];
  }
  destroy() {
    this.registeredListeners.clear();
  }
};
var BaseManager = class {
  constructor() {
    this.listeners = new Listeners();
    this.destroyFns = [];
  }
  addListener(type, handler) {
    return this.listeners.addListener(type, handler);
  }
  destroy() {
    this.listeners.destroy();
    this.destroyFns.forEach((fn) => fn());
  }
};
var InteractionState = /* @__PURE__ */ ((InteractionState2) => {
  InteractionState2[InteractionState2["Default"] = 32] = "Default";
  InteractionState2[InteractionState2["ZoomDrag"] = 16] = "ZoomDrag";
  InteractionState2[InteractionState2["Annotations"] = 8] = "Annotations";
  InteractionState2[InteractionState2["ContextMenu"] = 4] = "ContextMenu";
  InteractionState2[InteractionState2["Animation"] = 2] = "Animation";
  InteractionState2[InteractionState2["AnnotationsSelected"] = 1] = "AnnotationsSelected";
  InteractionState2[InteractionState2["All"] = 63] = "All";
  return InteractionState2;
})(InteractionState || {});
var InteractionStateListener = class extends BaseManager {
  // Wrapper to only broadcast events when the InteractionManager is a given state.
  addListener(type, handler, triggeringStates = 32) {
    return super.addListener(type, (e) => {
      const currentState = this.getState();
      if (currentState & triggeringStates) {
        handler(e);
      }
    });
  }
};
var DestroyFns = class {
  constructor() {
    this.destroyFns = [];
  }
  destroy() {
    this.destroyFns.forEach((fn) => fn());
    this.destroyFns.length = 0;
  }
  setFns(destroyFns) {
    this.destroy();
    this.destroyFns = destroyFns;
  }
  push(...destroyFns) {
    this.destroyFns.push(...destroyFns);
  }
};
var VERSION = "11.0.0";
var NOT_FOUND = Symbol("previous-memento-not-found");
var HistoryManager = class {
  constructor(keyNavManager) {
    this.history = [];
    this.historyIndex = -1;
    this.originators = /* @__PURE__ */ new Map();
    this.clearState = /* @__PURE__ */ new Map();
    this.maxHistoryLength = 100;
    this.debug = Debug.create(true, "history");
    this.destroyFns = new DestroyFns();
    this.destroyFns.setFns([
      keyNavManager.addListener(
        "undo",
        this.undo.bind(this),
        63
        /* All */
      ),
      keyNavManager.addListener(
        "redo",
        this.redo.bind(this),
        63
        /* All */
      )
    ]);
  }
  destroy() {
    this.destroyFns.destroy();
  }
  addMementoOriginator(originator) {
    this.originators.set(originator.mementoOriginatorKey, originator);
    this.clearState.set(originator.mementoOriginatorKey, originator.createMemento());
    this.debugEvent("History add originator:", originator.mementoOriginatorKey);
  }
  clear() {
    this.debug(`History clear:`, Object.keys(this.originators));
    this.history = [];
    this.historyIndex = -1;
    for (const [mementoOriginatorKey, originator] of this.originators.entries()) {
      this.clearState.set(mementoOriginatorKey, originator.createMemento());
    }
  }
  record(label, ...originators) {
    if (this.historyIndex < this.history.length - 1) {
      this.history = this.history.slice(0, this.historyIndex + 1);
    }
    if (this.history.length > this.maxHistoryLength) {
      this.history = this.history.slice(-this.maxHistoryLength);
    }
    const mementos = /* @__PURE__ */ new Map();
    for (const originator of originators) {
      if (!this.originators.has(originator.mementoOriginatorKey)) {
        throw new Error(
          `Originator [${originator.mementoOriginatorKey}] has not been added to the HistoryManager.`
        );
      }
      mementos.set(originator.mementoOriginatorKey, originator.createMemento());
    }
    this.history.push({ label, mementos });
    this.historyIndex = this.history.length - 1;
    this.debugEvent(`History record: [${label}]`);
  }
  undo() {
    const undoAction = this.history[this.historyIndex];
    if (!undoAction)
      return;
    for (const mementoOriginatorKey of undoAction.mementos.keys()) {
      const previousMemento = this.findPreviousMemento(mementoOriginatorKey);
      if (previousMemento === NOT_FOUND) {
        throw new Error(`Could not find previous memento for [${mementoOriginatorKey}].`);
      }
      this.restoreMemento(mementoOriginatorKey, previousMemento);
    }
    this.historyIndex -= 1;
    this.debugEvent(`History undo: [${undoAction.label}]`);
  }
  redo() {
    const redoAction = this.history[this.historyIndex + 1];
    if (!redoAction)
      return;
    for (const [mementoOriginatorKey, memento] of redoAction.mementos.entries()) {
      this.restoreMemento(mementoOriginatorKey, memento);
    }
    this.historyIndex += 1;
    this.debugEvent(`History redo: [${redoAction.label}]`);
  }
  findPreviousMemento(mementoOriginatorKey) {
    for (let i = this.historyIndex - 1; i >= 0; i--) {
      if (this.history[i].mementos.has(mementoOriginatorKey)) {
        return this.history[i].mementos.get(mementoOriginatorKey);
      }
    }
    if (this.clearState.has(mementoOriginatorKey)) {
      return this.clearState.get(mementoOriginatorKey);
    }
    return NOT_FOUND;
  }
  restoreMemento(mementoOriginatorKey, memento) {
    this.originators.get(mementoOriginatorKey)?.restoreMemento(VERSION, VERSION, memento);
  }
  debugEvent(...logContent) {
    this.debug(
      ...logContent,
      this.history.map((action, index) => index === this.historyIndex ? `** ${action.label} **` : action.label)
    );
  }
};
var MementoCaretaker = class _MementoCaretaker {
  constructor(version) {
    this.version = version.split("-")[0];
  }
  save(...originators) {
    const packet = { version: this.version };
    for (const originator of Object.values(originators)) {
      packet[originator.mementoOriginatorKey] = this.encode(originator, originator.createMemento());
    }
    return packet;
  }
  restore(blob, ...originators) {
    if (typeof blob !== "object") {
      Logger.warnOnce(`Could not restore data of type [${typeof blob}], expecting an object, ignoring.`);
      return;
    }
    if (blob == null) {
      Logger.warnOnce(`Could not restore data of type [null], expecting an object, ignoring.`);
      return;
    }
    if (!("version" in blob) || typeof blob.version !== "string") {
      Logger.warnOnce(`Could not restore data, missing [version] string in object, ignoring.`);
      return;
    }
    for (const originator of originators) {
      const memento = this.decode(originator, blob[originator.mementoOriginatorKey]);
      if (!originator.guardMemento(memento)) {
        Logger.warnOnce(
          `Could not restore [${originator.mementoOriginatorKey}] data, value was invalid, ignoring.`,
          memento
        );
        return;
      }
      originator.restoreMemento(this.version, blob.version, memento);
    }
  }
  /**
   * Encode a memento as a serializable object, encoding any non-serializble types.
   */
  encode(originator, memento) {
    try {
      return JSON.parse(JSON.stringify(memento, _MementoCaretaker.encodeTypes));
    } catch (error) {
      throw new Error(`Failed to encode [${originator.mementoOriginatorKey}] value [${error}].`, {
        cause: error
      });
    }
  }
  /**
   * Decode an encoded memento, decoding any non-serializable types.
   */
  decode(originator, encoded) {
    if (encoded == null)
      return encoded;
    try {
      return JSON.parse(JSON.stringify(encoded), _MementoCaretaker.decodeTypes);
    } catch (error) {
      throw new Error(`Failed to decode [${originator.mementoOriginatorKey}] value [${error}].`, {
        cause: error
      });
    }
  }
  static encodeTypes(key, value) {
    if (isDate(this[key])) {
      return { __type: "date", value: this[key].toISOString() };
    }
    return value;
  }
  static decodeTypes(key, value) {
    if (isObject(this[key]) && "__type" in this[key] && this[key].__type === "date") {
      return new Date(this[key].value);
    }
    return value;
  }
};
var StateManager = class {
  constructor() {
    this.caretaker = new MementoCaretaker(VERSION);
    this.state = /* @__PURE__ */ new Map();
  }
  setState(originator, value) {
    if (objectsEqual(this.state.get(originator.mementoOriginatorKey), value)) {
      return;
    }
    this.setStateAndRestore(originator, value);
  }
  setStateAndRestore(originator, value) {
    this.state.set(originator.mementoOriginatorKey, value);
    this.restoreState(originator);
  }
  restoreState(originator) {
    const { caretaker, state } = this;
    if (!state.has(originator.mementoOriginatorKey))
      return;
    const value = state.get(originator.mementoOriginatorKey);
    caretaker.restore({ version: caretaker.version, [originator.mementoOriginatorKey]: value }, originator);
  }
};
var styles_default = '.ag-charts-wrapper,.ag-charts-wrapper:after,.ag-charts-wrapper:before,.ag-charts-wrapper *,.ag-charts-wrapper *:after,.ag-charts-wrapper *:before{box-sizing:border-box}.ag-charts-wrapper{position:relative;user-select:none}.ag-charts-tab-guard{width:0%;height:0%;position:absolute;pointer-events:none}.ag-charts-canvas-center{width:100%;height:100%;position:absolute;touch-action:auto;pointer-events:auto;display:flex;align-items:var(--ag-charts-align);justify-content:var(--ag-charts-justify)}.ag-charts-canvas-container,.ag-charts-canvas{position:relative;user-select:none}.ag-charts-canvas-container>*,.ag-charts-canvas>*{display:block;pointer-events:none}.ag-charts-series-area{outline:none;pointer-events:none;position:absolute}.ag-charts-swapchain{outline:none;opacity:0;pointer-events:auto;position:absolute;width:100%;height:100%}.ag-charts-swapchain:focus-visible{opacity:1}.ag-charts-canvas-proxy,.ag-charts-canvas-overlay{inset:0;pointer-events:none;position:absolute;user-select:none}.ag-charts-canvas-overlay>*{position:absolute;pointer-events:auto}.ag-charts-theme-default,.ag-charts-theme-default-dark{--ag-charts-active-color: var(--ag-active-color, #2196f3);--ag-charts-background-color: var(--ag-background-color, #fff);--ag-charts-foreground-color: var(--ag-foreground-color, #181d1f);--ag-charts-border-color: var(--ag-border-color, #dddddd);--ag-charts-hover-color: color-mix(in srgb, var(--ag-charts-background-color), var(--ag-charts-active-color) 12%);--ag-charts-font-family: "Verdana", sans-serif;--ag-charts-font-size: var(--ag-font-size, 14px);--ag-charts-size: var(--ag-grid-size, 8px);--ag-charts-border: var(--ag-charts-border-color) var(--ag-borders, solid 1px);--ag-charts-border-critical: var(--ag-borders-critical, solid 1px);--ag-charts-floating-shadow: 0 2px 8px 0 color-mix(in srgb, black 8%, transparent);--ag-charts-layer-ui-overlay: 5;--ag-charts-layer-tooltip: 4;--ag-charts-layer-toolbar: 3;--ag-charts-layer-crosshair: 2;--ag-charts-layer-annotations: 1;--ag-charts-align: center;--ag-charts-justify: center;--ag-charts-axis-label-background-color: #474747;--ag-charts-axis-label-color: #ffffff;--ag-charts-tooltip-background-color: #fafafb;--ag-charts-tooltip-text-color: var(--ag-charts-foreground-color);--ag-charts-tooltip-border: 1px solid var(--ag-charts-border-color);--ag-charts-content-padding: 8px 12px;--ag-charts-content-gap: 8px;--ag-charts-content-compact-padding: 3px 6px;--ag-charts-tooltip-border-radius: 4px;--ag-charts-toolbar-foreground-color: var(--ag-header-foreground-color, var(--ag-charts-foreground-color));--ag-charts-toolbar-background-color: var( --ag-header-background-color, color-mix(in srgb, var(--ag-charts-background-color), var(--ag-charts-foreground-color) 2%) );--ag-charts-toolbar-shadow: var(--ag-charts-floating-shadow);--ag-charts-toolbar-size: 34px;--ag-charts-toolbar-size-small: 24px;--ag-charts-toolbar-border: var(--ag-charts-border-critical, solid 1px) var(--ag-charts-border-color);--ag-charts-toolbar-hover-color: color-mix( in srgb, var(--ag-charts-background-color), var(--ag-charts-active-color) 12% );--ag-charts-toolbar-focus-color: var(--ag-charts-active-color);--ag-charts-toolbar-active-background-color: var(--ag-charts-toolbar-hover-color);--ag-charts-toolbar-active-color: var(--ag-charts-active-color);--ag-charts-toolbar-disabled-foreground-color: var( --ag-disabled-foreground-color, color-mix(in srgb, transparent, var(--ag-charts-toolbar-foreground-color) 50%) );--ag-charts-toolbar-disabled-background-color: color-mix( in srgb, var(--ag-charts-toolbar-background-color), var(--ag-charts-toolbar-foreground-color) 6% );--ag-charts-toolbar-gap: var(--ag-charts-size);--ag-charts-toolbar-font-size: 13px;--ag-charts-toolbar-font-size-small: 12px;--ag-charts-toolbar-button-padding: 6px;--ag-charts-toolbar-button-padding-small: 1px;--ag-charts-popover-background-color: var(--ag-charts-toolbar-background-color);--ag-charts-popover-foreground-color: var(--ag-charts-toolbar-foreground-color);--ag-charts-popover-border: var(--ag-charts-toolbar-border);--ag-charts-popover-border-radius: var(--ag-border-radius, 4px);--ag-charts-popover-active-color: var(--ag-charts-toolbar-active-color);--ag-charts-popover-hover-color: var(--ag-charts-toolbar-hover-color);--ag-charts-popover-active-background-color: var(--ag-charts-toolbar-active-background-color);--ag-charts-popover-font-size: 14px;--ag-charts-popover-font-size-small: var(--ag-charts-toolbar-font-size-small);--ag-charts-popover-shadow: var(--ag-charts-floating-shadow);--ag-charts-dialog-input-group-label-color: color-mix(in srgb, transparent, var(--ag-charts-foreground-color) 55%);--ag-charts-dialog-tab-color--inactive: color-mix(in srgb, transparent, var(--ag-charts-foreground-color) 55%);--ag-charts-button-radius: var(--ag-border-radius, 4px);--ag-charts-focus-border-color: var(--ag-input-focus-border-color, var(--ag-charts-active-color));--ag-charts-focus-border: solid 1px var(--ag-charts-focus-border-color);--ag-charts-focus-border-shadow: var( --ag-input-focus-box-shadow, 0 0 0 3px color-mix(in srgb, transparent, var(--ag-input-focus-border-color, var(--ag-charts-active-color)) 20%) );--ag-charts-focus-box-shadow: var(--box-shadow), 0 0 0 2px #fff8, var(--ag-charts-focus-border-shadow);--ag-charts-icon-font-family: "agChartsDefault";--ag-charts-icon-font-weight: normal;--ag-charts-icon-font-color: color-mix(in srgb, transparent, var(--ag-charts-foreground-color), 90%);--ag-charts-icon-size: 20px;--ag-charts-input-background-color: var(--ag-charts-background-color);--ag-charts-input-background-color--hover: var(--ag-charts-hover-color);--ag-charts-input-background-color--active: var(--ag-charts-hover-color);--ag-charts-input-border-color: var(--ag-charts-border-color);--ag-charts-input-border-color--active: var(--ag-charts-active-color);--ag-charts-input-border-radius: var(--ag-border-radius, 4px);--ag-charts-input-color--active: var(--ag-charts-active-color);--ag-charts-input-focus-outline: var(--ag-charts-focus-border);--ag-charts-input-focus-box-shadow: var(--ag-charts-focus-border-shadow);--ag-charts-input-font-family: var(--ag-charts-font-family);--ag-charts-input-font-size: var(--ag-charts-font-size);--ag-charts-input-padding: 8px;--ag-charts-input-padding-large: 10px;--ag-charts-input-placeholder-color: #888888;--ag-charts-input-spacing: 8px;--ag-charts-input-transition-duration: .25s;--ag-charts-input-transition-duration--fast: .1s;--ag-charts-input-transition-timing-function: ease-out;--ag-charts-input-checkbox-background-color: #babbbc;--ag-charts-input-checkbox-background-color--checked: var(--ag-charts-active-color)}.ag-charts-theme-default-dark{--ag-charts-background-color: var(--ag-background-color, color-mix(in srgb, #fff, #182230 97%));--ag-charts-foreground-color: var(--ag-foreground-color, #fff);--ag-charts-border-color: var(--ag-border-color, rgba(255, 255, 255, .16));--ag-charts-hover-color: color-mix(in srgb, var(--ag-charts-background-color), var(--ag-charts-active-color) 18%);--ag-charts-floating-shadow: 0 2px 12px 0 color-mix(in srgb, black 33.3%, transparent);--ag-charts-axis-label-background-color: #9caebb;--ag-charts-axis-label-color: #000000;--ag-charts-tooltip-background-color: #28313e;--ag-charts-tooltip-border: 1px solid #474e59;--ag-charts-toolbar-background-color: var(--ag-header-background-color, color-mix(in srgb, #fff, #182230 93%));--ag-charts-toolbar-hover-color: color-mix( in srgb, var(--ag-charts-background-color), var(--ag-charts-active-color) 18% );--ag-charts-dialog-input-group-label-text-color: #ffffff;--ag-charts-focus-border-shadow: var( --ag-input-focus-box-shadow, 0 0 0 3px color-mix(in srgb, transparent, var(--ag-input-focus-border-color, var(--ag-charts-active-color)) 20%) );--ag-charts-input-placeholder-color: #aaaaaa}.ag-charts-icon{display:block;width:var(--ag-charts-icon-size);height:var(--ag-charts-icon-size);speak:none;speak:never;mask:var(--icon) center / contain no-repeat;background-color:currentColor;transition:background-color .25s ease-in-out}.ag-charts-icon-align-center{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNNyAxMGg2djFIN3pNNCA3aDEydjFINHptMSA2aDEwdjFINXoiLz48L3N2Zz4=)}.ag-charts-icon-align-left{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNNCAxMGg2djFINHptMC0zaDEydjFINHptMCA2aDEwdjFINHoiLz48L3N2Zz4=)}.ag-charts-icon-align-right{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMTAgMTBoNnYxaC02ek00IDdoMTJ2MUg0em0yIDZoMTB2MUg2eiIvPjwvc3ZnPg==)}.ag-charts-icon-arrow-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE1LjI5MyA0LjVIMTIuNXYtMUgxN3Y0aC0xVjUuMjA3bC05LjY0NiA5LjY0Ny0uNzA4LS43MDh6IiBmaWxsPSIjMDAwIi8+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDE2YTIuNSAyLjUgMCAxIDEtNSAwIDIuNSAyLjUgMCAwIDEgNSAwbS0yLjUgMS41YTEuNSAxLjUgMCAxIDAgMC0zIDEuNSAxLjUgMCAwIDAgMCAzIiBmaWxsPSIjMDAwIi8+PC9zdmc+)}.ag-charts-icon-arrow-down-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02IDhMMS41IDhMMTAgMThMMTguNSA4TDE0IDhMMTQgM0w2IDNMNiA4Wk03IDRMNyA5SDMuNjYyNDRMMTAgMTYuNDU2TDE2LjMzNzYgOUwxMyA5TDEzIDRMNyA0WiIgZmlsbD0iYmxhY2siLz4KPC9zdmc+Cg==)}.ag-charts-icon-arrow-up-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNCAxMkgxOC41TDEwIDJMMS41IDEySDZMNi4wMDAwMiAxN0gxNFYxMlpNMTMgMTZWMTFIMTYuMzM3NkwxMCAzLjU0NDA1TDMuNjYyNDQgMTFIN0w3LjAwMDAyIDE2SDEzWiIgZmlsbD0iYmxhY2siLz4KPC9zdmc+Cg==)}.ag-charts-icon-callout-annotation{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMyA0LjVBMS41IDEuNSAwIDAgMSA0LjUgM2gxMUExLjUgMS41IDAgMCAxIDE3IDQuNXY4YTEuNSAxLjUgMCAwIDEtMS41IDEuNWgtNC41MTRhMjYgMjYgMCAwIDAtMi4wMTcgMS41NGwtLjMxNC4yNmMtLjU1LjQ1Ny0xLjExNS45MjYtMS43NiAxLjQtLjY2OS40OTEtMS41NjItLjAxMi0xLjU2Mi0uOFYxNEg0LjVBMS41IDEuNSAwIDAgMSAzIDEyLjV6TTQuNSA0YS41LjUgMCAwIDAtLjUuNXY4YS41LjUgMCAwIDAgLjUuNWgxLjgzM3YzLjM3MmEzNiAzNiAwIDAgMCAxLjY3OC0xLjMzOGwuMzItLjI2NWEyNiAyNiAwIDAgMSAyLjIyNS0xLjY4NWwuMTI2LS4wODRIMTUuNWEuNS41IDAgMCAwIC41LS41di04YS41LjUgMCAwIDAtLjUtLjV6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-candlestick-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNyAxdjNoMnYxMkg3djNINnYtM0g0VjRoMlYxek01IDVoM3YxMEg1ek0xMSAxNFY2aDJWMy4yNWgxVjZoMnY4aC0ydjIuNzVoLTFWMTR6bTEtN2gzdjZoLTN6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-close{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNSA1IDEwIDEwTTUgMTUgMTUgNSIgc3Ryb2tlPSIjMDAwIi8+PC9zdmc+)}.ag-charts-icon-comment-annotation{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNy41MTMgMy45OTVhNi41IDYuNSAwIDAgMSA2LjA5OCAxMS40MWMtLjU4OC4zOTMtMS4yMTcuNTM2LTEuODI5LjU4NWExMyAxMyAwIDAgMS0xLjI3LjAxN0EyNyAyNyAwIDAgMCAxMCAxNkg0LjVhLjUuNSAwIDAgMS0uNS0uNVYxMHEwLS4yNDctLjAwNy0uNTEzYy0uMDA4LS40MTYtLjAxNi0uODU3LjAxNy0xLjI2OS4wNS0uNjEyLjE5Mi0xLjI0LjU4NS0xLjgzYTYuNSA2LjUgMCAwIDEgMi45MTgtMi4zOTNtMy41Ni42MWE1LjUgNS41IDAgMCAwLTUuNjQ2IDIuMzRjLS4yNjYuMzk3LS4zNzkuODQyLS40MiAxLjM1NC0uMDMuMzYtLjAyMi43MTgtLjAxNSAxLjEwOFE1IDkuNjg5IDUgMTB2NWg1cS4zMTEuMDAxLjU5My4wMDhjLjM5LjAwNy43NDcuMDE1IDEuMTA4LS4wMTUuNTEyLS4wNDEuOTU3LS4xNTQgMS4zNTUtLjQyYTUuNSA1LjUgMCAwIDAtMS45ODMtOS45NjciIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-crosshair-add-line{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZD0iTTEwIDUuNWEuNS41IDAgMCAxIC41LjV2My41aDMuODc1YS41LjUgMCAwIDEgMCAxSDEwLjV2NC4yNWEuNS41IDAgMSAxLTEgMFYxMC41SDUuNjI1YS41LjUgMCAxIDEgMC0xSDkuNVY2YS41LjUgMCAwIDEgLjUtLjUiLz48L3N2Zz4=)}.ag-charts-icon-date-range-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMiAyaDF2MTZIMnptMTUgMGgxdjE2aC0xeiIgZmlsbD0iIzE4MUQxRiIvPjxwYXRoIGQ9Ik0xMy4xNTcgMTFINXYtMWg3Ljc5M0wxMSA4LjIwN2wuNzA3LS43MDcgMy4xODIgMy4xODItMy4xODIgMy4xODItLjcwNy0uNzA3eiIgZmlsbD0iIzAwMCIvPjwvc3ZnPg==)}.ag-charts-icon-date-price-range-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMyAySDJ2MTZoMXptMy41MDcgNC44OUw4LjUgNC44OTVWMTBINXYxaDMuNXY3aDF2LTdoNS4wODhsLTEuOTU3IDEuOTU3LjcwNy43MDcgMy4xODItMy4xODJMMTMuMzM4IDcuM2wtLjcwNy43MDdMMTQuNjI0IDEwSDkuNVY0LjkzMmwxLjk1NyAxLjk1Ny43MDctLjcwN0w4Ljk4MiAzIDUuOCA2LjE4MnoiIGZpbGw9IiMxODFEMUYiLz48L3N2Zz4=)}.ag-charts-icon-delete{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZD0iTTguNDk2IDguOTk2QS41LjUgMCAwIDEgOSA5LjQ5MnY0YS41LjUgMCAxIDEtMSAuMDA4di00YS41LjUgMCAwIDEgLjQ5Ni0uNTA0TTEyIDkuNWEuNS41IDAgMCAwLTEgMHY0YS41LjUgMCAwIDAgMSAweiIvPjxwYXRoIGZpbGw9IiMxMzE3MjIiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTYgNVYzLjVBMi41IDIuNSAwIDAgMSA4LjUgMWgzQTIuNSAyLjUgMCAwIDEgMTQgMy41VjVoMi44MzNhLjUuNSAwIDAgMSAwIDFIMTV2MTAuMjVjMCAuNDE1LS4wNjYuODYzLS4zIDEuMjIxLS4yNTcuMzk0LS42NzIuNjEyLTEuMi42MTJoLTdjLS41MjggMC0uOTQzLS4yMTgtMS4yLS42MTItLjIzNC0uMzU4LS4zLS44MDYtLjMtMS4yMjFWNkgzLjMzM2EuNS41IDAgMCAxIDAtMXptMS0xLjVBMS41IDEuNSAwIDAgMSA4LjUgMmgzQTEuNSAxLjUgMCAwIDEgMTMgMy41VjVIN3pNNiAxNi4yNVY2aDh2MTAuMjVjMCAuMzM1LS4wNTkuNTU0LS4xMzguNjc1LS4wNTUuMDg1LS4xNC4xNTgtLjM2Mi4xNThoLTdjLS4yMjIgMC0uMzA3LS4wNzMtLjM2Mi0uMTU4LS4wOC0uMTIxLS4xMzgtLjM0LS4xMzgtLjY3NSIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.ag-charts-icon-disjoint-channel,.ag-charts-icon-disjoint-channel-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTkuMDI4IDE3LjQ2YTIuMjUgMi4yNSAwIDAgMC00LjA5Mi0xLjg1bC05LjUxMS0yLjM3OGEyLjI1IDIuMjUgMCAxIDAtLjIyNS45NzRsOS40NzUgMi4zNjlhMi4yNTEgMi4yNTEgMCAwIDAgNC4zNTMuODg2bS0xLjY2Mi0xLjk2NWExLjI1IDEuMjUgMCAxIDEtLjg4NSAyLjMzOCAxLjI1IDEuMjUgMCAwIDEgLjg4NS0yLjMzOE00LjM0MyAxMy42NjlhMS4yNSAxLjI1IDAgMSAwLTIuMzM4LS44ODUgMS4yNSAxLjI1IDAgMCAwIDIuMzM4Ljg4NU0zLjk3IDguNzY5YTIuMjUgMi4yNSAwIDAgMCAxLjQ1NS0yLjExbDkuNTExLTIuMzc4YTIuMjUgMi4yNSAwIDEgMC0uMjYtLjk2NUw1LjIgNS42ODVhMi4yNSAyLjI1IDAgMSAwLTEuMjMgMy4wODRtLjM3My0yLjU0N2ExLjI1IDEuMjUgMCAxIDEtMi4zMzguODg1IDEuMjUgMS4yNSAwIDAgMSAyLjMzOC0uODg1bTEzLjc1LTMuNDM4YTEuMjUgMS4yNSAwIDEgMS0yLjMzOC44ODUgMS4yNSAxLjI1IDAgMCAxIDIuMzM4LS44ODUiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-drag-handle{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSI1Ljc1IiBjeT0iNy43NSIgcj0iLjc1IiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii41Ii8+PGNpcmNsZSBjeD0iOS43NSIgY3k9IjcuNzUiIHI9Ii43NSIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNSIvPjxjaXJjbGUgY3g9IjEzLjc1IiBjeT0iNy43NSIgcj0iLjc1IiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii41Ii8+PGNpcmNsZSBjeD0iMTMuNzUiIGN5PSIxMS43NSIgcj0iLjc1IiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii41Ii8+PGNpcmNsZSBjeD0iOS43NSIgY3k9IjExLjc1IiByPSIuNzUiIGZpbGw9IiMwMDAiIGZpbGwtb3BhY2l0eT0iLjUiLz48Y2lyY2xlIGN4PSI1Ljc1IiBjeT0iMTEuNzUiIHI9Ii43NSIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuNSIvPjwvc3ZnPg==)}.ag-charts-icon-fibonacci-retracement-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMiA1aDEydjFIMnoiLz48Y2lyY2xlIGN4PSIxNS43NSIgY3k9IjUuNSIgcj0iMS43NSIgc3Ryb2tlPSIjMDAwIi8+PGNpcmNsZSBjeD0iNC4yNSIgY3k9IjE0LjUiIHI9IjEuNzUiIHN0cm9rZT0iIzAwMCIvPjxwYXRoIGZpbGw9IiMwMDAiIGQ9Ik0xOCAxNUg2di0xaDEyem0wLTQuNUgydi0xaDE2eiIvPjwvc3ZnPg==)}.ag-charts-icon-fill-color{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJtOC4wNzEgNC4wNi0uOTI0LS45MjQuNzA3LS43MDcgNy4yODggNy4yODgtNC45NSA0Ljk1YTMuNSAzLjUgMCAwIDEtNC45NSAwbC0xLjQxNC0xLjQxNGEzLjUgMy41IDAgMCAxIDAtNC45NXptLjcwNy43MDhMNC41MzYgOS4wMWEyLjUgMi41IDAgMCAwIDAgMy41MzZMNS45NSAxMy45NmEyLjUgMi41IDAgMCAwIDMuNTM1IDBsNC4yNDMtNC4yNDN6bTYuOSA3LjIwMi0uMzQ1LjM2My0uMzQ0LS4zNjNhLjUuNSAwIDAgMSAuNjg4IDBtLS4zNDUgMS4wOGE4IDggMCAwIDAtLjI4LjMyMyA0LjMgNC4zIDAgMCAwLS40MDkuNTgyYy0uMTEzLjIwMS0uMTQ0LjMyNi0uMTQ0LjM3OGEuODMzLjgzMyAwIDAgMCAxLjY2NyAwYzAtLjA1Mi0uMDMxLS4xNzctLjE0NC0uMzc4YTQuMyA0LjMgMCAwIDAtLjQxLS41ODIgOCA4IDAgMCAwLS4yOC0uMzIybS0uMzQ0LTEuMDguMzQ0LjM2My4zNDQtLjM2My4wMDIuMDAyLjAwNC4wMDQuMDEzLjAxMmE2IDYgMCAwIDEgLjIwNi4yMDhjLjEzMS4xMzYuMzA4LjMyNy40ODUuNTQ1LjE3Ni4yMTUuMzYzLjQ2Ny41MDcuNzI0LjEzNy4yNDMuMjczLjU1My4yNzMuODY4YTEuODMzIDEuODMzIDAgMSAxLTMuNjY3IDBjMC0uMzE1LjEzNi0uNjI1LjI3My0uODY4LjE0NC0uMjU3LjMzLS41MDkuNTA3LS43MjRhOSA5IDAgMCAxIC42NDUtLjcwOGwuMDQ2LS4wNDUuMDEzLS4wMTIuMDA0LS4wMDR6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-hollow-candlestick-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1vcGFjaXR5PSIuMTUiIGQ9Ik01IDVoM3YxMEg1eiIvPjxwYXRoIGZpbGw9IiMxMzE3MjIiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTcgMXYzaDJ2MTJIN3YzSDZ2LTNINFY0aDJWMXpNNSA1aDN2MTBINXptNyAyaDN2NmgtM3ptLTEgN1Y2aDJWMy4yNWgxVjZoMnY4aC0ydjIuNzVoLTFWMTR6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-horizontal-line,.ag-charts-icon-horizontal-line-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNLjUgOS41aDcuMzA2YTIuMjUgMi4yNSAwIDAgMSA0LjM4OCAwSDE5LjV2MWgtNy4zMDZhMi4yNSAyLjI1IDAgMCAxLTQuMzg4IDBILjV6bTkuNSAxLjc1YTEuMjUgMS4yNSAwIDEgMCAwLTIuNSAxLjI1IDEuMjUgMCAwIDAgMCAyLjUiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-line-color{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTQuMjQyIDIuNzIyYy0uNjEyIDAtMS4yLjI0My0xLjYzMi42NzVsLTEuMzQzIDEuMzQ0YS41LjUgMCAwIDAtLjExMi4xMTJMNC4wNSAxMS45NTljLS4yMDcuMjA3LS4zNi40Ni0uNDQ2Ljc0di4wMDFsLS42OSAyLjc2N3YuMDAyYS44Mi44MiAwIDAgMCAxLjAyMiAxLjAyMWguMDAybDIuNjM0LS44MjJjLjI4LS4wODUuNTM0LS4yMzcuNzQtLjQ0M2w3LjEwNy03LjEwOGEuNS41IDAgMCAwIC4xMTItLjExMmwxLjM0My0xLjM0M2EyLjMwOCAyLjMwOCAwIDAgMC0xLjYzMi0zLjk0TTE0LjEyMiA3bDEuMDQ0LTEuMDQ1YTEuMzA4IDEuMzA4IDAgMSAwLTEuODQ5LTEuODVMMTIuMjcxIDUuMTV6bS0yLjU1OC0xLjE0Mi02LjgwNyA2LjgwOWEuOC44IDAgMCAwLS4xOTYuMzI1bC0uNzUgMi40NjggMi40Ny0uNzQ5YS44LjggMCAwIDAgLjMyNS0uMTk0bDYuODA4LTYuODF6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-line-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJtMTcuMzYyIDQuODczLTQuNTk0IDYuNjU0LTQuODUtMy4zMTctNC4yNTEgNi45NzctLjg1NC0uNTJMNy42MTIgNi43OWw0Ljg5OSAzLjM1IDQuMDI4LTUuODM2eiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.ag-charts-icon-line-style-dashed{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMiA5aDR2MUgyem0xMiAwaDR2MWgtNHpNOCA5aDR2MUg4eiIvPjwvc3ZnPg==)}.ag-charts-icon-line-style-dotted{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSIyLjUiIGN5PSI5LjUiIHI9Ii41IiBmaWxsPSIjMDAwIi8+PGNpcmNsZSBjeD0iNC41IiBjeT0iOS41IiByPSIuNSIgZmlsbD0iIzAwMCIvPjxjaXJjbGUgY3g9IjYuNSIgY3k9IjkuNSIgcj0iLjUiIGZpbGw9IiMwMDAiLz48Y2lyY2xlIGN4PSI4LjUiIGN5PSI5LjUiIHI9Ii41IiBmaWxsPSIjMDAwIi8+PGNpcmNsZSBjeD0iMTAuNSIgY3k9IjkuNSIgcj0iLjUiIGZpbGw9IiMwMDAiLz48Y2lyY2xlIGN4PSIxMi41IiBjeT0iOS41IiByPSIuNSIgZmlsbD0iIzAwMCIvPjxjaXJjbGUgY3g9IjE0LjUiIGN5PSI5LjUiIHI9Ii41IiBmaWxsPSIjMDAwIi8+PGNpcmNsZSBjeD0iMTYuNSIgY3k9IjkuNSIgcj0iLjUiIGZpbGw9IiMwMDAiLz48L3N2Zz4=)}.ag-charts-icon-line-style-solid{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMiA5aDE2djFIMnoiLz48L3N2Zz4=)}.ag-charts-icon-line-with-markers-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJtMTguMTk4IDQuODg4LTMuNTU2IDQuOTE4YTIuMjUgMi4yNSAwIDEgMS0zLjg2Ni43NWwtMS40MzItLjlhMi4yNCAyLjI0IDAgMCAxLTIuMDA5LjQzNWwtMy44MjggNi40MjgtLjg2LS41MTJMNi40NSA5LjYyM2EyLjI1IDIuMjUgMCAxIDEgMy41MS0uNzYxbDEuMzI5LjgzNWEyLjI0IDIuMjQgMCAwIDEgMi41NTctLjQ5N2wzLjU0Mi00Ljg5OHptLTQuOTYgNS4xNTNhMS4yNSAxLjI1IDAgMSAwLS42NCAyLjQxOSAxLjI1IDEuMjUgMCAwIDAgLjY0LTIuNDE5TTkuMSA4LjMyMXEuMDY2LS4xOTIuMDY3LS40MDRhMS4yNSAxLjI1IDAgMSAwLS4wNjcuNDA0IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-lock,.ag-charts-icon-locked{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTAuMjA3IDMuNzY0YTIuODk0IDIuODk0IDAgMCAwLTIuODk1IDIuODk0VjloNS43ODlWNi42NThhMi44OTQgMi44OTQgMCAwIDAtMi44OTUtMi44OTRNMTQuMSA5VjYuNjU4YTMuODk0IDMuODk0IDAgMSAwLTcuNzg5IDB2Mi4zNDlBMi41IDIuNSAwIDAgMCA0IDExLjV2M0EyLjUgMi41IDAgMCAwIDYuNSAxN2g4YTIuNSAyLjUgMCAwIDAgMi41LTIuNXYtM0EyLjUgMi41IDAgMCAwIDE0LjUgOXpNNi41IDEwQTEuNSAxLjUgMCAwIDAgNSAxMS41djNBMS41IDEuNSAwIDAgMCA2LjUgMTZoOGExLjUgMS41IDAgMCAwIDEuNS0xLjV2LTNhMS41IDEuNSAwIDAgMC0xLjUtMS41eiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.ag-charts-icon-measurer-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0ibTQuNDYxIDEyLjcxIDEuNTMyLTEuNTMxIDEuNDE0IDEuNDE0LjcwNy0uNzA3TDYuNyAxMC40NzJsMS41MzItMS41MzMgMiAyIC43MDctLjcwNy0yLTIgNi4wMS02LjAxIDIuODMgMi44MjhMNS4wNSAxNy43NzggMi4yMjIgMTQuOTVsMS41MzItMS41MzIgMS40MTQgMS40MTQuNzA3LS43MDd6TS44MDggMTQuOTVsLjcwNy0uNzA3TDE0LjI0MyAxLjUxNWwuNzA3LS43MDcuNzA3LjcwNyAyLjgyOCAyLjgyOC43MDcuNzA3LS43MDcuNzA3TDUuNzU3IDE4LjQ4NWwtLjcwNy43MDctLjcwNy0uNzA3LTIuODI4LTIuODI4em0xMS4wNzgtNi44MzVMMTAuNDcgNi43bC43MDctLjcwNyAxLjQxNSAxLjQxNHptLjgyNC0zLjY1NCAxIDEgLjcwOC0uNzA3LTEtMXoiIGZpbGw9IiMxODFEMUYiLz48L3N2Zz4=)}.ag-charts-icon-note-annotation{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMyA0LjVBMS41IDEuNSAwIDAgMSA0LjUgM2gxMUExLjUgMS41IDAgMCAxIDE3IDQuNXY4YTEuNSAxLjUgMCAwIDEtMS41IDEuNWgtMy4yMWwtMS40NjkgMi41N2ExIDEgMCAwIDEtMS42ODIuMDg1TDcuMjQzIDE0SDQuNUExLjUgMS41IDAgMCAxIDMgMTIuNXpNNC41IDRhLjUuNSAwIDAgMC0uNS41djhhLjUuNSAwIDAgMCAuNS41aDMuMjU3bDIuMTk2IDMuMDc0TDExLjcxIDEzaDMuNzlhLjUuNSAwIDAgMCAuNS0uNXYtOGEuNS41IDAgMCAwLS41LS41eiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNi41IDYuNUEuNS41IDAgMCAxIDcgNmg2YS41LjUgMCAwIDEgMCAxSDdhLjUuNSAwIDAgMS0uNS0uNU02LjUgOS41QS41LjUgMCAwIDEgNyA5aDZhLjUuNSAwIDAgMSAwIDFIN2EuNS41IDAgMCAxLS41LS41IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-ohlc-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZD0iTTEzIDExaC0zdi0xaDNWM2gxdjJoNHYxaC00djExaC0xek02IDE3di0yaDN2LTFINlY0SDV2MUgydjFoM3YxMXoiLz48L3N2Zz4=)}.ag-charts-icon-pan-end{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZD0ibTYuNjQ2IDEzLjgxMy0uMzUzLjM1NC43MDcuNzA3LjM1NC0uMzU0ek0xMS4xNjYgMTBsLjM1NC4zNTQuMzU0LS4zNTQtLjM1NC0uMzU0ek03LjM1NSA1LjQ4IDcgNS4xMjZsLS43MDcuNzA3LjM1My4zNTR6bTAgOS4wNCA0LjE2Ni00LjE2Ni0uNzA3LS43MDgtNC4xNjcgNC4xNjd6bTQuMTY2LTQuODc0TDcuMzU0IDUuNDhsLS43MDguNzA3IDQuMTY3IDQuMTY3ek0xMy4wODMgNXYxMGgxVjV6Ii8+PC9zdmc+)}.ag-charts-icon-pan-left{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTIuNzkgNS44MzMgOC42MjUgMTBsNC4xNjYgNC4xNjctLjcwNy43MDdMNy4yMSAxMGw0Ljg3My00Ljg3NHoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-pan-right{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNy4yMSAxNC4xNjcgMTEuMzc2IDEwIDcuMjEgNS44MzNsLjcwNy0uNzA3TDEyLjc5IDEwbC00Ljg3MyA0Ljg3NHoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-pan-start{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZD0iTTYgNXYxMGgxVjV6TTkuNjI0IDEwbDQuMTY2LTQuMTY3LS43MDctLjcwN0w4LjIxIDEwbDQuODc0IDQuODc0LjcwNy0uNzA3eiIvPjwvc3ZnPg==)}.ag-charts-icon-parallel-channel,.ag-charts-icon-parallel-channel-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTcuNzIgNS4zMzFBMi4yNSAyLjI1IDAgMSAwIDE0LjcwNSAzLjZsLTkuNDkgNC41NjJhMi4yNSAyLjI1IDAgMSAwIC4yMDkgMS4wMWw5LjY2Mi00LjY0NmEyLjI1IDIuMjUgMCAwIDAgMi42MzQuODA1bS4zNzMtMi41NDdhMS4yNSAxLjI1IDAgMSAxLTIuMzM4Ljg4NSAxLjI1IDEuMjUgMCAwIDEgMi4zMzgtLjg4NU00LjM0MyA4LjY3YTEuMjUgMS4yNSAwIDEgMS0yLjMzOC44ODUgMS4yNSAxLjI1IDAgMCAxIDIuMzM4LS44ODVNNS4zMDcgMTYuNzI4YTIuMjUgMi4yNSAwIDEgMS0uNTI1LS44NThsOS45MjMtNC43N2EyLjI1IDIuMjUgMCAxIDEgLjM4MS45MjZ6bS0uOTY0LjI3NGExLjI1IDEuMjUgMCAxIDEtMi4zMzguODg1IDEuMjUgMS4yNSAwIDAgMSAyLjMzOC0uODg1bTEzLjAyMy01LjEwNmExLjI1IDEuMjUgMCAxIDAtLjg4NS0yLjMzOSAxLjI1IDEuMjUgMCAwIDAgLjg4NSAyLjMzOSIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.ag-charts-icon-position-bottom{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii4yNSIgZD0iTTMgMTBoMTR2MUgzem0zLTNoOHYxSDZ6Ii8+PHBhdGggZmlsbD0iIzAwMCIgZD0iTTYgMTNoOHYxSDZ6Ii8+PC9zdmc+)}.ag-charts-icon-position-center{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMyAxMGgxNHYxSDN6Ii8+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuMjUiIGQ9Ik02IDdoOHYxSDZ6bTAgNmg4djFINnoiLz48L3N2Zz4=)}.ag-charts-icon-position-top{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9Ii4yNSIgZD0iTTMgMTBoMTR2MUgzeiIvPjxwYXRoIGZpbGw9IiMwMDAiIGQ9Ik02IDdoOHYxSDZ6Ii8+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIuMjUiIGQ9Ik02IDEzaDh2MUg2eiIvPjwvc3ZnPg==)}.ag-charts-icon-price-label-annotation{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNC41IDNBMS41IDEuNSAwIDAgMCAzIDQuNVYxM2ExLjUgMS41IDAgMCAwIDEuNSAxLjVoLjgzM3YuMDU3Yy4yNDItLjI5OS41OTctLjUwMyAxLS41NDhWMTMuNUg0LjVBLjUuNSAwIDAgMSA0IDEzVjQuNWEuNS41IDAgMCAxIC41LS41aDExYS41LjUgMCAwIDEgLjUuNXY4YS41LjUgMCAwIDEtLjUuNWgtNC44MThsLS4xMjYuMDg0YTI2IDI2IDAgMCAwLTIuMjI1IDEuNjg1bC0uMzIuMjY1LS4wNjguMDU2YTEuNSAxLjUgMCAwIDEtMi42MDkgMS4zNTRjLjAzMy43NjMuOTA1IDEuMjM4IDEuNTYuNzU2LjY0Ni0uNDc0IDEuMjEtLjk0MyAxLjc2MS0xLjRsLjMxMy0uMjZBMjYgMjYgMCAwIDEgMTAuOTg2IDE0SDE1LjVhMS41IDEuNSAwIDAgMCAxLjUtMS41di04QTEuNSAxLjUgMCAwIDAgMTUuNSAzeiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOC43MTYgMTQuODE1YTIuMjUgMi4yNSAwIDEgMS00LjIxIDEuNTkzIDIuMjUgMi4yNSAwIDAgMSA0LjIxLTEuNTkzbS0xLjY2MiAxLjk2NmExLjI1IDEuMjUgMCAxIDAtLjg4NS0yLjMzOSAxLjI1IDEuMjUgMCAwIDAgLjg4NSAyLjMzOSIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.ag-charts-icon-price-range-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNOS4wNDYgMTVWNS44NzdoLjk0MlYxNXoiIGZpbGw9IiMxODFEMUYiLz48cGF0aCBkPSJNOS4wNDYgMTVWNS44NzdoLjk0MlYxNXoiIGZpbGw9IiMxODFEMUYiLz48cGF0aCBkPSJNOS41IDYuMjI4IDcuMTY3IDguMzc2IDYuNSA3Ljc2MiA5LjUgNWwzIDIuNzYyLS42NjcuNjE0eiIgZmlsbD0iIzAwMCIvPjxwYXRoIGQ9Ik0yIDE4di0xaDE2djF6TTIgM1YyaDE2djF6IiBmaWxsPSIjMTgxRDFGIi8+PC9zdmc+)}.ag-charts-icon-reset{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTIuMDQgNC40NDVhNS44MSA1LjgxIDAgMCAwLTcuMjU3IDIuNDUzLjUuNSAwIDAgMS0uODY1LS41MDJBNi44MSA2LjgxIDAgMSAxIDMgOS44MTNhLjUuNSAwIDAgMSAxIDAgNS44MSA1LjgxIDAgMSAwIDguMDQtNS4zNjgiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjxwYXRoIGZpbGw9IiMwMDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTQuMjg5IDMuMDAyYS41LjUgMCAwIDEgLjUuNXYyLjY1NWgyLjY1NWEuNS41IDAgMCAxIDAgMUg0LjI5YS41LjUgMCAwIDEtLjUtLjVWMy41MDJhLjUuNSAwIDAgMSAuNS0uNSIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.ag-charts-icon-settings{--icon: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgc3R5bGU9ImZpbGwtcnVsZTpldmVub2RkIj48cGF0aCBkPSJNMTAgMTNhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2bTAtMWEyIDIgMCAxIDEtLjAwMS0zLjk5OUEyIDIgMCAwIDEgMTAgMTIiLz48cGF0aCBkPSJNMi4zMSAxNC4zNDVjLS44MTctMS40OTEuMDI3LTIuNDk5LjQ3NC0yLjg2NS41MzEtLjQzNC45NjktLjM2NS45NzItMS40OC0uMDAzLTEuMTE1LS40NDEtMS4wNDYtLjk3Mi0xLjQ4MS0uNDU0LS4zNzEtMS4zMTctMS40MDUtLjQzNC0yLjkzNmwuMDA1LS4wMDljLjg4NC0xLjUyIDIuMjA3LTEuMjkgMi43NTUtMS4wODMuNjQxLjI0My44MDEuNjU2IDEuNzY4LjEwMS45NjQtLjU2LjY4Ni0uOTA0Ljc5Ni0xLjU4Mi4wOTQtLjU3OC41NTktMS44NDMgMi4zMjYtMS44NDNoLjAxYzEuNzU5LjAwNSAyLjIyMiAxLjI2NiAyLjMxNiAxLjg0My4xMS42NzgtLjE2OCAxLjAyMi43OTYgMS41ODIuOTY3LjU1NSAxLjEyNy4xNDIgMS43NjgtLjEwMS41NDktLjIwOCAxLjg3Ni0uNDM4IDIuNzYgMS4wOTJzLjAyIDIuNTY1LS40MzQgMi45MzZjLS41MzEuNDM1LS45NjkuMzY2LS45NzIgMS40ODEuMDAzIDEuMTE1LjQ0MSAxLjA0Ni45NzIgMS40OC40NTQuMzcyIDEuMzE3IDEuNDA2LjQzNCAyLjkzN2wtLjAwNS4wMDljLS44ODQgMS41Mi0yLjIwNyAxLjI5LTIuNzU1IDEuMDgzLS42NDEtLjI0My0uODAxLS42NTYtMS43NjgtLjEwMS0uOTY0LjU2LS42ODYuOTA0LS43OTYgMS41ODEtLjA5NC41NzktLjU1OSAxLjg0NC0yLjMyNiAxLjg0NGgtLjAxYy0xLjc1OS0uMDA1LTIuMjIyLTEuMjY2LTIuMzE2LTEuODQ0LS4xMS0uNjc3LjE2OC0xLjAyMS0uNzk2LTEuNTgxLS45NjctLjU1NS0xLjEyNy0uMTQyLTEuNzY4LjEwMS0uNTQ5LjIwOC0xLjg3Ni40MzgtMi43Ni0xLjA5MmwtLjAyLS4wMzZ6TTkuOTg0IDIuMTYySDEwYzEuMzU1IDAgMS4zNDIgMS4wMzkgMS4zNTMgMS40MjUuMDA4LjMxMi4wNCAxLjE2IDEuMjU5IDEuODcybC4wMTUuMDA4YzEuMjI1LjcgMS45NzYuMzA0IDIuMjUxLjE1NS4zMzctLjE4MyAxLjIyNi0uNzExIDEuOTAyLjQ0NWwuMDA4LjAxNGMuNjc4IDEuMTczLS4yMjkgMS42ODItLjU1OCAxLjg4NC0uMjY2LjE2My0uOTg0LjYxNS0uOTkxIDIuMDI3di4wMTZjLjAwNyAxLjQxMi43MjUgMS44NjQuOTkxIDIuMDI3LjMyOC4yMDEgMS4yMjkuNzA3LjU2NiAxLjg3bC0uMDA4LjAxNGMtLjY3NyAxLjE3NC0xLjU3MS42NDMtMS45MS40NTktLjI3NS0uMTQ5LTEuMDI2LS41NDUtMi4yNTEuMTU0bC0uMDE1LjAwOWMtMS4yMTkuNzEyLTEuMjUxIDEuNTYtMS4yNTkgMS44NzItLjAxMS4zODYuMDAyIDEuNDI1LTEuMzUzIDEuNDI1cy0xLjM0Mi0xLjAzOS0xLjM1My0xLjQyNWMtLjAwOC0uMzEyLS4wNC0xLjE2LTEuMjU5LTEuODcybC0uMDE1LS4wMDljLTEuMjI1LS42OTktMS45NzYtLjMwMy0yLjI1MS0uMTU0LS4zMzYuMTgzLTEuMjE5LjcwNi0xLjg5NC0uNDMybC0uMDE2LS4wMjdjLS42NzgtMS4xNzQuMjI5LTEuNjgyLjU1OC0xLjg4NC4yNjYtLjE2My45ODQtLjYxNS45OTEtMi4wMjd2LS4wMTZjLS4wMDctMS40MTItLjcyNS0xLjg2NC0uOTkxLTIuMDI3LS4zMjgtLjIwMS0xLjIyOS0uNzA3LS41NjYtMS44N2wuMDA4LS4wMTRjLjY3Ny0xLjE3NCAxLjU3MS0uNjQzIDEuOTEtLjQ1OS4yNzUuMTQ5IDEuMDI2LjU0NSAyLjI1MS0uMTU1bC4wMTUtLjAwOGMxLjIxOS0uNzEyIDEuMjUxLTEuNTYgMS4yNTktMS44NzIuMDEtLjM4NC0uMDAyLTEuNDE3IDEuMzM3LTEuNDI1Ii8+PC9zdmc+)}.ag-charts-icon-step-line-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzE4MUQxRiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNiA0aDV2OGgzVjhoNXYxaC00djRoLTVWNUg3djEwSDJ2LTFoNHoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-text-annotation{--icon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDRIMTZWN0gxNVY1SDEwLjVWMTVIMTRWMTZINlYxNUg5LjVWNUg1VjdINFY0WiIgZmlsbD0iYmxhY2siLz4KPC9zdmc+Cg==)}.ag-charts-icon-trend-line,.ag-charts-icon-trend-line-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS4zMTQgMTAuOTM4YTIuMjUgMi4yNSAwIDEgMSAuMDEtMWg5LjM1MmEyLjI1IDIuMjUgMCAxIDEgLjAxIDF6bS0yLjE4OS43MjlhMS4yNSAxLjI1IDAgMSAwIDAtMi41IDEuMjUgMS4yNSAwIDAgMCAwIDIuNW0xMy43NSAwYTEuMjUgMS4yNSAwIDEgMCAwLTIuNSAxLjI1IDEuMjUgMCAwIDAgMCAyLjUiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-unlock,.ag-charts-icon-unlocked{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNjUxIDMuNWEyLjg5NCAyLjg5NCAwIDAgMC0yLjg5NCAyLjg5NFY5SDE0LjVhMi41IDIuNSAwIDAgMSAyLjUgMi41djNhMi41IDIuNSAwIDAgMS0yLjUgMi41aC04QTIuNSAyLjUgMCAwIDEgNCAxNC41di0zQTIuNSAyLjUgMCAwIDEgNi41IDloLjI1N1Y2LjM5NGEzLjg5NCAzLjg5NCAwIDEgMSA3Ljc4OSAwIC41LjUgMCAwIDEtMSAwQTIuODk0IDIuODk0IDAgMCAwIDEwLjY1IDMuNU02LjUgMTBBMS41IDEuNSAwIDAgMCA1IDExLjV2M0ExLjUgMS41IDAgMCAwIDYuNSAxNmg4YTEuNSAxLjUgMCAwIDAgMS41LTEuNXYtM2ExLjUgMS41IDAgMCAwLTEuNS0xLjV6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-vertical-line,.ag-charts-icon-vertical-line-drawing{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNSA3LjgwNmEyLjI1IDIuMjUgMCAwIDEgMCA0LjM4OFYxOS41aC0xdi03LjMwNmEyLjI1IDIuMjUgMCAwIDEgMC00LjM4OFYuNWgxem0tLjUuOTQ0YTEuMjUgMS4yNSAwIDEgMSAwIDIuNSAxLjI1IDEuMjUgMCAwIDEgMC0yLjUiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-zoom-in{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZD0iTTEwIDUuNWEuNS41IDAgMCAxIC41LjV2My41aDMuODc1YS41LjUgMCAwIDEgMCAxSDEwLjV2NC4yNWEuNS41IDAgMSAxLTEgMFYxMC41SDUuNjI1YS41LjUgMCAxIDEgMC0xSDkuNVY2YS41LjUgMCAwIDEgLjUtLjUiLz48L3N2Zz4=)}.ag-charts-icon-zoom-out{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS41IDEwYS41LjUgMCAwIDEgLjUtLjVoOGEuNS41IDAgMCAxIDAgMUg2YS41LjUgMCAwIDEtLjUtLjUiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-high-low-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNyA0aDJ2MTJINFY0aDNNNSA1aDN2MTBINXpNMTEgMTRWNmg1djhoLTVtMS03aDN2NmgtM3oiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.ag-charts-icon-hlc-series{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzEzMTcyMiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJtMTguMTYzIDEuODM3LTUuMzM0IDExLjYyMUw2Ljk1NyA4LjEybC00LjE5OSA5LjYyMi0uOTE2LS40IDQuNzU2LTEwLjlMMTIuNDkgMTEuOCAxNy4yNTQgMS40MnoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjxwYXRoIGZpbGw9IiMwMDAiIGZpbGwtb3BhY2l0eT0iLjQiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTUuODI1IDIuNzA0LjU1IDEzLjc4NWwuOTAyLjQzIDQuNzI0LTkuOTE5IDYuMDM0IDUuMDI5IDMuMjU1LTguMTQtLjkyOC0uMzctMi43NDUgNi44NnptNy44NTIgMTQuNjM2IDUuNzgtMTMuMTM5LS45MTUtLjQwMi01LjIxOSAxMS44Ni02LjAwNS01LjUwNC0zLjI3OCA3LjY0OC45Mi4zOTQgMi43MjItNi4zNTJ6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.ag-charts-icon-zoom-in-alt{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXpvb20taW4iPjxjaXJjbGUgY3g9IjExIiBjeT0iMTEiIHI9IjgiLz48bGluZSB4MT0iMjEiIHgyPSIxNi42NSIgeTE9IjIxIiB5Mj0iMTYuNjUiLz48bGluZSB4MT0iMTEiIHgyPSIxMSIgeTE9IjgiIHkyPSIxNCIvPjxsaW5lIHgxPSI4IiB4Mj0iMTQiIHkxPSIxMSIgeTI9IjExIi8+PC9zdmc+)}.ag-charts-icon-zoom-out-alt{--icon: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXpvb20tb3V0Ij48Y2lyY2xlIGN4PSIxMSIgY3k9IjExIiByPSI4Ii8+PGxpbmUgeDE9IjIxIiB4Mj0iMTYuNjUiIHkxPSIyMSIgeTI9IjE2LjY1Ii8+PGxpbmUgeDE9IjgiIHgyPSIxNCIgeTE9IjExIiB5Mj0iMTEiLz48L3N2Zz4=)}.ag-charts-input{--input-layer-active: 1;--input-layer-focus: 2;color:inherit;font-family:var(--ag-charts-input-font-family);font-size:var(--ag-charts-input-font-size);transition-duration:var(--ag-charts-input-transition-duration);transition-property:none;transition-timing-function:var(--ag-charts-input-transition-timing-function)}.ag-charts-input:focus-visible{outline:var(--ag-charts-input-focus-outline);box-shadow:var(--ag-charts-input-focus-box-shadow);z-index:var(--input-layer-focus)}.ag-charts-button{background:var(--ag-charts-input-background-color);border:1px solid var(--ag-charts-input-border-color);border-radius:var(--ag-charts-input-border-radius);cursor:pointer;padding:var(--ag-charts-input-padding);transition-property:background,border-color}.ag-charts-button:hover{background:var(--ag-charts-input-background-color--hover)}.ag-charts-button:has(.ag-charts-icon){padding:2px}.ag-charts-checkbox{appearance:none;background:var(--ag-charts-input-checkbox-background-color);border-radius:9px;cursor:pointer;height:18px;margin:0;transition-duration:var(--ag-charts-input-transition-duration--fast);transition-property:margin;width:29px}.ag-charts-checkbox:before{display:block;background:var(--ag-charts-input-background-color);border-radius:7px;content:" ";height:14px;margin:2px;transition-duration:var(--ag-charts-input-transition-duration--fast);transition-property:margin;transition-timing-function:var(--ag-charts-input-transition-easing);width:14px}.ag-charts-checkbox:checked{background:var(--ag-charts-input-checkbox-background-color--checked)}.ag-charts-checkbox:checked:before{margin-left:13px}.ag-charts-select{background:var(--ag-charts-input-background-color);border:1px solid var(--ag-charts-input-border-color);border-radius:var(--ag-charts-input-border-radius);padding:3px 2px 4px;font-size:inherit}.ag-charts-textarea{--line-height: 1.38;background:var(--ag-charts-input-background-color);border:1px solid var(--ag-charts-input-border-color);border-radius:var(--ag-charts-input-border-radius);line-height:var(--line-height);font-family:var(--ag-charts-input-font-family);font-size:var(--ag-charts-input-font-size);padding:var(--ag-charts-input-padding-large) var(--ag-charts-input-padding)}.ag-charts-textarea[placeholder]:empty:before{color:var(--ag-charts-input-placeholder);content:attr(placeholder)}.ag-charts-proxy-container{pointer-events:none;position:absolute}.ag-charts-proxy-elem{-webkit-appearance:none;appearance:none;background:none;border:none;color:#0000;overflow:hidden;pointer-events:auto;position:absolute}.ag-charts-proxy-elem::-moz-range-thumb,.ag-charts-proxy-elem::-moz-range-track{opacity:0}.ag-charts-proxy-elem::-webkit-slider-runnable-track,.ag-charts-proxy-elem::-webkit-slider-thumb{opacity:0}.ag-charts-proxy-elem:focus-visible{outline:var(--ag-charts-focus-border);box-shadow:var(--ag-charts-focus-border-shadow)}.ag-charts-focus-indicator{position:absolute;display:block;pointer-events:none;user-select:none;width:100%;height:100%}.ag-charts-focus-indicator>div{position:absolute;outline:var(--ag-charts-focus-border);outline-width:2px;box-shadow:var(--ag-charts-focus-border-shadow)}.ag-charts-focus-indicator>svg{width:100%;height:100%;fill:none;stroke:var(--ag-charts-focus-border-color);stroke-width:2px}.ag-charts-overlay{color:#181d1f;pointer-events:none}.ag-charts-overlay.ag-charts-dark-overlay{color:#fff}.ag-charts-overlay--loading{color:#8c8c8c}.ag-charts-overlay__loading-background{background:#fff;pointer-events:none}.ag-charts-overlay.ag-charts-dark-overlay .ag-charts-overlay__loading-background{background:#192232}.ag-charts-tooltip{position:fixed;inset:unset;margin:0;padding:0;overflow:visible;width:max-content;max-width:100%;font:12px Verdana,sans-serif;color:var(--ag-charts-tooltip-text-color);background:var(--ag-charts-tooltip-background-color);border:var(--ag-charts-tooltip-border);border-radius:var(--ag-charts-tooltip-border-radius);box-shadow:0 4px 8px #00000014}.ag-charts-tooltip--compact{--ag-charts-content-padding: var(--ag-charts-content-compact-padding)}.ag-charts-tooltip--arrow:before{--tooltip-arrow-size: 8px;content:"";position:absolute;top:100%;left:50%;margin:0 auto;transform:translate(-50%) translateY(calc(var(--tooltip-arrow-size) * -.5)) rotate(45deg);display:block;width:var(--tooltip-arrow-size);height:var(--tooltip-arrow-size);border:inherit;background:inherit;border-top:none;border-left:none;clip-path:polygon(0 100%,100% 0,100% 100%)}.ag-charts-tooltip--no-interaction{pointer-events:none;user-select:none}.ag-charts-tooltip--wrap-always{overflow-wrap:break-word;word-break:break-word;hyphens:none}.ag-charts-tooltip--wrap-hyphenate{overflow-wrap:break-word;word-break:break-word;hyphens:auto}.ag-charts-tooltip--wrap-on-space{overflow-wrap:normal;word-break:normal}.ag-charts-tooltip--wrap-never{white-space:nowrap}.ag-charts-tooltip-heading,.ag-charts-tooltip-title,.ag-charts-tooltip-label,.ag-charts-tooltip-value{overflow:hidden;text-overflow:ellipsis}.ag-charts-tooltip-content{display:grid;grid:auto-flow minmax(1em,auto) / 1fr;padding:var(--ag-charts-content-padding);gap:var(--ag-charts-content-gap)}.ag-charts-tooltip-content:has(.ag-charts-tooltip-symbol){grid:auto-flow minmax(1em,auto) / auto 1fr}.ag-charts-tooltip-heading{grid-column:1 / -1}.ag-charts-tooltip-symbol{grid-column:1 / 2;align-self:center}.ag-charts-tooltip-symbol svg{display:block}.ag-charts-tooltip-title{grid-column:-2 / -1}.ag-charts-tooltip-row{grid-column:1 / -1;display:flex;gap:16px;align-items:baseline;justify-content:space-between;overflow:hidden}.ag-charts-tooltip-row--inline{grid-column:-2 / -1}.ag-charts-tooltip-label{flex:1;min-width:0}.ag-charts-tooltip-value{min-width:0}.ag-charts-popover{position:absolute;border:var(--ag-charts-popover-border);border-radius:var(--ag-charts-popover-border-radius);background:var(--ag-charts-popover-background-color);color:var(--ag-charts-popover-foreground-color);font-family:var(--ag-charts-font-family);font-size:var(--ag-charts-popover-font-size);box-shadow:var(--ag-charts-popover-shadow);z-index:var(--ag-charts-layer-ui-overlay)}.ag-charts-menu{--item-padding: 6px 12px;--icon-color: var(--ag-charts-popover-foreground-color);display:grid;grid:auto-flow auto / 1fr;column-gap:12px;font-size:var(--ag-charts-popover-font-size-small)}.ag-charts-menu:has(.ag-charts-menu__icon,.ag-charts-menu__row--stroke-width-visible){grid:auto-flow auto / auto 1fr}.ag-charts-menu__row--stroke-width-visible:before{content:"";height:var(--strokeWidth);width:12px;background:var(--icon-color)}.ag-charts-menu__row--stroke-width-visible[aria-disabled=true]:before{filter:grayscale(1);opacity:.5}.ag-charts-menu__row{display:grid;grid-column:1 / -1;grid-template-columns:subgrid;align-items:center;padding:var(--item-padding)}.ag-charts-menu__row:not(.ag-charts-menu__row--active){cursor:pointer}.ag-charts-menu__row:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.ag-charts-menu__row:last-child{border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.ag-charts-menu__row:focus{background:var(--ag-charts-popover-hover-color)}.ag-charts-menu__row:focus-visible{outline:var(--ag-charts-focus-border);box-shadow:var(--ag-charts-focus-border-shadow);z-index:calc(var(--ag-charts-layer-ui-overlay) + 1)}.ag-charts-menu__row--active{--icon-color: var(--ag-charts-popover-active-color);background:var(--ag-charts-popover-active-background-color);color:var(--ag-charts-popover-active-color)}.ag-charts-menu__label{grid-column:-1 / span 1}.ag-charts-toolbar{align-items:center;display:flex;flex-wrap:nowrap;position:absolute}.ag-charts-toolbar__button{align-items:center;background:var(--ag-charts-toolbar-background-color);border:var(--ag-charts-toolbar-border);color:var(--ag-charts-toolbar-foreground-color);cursor:pointer;display:flex;font:var(--ag-charts-toolbar-font-size) var(--ag-charts-font-family);justify-content:center;min-height:var(--ag-charts-toolbar-size);min-width:var(--ag-charts-toolbar-size);padding:var(--ag-charts-toolbar-button-padding);position:relative;transition:background-color .25s ease-in-out,border-color .25s ease-in-out,color .25s ease-in-out;white-space:nowrap}.ag-charts-toolbar__button:hover{background:var(--ag-charts-toolbar-hover-color);z-index:1}.ag-charts-toolbar__button:focus-visible{outline:var(--ag-charts-focus-border);box-shadow:var(--ag-charts-focus-border-shadow);z-index:calc(var(--ag-charts-layer-ui-overlay) + 1)}.ag-charts-toolbar__button--active{background:var(--ag-charts-toolbar-active-background-color);border-color:var(--ag-charts-toolbar-active-color);color:var(--ag-charts-toolbar-active-color);z-index:2}.ag-charts-toolbar__button[aria-disabled=true]{background:var(--ag-charts-toolbar-disabled-background-color);color:var(--ag-charts-toolbar-disabled-foreground-color);cursor:default}.ag-charts-toolbar--horizontal{flex-direction:row;.ag-charts-toolbar__button{margin:0 0 0 -1px}.ag-charts-toolbar__button--first{border-bottom-left-radius:var(--ag-charts-button-radius);border-top-left-radius:var(--ag-charts-button-radius);margin:0}.ag-charts-toolbar__button--last{border-bottom-right-radius:var(--ag-charts-button-radius);border-top-right-radius:var(--ag-charts-button-radius)}}.ag-charts-toolbar--vertical{flex-direction:column;.ag-charts-toolbar__button{margin:-1px 0 0;max-width:100%}.ag-charts-toolbar__button--first{border-top-left-radius:var(--ag-charts-button-radius);border-top-right-radius:var(--ag-charts-button-radius);margin:0}.ag-charts-toolbar__button--last{border-bottom-left-radius:var(--ag-charts-button-radius);border-bottom-right-radius:var(--ag-charts-button-radius)}}.ag-charts-toolbar__icon+.ag-charts-toolbar__label{margin-left:var(--ag-charts-toolbar-gap)}.ag-charts-toolbar__icon,.ag-charts-toolbar__label{pointer-events:none}.ag-charts-floating-toolbar{border:none;display:flex;.ag-charts-toolbar{align-items:unset;position:unset}}.ag-charts-floating-toolbar__drag-handle{align-items:center;background:var(--ag-charts-toolbar-background-color);border:var(--ag-charts-toolbar-border);border-bottom-left-radius:var(--ag-charts-button-radius);border-top-left-radius:var(--ag-charts-button-radius);cursor:grab;display:flex;justify-content:center;min-width:24px;padding-left:0;padding-right:0}.ag-charts-floating-toolbar__drag-handle--dragging{cursor:grabbing}\n';
function booleanParser(value) {
  return value === "true";
}
function numberParser(value) {
  return Number(value);
}
function stringParser(value) {
  return value;
}
var AttributeTypeParsers = {
  role: stringParser,
  "aria-checked": booleanParser,
  "aria-controls": stringParser,
  "aria-describedby": stringParser,
  "aria-disabled": booleanParser,
  "aria-expanded": booleanParser,
  "aria-haspopup": booleanParser,
  "aria-hidden": booleanParser,
  "aria-label": stringParser,
  "aria-labelledby": stringParser,
  "aria-live": stringParser,
  "aria-orientation": stringParser,
  "aria-selected": booleanParser,
  "data-preventdefault": booleanParser,
  class: stringParser,
  id: stringParser,
  tabindex: numberParser,
  title: stringParser,
  placeholder: stringParser
};
function setAttribute(e, qualifiedName, value) {
  if (value == null || value === "" || value === "") {
    e?.removeAttribute(qualifiedName);
  } else {
    e?.setAttribute(qualifiedName, value.toString());
  }
}
function setAttributes(e, attrs) {
  if (attrs == null)
    return;
  for (const [key, value] of Object.entries(attrs)) {
    if (key === "class")
      continue;
    setAttribute(e, key, value);
  }
}
function getAttribute(e, qualifiedName, defaultValue) {
  if (!(e instanceof HTMLElement))
    return void 0;
  const value = e.getAttribute(qualifiedName);
  if (value === null)
    return defaultValue;
  return AttributeTypeParsers[qualifiedName]?.(value) ?? void 0;
}
function setElementStyle(e, property, value) {
  if (e == null)
    return;
  if (value == null) {
    e.style.removeProperty(property);
  } else {
    e.style.setProperty(property, value.toString());
  }
}
function setElementStyles(e, styles) {
  for (const [key, value] of Object.entries(styles)) {
    setElementStyle(e, key, value);
  }
}
var GuardedElement = class _GuardedElement {
  constructor(element2, topTabGuard, bottomTabGuard) {
    this.element = element2;
    this.topTabGuard = topTabGuard;
    this.bottomTabGuard = bottomTabGuard;
    this.destroyFns = [];
    this.guardTabIndex = 0;
    this.hasFocus = false;
    this.initTabGuard(this.topTabGuard, (el) => this.onTab(el, false));
    this.initTabGuard(this.bottomTabGuard, (el) => this.onTab(el, true));
    this.element.addEventListener("focus", () => this.onFocus(), { capture: true });
    this.element.addEventListener("blur", (ev) => this.onBlur(ev), { capture: true });
  }
  set tabIndex(index) {
    this.guardTabIndex = index;
    if (this.guardTabIndex === 0) {
      this.setGuardIndices(void 0);
    } else if (!this.hasFocus) {
      this.setGuardIndices(this.guardTabIndex);
    }
  }
  destroy() {
    for (const fn of this.destroyFns)
      fn();
    this.destroyFns.length = 0;
  }
  initTabGuard(guard, handler) {
    const handlerBinding = () => handler(guard);
    guard.addEventListener("focus", handlerBinding);
    this.destroyFns.push(() => guard.removeEventListener("focus", handlerBinding));
  }
  setGuardIndices(index) {
    const tabindex = index;
    setAttribute(this.topTabGuard, "tabindex", tabindex);
    setAttribute(this.bottomTabGuard, "tabindex", tabindex);
  }
  onFocus() {
    this.hasFocus = true;
    if (this.guardTabIndex !== 0) {
      this.setGuardIndices(0);
    }
  }
  onBlur({ relatedTarget }) {
    const { topTabGuard: top, bottomTabGuard: bot } = this;
    this.hasFocus = false;
    if (this.guardTabIndex !== 0 && relatedTarget !== top && relatedTarget !== bot) {
      this.setGuardIndices(this.guardTabIndex);
    }
  }
  onTab(guard, reverse) {
    if (this.guardTabIndex !== 0) {
      let focusTarget;
      if (guard.tabIndex === 0) {
        focusTarget = this.findExitTarget(!reverse);
        this.setGuardIndices(this.guardTabIndex);
      } else {
        focusTarget = this.findEnterTarget(reverse);
      }
      focusTarget?.focus();
    }
  }
  static queryFocusable(element2, selectors) {
    const myWindow = getWindow();
    return Array.from(element2.querySelectorAll(selectors)).filter((e) => {
      if (e instanceof HTMLElement) {
        const style = myWindow.getComputedStyle(e);
        return style.display !== "none" && style.visibility !== "none";
      }
      return false;
    });
  }
  findEnterTarget(reverse) {
    const focusables = _GuardedElement.queryFocusable(this.element, '[tabindex="0"]');
    const index = reverse ? focusables.length - 1 : 0;
    return focusables[index];
  }
  findExitTarget(reverse) {
    const focusables = _GuardedElement.queryFocusable(getDocument(), "[tabindex]").filter((e) => e.tabIndex > 0).sort((a, b) => a.tabIndex - b.tabIndex);
    const { before, after } = _GuardedElement.findBeforeAndAfter(focusables, this.guardTabIndex);
    return reverse ? before : after;
  }
  static findBeforeAndAfter(elements, targetTabIndex) {
    let left = 0;
    let right = elements.length - 1;
    let before = void 0;
    let after = void 0;
    while (left <= right) {
      const mid = Math.floor((left + right) / 2);
      const currentTabIndex = elements[mid].tabIndex;
      if (currentTabIndex === targetTabIndex) {
        before = elements[mid - 1] || void 0;
        after = elements[mid + 1] || void 0;
        break;
      } else if (currentTabIndex < targetTabIndex) {
        before = elements[mid];
        left = mid + 1;
      } else {
        after = elements[mid];
        right = mid - 1;
      }
    }
    return { before, after };
  }
};
function addRemovableEventListener(destroyFns, elem, type, listener) {
  elem.addEventListener(type, listener);
  const remover = () => elem.removeEventListener(type, listener);
  destroyFns.push(remover);
  return remover;
}
function addEscapeEventListener(destroyFns, elem, onEscape) {
  addRemovableEventListener(destroyFns, elem, "keydown", (event) => {
    if (event.key === "Escape") {
      onEscape(event);
    }
  });
}
function addMouseCloseListener(destroyFns, menu, hideCallback) {
  const self = addRemovableEventListener(destroyFns, window, "mousedown", (event) => {
    if ([0, 2].includes(event.button) && !containsPoint2(menu, event)) {
      hideCallback();
      self();
    }
  });
  return self;
}
function containsPoint2(container, event) {
  if (event.target instanceof Element) {
    const { x, y, width: width2, height: height2 } = container.getBoundingClientRect();
    const { clientX: ex, clientY: ey } = event;
    return ex >= x && ey >= y && ex <= x + width2 && ey <= y + height2;
  }
  return false;
}
function hasNoModifiers(event) {
  return !(event.shiftKey || event.altKey || event.ctrlKey || event.metaKey);
}
function matchesKey(event, key, ...morekeys) {
  return hasNoModifiers(event) && (event.key === key || morekeys.some((altkey) => event.key === altkey));
}
function linkTwoButtons(destroyFns, src, dst, key) {
  if (!dst)
    return;
  addRemovableEventListener(destroyFns, src, "keydown", (event) => {
    if (matchesKey(event, key)) {
      dst.focus();
    }
  });
}
function linkThreeButtons(destroyFns, curr, next, nextKey, prev, prevKey) {
  linkTwoButtons(destroyFns, curr, prev, prevKey);
  linkTwoButtons(destroyFns, curr, next, nextKey);
  addRemovableEventListener(destroyFns, curr, "keydown", (event) => {
    if (matchesKey(event, nextKey, prevKey)) {
      event.preventDefault();
    }
  });
}
var PREV_NEXT_KEYS = {
  horizontal: { nextKey: "ArrowRight", prevKey: "ArrowLeft" },
  vertical: { nextKey: "ArrowDown", prevKey: "ArrowUp" }
};
function initToolbarKeyNav(opts) {
  opts.toolbar.role = "toolbar";
  opts.toolbar.ariaOrientation = opts.orientation;
  opts.toolbar.ariaHidden = (opts.buttons.length === 0).toString();
  return initRovingTabIndex(opts);
}
function initRovingTabIndex(opts) {
  const { orientation, buttons, wrapAround = false, onEscape, onFocus, onBlur } = opts;
  const { nextKey, prevKey } = PREV_NEXT_KEYS[orientation];
  const setTabIndices = (event) => {
    if (event.target && "tabIndex" in event.target) {
      buttons.forEach((b) => b.tabIndex = -1);
      event.target.tabIndex = 0;
    }
  };
  const [c, m] = wrapAround ? [buttons.length, buttons.length] : [0, Infinity];
  const destroyFns = [];
  for (let i = 0; i < buttons.length; i++) {
    const prev = buttons[(c + i - 1) % m];
    const curr = buttons[i];
    const next = buttons[(c + i + 1) % m];
    addRemovableEventListener(destroyFns, curr, "focus", setTabIndices);
    if (onFocus)
      addRemovableEventListener(destroyFns, curr, "focus", onFocus);
    if (onBlur)
      addRemovableEventListener(destroyFns, curr, "blur", onBlur);
    if (onEscape)
      addEscapeEventListener(destroyFns, curr, onEscape);
    linkThreeButtons(destroyFns, curr, next, nextKey, prev, prevKey);
    curr.tabIndex = i === 0 ? 0 : -1;
  }
  return destroyFns;
}
var MenuCloserImp = class {
  constructor(menu, lastFocus, closeCallback) {
    this.lastFocus = lastFocus;
    this.closeCallback = closeCallback;
    this.destroyFns = [];
    this.destroyFns.push(addMouseCloseListener(this.destroyFns, menu, () => this.close(true)));
  }
  close(mousedown) {
    this.destroyFns.forEach((d) => d());
    this.destroyFns.length = 0;
    this.closeCallback();
    this.finishClosing(mousedown);
  }
  finishClosing(mousedown) {
    this.destroyFns.forEach((d) => d());
    this.destroyFns.length = 0;
    setAttribute(this.lastFocus, "aria-expanded", false);
    if (!mousedown) {
      this.lastFocus?.focus({ preventScroll: true });
    }
    this.lastFocus = void 0;
  }
};
function initMenuKeyNav(opts) {
  const { sourceEvent, orientation, menu, buttons, closeCallback, autoCloseOnBlur = false } = opts;
  const { nextKey, prevKey } = PREV_NEXT_KEYS[orientation];
  const lastFocus = getLastFocus(sourceEvent);
  setAttribute(lastFocus, "aria-expanded", true);
  const menuCloser = new MenuCloserImp(menu, lastFocus, closeCallback);
  const onEscape = () => menuCloser.close();
  const { destroyFns } = menuCloser;
  menu.role = "menu";
  menu.ariaOrientation = orientation;
  destroyFns.push(...initRovingTabIndex({ orientation, buttons, onEscape, wrapAround: true }));
  menu.tabIndex = -1;
  addEscapeEventListener(destroyFns, menu, onEscape);
  addRemovableEventListener(destroyFns, menu, "keydown", (ev) => {
    if (ev.target === menu && (ev.key === nextKey || ev.key === prevKey)) {
      ev.preventDefault();
      buttons[0]?.focus();
    }
  });
  if (autoCloseOnBlur) {
    const handler = (ev) => {
      const buttonArray = buttons;
      const isLeavingMenu = !buttonArray.includes(ev.relatedTarget);
      if (isLeavingMenu) {
        onEscape();
      }
    };
    for (const button of buttons) {
      addRemovableEventListener(destroyFns, button, "blur", handler);
    }
  }
  buttons[0]?.focus({ preventScroll: true });
  return menuCloser;
}
function makeAccessibleClickListener(element2, onclick) {
  return (event) => {
    if (element2.ariaDisabled === "true") {
      return event.preventDefault();
    }
    onclick(event);
  };
}
function isButtonClickEvent(event) {
  if ("button" in event) {
    return event.button === 0;
  }
  return hasNoModifiers(event) && (event.code === "Space" || event.key === "Enter");
}
function getLastFocus(sourceEvent) {
  if (sourceEvent?.target instanceof HTMLElement && "tabindex" in sourceEvent.target.attributes) {
    return sourceEvent.target;
  }
  return void 0;
}
function stopPageScrolling(element2) {
  const handler = (event) => {
    if (event.defaultPrevented)
      return;
    const shouldPrevent = getAttribute(event.target, "data-preventdefault", true);
    if (shouldPrevent && matchesKey(event, "ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp")) {
      event.preventDefault();
    }
  };
  element2.addEventListener("keydown", handler);
  return () => element2.removeEventListener("keydown", handler);
}
var SizeMonitor = class {
  constructor() {
    this.elements = /* @__PURE__ */ new Map();
    this.documentReady = false;
    this.queuedObserveRequests = [];
    this.onLoad = () => {
      this.documentReady = true;
      this.queuedObserveRequests.forEach(([el, cb]) => this.observe(el, cb));
      this.queuedObserveRequests = [];
    };
    if (typeof ResizeObserver === "undefined")
      return;
    this.resizeObserver = new ResizeObserver((entries) => {
      for (const {
        target,
        contentRect: { width: width2, height: height2 }
      } of entries) {
        const entry = this.elements.get(target);
        this.checkSize(entry, target, width2, height2);
      }
    });
    this.documentReady = getDocument("readyState") === "complete";
    if (!this.documentReady) {
      getWindow()?.addEventListener("load", this.onLoad);
    }
  }
  destroy() {
    getWindow()?.removeEventListener("load", this.onLoad);
    this.resizeObserver?.disconnect();
    this.resizeObserver = null;
  }
  checkSize(entry, element2, width2, height2) {
    if (!entry)
      return;
    if (width2 !== entry.size?.width || height2 !== entry.size?.height) {
      entry.size = { width: width2, height: height2 };
      entry.cb(entry.size, element2);
    }
  }
  // Only a single callback is supported.
  observe(element2, cb) {
    if (!this.documentReady) {
      this.queuedObserveRequests.push([element2, cb]);
      return;
    }
    if (this.elements.has(element2)) {
      this.removeFromQueue(element2);
    } else {
      this.resizeObserver?.observe(element2);
    }
    const entry = { cb };
    this.elements.set(element2, entry);
  }
  unobserve(element2) {
    this.resizeObserver?.unobserve(element2);
    this.elements.delete(element2);
    this.removeFromQueue(element2);
    if (!this.elements.size) {
      this.destroy();
    }
  }
  removeFromQueue(element2) {
    this.queuedObserveRequests = this.queuedObserveRequests.filter(([el]) => el !== element2);
  }
};
var domLayout_default = '<div role="presentation" class="ag-charts-wrapper ag-charts-styles" data-ag-charts><div role="presentation" class="ag-charts-canvas-center"><div role="presentation" class="ag-charts-canvas-container"><div role="presentation" class="ag-charts-canvas" aria-hidden="true"></div><div role="figure" class="ag-charts-canvas-proxy"><div role="presentation" class="ag-charts-series-area"></div></div><div role="presentation" class="ag-charts-canvas-overlay"></div></div></div></div>';
var DOM_ELEMENT_CLASSES = [
  "styles",
  "canvas",
  "canvas-center",
  "canvas-container",
  "canvas-overlay",
  "canvas-proxy",
  "series-area"
];
var domElementConfig = /* @__PURE__ */ new Map([
  ["styles", { childElementType: "style" }],
  ["canvas", { childElementType: "canvas" }],
  ["canvas-proxy", { childElementType: "div" }],
  ["canvas-overlay", { childElementType: "div" }],
  ["canvas-center", { childElementType: "div" }],
  ["series-area", { childElementType: "div" }]
]);
function setupObserver(element2, cb) {
  if (typeof IntersectionObserver === "undefined")
    return;
  const observer = new IntersectionObserver(
    (entries) => {
      for (const entry of entries) {
        if (entry.target === element2) {
          cb(entry.intersectionRatio);
        }
      }
    },
    { root: element2 }
  );
  observer.observe(element2);
  return observer;
}
var NULL_DOMRECT = {
  x: 0,
  y: 0,
  width: 0,
  height: 0,
  top: 0,
  bottom: 0,
  left: 0,
  right: 0,
  toJSON() {
    return NULL_DOMRECT;
  }
};
function createTabGuardElement(guardedElem, where) {
  const div = createElement("div");
  div.className = "ag-charts-tab-guard";
  guardedElem.insertAdjacentElement(where, div);
  return div;
}
var DOMManager = class extends BaseManager {
  constructor(container, styleContainer) {
    super();
    this.styles = /* @__PURE__ */ new Map();
    this.container = void 0;
    this.containerSize = void 0;
    this.sizeMonitor = new SizeMonitor();
    const templateEl = createElement("div");
    templateEl.innerHTML = domLayout_default;
    this.element = templateEl.children.item(0);
    this.styleRootElement = styleContainer;
    this.rootElements = DOM_ELEMENT_CLASSES.reduce(
      (r, c) => {
        const cssClass = `ag-charts-${c}`;
        const el = this.element.classList.contains(cssClass) ? this.element : this.element.querySelector(`.${cssClass}`);
        if (!el)
          throw new Error(`AG Charts - unable to find DOM element ${cssClass}`);
        r[c] = { element: el, children: /* @__PURE__ */ new Map(), listeners: [] };
        return r;
      },
      {}
    );
    let hidden = false;
    this.observer = setupObserver(this.element, (intersectionRatio) => {
      if (intersectionRatio === 0 && !hidden) {
        this.listeners.dispatch("hidden", { type: "hidden" });
      }
      hidden = intersectionRatio === 0;
    });
    this.setSizeOptions();
    this.addStyles("ag-charts-community", styles_default);
    if (container) {
      this.setContainer(container);
    }
    this.destroyFns.push(stopPageScrolling(this.element));
    const guardedElement = this.element.querySelector(".ag-charts-canvas-center");
    if (guardedElement == null)
      throw new Error("Error initializing tab guards");
    const topGuard = createTabGuardElement(guardedElement, "beforebegin");
    const botGuard = createTabGuardElement(guardedElement, "afterend");
    this.tabGuards = new GuardedElement(guardedElement, topGuard, botGuard);
  }
  destroy() {
    super.destroy();
    this.observer?.unobserve(this.element);
    if (this.container) {
      this.sizeMonitor.unobserve(this.container);
    }
    Object.values(this.rootElements).forEach((el) => {
      el.children.forEach((c) => c.remove());
      el.element.remove();
    });
    this.element.remove();
  }
  setSizeOptions(minWidth = 300, minHeight = 300, optionsWidth, optionsHeight) {
    const { style } = this.element;
    style.width = `${optionsWidth ?? minWidth}px`;
    style.height = `${optionsHeight ?? minHeight}px`;
  }
  updateContainerSize() {
    const { style: centerStyle } = this.rootElements["canvas-center"].element;
    centerStyle.width = `${this.containerSize?.width ?? 0}px`;
    centerStyle.height = `${this.containerSize?.height ?? 0}px`;
  }
  setTabGuardIndex(tabIndex) {
    this.tabGuards.tabIndex = tabIndex;
  }
  setContainer(newContainer) {
    if (newContainer === this.container)
      return;
    if (this.container) {
      this.container.removeChild(this.element);
      this.sizeMonitor.unobserve(this.container);
    }
    const isShadowDom = this.getShadowDocumentRoot(newContainer) != null;
    if (!isShadowDom) {
      for (const id of this.rootElements["styles"].children.keys()) {
        this.removeChild("styles", id);
      }
    }
    this.container = newContainer;
    for (const [id, styles] of this.styles) {
      this.addStyles(id, styles);
    }
    newContainer.appendChild(this.element);
    this.sizeMonitor.observe(newContainer, (size) => {
      this.containerSize = size;
      this.updateContainerSize();
      this.listeners.dispatch("resize", { type: "resize" });
    });
    this.listeners.dispatch("container-changed", { type: "container-changed" });
  }
  setThemeClass(themeClassName) {
    const themeClassNamePrefix = "ag-charts-theme-";
    this.element.classList.forEach((className) => {
      if (className.startsWith(themeClassNamePrefix) && className !== themeClassName) {
        this.element.classList.remove(className);
      }
    });
    this.element.classList.add(themeClassName);
  }
  updateCanvasLabel(ariaLabel) {
    setAttribute(this.rootElements["canvas-proxy"].element, "aria-label", ariaLabel);
  }
  getEventElement(defaultElem, eventType) {
    const events = ["focus", "blur", "keydown", "keyup"];
    return events.includes(eventType) ? this.rootElements["series-area"].element : defaultElem;
  }
  addEventListener(type, listener, options) {
    this.getEventElement(this.element, type).addEventListener(type, listener, options);
  }
  removeEventListener(type, listener, options) {
    this.getEventElement(this.element, type).removeEventListener(type, listener, options);
  }
  /** Get the main chart area client bound rect. */
  getBoundingClientRect() {
    return this.rootElements["canvas"].element.getBoundingClientRect();
  }
  /**
   * Get the client bounding rect for overlay elements that might float outside the bounds of the
   * main chart area.
   */
  getOverlayClientRect() {
    const window2 = getWindow();
    const windowBBox = new BBox(0, 0, window2.innerWidth, window2.innerHeight);
    const containerBBox = this.getRawOverlayClientRect();
    return windowBBox.intersection(containerBBox)?.toDOMRect() ?? NULL_DOMRECT;
  }
  getRawOverlayClientRect() {
    let element2 = this.element;
    while (element2 != null) {
      const styleMap = element2.computedStyleMap?.();
      const overflowY = styleMap?.get("overflow-y")?.toString();
      if (overflowY === "auto" || overflowY === "scroll") {
        return BBox.fromDOMRect(element2.getBoundingClientRect());
      }
      element2 = element2.parentElement;
    }
    const docRoot = this.getShadowDocumentRoot();
    if (docRoot != null)
      return BBox.fromDOMRect(docRoot.getBoundingClientRect());
    const { innerWidth, innerHeight } = getWindow();
    return new BBox(0, 0, innerWidth, innerHeight);
  }
  getShadowDocumentRoot(current = this.container) {
    const docRoot = current?.ownerDocument?.body ?? getDocument("body");
    while (current != null) {
      if (current === docRoot) {
        return void 0;
      }
      if (current.parentNode instanceof DocumentFragment) {
        return current;
      }
      current = current.parentNode;
    }
    return this.container;
  }
  getParent(domElementClass) {
    return this.rootElements[domElementClass].element;
  }
  getChildBoundingClientRect(type) {
    const { children } = this.rootElements[type];
    const childRects = [];
    for (const child of children.values()) {
      childRects.push(BBox.fromDOMRect(child.getBoundingClientRect()));
    }
    return BBox.merge(childRects);
  }
  calculateCanvasPosition(el) {
    let x = 0;
    let y = 0;
    const { x: cx = 0, y: cy = 0 } = this.getChildBoundingClientRect("canvas") ?? {};
    const elRect = el.getBoundingClientRect();
    x = elRect.x - cx;
    y = elRect.y - cy;
    return { x, y };
  }
  isManagedChildDOMElement(el, domElementClass, id) {
    const { children } = this.rootElements[domElementClass];
    const search = children?.get(id);
    return search != null && el.contains(search);
  }
  contains(element2, domElementClass) {
    if (domElementClass == null)
      return this.element.contains(element2);
    return this.rootElements[domElementClass].element.contains(element2);
  }
  addStyles(id, styles) {
    const dataAttribute = "data-ag-charts";
    this.styles.set(id, styles);
    if (this.container == null)
      return;
    const checkId = (el) => {
      return el.getAttribute(dataAttribute) === id;
    };
    const addStyleElement = (el) => {
      const metaElements = /* @__PURE__ */ new Set(["TITLE", "META"]);
      let skippingMetaElements = true;
      let insertAfterEl;
      for (const child of el.children) {
        if (skippingMetaElements && metaElements.has(child.tagName)) {
          insertAfterEl = child;
          continue;
        }
        skippingMetaElements = false;
        if (checkId(child))
          return;
        if (child.hasAttribute(dataAttribute)) {
          insertAfterEl = child;
        }
      }
      const styleEl = createElement("style");
      if (insertAfterEl != null) {
        el.insertBefore(styleEl, insertAfterEl.nextSibling);
      } else {
        el.prepend(styleEl);
      }
      return styleEl;
    };
    let styleElement;
    if (this.styleRootElement) {
      styleElement = addStyleElement(this.styleRootElement);
    } else {
      const documentRoot = this.getShadowDocumentRoot(this.container);
      if (documentRoot != null) {
        styleElement = this.addChild("styles", id);
      } else {
        styleElement = addStyleElement(getDocument("head"));
      }
    }
    if (styleElement == null || checkId(styleElement))
      return;
    styleElement.setAttribute(dataAttribute, id);
    styleElement.innerHTML = styles;
  }
  removeStyles(id) {
    this.removeChild("styles", id);
  }
  updateCursor(style) {
    this.element.style.cursor = style;
  }
  getCursor() {
    return this.element.style.cursor;
  }
  addChild(domElementClass, id, child, insert) {
    const { element: element2, children, listeners } = this.rootElements[domElementClass];
    if (!children) {
      throw new Error("AG Charts - unable to create DOM elements after destroy()");
    }
    if (children.has(id)) {
      return children.get(id);
    }
    const { childElementType = "div" } = domElementConfig.get(domElementClass) ?? {};
    if (child && child.tagName.toLowerCase() !== childElementType.toLowerCase()) {
      throw new Error("AG Charts - mismatching DOM element type");
    }
    const newChild = child ?? createElement(childElementType);
    for (const [type, fn, opts] of listeners) {
      newChild.addEventListener(type, fn, opts);
    }
    children.set(id, newChild);
    if (insert) {
      const queryResult = element2.querySelector(insert.query);
      if (queryResult == null) {
        throw new Error(`AG Charts - addChild query failed ${insert.query}`);
      }
      queryResult.insertAdjacentElement(insert.where, newChild);
    } else {
      element2?.appendChild(newChild);
    }
    return newChild;
  }
  removeChild(domElementClass, id) {
    const { children } = this.rootElements[domElementClass];
    if (!children)
      return;
    children.get(id)?.remove();
    children.delete(id);
  }
  incrementDataCounter(name) {
    const { dataset } = this.element;
    dataset[name] ?? (dataset[name] = "0");
    dataset[name] = String(Number(dataset[name]) + 1);
  }
  setDataBoolean(name, value) {
    this.element.dataset[name] = String(value);
  }
};
var WIDGET_HTML_EVENTS = [
  "blur",
  "change",
  "contextmenu",
  "focus",
  "keydown",
  "keyup",
  "click",
  "dblclick",
  "mouseenter",
  "mousemove",
  "mouseleave",
  "wheel"
];
function allocMouseEvent(type, sourceEvent) {
  const { offsetX, offsetY, clientX, clientY } = sourceEvent;
  return { type, offsetX, offsetY, clientX, clientY, sourceEvent };
}
var WidgetAllocators = {
  blur: (sourceEvent) => {
    return { type: "blur", sourceEvent };
  },
  change: (sourceEvent) => {
    return { type: "change", sourceEvent };
  },
  contextmenu: (sourceEvent) => {
    return allocMouseEvent("contextmenu", sourceEvent);
  },
  focus: (sourceEvent) => {
    return { type: "focus", sourceEvent };
  },
  keydown: (sourceEvent) => {
    return { type: "keydown", sourceEvent };
  },
  keyup: (sourceEvent) => {
    return { type: "keyup", sourceEvent };
  },
  click: (sourceEvent) => {
    return allocMouseEvent("click", sourceEvent);
  },
  dblclick: (sourceEvent) => {
    return allocMouseEvent("dblclick", sourceEvent);
  },
  mouseenter: (sourceEvent) => {
    return allocMouseEvent("mouseenter", sourceEvent);
  },
  mousemove: (sourceEvent) => {
    return allocMouseEvent("mousemove", sourceEvent);
  },
  mouseleave: (sourceEvent) => {
    return allocMouseEvent("mouseleave", sourceEvent);
  },
  wheel: (sourceEvent) => {
    const { offsetX, offsetY, clientX, clientY, deltaX, deltaY } = sourceEvent;
    return { type: "wheel", offsetX, offsetY, clientX, clientY, deltaX, deltaY, sourceEvent };
  }
};
var WidgetEventUtil = class {
  static alloc(type, sourceEvent) {
    return WidgetAllocators[type](sourceEvent);
  }
  static isHTMLEvent(type) {
    const htmlTypes = WIDGET_HTML_EVENTS;
    return htmlTypes.includes(type);
  }
};
var WidgetListenerHTML = class {
  constructor() {
    this.maps = {};
  }
  lazyGetMap(type) {
    let result = this.maps[type];
    if (result === void 0) {
      result = /* @__PURE__ */ new Map();
      this.maps[type] = result;
    }
    return result;
  }
  add(type, target, handler) {
    const map = this.lazyGetMap(type);
    if (map.has(handler))
      throw new Error("AG Charts - duplicate add(handler)");
    const sourceHandler = (sourceEvent) => {
      const widgetEvent = WidgetEventUtil.alloc(type, sourceEvent);
      handler(widgetEvent, target);
    };
    target.getElement().addEventListener(type, sourceHandler);
    map.set(handler, sourceHandler);
  }
  remove(type, target, handler) {
    const map = this.lazyGetMap(type);
    const sourceHandler = map.get(handler);
    if (sourceHandler) {
      target.getElement().removeEventListener(type, sourceHandler);
    }
    map.delete(handler);
  }
  destroy(target) {
    for (const type of Object.keys(this.maps)) {
      this.typedDestroy(type, target);
    }
  }
  typedDestroy(type, target) {
    const map = this.maps[type];
    if (map == null)
      return;
    for (const [_widgetHandler, sourceHandler] of map.entries()) {
      target.getElement().removeEventListener(type, sourceHandler);
    }
  }
};
function makeDragEvent(type, origin3, sourceEvent) {
  const originDeltaX = sourceEvent.pageX - origin3.pageX;
  const originDeltaY = sourceEvent.pageY - origin3.pageY;
  return {
    type,
    offsetX: origin3.offsetX + originDeltaX,
    offsetY: origin3.offsetY + originDeltaY,
    clientX: sourceEvent.clientX,
    clientY: sourceEvent.clientY,
    originDeltaX,
    originDeltaY,
    sourceEvent
  };
}
function startDrag(that, myCallbacks, downEvent) {
  if (that.globalDragCallbacks != null)
    return;
  const window2 = getWindow();
  const mousegeneral = (generalEvent) => {
    generalEvent.stopPropagation();
    generalEvent.stopImmediatePropagation();
  };
  const mousemove = (moveEvent) => {
    moveEvent.stopPropagation();
    moveEvent.stopImmediatePropagation();
    that.globalDragCallbacks?.move(moveEvent);
  };
  const mouseup = (upEvent) => {
    if (upEvent.button === 0) {
      upEvent.stopPropagation();
      upEvent.stopImmediatePropagation();
      window2.removeEventListener("mousedown", mousegeneral, { capture: true });
      window2.removeEventListener("mouseenter", mousegeneral, { capture: true });
      window2.removeEventListener("mouseleave", mousegeneral, { capture: true });
      window2.removeEventListener("mouseout", mousegeneral, { capture: true });
      window2.removeEventListener("mouseover", mousegeneral, { capture: true });
      window2.removeEventListener("mousemove", mousemove, { capture: true });
      window2.removeEventListener("mouseup", mouseup, { capture: true });
      that.globalDragCallbacks?.up(upEvent);
      that.globalDragCallbacks = void 0;
    }
  };
  window2.addEventListener("mousedown", mousegeneral, { capture: true });
  window2.addEventListener("mouseenter", mousegeneral, { capture: true });
  window2.addEventListener("mouseleave", mousegeneral, { capture: true });
  window2.addEventListener("mouseout", mousegeneral, { capture: true });
  window2.addEventListener("mouseover", mousegeneral, { capture: true });
  window2.addEventListener("mousemove", mousemove, { capture: true });
  window2.addEventListener("mouseup", mouseup, { capture: true });
  that.globalDragCallbacks = myCallbacks;
  that.globalDragCallbacks.down(downEvent);
}
var WidgetListenerInternal = class _WidgetListenerInternal {
  destroy() {
    this.dragTriggerRemovers?.forEach((fn) => fn());
    this.dragTriggerRemovers = void 0;
    this.dragStartListeners = void 0;
    this.dragMoveListeners = void 0;
    this.dragEndListeners = void 0;
    if (_WidgetListenerInternal.globalDragCallbacks === this.localDragCallbacks) {
      _WidgetListenerInternal.globalDragCallbacks = void 0;
    }
  }
  add(type, target, handler) {
    switch (type) {
      case "drag-start": {
        this.dragStartListeners ?? (this.dragStartListeners = []);
        this.dragStartListeners.push(handler);
        this.registerDragTrigger(target, handler);
        break;
      }
      case "drag-move": {
        this.dragMoveListeners ?? (this.dragMoveListeners = []);
        this.dragMoveListeners.push(handler);
        break;
      }
      case "drag-end": {
        this.dragEndListeners ?? (this.dragEndListeners = []);
        this.dragEndListeners.push(handler);
        break;
      }
    }
  }
  remove(type, _target, handler) {
    switch (type) {
      case "drag-start":
        return this.removeHandler(this.dragStartListeners, handler);
      case "drag-move":
        return this.removeHandler(this.dragMoveListeners, handler);
      case "drag-end":
        return this.removeHandler(this.dragEndListeners, handler);
    }
  }
  removeHandler(array2, handler) {
    const index = array2?.indexOf(handler);
    if (index !== void 0)
      array2?.splice(index, 1);
  }
  registerDragTrigger(target, handler) {
    const mouseDownHandler = (event) => event.button === 0 && this.startDrag(target, event);
    target.getElement().addEventListener("mousedown", mouseDownHandler);
    this.dragTriggerRemovers ?? (this.dragTriggerRemovers = /* @__PURE__ */ new Map());
    this.dragTriggerRemovers.set(
      handler,
      () => target.getElement().removeEventListener("mousedown", mouseDownHandler)
    );
  }
  startDrag(current, initialDownEvent) {
    const origin3 = { pageX: NaN, pageY: NaN, offsetX: NaN, offsetY: NaN };
    partialAssign(["pageX", "pageY", "offsetX", "offsetY"], origin3, initialDownEvent);
    const dragCallbacks = {
      down: (downEvent) => {
        this.localDragCallbacks = dragCallbacks;
        const dragStartEvent = makeDragEvent("drag-start", origin3, downEvent);
        this.dispatch("drag-start", current, dragStartEvent);
      },
      move: (moveEvent) => {
        const dragMoveEvent = makeDragEvent("drag-move", origin3, moveEvent);
        this.dispatch("drag-move", current, dragMoveEvent);
      },
      up: (upEvent) => {
        const dragEndEvent = makeDragEvent("drag-end", origin3, upEvent);
        this.dispatch("drag-end", current, dragEndEvent);
        this.endDrag(current, dragEndEvent);
      }
    };
    startDrag(_WidgetListenerInternal, dragCallbacks, initialDownEvent);
  }
  endDrag(target, { sourceEvent, clientX, clientY }) {
    const elem = target.getElement();
    const rect = elem.getBoundingClientRect();
    if (!BBoxValues.containsPoint(rect, clientX, clientY)) {
      elem.dispatchEvent(new MouseEvent("mouseleave", sourceEvent));
      sourceEvent.target?.dispatchEvent(new MouseEvent("mouseenter", sourceEvent));
    }
  }
  dispatch(type, current, event) {
    switch (type) {
      case "drag-start":
        return this.dragStartListeners?.forEach((handler) => handler(event, current));
      case "drag-move":
        return this.dragMoveListeners?.forEach((handler) => handler(event, current));
      case "drag-end":
        return this.dragEndListeners?.forEach((handler) => handler(event, current));
    }
  }
};
var WidgetBounds = class {
  constructor(elem) {
    this.elem = elem;
  }
  setBounds(bounds) {
    setElementBBox(this.elemContainer ?? this.elem, bounds);
  }
  getBounds() {
    return getElementBBox(this.elemContainer ?? this.elem);
  }
  static setElementContainer(widget, elemContainer) {
    const currentBounds = widget.getBounds();
    setElementBBox(elemContainer, currentBounds);
    setElementStyles(widget.elem, { width: "100%", height: "100%" });
    widget.elem.remove();
    widget.elemContainer = elemContainer;
    widget.elemContainer.replaceChildren(widget.elem);
  }
};
var Widget = class extends WidgetBounds {
  constructor(elem) {
    super(elem);
    this.elem = elem;
    this.index = NaN;
    this.children = [];
  }
  getElement() {
    return this.elem;
  }
  get clientWidth() {
    return this.elem.clientWidth;
  }
  get clientHeight() {
    return this.elem.clientHeight;
  }
  destroy() {
    this.parent?.removeChild(this);
    this.children.forEach((child) => {
      child.parent = void 0;
      child.destroy();
    });
    this.children.length = 0;
    this.destructor();
    this.elem.remove();
    this.elemContainer?.remove();
    this.internalListener?.destroy();
    this.htmlListener?.destroy(this);
  }
  setHidden(hidden) {
    setElementStyle(this.elem, "display", hidden ? "none" : void 0);
  }
  isHidden() {
    return getWindow()?.getComputedStyle?.(this.elem).display === "none";
  }
  setCursor(cursor) {
    setElementStyle(this.elem, "cursor", cursor);
  }
  setTextContent(textContent) {
    this.elem.textContent = textContent ?? null;
  }
  setAriaDescribedBy(ariaDescribedBy) {
    setAttribute(this.elem, "aria-describedby", ariaDescribedBy);
  }
  setAriaHidden(ariaHidden) {
    setAttribute(this.elem, "aria-hidden", ariaHidden);
  }
  setAriaLabel(ariaLabel) {
    setAttribute(this.elem, "aria-label", ariaLabel);
  }
  setInnerHTML(html) {
    this.elem.innerHTML = html;
  }
  isDisabled() {
    return getAttribute(this.elem, "aria-disabled", false);
  }
  parseFloat(s) {
    return s === "" ? 0 : parseFloat(s);
  }
  cssLeft() {
    return this.parseFloat(this.elem.style.left);
  }
  cssTop() {
    return this.parseFloat(this.elem.style.top);
  }
  focus() {
    this.elem.focus();
  }
  setPreventsDefault(preventDefault) {
    setAttribute(this.elem, "data-preventdefault", preventDefault);
  }
  setTabIndex(tabIndex) {
    setAttribute(this.elem, "tabindex", tabIndex);
  }
  addChild(child) {
    this.addChildToDOM(child, this.getBefore(child));
    this.children.push(child);
    child.index = this.children.length - 1;
    child.parent = this;
    this.onChildAdded(child);
  }
  removeChild(child) {
    const i = this.children.findIndex((value) => value === child);
    this.children.splice(i, 1);
    this.removeChildFromDOM(child);
    this.onChildRemoved(child);
  }
  addClass(...tokens) {
    this.elem.classList.add(...tokens);
  }
  removeClass(...tokens) {
    this.elem.classList.remove(...tokens);
  }
  toggleClass(token, force) {
    this.elem.classList.toggle(token, force);
  }
  appendOrInsert(child, before) {
    if (before) {
      before.getElement().insertAdjacentElement("beforebegin", child);
    } else {
      this.elem.appendChild(child);
    }
  }
  addChildToDOM(child, before) {
    this.appendOrInsert(child.getElement(), before);
  }
  removeChildFromDOM(child) {
    this.elem.removeChild(child.getElement());
  }
  onChildAdded(_child) {
  }
  onChildRemoved(_child) {
  }
  getBefore({ domIndex }) {
    if (domIndex === void 0)
      return void 0;
    return this.children.filter((child) => child.domIndex !== void 0 && child.domIndex > domIndex).reduce((prev, curr) => !prev || curr.domIndex < prev.domIndex ? curr : prev, void 0);
  }
  addListener(type, listener) {
    if (WidgetEventUtil.isHTMLEvent(type)) {
      this.htmlListener ?? (this.htmlListener = new WidgetListenerHTML());
      this.htmlListener.add(type, this, listener);
    } else {
      this.internalListener ?? (this.internalListener = new WidgetListenerInternal());
      this.internalListener.add(type, this, listener);
    }
  }
  removeListener(type, listener) {
    if (WidgetEventUtil.isHTMLEvent(type)) {
      this.htmlListener?.remove(type, this, listener);
    } else if (this.htmlListener != null) {
      this.internalListener?.remove(type, this, listener);
    }
  }
};
var BoundedTextWidget = class extends Widget {
  constructor() {
    super(getDocument().createElement("div"));
    this.textElement = createElementNS("http://www.w3.org/2000/svg", "text");
    this.textElement.role = "presentation";
    this.svgElement = createElementNS("http://www.w3.org/2000/svg", "svg");
    this.svgElement.appendChild(this.textElement);
    this.svgElement.style.width = "100%";
    this.svgElement.style.opacity = "0";
    this.svgElement.role = "presentation";
    this.elem.appendChild(this.svgElement);
    this.elem.role = "presentation";
  }
  set textContent(text) {
    this.textElement.textContent = text;
    const bboxCalculator = this.textElement;
    const bbox = bboxCalculator.getBBox?.();
    if (bbox) {
      this.svgElement.setAttribute("viewBox", `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`);
    }
  }
  get textContent() {
    return this.textElement.textContent;
  }
  destructor() {
  }
};
var ButtonWidget = class extends Widget {
  constructor() {
    super(getDocument().createElement("button"));
    this.setEnabled(true);
  }
  destructor() {
  }
  setEnabled(enabled) {
    setAttribute(this.elem, "aria-disabled", !enabled);
    setElementStyle(this.elem, "pointer-events", enabled ? void 0 : "none");
  }
  addListener(type, listener) {
    return super.addListener(type, (ev, current) => {
      if ((type === "click" || type === "dblclick") && this.isDisabled())
        return;
      listener(ev, current);
    });
  }
};
var GroupWidget = class extends Widget {
  constructor() {
    super(getDocument().createElement("div"));
    setAttribute(this.elem, "role", "group");
  }
  destructor() {
  }
};
var RovingTabContainerWidget = class extends Widget {
  constructor(initialOrientation, role) {
    super(getDocument().createElement("div"));
    this.focusedChildIndex = 0;
    this.onChildFocus = (_event, child) => {
      const oldFocus = this.children[this.focusedChildIndex];
      this.focusedChildIndex = child.index;
      oldFocus?.setTabIndex(-1);
      child.setTabIndex(0);
    };
    this.onChildKeyDown = (event, child) => {
      const rovingOrientation = this.orientation;
      const [primaryKeys, secondaryKeys] = rovingOrientation === "both" ? [PREV_NEXT_KEYS["horizontal"], PREV_NEXT_KEYS["vertical"]] : [PREV_NEXT_KEYS[rovingOrientation], void 0];
      let targetIndex = -1;
      if (hasNoModifiers(event.sourceEvent)) {
        const key = event.sourceEvent.key;
        if (key === primaryKeys.nextKey || key === secondaryKeys?.nextKey) {
          targetIndex = child.index + 1;
        } else if (key === primaryKeys.prevKey || key === secondaryKeys?.prevKey) {
          targetIndex = child.index - 1;
        }
      }
      this.children[targetIndex]?.focus();
    };
    this.orientation = initialOrientation;
    setAttribute(this.elem, "role", role);
  }
  get orientation() {
    return getAttribute(this.elem, "aria-orientation") ?? "both";
  }
  set orientation(orientation) {
    setAttribute(this.elem, "aria-orientation", orientation !== "both" ? orientation : void 0);
  }
  focus() {
    this.children[this.focusedChildIndex]?.focus();
  }
  onChildAdded(child) {
    child.addListener("focus", this.onChildFocus);
    child.addListener("keydown", this.onChildKeyDown);
    child.setTabIndex(this.children.length === 1 ? 0 : -1);
  }
  onChildRemoved(child) {
    child.removeListener("focus", this.onChildFocus);
    child.removeListener("keydown", this.onChildKeyDown);
  }
};
var ListWidget = class extends RovingTabContainerWidget {
  constructor() {
    super("both", "list");
    this.setHidden(true);
  }
  destructor() {
    this.children.forEach((c) => c.getElement().parentElement.remove());
  }
  addChildToDOM(child, before) {
    const listitem = getDocument().createElement("div");
    setAttribute(listitem, "role", "listitem");
    setElementStyle(listitem, "position", "absolute");
    Widget.setElementContainer(child, listitem);
    this.appendOrInsert(listitem, before);
    this.setHidden(false);
  }
  removeChildFromDOM(child) {
    child.getElement().parentElement.remove();
    this.setHidden(this.children.length === 0);
  }
  setHidden(hidden) {
    if (this.children.length === 0) {
      hidden = true;
    }
    super.setHidden(hidden);
  }
};
var NativeWidget = class extends Widget {
  constructor(elem) {
    super(elem);
  }
  destructor() {
  }
};
var _SliderWidget = class _SliderWidget2 extends Widget {
  constructor() {
    super(getDocument().createElement("input"));
    this._step = _SliderWidget2.STEP_ONE;
    this.orientation = "both";
  }
  get step() {
    return this._step;
  }
  set step(step) {
    this._step = step;
    this.getElement().step = step.attributeValue;
  }
  get keyboardStep() {
    return this._keyboardStep?.step ?? this._step;
  }
  set keyboardStep(step) {
    if (step === this._keyboardStep?.step)
      return;
    if (this._keyboardStep !== void 0) {
      this.removeListener("keydown", this._keyboardStep.onKeyDown);
      this.removeListener("keyup", this._keyboardStep.onKeyUp);
      this.removeListener("blur", this._keyboardStep.onBlur);
      this._keyboardStep = void 0;
    }
    if (step !== void 0) {
      const onKeyDown = () => this.getElement().step = step.attributeValue;
      const resetStep = () => this.getElement().step = this._step.attributeValue;
      this._keyboardStep = { step, onKeyDown, onKeyUp: resetStep, onBlur: resetStep };
      this.addListener("keydown", this._keyboardStep.onKeyDown);
      this.addListener("keyup", this._keyboardStep.onKeyUp);
      this.addListener("blur", this._keyboardStep.onBlur);
    }
  }
  get orientation() {
    return getAttribute(this.elem, "aria-orientation") ?? "both";
  }
  set orientation(orientation) {
    setAttribute(this.elem, "aria-orientation", orientation !== "both" ? orientation : void 0);
    _SliderWidget2.registerDefaultPreventers(this, orientation);
  }
  destructor() {
  }
  clampValueRatio(clampMin, clampMax) {
    const ratio2 = this.getValueRatio();
    const clampedRatio = clamp(clampMin, ratio2, clampMax);
    if (clampedRatio !== ratio2) {
      this.setValueRatio(clampedRatio);
    }
    return clampedRatio;
  }
  setValueRatio(ratio2, opts) {
    const { divider } = this.step;
    const value = Math.round(ratio2 * 1e4) / divider;
    const { ariaValueText = formatPercent(value / divider) } = opts ?? {};
    const elem = this.getElement();
    elem.value = `${value}`;
    elem.ariaValueText = ariaValueText;
  }
  getValueRatio() {
    return parseFloat(this.getElement().value) / this.step.divider;
  }
  static registerDefaultPreventers(target, orientation) {
    if (orientation === "both") {
      target.removeListener("keydown", _SliderWidget2.onKeyDown);
    } else {
      target.addListener("keydown", _SliderWidget2.onKeyDown);
    }
  }
  static onKeyDown(ev, current) {
    let ignoredKeys = [];
    const { orientation } = current;
    if (orientation === "horizontal") {
      ignoredKeys = ["ArrowUp", "ArrowDown"];
    } else if (orientation === "vertical") {
      ignoredKeys = ["ArrowLeft", "ArrowRight"];
    }
    if (ignoredKeys.includes(ev.sourceEvent.code)) {
      ev.sourceEvent.preventDefault();
    }
  }
};
_SliderWidget.STEP_ONE = { attributeValue: "1", divider: 1 };
_SliderWidget.STEP_HUNDRETH = { attributeValue: "0.01", divider: 100 };
var SliderWidget = _SliderWidget;
var SwitchWidget = class extends ButtonWidget {
  constructor() {
    super();
    setAttribute(this.elem, "role", "switch");
    this.setChecked(false);
  }
  setChecked(checked) {
    setAttribute(this.elem, "aria-checked", checked);
  }
};
var ToolbarWidget = class extends RovingTabContainerWidget {
  constructor(orientation = "horizontal") {
    super(orientation, "toolbar");
  }
  destructor() {
  }
};
function checkType(type, meta) {
  return meta.params?.type === type;
}
function allocateResult(type) {
  if ("button" === type) {
    return new ButtonWidget();
  } else if ("slider" === type) {
    return new SliderWidget();
  } else if ("toolbar" === type) {
    return new ToolbarWidget();
  } else if ("group" === type) {
    return new GroupWidget();
  } else if ("list" === type) {
    return new ListWidget();
  } else if ("region" === type) {
    return new NativeWidget(createElement("div"));
  } else if ("text" === type) {
    return new BoundedTextWidget();
  } else if ("listswitch" === type) {
    return new SwitchWidget();
  } else {
    throw Error("AG Charts - error allocating meta");
  }
}
function allocateMeta(params) {
  const meta = { params, result: void 0 };
  meta.result = allocateResult(meta.params.type);
  return meta;
}
var ProxyInteractionService = class {
  constructor(localeManager, domManager) {
    this.localeManager = localeManager;
    this.domManager = domManager;
    this.destroyFns = [];
  }
  destroy() {
    this.destroyFns.forEach((fn) => fn());
  }
  addLocalisation(fn) {
    fn();
    this.destroyFns.push(this.localeManager.addListener("locale-changed", fn));
  }
  createProxyContainer(args) {
    const meta = allocateMeta(args);
    const { params, result } = meta;
    const div = result.getElement();
    this.domManager.addChild("canvas-proxy", params.domManagerId, div);
    div.classList.add(...params.classList, "ag-charts-proxy-container");
    div.role = params.type;
    if ("ariaOrientation" in params) {
      div.ariaOrientation = params.ariaOrientation;
    }
    if (checkType("toolbar", meta)) {
      meta.result.orientation = meta.params.orientation;
    }
    this.addLocalisation(() => {
      div.ariaLabel = this.localeManager.t(params.ariaLabel.id, params.ariaLabel.params);
    });
    return result;
  }
  createProxyElement(args) {
    const meta = allocateMeta(args);
    if (checkType("button", meta)) {
      const { params, result } = meta;
      const button = result.getElement();
      this.initInteract(params, result);
      if (typeof params.textContent === "string") {
        button.textContent = params.textContent;
      } else {
        const { textContent } = params;
        this.addLocalisation(() => {
          button.textContent = this.localeManager.t(textContent.id, textContent.params);
        });
      }
      this.setParent(meta.params, meta.result);
    }
    if (checkType("slider", meta)) {
      const { params, result } = meta;
      const slider = result.getElement();
      this.initInteract(params, result);
      slider.type = "range";
      slider.role = "presentation";
      slider.style.margin = "0px";
      this.addLocalisation(() => {
        slider.ariaLabel = this.localeManager.t(params.ariaLabel.id, params.ariaLabel.params);
      });
      this.setParent(meta.params, meta.result);
    }
    if (checkType("text", meta)) {
      const { params, result } = meta;
      this.initElement(params, result);
      this.setParent(meta.params, meta.result);
    }
    if (checkType("listswitch", meta)) {
      const { params, result: button } = meta;
      this.initInteract(params, button);
      button.setTextContent(params.textContent);
      button.setChecked(params.ariaChecked);
      button.setAriaDescribedBy(params.ariaDescribedBy);
      this.setParent(meta.params, meta.result);
    }
    if (checkType("region", meta)) {
      const { params, result } = meta;
      const region = result.getElement();
      this.initInteract(params, result);
      region.role = "region";
      this.setParent(meta.params, meta.result);
    }
    return meta.result;
  }
  initElement(params, widget) {
    const element2 = widget.getElement();
    setAttribute(element2, "id", params.id);
    setElementStyle(element2, "cursor", params.cursor);
    element2.classList.toggle("ag-charts-proxy-elem", true);
    return element2;
  }
  initInteract(params, widget) {
    const { tabIndex, domIndex } = params;
    const element2 = this.initElement(params, widget);
    if (tabIndex !== void 0) {
      element2.tabIndex = tabIndex;
    }
    if (domIndex !== void 0) {
      widget.domIndex = domIndex;
    }
  }
  setParent(params, element2) {
    if ("parent" in params) {
      params.parent?.addChild(element2);
    } else {
      const insert = { where: params.where, query: ".ag-charts-series-area" };
      this.domManager.addChild("canvas-proxy", params.domManagerId, element2.getElement(), insert);
    }
  }
};
var messageRegExp = /\$\{(\w+)}(?:\[(\w+)])?/gi;
var formatters = {
  number: new Intl.NumberFormat("en-US"),
  percent: new Intl.NumberFormat("en-US", { style: "percent", minimumFractionDigits: 2, maximumFractionDigits: 2 }),
  date: new Intl.DateTimeFormat("en-US", { dateStyle: "full" }),
  time: new Intl.DateTimeFormat("en-US", { timeStyle: "full" }),
  datetime: new Intl.DateTimeFormat("en-US", { dateStyle: "full", timeStyle: "full" })
};
var defaultMessageFormatter = ({ defaultValue, variables }) => {
  return defaultValue?.replaceAll(messageRegExp, (_, match, format) => {
    const value = variables[match];
    const formatter = format != null ? formatters[format] : null;
    if (format != null && formatter == null) {
      Logger.warnOnce(`Format style [${format}] is not supported`);
    }
    if (formatter != null) {
      return formatter.format(value);
    } else if (typeof value === "number") {
      return formatters.number.format(value);
    } else if (value instanceof Date) {
      return formatters.datetime.format(value);
    }
    return String(value);
  });
};
var LocaleManager = class extends Listeners {
  constructor() {
    super(...arguments);
    this.localeText = void 0;
    this.getLocaleText = void 0;
  }
  setLocaleText(localeText) {
    if (this.localeText !== localeText) {
      this.localeText = localeText;
      this.dispatch("locale-changed");
    }
  }
  setLocaleTextFormatter(getLocaleText) {
    this.getLocaleText = getLocaleText;
    if (this.getLocaleText !== getLocaleText) {
      this.getLocaleText = getLocaleText;
      this.dispatch("locale-changed");
    }
  }
  t(key, variables = {}) {
    const { localeText = AG_CHARTS_LOCALE_EN_US, getLocaleText } = this;
    const defaultValue = localeText[key];
    return getLocaleText?.({ key, defaultValue, variables }) ?? defaultMessageFormatter({ key, defaultValue, variables }) ?? key;
  }
};
function clearContext({
  context,
  pixelRatio,
  width: width2,
  height: height2
}) {
  context.save();
  context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
  context.clearRect(0, 0, width2, height2);
  context.restore();
}
function debugContext(ctx) {
  if (Debug.check("canvas")) {
    const save = ctx.save.bind(ctx);
    const restore = ctx.restore.bind(ctx);
    let depth = 0;
    Object.assign(ctx, {
      save() {
        save();
        depth++;
      },
      restore() {
        if (depth === 0) {
          throw new Error("AG Charts - Unable to restore() past depth 0");
        }
        restore();
        depth--;
      },
      verifyDepthZero() {
        if (depth !== 0) {
          throw new Error(`AG Charts - Save/restore depth is non-zero: ${depth}`);
        }
      }
    });
  }
}
var HdpiCanvas = class {
  constructor(options) {
    this.enabled = true;
    this.width = 600;
    this.height = 300;
    const { width: width2, height: height2, pixelRatio, canvasElement, willReadFrequently = false } = options;
    this.pixelRatio = pixelRatio ?? getWindow("devicePixelRatio");
    this.element = canvasElement ?? createElement("canvas");
    this.element.style.display = "block";
    this.element.style.width = (width2 ?? this.width) + "px";
    this.element.style.height = (height2 ?? this.height) + "px";
    this.element.width = Math.round((width2 ?? this.width) * this.pixelRatio);
    this.element.height = Math.round((height2 ?? this.height) * this.pixelRatio);
    this.context = this.element.getContext("2d", { willReadFrequently });
    this.onEnabledChange();
    this.resize(width2 ?? 0, height2 ?? 0);
    debugContext(this.context);
  }
  drawImage(context, dx = 0, dy = 0) {
    return context.drawImage(this.context.canvas, dx, dy);
  }
  toDataURL(type) {
    return this.element.toDataURL(type);
  }
  resize(width2, height2) {
    if (!(width2 > 0 && height2 > 0))
      return;
    const { element: element2, context, pixelRatio } = this;
    element2.width = Math.round(width2 * pixelRatio);
    element2.height = Math.round(height2 * pixelRatio);
    context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
    element2.style.width = width2 + "px";
    element2.style.height = height2 + "px";
    this.width = width2;
    this.height = height2;
  }
  clear() {
    clearContext(this);
  }
  destroy() {
    this.element.remove();
    this.element.width = 0;
    this.element.height = 0;
    this.context.clearRect(0, 0, 0, 0);
    Object.freeze(this);
  }
  onEnabledChange() {
    if (this.element) {
      this.element.style.display = this.enabled ? "" : "none";
    }
  }
};
__decorateClass([
  ObserveChanges((target) => target.onEnabledChange())
], HdpiCanvas.prototype, "enabled", 2);
var HdpiOffscreenCanvas = class {
  constructor(options) {
    this.width = 600;
    this.height = 300;
    const { width: width2, height: height2, pixelRatio, willReadFrequently = false } = options;
    this.pixelRatio = pixelRatio ?? getWindow("devicePixelRatio");
    this.canvas = new OffscreenCanvas(width2 ?? this.width, height2 ?? this.height);
    this.context = this.canvas.getContext("2d", { willReadFrequently });
    this.resize(width2 ?? 0, height2 ?? 0);
    debugContext(this.context);
  }
  drawImage(context, dx = 0, dy = 0) {
    return context.drawImage(this.context.canvas, dx, dy);
  }
  resize(width2, height2) {
    if (!(width2 > 0 && height2 > 0))
      return;
    const { canvas, context, pixelRatio } = this;
    canvas.width = Math.round(width2 * pixelRatio);
    canvas.height = Math.round(height2 * pixelRatio);
    context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
    this.width = width2;
    this.height = height2;
  }
  clear() {
    clearContext(this);
  }
  destroy() {
    this.canvas.width = 0;
    this.canvas.height = 0;
    this.context.clearRect(0, 0, 0, 0);
    this.canvas = null;
    this.context = null;
    Object.freeze(this);
  }
};
var LayersManager = class {
  constructor(canvas) {
    this.canvas = canvas;
    this.debug = Debug.create(true, "scene");
    this.layersMap = /* @__PURE__ */ new Map();
    this.nextLayerId = 0;
  }
  get size() {
    return this.layersMap.size;
  }
  resize(width2, height2) {
    this.canvas.resize(width2, height2);
    this.layersMap.forEach(({ canvas }) => canvas.resize(width2, height2));
  }
  addLayer(opts) {
    const { width: width2, height: height2, pixelRatio } = this.canvas;
    const { name } = opts;
    const canvas = new HdpiOffscreenCanvas({ width: width2, height: height2, pixelRatio });
    this.layersMap.set(canvas, {
      id: this.nextLayerId++,
      name,
      canvas
    });
    this.debug("Scene.addLayer() - layers", this.layersMap);
    return canvas;
  }
  removeLayer(canvas) {
    if (this.layersMap.has(canvas)) {
      this.layersMap.delete(canvas);
      canvas.destroy();
      this.debug("Scene.removeLayer() -  layers", this.layersMap);
    }
  }
  clear() {
    for (const layer of this.layersMap.values()) {
      layer.canvas.destroy();
    }
    this.layersMap.clear();
  }
};
var _SpriteRenderer = class _SpriteRenderer2 {
  constructor() {
    this.offscreenCanvas = new OffscreenCanvas(1, 1);
    _SpriteRenderer2.offscreenCanvasCount++;
    const ctx = this.offscreenCanvas.getContext("2d");
    if (ctx == null)
      throw new TypeError(`AG Charts - invalid 2d context`);
    this.renderCtx = {
      ctx,
      devicePixelRatio: 1,
      resized: false,
      debugNodes: {}
    };
  }
  resize({ spritePixelRatio, spriteWidth, spriteHeight }) {
    this.offscreenCanvas.width = Math.max(spriteWidth, 0) * spritePixelRatio;
    this.offscreenCanvas.height = Math.max(spriteHeight, 0) * spritePixelRatio;
  }
  renderSprite(nodes, opts) {
    nodes = toIterable(nodes);
    const {
      renderCtx,
      renderCtx: { ctx },
      offscreenCanvas
    } = this;
    const { scale: scale2 = 1, translateX = 0, translateY = 0 } = opts ?? {};
    ctx.save();
    ctx.resetTransform();
    ctx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
    ctx.beginPath();
    ctx.setTransform(scale2, 0, 0, scale2, translateX, translateY);
    for (const node of nodes) {
      node.preRender();
      node.render(renderCtx);
    }
    ctx.closePath();
    ctx.restore();
    return offscreenCanvas.transferToImageBitmap();
  }
};
_SpriteRenderer.offscreenCanvasCount = 0;
var SpriteRenderer = _SpriteRenderer;
function formatBytes(value) {
  for (const unit of ["B", "KB", "MB", "GB"]) {
    if (value < 1536) {
      return `${value.toFixed(1)}${unit}`;
    }
    value /= 1024;
  }
  return `${value.toFixed(1)}TB}`;
}
function memoryUsage() {
  if (!("memory" in performance))
    return;
  const { totalJSHeapSize, usedJSHeapSize, jsHeapSizeLimit } = performance.memory;
  const result = [];
  for (const amount of [usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit]) {
    if (typeof amount !== "number")
      continue;
    result.push(formatBytes(amount));
  }
  return `Heap ${result.join(" / ")}`;
}
function debugStats(layersManager, debugSplitTimes, ctx, renderCtxStats, extraDebugStats = {}, seriesRect = BBox.zero) {
  if (!Debug.check(
    "scene:stats",
    "scene:stats:verbose"
    /* SCENE_STATS_VERBOSE */
  ))
    return;
  const {
    layersRendered = 0,
    layersSkipped = 0,
    nodesRendered = 0,
    nodesSkipped = 0,
    opsPerformed = 0,
    opsSkipped = 0
  } = renderCtxStats ?? {};
  const end2 = performance.now();
  const { start: start2, ...durations } = debugSplitTimes;
  const splits = Object.entries(durations).map(([n, t]) => {
    return time(n, t);
  }).filter((v) => v != null).join(" + ");
  const extras = Object.entries(extraDebugStats).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(" ; ");
  const detailedStats = Debug.check(
    "scene:stats:verbose"
    /* SCENE_STATS_VERBOSE */
  );
  const memUsage = memoryUsage();
  const stats = [
    `${time("\u23F1\uFE0F", start2, end2)} (${splits})`,
    `${extras}`,
    `Layers: ${detailedStats ? pct(layersRendered, layersSkipped) : layersManager.size}; Sprites: ${SpriteRenderer.offscreenCanvasCount}`,
    detailedStats ? `Nodes: ${pct(nodesRendered, nodesSkipped)}` : null,
    detailedStats ? `Ops: ${pct(opsPerformed, opsSkipped)}` : null,
    detailedStats && memUsage ? memUsage : null
  ].filter(isString);
  const measurer = new SimpleTextMeasurer((t) => ctx.measureText(t));
  const statsSize = new Map(stats.map((t) => [t, measurer.measureLines(t)]));
  const width2 = Math.max(...Array.from(statsSize.values(), (s) => s.width));
  const height2 = accumulate(statsSize.values(), (s) => s.height);
  const x = 2 + seriesRect.x;
  ctx.save();
  ctx.fillStyle = "white";
  ctx.fillRect(x, 0, width2, height2);
  ctx.fillStyle = "black";
  let y = 0;
  for (const [stat, size] of statsSize.entries()) {
    y += size.height;
    ctx.fillText(stat, x, y);
  }
  ctx.restore();
}
function prepareSceneNodeHighlight(ctx) {
  const config = toArray(getWindow("agChartsSceneDebug"));
  const result = [];
  for (const name of config) {
    if (name === "layout") {
      result.push("seriesRoot", "legend", "root", /.*Axis-\d+-axis.*/);
    } else {
      result.push(name);
    }
  }
  ctx.debugNodeSearch = result;
}
function debugSceneNodeHighlight(ctx, debugNodes) {
  ctx.save();
  for (const [name, node] of Object.entries(debugNodes)) {
    const bbox = Transformable.toCanvas(node);
    if (!bbox) {
      Logger.log(`Scene.render() - no bbox for debugged node [${name}].`);
      continue;
    }
    ctx.globalAlpha = 0.8;
    ctx.strokeStyle = "red";
    ctx.lineWidth = 1;
    ctx.strokeRect(bbox.x, bbox.y, bbox.width, bbox.height);
    ctx.fillStyle = "red";
    ctx.strokeStyle = "white";
    ctx.font = "16px sans-serif";
    ctx.textBaseline = "top";
    ctx.textAlign = "left";
    ctx.lineWidth = 2;
    ctx.strokeText(name, bbox.x, bbox.y, bbox.width);
    ctx.fillText(name, bbox.x, bbox.y, bbox.width);
  }
  ctx.restore();
}
var skippedProperties = /* @__PURE__ */ new Set();
var allowedProperties = /* @__PURE__ */ new Set([
  "gradient",
  // '_datum',
  "zIndex",
  "clipRect",
  "cachedBBox",
  "childNodeCounts",
  "path",
  "__zIndex",
  "name",
  "__scalingCenterX",
  "__scalingCenterY",
  "__rotationCenterX",
  "__rotationCenterY",
  "_previousDatum",
  "__fill",
  "__lineDash",
  "borderPath",
  "borderClipPath",
  "_clipPath"
]);
function nodeProps(node) {
  const { ...allProps } = node;
  for (const prop of Object.keys(allProps)) {
    if (allowedProperties.has(prop))
      continue;
    if (typeof allProps[prop] === "number")
      continue;
    if (typeof allProps[prop] === "string")
      continue;
    if (typeof allProps[prop] === "boolean")
      continue;
    skippedProperties.add(prop);
    delete allProps[prop];
  }
  return allProps;
}
function buildTree(node, mode) {
  if (!Debug.check(
    true,
    "scene"
    /* SCENE */
  )) {
    return {};
  }
  let order = 0;
  return {
    node: mode === "json" ? nodeProps(node) : node,
    name: node.name ?? node.id,
    dirty: node.dirty,
    ...Array.from(node.children(), (c) => buildTree(c, mode)).reduce(
      (result, childTree) => {
        let { name: treeNodeName } = childTree;
        const {
          node: { visible, opacity, zIndex, translationX, translationY, rotation, scalingX, scalingY },
          node: childNode
        } = childTree;
        if (!visible || opacity <= 0) {
          treeNodeName = `(${treeNodeName})`;
        }
        if (Group.is(childNode) && childNode.renderToOffscreenCanvas) {
          treeNodeName = `*${treeNodeName}*`;
        }
        const zIndexString = Array.isArray(zIndex) ? `(${zIndex.join(", ")})` : zIndex;
        const key = [
          `${(order++).toString().padStart(3, "0")}|`,
          `${treeNodeName ?? "<unknown>"}`,
          `z: ${zIndexString}`,
          translationX && `x: ${translationX}`,
          translationY && `y: ${translationY}`,
          rotation && `r: ${rotation}`,
          scalingX != null && scalingX !== 1 && `sx: ${scalingX}`,
          scalingY != null && scalingY !== 1 && `sy: ${scalingY}`
        ].filter((v) => !!v).join(" ");
        let selectedKey = key;
        let index = 1;
        while (result[selectedKey] != null && index < 100) {
          selectedKey = `${key} (${index++})`;
        }
        result[selectedKey] = childTree;
        return result;
      },
      {}
    )
  };
}
function buildDirtyTree(node) {
  if (!node.dirty) {
    return { dirtyTree: {}, paths: [] };
  }
  const childrenDirtyTree = Array.from(node.children(), (c) => buildDirtyTree(c)).filter((c) => c.paths.length > 0);
  const name = Group.is(node) ? node.name ?? node.id : node.id;
  const paths = childrenDirtyTree.length ? childrenDirtyTree.flatMap((c) => c.paths).map((p) => `${name}.${p}`) : [name];
  return {
    dirtyTree: {
      name,
      node,
      dirty: node.dirty,
      ...childrenDirtyTree.map((c) => c.dirtyTree).filter((t) => t.dirty != null).reduce((result, childTree) => {
        result[childTree.name ?? "<unknown>"] = childTree;
        return result;
      }, {})
    },
    paths
  };
}
function pct(rendered, skipped) {
  const total = rendered + skipped;
  return `${rendered} / ${total} (${Math.round(100 * rendered / total)}%)`;
}
function time(name, start2, end2) {
  const duration = end2 != null ? end2 - start2 : start2;
  return `${name}: ${Math.round(duration * 100) / 100}ms`;
}
function accumulate(iterator, mapper) {
  let sum2 = 0;
  for (const item of iterator) {
    sum2 += mapper(item);
  }
  return sum2;
}
var Scene = class {
  constructor(canvasOptions) {
    this.debug = Debug.create(
      true,
      "scene"
      /* SCENE */
    );
    this.id = createId(this);
    this.root = null;
    this.pendingSize = null;
    this.isDirty = false;
    this.canvas = new HdpiCanvas(canvasOptions);
    this.layersManager = new LayersManager(this.canvas);
  }
  get width() {
    return this.pendingSize?.[0] ?? this.canvas.width;
  }
  get height() {
    return this.pendingSize?.[1] ?? this.canvas.height;
  }
  /** @deprecated v10.2.0 Only used by AG Grid Sparklines */
  setContainer(value) {
    const { element: element2 } = this.canvas;
    element2.parentElement?.removeChild(element2);
    value.appendChild(element2);
    return this;
  }
  setRoot(node) {
    if (this.root === node) {
      return this;
    }
    this.isDirty = true;
    this.root?._setLayerManager();
    this.root = node;
    if (node) {
      node.visible = true;
      node._setLayerManager(this.layersManager);
    }
    return this;
  }
  clear() {
    this.canvas.clear();
  }
  attachNode(node) {
    this.appendChild(node);
    return () => this.removeChild(node);
  }
  appendChild(node) {
    this.root?.appendChild(node);
    return this;
  }
  removeChild(node) {
    this.root?.removeChild(node);
    return this;
  }
  download(fileName, fileFormat) {
    downloadUrl(this.canvas.toDataURL(fileFormat), fileName?.trim() ?? "image");
  }
  /** NOTE: Integrated Charts undocumented image download method. */
  getDataURL(fileFormat) {
    return this.canvas.toDataURL(fileFormat);
  }
  resize(width2, height2) {
    width2 = Math.round(width2);
    height2 = Math.round(height2);
    if (width2 > 0 && height2 > 0 && (width2 !== this.width || height2 !== this.height)) {
      this.pendingSize = [width2, height2];
      this.isDirty = true;
      return true;
    }
    return false;
  }
  render(opts) {
    const { debugSplitTimes = { start: performance.now() }, extraDebugStats, seriesRect } = opts ?? {};
    const { canvas, canvas: { context: ctx } = {}, root, pendingSize } = this;
    if (!ctx) {
      return;
    }
    const renderStartTime = performance.now();
    if (pendingSize) {
      this.layersManager.resize(...pendingSize);
      this.pendingSize = null;
    }
    if (root && !root.visible) {
      this.isDirty = false;
      return;
    }
    if (root?.dirty === false && !this.isDirty) {
      if (this.debug.check()) {
        this.debug("Scene.render() - no-op", {
          tree: buildTree(root, "console")
        });
      }
      debugStats(this.layersManager, debugSplitTimes, ctx, void 0, extraDebugStats, seriesRect);
      return;
    }
    const renderCtx = {
      ctx,
      devicePixelRatio: this.canvas.pixelRatio ?? 1,
      resized: Boolean(pendingSize),
      debugNodes: {}
    };
    if (Debug.check(
      "scene:stats:verbose"
      /* SCENE_STATS_VERBOSE */
    )) {
      renderCtx.stats = {
        layersRendered: 0,
        layersSkipped: 0,
        nodesRendered: 0,
        nodesSkipped: 0,
        opsPerformed: 0,
        opsSkipped: 0
      };
    }
    prepareSceneNodeHighlight(renderCtx);
    let canvasCleared = false;
    if (root?.dirty !== false) {
      canvasCleared = true;
      canvas.clear();
    }
    if (root && Debug.check(
      "scene:dirtyTree"
      /* SCENE_DIRTY_TREE */
    )) {
      const { dirtyTree, paths } = buildDirtyTree(root);
      Debug.create(
        "scene:dirtyTree"
        /* SCENE_DIRTY_TREE */
      )("Scene.render() - dirtyTree", { dirtyTree, paths });
    }
    if (root && canvasCleared) {
      if (root.visible) {
        root.preRender();
      }
      if (this.debug.check()) {
        const tree = buildTree(root, "console");
        this.debug("Scene.render() - before", {
          canvasCleared,
          tree
        });
      }
      if (root.visible) {
        ctx.save();
        root.render(renderCtx);
        ctx.restore();
      }
    }
    debugSplitTimes["\u270D\uFE0F"] = performance.now() - renderStartTime;
    ctx.verifyDepthZero?.();
    this.isDirty = false;
    debugStats(this.layersManager, debugSplitTimes, ctx, renderCtx.stats, extraDebugStats, seriesRect);
    debugSceneNodeHighlight(ctx, renderCtx.debugNodes);
    if (root && this.debug.check()) {
      this.debug("Scene.render() - after", {
        tree: buildTree(root, "console"),
        canvasCleared
      });
    }
  }
  toSVG() {
    const { root, width: width2, height: height2 } = this;
    if (root == null)
      return;
    return Node.toSVG(root, width2, height2);
  }
  /** Alternative to destroy() that preserves re-usable resources. */
  strip() {
    const { context, pixelRatio } = this.canvas;
    context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
    this.layersManager.clear();
    this.setRoot(null);
    this.isDirty = false;
  }
  destroy() {
    this.strip();
    this.canvas.destroy();
    Object.assign(this, { canvas: void 0 });
  }
};
Scene.className = "Scene";
var CallbackCache = class {
  constructor() {
    this.cache = /* @__PURE__ */ new WeakMap();
  }
  call(fn, ...params) {
    let serialisedParams;
    let paramCache = this.cache.get(fn);
    try {
      serialisedParams = JSON.stringify(params);
    } catch {
      return this.invoke(fn, params, paramCache);
    }
    if (paramCache == null) {
      paramCache = /* @__PURE__ */ new Map();
      this.cache.set(fn, paramCache);
    }
    if (!paramCache.has(serialisedParams)) {
      return this.invoke(fn, params, paramCache, serialisedParams);
    }
    return paramCache.get(serialisedParams);
  }
  invoke(fn, params, paramCache, serialisedParams) {
    try {
      const result = fn(...params);
      if (paramCache && serialisedParams != null) {
        paramCache.set(serialisedParams, result);
      }
      return result;
    } catch (e) {
      Logger.warnOnce(`User callback errored, ignoring`, e);
      return;
    }
  }
  invalidateCache() {
    this.cache = /* @__PURE__ */ new WeakMap();
  }
};
var AnnotationManager = class extends BaseManager {
  constructor(annotationRoot) {
    super();
    this.annotationRoot = annotationRoot;
    this.mementoOriginatorKey = "annotations";
    this.annotations = [];
  }
  createMemento() {
    return this.annotations;
  }
  guardMemento(blob) {
    return blob == null || isArray(blob);
  }
  restoreMemento(_version, _mementoVersion, memento) {
    this.annotations = this.cleanData(memento ?? []).map((annotation) => {
      const annotationTheme = this.getAnnotationTypeStyles(annotation.type);
      return mergeDefaults(annotation, annotationTheme);
    });
    this.listeners.dispatch("restore-annotations", {
      type: "restore-annotations",
      annotations: this.annotations
    });
  }
  updateData(annotations) {
    this.annotations = this.cleanData(annotations ?? []);
  }
  attachNode(node) {
    this.annotationRoot.append(node);
    return () => {
      this.annotationRoot?.removeChild(node);
      return this;
    };
  }
  setAnnotationStyles(styles) {
    this.styles = styles;
  }
  getAnnotationTypeStyles(type) {
    return this.styles?.[type];
  }
  cleanData(annotations) {
    for (const annotation of annotations) {
      if ("textAlign" in annotation)
        delete annotation.textAlign;
    }
    return annotations;
  }
};
var AxisManager = class {
  constructor(sceneRoot) {
    this.sceneRoot = sceneRoot;
    this.axes = /* @__PURE__ */ new Map();
    this.axisGridGroup = new Group({
      name: "Axes-Grids",
      zIndex: 1
      /* AXIS_GRID */
    });
    this.axisGroup = new Group({
      name: "Axes",
      zIndex: 2
      /* AXIS */
    });
    this.axisLabelGroup = new Group({
      name: "Axes-Labels",
      zIndex: 12
      /* SERIES_LABEL */
    });
    this.axisCrosslineRangeGroup = new Group({
      name: "Axes-Crosslines-Range",
      zIndex: 3
      /* SERIES_CROSSLINE_RANGE */
    });
    this.axisCrosslineLineGroup = new Group({
      name: "Axes-Crosslines-Line",
      zIndex: 7
      /* SERIES_CROSSLINE_LINE */
    });
    this.axisCrosslineLabelGroup = new Group({
      name: "Axes-Crosslines-Label",
      zIndex: 12
      /* SERIES_LABEL */
    });
    this.sceneRoot.appendChild(this.axisGroup);
    this.sceneRoot.appendChild(this.axisGridGroup);
    this.sceneRoot.appendChild(this.axisLabelGroup);
    this.sceneRoot.appendChild(this.axisCrosslineRangeGroup);
    this.sceneRoot.appendChild(this.axisCrosslineLineGroup);
    this.sceneRoot.appendChild(this.axisCrosslineLabelGroup);
  }
  updateAxes(oldAxes, newAxes) {
    const axisNodes = {
      axisNode: this.axisGroup,
      gridNode: this.axisGridGroup,
      labelNode: this.axisLabelGroup,
      crossLineRangeNode: this.axisCrosslineRangeGroup,
      crossLineLineNode: this.axisCrosslineLineGroup,
      crossLineLabelNode: this.axisCrosslineLabelGroup
    };
    for (const axis of oldAxes) {
      if (newAxes.includes(axis))
        continue;
      axis.detachAxis(axisNodes);
      axis.destroy();
    }
    for (const axis of newAxes) {
      if (oldAxes?.includes(axis))
        continue;
      axis.attachAxis(axisNodes);
    }
    this.axes.clear();
    for (const axis of newAxes) {
      const ctx = axis.createAxisContext();
      if (this.axes.has(ctx.direction)) {
        this.axes.get(ctx.direction)?.push(ctx);
      } else {
        this.axes.set(ctx.direction, [ctx]);
      }
    }
  }
  getAxisContext(direction) {
    return this.axes.get(direction) ?? [];
  }
  destroy() {
    this.axes.clear();
    this.sceneRoot.removeChild(this.axisGroup);
    this.sceneRoot.removeChild(this.axisGridGroup);
  }
};
var DataService = class extends Listeners {
  constructor(animationManager) {
    super();
    this.animationManager = animationManager;
    this.dispatchOnlyLatest = true;
    this.dispatchThrottle = 0;
    this.requestThrottle = 300;
    this.isLoadingInitialData = false;
    this.isLoadingData = false;
    this.freshRequests = [];
    this.requestCounter = 0;
    this.debug = Debug.create(true, "data-model", "data-source");
    this.throttledFetch = this.createThrottledFetch(this.requestThrottle);
    this.throttledDispatch = this.createThrottledDispatch(this.dispatchThrottle);
  }
  updateCallback(dataSourceCallback) {
    if (typeof dataSourceCallback !== "function")
      return;
    this.debug("DataService - updated data source callback");
    this.dataSourceCallback = dataSourceCallback;
    this.isLoadingInitialData = true;
    this.animationManager.skip();
    this.dispatch("data-source-change");
  }
  clearCallback() {
    this.dataSourceCallback = void 0;
  }
  load(params) {
    this.isLoadingData = true;
    this.throttledFetch(params);
  }
  isLazy() {
    return this.dataSourceCallback != null;
  }
  isLoading() {
    return this.isLazy() && (this.isLoadingInitialData || this.isLoadingData);
  }
  createThrottledFetch(requestThrottle) {
    return throttle(
      (params) => this.fetch(params).catch((e) => Logger.error("callback failed", e)),
      requestThrottle,
      {
        leading: false,
        trailing: true
      }
    );
  }
  createThrottledDispatch(dispatchThrottle) {
    return throttle(
      (id, data) => {
        this.debug(`DataService - dispatching 'data-load' | ${id}`);
        this.dispatch("data-load", { type: "data-load", data });
      },
      dispatchThrottle,
      {
        leading: true,
        trailing: true
      }
    );
  }
  async fetch(params) {
    if (!this.dataSourceCallback) {
      throw new Error("DataService - [dataSource.getData] callback not initialised");
    }
    const start2 = performance.now();
    const id = this.requestCounter++;
    this.debug(`DataService - requesting | ${id}`);
    this.freshRequests.push(id);
    let response;
    try {
      response = await this.dataSourceCallback(params);
      this.debug(`DataService - response | ${performance.now() - start2}ms | ${id}`);
    } catch (error) {
      this.debug(`DataService - request failed | ${id}`);
      Logger.errorOnce(`DataService - request failed | [${error}]`);
    }
    this.isLoadingInitialData = false;
    const requestIndex = this.freshRequests.findIndex((rid) => rid === id);
    if (requestIndex === -1 || this.dispatchOnlyLatest && requestIndex !== this.freshRequests.length - 1) {
      this.debug(`DataService - discarding stale request | ${id}`);
      return;
    }
    this.freshRequests = this.freshRequests.slice(requestIndex + 1);
    if (this.freshRequests.length === 0) {
      this.isLoadingData = false;
    }
    if (Array.isArray(response)) {
      this.throttledDispatch(id, response);
    } else {
      this.dispatch("data-error");
    }
  }
};
__decorateClass([
  ActionOnSet({
    newValue(dispatchThrottle) {
      this.throttledDispatch = this.createThrottledDispatch(dispatchThrottle);
    }
  })
], DataService.prototype, "dispatchThrottle", 2);
__decorateClass([
  ActionOnSet({
    newValue(requestThrottle) {
      this.throttledFetch = this.createThrottledFetch(requestThrottle);
    }
  })
], DataService.prototype, "requestThrottle", 2);
var AnimationBatch = class {
  constructor(maxAnimationTime) {
    this.maxAnimationTime = maxAnimationTime;
    this.debug = Debug.create(true, "animation");
    this.controllers = /* @__PURE__ */ new Map();
    this.stoppedCbs = /* @__PURE__ */ new Set();
    this.currentPhase = 0;
    this.phases = new Map(PHASE_ORDER.map((p) => [p, []]));
    this.skipAnimations = false;
    this.animationTimeConsumed = 0;
    this.isReady = false;
  }
  get size() {
    return this.controllers.size;
  }
  get consumedTimeMs() {
    return this.animationTimeConsumed;
  }
  isActive() {
    return this.controllers.size > 0;
  }
  getActiveControllers() {
    return this.phases.get(PHASE_ORDER[this.currentPhase]) ?? [];
  }
  checkOverlappingId(id) {
    if (id != null && this.controllers.has(id)) {
      this.controllers.get(id).stop();
      this.debug(`Skipping animation batch due to update of existing animation: ${id}`);
      this.skip();
    }
  }
  addAnimation(animation) {
    if (animation.isComplete)
      return;
    const animationPhaseIdx = PHASE_ORDER.indexOf(animation.phase);
    if (animationPhaseIdx < this.currentPhase) {
      this.debug(`Skipping animation due to being for an earlier phase`, animation.id);
      animation.stop();
      return;
    }
    this.controllers.set(animation.id, animation);
    this.phases.get(animation.phase)?.push(animation);
  }
  removeAnimation(animation) {
    this.controllers.delete(animation.id);
    const phase = this.phases.get(animation.phase);
    const index = phase?.indexOf(animation);
    if (index != null && index >= 0) {
      phase?.splice(index, 1);
    }
  }
  progress(deltaTime) {
    if (!this.isReady)
      return;
    let unusedTime = deltaTime === 0 ? 0.01 : deltaTime;
    const refresh = () => {
      const phase2 = PHASE_ORDER[this.currentPhase];
      return {
        phaseControllers: [...this.getActiveControllers()],
        phase: phase2,
        phaseMeta: PHASE_METADATA[phase2]
      };
    };
    let { phase, phaseControllers, phaseMeta } = refresh();
    const arePhasesComplete = () => PHASE_ORDER[this.currentPhase] == null;
    const progressPhase = () => {
      ({ phase, phaseControllers, phaseMeta } = refresh());
      while (!arePhasesComplete() && phaseControllers.length === 0) {
        this.currentPhase++;
        ({ phase, phaseControllers, phaseMeta } = refresh());
        this.debug(`AnimationBatch - phase changing to ${phase}`, { unusedTime }, phaseControllers);
      }
    };
    const total = this.controllers.size;
    this.debug(`AnimationBatch - ${deltaTime}ms; phase ${phase} with ${phaseControllers?.length} of ${total}`);
    do {
      const phaseDeltaTime = unusedTime;
      const skipPhase = phaseMeta.skipIfNoEarlierAnimations && this.animationTimeConsumed === 0;
      let completeCount = 0;
      for (const controller of phaseControllers) {
        if (skipPhase) {
          controller.stop();
        } else {
          unusedTime = Math.min(controller.update(phaseDeltaTime), unusedTime);
        }
        if (controller.isComplete) {
          completeCount++;
          this.removeAnimation(controller);
        }
      }
      this.animationTimeConsumed += phaseDeltaTime - unusedTime;
      this.debug(`AnimationBatch - updated ${phaseControllers.length} controllers; ${completeCount} completed`);
      this.debug(`AnimationBatch - animationTimeConsumed: ${this.animationTimeConsumed}`);
      progressPhase();
    } while (unusedTime > 0 && !arePhasesComplete());
    if (this.animationTimeConsumed > this.maxAnimationTime) {
      this.debug(`Animation batch exceeded max animation time, skipping`, [...this.controllers]);
      this.stop();
    }
  }
  ready() {
    if (this.isReady)
      return;
    this.isReady = true;
    this.debug(`AnimationBatch - ready; skipped: ${this.skipAnimations}`, [...this.controllers]);
    let skipAll = true;
    for (const [, controller] of this.controllers) {
      if (controller.duration > 0 && PHASE_METADATA[controller.phase].skipIfNoEarlierAnimations !== true) {
        skipAll = false;
        break;
      }
    }
    if (!skipAll) {
      for (const [, controller] of this.controllers) {
        if (controller.autoplay) {
          controller.play(true);
        }
      }
    }
  }
  skip(skip = true) {
    if (this.skipAnimations === false && skip === true) {
      for (const controller of this.controllers.values()) {
        controller.stop();
      }
      this.controllers.clear();
    }
    this.skipAnimations = skip;
  }
  play() {
    for (const controller of this.controllers.values()) {
      controller.play();
    }
  }
  pause() {
    for (const controller of this.controllers.values()) {
      controller.pause();
    }
  }
  stop() {
    for (const controller of this.controllers.values()) {
      try {
        controller.stop();
        this.removeAnimation(controller);
      } catch (error) {
        Logger.error("Error during animation stop", error);
      }
    }
    this.dispatchStopped();
  }
  stopByAnimationId(id) {
    if (id != null && this.controllers.has(id)) {
      const controller = this.controllers.get(id);
      if (controller) {
        controller.stop();
        this.removeAnimation(controller);
      }
    }
  }
  stopByAnimationGroupId(id) {
    for (const controller of this.controllers.values()) {
      if (controller.groupId === id) {
        this.stopByAnimationId(controller.id);
      }
    }
  }
  dispatchStopped() {
    this.stoppedCbs.forEach((cb) => cb());
    this.stoppedCbs.clear();
  }
  isSkipped() {
    return this.skipAnimations;
  }
  destroy() {
    this.stop();
    this.controllers.clear();
  }
};
function buildPreventable(obj) {
  const self = {
    ...obj,
    preventDefault() {
      self.sourceEvent?.preventDefault();
    }
  };
  return self;
}
function dispatchTypedEvent(listeners, event) {
  listeners.dispatchWrapHandlers(event.type, (handler, e) => handler(e), buildPreventable(event));
}
var POINTER_INTERACTION_TYPES = [
  "click",
  "dblclick",
  "contextmenu",
  "hover",
  "leave",
  "enter",
  "page-left",
  "wheel"
];
var KEY_INTERACTION_TYPES = ["keydown", "keyup"];
var SHADOW_DOM_HANDLERS = ["mousemove", "mouseup"];
var WINDOW_EVENT_HANDLERS = ["pagehide", "mousemove", "mouseup"];
var EVENT_HANDLERS = [
  "click",
  "dblclick",
  "contextmenu",
  "mousedown",
  "mouseleave",
  "mouseenter",
  "touchstart",
  "touchmove",
  "touchend",
  "touchcancel",
  "wheel",
  "keydown",
  "keyup"
];
function isPointerEvent(type) {
  return POINTER_INTERACTION_TYPES.includes(type);
}
function isKeyEvent(type) {
  return KEY_INTERACTION_TYPES.includes(type);
}
var _InteractionManager = class _InteractionManager2 extends InteractionStateListener {
  constructor(keyboardOptions, domManager) {
    super();
    this.keyboardOptions = keyboardOptions;
    this.domManager = domManager;
    this.debug = Debug.create(true, "interaction");
    this.eventHandler = (event) => this.processEvent(event);
    this.clickHistory = [{ offsetX: NaN, offsetY: NaN, type: "mousedown" }];
    this.dblclickHistory = [
      { offsetX: NaN, offsetY: NaN, type: "mousedown" },
      { offsetX: NaN, offsetY: NaN, type: "mouseup" },
      { offsetX: NaN, offsetY: NaN, type: "mousedown" }
    ];
    this.stateQueue = 32 | 2;
    this.rootElement = this.domManager.getShadowDocumentRoot();
    for (const type of EVENT_HANDLERS) {
      if (type.startsWith("touch") || type === "wheel") {
        this.domManager.addEventListener(type, this.eventHandler, { passive: false });
      } else {
        this.domManager.addEventListener(type, this.eventHandler);
      }
    }
    for (const type of WINDOW_EVENT_HANDLERS) {
      getWindow().addEventListener(type, this.eventHandler);
    }
    this.containerChanged(true);
    this.domManager.addListener("container-changed", () => this.containerChanged());
  }
  containerChanged(force = false) {
    const newRoot = this.domManager.getShadowDocumentRoot();
    if (!force && newRoot === this.rootElement)
      return;
    for (const type of SHADOW_DOM_HANDLERS) {
      this.rootElement?.removeEventListener(type, this.eventHandler);
    }
    this.rootElement = newRoot;
    this.debug("[InteractionManager] Switching rootElement to:", this.rootElement);
    for (const type of SHADOW_DOM_HANDLERS) {
      this.rootElement?.addEventListener(type, this.eventHandler);
    }
  }
  destroy() {
    super.destroy();
    for (const type of WINDOW_EVENT_HANDLERS) {
      getWindow().removeEventListener(type, this.eventHandler);
    }
    for (const type of SHADOW_DOM_HANDLERS) {
      this.rootElement?.removeEventListener(type, this.eventHandler);
    }
    for (const type of EVENT_HANDLERS) {
      this.domManager.removeEventListener(type, this.eventHandler);
    }
    this.domManager.removeStyles("interactionManager");
  }
  pushState(state) {
    this.stateQueue |= state;
  }
  popState(state) {
    this.stateQueue &= ~state;
  }
  getState() {
    return this.stateQueue & -this.stateQueue;
  }
  processEvent(event) {
    this.debug("Received raw event", event);
    let types = this.decideInteractionEventTypes(event);
    if (types != null && !Array.isArray(types)) {
      types = [types];
    }
    for (const type of types ?? []) {
      this.dispatchEvent(event, type);
    }
  }
  dispatchEvent(event, type) {
    if (isPointerEvent(type)) {
      this.dispatchPointerEvent(event, type);
      return;
    }
    const { relatedElement, targetElement } = this.extractElements(event);
    if (isKeyEvent(type)) {
      const sourceEvent = event;
      this.dispatchTypedEvent(this.listeners, { type, sourceEvent, relatedElement, targetElement });
    }
  }
  dispatchTypedEvent(listeners, event) {
    const preventableEvent = buildPreventable(event);
    this.debug("Dispatching typed event", preventableEvent, this.getState());
    listeners.dispatchWrapHandlers(event.type, (handler, e) => handler(e), preventableEvent);
  }
  extractElements(event) {
    let relatedElement;
    let targetElement;
    if ("relatedTarget" in event && event["relatedTarget"] instanceof HTMLElement) {
      relatedElement = event["relatedTarget"];
    }
    if ("target" in event && event["target"] instanceof HTMLElement) {
      targetElement = event["target"];
    }
    return { relatedElement, targetElement };
  }
  dispatchPointerEvent(event, type) {
    const coords = this.calculateCoordinates(event);
    if (coords == null)
      return;
    const pointerEvent = this.buildPointerEvent({ type, event, ...coords });
    this.debug("Dispatching pointer event", pointerEvent, this.getState());
    dispatchTypedEvent(this.listeners, pointerEvent);
  }
  getEventHTMLTarget(event) {
    if (event.target instanceof HTMLElement) {
      return event.target;
    } else if (event.currentTarget instanceof HTMLElement) {
      return event.currentTarget;
    }
    return void 0;
  }
  recordDown(event) {
    if (event instanceof MouseEvent) {
      partialAssign(["offsetX", "offsetY"], this.clickHistory[0], event);
      partialAssign(["offsetX", "offsetY"], this.dblclickHistory[2], this.dblclickHistory[0]);
      partialAssign(["offsetX", "offsetY"], this.dblclickHistory[0], event);
    }
  }
  recordUp(event) {
    if (event instanceof MouseEvent) {
      partialAssign(["offsetX", "offsetY"], this.dblclickHistory[1], event);
    }
  }
  decideInteractionEventTypes(event) {
    switch (event.type) {
      case "keydown":
      case "keyup":
        return this.keyboardOptions.enabled ? event.type : void 0;
      case "click":
      case "dblclick":
        return event.type;
      case "contextmenu":
      case "wheel":
        return event.type;
      case "touchstart":
      case "mousedown":
        if (!this.isEventOverElement(event)) {
          return;
        }
        this.recordDown(event);
        return;
      case "touchmove":
      case "mousemove":
        if (!this.isEventOverElement(event)) {
          return;
        }
        return "hover";
      case "mouseup":
      case "touchend":
        if (!this.isEventOverElement(event)) {
          return;
        }
        this.recordUp(event);
        return;
      case "mouseleave":
      case "touchcancel":
        return "leave";
      case "mouseenter":
        return "enter";
      case "pagehide":
        return "page-left";
    }
  }
  isEventOverElement(event) {
    return event.target instanceof HTMLElement && this.domManager.contains(event.target);
  }
  calculateCoordinates(event) {
    if (event instanceof MouseEvent) {
      return this.getMouseEventCoords(event);
    } else if (typeof TouchEvent !== "undefined" && event instanceof TouchEvent) {
      const lastTouch = event.touches[0] ?? event.changedTouches[0];
      const { clientX, clientY, pageX, pageY } = lastTouch;
      return { ..._InteractionManager2.NULL_COORDS, clientX, clientY, pageX, pageY };
    } else if (event instanceof PageTransitionEvent) {
      if (event.persisted) {
        return;
      }
      return _InteractionManager2.NULL_COORDS;
    }
  }
  getMouseEventCoords(event) {
    const { clientX, clientY, pageX, pageY } = event;
    let { offsetX, offsetY } = event;
    const target = this.getEventHTMLTarget(event);
    const { x = 0, y = 0 } = target ? this.domManager.calculateCanvasPosition(target) : {};
    offsetX += x;
    offsetY += y;
    return { clientX, clientY, pageX, pageY, offsetX, offsetY };
  }
  static isWheelEvent(event) {
    return event.type === "wheel";
  }
  static getWheelDeltas(event) {
    let [deltaX, deltaY] = [NaN, NaN];
    if (this.isWheelEvent(event)) {
      const factor = event.deltaMode === 0 ? 0.01 : 1;
      deltaX = event.deltaX * factor;
      deltaY = event.deltaY * factor;
    }
    return { deltaX, deltaY };
  }
  buildPointerEvent(opts) {
    const { type, event, clientX, clientY } = opts;
    let { offsetX, offsetY, pageX, pageY } = opts;
    if (!isFiniteNumber(offsetX) || !isFiniteNumber(offsetY)) {
      const rect = this.domManager.getBoundingClientRect();
      offsetX = clientX - rect.left;
      offsetY = clientY - rect.top;
    }
    if (!isFiniteNumber(pageX) || !isFiniteNumber(pageY)) {
      const pageRect = this.rootElement?.getBoundingClientRect();
      pageX = clientX - (pageRect?.left ?? 0);
      pageY = clientY - (pageRect?.top ?? 0);
    }
    const { deltaX, deltaY } = _InteractionManager2.getWheelDeltas(event);
    let pointerHistory = [];
    if (event.type === "click") {
      pointerHistory = this.clickHistory;
    } else if (event.type === "dblclick") {
      pointerHistory = this.dblclickHistory;
    }
    const { relatedElement, targetElement } = this.extractElements(event);
    const button = "button" in event ? Number(event.button) : 0;
    const builtEvent = {
      type,
      offsetX,
      offsetY,
      pageX,
      pageY,
      deltaX,
      deltaY,
      button,
      pointerHistory,
      sourceEvent: event,
      relatedElement,
      targetElement
    };
    this.debug("InteractionManager - builtEvent: ", builtEvent, this.getState());
    return builtEvent;
  }
};
_InteractionManager.NULL_COORDS = {
  clientX: -Infinity,
  clientY: -Infinity,
  pageX: -Infinity,
  pageY: -Infinity,
  offsetX: -Infinity,
  offsetY: -Infinity
};
var InteractionManager = _InteractionManager;
function validAnimationDuration(testee) {
  if (testee == null)
    return true;
  return !isNaN(testee) && testee >= 0 && testee <= 2;
}
var AnimationManager = class {
  constructor(interactionManager, chartUpdateMutex) {
    this.interactionManager = interactionManager;
    this.chartUpdateMutex = chartUpdateMutex;
    this.defaultDuration = 1e3;
    this.batch = new AnimationBatch(this.defaultDuration * 1.5);
    this.debug = Debug.create(true, "animation");
    this.events = new EventEmitter();
    this.rafAvailable = typeof requestAnimationFrame !== "undefined";
    this.isPlaying = true;
    this.requestId = null;
    this.skipAnimations = true;
    this.currentAnonymousAnimationId = 0;
  }
  addListener(eventName, listener) {
    return this.events.on(eventName, listener);
  }
  /**
   * Create an animation to tween a value between the `from` and `to` properties. If an animation already exists
   * with the same `id`, immediately stop it.
   */
  animate(opts) {
    const batch = this.batch;
    try {
      batch.checkOverlappingId(opts.id);
    } catch (error) {
      this.failsafeOnError(error);
      return;
    }
    let { id } = opts;
    if (id == null) {
      id = `__${this.currentAnonymousAnimationId}`;
      this.currentAnonymousAnimationId += 1;
    }
    const skip = this.isSkipped() || opts.phase === "none";
    if (skip) {
      this.debug("AnimationManager - skipping animation");
    }
    const { delay, duration } = opts;
    if (!validAnimationDuration(delay)) {
      throw new Error(`Animation delay of ${delay} is unsupported (${id})`);
    }
    if (!validAnimationDuration(duration)) {
      throw new Error(`Animation duration of ${duration} is unsupported (${id})`);
    }
    const animation = new Animation({
      ...opts,
      id,
      skip,
      autoplay: this.isPlaying ? opts.autoplay : false,
      phase: opts.phase,
      defaultDuration: this.defaultDuration
    });
    if (this.forceTimeJump(animation, this.defaultDuration)) {
      return;
    }
    this.batch.addAnimation(animation);
    return animation;
  }
  play() {
    if (this.isPlaying) {
      return;
    }
    this.isPlaying = true;
    this.debug("AnimationManager.play()");
    try {
      this.batch.play();
    } catch (error) {
      this.failsafeOnError(error);
    }
    this.requestAnimation();
  }
  pause() {
    if (!this.isPlaying) {
      return;
    }
    this.isPlaying = false;
    this.cancelAnimation();
    this.debug("AnimationManager.pause()");
    try {
      this.batch.pause();
    } catch (error) {
      this.failsafeOnError(error);
    }
  }
  stop() {
    this.isPlaying = false;
    this.cancelAnimation();
    this.debug("AnimationManager.stop()");
    this.batch.stop();
  }
  stopByAnimationId(id) {
    try {
      this.batch.stopByAnimationId(id);
    } catch (error) {
      this.failsafeOnError(error);
    }
  }
  stopByAnimationGroupId(id) {
    try {
      this.batch.stopByAnimationGroupId(id);
    } catch (error) {
      this.failsafeOnError(error);
    }
  }
  reset() {
    if (this.isPlaying) {
      this.stop();
      this.play();
    } else {
      this.stop();
    }
  }
  skip(skip = true) {
    this.skipAnimations = skip;
  }
  isSkipped() {
    return !this.rafAvailable || this.skipAnimations || this.batch.isSkipped();
  }
  isActive() {
    return this.isPlaying && this.batch.isActive();
  }
  skipCurrentBatch() {
    if (this.debug.check()) {
      this.debug(`AnimationManager - skipCurrentBatch()`, { stack: new Error().stack });
    }
    this.batch.skip();
  }
  /** Mocking point for tests to guarantee that animation updates happen. */
  isSkippingFrames() {
    return true;
  }
  /** Mocking point for tests to capture requestAnimationFrame callbacks. */
  scheduleAnimationFrame(cb) {
    this.requestId = getWindow().requestAnimationFrame((t) => {
      cb(t).catch((e) => Logger.error(e));
    });
  }
  /** Mocking point for tests to skip animations to a specific point in time. */
  forceTimeJump(_animation, _defaultDuration) {
    return false;
  }
  requestAnimation() {
    if (!this.rafAvailable)
      return;
    if (!this.batch.isActive() || this.requestId !== null)
      return;
    let prevTime;
    const onAnimationFrame = async (time2) => {
      const executeAnimationFrame = () => {
        const deltaTime = time2 - (prevTime ?? time2);
        prevTime = time2;
        this.debug("AnimationManager - onAnimationFrame()", {
          controllersCount: this.batch.size,
          deltaTime
        });
        this.interactionManager.pushState(
          2
          /* Animation */
        );
        try {
          this.batch.progress(deltaTime);
        } catch (error) {
          this.failsafeOnError(error);
        }
        this.events.emit("animation-frame", {
          type: "animation-frame",
          deltaMs: deltaTime
        });
      };
      if (this.isSkippingFrames()) {
        await this.chartUpdateMutex.acquireImmediately(executeAnimationFrame);
      } else {
        await this.chartUpdateMutex.acquire(executeAnimationFrame);
      }
      if (this.batch.isActive()) {
        this.scheduleAnimationFrame(onAnimationFrame);
      } else {
        this.batch.stop();
        this.events.emit("animation-stop", {
          type: "animation-stop",
          deltaMs: this.batch.consumedTimeMs
        });
      }
    };
    this.events.emit("animation-start", {
      type: "animation-start",
      deltaMs: 0
    });
    this.scheduleAnimationFrame(onAnimationFrame);
  }
  cancelAnimation() {
    if (this.requestId === null)
      return;
    cancelAnimationFrame(this.requestId);
    this.requestId = null;
    this.startBatch();
  }
  failsafeOnError(error, cancelAnimation = true) {
    Logger.error("Error during animation, skipping animations", error);
    if (cancelAnimation) {
      this.cancelAnimation();
    }
  }
  startBatch(skipAnimations) {
    this.debug(`AnimationManager - startBatch() with skipAnimations=${skipAnimations}.`);
    this.reset();
    this.batch.destroy();
    this.batch = new AnimationBatch(this.defaultDuration * 1.5);
    if (skipAnimations === true) {
      this.batch.skip();
    }
  }
  endBatch() {
    if (this.batch.isActive()) {
      this.batch.ready();
      this.requestAnimation();
    } else {
      this.interactionManager.popState(
        2
        /* Animation */
      );
      if (this.batch.isSkipped()) {
        this.batch.skip(false);
      }
    }
  }
  onBatchStop(cb) {
    this.batch.stoppedCbs.add(cb);
  }
  destroy() {
    this.stop();
    this.events.clear();
  }
};
var ChartEventManager = class extends BaseManager {
  legendItemClick(legendType, series, itemId, enabled, legendItemName) {
    const event = {
      type: "legend-item-click",
      legendType,
      series,
      itemId,
      enabled,
      legendItemName
    };
    this.listeners.dispatch("legend-item-click", event);
  }
  legendItemDoubleClick(legendType, series, itemId, enabled, numVisibleItems, legendItemName) {
    const event = {
      type: "legend-item-double-click",
      legendType,
      series,
      itemId,
      enabled,
      legendItemName,
      numVisibleItems
    };
    this.listeners.dispatch("legend-item-double-click", event);
  }
  axisHover(axisId, direction) {
    const event = {
      type: "axis-hover",
      axisId,
      direction
    };
    this.listeners.dispatch("axis-hover", event);
  }
};
var ContextMenuRegistry = class {
  constructor() {
    this.defaultActions = [];
    this.disabledActions = /* @__PURE__ */ new Set();
    this.hiddenActions = /* @__PURE__ */ new Set();
    this.listeners = new Listeners();
  }
  static check(type, event) {
    return event.type === type;
  }
  static checkCallback(desiredType, type, _callback) {
    return desiredType === type;
  }
  dispatchContext(type, pointerEvent, context, position) {
    const { sourceEvent } = pointerEvent;
    const x = position?.x ?? pointerEvent.canvasX;
    const y = position?.y ?? pointerEvent.canvasY;
    sourceEvent.stopPropagation();
    this.listeners.dispatch("", buildPreventable({ type, x, y, context, sourceEvent }));
  }
  addListener(handler) {
    return this.listeners.addListener("", handler);
  }
  filterActions(type) {
    return this.defaultActions.filter((action) => {
      return action.id && !this.hiddenActions.has(action.id) && ["all", type].includes(action.type);
    });
  }
  registerDefaultAction(action) {
    const didAdd = action.id != null && !this.defaultActions.some(({ id }) => id === action.id);
    if (didAdd) {
      this.defaultActions.push(action);
    }
    return () => {
      const index = didAdd ? this.defaultActions.findIndex(({ id }) => id === action.id) : -1;
      if (index !== -1) {
        this.defaultActions.splice(index, 1);
      }
    };
  }
  enableAction(actionId) {
    this.disabledActions.delete(actionId);
  }
  disableAction(actionId) {
    this.disabledActions.add(actionId);
  }
  showAction(actionId) {
    this.hiddenActions.add(actionId);
  }
  hideAction(actionId) {
    this.hiddenActions.delete(actionId);
  }
  isDisabled(actionId) {
    return this.disabledActions.has(actionId);
  }
};
var StateTracker = class extends Map {
  constructor(defaultValue, defaultState) {
    super();
    this.defaultValue = defaultValue;
    this.defaultState = defaultState;
  }
  set(key, value) {
    this.delete(key);
    if (typeof value !== "undefined") {
      super.set(key, value);
    }
    return this;
  }
  stateId() {
    return Array.from(this.keys()).pop() ?? this.defaultState;
  }
  stateValue() {
    return Array.from(this.values()).pop() ?? this.defaultValue;
  }
};
var Cursor = /* @__PURE__ */ ((Cursor2) => {
  Cursor2["Auto"] = "auto";
  Cursor2["Default"] = "default";
  Cursor2["Grab"] = "grab";
  Cursor2["Grabbing"] = "grabbing";
  Cursor2["Move"] = "move";
  Cursor2["NotAllowed"] = "not-allowed";
  Cursor2["Pointer"] = "pointer";
  Cursor2["EWResize"] = "ew-resize";
  Cursor2["NSResize"] = "ns-resize";
  Cursor2["ZoomIn"] = "zoom-in";
  Cursor2["ZoomOut"] = "zoom-out";
  return Cursor2;
})(Cursor || {});
var CursorManager = class {
  constructor(domManager) {
    this.domManager = domManager;
    this.stateTracker = new StateTracker("default");
  }
  updateCursor(callerId, style) {
    this.stateTracker.set(callerId, style);
    this.domManager.updateCursor(this.stateTracker.stateValue());
  }
  getCursor() {
    return this.domManager.getCursor();
  }
};
function distanceSquared(finger1, finger2) {
  const dx = finger1.screenX - finger2.screenX;
  const dy = finger1.screenY - finger2.screenY;
  return dx * dx + dy * dy;
}
function distance(finger1, finger2) {
  return Math.sqrt(distanceSquared(finger1, finger2));
}
var MIN_DISTANCE_TO_START_PINCH = 1;
var GestureDetector = class extends BaseManager {
  constructor(domManager) {
    super();
    this.domManager = domManager;
    this.touchstart = (event) => this.onTouchStart(event);
    this.touchmove = (event) => this.onTouchMove(event);
    this.touchend = (event) => this.onTouchEnd(event);
    this.touchcancel = (event) => this.onTouchCancel(event);
    this.pinch = {
      finger1: { identifier: NaN, screenX: NaN, screenY: NaN },
      finger2: { identifier: NaN, screenX: NaN, screenY: NaN },
      origin: { x: NaN, y: NaN },
      distance: NaN,
      status: 0
      /* Off */
    };
    this.domManager.addEventListener("touchstart", this.touchstart, { passive: true });
    this.domManager.addEventListener("touchmove", this.touchmove, { passive: false });
    this.domManager.addEventListener("touchend", this.touchend);
    this.domManager.addEventListener("touchcancel", this.touchcancel);
  }
  destroy() {
    this.domManager.removeEventListener("touchstart", this.touchstart);
    this.domManager.removeEventListener("touchmove", this.touchmove);
    this.domManager.removeEventListener("touchend", this.touchend);
    this.domManager.removeEventListener("touchcancel", this.touchcancel);
  }
  findPinchTouches(moveEvent) {
    const { touches } = moveEvent;
    const { finger1, finger2 } = this.pinch;
    if (this.pinch.status !== 0 && touches.length === 2) {
      if (touches[0].identifier === finger1.identifier && touches[1].identifier === finger2.identifier) {
        return [touches[0], touches[1]];
      }
      if (touches[0].identifier === finger2.identifier && touches[1].identifier === finger1.identifier) {
        return [touches[1], touches[0]];
      }
    }
  }
  copyTouchData(event) {
    const keys = ["identifier", "screenX", "screenY"];
    partialAssign(keys, this.pinch.finger1, event.touches[0]);
    partialAssign(keys, this.pinch.finger2, event.touches[1]);
    this.pinch.distance = distance(this.pinch.finger1, this.pinch.finger2);
  }
  dispatchPinchEvent(type, deltaDistance, sourceEvent) {
    const { finger1, finger2, origin: origin3 } = this.pinch;
    this.listeners.dispatch(type, buildPreventable({ sourceEvent, type, finger1, finger2, deltaDistance, origin: origin3 }));
  }
  onTouchStart(event) {
    this.stopPinchTracking(event);
    const { pinch } = this;
    if (event.touches.length === 2) {
      pinch.status = 1;
      this.copyTouchData(event);
      pinch.origin.x = (event.touches[0].clientX + event.touches[1].clientX) / 2;
      pinch.origin.y = (event.touches[0].clientY + event.touches[1].clientY) / 2;
    }
  }
  onTouchMove(event) {
    const pinchTouches = this.findPinchTouches(event);
    if (pinchTouches !== void 0) {
      const [touch1, touch2] = pinchTouches;
      const { pinch } = this;
      const newDistance = distance(touch1, touch2);
      const deltaDistance = newDistance - pinch.distance;
      if (pinch.status === 1) {
        if (Math.abs(deltaDistance) > MIN_DISTANCE_TO_START_PINCH) {
          pinch.status = 2;
          this.copyTouchData(event);
          this.dispatchPinchEvent("pinch-start", 0, event);
        }
      } else if (pinch.status === 2) {
        pinch.distance = newDistance;
        this.copyTouchData(event);
        this.dispatchPinchEvent("pinch-move", deltaDistance, event);
      } else {
        Logger.error(`unexpected pinch.status: ${pinch.status}`);
      }
    }
  }
  onTouchEnd(event) {
    this.stopPinchTracking(event);
  }
  onTouchCancel(event) {
    this.stopPinchTracking(event);
  }
  stopPinchTracking(event) {
    const { pinch } = this;
    if (pinch.status === 2) {
      this.dispatchPinchEvent("pinch-end", 0, event);
    }
    this.pinch.status = 0;
  }
};
var HighlightManager = class extends BaseManager {
  constructor() {
    super(...arguments);
    this.highlightStates = new StateTracker();
  }
  updateHighlight(callerId, highlightedDatum) {
    const { activeHighlight: previousHighlight } = this;
    this.highlightStates.set(callerId, highlightedDatum);
    this.activeHighlight = this.highlightStates.stateValue();
    if (!this.isEqual(this.activeHighlight, previousHighlight)) {
      this.listeners.dispatch("highlight-change", {
        type: "highlight-change",
        currentHighlight: this.activeHighlight,
        previousHighlight,
        callerId
      });
    }
  }
  getActiveHighlight() {
    return this.activeHighlight;
  }
  isEqual(a, b) {
    return a === b || a != null && b != null && a?.series === b?.series && a?.itemId === b?.itemId && a?.datum === b?.datum;
  }
};
var KeyNavManager = class extends InteractionStateListener {
  constructor(interactionManager, regionManager) {
    super();
    this.interactionManager = interactionManager;
    this.previousInputDevice = "keyboard";
    const series = regionManager.getRegion("series");
    const mouseStates = 32 | 8 | 1;
    this.destroyFns.push(
      interactionManager.addListener("click", () => this.onClick(), mouseStates),
      interactionManager.addListener("hover", () => this.onMouse(), mouseStates),
      interactionManager.addListener("wheel", () => this.onClick(), mouseStates),
      interactionManager.addListener(
        "keydown",
        (e) => this.onKeyDown(e),
        63
        /* All */
      ),
      series.addListener("drag-start", () => this.onClick(), mouseStates)
    );
  }
  getState() {
    return this.interactionManager.getState();
  }
  destroy() {
    super.destroy();
  }
  onClick() {
    this.focusIndicator?.overrideFocusVisible(false);
    this.previousInputDevice = "mouse";
  }
  onMouse() {
    this.previousInputDevice = "mouse";
  }
  onKeyDown(event) {
    const state = this.getState();
    const { key, code, altKey, shiftKey, metaKey, ctrlKey } = event.sourceEvent;
    if (ctrlKey || metaKey) {
      if (key === "y" || key === "z" && shiftKey) {
        this.focusIndicator?.overrideFocusVisible(this.previousInputDevice === "keyboard");
        return this.dispatch("redo", 0, event);
      } else if (key === "z") {
        this.focusIndicator?.overrideFocusVisible(this.previousInputDevice === "keyboard");
        return this.dispatch("undo", 0, event);
      }
    }
    if (state & (8 | 1)) {
      this.focusIndicator?.overrideFocusVisible(false);
      return;
    }
    switch (key) {
      case "+":
        return this.dispatch("nav-zoom", 1, event);
      case "-":
        return this.dispatch("nav-zoom", -1, event);
    }
    if (altKey || shiftKey || metaKey || ctrlKey)
      return;
    this.focusIndicator?.overrideFocusVisible(true);
    switch (code) {
      case "ArrowDown":
        return this.dispatch("nav-vert", 1, event);
      case "ArrowUp":
        return this.dispatch("nav-vert", -1, event);
      case "ArrowLeft":
        return this.dispatch("nav-hori", -1, event);
      case "ArrowRight":
        return this.dispatch("nav-hori", 1, event);
      case "ZoomIn":
      case "Add":
        return this.dispatch("nav-zoom", 1, event);
      case "ZoomOut":
      case "Substract":
        return this.dispatch("nav-zoom", -1, event);
      case "Space":
      case "Enter":
        return this.dispatch("submit", 0, event);
    }
  }
  dispatch(type, delta4, sourceEvent) {
    const { previousInputDevice } = this;
    dispatchTypedEvent(this.listeners, { type, delta: delta4, sourceEvent, previousInputDevice });
    const sharedKbmTypes = ["redo", "undo", "nav-zoom"];
    if (sourceEvent.type === "keydown" && !sharedKbmTypes.includes(type)) {
      this.previousInputDevice = "keyboard";
    }
  }
};
var RegionListeners = class extends Listeners {
};
var DRAG_THRESHOLD_MS = 300;
var DRAG_THRESHOLD_PX = 3;
function addHandler(listeners, interactionManager, type, handler, triggeringStates = 32) {
  return listeners?.addListener(type, (e) => {
    const currentState = interactionManager.getState();
    if (currentState & triggeringStates) {
      handler(e);
    }
  }) ?? (() => {
  });
}
function getTooltipContainer(target) {
  if (target == null || !(target instanceof HTMLElement))
    return void 0;
  let current = target;
  while (current != null && !current?.classList.contains("ag-charts-wrapper")) {
    if (current.classList.contains("ag-charts-tooltip")) {
      return current;
    }
    current = current.parentElement;
  }
  return void 0;
}
function shouldIgnore(event) {
  const { sourceEvent } = event;
  const { className, classList, ariaHidden } = event.sourceEvent?.target ?? {};
  if (className === "ag-charts-proxy-elem" || !(classList instanceof DOMTokenList))
    return "leave";
  if (
    // Handle drag event on the axis 'add horizontal line annotation' button as canvas events.
    classList.contains("ag-charts-annotations__axis-button-icon") || className === "ag-charts-swapchain" || className === "ag-charts-canvas-container" || className === "ag-charts-canvas-proxy" || sourceEvent?.target instanceof HTMLCanvasElement
  ) {
    return "none";
  }
  if (getTooltipContainer(sourceEvent.target) && ariaHidden !== "true") {
    return "wait";
  }
  return "leave";
}
var RegionManager = class {
  constructor(interactionManager) {
    this.interactionManager = interactionManager;
    this.debug = Debug.create(true, "region");
    this.regions = {
      root: { properties: { name: "root" }, listeners: new RegionListeners() },
      series: { properties: { name: "series" }, listeners: new RegionListeners() }
    };
    this.destroyFns = [];
    this.allRegionsListeners = new RegionListeners();
    this.isDragMoving = false;
    this.blockNextClickEvent = false;
    this.processPointerEvent = (event) => {
      const ignore = shouldIgnore(event);
      const { current } = this;
      let newCurrent = current;
      if (!this.isDragMoving && this.deferredDragStart == null) {
        switch (ignore) {
          case "wait":
            return;
          case "none":
            newCurrent = this.pickRegion(event);
            break;
          case "leave":
            newCurrent = void 0;
            break;
        }
      }
      const newRegion = newCurrent;
      if (current !== void 0 && newRegion?.properties.name !== current.properties.name) {
        this.dispatch(current, event, "leave");
      }
      if (newRegion !== void 0 && newRegion.properties.name !== current?.properties.name) {
        this.dispatch(newCurrent, event, "enter");
      }
      if (newRegion !== void 0) {
        this.dispatch(newCurrent, event);
      }
      this.current = newCurrent;
    };
  }
  destroy() {
    this.destroyFns.forEach((fn) => fn());
    this.current = void 0;
    this.regions.root.listeners.destroy();
    this.regions.series.listeners.destroy();
  }
  initRegions(root, series) {
    this.regions.root.properties.widget = root;
    this.regions.series.properties.widget = series;
    root.addListener("wheel", this.processPointerEvent);
    root.addListener("contextmenu", this.processPointerEvent);
    root.addListener("click", this.processPointerEvent);
    root.addListener("dblclick", this.processPointerEvent);
    root.addListener("mouseenter", this.processPointerEvent);
    root.addListener("mousemove", this.processPointerEvent);
    root.addListener("mouseleave", this.processPointerEvent);
    root.addListener("drag-start", this.processPointerEvent);
    root.addListener("drag-move", this.processPointerEvent);
    root.addListener("drag-end", this.processPointerEvent);
  }
  getRegion(name) {
    return this.makeObserver(this.regions[name]);
  }
  listenAll(type, handler, triggeringStates = 32) {
    return addHandler(this.allRegionsListeners, this.interactionManager, type, handler, triggeringStates);
  }
  // This method return a wrapper object that matches the interface of InteractionManager.addListener.
  // The intent is to allow the InteractionManager and RegionManager to be used almost interchangeably.
  makeObserver(region) {
    const { interactionManager } = this;
    class ObservableRegionImplementation {
      addListener(type, handler, triggeringStates = 32) {
        return addHandler(region?.listeners, interactionManager, type, handler, triggeringStates);
      }
    }
    return new ObservableRegionImplementation();
  }
  widgetEventTypeToRegionEventType(widgetEvent, regionEventType) {
    if (regionEventType !== void 0)
      return regionEventType;
    const map = {
      contextmenu: "contextmenu",
      click: "click",
      dblclick: "dblclick",
      mouseenter: "enter",
      mousemove: "hover",
      mouseleave: "leave",
      wheel: "wheel",
      "drag-start": "drag-start",
      "drag-move": "drag",
      "drag-end": "drag-end"
    };
    return map[widgetEvent.type];
  }
  computeEventOffsets(currentWidget, rootWidget, widgetEvent) {
    const { deltaX, deltaY } = InteractionManager.getWheelDeltas(widgetEvent.sourceEvent);
    if ("mockRegion" in widgetEvent.sourceEvent) {
      const mockRegion = widgetEvent.sourceEvent.mockRegion;
      if (mockRegion) {
        return { deltaX, deltaY, ...mockRegion };
      }
    }
    const rootRect = rootWidget.getElement().getBoundingClientRect();
    const currentWidgetRect = currentWidget.getElement().getBoundingClientRect();
    return {
      canvasX: widgetEvent.clientX - rootRect.x,
      canvasY: widgetEvent.clientY - rootRect.y,
      regionX: widgetEvent.clientX - currentWidgetRect.x,
      regionY: widgetEvent.clientY - currentWidgetRect.y,
      deltaX,
      deltaY
    };
  }
  // Create and dispatch a copy of the InteractionEvent.
  dispatch(current, widgetEvent, regionEventType) {
    const { widget: currentWidget } = current?.properties ?? {};
    const { widget: rootWidget } = this.regions.root.properties;
    if (current == null || currentWidget == null || rootWidget == null)
      return;
    const event = buildPreventable({
      ...this.computeEventOffsets(currentWidget, rootWidget, widgetEvent),
      sourceEvent: widgetEvent.sourceEvent,
      type: this.widgetEventTypeToRegionEventType(widgetEvent, regionEventType),
      region: current.properties.name,
      timestamp: Date.now()
    });
    switch (event.type) {
      case "drag-start": {
        this.deferredDragStart = event;
        break;
      }
      case "drag": {
        if (this.deferredDragStart) {
          if (this.canStartDrag(event)) {
            this.dispatchEvent(current, this.deferredDragStart);
          } else {
            return;
          }
        }
        this.dispatchEvent(current, event);
        this.deferredDragStart = void 0;
        this.isDragMoving = true;
        this.blockNextClickEvent = true;
        break;
      }
      case "drag-end": {
        if (this.isDragMoving) {
          this.dispatchEvent(current, event);
        }
        this.deferredDragStart = void 0;
        this.isDragMoving = false;
        break;
      }
      case "click": {
        if (!this.blockNextClickEvent) {
          this.dispatchEvent(current, event);
        }
        this.blockNextClickEvent = false;
        break;
      }
      case "leave":
      case "enter":
        if (!this.isDragMoving || this.deferredDragStart != null) {
          this.dispatchEvent(current, event);
        }
        break;
      case "hover": {
        this.blockNextClickEvent = false;
        this.dispatchEvent(current, event);
        break;
      }
      default: {
        this.dispatchEvent(current, event);
        break;
      }
    }
  }
  dispatchEvent(current, event) {
    this.debug("Dispatching region event: ", event);
    this.allRegionsListeners.dispatch(event.type, event);
    current.listeners.dispatch(event.type, event);
  }
  pickRegion({ sourceEvent }) {
    if ("mockRegion" in sourceEvent && sourceEvent.mockRegion) {
      return sourceEvent.mockRegion.region === "series" ? this.regions.series : this.regions.root;
    }
    if (sourceEvent.target == this.regions.root?.properties.widget?.getElement()) {
      return this.regions.root;
    }
    return this.regions.series;
  }
  canStartDrag(event) {
    if (!this.deferredDragStart)
      return false;
    const time2 = event.timestamp - this.deferredDragStart.timestamp;
    if (time2 > DRAG_THRESHOLD_MS) {
      return true;
    }
    const distanceApproximation = Math.abs(event.canvasX - this.deferredDragStart.canvasX) + Math.abs(event.canvasY - this.deferredDragStart.canvasY);
    return distanceApproximation > DRAG_THRESHOLD_PX;
  }
};
function getDatumRefPoint(datum) {
  const refPoint = datum.yBar?.upperPoint ?? datum.midPoint ?? datum.series.datumMidPoint?.(datum);
  if (refPoint) {
    const { x, y } = Transformable.toCanvasPoint(datum.series.contentGroup, refPoint.x, refPoint.y);
    return { canvasX: Math.round(x), canvasY: Math.round(y) };
  }
}
var TooltipManager = class {
  constructor(domManager, tooltip) {
    this.domManager = domManager;
    this.tooltip = tooltip;
    this.stateTracker = new StateTracker();
    this.suppressState = new StateTracker(false);
    this.appliedState = null;
    tooltip.setup(domManager);
    domManager.addListener("hidden", () => this.tooltip.hide());
  }
  updateTooltip(callerId, meta, content) {
    if (!this.tooltip.enabled)
      return;
    content ?? (content = this.stateTracker.get(callerId)?.content);
    this.stateTracker.set(callerId, { content, meta });
    this.applyStates();
  }
  removeTooltip(callerId) {
    if (!this.tooltip.enabled)
      return;
    this.stateTracker.delete(callerId);
    this.applyStates();
  }
  suppressTooltip(callerId) {
    this.suppressState.set(callerId, true);
  }
  unsuppressTooltip(callerId) {
    this.suppressState.delete(callerId);
  }
  getTooltipMeta(callerId) {
    return this.stateTracker.get(callerId)?.meta;
  }
  destroy() {
    this.domManager.removeStyles("tooltip");
  }
  applyStates() {
    const id = this.stateTracker.stateId();
    const state = id ? this.stateTracker.get(id) : null;
    if (this.suppressState.stateValue() || state?.meta == null || state?.content == null) {
      this.appliedState = null;
      this.tooltip.hide();
      return;
    }
    const canvasRect = this.domManager.getBoundingClientRect();
    const boundingRect = this.tooltip.bounds === "extended" ? this.domManager.getOverlayClientRect() : canvasRect;
    if (this.appliedState?.content === state?.content) {
      const renderInstantly = this.tooltip.isVisible();
      this.tooltip.show(boundingRect, canvasRect, state?.meta, null, renderInstantly);
    } else {
      this.tooltip.show(boundingRect, canvasRect, state?.meta, state?.content);
    }
    this.appliedState = state;
  }
  static makeTooltipMeta(event, datum) {
    const { canvasX, canvasY } = event;
    const tooltip = datum.series.properties.tooltip;
    const meta = {
      canvasX,
      canvasY,
      enableInteraction: tooltip.interaction?.enabled ?? false,
      lastPointerEvent: { type: event.type, canvasX, canvasY },
      showArrow: tooltip.showArrow,
      position: {
        type: tooltip.position.type,
        xOffset: tooltip.position.xOffset,
        yOffset: tooltip.position.yOffset
      }
    };
    const refPoint = getDatumRefPoint(datum);
    if ((tooltip.position.type === "node" || tooltip.position.type === "sparkline") && refPoint) {
      return { ...meta, canvasX: refPoint.canvasX, canvasY: refPoint.canvasY };
    }
    return meta;
  }
};
var Vec4 = {
  bottomCenter,
  center,
  clone,
  end,
  from,
  height,
  round: round2,
  start,
  topCenter,
  origin,
  width
};
function start(a) {
  return { x: a.x1, y: a.y1 };
}
function end(a) {
  return { x: a.x2, y: a.y2 };
}
function topCenter(a) {
  return { x: (a.x1 + a.x2) / 2, y: Math.min(a.y1, a.y2) };
}
function center(a) {
  return { x: (a.x1 + a.x2) / 2, y: (a.y1 + a.y2) / 2 };
}
function bottomCenter(a) {
  return { x: (a.x1 + a.x2) / 2, y: Math.max(a.y1, a.y2) };
}
function width(a) {
  return Math.abs(a.x2 - a.x1);
}
function height(a) {
  return Math.abs(a.y2 - a.y1);
}
function round2(a) {
  return { x1: Math.round(a.x1), y1: Math.round(a.y1), x2: Math.round(a.x2), y2: Math.round(a.y2) };
}
function clone(a) {
  return { x1: a.x1, y1: a.y1, x2: a.x2, y2: a.y2 };
}
function from(a, b, c, d) {
  if (typeof a === "number") {
    return { x1: a, y1: b, x2: c, y2: d };
  }
  if ("width" in a) {
    return {
      x1: a.x,
      y1: a.y,
      x2: a.x + a.width,
      y2: a.y + a.height
    };
  }
  throw new Error(`Values can not be converted into a vector4: [${JSON.stringify(a)}] [${b}] [${c}] [${d}]`);
}
function origin() {
  return { x1: 0, y1: 0, x2: 0, y2: 0 };
}
function normalize2(screenMin, min, screenMax, max, target) {
  return min + (max - min) * ((target - screenMin) / (screenMax - screenMin));
}
function unnormalize(screenMin, min, screenMax, max, ratio2) {
  return screenMin + (ratio2 - min) * ((screenMax - screenMin) / (max - min));
}
function calcWorldAxis(viewportMin, viewportMax, ratio2) {
  return [
    unnormalize(viewportMin, ratio2.min, viewportMax, ratio2.max, 0),
    unnormalize(viewportMin, ratio2.min, viewportMax, ratio2.max, 1)
  ];
}
function calcWorldVec4(viewport, ratioX, ratioY) {
  const [x1, x2] = calcWorldAxis(viewport.x1, viewport.x2, ratioX);
  const [y1, y2] = calcWorldAxis(viewport.y1, viewport.y2, ratioY);
  return { x1, x2, y1, y2 };
}
function panAxesUnnormalized(worldMin, worldMax, viewportMin, viewportMax, targetMin, targetMax) {
  if (viewportMin <= targetMin && targetMax <= viewportMax)
    return viewportMin;
  const minDiff = targetMin - viewportMin;
  const maxDiff = targetMax - viewportMax;
  const diff2 = Math.abs(minDiff) < Math.abs(maxDiff) ? minDiff : maxDiff;
  return clamp(worldMin, viewportMin + diff2, worldMax);
}
function calcPanToBBoxRatios(viewportBBox, ratios, targetBBox) {
  const { x: ratioX = { min: 0, max: 1 }, y: ratioY = { min: 0, max: 1 } } = ratios;
  const target = Vec4.from(targetBBox);
  const viewport = Vec4.from(viewportBBox);
  const world = calcWorldVec4(viewport, ratioX, ratioY);
  const x = panAxesUnnormalized(world.x1, world.x2, viewport.x1, viewport.x2, target.x1, target.x2);
  const y = panAxesUnnormalized(world.y1, world.y2, viewport.y1, viewport.y2, target.y1, target.y2);
  return {
    x: {
      min: normalize2(viewport.x1, ratioX.min, viewport.x2, ratioX.max, x),
      max: normalize2(viewport.x1, ratioX.min, viewport.x2, ratioX.max, x + viewportBBox.width)
    },
    y: {
      min: normalize2(viewport.y1, ratioY.min, viewport.y2, ratioY.max, y),
      max: normalize2(viewport.y1, ratioY.min, viewport.y2, ratioY.max, y + viewportBBox.height)
    }
  };
}
var expectedMementoKeys = ["rangeX", "rangeY", "ratioX", "ratioY", "autoScaleYAxis"];
var ZoomManagerAutoScaleAxis = class {
  constructor() {
    this.enabled = false;
    this.padding = 0;
    this.manuallyAdjusted = false;
  }
};
var ZoomManager = class extends BaseManager {
  constructor() {
    super(...arguments);
    this.mementoOriginatorKey = "zoom";
    this.axisZoomManagers = /* @__PURE__ */ new Map();
    this.state = new StateTracker(void 0, "initial");
    this.axes = [];
    this.didLayoutAxes = false;
    this.autoScaleYAxis = new ZoomManagerAutoScaleAxis();
    this.lastRestoredState = void 0;
    this.independentAxes = false;
    this.navigatorModule = false;
    this.zoomModule = false;
    this.pendingMemento = void 0;
  }
  addLayoutListeners(layoutManager) {
    this.destroyFns.push(
      layoutManager.addListener("layout:complete", () => {
        const { pendingMemento } = this;
        const shouldPerformInitialLayout = !this.didLayoutAxes;
        this.didLayoutAxes = true;
        if (pendingMemento) {
          this.restoreMemento(pendingMemento.version, pendingMemento.mementoVersion, pendingMemento.memento);
        } else if (shouldPerformInitialLayout) {
          this.autoScaleYZoom("zoom-manager");
        }
      })
    );
  }
  createMemento() {
    const zoom = this.getDefinedZoom();
    const memento = {
      rangeX: this.getRangeDirection(
        zoom.x,
        "x"
        /* X */
      ),
      rangeY: this.getRangeDirection(
        zoom.y,
        "y"
        /* Y */
      ),
      ratioX: { start: zoom.x.min, end: zoom.x.max },
      ratioY: { start: zoom.y.min, end: zoom.y.max }
    };
    if (this.autoScaleYAxis.enabled) {
      memento.autoScaleYAxis = !this.autoScaleYAxis.manuallyAdjusted;
    }
    return memento;
  }
  guardMemento(blob) {
    if (blob == null)
      return true;
    if (!isObject(blob))
      return false;
    for (const key of Object.keys(blob)) {
      if (!includes(expectedMementoKeys, key)) {
        return false;
      }
    }
    return true;
  }
  restoreMemento(_version, _mementoVersion, memento) {
    const { independentAxes } = this;
    if (!this.axes || !this.didLayoutAxes) {
      this.pendingMemento = { version: _version, mementoVersion: _mementoVersion, memento };
      return;
    }
    this.pendingMemento = void 0;
    const zoom = this.getDefinedZoom();
    if (memento?.rangeX) {
      zoom.x = this.rangeToRatio(
        memento.rangeX,
        "x"
        /* X */
      ) ?? { min: 0, max: 1 };
    } else if (memento?.ratioX) {
      zoom.x = {
        min: memento.ratioX.start ?? 0,
        max: memento.ratioX.end ?? 1
      };
    } else {
      zoom.x = { min: 0, max: 1 };
    }
    if (!this.navigatorModule || this.zoomModule) {
      if (memento?.rangeY) {
        zoom.y = this.rangeToRatio(
          memento.rangeY,
          "y"
          /* Y */
        ) ?? { min: 0, max: 1 };
      } else if (memento?.ratioY) {
        zoom.y = {
          min: memento.ratioY.start ?? 0,
          max: memento.ratioY.end ?? 1
        };
      } else {
        zoom.y = { min: 0, max: 1 };
      }
    }
    if (memento?.autoScaleYAxis != null) {
      this.autoScaleYAxis.manuallyAdjusted = !memento.autoScaleYAxis;
    }
    this.lastRestoredState = zoom;
    if (independentAxes !== true) {
      this.updateZoom("zoom-manager", zoom);
      return;
    }
    const primaryX = this.getPrimaryAxis(
      "x"
      /* X */
    );
    const primaryY = this.getPrimaryAxis(
      "y"
      /* Y */
    );
    for (const axis of [primaryX, primaryY]) {
      if (!axis)
        continue;
      this.updateAxisZoom("zoom-manager", axis.id, zoom[axis.direction]);
    }
  }
  updateAxes(axes) {
    this.axes = axes;
    const zoomManagers = new Map(axes.map((axis) => [axis.id, this.axisZoomManagers.get(axis.id)]));
    this.axisZoomManagers.clear();
    for (const axis of axes) {
      this.axisZoomManagers.set(axis.id, zoomManagers.get(axis.id) ?? new AxisZoomManager(axis));
    }
    if (this.state.size > 0 && axes.length > 0) {
      this.updateZoom(this.state.stateId(), this.state.stateValue());
    }
  }
  setIndependentAxes(independent = true) {
    this.independentAxes = independent;
  }
  setAutoScaleYAxis(enabled, padding) {
    this.autoScaleYAxis.enabled = enabled;
    this.autoScaleYAxis.padding = padding;
  }
  setNavigatorEnabled(enabled = true) {
    this.navigatorModule = enabled;
  }
  setZoomModuleEnabled(enabled = true) {
    this.zoomModule = enabled;
  }
  isZoomEnabled() {
    return this.zoomModule;
  }
  updateZoom(callerId, newZoom) {
    if (this.axisZoomManagers.size === 0) {
      const stateId = this.state.stateId();
      if (stateId === "initial" || stateId === callerId) {
        this.state.set(callerId, newZoom);
      }
      return;
    }
    this.state.set(callerId, newZoom);
    this.axisZoomManagers.forEach((axis) => {
      axis.updateZoom(callerId, newZoom?.[axis.getDirection()]);
    });
    this.applyChanges(callerId);
  }
  updateAxisZoom(callerId, axisId, newZoom) {
    this.axisZoomManagers.get(axisId)?.updateZoom(callerId, newZoom);
    this.applyChanges(callerId);
  }
  resetZoom(callerId) {
    this.autoScaleYAxis.manuallyAdjusted = false;
    const zoom = this.getRestoredZoom();
    this.updateZoom(callerId, {
      x: { min: zoom?.x?.min ?? 0, max: zoom?.x?.max ?? 1 },
      y: { min: zoom?.y?.min ?? 0, max: zoom?.y?.max ?? 1 }
    });
  }
  resetAxisZoom(callerId, axisId) {
    const axisZoomManager = this.axisZoomManagers.get(axisId);
    const direction = axisZoomManager?.getDirection();
    if (direction == null)
      return;
    if (direction === "y") {
      this.autoScaleYAxis.manuallyAdjusted = false;
    }
    this.updateAxisZoom(callerId, axisId, this.getRestoredZoom()?.[direction] ?? { min: 0, max: 1 });
  }
  setAxisManuallyAdjusted(_callerId, axisId) {
    const direction = this.axisZoomManagers.get(axisId)?.getDirection();
    if (direction !== "y")
      return;
    this.autoScaleYAxis.manuallyAdjusted = true;
  }
  updatePrimaryAxisZoom(callerId, direction, newZoom) {
    const primaryAxis = this.getPrimaryAxis(direction);
    if (!primaryAxis)
      return;
    this.updateAxisZoom(callerId, primaryAxis.id, newZoom);
  }
  panToBBox(callerId, seriesRect, target) {
    const zoom = this.getZoom();
    if (zoom === void 0 || !zoom.x && !zoom.y)
      return;
    const panIsPossible = seriesRect.width > 0 && seriesRect.height > 0 && Math.abs(target.width) <= Math.abs(seriesRect.width) && Math.abs(target.height) <= Math.abs(seriesRect.height);
    if (!panIsPossible) {
      Logger.warnOnce(`cannot pan to target BBox - chart too small?`);
      return;
    }
    const newZoom = calcPanToBBoxRatios(seriesRect, zoom, target);
    if (this.independentAxes) {
      this.updatePrimaryAxisZoom(callerId, "x", newZoom.x);
      this.updatePrimaryAxisZoom(callerId, "y", newZoom.y);
    } else {
      this.updateZoom(callerId, newZoom);
    }
  }
  // Fire this event to signal to listeners that the view is changing through a zoom and/or pan change.
  fireZoomPanStartEvent(callerId) {
    this.listeners.dispatch("zoom-pan-start", { type: "zoom-pan-start", callerId });
  }
  extendToEnd(callerId, direction, extent2) {
    return this.extendWith(callerId, direction, (end2) => Number(end2) - extent2);
  }
  extendWith(callerId, direction, fn) {
    const axis = this.getPrimaryAxis(direction);
    if (!axis)
      return;
    const extents = this.getDomainExtents(axis);
    if (!extents)
      return;
    const [, end2] = extents;
    const start2 = fn(end2);
    const ratio2 = this.rangeToRatio({ start: start2, end: end2 }, direction);
    if (!ratio2)
      return;
    this.updateZoom(callerId, { [direction]: ratio2 });
  }
  updateWith(callerId, direction, fn) {
    const axis = this.getPrimaryAxis(direction);
    if (!axis)
      return;
    const extents = this.getDomainExtents(axis);
    if (!extents)
      return;
    let [start2, end2] = extents;
    [start2, end2] = fn(start2, end2);
    const ratio2 = this.rangeToRatio({ start: start2, end: end2 }, direction);
    if (!ratio2)
      return;
    this.updateZoom(callerId, { [direction]: ratio2 });
  }
  getZoom() {
    let x;
    let y;
    this.axisZoomManagers.forEach((axis) => {
      if (axis.getDirection() === "x") {
        x ?? (x = axis.getZoom());
      } else if (axis.getDirection() === "y") {
        y ?? (y = axis.getZoom());
      }
    });
    if (x || y) {
      return { x, y };
    }
  }
  getAxisZoom(axisId) {
    return this.axisZoomManagers.get(axisId)?.getZoom() ?? { min: 0, max: 1 };
  }
  getAxisZooms() {
    const axes = {};
    for (const [axisId, axis] of this.axisZoomManagers.entries()) {
      axes[axisId] = {
        direction: axis.getDirection(),
        zoom: axis.getZoom()
      };
    }
    return axes;
  }
  getRestoredZoom() {
    return this.lastRestoredState;
  }
  autoScaleYZoom(callerId, applyChanges = true) {
    const { independentAxes, autoScaleYAxis } = this;
    const zoom = this.getZoom();
    if (zoom?.x == null || !autoScaleYAxis.enabled || autoScaleYAxis.manuallyAdjusted)
      return;
    const { padding } = autoScaleYAxis;
    const zoomY = independentAxes ? this.primaryAxisZoom("y", zoom.x, { padding }) : this.combinedAxisZoom("y", zoom.x, { padding });
    if (zoomY == null)
      return;
    if (independentAxes) {
      const primaryAxis = this.getPrimaryAxis(
        "y"
        /* Y */
      );
      const primaryAxisManager = primaryAxis == null ? void 0 : this.axisZoomManagers.get(primaryAxis.id);
      primaryAxisManager?.updateZoom("zoom-manager", zoomY);
    } else {
      for (const axisZoomManager of this.axisZoomManagers.values()) {
        if (axisZoomManager.getDirection() === "y") {
          axisZoomManager.updateZoom("zoom-manager", zoomY);
        }
      }
    }
    if (applyChanges) {
      this.applyChanges(callerId);
    }
  }
  applyChanges(callerId) {
    this.autoScaleYZoom(callerId, false);
    const changed = Array.from(this.axisZoomManagers.values(), (axis) => axis.applyChanges()).includes(true);
    if (!changed) {
      return;
    }
    const axes = {};
    for (const [axisId, axis] of this.axisZoomManagers.entries()) {
      axes[axisId] = axis.getZoom();
    }
    this.listeners.dispatch("zoom-change", { type: "zoom-change", ...this.getZoom(), axes, callerId });
  }
  getRangeDirection(ratio2, direction) {
    const axis = this.getPrimaryAxis(direction);
    if (!axis || !ContinuousScale.is(axis.scale) && !OrdinalTimeScale.is(axis.scale))
      return;
    const extents = this.getDomainPixelExtents(axis);
    if (!extents)
      return;
    const [d0, d1] = extents;
    let start2;
    let end2;
    if (d0 <= d1) {
      start2 = axis.scale.invert?.(0);
      end2 = axis.scale.invert?.(d0 + (d1 - d0) * ratio2.max);
    } else {
      start2 = axis.scale.invert?.(d0 - (d0 - d1) * ratio2.min);
      end2 = axis.scale.invert?.(0);
    }
    return { start: start2, end: end2 };
  }
  rangeToRatio(range3, direction) {
    const axis = this.getPrimaryAxis(direction);
    if (!axis)
      return;
    const extents = this.getDomainPixelExtents(axis);
    if (!extents)
      return;
    const [d0, d1] = extents;
    const r0 = range3.start == null ? d0 : axis.scale.convert?.(range3.start);
    const r1 = range3.end == null ? d1 : axis.scale.convert?.(range3.end);
    if (!isFiniteNumber(r0) || !isFiniteNumber(r1))
      return;
    const diff2 = d1 - d0;
    const min = Math.abs((r0 - d0) / diff2);
    const max = Math.abs((r1 - d0) / diff2);
    return { min, max };
  }
  getPrimaryAxis(direction) {
    return this.axes?.find((a) => a.direction === direction);
  }
  getDomainExtents(axis) {
    const domain = axis.scale.getDomain?.();
    const d0 = domain?.at(0);
    const d1 = domain?.at(-1);
    if (d0 == null || d1 == null)
      return;
    return [d0, d1];
  }
  getDomainPixelExtents(axis) {
    const domain = axis.scale.getDomain?.();
    const d0 = axis.scale.convert?.(domain?.at(0));
    const d1 = axis.scale.convert?.(domain?.at(-1));
    if (!isFiniteNumber(d0) || !isFiniteNumber(d1))
      return;
    return [d0, d1];
  }
  getDefinedZoom() {
    const zoom = this.getZoom();
    return {
      x: { min: zoom?.x?.min ?? 0, max: zoom?.x?.max ?? 1 },
      y: { min: zoom?.y?.min ?? 0, max: zoom?.y?.max ?? 1 }
    };
  }
  zoomBounds(xAxis, yAxis, zoom, padding) {
    const xScale = xAxis.scale;
    const xScaleRange = xScale.range;
    xScale.range = [0, 1];
    const [d0, d1] = findMinMax(yAxis.scale.domain);
    let min = 1;
    let minPadding = false;
    let max = 0;
    let maxPadding = false;
    for (const series of yAxis.boundSeries) {
      const [yValue0, yValue1] = series.getRange("y", [zoom.min, zoom.max]);
      let y0 = (yValue0 - d0) / (d1 - d0);
      let y1 = (yValue1 - d0) / (d1 - d0);
      [y0, y1] = findMinMax([y0, y1]);
      if (!Number.isFinite(y0) || !Number.isFinite(y1))
        continue;
      const { connectsToYAxis } = series;
      if (y0 < min) {
        min = y0;
        minPadding = !connectsToYAxis || yValue0 < 0;
      }
      if (y1 > max) {
        max = y1;
        maxPadding = !connectsToYAxis || yValue1 > 0;
      }
    }
    xScale.range = xScaleRange;
    const totalPadding = (minPadding ? padding : 0) + (maxPadding ? padding : 0);
    const paddedDelta = (max - min) * (1 + totalPadding);
    if (paddedDelta <= 0 || paddedDelta >= 1)
      return;
    if (minPadding && maxPadding) {
      const mid = (max + min) / 2;
      min = mid - paddedDelta / 2;
      max = mid + paddedDelta / 2;
    } else if (!minPadding && maxPadding) {
      max = min + paddedDelta;
    } else if (minPadding && !maxPadding) {
      min = max - paddedDelta;
    }
    if (min < 0) {
      max += -min;
      min = 0;
    } else if (max > 1) {
      min -= max - 1;
      max = 1;
    }
    return { min, max };
  }
  primaryAxisZoom(direction, zoom, { padding = 0 } = {}) {
    const crossDirection = direction === "x" ? "y" : "x";
    const xAxis = this.getPrimaryAxis(crossDirection);
    const yAxis = this.getPrimaryAxis(direction);
    if (xAxis == null || yAxis == null)
      return;
    return this.zoomBounds(xAxis, yAxis, zoom, padding);
  }
  combinedAxisZoom(direction, zoom, { padding = 0 } = {}) {
    const crossDirection = direction === "x" ? "y" : "x";
    const seriesXAxes = /* @__PURE__ */ new Map();
    for (const xAxis of this.axes) {
      if (xAxis.direction !== crossDirection)
        continue;
      for (const series of xAxis.boundSeries) {
        seriesXAxes.set(series, xAxis);
      }
    }
    let min = 1;
    let max = 0;
    for (const yAxis of this.axes) {
      if (yAxis.direction !== direction)
        continue;
      for (const series of yAxis.boundSeries) {
        const xAxis = seriesXAxes.get(series);
        if (xAxis == null)
          continue;
        const bounds = this.zoomBounds(xAxis, yAxis, zoom, padding);
        if (bounds == null)
          return;
        min = Math.min(min, bounds.min);
        max = Math.max(max, bounds.max);
      }
    }
    if (min > max)
      return;
    return { min, max };
  }
};
var AxisZoomManager = class {
  constructor(axis) {
    this.axis = axis;
    const [min = 0, max = 1] = axis.visibleRange;
    this.state = new StateTracker({ min, max });
    this.currentZoom = this.state.stateValue();
  }
  getDirection() {
    return this.axis.direction;
  }
  updateZoom(callerId, newZoom) {
    this.state.set(callerId, newZoom);
  }
  getZoom() {
    return deepClone(this.state.stateValue());
  }
  hasChanges() {
    const currentZoom = this.currentZoom;
    const pendingZoom = this.state.stateValue();
    return currentZoom.min !== pendingZoom.min || currentZoom.max !== pendingZoom.max;
  }
  applyChanges() {
    const hasChanges = this.hasChanges();
    this.currentZoom = this.state.stateValue();
    return hasChanges;
  }
};
var SeriesLabelLayoutManager = class {
  constructor() {
    this.labelData = /* @__PURE__ */ new Map();
  }
  updateLabels(placedLabelSeries, padding, seriesRect = BBox.zero) {
    const bounds = {
      x: -padding.left,
      y: -padding.top,
      width: seriesRect.width + padding.left + padding.right,
      height: seriesRect.height + padding.top + padding.bottom
    };
    const expectedSeriesId = new Set(placedLabelSeries.map((s) => s.id));
    for (const seriesId of this.labelData.keys()) {
      if (!expectedSeriesId.has(seriesId)) {
        this.labelData.delete(seriesId);
      }
    }
    for (const series of placedLabelSeries) {
      const labelData = series.getLabelData();
      if (labelData.every(isPointLabelDatum)) {
        this.labelData.set(series.id, labelData);
      }
    }
    const placedLabels = placeLabels(this.labelData, bounds, 5);
    for (const series of placedLabelSeries) {
      series.updatePlacedLabelData?.(placedLabels.get(series.id) ?? []);
    }
  }
};
var LegendManager = class extends BaseManager {
  constructor(chartService) {
    super();
    this.chartService = chartService;
    this.mementoOriginatorKey = "legend";
    this.legendDataMap = /* @__PURE__ */ new Map();
  }
  createMemento() {
    return this.getData().filter(({ hideInLegend, isFixed }) => !hideInLegend && !isFixed).map(({ enabled, seriesId, itemId, legendItemName }) => ({
      visible: enabled,
      seriesId,
      itemId,
      legendItemName
    }));
  }
  guardMemento(blob) {
    return blob == null || isArray(blob);
  }
  restoreMemento(_version, _mementoVersion, memento) {
    memento?.forEach((datum) => {
      const { seriesId, data } = this.getRestoredData(datum) ?? {};
      if (!seriesId || !data) {
        return;
      }
      this.updateData(seriesId, data);
    });
    this.update();
  }
  getRestoredData(datum) {
    const { seriesId, itemId, legendItemName, visible } = datum;
    if (seriesId) {
      const legendData = this.legendDataMap.get(seriesId) ?? [];
      const data = legendData.map((d) => {
        const match = d.seriesId === seriesId && (!itemId || d.itemId === itemId);
        if (match && d.isFixed) {
          this.warnFixed(d.seriesId, d.itemId);
        }
        return !d.isFixed && match ? { ...d, enabled: visible } : d;
      });
      return { seriesId, data };
    }
    if (itemId == null && legendItemName == null) {
      return;
    }
    for (const legendDatum of this.getData()) {
      if (itemId != null && legendDatum.itemId !== itemId || legendItemName != null && legendDatum.legendItemName !== legendItemName) {
        continue;
      }
      if (legendDatum.isFixed) {
        this.warnFixed(legendDatum.seriesId, itemId);
        return;
      }
      const seriesLegendData = (this.legendDataMap.get(legendDatum.seriesId) ?? []).map(
        (d) => d.itemId === itemId || d.legendItemName === legendItemName ? { ...d, enabled: visible } : d
      );
      return {
        seriesId: legendDatum.seriesId,
        data: seriesLegendData
      };
    }
  }
  warnFixed(seriesId, itemId) {
    Logger.warnOnce(
      `The legend item with seriesId [${seriesId}] and itemId [${itemId}] is not configurable, this series item cannot be toggled through the legend.`
    );
  }
  update(data) {
    this.listeners.dispatch("legend-change", {
      type: "legend-change",
      legendData: data ?? this.getData()
    });
  }
  updateData(seriesId, data = []) {
    this.legendDataMap.set(seriesId, data);
  }
  clearData() {
    this.legendDataMap.clear();
  }
  toggleItem({
    enabled,
    seriesId,
    itemId,
    legendItemName
  }) {
    if (legendItemName) {
      this.getData().forEach((datum) => {
        const newData = (this.legendDataMap.get(datum.seriesId) ?? []).map(
          (d) => d.legendItemName === legendItemName ? { ...d, enabled } : d
        );
        this.updateData(datum.seriesId, newData);
      });
      return;
    }
    const seriesLegendData = this.getData(seriesId);
    const singleLegendItem = seriesLegendData.length === 1;
    const data = seriesLegendData.map(
      (datum) => itemId == null && singleLegendItem || datum.itemId === itemId ? { ...datum, enabled } : datum
    );
    this.updateData(seriesId, data);
  }
  getData(seriesId) {
    if (seriesId) {
      return this.legendDataMap.get(seriesId) ?? [];
    }
    return [...this.legendDataMap].reduce(
      (data, [_, legendData]) => data.concat(legendData),
      []
    );
  }
  getDatum({ seriesId, itemId } = {}) {
    return this.getData(seriesId).find((datum) => datum.itemId === itemId);
  }
  getSeriesEnabled(seriesId) {
    const data = this.getData(seriesId);
    if (data.length > 0) {
      return data.some((d) => d.enabled);
    }
  }
  getItemEnabled({ seriesId, itemId } = {}) {
    return this.getDatum({ seriesId, itemId })?.enabled ?? true;
  }
};
var SeriesStateManager = class {
  constructor() {
    this.groups = {};
  }
  registerSeries({ internalId, seriesGrouping, visible, type }) {
    var _a;
    if (!seriesGrouping)
      return;
    (_a = this.groups)[type] ?? (_a[type] = {});
    this.groups[type][internalId] = { grouping: seriesGrouping, visible };
  }
  updateSeries({ internalId, seriesGrouping, visible, type }) {
    if (!seriesGrouping)
      return;
    const entry = this.groups[type]?.[internalId];
    if (entry) {
      entry.grouping = seriesGrouping;
      entry.visible = visible;
    }
  }
  deregisterSeries({ internalId, type }) {
    if (this.groups[type]) {
      delete this.groups[type][internalId];
    }
    if (this.groups[type] && Object.keys(this.groups[type]).length === 0) {
      delete this.groups[type];
    }
  }
  getVisiblePeerGroupIndex({ type, seriesGrouping, visible }) {
    if (!seriesGrouping) {
      return { visibleGroupCount: visible ? 1 : 0, visibleSameStackCount: visible ? 1 : 0, index: 0 };
    }
    const visibleGroupsSet = /* @__PURE__ */ new Set();
    const visibleSameStackSet = /* @__PURE__ */ new Set();
    for (const entry of Object.values(this.groups[type] ?? {})) {
      if (!entry.visible)
        continue;
      visibleGroupsSet.add(entry.grouping.groupIndex);
      if (entry.grouping.groupIndex === seriesGrouping.groupIndex) {
        visibleSameStackSet.add(entry.grouping.stackIndex);
      }
    }
    const visibleGroups = Array.from(visibleGroupsSet);
    visibleGroups.sort((a, b) => a - b);
    return {
      visibleGroupCount: visibleGroups.length,
      visibleSameStackCount: visibleSameStackSet.size,
      index: visibleGroups.indexOf(seriesGrouping.groupIndex)
    };
  }
};
var ChartUpdateType = /* @__PURE__ */ ((ChartUpdateType2) => {
  ChartUpdateType2[ChartUpdateType2["FULL"] = 0] = "FULL";
  ChartUpdateType2[ChartUpdateType2["UPDATE_DATA"] = 1] = "UPDATE_DATA";
  ChartUpdateType2[ChartUpdateType2["PROCESS_DATA"] = 2] = "PROCESS_DATA";
  ChartUpdateType2[ChartUpdateType2["PERFORM_LAYOUT"] = 3] = "PERFORM_LAYOUT";
  ChartUpdateType2[ChartUpdateType2["SERIES_UPDATE"] = 4] = "SERIES_UPDATE";
  ChartUpdateType2[ChartUpdateType2["PRE_SCENE_RENDER"] = 5] = "PRE_SCENE_RENDER";
  ChartUpdateType2[ChartUpdateType2["SCENE_RENDER"] = 6] = "SCENE_RENDER";
  ChartUpdateType2[ChartUpdateType2["NONE"] = 7] = "NONE";
  return ChartUpdateType2;
})(ChartUpdateType || {});
var UpdateService = class extends Listeners {
  constructor(updateCallback) {
    super();
    this.updateCallback = updateCallback;
  }
  update(type = 0, options) {
    this.updateCallback(type, options);
  }
  dispatchUpdateComplete(rects) {
    this.dispatch("update-complete", {
      type: "update-complete",
      minRect: rects?.minRect,
      minVisibleRect: rects?.minVisibleRect
    });
  }
  dispatchPreDomUpdate() {
    this.dispatch("pre-dom-update", { type: "pre-dom-update" });
  }
  dispatchPreSceneRender(rects) {
    this.dispatch("pre-scene-render", { type: "pre-scene-render", ...rects });
  }
};
var ChartContext = class {
  constructor(chart, vars) {
    this.callbackCache = new CallbackCache();
    this.chartEventManager = new ChartEventManager();
    this.highlightManager = new HighlightManager();
    this.layoutManager = new LayoutManager();
    this.localeManager = new LocaleManager();
    this.seriesStateManager = new SeriesStateManager();
    this.stateManager = new StateManager();
    this.zoomManager = new ZoomManager();
    this.seriesLabelLayoutManager = new SeriesLabelLayoutManager();
    this.contextModules = [];
    const {
      scene,
      root,
      syncManager,
      container,
      updateCallback,
      updateMutex,
      pixelRatio,
      styleContainer,
      chartType: chartType2
    } = vars;
    this.chartService = chart;
    this.syncManager = syncManager;
    this.domManager = new DOMManager(container, styleContainer);
    const canvasElement = this.domManager.addChild(
      "canvas",
      "scene-canvas",
      scene?.canvas.element
    );
    this.scene = scene ?? new Scene({ pixelRatio, canvasElement });
    this.scene.setRoot(root);
    this.axisManager = new AxisManager(root);
    this.legendManager = new LegendManager(this.chartService);
    this.annotationManager = new AnnotationManager(chart.annotationRoot);
    this.chartTypeOriginator = new ChartTypeOriginator(chart);
    this.cursorManager = new CursorManager(this.domManager);
    this.interactionManager = new InteractionManager(chart.keyboard, this.domManager);
    this.regionManager = new RegionManager(this.interactionManager);
    this.keyNavManager = new KeyNavManager(this.interactionManager, this.regionManager);
    this.contextMenuRegistry = new ContextMenuRegistry();
    this.gestureDetector = new GestureDetector(this.domManager);
    this.updateService = new UpdateService(updateCallback);
    this.proxyInteractionService = new ProxyInteractionService(this.localeManager, this.domManager);
    this.historyManager = new HistoryManager(this.keyNavManager);
    this.animationManager = new AnimationManager(this.interactionManager, updateMutex);
    this.dataService = new DataService(this.animationManager);
    this.tooltipManager = new TooltipManager(this.domManager, chart.tooltip);
    this.zoomManager.addLayoutListeners(this.layoutManager);
    for (const module2 of moduleRegistry.byType("context")) {
      if (!module2.chartTypes.includes(chartType2))
        continue;
      const moduleInstance = module2.moduleFactory(this);
      this.contextModules.push(moduleInstance);
      this[module2.contextKey] = moduleInstance;
    }
  }
  destroy() {
    this.animationManager.destroy();
    this.highlightManager.destroy();
    this.axisManager.destroy();
    this.callbackCache.invalidateCache();
    this.chartEventManager.destroy();
    this.domManager.destroy();
    this.highlightManager.destroy();
    this.keyNavManager.destroy();
    this.regionManager.destroy();
    this.interactionManager.destroy();
    this.proxyInteractionService.destroy();
    this.syncManager.destroy();
    this.tooltipManager.destroy();
    this.zoomManager.destroy();
    this.contextModules.forEach((m) => m.destroy());
  }
};
var ChartHighlight = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.range = "tooltip";
  }
};
__decorateClass([
  Validate(UNION(["tooltip", "node"], "a range"))
], ChartHighlight.prototype, "range", 2);
function setsEqual(a, b) {
  if (a.size !== b.size)
    return false;
  for (const value of a) {
    if (!b.has(value))
      return false;
  }
  return true;
}
function idsMapEqual(a, b) {
  if (a == null || b == null)
    return a === b;
  if (a.size !== b.size)
    return false;
  for (const [key, aValue] of a) {
    const bValue = b.get(key);
    if (bValue == null)
      return false;
    if (!setsEqual(aValue, bValue))
      return false;
  }
  return true;
}
function propsEqual(a, b) {
  if (a.length !== b.length)
    return false;
  for (let i = 0; i < a.length; i += 1) {
    const { idsMap: idsMapA, ...propA } = a[i];
    const { idsMap: idsMapB, ...propB } = b[i];
    if (!objectsEqual(propA, propB) || !idsMapEqual(idsMapA, idsMapB))
      return false;
  }
  return true;
}
function optsEqual(a, b) {
  const { props: propsA, ...restA } = a;
  const { props: propsB, ...restB } = b;
  return objectsEqual(restA, restB) && propsEqual(propsA, propsB);
}
function canReuseCachedData(cachedDataItem, data, ids, opts) {
  return data === cachedDataItem.data && arraysEqual(ids, cachedDataItem.ids) && optsEqual(opts, cachedDataItem.opts);
}
var DiscreteDomain = class _DiscreteDomain {
  constructor() {
    this.domain = /* @__PURE__ */ new Set();
  }
  static is(value) {
    return value instanceof _DiscreteDomain;
  }
  extend(val) {
    this.domain.add(val);
  }
  getDomain() {
    return Array.from(this.domain);
  }
};
var ContinuousDomain = class _ContinuousDomain {
  constructor() {
    this.domain = [Infinity, -Infinity];
  }
  static is(value) {
    return value instanceof _ContinuousDomain;
  }
  static extendDomain(values, domain = [Infinity, -Infinity]) {
    for (const value of values) {
      if (typeof value !== "number") {
        continue;
      }
      if (domain[0] > value) {
        domain[0] = value;
      }
      if (domain[1] < value) {
        domain[1] = value;
      }
    }
    return domain;
  }
  extend(value) {
    if (this.domain[0] > value) {
      this.domain[0] = value;
    }
    if (this.domain[1] < value) {
      this.domain[1] = value;
    }
  }
  getDomain() {
    return [...this.domain];
  }
};
var MIN = 0;
var MAX = 1;
var SPAN = 2;
var RangeLookup = class {
  constructor(allValues) {
    const dataLength = allValues.reduce((acc, v) => Math.max(acc, v.length), 0);
    const sizePower = 32 - Math.clz32(dataLength);
    let maxLevelSize = 1 << sizePower;
    if (dataLength === maxLevelSize / 2) {
      maxLevelSize = maxLevelSize >>> 1;
    }
    this.maxLevelSize = maxLevelSize;
    const buffer = new Float64Array((maxLevelSize * 2 - 1) * 2).fill(NaN);
    for (const values of allValues) {
      for (let i = 0; i < values.length; i += 1) {
        const value = Number(values[i]);
        const bufferIndex = maxLevelSize + i - 1;
        const bufferMinIndex = (bufferIndex * SPAN | 0) + MIN;
        const bufferMaxIndex = (bufferIndex * SPAN | 0) + MAX;
        const prevMinValue = buffer[bufferMinIndex];
        const prevMaxValue = buffer[bufferMaxIndex];
        if (!Number.isFinite(prevMinValue) || value < prevMinValue) {
          buffer[bufferMinIndex] = value;
        }
        if (!Number.isFinite(prevMaxValue) || value > prevMaxValue) {
          buffer[bufferMaxIndex] = value;
        }
      }
    }
    for (let size = maxLevelSize / 2 | 0; size >= 1; size = size / 2 | 0) {
      const start2 = size - 1 | 0;
      const end2 = start2 + size | 0;
      for (let i = 0; i < size; i += 1) {
        const nodeIndex = start2 + i;
        const leftIndex = end2 + i * 2;
        const rightIndex = leftIndex + 1;
        const aMin = buffer[(leftIndex * SPAN | 0) + MIN];
        const bMin = buffer[(rightIndex * SPAN | 0) + MIN];
        buffer[(nodeIndex * SPAN | 0) + MIN] = !Number.isFinite(bMin) || aMin < bMin ? aMin : bMin;
        const aMax = buffer[(leftIndex * SPAN | 0) + MAX];
        const bMax = buffer[(rightIndex * SPAN | 0) + MAX];
        buffer[(nodeIndex * SPAN | 0) + MAX] = !Number.isFinite(bMax) || aMax > bMax ? aMax : bMax;
      }
    }
    this.buffer = buffer;
  }
  computeRangeInto(buffer, start2, end2, bufferIndex, currentStart, step, into) {
    const currentEnd = currentStart + step - 1;
    if (currentEnd < start2 || currentStart > end2)
      return into;
    if (currentStart >= start2 && currentEnd <= end2) {
      const min = buffer[(bufferIndex * SPAN | 0) + MIN];
      const max = buffer[(bufferIndex * SPAN | 0) + MAX];
      if (Number.isFinite(min))
        into[0] = Math.min(into[0], min);
      if (Number.isFinite(max))
        into[1] = Math.max(into[1], max);
    } else if (step > 1) {
      bufferIndex = bufferIndex * 2 | 0;
      step = step / 2 | 0;
      this.computeRangeInto(buffer, start2, end2, bufferIndex + 1 | 0, currentStart, step, into);
      this.computeRangeInto(buffer, start2, end2, bufferIndex + 2 | 0, currentStart + step, step, into);
    }
    return into;
  }
  rangeBetween(start2, end2) {
    const { maxLevelSize, buffer } = this;
    const range3 = [Infinity, -Infinity];
    this.computeRangeInto(buffer, start2, end2, 0, 0, maxLevelSize, range3);
    return range3;
  }
  get range() {
    const { buffer } = this;
    return [buffer[MIN], buffer[MAX]];
  }
};
var DOMAIN_RANGES = Symbol("domain-ranges");
function toKeyString(keys) {
  return keys.map((key) => isObject(key) ? JSON.stringify(key) : key).join("-");
}
function round3(val) {
  const accuracy = 1e4;
  if (Number.isInteger(val)) {
    return val;
  } else if (Math.abs(val) > accuracy) {
    return Math.trunc(val);
  }
  return Math.round(val * accuracy) / accuracy;
}
function fixNumericExtent(extent2) {
  const numberExtent = extent2?.map(Number);
  return numberExtent?.every(Number.isFinite) ? numberExtent : [];
}
function getMissCount(scopeProvider, missMap) {
  return missMap?.get(scopeProvider.id) ?? 0;
}
var INVALID_VALUE = Symbol("invalid");
function createArray(length2, value) {
  const out = [];
  for (let i = 0; i < length2; i += 1) {
    out[i] = value;
  }
  return out;
}
function datumKeys(keys, datumIndex) {
  const out = [];
  for (const k of keys) {
    const key = k[datumIndex];
    if (key == null)
      return;
    out.push(key);
  }
  return out;
}
function getPathComponents(path) {
  const components = [];
  let matchIndex = 0;
  let matchGroup;
  const regExp = /((?:(?:^|\.)\s*\w+|\[\s*(?:'(?:[^']|(?<!\\)\\')*'|"(?:[^"]|(?<!\\)\\")*"|-?\d+)\s*\])\s*)/g;
  while (matchGroup = regExp.exec(path)) {
    if (matchGroup.index !== matchIndex) {
      return;
    }
    matchIndex = matchGroup.index + matchGroup[0].length;
    const match = matchGroup[1].trim();
    if (match.startsWith(".")) {
      components.push(match.slice(1).trim());
    } else if (match.startsWith("[")) {
      const accessor = match.slice(1, -1).trim();
      if (accessor.startsWith(`'`)) {
        components.push(accessor.slice(1, -1).replace(/(?<!\\)\\'/g, `'`));
      } else if (accessor.startsWith(`"`)) {
        components.push(accessor.slice(1, -1).replace(/(?<!\\)\\"/g, `"`));
      } else {
        components.push(accessor);
      }
    } else {
      components.push(match);
    }
  }
  if (matchIndex !== path.length)
    return;
  return components;
}
function createPathAccessor(components) {
  return (datum) => {
    let current = datum;
    for (const component of components) {
      current = current[component];
    }
    return current;
  };
}
var DataModel = class {
  constructor(opts, mode = "standalone", suppressFieldDotNotation = false) {
    this.opts = opts;
    this.mode = mode;
    this.suppressFieldDotNotation = suppressFieldDotNotation;
    this.debug = Debug.create(true, "data-model");
    this.scopeCache = /* @__PURE__ */ new Map();
    this.keys = [];
    this.values = [];
    this.aggregates = [];
    this.groupProcessors = [];
    this.propertyProcessors = [];
    this.reducers = [];
    this.processors = [];
    let keys = true;
    for (const next of opts.props) {
      if (next.type === "key" && !keys) {
        throw new Error("AG Charts - internal config error: keys must come before values.");
      }
      if (next.type === "value" && keys) {
        keys = false;
      }
    }
    const verifyMatchGroupId = ({ matchGroupIds = [] }) => {
      for (const matchGroupId of matchGroupIds) {
        if (this.values.every((def) => def.groupId !== matchGroupId)) {
          throw new Error(
            `AG Charts - internal config error: matchGroupIds properties must match defined groups (${matchGroupId}).`
          );
        }
      }
    };
    for (const def of opts.props) {
      switch (def.type) {
        case "key":
          this.keys.push({ ...def, index: this.keys.length, missing: /* @__PURE__ */ new Map() });
          break;
        case "value":
          if (def.property == null) {
            throw new Error(
              `AG Charts - internal config error: no properties specified for value definitions: ${JSON.stringify(
                def
              )}`
            );
          }
          this.values.push({ ...def, index: this.values.length, missing: /* @__PURE__ */ new Map() });
          break;
        case "aggregate":
          verifyMatchGroupId(def);
          this.aggregates.push({ ...def, index: this.aggregates.length });
          break;
        case "group-value-processor":
          verifyMatchGroupId(def);
          this.groupProcessors.push({ ...def, index: this.groupProcessors.length });
          break;
        case "property-value-processor":
          this.propertyProcessors.push({ ...def, index: this.propertyProcessors.length });
          break;
        case "reducer":
          this.reducers.push({ ...def, index: this.reducers.length });
          break;
        case "processor":
          this.processors.push({ ...def, index: this.processors.length });
          break;
      }
    }
  }
  resolveProcessedDataDefById(scope, searchId) {
    const def = this.scopeCache.get(scope.id)?.get(searchId);
    if (!def) {
      throw new Error(`AG Charts - didn't find property definition for [${searchId}, ${scope.id}]`);
    }
    return { index: def.index, def };
  }
  resolveProcessedDataIndexById(scope, searchId) {
    return this.resolveProcessedDataDefById(scope, searchId).index;
  }
  resolveProcessedDataDefsByIds(scope, searchIds) {
    return searchIds.map((searchId) => [searchId, this.resolveProcessedDataDefById(scope, searchId)]);
  }
  resolveKeysById(scope, searchId, processedData) {
    const index = this.resolveProcessedDataIndexById(scope, searchId);
    const keys = processedData.keys[index];
    if (keys == null) {
      throw new Error(`AG Charts - didn't find keys for [${searchId}, ${scope.id}]`);
    }
    return keys;
  }
  resolveColumnById(scope, searchId, processedData) {
    const index = this.resolveProcessedDataIndexById(scope, searchId);
    const column = processedData.columns?.[index];
    if (column == null) {
      throw new Error(`AG Charts - didn't find column for [${searchId}, ${scope.id}]`);
    }
    return column;
  }
  resolveProcessedDataDefsValues(defs, { keys, values }) {
    const result = {};
    for (const [searchId, { index, def }] of defs) {
      const processedData = def.type === "key" ? keys : values;
      result[searchId] = processedData[index];
    }
    return result;
  }
  getDomain(scope, searchId, type, processedData) {
    const domains = this.getDomainsByType(type ?? "value", processedData);
    return domains?.[this.resolveProcessedDataIndexById(scope, searchId)] ?? [];
  }
  getDomainBetweenRange(scope, searchIds, [i0, i1], processedData) {
    const columnIndices = searchIds.map((searchId) => this.resolveProcessedDataIndexById(scope, searchId));
    const cacheKey = columnIndices.join(":");
    const domainRanges = processedData[DOMAIN_RANGES];
    let rangeLookup = domainRanges.get(cacheKey);
    if (rangeLookup == null) {
      const values = columnIndices.map((columnIndex) => processedData.columns[columnIndex]);
      rangeLookup = new RangeLookup(values);
      domainRanges.set(cacheKey, rangeLookup);
    }
    return rangeLookup.rangeBetween(i0, i1);
  }
  getDomainsByType(type, processedData) {
    switch (type) {
      case "key":
        return processedData.domain.keys;
      case "value":
        return processedData.domain.values;
      case "aggregate":
        return processedData.domain.aggValues;
      case "group-value-processor":
        return processedData.domain.groups;
      default:
        return null;
    }
  }
  processData(data, sources) {
    const {
      opts: { groupByKeys, groupByFn },
      aggregates,
      groupProcessors,
      reducers,
      processors,
      propertyProcessors
    } = this;
    const start2 = performance.now();
    if (groupByKeys && this.keys.length === 0) {
      return;
    }
    let processedData = this.extractData(data, sources);
    if (groupByKeys) {
      processedData = this.groupData(processedData);
    } else if (groupByFn) {
      processedData = this.groupData(processedData, groupByFn(processedData));
    }
    if (groupProcessors.length > 0) {
      this.postProcessGroups(processedData);
    }
    if (aggregates.length > 0) {
      this.aggregateData(processedData);
    }
    if (propertyProcessors.length > 0) {
      this.postProcessProperties(processedData);
    }
    if (reducers.length > 0) {
      this.reduceData(processedData);
    }
    if (processors.length > 0) {
      this.postProcessData(processedData);
    }
    this.warnDataMissingProperties(data);
    const end2 = performance.now();
    processedData.time = end2 - start2;
    if (this.debug.check()) {
      logProcessedData(processedData);
    }
    this.processScopeCache();
    return processedData;
  }
  warnDataMissingProperties(data) {
    if (data.length === 0)
      return;
    for (const def of iterate(this.keys, this.values)) {
      for (const [scope, missCount] of def.missing) {
        if (missCount < data.length)
          continue;
        const scopeHint = scope == null ? "" : ` for ${scope}`;
        Logger.warnOnce(`the key '${def.property}' was not found in any data element${scopeHint}.`);
      }
    }
  }
  processScopeCache() {
    this.scopeCache.clear();
    for (const def of iterate(this.keys, this.values, this.aggregates)) {
      if (!def.idsMap)
        continue;
      for (const [scope, ids] of def.idsMap) {
        for (const id of ids) {
          if (!this.scopeCache.has(scope)) {
            this.scopeCache.set(scope, /* @__PURE__ */ new Map([[id, def]]));
          } else if (this.scopeCache.get(scope)?.has(id)) {
            throw new Error("duplicate definition ids on the same scope are not allowed.");
          } else {
            this.scopeCache.get(scope).set(id, def);
          }
        }
      }
    }
  }
  valueGroupIdxLookup({ matchGroupIds }) {
    const result = [];
    for (const [index, def] of this.values.entries()) {
      if (!matchGroupIds || def.groupId && matchGroupIds.includes(def.groupId)) {
        result.push(index);
      }
    }
    return result;
  }
  valueIdxLookup(scopes, prop) {
    const noScopesToMatch = scopes == null || scopes.length === 0;
    const propId = typeof prop === "string" ? prop : prop.id;
    const hasMatchingScopeId = (def) => {
      if (def.idsMap) {
        for (const [scope, ids] of def.idsMap) {
          if (scopes?.includes(scope) && ids.has(propId)) {
            return true;
          }
        }
      }
      return false;
    };
    const result = this.values.reduce((res, def, index) => {
      const validDefScopes = def.scopes == null || noScopesToMatch && !def.scopes.length || def.scopes.some((s) => scopes?.includes(s));
      if (validDefScopes && (def.property === propId || def.id === propId || hasMatchingScopeId(def))) {
        res.push(index);
      }
      return res;
    }, []);
    if (result.length === 0) {
      throw new Error(
        `AG Charts - configuration error, unknown property ${JSON.stringify(prop)} in scope(s) ${JSON.stringify(
          scopes
        )}`
      );
    }
    return result;
  }
  extractData(data, sources) {
    const { dataDomain, processValue, scopes, allScopesHaveSameDefs } = this.initDataDomainProcessor();
    const sourcesById = new Map(sources?.map((s) => [s.id, s]));
    const { keys: keyDefs, values: valueDefs } = this;
    const dataLength = data.length;
    let partialValidDataCount = 0;
    let invalidKeys;
    let invalidData;
    const keys = keyDefs.map((def) => {
      const { invalidValue } = def;
      return data.map((datum, datumIndex) => {
        const key = processValue(def, datum, datumIndex);
        if (key !== INVALID_VALUE)
          return key;
        invalidKeys ?? (invalidKeys = createArray(dataLength, false));
        invalidKeys[datumIndex] = true;
        invalidData ?? (invalidData = createArray(dataLength, false));
        invalidData[datumIndex] = true;
        return invalidValue;
      });
    });
    let invalidDataScopes;
    const markScopeDatumInvalid = (scope, datumIndex) => {
      invalidDataScopes ?? (invalidDataScopes = /* @__PURE__ */ new Map());
      let datumValidity = invalidDataScopes.get(scope);
      if (datumValidity == null) {
        datumValidity = createArray(dataLength, false);
        invalidDataScopes.set(scope, datumValidity);
      }
      datumValidity[datumIndex] = true;
      invalidData ?? (invalidData = createArray(dataLength, false));
      invalidData[datumIndex] = true;
    };
    const columns = [];
    valueDefs.forEach((def) => {
      const { invalidValue } = def;
      const previousColumn = columns.length > 0 ? columns[columns.length - 1] : void 0;
      const column = data.map((datum, datumIndex) => {
        const invalidKey = invalidKeys?.[datumIndex] === true;
        let value = previousColumn?.[datumIndex];
        for (const scope of def.scopes ?? scopes) {
          const source = sourcesById.get(scope);
          const valueDatum = source?.data[datumIndex] ?? datum;
          value = processValue(def, valueDatum, datumIndex, value, scope);
          if (invalidKey || value === INVALID_VALUE) {
            markScopeDatumInvalid(scope, datumIndex);
          }
        }
        if (invalidKey) {
          return invalidValue;
        } else if (value === INVALID_VALUE) {
          partialValidDataCount += 1;
          return invalidValue;
        }
        return value;
      });
      columns.push(column);
    });
    const propertyDomain = (def) => {
      const defDomain = dataDomain.get(def);
      const result = defDomain.getDomain();
      if (ContinuousDomain.is(defDomain) && result[0] > result[1]) {
        return [];
      }
      return result;
    };
    return {
      type: "ungrouped",
      input: { count: data.length },
      rawData: data,
      rawDataSources: sources != null ? new Map(sources.map((s) => [s.id, s.data])) : void 0,
      aggregation: void 0,
      keys,
      columns,
      invalidKeys,
      invalidDataScopes,
      invalidData,
      domain: {
        keys: keyDefs.map(propertyDomain),
        values: valueDefs.map(propertyDomain)
      },
      defs: {
        allScopesHaveSameDefs,
        keys: keyDefs,
        values: valueDefs
      },
      partialValidDataCount,
      time: 0,
      [DOMAIN_RANGES]: /* @__PURE__ */ new Map()
    };
  }
  groupData(data, groupingFn) {
    const groups = /* @__PURE__ */ new Map();
    const { rawData, keys: dataKeys, invalidKeys, invalidDataScopes, invalidData } = data;
    for (let datumIndex = 0; datumIndex < rawData.length; datumIndex += 1) {
      const datum = rawData[datumIndex];
      const keys = datumKeys(dataKeys, datumIndex);
      if (keys == null || keys.length === 0)
        continue;
      const group = groupingFn?.({
        index: datumIndex,
        keys,
        values: void 0,
        aggValues: void 0,
        datum,
        validScopes: void 0
      }) ?? keys;
      const groupStr = toKeyString(group);
      if (invalidKeys?.[datumIndex] === true)
        continue;
      let validScopes;
      if (invalidDataScopes != null && invalidData?.[datumIndex] === true) {
        validScopes = /* @__PURE__ */ new Set();
        invalidDataScopes.forEach((invalidDatums, scope) => {
          if (invalidDatums[datumIndex] === false) {
            validScopes.add(scope);
          }
        });
        if (validScopes.size === 0)
          continue;
      }
      const existingGroup = groups.get(groupStr);
      if (existingGroup != null) {
        existingGroup.datumIndices.push(datumIndex);
        if (validScopes != null && existingGroup.validScopes != null) {
          for (const scope of existingGroup.validScopes) {
            if (!validScopes.has(scope)) {
              existingGroup.validScopes.delete(scope);
            }
          }
        }
      } else {
        groups.set(groupStr, {
          keys: group,
          datumIndices: [datumIndex],
          validScopes
        });
      }
    }
    const resultGroups = [];
    const resultData = [];
    for (const { keys, datumIndices, validScopes } of groups.values()) {
      if (validScopes?.size === 0)
        continue;
      resultGroups.push(keys);
      resultData.push({
        datumIndices,
        keys,
        aggregation: [],
        validScopes
      });
    }
    return {
      ...data,
      type: "grouped",
      domain: {
        ...data.domain,
        groups: resultGroups
      },
      groups: resultData
    };
  }
  aggregateData(processedData) {
    const domainAggValues = this.aggregates.map(() => [Infinity, -Infinity]);
    processedData.domain.aggValues = domainAggValues;
    const { keys, columns, rawData } = processedData;
    if (processedData.type === "ungrouped") {
      const resultAggregation = rawData.map((_datum, datumIndex) => {
        const aggregation = [];
        for (const [index, def] of this.aggregates.entries()) {
          const indices = this.valueGroupIdxLookup(def);
          let groupAggValues = def.groupAggregateFunction?.() ?? [Infinity, -Infinity];
          const valuesToAgg = indices.map((columnIndex) => columns[columnIndex][datumIndex]);
          const k = datumKeys(keys, datumIndex);
          const valuesAgg = k != null ? def.aggregateFunction(valuesToAgg, k) : void 0;
          if (valuesAgg) {
            groupAggValues = def.groupAggregateFunction?.(valuesAgg, groupAggValues) ?? ContinuousDomain.extendDomain(valuesAgg, groupAggValues);
          }
          const finalValues = (def.finalFunction?.(groupAggValues) ?? groupAggValues).map(
            (v) => round3(v)
          );
          aggregation[index] = finalValues;
          ContinuousDomain.extendDomain(finalValues, domainAggValues[index]);
        }
        return aggregation;
      });
      processedData.aggregation = resultAggregation;
    } else {
      for (const [index, def] of this.aggregates.entries()) {
        const indices = this.valueGroupIdxLookup(def);
        for (const group of processedData.groups) {
          group.aggregation ?? (group.aggregation = []);
          if (group.validScopes != null)
            continue;
          const groupKeys = group.keys;
          let groupAggValues = def.groupAggregateFunction?.() ?? [Infinity, -Infinity];
          for (const datumIndex of group.datumIndices) {
            const valuesToAgg = indices.map((columnIndex) => columns[columnIndex][datumIndex]);
            const valuesAgg = def.aggregateFunction(valuesToAgg, groupKeys);
            if (valuesAgg) {
              groupAggValues = def.groupAggregateFunction?.(valuesAgg, groupAggValues) ?? ContinuousDomain.extendDomain(valuesAgg, groupAggValues);
            }
          }
          const finalValues = (def.finalFunction?.(groupAggValues) ?? groupAggValues).map(
            (v) => round3(v)
          );
          group.aggregation[index] = finalValues;
          ContinuousDomain.extendDomain(finalValues, domainAggValues[index]);
        }
      }
    }
  }
  postProcessGroups(processedData) {
    const { groupProcessors } = this;
    const { rawData, columns, invalidData } = processedData;
    for (const processor of groupProcessors) {
      const valueIndexes = this.valueGroupIdxLookup(processor);
      const adjustFn = processor.adjust()();
      for (let datumIndex = 0; datumIndex < rawData.length; datumIndex += 1) {
        if (invalidData?.[datumIndex] === true)
          continue;
        adjustFn(columns, valueIndexes, datumIndex);
      }
      for (const valueIndex of valueIndexes) {
        const valueDef = this.values[valueIndex];
        const isDiscrete = valueDef.valueType === "category";
        const column = columns[valueIndex];
        const domain = isDiscrete ? new DiscreteDomain() : new ContinuousDomain();
        for (let datumIndex = 0; datumIndex < rawData.length; datumIndex += 1) {
          if (invalidData?.[datumIndex] === true)
            continue;
          domain.extend(column[datumIndex]);
        }
        processedData.domain.values[valueIndex] = domain.getDomain();
      }
    }
  }
  postProcessProperties(processedData) {
    for (const { adjust, property, scopes } of this.propertyProcessors) {
      for (const idx of this.valueIdxLookup(scopes, property)) {
        adjust()(processedData, idx);
      }
    }
  }
  reduceData(processedData) {
    processedData.reduced ?? (processedData.reduced = {});
    for (const def of this.reducers) {
      const reducer = def.reducer();
      let accValue = def.initialValue;
      const { rawData, keys, columns } = processedData;
      if (processedData.type === "grouped") {
        for (const group of processedData.groups) {
          if (!group.validScopes || def.scopes?.some((s) => group.validScopes?.has(s))) {
            accValue = reducer(accValue, {
              index: group.datumIndices,
              // Why is flatMap needed?
              keys: group.datumIndices.flatMap((datumIndex) => keys.map((k) => k[datumIndex])),
              values: group.datumIndices.map((datumIndex) => columns[datumIndex]),
              datum: group.datumIndices.map((datumIndex) => rawData[datumIndex])
            });
          }
        }
      } else {
        for (let datumIndex = 0; datumIndex < rawData.length; datumIndex += 1) {
          accValue = reducer(accValue, {
            index: [datumIndex],
            keys: keys.map((k) => k[datumIndex]),
            values: [columns[datumIndex]],
            datum: [rawData[datumIndex]]
          });
        }
      }
      processedData.reduced[def.property] = accValue;
    }
  }
  postProcessData(processedData) {
    processedData.reduced ?? (processedData.reduced = {});
    for (const def of this.processors) {
      processedData.reduced[def.property] = def.calculate(
        processedData,
        processedData.reduced[def.property]
      );
    }
  }
  initDataDomainProcessor() {
    const { keys: keyDefs, values: valueDefs } = this;
    const scopes = /* @__PURE__ */ new Set();
    for (const valueDef of valueDefs) {
      if (!valueDef.scopes)
        continue;
      for (const scope of valueDef.scopes) {
        scopes.add(scope);
      }
    }
    const dataDomain = /* @__PURE__ */ new Map();
    const processorFns = /* @__PURE__ */ new Map();
    let allScopesHaveSameDefs = true;
    const initDataDomain = () => {
      for (const def of iterate(keyDefs, valueDefs)) {
        if (def.valueType === "category") {
          dataDomain.set(def, new DiscreteDomain());
        } else {
          dataDomain.set(def, new ContinuousDomain());
          allScopesHaveSameDefs && (allScopesHaveSameDefs = (def.scopes ?? []).length === scopes.size);
        }
      }
    };
    initDataDomain();
    const accessors = this.buildAccessors(iterate(keyDefs, valueDefs));
    const processValue = (def, datum, idx, previousDatum, scope) => {
      let valueInDatum;
      let value;
      if (accessors.has(def.property)) {
        try {
          value = accessors.get(def.property)(datum);
        } catch {
        }
        valueInDatum = value != null;
      } else {
        valueInDatum = def.property in datum;
        value = valueInDatum ? datum[def.property] : def.missingValue;
      }
      if (def.forceValue != null) {
        const valueNegative = valueInDatum && isNegative(value);
        value = valueNegative ? -1 * def.forceValue : def.forceValue;
        valueInDatum = true;
      }
      const missingValueDef = "missingValue" in def;
      if (!valueInDatum && !missingValueDef) {
        const missCount = def.missing.get(scope) ?? 0;
        def.missing.set(scope, missCount + 1);
      }
      if (!dataDomain.has(def)) {
        initDataDomain();
      }
      if (valueInDatum && def.validation?.(value, datum, idx) === false) {
        if ("invalidValue" in def) {
          value = def.invalidValue;
        } else {
          if (this.mode !== "integrated") {
            Logger.warnOnce(
              `invalid value of type [${typeof value}] for [${def.scopes} / ${def.id}] ignored:`,
              `[${value}]`
            );
          }
          return INVALID_VALUE;
        }
      }
      if (def.processor) {
        if (!processorFns.has(def)) {
          processorFns.set(def, def.processor());
        }
        value = processorFns.get(def)?.(value, previousDatum === INVALID_VALUE ? void 0 : previousDatum);
      }
      dataDomain.get(def)?.extend(value);
      return value;
    };
    return { dataDomain, processValue, initDataDomain, scopes, allScopesHaveSameDefs };
  }
  buildAccessors(defs) {
    const result = /* @__PURE__ */ new Map();
    if (this.suppressFieldDotNotation) {
      return result;
    }
    for (const def of defs) {
      const isPath = def.property.includes(".") || def.property.includes("[");
      if (!isPath)
        continue;
      const components = getPathComponents(def.property);
      if (components == null) {
        Logger.warnOnce("Invalid property path [%s]", def.property);
        continue;
      }
      const accessor = createPathAccessor(components);
      result.set(def.property, accessor);
    }
    return result;
  }
};
function logProcessedData(processedData) {
  const logValues = (name, data) => {
    if (data.length > 0) {
      Logger.log(`DataModel.processData() - ${name}`);
      Logger.table(data);
    }
  };
  Logger.log("DataModel.processData() - processedData", processedData);
  logValues("Key Domains", processedData.domain.keys);
  logValues("Group Domains", processedData.domain.groups ?? []);
  logValues("Value Domains", processedData.domain.values);
  logValues("Aggregate Domains", processedData.domain.aggValues ?? []);
}
var _DataController = class _DataController2 {
  constructor(mode, suppressFieldDotNotation) {
    this.mode = mode;
    this.suppressFieldDotNotation = suppressFieldDotNotation;
    this.debug = Debug.create(true, "data-model");
    this.requested = [];
    this.status = "setup";
  }
  async request(id, data, opts) {
    if (this.status !== "setup") {
      throw new Error(`AG Charts - data request after data setup phase.`);
    }
    return new Promise((resolve, reject) => {
      this.requested.push({ id, opts, data, resolve, reject });
    });
  }
  execute(cachedData) {
    if (this.status !== "setup") {
      throw new Error(`AG Charts - data request after data setup phase.`);
    }
    this.status = "executed";
    this.debug("DataController.execute() - requested", this.requested);
    const valid = this.validateRequests(this.requested);
    this.debug("DataController.execute() - validated", valid);
    const merged = this.mergeRequested(valid);
    this.debug("DataController.execute() - merged", merged);
    if (this.debug.check()) {
      getWindow().processedData = [];
    }
    const nextCachedData = [];
    for (const { data, ids, opts, resolves, rejects } of merged) {
      const reusableCache = cachedData?.find((cacheItem) => canReuseCachedData(cacheItem, data, ids, opts));
      let dataModel;
      let processedData;
      if (reusableCache == null) {
        try {
          dataModel = new DataModel(opts, this.mode, this.suppressFieldDotNotation);
          processedData = dataModel.processData(data, valid);
        } catch (error) {
          rejects.forEach((cb) => cb(error));
          continue;
        }
      } else {
        ({ dataModel, processedData } = reusableCache);
      }
      nextCachedData.push({ opts, data, ids, dataModel, processedData });
      if (this.debug.check()) {
        getWindow("processedData").push(processedData);
      }
      if (processedData?.partialValidDataCount === 0) {
        resolves.forEach(
          (resolve) => resolve({
            dataModel,
            processedData
          })
        );
      } else if (processedData) {
        this.splitResult(dataModel, processedData, ids, resolves);
      } else {
        rejects.forEach((cb) => cb(new Error(`AG Charts - no processed data generated`)));
      }
    }
    return nextCachedData;
  }
  validateRequests(requested) {
    const valid = [];
    for (const [index, request] of requested.entries()) {
      if (index > 0 && request.data.length !== requested[0].data.length && request.opts.groupByData === false) {
        request.reject(
          new Error("all series[].data arrays must be of the same length and have matching keys.")
        );
      } else {
        valid.push(request);
      }
    }
    return valid;
  }
  mergeRequested(requested) {
    const grouped = [];
    for (const request of requested) {
      const match = grouped.find(_DataController2.groupMatch(request));
      if (match) {
        match.push(request);
      } else {
        grouped.push([request]);
      }
    }
    return grouped.map(_DataController2.mergeRequests);
  }
  splitResult(dataModel, processedData, scopes, resolves) {
    for (let i = 0; i < scopes.length; i++) {
      const resolve = resolves[i];
      resolve({
        dataModel,
        processedData
      });
    }
  }
  static groupMatch({ data, opts }) {
    function keys(props2) {
      return props2.filter((p) => p.type === "key").map((p) => p.property).join(";");
    }
    const { groupByData, groupByKeys = false, groupByFn, props } = opts;
    const propsKeys = keys(props);
    return ([group]) => (groupByData === false || group.data === data) && (group.opts.groupByKeys ?? false) === groupByKeys && group.opts.groupByFn === groupByFn && keys(group.opts.props) === propsKeys;
  }
  static mergeRequests(requests) {
    return requests.reduce(
      (result, { id, data, resolve, reject, opts: { props, ...opts } }) => {
        result.ids.push(id);
        result.rejects.push(reject);
        result.resolves.push(resolve);
        result.data ?? (result.data = data);
        result.opts ?? (result.opts = { ...opts, props: [] });
        for (const prop of props) {
          const clone2 = { ...prop, scopes: [id] };
          _DataController2.createIdsMap(id, clone2);
          const match = result.opts.props.find(
            (existing) => existing.type === clone2.type && _DataController2.deepEqual(existing, clone2)
          );
          if (!match) {
            result.opts.props.push(clone2);
            continue;
          }
          match.scopes ?? (match.scopes = []);
          match.scopes.push(...clone2.scopes ?? []);
          if ((match.type === "key" || match.type === "value") && clone2.idsMap?.size) {
            _DataController2.mergeIdsMap(clone2.idsMap, match.idsMap);
          }
        }
        return result;
      },
      { ids: [], rejects: [], resolves: [], data: null, opts: null }
    );
  }
  static mergeIdsMap(fromMap, toMap) {
    for (const [scope, ids] of fromMap) {
      const toMapValue = toMap.get(scope);
      if (toMapValue == null) {
        toMap.set(scope, new Set(ids));
      } else {
        for (const id of ids) {
          toMapValue.add(id);
        }
      }
    }
  }
  static createIdsMap(scope, prop) {
    if (prop.id == null)
      return;
    prop.idsMap ?? (prop.idsMap = /* @__PURE__ */ new Map());
    if (prop.idsMap.has(scope)) {
      prop.idsMap.get(scope).add(prop.id);
    } else {
      prop.idsMap.set(scope, /* @__PURE__ */ new Set([prop.id]));
    }
  }
  static deepEqual(a, b) {
    if (a === b) {
      return true;
    }
    if (a && b && typeof a == "object" && typeof b == "object") {
      if (a.constructor !== b.constructor) {
        return false;
      }
      let i, length2;
      if (Array.isArray(a)) {
        length2 = a.length;
        if (length2 !== b.length) {
          return false;
        }
        for (i = length2 - 1; i >= 0; i--) {
          if (!_DataController2.deepEqual(a[i], b[i])) {
            return false;
          }
        }
        return true;
      }
      const keys = Object.keys(a);
      length2 = keys.length;
      if (length2 !== Object.keys(b).length) {
        return false;
      }
      for (i = length2 - 1; i >= 0; i--) {
        const key = keys[i];
        if (!_DataController2.skipKeys.has(key) && (!Object.hasOwn(b, key) || !_DataController2.deepEqual(a[key], b[key]))) {
          return false;
        }
      }
      return true;
    }
    return false;
  }
};
_DataController.skipKeys = /* @__PURE__ */ new Set(["id", "idsMap", "type", "scopes"]);
var DataController = _DataController;
var AxisRegistry = class {
  constructor() {
    this.axesMap = /* @__PURE__ */ new Map();
    this.hidden = /* @__PURE__ */ new Set();
    this.themeTemplates = /* @__PURE__ */ new Map();
  }
  register(axisType, module2) {
    this.axesMap.set(axisType, module2.moduleFactory);
    if (module2.themeTemplate) {
      this.setThemeTemplate(axisType, module2.themeTemplate);
    }
    if (module2.hidden) {
      this.hidden.add(axisType);
    }
  }
  create(axisType, moduleContext) {
    const axisFactory = this.axesMap.get(axisType);
    if (axisFactory) {
      return axisFactory(moduleContext);
    }
    throw new Error(`AG Charts - unknown axis type: ${axisType}`);
  }
  has(axisType) {
    return this.axesMap.has(axisType);
  }
  keys() {
    return this.axesMap.keys();
  }
  publicKeys() {
    return [...this.keys()].filter((k) => !this.hidden.has(k));
  }
  setThemeTemplate(axisType, themeTemplate) {
    this.themeTemplates.set(axisType, themeTemplate);
    return this;
  }
  getThemeTemplate(axisType) {
    return this.themeTemplates.get(axisType);
  }
};
var axisRegistry = new AxisRegistry();
var EXPECTED_ENTERPRISE_MODULES = [
  {
    type: "root",
    optionsKey: "animation",
    chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"]
  },
  { type: "root", optionsKey: "annotations", chartTypes: ["cartesian"] },
  {
    type: "root",
    optionsKey: "background",
    chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"],
    optionsInnerKey: "image"
  },
  {
    type: "root",
    optionsKey: "foreground",
    chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"],
    optionsInnerKey: "image"
  },
  {
    type: "root",
    optionsKey: "chartToolbar",
    chartTypes: ["cartesian"]
  },
  {
    type: "root",
    optionsKey: "contextMenu",
    chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"]
  },
  { type: "root", optionsKey: "statusBar", chartTypes: ["cartesian"], identifier: "status-bar" },
  {
    type: "root",
    optionsKey: "dataSource",
    chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"]
  },
  { type: "root", optionsKey: "sync", chartTypes: ["cartesian"] },
  { type: "root", optionsKey: "zoom", chartTypes: ["cartesian", "topology"] },
  { type: "root", optionsKey: "ranges", chartTypes: ["cartesian"] },
  {
    type: "legend",
    optionsKey: "gradientLegend",
    chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"],
    identifier: "gradient"
  },
  { type: "root", optionsKey: "navigator", chartTypes: ["cartesian"] },
  { type: "axis", optionsKey: "axes[]", chartTypes: ["polar"], identifier: "angle-category" },
  { type: "axis", optionsKey: "axes[]", chartTypes: ["polar"], identifier: "angle-number" },
  { type: "axis", optionsKey: "axes[]", chartTypes: ["polar"], identifier: "radius-category" },
  { type: "axis", optionsKey: "axes[]", chartTypes: ["polar"], identifier: "radius-number" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "bar", community: true },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "line", community: true },
  { type: "axis", optionsKey: "axes[]", chartTypes: ["cartesian"], identifier: "ordinal-time" },
  { type: "axis-option", optionsKey: "crosshair", chartTypes: ["cartesian"] },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "box-plot" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "candlestick" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "cone-funnel" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "funnel" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "ohlc" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "heatmap" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "range-area" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "range-bar" },
  { type: "series", optionsKey: "series[]", chartTypes: ["cartesian"], identifier: "waterfall" },
  { type: "series", optionsKey: "series[]", chartTypes: ["polar"], identifier: "nightingale" },
  { type: "series", optionsKey: "series[]", chartTypes: ["polar"], identifier: "radar-area" },
  { type: "series", optionsKey: "series[]", chartTypes: ["polar"], identifier: "radar-line" },
  { type: "series", optionsKey: "series[]", chartTypes: ["polar"], identifier: "radial-bar" },
  { type: "series", optionsKey: "series[]", chartTypes: ["polar"], identifier: "radial-column" },
  { type: "series", optionsKey: "series[]", chartTypes: ["hierarchy"], identifier: "sunburst" },
  { type: "series", optionsKey: "series[]", chartTypes: ["hierarchy"], identifier: "treemap" },
  { type: "series", optionsKey: "series[]", chartTypes: ["topology"], identifier: "map-shape" },
  { type: "series", optionsKey: "series[]", chartTypes: ["topology"], identifier: "map-line" },
  { type: "series", optionsKey: "series[]", chartTypes: ["topology"], identifier: "map-marker" },
  { type: "series", optionsKey: "series[]", chartTypes: ["topology"], identifier: "map-shape-background" },
  { type: "series", optionsKey: "series[]", chartTypes: ["topology"], identifier: "map-line-background" },
  { type: "series", optionsKey: "series[]", chartTypes: ["flow-proportion"], identifier: "chord" },
  { type: "series", optionsKey: "series[]", chartTypes: ["flow-proportion"], identifier: "sankey" },
  { type: "series", optionsKey: "series[]", chartTypes: ["standalone"], identifier: "pyramid" },
  { type: "series", optionsKey: "series[]", chartTypes: ["gauge"], identifier: "linear-gauge" },
  { type: "series", optionsKey: "series[]", chartTypes: ["gauge"], identifier: "radial-gauge" },
  { type: "series-option", optionsKey: "errorBar", chartTypes: ["cartesian"], identifier: "error-bars" },
  { type: "context", contextKey: "sharedToolbar", chartTypes: ["cartesian"] }
];
function isEnterpriseSeriesType(type) {
  return EXPECTED_ENTERPRISE_MODULES.some((s) => s.type === "series" && s.identifier === type);
}
function getEnterpriseSeriesChartTypes(type) {
  return EXPECTED_ENTERPRISE_MODULES.find((s) => s.type === "series" && s.identifier === type)?.chartTypes;
}
function isEnterpriseCartesian(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "cartesian");
  return type === "cartesian";
}
function isEnterprisePolar(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "polar");
  return type === "polar";
}
function isEnterpriseHierarchy(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "hierarchy");
  return type === "hierarchy";
}
function isEnterpriseTopology(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "topology");
  return type === "topology";
}
function isEnterpriseFlowProportion(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "flow-proportion");
  return type === "flow-proportion";
}
function isEnterpriseStandalone(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "standalone");
  return type === "standalone";
}
function isEnterpriseGauge(seriesType) {
  const type = getEnterpriseSeriesChartTypes(seriesType)?.find((v) => v === "gauge");
  return type === "gauge";
}
function isEnterpriseModule(module2) {
  return module2.packageType === "enterprise";
}
function verifyIfModuleExpected(module2) {
  if (!isEnterpriseModule(module2)) {
    throw new Error("AG Charts - internal configuration error, only enterprise modules need verification.");
  }
  const stub = EXPECTED_ENTERPRISE_MODULES.find((s) => {
    return s.type === module2.type && ("optionsKey" in s && "optionsKey" in module2 ? s.optionsKey === module2.optionsKey : true) && ("contextKey" in s && "contextKey" in module2 ? s.contextKey === module2.contextKey : true) && s.identifier === module2.identifier && module2.chartTypes.every((t) => s.chartTypes.includes(t));
  });
  if (stub) {
    stub.useCount ?? (stub.useCount = 0);
    stub.useCount++;
  }
  return stub != null;
}
function getUnusedExpectedModules() {
  return EXPECTED_ENTERPRISE_MODULES.filter(({ useCount }) => useCount == null || useCount === 0);
}
var LegendRegistry = class {
  constructor() {
    this.legendMap = /* @__PURE__ */ new Map();
    this.themeTemplates = /* @__PURE__ */ new Map();
  }
  register(legendType, { optionsKey, moduleFactory, themeTemplate }) {
    this.legendMap.set(legendType, { optionsKey, moduleFactory });
    this.themeTemplates.set(optionsKey, themeTemplate);
  }
  create(legendType, moduleContext) {
    const legendFactory = this.legendMap.get(legendType)?.moduleFactory;
    if (legendFactory) {
      return legendFactory(moduleContext);
    }
    throw new Error(`AG Charts - unknown legend type: ${legendType}`);
  }
  getThemeTemplates() {
    return Object.fromEntries(this.themeTemplates);
  }
  getKeys() {
    return Array.from(this.legendMap.entries()).reduce(
      (result, [legendType, record]) => {
        result[legendType] = record.optionsKey;
        return result;
      },
      {}
    );
  }
};
var legendRegistry = new LegendRegistry();
var ChartTypes = class extends Map {
  get(seriesType) {
    return super.get(seriesType) ?? "unknown";
  }
  isCartesian(seriesType) {
    return this.get(seriesType) === "cartesian";
  }
  isPolar(seriesType) {
    return this.get(seriesType) === "polar";
  }
  isHierarchy(seriesType) {
    return this.get(seriesType) === "hierarchy";
  }
  isTopology(seriesType) {
    return this.get(seriesType) === "topology";
  }
  isFlowProportion(seriesType) {
    return this.get(seriesType) === "flow-proportion";
  }
  isStandalone(seriesType) {
    return this.get(seriesType) === "standalone";
  }
  isGauge(seriesType) {
    return this.get(seriesType) === "gauge";
  }
  get seriesTypes() {
    return Array.from(this.keys());
  }
  get cartesianTypes() {
    return this.seriesTypes.filter((t) => this.isCartesian(t));
  }
  get polarTypes() {
    return this.seriesTypes.filter((t) => this.isPolar(t));
  }
  get hierarchyTypes() {
    return this.seriesTypes.filter((t) => this.isHierarchy(t));
  }
  get topologyTypes() {
    return this.seriesTypes.filter((t) => this.isTopology(t));
  }
  get flowProportionTypes() {
    return this.seriesTypes.filter((t) => this.isFlowProportion(t));
  }
  get standaloneTypes() {
    return this.seriesTypes.filter((t) => this.isStandalone(t));
  }
  get gaugeTypes() {
    return this.seriesTypes.filter((t) => this.isGauge(t));
  }
};
var ChartDefaults = class extends Map {
  set(chartType2, defaults) {
    return super.set(chartType2, mergeDefaults(defaults, this.get(chartType2)));
  }
};
var chartTypes2 = new ChartTypes();
var publicChartTypes = new ChartTypes();
var chartDefaults = new ChartDefaults();
var SeriesRegistry = class {
  constructor() {
    this.seriesMap = /* @__PURE__ */ new Map();
    this.themeTemplates = /* @__PURE__ */ new Map();
  }
  register(seriesType, {
    chartTypes: [chartType2],
    moduleFactory,
    tooltipDefaults: tooltipDefaults2,
    defaultAxes,
    themeTemplate,
    paletteFactory,
    solo,
    stackable,
    groupable,
    stackedByDefault,
    hidden
  }) {
    this.setThemeTemplate(seriesType, themeTemplate);
    this.seriesMap.set(seriesType, {
      moduleFactory,
      tooltipDefaults: tooltipDefaults2,
      defaultAxes,
      paletteFactory,
      solo,
      stackable,
      groupable,
      stackedByDefault
    });
    chartTypes2.set(seriesType, chartType2);
    if (!hidden) {
      publicChartTypes.set(seriesType, chartType2);
    }
  }
  create(seriesType, moduleContext) {
    const seriesFactory = this.seriesMap.get(seriesType)?.moduleFactory;
    if (seriesFactory) {
      return seriesFactory(moduleContext);
    }
    throw new Error(`AG Charts - unknown series type: ${seriesType}`);
  }
  cloneDefaultAxes(seriesType, options) {
    const defaultAxes = this.seriesMap.get(seriesType)?.defaultAxes;
    if (defaultAxes == null)
      return null;
    const axes = typeof defaultAxes === "function" ? defaultAxes(options) : defaultAxes;
    return { axes: deepClone(axes) };
  }
  setThemeTemplate(seriesType, themeTemplate) {
    const currentTemplate = this.themeTemplates.get(seriesType);
    this.themeTemplates.set(seriesType, mergeDefaults(themeTemplate, currentTemplate));
  }
  getThemeTemplate(seriesType) {
    return this.themeTemplates.get(seriesType);
  }
  getPaletteFactory(seriesType) {
    return this.seriesMap.get(seriesType)?.paletteFactory;
  }
  getTooltipDefauls(seriesType) {
    return this.seriesMap.get(seriesType)?.tooltipDefaults;
  }
  isSolo(seriesType) {
    return this.seriesMap.get(seriesType)?.solo ?? false;
  }
  isGroupable(seriesType) {
    return this.seriesMap.get(seriesType)?.groupable ?? false;
  }
  isStackable(seriesType) {
    return this.seriesMap.get(seriesType)?.stackable ?? false;
  }
  isStackedByDefault(seriesType) {
    return this.seriesMap.get(seriesType)?.stackedByDefault ?? false;
  }
};
var seriesRegistry = new SeriesRegistry();
var _SyncManager = class _SyncManager2 extends BaseManager {
  constructor(chart) {
    super();
    this.chart = chart;
  }
  subscribe(groupId = _SyncManager2.DEFAULT_GROUP) {
    let syncGroup = this.get(groupId);
    if (!syncGroup) {
      syncGroup = /* @__PURE__ */ new Set();
      _SyncManager2.chartsGroups.set(groupId, syncGroup);
    }
    syncGroup.add(this.chart);
    return this;
  }
  unsubscribe(groupId = _SyncManager2.DEFAULT_GROUP) {
    this.get(groupId)?.delete(this.chart);
    return this;
  }
  getChart() {
    return this.chart;
  }
  getGroup(groupId = _SyncManager2.DEFAULT_GROUP) {
    const syncGroup = this.get(groupId);
    return syncGroup ? Array.from(syncGroup) : [];
  }
  getGroupSiblings(groupId = _SyncManager2.DEFAULT_GROUP) {
    return this.getGroup(groupId).filter((chart) => chart !== this.chart);
  }
  get(groupId) {
    return _SyncManager2.chartsGroups.get(groupId);
  }
};
_SyncManager.chartsGroups = /* @__PURE__ */ new Map();
_SyncManager.DEFAULT_GROUP = Symbol("sync-group-default");
var SyncManager = _SyncManager;
var Keyboard = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = false;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], Keyboard.prototype, "enabled", 2);
__decorateClass([
  Validate(NUMBER)
], Keyboard.prototype, "tabIndex", 2);
var CartesianAxisPositions = ["top", "right", "bottom", "left"];
function isAxisPosition(position) {
  return typeof position === "string" && CartesianAxisPositions.includes(position);
}
function guessInvalidPositions(axes) {
  const invalidAxes = [];
  const usedPositions = [];
  const guesses = [...CartesianAxisPositions];
  for (const axis of axes) {
    if (axis instanceof CartesianAxis) {
      if (isAxisPosition(axis.position)) {
        usedPositions.push(axis.position);
      } else {
        invalidAxes.push(axis);
      }
    }
  }
  for (const axis of invalidAxes) {
    let nextGuess;
    do {
      nextGuess = guesses.pop();
    } while (nextGuess && usedPositions.includes(nextGuess));
    if (nextGuess == null)
      break;
    axis.position = nextGuess;
  }
}
var MATCHING_KEYS = ["direction", "xKey", "yKey", "sizeKey", "angleKey", "radiusKey", "normalizedTo"];
function matchSeriesOptions(series, optSeries, oldOptsSeries) {
  const generateKey = (type, i, opts) => {
    const result = [type];
    for (const key of MATCHING_KEYS) {
      if (key in i && i[key] != null)
        result.push(`${key}=${i[key]}`);
    }
    if (opts?.seriesGrouping) {
      result.push(`seriesGrouping.groupId=${opts?.seriesGrouping.groupId}`);
    }
    return result.join(";");
  };
  const seriesMap = /* @__PURE__ */ new Map();
  let idx = 0;
  for (const s of series) {
    const key = generateKey(s.type, s.properties, oldOptsSeries?.[idx]);
    if (!seriesMap.has(key)) {
      seriesMap.set(key, []);
    }
    seriesMap.get(key)?.push([s, idx++]);
  }
  const optsMap = /* @__PURE__ */ new Map();
  idx = 0;
  for (const o of optSeries) {
    const key = generateKey(o.type, o, o);
    if (!optsMap.has(key)) {
      optsMap.set(key, []);
    }
    optsMap.get(key)?.push([o, idx++]);
  }
  const overlap = [...seriesMap.keys()].some((k) => optsMap.has(k));
  if (!overlap) {
    return { status: "no-overlap", oldKeys: seriesMap.keys(), newKeys: optsMap.keys() };
  }
  const changes = [];
  for (const [key, optsTuples] of optsMap.entries()) {
    for (const [opts, targetIdx] of optsTuples) {
      const seriesArray = seriesMap.get(key);
      if (seriesArray == null || seriesArray.length < 1) {
        changes.push({ opts, targetIdx, idx: targetIdx, status: "add" });
        seriesMap.delete(key);
        continue;
      }
      const [outputSeries, currentIdx] = seriesArray.shift();
      const previousOpts = oldOptsSeries?.[currentIdx] ?? {};
      const diff2 = jsonDiff(previousOpts, opts ?? {});
      const { groupIndex, stackIndex } = diff2?.seriesGrouping ?? {};
      if (groupIndex != null || stackIndex != null) {
        changes.push({
          opts,
          series: outputSeries,
          diff: diff2,
          targetIdx,
          idx: currentIdx,
          status: "series-grouping"
        });
      } else if (diff2) {
        changes.push({
          opts,
          series: outputSeries,
          diff: diff2,
          targetIdx,
          idx: currentIdx,
          status: "update"
        });
      } else {
        changes.push({ opts, series: outputSeries, targetIdx, idx: currentIdx, status: "no-op" });
      }
      if (seriesArray.length === 0) {
        seriesMap.delete(key);
      }
    }
  }
  for (const seriesArray of seriesMap.values()) {
    for (const [outputSeries, currentIdx] of seriesArray) {
      changes.push({ series: outputSeries, idx: currentIdx, targetIdx: -1, status: "remove" });
    }
  }
  return { status: "overlap", changes };
}
function optionsType(input) {
  const { series } = input;
  if (!series)
    return;
  return series[0]?.type ?? "line";
}
function isAgCartesianChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isCartesian(specifiedType) || isEnterpriseCartesian(specifiedType);
}
function isAgPolarChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isPolar(specifiedType) || isEnterprisePolar(specifiedType);
}
function isAgHierarchyChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isHierarchy(specifiedType) || isEnterpriseHierarchy(specifiedType);
}
function isAgTopologyChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isTopology(specifiedType) || isEnterpriseTopology(specifiedType);
}
function isAgFlowProportionChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isFlowProportion(specifiedType) || isEnterpriseFlowProportion(specifiedType);
}
function isAgStandaloneChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isStandalone(specifiedType) || isEnterpriseStandalone(specifiedType);
}
function isAgGaugeChartOptions(input) {
  const specifiedType = optionsType(input);
  if (specifiedType == null) {
    return false;
  }
  return chartTypes2.isGauge(specifiedType) || isEnterpriseGauge(specifiedType);
}
function isAgPolarChartOptionsWithSeriesBasedLegend(input) {
  const specifiedType = optionsType(input);
  return isAgPolarChartOptions(input) && specifiedType !== "pie" && specifiedType !== "donut";
}
function isSeriesOptionType(input) {
  if (input == null) {
    return false;
  }
  return chartTypes2.has(input);
}
function isAxisOptionType(input) {
  if (input == null) {
    return false;
  }
  return axisRegistry.has(input);
}
var ModulesManager = class extends ModuleMap {
  applyOptions(options) {
    for (const m of this.moduleMap.values()) {
      if (m.module.optionsKey in options && isProperties(m.moduleInstance)) {
        m.moduleInstance.set(options[m.module.optionsKey]);
      }
    }
  }
  *legends() {
    for (const { module: module2, moduleInstance } of this.moduleMap.values()) {
      if (module2.type !== "legend")
        continue;
      yield {
        legendType: module2.identifier,
        legend: moduleInstance
      };
    }
  }
};
var DEFAULT_OVERLAY_CLASS = "ag-charts-overlay";
var DEFAULT_OVERLAY_DARK_CLASS = "ag-charts-dark-overlay";
var Overlay = class extends BaseProperties {
  constructor(className, defaultMessageId) {
    super();
    this.className = className;
    this.defaultMessageId = defaultMessageId;
    this.enabled = true;
  }
  getText(localeManager) {
    return localeManager.t(this.text ?? this.defaultMessageId);
  }
  getElement(animationManager, localeManager, rect) {
    this.content?.remove();
    this.focusBox = rect;
    if (this.renderer) {
      const htmlContent = this.renderer();
      if (htmlContent instanceof HTMLElement) {
        this.content = htmlContent;
      } else {
        const tempDiv = createElement("div");
        tempDiv.innerHTML = htmlContent;
        this.content = tempDiv.firstElementChild;
      }
    } else {
      const content = createElement("div", {
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        boxSizing: "border-box",
        height: "100%",
        margin: "8px",
        font: "12px Verdana, sans-serif"
      });
      content.innerText = this.getText(localeManager);
      this.content = content;
      animationManager?.animate({
        from: 0,
        to: 1,
        id: "overlay",
        phase: "add",
        groupId: "opacity",
        onUpdate(value) {
          content.style.opacity = String(value);
        },
        onStop() {
          content.style.opacity = "1";
        }
      });
    }
    return this.content;
  }
  removeElement(cleanup = () => this.content?.remove(), animationManager) {
    if (!this.content)
      return;
    if (animationManager) {
      const { content } = this;
      animationManager.animate({
        from: 1,
        to: 0,
        phase: "remove",
        id: "overlay",
        groupId: "opacity",
        onUpdate(value) {
          content.style.opacity = String(value);
        },
        onStop() {
          cleanup?.();
        }
      });
    } else {
      cleanup?.();
    }
    this.content = void 0;
    this.focusBox = void 0;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], Overlay.prototype, "enabled", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], Overlay.prototype, "text", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], Overlay.prototype, "renderer", 2);
var ChartOverlays = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.darkTheme = false;
    this.loading = new Overlay("ag-charts-loading-overlay", "overlayLoadingData");
    this.noData = new Overlay("ag-charts-no-data-overlay", "overlayNoData");
    this.noVisibleSeries = new Overlay("ag-charts-no-visible-series", "overlayNoVisibleSeries");
    this.unsupportedBrowser = new Overlay("ag-charts-unsupported-browser", "overlayUnsupportedBrowser");
  }
  getFocusInfo(localeManager) {
    for (const overlay of [this.loading, this.noData, this.noVisibleSeries, this.unsupportedBrowser]) {
      if (overlay.focusBox !== void 0) {
        return { text: overlay.getText(localeManager), rect: overlay.focusBox };
      }
    }
    return void 0;
  }
  destroy() {
    this.loading.removeElement();
    this.noData.removeElement();
    this.noVisibleSeries.removeElement();
    this.unsupportedBrowser.removeElement();
  }
};
__decorateClass([
  Validate(BOOLEAN)
], ChartOverlays.prototype, "darkTheme", 2);
__decorateClass([
  Validate(OBJECT)
], ChartOverlays.prototype, "loading", 2);
__decorateClass([
  Validate(OBJECT)
], ChartOverlays.prototype, "noData", 2);
__decorateClass([
  Validate(OBJECT)
], ChartOverlays.prototype, "noVisibleSeries", 2);
__decorateClass([
  Validate(OBJECT)
], ChartOverlays.prototype, "unsupportedBrowser", 2);
function getLoadingSpinner(text, defaultDuration) {
  const { animationDuration } = PHASE_METADATA["add"];
  const duration = animationDuration * defaultDuration;
  const container = createElement("div", `${DEFAULT_OVERLAY_CLASS}--loading`, {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    flexDirection: "column",
    height: "100%",
    boxSizing: "border-box",
    font: "13px Verdana, sans-serif",
    // FONT_SIZE.MEDIUM
    userSelect: "none",
    animation: `ag-charts-loading ${duration}ms linear 50ms both`
  });
  const matrix = createElement("span", {
    width: "45px",
    height: "40px",
    backgroundImage: [
      "linear-gradient(#0000 calc(1 * 100% / 6), #ccc 0 calc(3 * 100% / 6), #0000 0), ",
      "linear-gradient(#0000 calc(2 * 100% / 6), #ccc 0 calc(4 * 100% / 6), #0000 0), ",
      "linear-gradient(#0000 calc(3 * 100% / 6), #ccc 0 calc(5 * 100% / 6), #0000 0)"
    ].join(""),
    backgroundSize: "10px 400%",
    backgroundRepeat: "no-repeat",
    animation: "ag-charts-loading-matrix 1s infinite linear"
  });
  const label = createElement("p", { marginTop: "1em" });
  label.innerText = text;
  const background = createElement("div", `${DEFAULT_OVERLAY_CLASS}__loading-background`, {
    position: "absolute",
    inset: "0",
    opacity: "0.5",
    zIndex: "-1"
  });
  const animationStyles = createElement("style");
  animationStyles.innerText = [
    "@keyframes ag-charts-loading { from { opacity: 0 } to { opacity: 1 } }",
    "@keyframes ag-charts-loading-matrix {",
    "0% { background-position: 0% 0%, 50% 0%, 100% 0%; }",
    "100% { background-position: 0% 100%, 50% 100%, 100% 100%; }",
    "}"
  ].join(" ");
  container.replaceChildren(animationStyles, matrix, label, background);
  return container;
}
var SeriesZIndexMap = /* @__PURE__ */ ((SeriesZIndexMap2) => {
  SeriesZIndexMap2[SeriesZIndexMap2["BACKGROUND"] = 0] = "BACKGROUND";
  SeriesZIndexMap2[SeriesZIndexMap2["ANY_CONTENT"] = 1] = "ANY_CONTENT";
  return SeriesZIndexMap2;
})(SeriesZIndexMap || {});
var SeriesContentZIndexMap = /* @__PURE__ */ ((SeriesContentZIndexMap2) => {
  SeriesContentZIndexMap2[SeriesContentZIndexMap2["FOREGROUND"] = 0] = "FOREGROUND";
  SeriesContentZIndexMap2[SeriesContentZIndexMap2["HIGHLIGHT"] = 1] = "HIGHLIGHT";
  SeriesContentZIndexMap2[SeriesContentZIndexMap2["LABEL"] = 2] = "LABEL";
  return SeriesContentZIndexMap2;
})(SeriesContentZIndexMap || {});
var SeriesNodePickMode = /* @__PURE__ */ ((SeriesNodePickMode2) => {
  SeriesNodePickMode2[SeriesNodePickMode2["EXACT_SHAPE_MATCH"] = 0] = "EXACT_SHAPE_MATCH";
  SeriesNodePickMode2[SeriesNodePickMode2["NEAREST_NODE"] = 1] = "NEAREST_NODE";
  SeriesNodePickMode2[SeriesNodePickMode2["AXIS_ALIGNED"] = 2] = "AXIS_ALIGNED";
  return SeriesNodePickMode2;
})(SeriesNodePickMode || {});
var CROSS_FILTER_MARKER_FILL_OPACITY_FACTOR = 0.25;
var CROSS_FILTER_MARKER_STROKE_OPACITY_FACTOR = 0.125;
var SeriesNodeEvent = class {
  constructor(type, event, { datum }, series) {
    this.type = type;
    this.event = event;
    this.datum = datum;
    this.seriesId = series.id;
  }
};
var SeriesGroupingChangedEvent = class {
  constructor(series, seriesGrouping, oldGrouping) {
    this.series = series;
    this.seriesGrouping = seriesGrouping;
    this.oldGrouping = oldGrouping;
    this.type = "groupingChanged";
  }
};
var Series = class extends Observable {
  constructor(seriesOpts) {
    super();
    this.destroyFns = [];
    this.usesPlacedLabels = false;
    this.seriesGrouping = void 0;
    this.NodeEvent = SeriesNodeEvent;
    this.internalId = createId(this);
    this.contentGroup = new TranslatableGroup({
      name: `${this.internalId}-content`,
      zIndex: 1
      /* ANY_CONTENT */
    });
    this.highlightGroup = new TranslatableGroup({
      name: `${this.internalId}-highlight`,
      zIndex: 1
      /* ANY_CONTENT */
    });
    this.annotationGroup = new TranslatableGroup({
      name: `${this.internalId}-annotation`
    });
    this.labelGroup = new TranslatableGroup({
      name: `${this.internalId}-series-labels`
    });
    this.axes = {
      [
        "x"
        /* X */
      ]: void 0,
      [
        "y"
        /* Y */
      ]: void 0
    };
    this.directions = [
      "x",
      "y"
      /* Y */
    ];
    this.nodeDataRefresh = true;
    this.moduleMap = new ModuleMap();
    this.datumCallbackCache = /* @__PURE__ */ new Map();
    this.connectsToYAxis = false;
    this._declarationOrder = -1;
    this.seriesListeners = new Listeners();
    this._pickNodeCache = new LRUCache();
    const {
      moduleCtx,
      pickModes,
      directionKeys = {},
      directionNames = {},
      canHaveAxes = false,
      usesPlacedLabels = false
    } = seriesOpts;
    this.ctx = moduleCtx;
    this.directionKeys = directionKeys;
    this.directionNames = directionNames;
    this.canHaveAxes = canHaveAxes;
    this.usesPlacedLabels = usesPlacedLabels;
    this.highlightGroup = new TranslatableGroup({
      name: `${this.internalId}-highlight`
    });
    this.highlightNode = this.highlightGroup.appendChild(new Group({ name: "highlightNode", zIndex: 0 }));
    this.highlightLabel = this.highlightGroup.appendChild(new Group({ name: "highlightLabel", zIndex: 10 }));
    this.pickModes = pickModes;
  }
  get pickModeAxis() {
    return "main";
  }
  get id() {
    return this.properties?.id ?? this.internalId;
  }
  get type() {
    return this.constructor.type ?? "";
  }
  get data() {
    return this._data ?? this._chartData;
  }
  set visible(newVisibility) {
    this.properties.visible = newVisibility;
    this.ctx.legendManager.toggleItem({ enabled: newVisibility, seriesId: this.id });
    this.ctx.legendManager.update();
    this.visibleMaybeChanged();
  }
  get visible() {
    return this.ctx.legendManager.getSeriesEnabled(this.id) ?? this.properties.visible;
  }
  get hasData() {
    return this.data != null && this.data.length > 0;
  }
  get tooltipEnabled() {
    return this.properties.tooltip?.enabled ?? false;
  }
  onDataChange() {
    this.nodeDataRefresh = true;
    this._pickNodeCache.clear();
  }
  setOptionsData(input) {
    this._data = input;
    this.onDataChange();
  }
  setChartData(input) {
    this._chartData = input;
    if (this.data === input) {
      this.onDataChange();
    }
  }
  onSeriesGroupingChange(prev, next) {
    const { internalId, type, visible } = this;
    if (prev) {
      this.ctx.seriesStateManager.deregisterSeries(this);
    }
    if (next) {
      this.ctx.seriesStateManager.registerSeries({ internalId, type, visible, seriesGrouping: next });
    }
    this.fireEvent(new SeriesGroupingChangedEvent(this, next, prev));
  }
  getBandScalePadding() {
    return { inner: 1, outer: 0 };
  }
  attachSeries(seriesContentNode, seriesNode, annotationNode) {
    seriesContentNode.appendChild(this.contentGroup);
    seriesNode.appendChild(this.highlightGroup);
    seriesNode.appendChild(this.labelGroup);
    annotationNode?.appendChild(this.annotationGroup);
  }
  detachSeries(seriesContentNode, seriesNode, annotationNode) {
    seriesContentNode?.removeChild(this.contentGroup);
    seriesNode.removeChild(this.highlightGroup);
    seriesNode.removeChild(this.labelGroup);
    annotationNode?.removeChild(this.annotationGroup);
  }
  setSeriesIndex(index) {
    if (index === this._declarationOrder)
      return false;
    this._declarationOrder = index;
    this.contentGroup.zIndex = [
      1,
      index,
      0
      /* FOREGROUND */
    ];
    this.highlightGroup.zIndex = [
      1,
      index,
      1
      /* HIGHLIGHT */
    ];
    this.labelGroup.zIndex = [
      1,
      index,
      2
      /* LABEL */
    ];
    this.annotationGroup.zIndex = index;
    return true;
  }
  renderToOffscreenCanvas() {
    return false;
  }
  addEventListener(type, listener) {
    return super.addEventListener(type, listener);
  }
  addListener(type, listener) {
    return this.seriesListeners.addListener(type, listener);
  }
  dispatch(type, event) {
    this.seriesListeners.dispatch(type, event);
  }
  addChartEventListeners() {
    return;
  }
  destroy() {
    this.destroyFns.forEach((f) => f());
    this.destroyFns = [];
    this.resetDatumCallbackCache();
    this.ctx.seriesStateManager.deregisterSeries(this);
  }
  getDirectionValues(direction, properties) {
    const resolvedDirection = this.resolveKeyDirection(direction);
    const keys = properties?.[resolvedDirection];
    const values = [];
    if (!keys) {
      return values;
    }
    const addValues = (...items) => {
      for (const value of items) {
        if (Array.isArray(value)) {
          addValues(...value);
        } else if (typeof value === "object") {
          addValues(...Object.values(value));
        } else {
          values.push(value);
        }
      }
    };
    addValues(...keys.map((key) => this.properties[key]));
    return values;
  }
  getKeys(direction) {
    return this.getDirectionValues(direction, this.directionKeys);
  }
  getKeyProperties(direction) {
    return this.directionKeys[this.resolveKeyDirection(direction)] ?? [];
  }
  getNames(direction) {
    return this.getDirectionValues(direction, this.directionNames);
  }
  resolveKeyDirection(direction) {
    return direction;
  }
  // The union of the series domain ('community') and series-option domains ('enterprise').
  getDomain(direction) {
    const seriesDomain = this.getSeriesDomain(direction);
    const moduleDomains = this.moduleMap.mapModules((module2) => module2.getDomain(direction)).flat();
    return moduleDomains.length !== 0 ? seriesDomain.concat(moduleDomains) : seriesDomain;
  }
  getRange(direction, visibleRange) {
    return this.getSeriesRange(direction, visibleRange);
  }
  // Indicate that something external changed and we should recalculate nodeData.
  markNodeDataDirty() {
    this.nodeDataRefresh = true;
    this._pickNodeCache.clear();
    this.visibleMaybeChanged();
  }
  visibleMaybeChanged() {
    this.ctx.seriesStateManager.updateSeries(this);
  }
  getOpacity() {
    const defaultOpacity = 1;
    const { dimOpacity = 1, enabled = true } = this.properties.highlightStyle.series;
    if (!enabled || dimOpacity === defaultOpacity) {
      return defaultOpacity;
    }
    switch (this.isItemIdHighlighted()) {
      case 0:
      case 1:
        return defaultOpacity;
      case 2:
      default:
        return dimOpacity;
    }
  }
  getStrokeWidth(defaultStrokeWidth) {
    const { strokeWidth, enabled = true } = this.properties.highlightStyle.series;
    if (!enabled || strokeWidth === void 0) {
      return defaultStrokeWidth;
    }
    switch (this.isItemIdHighlighted()) {
      case 1:
        return strokeWidth;
      case 0:
      case 2:
        return defaultStrokeWidth;
    }
  }
  isItemIdHighlighted() {
    const series = this.ctx.highlightManager?.getActiveHighlight()?.series;
    if (series == null) {
      return 0;
    }
    if (series !== this) {
      return 2;
    }
    return 1;
  }
  getModuleTooltipParams() {
    return this.moduleMap.mapModules((module2) => module2.getTooltipParams()).reduce((total, current) => Object.assign(total, current), {});
  }
  pickNode(point, intent, exactMatchOnly = false) {
    const { pickModes, pickModeAxis, visible, contentGroup } = this;
    if (!visible || !contentGroup.visible)
      return;
    if (intent === "highlight" && !this.properties.highlight.enabled)
      return;
    if (intent === "highlight-tooltip" && !this.properties.highlight.enabled)
      return;
    let maxDistance = Infinity;
    if (intent === "tooltip" || intent === "highlight-tooltip") {
      const { tooltip } = this.properties;
      maxDistance = typeof tooltip.range === "number" ? tooltip.range : Infinity;
      exactMatchOnly || (exactMatchOnly = tooltip.range === "exact");
    } else if (intent === "event" || intent === "context-menu") {
      const { nodeClickRange } = this.properties;
      maxDistance = typeof nodeClickRange === "number" ? nodeClickRange : Infinity;
      exactMatchOnly || (exactMatchOnly = nodeClickRange === "exact");
    }
    const selectedPickModes = pickModes.filter(
      (m) => !exactMatchOnly || m === 0
      /* EXACT_SHAPE_MATCH */
    );
    const { x, y } = point;
    const key = JSON.stringify({ x, y, maxDistance, selectedPickModes });
    if (this._pickNodeCache.has(key)) {
      return this._pickNodeCache.get(key);
    }
    for (const pickMode of selectedPickModes) {
      let match;
      switch (pickMode) {
        case 0:
          match = this.pickNodeExactShape(point);
          break;
        case 1:
          match = this.pickNodeClosestDatum(point);
          break;
        case 2:
          match = pickModeAxis != null ? this.pickNodeMainAxisFirst(point, pickModeAxis === "main-category") : void 0;
          break;
      }
      if (match && match.distance <= maxDistance) {
        return this._pickNodeCache.set(key, { pickMode, match: match.datum, distance: match.distance });
      }
    }
    return this._pickNodeCache.set(key, void 0);
  }
  pickNodeExactShape(point) {
    const match = this.contentGroup.pickNode(point.x, point.y);
    if (match && match.datum.missing !== true) {
      return { datum: match.datum, distance: 0 };
    }
    return void 0;
  }
  pickNodeClosestDatum(_point) {
    throw new Error("AG Charts - Series.pickNodeClosestDatum() not implemented");
  }
  pickNodeNearestDistantObject(point, items) {
    const match = nearestSquared(point.x, point.y, items);
    if (match.nearest !== void 0 && match.nearest.datum.missing !== true) {
      return { datum: match.nearest.datum, distance: Math.sqrt(match.distanceSquared) };
    }
    return void 0;
  }
  pickNodeMainAxisFirst(_point, _requireCategoryAxis) {
    throw new Error("AG Charts - Series.pickNodeMainAxisFirst() not implemented");
  }
  getLabelData() {
    return [];
  }
  updatePlacedLabelData(_labels) {
    return;
  }
  fireNodeClickEvent(event, datum) {
    this.fireEvent(new this.NodeEvent("nodeClick", event, datum, this));
  }
  fireNodeDoubleClickEvent(event, datum) {
    this.fireEvent(new this.NodeEvent("nodeDoubleClick", event, datum, this));
  }
  createNodeContextMenuActionEvent(event, datum) {
    return new this.NodeEvent("nodeContextMenuAction", event, datum, this);
  }
  onLegendInitialState(legendType, initialState) {
    const { visible = true, itemId, legendItemName } = initialState ?? {};
    this.toggleSeriesItem(visible, legendType, itemId, legendItemName);
  }
  onLegendItemClick(event) {
    const { enabled, itemId, series, legendType } = event;
    const legendItemName = "legendItemName" in this.properties ? this.properties.legendItemName : void 0;
    const legendItemKey = "legendItemKey" in this.properties ? this.properties.legendItemKey : void 0;
    const matchedLegendItemName = legendItemName != void 0 && legendItemName === event.legendItemName;
    if (series.id === this.id || matchedLegendItemName || legendItemKey != void 0) {
      this.toggleSeriesItem(enabled, legendType, itemId, legendItemName, event);
    }
  }
  onLegendItemDoubleClick(event) {
    const { enabled, itemId, series, numVisibleItems, legendType } = event;
    const legendItemName = "legendItemName" in this.properties ? this.properties.legendItemName : void 0;
    const legendItemKey = "legendItemKey" in this.properties ? this.properties.legendItemKey : void 0;
    const matchedLegendItemName = legendItemName != void 0 && legendItemName === event.legendItemName;
    if (series.id === this.id || matchedLegendItemName || legendItemKey != void 0) {
      this.toggleSeriesItem(true, legendType, itemId, legendItemName, event);
    } else if (enabled && numVisibleItems === 1) {
      this.toggleSeriesItem(true, legendType, void 0, legendItemName);
    } else {
      this.toggleSeriesItem(false, legendType, void 0, legendItemName);
    }
  }
  toggleSeriesItem(enabled, legendType, itemId, legendItemName, legendEvent) {
    const seriesId = this.id;
    if (enabled || legendType !== "category") {
      this.visible = enabled;
    }
    this.nodeDataRefresh = true;
    this._pickNodeCache.clear();
    const event = {
      type: "seriesVisibilityChange",
      seriesId,
      itemId,
      legendItemName: legendEvent?.legendItemName ?? legendItemName,
      visible: enabled
    };
    this.fireEvent(event);
    this.ctx.legendManager.toggleItem({ enabled, seriesId, itemId, legendItemName });
  }
  isEnabled() {
    return this.visible;
  }
  getModuleMap() {
    return this.moduleMap;
  }
  createModuleContext() {
    return { ...this.ctx, series: this };
  }
  getLabelText(label, params, defaultFormatter = formatValue) {
    if (label.formatter) {
      return this.ctx.callbackCache.call(label.formatter, { seriesId: this.id, ...params }) ?? defaultFormatter(params.value);
    }
    return defaultFormatter(params.value);
  }
  getMarkerStyle(marker, params, defaultStyle = marker.getStyle()) {
    const defaultSize = { size: params.datum.point?.size ?? 0 };
    const markerStyle = mergeDefaults(defaultSize, defaultStyle);
    if (marker.itemStyler) {
      const style = this.ctx.callbackCache.call(marker.itemStyler, {
        seriesId: this.id,
        ...markerStyle,
        ...params,
        datum: params.datum.datum
      });
      return mergeDefaults(style, markerStyle);
    }
    return markerStyle;
  }
  updateMarkerStyle(markerNode, marker, params, defaultStyle = marker.getStyle(), { applyTranslation = true, selected = true } = {}) {
    const { point } = params.datum;
    const activeStyle = this.getMarkerStyle(marker, params, defaultStyle);
    const visible = this.visible && activeStyle.size > 0 && point && !isNaN(point.x) && !isNaN(point.y);
    if (applyTranslation) {
      markerNode.setProperties({ visible, ...activeStyle, translationX: point?.x, translationY: point?.y });
    } else {
      markerNode.setProperties({ visible, ...activeStyle });
    }
    if (!selected) {
      markerNode.fillOpacity *= CROSS_FILTER_MARKER_FILL_OPACITY_FACTOR;
      markerNode.strokeOpacity *= CROSS_FILTER_MARKER_STROKE_OPACITY_FACTOR;
    }
    if (typeof marker.shape === "function" && !markerNode.dirtyPath) {
      markerNode.path.clear(true);
      markerNode.updatePath();
      markerNode.checkPathDirty();
      const bb = markerNode.getBBox();
      if (point !== void 0 && bb.isFinite()) {
        const center2 = bb.computeCenter();
        const [dx, dy] = ["x", "y"].map(
          (key) => (activeStyle.strokeWidth ?? 0) + Math.abs(center2[key] - point[key])
        );
        const customSize = Math.max(bb.width + dx, bb.height + dy);
        point.focusSize = customSize;
      }
    }
  }
  getMinRects(_width, _height) {
    return;
  }
  get nodeDataDependencies() {
    return this._nodeDataDependencies ?? { seriesRectWidth: NaN, seriesRectHeight: NaN };
  }
  checkResize(newSeriesRect) {
    const { width: seriesRectWidth, height: seriesRectHeight } = newSeriesRect ?? { width: NaN, height: NaN };
    const newNodeDataDependencies = newSeriesRect ? { seriesRectWidth, seriesRectHeight } : void 0;
    const resize = jsonDiff(this.nodeDataDependencies, newNodeDataDependencies) != null;
    if (resize) {
      this._nodeDataDependencies = newNodeDataDependencies;
      this.markNodeDataDirty();
    }
    return resize;
  }
  pickFocus(_opts) {
    return void 0;
  }
  resetDatumCallbackCache() {
    this.datumCallbackCache.clear();
  }
  cachedDatumCallback(id, fn) {
    const { datumCallbackCache } = this;
    const existing = datumCallbackCache.get(id);
    if (existing != null)
      return existing;
    const value = fn();
    datumCallbackCache.set(id, value);
    return value;
  }
};
Series.highlightedZIndex = 1e12;
__decorateClass([
  ActionOnSet({
    changeValue: function(newVal, oldVal) {
      this.onSeriesGroupingChange(oldVal, newVal);
    }
  })
], Series.prototype, "seriesGrouping", 2);
function linearRoot(a, b) {
  const t = -b / a;
  return a !== 0 && t >= 0 && t <= 1 ? [t] : [];
}
function quadraticRoots(a, b, c) {
  if (a === 0) {
    return linearRoot(b, c);
  }
  const D = b * b - 4 * a * c;
  const roots = [];
  if (D === 0) {
    const t = -b / (2 * a);
    if (t >= 0 && t <= 1) {
      roots.push(t);
    }
  } else if (D > 0) {
    const rD = Math.sqrt(D);
    const t1 = (-b - rD) / (2 * a);
    const t2 = (-b + rD) / (2 * a);
    if (t1 >= 0 && t1 <= 1) {
      roots.push(t1);
    }
    if (t2 >= 0 && t2 <= 1) {
      roots.push(t2);
    }
  }
  return roots;
}
function cubicRoots(a, b, c, d) {
  if (a === 0) {
    return quadraticRoots(b, c, d);
  }
  const A = b / a;
  const B = c / a;
  const C2 = d / a;
  const Q = (3 * B - A * A) / 9;
  const R = (9 * A * B - 27 * C2 - 2 * A * A * A) / 54;
  const D = Q * Q * Q + R * R;
  const third = 1 / 3;
  const roots = [];
  if (D >= 0) {
    const rD = Math.sqrt(D);
    const S = Math.sign(R + rD) * Math.pow(Math.abs(R + rD), third);
    const T = Math.sign(R - rD) * Math.pow(Math.abs(R - rD), third);
    const Im = Math.abs(Math.sqrt(3) * (S - T) / 2);
    const t = -third * A + (S + T);
    if (t >= 0 && t <= 1) {
      roots.push(t);
    }
    if (Im === 0) {
      const t2 = -third * A - (S + T) / 2;
      if (t2 >= 0 && t2 <= 1) {
        roots.push(t2);
      }
    }
  } else {
    const theta = Math.acos(R / Math.sqrt(-Q * Q * Q));
    const thirdA = third * A;
    const twoSqrtQ = 2 * Math.sqrt(-Q);
    const t1 = twoSqrtQ * Math.cos(third * theta) - thirdA;
    const t2 = twoSqrtQ * Math.cos(third * (theta + 2 * Math.PI)) - thirdA;
    const t3 = twoSqrtQ * Math.cos(third * (theta + 4 * Math.PI)) - thirdA;
    if (t1 >= 0 && t1 <= 1) {
      roots.push(t1);
    }
    if (t2 >= 0 && t2 <= 1) {
      roots.push(t2);
    }
    if (t3 >= 0 && t3 <= 1) {
      roots.push(t3);
    }
  }
  return roots;
}
function segmentIntersection(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) {
  const d = (ax2 - ax1) * (by2 - by1) - (ay2 - ay1) * (bx2 - bx1);
  if (d === 0) {
    return 0;
  }
  const ua = ((bx2 - bx1) * (ay1 - by1) - (ax1 - bx1) * (by2 - by1)) / d;
  const ub = ((ax2 - ax1) * (ay1 - by1) - (ay2 - ay1) * (ax1 - bx1)) / d;
  if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
    return 1;
  }
  return 0;
}
function cubicSegmentIntersections(px1, py1, px2, py2, px3, py3, px4, py4, x1, y1, x2, y2) {
  let intersections = 0;
  const A = y1 - y2;
  const B = x2 - x1;
  const C2 = x1 * (y2 - y1) - y1 * (x2 - x1);
  const bx = bezierCoefficients(px1, px2, px3, px4);
  const by = bezierCoefficients(py1, py2, py3, py4);
  const a = A * bx[0] + B * by[0];
  const b = A * bx[1] + B * by[1];
  const c = A * bx[2] + B * by[2];
  const d = A * bx[3] + B * by[3] + C2;
  const roots = cubicRoots(a, b, c, d);
  for (const t of roots) {
    const tt = t * t;
    const ttt = t * tt;
    const x = bx[0] * ttt + bx[1] * tt + bx[2] * t + bx[3];
    const y = by[0] * ttt + by[1] * tt + by[2] * t + by[3];
    let s;
    if (x1 === x2) {
      s = (y - y1) / (y2 - y1);
    } else {
      s = (x - x1) / (x2 - x1);
    }
    if (s >= 0 && s <= 1) {
      intersections++;
    }
  }
  return intersections;
}
function bezierCoefficients(P1, P2, P3, P4) {
  return [
    // Bézier expressed as matrix operations:
    -P1 + 3 * P2 - 3 * P3 + P4,
    //                 |-1  3 -3  1| |P1|
    3 * P1 - 6 * P2 + 3 * P3,
    //   [t^3 t^2 t 1] | 3 -6  3  0| |P2|
    -3 * P1 + 3 * P2,
    //                 |-3  3  0  0| |P3|
    P1
    //                 | 1  0  0  0| |P4|
  ];
}
function arcIntersections(cx, cy, r, startAngle, endAngle, counterClockwise, x1, y1, x2, y2) {
  if (isNaN(cx) || isNaN(cy)) {
    return 0;
  }
  if (counterClockwise) {
    [endAngle, startAngle] = [startAngle, endAngle];
  }
  const k = (y2 - y1) / (x2 - x1);
  const y0 = y1 - k * x1;
  const a = Math.pow(k, 2) + 1;
  const b = 2 * (k * (y0 - cy) - cx);
  const c = Math.pow(cx, 2) + Math.pow(y0 - cy, 2) - Math.pow(r, 2);
  const d = Math.pow(b, 2) - 4 * a * c;
  if (d < 0) {
    return 0;
  }
  const i1x = (-b + Math.sqrt(d)) / 2 / a;
  const i2x = (-b - Math.sqrt(d)) / 2 / a;
  let intersections = 0;
  [i1x, i2x].forEach((x) => {
    const isXInsideLine = x >= Math.min(x1, x2) && x <= Math.max(x1, x2);
    if (!isXInsideLine) {
      return;
    }
    const y = k * x + y0;
    const adjacent = x - cx;
    const opposite = y - cy;
    const angle2 = Math.atan2(opposite, adjacent);
    if (isBetweenAngles(angle2, startAngle, endAngle)) {
      intersections++;
    }
  });
  return intersections;
}
function evaluateBezier(p0, p1, p2, p3, t) {
  return (1 - t) ** 3 * p0 + 3 * (1 - t) ** 2 * t * p1 + 3 * (1 - t) * t ** 2 * p2 + t ** 3 * p3;
}
function solveBezier(p0, p1, p2, p3, value) {
  if (value <= Math.min(p0, p3)) {
    return p0 < p3 ? 0 : 1;
  } else if (value >= Math.max(p0, p3)) {
    return p0 < p3 ? 1 : 0;
  }
  let t0 = 0;
  let t1 = 1;
  let t = NaN;
  for (let i = 0; i < 12; i += 1) {
    t = (t0 + t1) / 2;
    const curveValue = evaluateBezier(p0, p1, p2, p3, t);
    if (curveValue < value) {
      t0 = t;
    } else {
      t1 = t;
    }
  }
  return t;
}
function splitBezier(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, t) {
  const x01 = (1 - t) * p0x + t * p1x;
  const y01 = (1 - t) * p0y + t * p1y;
  const x12 = (1 - t) * p1x + t * p2x;
  const y12 = (1 - t) * p1y + t * p2y;
  const x23 = (1 - t) * p2x + t * p3x;
  const y23 = (1 - t) * p2y + t * p3y;
  const x012 = (1 - t) * x01 + t * x12;
  const y012 = (1 - t) * y01 + t * y12;
  const x123 = (1 - t) * x12 + t * x23;
  const y123 = (1 - t) * y12 + t * y23;
  const x0123 = (1 - t) * x012 + t * x123;
  const y0123 = (1 - t) * y012 + t * y123;
  return [
    [
      { x: p0x, y: p0y },
      { x: x01, y: y01 },
      { x: x012, y: y012 },
      { x: x0123, y: y0123 }
    ],
    [
      { x: x0123, y: y0123 },
      { x: x123, y: y123 },
      { x: x23, y: y23 },
      { x: p3x, y: p3y }
    ]
  ];
}
function calculateDerivativeExtrema(p0, p1, p2, p3) {
  const a = -p0 + 3 * p1 - 3 * p2 + p3;
  const b = 3 * p0 - 6 * p1 + 3 * p2;
  const c = -3 * p0 + 3 * p1;
  if (a === 0) {
    if (b !== 0) {
      const t = -c / b;
      if (t > 0 && t < 1) {
        return [t];
      }
    }
    return [];
  }
  const discriminant = b * b - 4 * a * c;
  if (discriminant >= 0) {
    const sqrtDiscriminant = Math.sqrt(discriminant);
    const t1 = (-b + sqrtDiscriminant) / (2 * a);
    const t2 = (-b - sqrtDiscriminant) / (2 * a);
    return [t1, t2].filter((t) => t > 0 && t < 1);
  }
  return [];
}
function calculateDerivativeExtremaXY(sx, sy, cp1x, cp1y, cp2x, cp2y, x, y) {
  const tx = calculateDerivativeExtrema(sx, cp1x, cp2x, x);
  const ty = calculateDerivativeExtrema(sy, cp1y, cp2y, y);
  return [...tx, ...ty];
}
var ExtendedPath2D = class {
  constructor() {
    this.path2d = new Path2D();
    this.previousCommands = [];
    this.previousParams = [];
    this.previousClosedPath = false;
    this.commands = [];
    this.params = [];
    this.openedPath = false;
    this.closedPath = false;
  }
  isEmpty() {
    return this.commands.length === 0;
  }
  isDirty() {
    return this.closedPath !== this.previousClosedPath || this.previousCommands.length !== this.commands.length || this.previousParams.length !== this.params.length || this.previousCommands.toString() !== this.commands.toString() || this.previousParams.toString() !== this.params.toString();
  }
  getPath2D() {
    return this.path2d;
  }
  moveTo(x, y) {
    this.openedPath = true;
    this.path2d.moveTo(x, y);
    this.commands.push(
      0
      /* Move */
    );
    this.params.push(x, y);
  }
  lineTo(x, y) {
    if (this.openedPath) {
      this.path2d.lineTo(x, y);
      this.commands.push(
        1
        /* Line */
      );
      this.params.push(x, y);
    } else {
      this.moveTo(x, y);
    }
  }
  rect(x, y, width2, height2) {
    this.moveTo(x, y);
    this.lineTo(x + width2, y);
    this.lineTo(x + width2, y + height2);
    this.lineTo(x, y + height2);
    this.closePath();
  }
  roundRect(x, y, width2, height2, radii) {
    radii = Math.min(radii, width2 / 2, height2 / 2);
    this.moveTo(x, y + radii);
    this.arc(x + radii, y + radii, radii, Math.PI, 1.5 * Math.PI);
    this.lineTo(x + radii, y);
    this.lineTo(x + width2 - radii, y);
    this.arc(x + width2 - radii, y + radii, radii, 1.5 * Math.PI, 2 * Math.PI);
    this.lineTo(x + width2, y + radii);
    this.lineTo(x + width2, y + height2 - radii);
    this.arc(x + width2 - radii, y + height2 - radii, radii, 0, Math.PI / 2);
    this.lineTo(x + width2 - radii, y + height2);
    this.lineTo(x + radii, y + height2);
    this.arc(x + +radii, y + height2 - radii, radii, Math.PI / 2, Math.PI);
    this.lineTo(x, y + height2 - radii);
    this.closePath();
  }
  arc(x, y, r, sAngle, eAngle, counterClockwise) {
    this.openedPath = true;
    this.path2d.arc(x, y, r, sAngle, eAngle, counterClockwise);
    this.commands.push(
      2
      /* Arc */
    );
    this.params.push(x, y, r, sAngle, eAngle, counterClockwise ? 1 : 0);
  }
  cubicCurveTo(cx1, cy1, cx2, cy2, x, y) {
    if (!this.openedPath) {
      this.moveTo(cx1, cy1);
    }
    this.path2d.bezierCurveTo(cx1, cy1, cx2, cy2, x, y);
    this.commands.push(
      3
      /* Curve */
    );
    this.params.push(cx1, cy1, cx2, cy2, x, y);
  }
  closePath() {
    if (this.openedPath) {
      this.path2d.closePath();
      this.commands.push(
        4
        /* ClosePath */
      );
      this.openedPath = false;
      this.closedPath = true;
    }
  }
  clear(trackChanges) {
    if (trackChanges) {
      this.previousCommands = this.commands;
      this.previousParams = this.params;
      this.previousClosedPath = this.closedPath;
    }
    this.path2d = new Path2D();
    this.openedPath = false;
    this.closedPath = false;
    this.commands = [];
    this.params = [];
  }
  isPointInPath(x, y) {
    const commands = this.commands;
    const params = this.params;
    const cn = commands.length;
    const ox = -1e4;
    const oy = -1e4;
    let sx = NaN;
    let sy = NaN;
    let px = 0;
    let py = 0;
    let intersectionCount = 0;
    for (let ci = 0, pi = 0; ci < cn; ci++) {
      switch (commands[ci]) {
        case 0:
          intersectionCount += segmentIntersection(sx, sy, px, py, ox, oy, x, y);
          px = params[pi++];
          sx = px;
          py = params[pi++];
          sy = py;
          break;
        case 1:
          intersectionCount += segmentIntersection(px, py, params[pi++], params[pi++], ox, oy, x, y);
          px = params[pi - 2];
          py = params[pi - 1];
          break;
        case 3:
          intersectionCount += cubicSegmentIntersections(
            px,
            py,
            params[pi++],
            params[pi++],
            params[pi++],
            params[pi++],
            params[pi++],
            params[pi++],
            ox,
            oy,
            x,
            y
          );
          px = params[pi - 2];
          py = params[pi - 1];
          break;
        case 2: {
          const cx = params[pi++];
          const cy = params[pi++];
          const r = params[pi++];
          const startAngle = params[pi++];
          const endAngle = params[pi++];
          const counterClockwise = Boolean(params[pi++]);
          intersectionCount += arcIntersections(
            cx,
            cy,
            r,
            startAngle,
            endAngle,
            counterClockwise,
            ox,
            oy,
            x,
            y
          );
          if (!isNaN(sx)) {
            const startX = cx + Math.cos(startAngle) * r;
            const startY = cy + Math.sin(startAngle) * r;
            intersectionCount += segmentIntersection(px, py, startX, startY, ox, oy, x, y);
          }
          px = cx + Math.cos(endAngle) * r;
          py = cy + Math.sin(endAngle) * r;
          break;
        }
        case 4:
          intersectionCount += segmentIntersection(sx, sy, px, py, ox, oy, x, y);
          break;
      }
    }
    return intersectionCount % 2 === 1;
  }
  distanceSquared(x, y) {
    let best = Infinity;
    const commands = this.commands;
    const params = this.params;
    const cn = commands.length;
    let sx = NaN;
    let sy = NaN;
    let px = 0;
    let py = 0;
    for (let ci = 0, pi = 0; ci < cn; ci++) {
      switch (commands[ci]) {
        case 0:
          px = sx = params[pi++];
          py = sy = params[pi++];
          break;
        case 1: {
          const nx = params[pi++];
          const ny = params[pi++];
          best = lineDistanceSquared(x, y, px, py, nx, ny, best);
          break;
        }
        case 3:
          Logger.error("Command.Curve distanceSquare not implemented");
          break;
        case 2: {
          const cx = params[pi++];
          const cy = params[pi++];
          const r = params[pi++];
          const startAngle = params[pi++];
          const endAngle = params[pi++];
          const startX = cx + Math.cos(startAngle) * r;
          const startY = cy + Math.sin(startAngle) * r;
          const counterClockwise = Boolean(params[pi++]);
          best = lineDistanceSquared(x, y, px, py, startX, startY, best);
          best = arcDistanceSquared(x, y, cx, cy, r, startAngle, endAngle, counterClockwise, best);
          px = cx + Math.cos(endAngle) * r;
          py = cy + Math.sin(endAngle) * r;
          break;
        }
        case 4:
          best = lineDistanceSquared(x, y, px, py, sx, sy, best);
          break;
      }
    }
    return best;
  }
  getPoints() {
    const { commands, params } = this;
    const coords = [];
    let pi = 0;
    for (const command of commands) {
      switch (command) {
        case 0:
        case 1:
          coords.push({ x: params[pi++], y: params[pi++] });
          break;
        case 3:
          pi += 4;
          coords.push({ x: params[pi++], y: params[pi++] });
          break;
        case 2:
          coords.push({ x: params[pi++], y: params[pi++] });
          pi += 4;
          break;
        case 4:
          break;
      }
    }
    return coords;
  }
  // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
  toSVG(transform = (x, y) => ({ x, y })) {
    const buffer = [];
    const { commands, params } = this;
    const addCommand = (command, ...points) => {
      buffer.push(command);
      for (let i = 0; i < points.length; i += 2) {
        const { x, y } = transform(points[i], points[i + 1]);
        buffer.push(x, y);
      }
    };
    let pi = 0;
    for (const command of commands) {
      switch (command) {
        case 0:
          addCommand("M", params[pi++], params[pi++]);
          break;
        case 1:
          addCommand("L", params[pi++], params[pi++]);
          break;
        case 3:
          addCommand("C", params[pi++], params[pi++], params[pi++], params[pi++], params[pi++], params[pi++]);
          break;
        case 2: {
          const cx = params[pi++];
          const cy = params[pi++];
          const r = params[pi++];
          const A0 = params[pi++];
          const A1 = params[pi++];
          const ccw = params[pi++];
          let sweep = ccw ? A0 - A1 : A1 - A0;
          if (sweep < 0) {
            sweep += Math.ceil(-sweep / (2 * Math.PI)) * 2 * Math.PI;
          }
          if (ccw) {
            sweep = -sweep;
          }
          const arcSections = Math.max(Math.ceil(Math.abs(sweep) / (Math.PI / 2)), 1);
          const step = sweep / arcSections;
          const h = 4 / 3 * Math.tan(step / 4);
          const move = buffer.length === 0 ? "M" : "L";
          addCommand(move, cx + Math.cos(A0) * r, cy + Math.sin(A0) * r);
          for (let i = 0; i < arcSections; i += 1) {
            const a0 = A0 + step * (i + 0);
            const a1 = A0 + step * (i + 1);
            const rSinStart = r * Math.sin(a0);
            const rCosStart = r * Math.cos(a0);
            const rSinEnd = r * Math.sin(a1);
            const rCosEnd = r * Math.cos(a1);
            addCommand(
              "C",
              cx + rCosStart - h * rSinStart,
              cy + rSinStart + h * rCosStart,
              cx + rCosEnd + h * rSinEnd,
              cy + rSinEnd - h * rCosEnd,
              cx + rCosEnd,
              cy + rSinEnd
            );
          }
          break;
        }
        case 4:
          buffer.push("Z");
          break;
      }
    }
    return buffer.join(" ");
  }
  computeBBox() {
    const { commands, params } = this;
    let [top, left, right, bot] = [Infinity, Infinity, -Infinity, -Infinity];
    let [sx, sy] = [NaN, NaN];
    let [mx, my] = [NaN, NaN];
    const joinPoint = (x, y, updatestart) => {
      top = Math.min(y, top);
      left = Math.min(x, left);
      right = Math.max(x, right);
      bot = Math.max(y, bot);
      if (updatestart) {
        [sx, sy] = [x, y];
      }
    };
    let pi = 0;
    for (const command of commands) {
      switch (command) {
        case 0:
          joinPoint(params[pi++], params[pi++], true);
          [mx, my] = [sx, sy];
          break;
        case 1:
          joinPoint(params[pi++], params[pi++], true);
          break;
        case 3: {
          const cp1x = params[pi++];
          const cp1y = params[pi++];
          const cp2x = params[pi++];
          const cp2y = params[pi++];
          const x = params[pi++];
          const y = params[pi++];
          joinPoint(x, y, true);
          const Ts = calculateDerivativeExtremaXY(sx, sy, cp1x, cp1y, cp2x, cp2y, x, y);
          Ts.forEach((t) => {
            const px = evaluateBezier(sx, cp1x, cp2x, x, t);
            const py = evaluateBezier(sy, cp1y, cp2y, y, t);
            joinPoint(px, py);
          });
          break;
        }
        case 2: {
          const cx = params[pi++];
          const cy = params[pi++];
          const r = params[pi++];
          let A0 = normalizeAngle360(params[pi++]);
          let A1 = normalizeAngle360(params[pi++]);
          const ccw = params[pi++];
          if (ccw) {
            [A0, A1] = [A1, A0];
          }
          const joinAngle = (angle2, updatestart) => {
            const px = cx + r * Math.cos(angle2);
            const py = cy + r * Math.sin(angle2);
            joinPoint(px, py, updatestart);
          };
          joinAngle(A0);
          joinAngle(A1, true);
          const criticalAngles = [0, Math.PI / 2, Math.PI, 3 * Math.PI / 2];
          for (const crit of criticalAngles) {
            if (A0 < A1 && A0 <= crit && crit <= A1 || A0 > A1 && (A0 <= crit || crit <= A1)) {
              joinAngle(crit);
            }
          }
          break;
        }
        case 4:
          [sx, sy] = [mx, my];
          break;
      }
    }
    return new BBox(left, top, right - left, bot - top);
  }
};
function ScenePathChangeDetection(opts) {
  const { changeCb, convertor } = opts ?? {};
  return SceneChangeDetection({ type: "path", convertor, changeCb });
}
var Path = class extends Shape {
  constructor() {
    super(...arguments);
    this.path = new ExtendedPath2D();
    this._clipX = NaN;
    this._clipY = NaN;
    this.clip = false;
    this._dirtyPath = true;
  }
  set clipX(value) {
    this._clipX = value;
    this.dirtyPath = true;
  }
  set clipY(value) {
    this._clipY = value;
    this.dirtyPath = true;
  }
  set dirtyPath(value) {
    if (this._dirtyPath !== value) {
      this._dirtyPath = value;
      if (value) {
        this.markDirty();
      }
    }
  }
  get dirtyPath() {
    return this._dirtyPath;
  }
  checkPathDirty() {
    if (this._dirtyPath) {
      return;
    }
    this.dirtyPath = this.path.isDirty() || (this.fillShadow?.isDirty() ?? false) || (this._clipPath?.isDirty() ?? false);
  }
  isPointInPath(x, y) {
    this.updatePathIfDirty();
    return this.path.closedPath && this.path.isPointInPath(x, y);
  }
  distanceSquared(x, y) {
    return this.distanceSquaredTransformedPoint(x, y);
  }
  svgPathData(transform) {
    this.updatePathIfDirty();
    return this.path.toSVG(transform);
  }
  distanceSquaredTransformedPoint(x, y) {
    this.updatePathIfDirty();
    if (this.path.closedPath && this.path.isPointInPath(x, y)) {
      return 0;
    }
    return this.path.distanceSquared(x, y);
  }
  isDirtyPath() {
    return false;
  }
  updatePath() {
  }
  updatePathIfDirty() {
    if (this.dirtyPath || this.isDirtyPath()) {
      this.updatePath();
      this.dirtyPath = false;
    }
  }
  preRender() {
    this.updatePathIfDirty();
    return super.preRender(this.path.commands.length);
  }
  render(renderCtx) {
    const { ctx } = renderCtx;
    if (this.clip && !isNaN(this._clipX) && !isNaN(this._clipY)) {
      ctx.save();
      const margin = this.strokeWidth / 2;
      this._clipPath ?? (this._clipPath = new ExtendedPath2D());
      this._clipPath.clear();
      this._clipPath.rect(-margin, -margin, this._clipX + margin, this._clipY + margin + margin);
      ctx.clip(this._clipPath?.getPath2D());
      if (this._clipX > 0 && this._clipY > 0) {
        this.drawPath(ctx);
      }
      ctx.restore();
    } else {
      this._clipPath = void 0;
      this.drawPath(ctx);
    }
    this.fillShadow?.markClean();
    super.render(renderCtx);
  }
  drawPath(ctx) {
    this.fillStroke(ctx, this.path.getPath2D());
  }
  toSVG() {
    if (!this.visible)
      return;
    const element2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
    element2.setAttribute("d", this.svgPathData());
    this.applySvgFillAttributes(element2);
    this.applySvgStrokeAttributes(element2);
    return {
      elements: [element2]
    };
  }
};
Path.className = "Path";
__decorateClass([
  ScenePathChangeDetection()
], Path.prototype, "clip", 2);
__decorateClass([
  ScenePathChangeDetection()
], Path.prototype, "clipX", 1);
__decorateClass([
  ScenePathChangeDetection()
], Path.prototype, "clipY", 1);
var FocusIndicator = class {
  constructor(swapChain) {
    this.swapChain = swapChain;
    this.div = getDocument().createElement("div");
    this.svg = getDocument().createElementNS("http://www.w3.org/2000/svg", "svg");
    this.path = getDocument().createElementNS("http://www.w3.org/2000/svg", "path");
    this.svg.append(this.path);
    this.element = getDocument().createElement("div");
    this.element.classList.add("ag-charts-focus-indicator");
    this.element.ariaHidden = "true";
    this.element.append(this.svg);
    this.swapChain.addListener("swap", (parent) => this.onSwap(parent));
  }
  updateBounds(bounds, clipRect, fixmeTranslatePathX = 0, fixmeTranslatePathY = 0) {
    if (bounds === void 0) {
      return;
    } else if (bounds instanceof Path) {
      const transform = (localX, localY) => {
        let { x, y } = Transformable.toCanvasPoint(bounds, localX, localY);
        x -= fixmeTranslatePathX;
        y -= fixmeTranslatePathY;
        return { x, y };
      };
      this.path.setAttribute("d", bounds.svgPathData(transform));
      this.show(this.svg);
    } else {
      if (clipRect == null) {
        setElementBBox(this.div, bounds);
      } else {
        const x0 = Math.max(bounds.x, clipRect.x);
        const y0 = Math.max(bounds.y, clipRect.y);
        const x1 = Math.min(bounds.x + bounds.width, clipRect.x + clipRect.width);
        const y1 = Math.min(bounds.y + bounds.height, clipRect.y + clipRect.height);
        setElementBBox(this.div, new BBox(x0, y0, x1 - x0, y1 - y0));
      }
      this.show(this.div);
    }
  }
  onSwap(newParent) {
    if (newParent === this.element.parentElement)
      return;
    this.element.remove();
    newParent.appendChild(this.element);
    this.overrideFocusVisible(this.focusVisible);
  }
  show(child) {
    this.element.innerHTML = "";
    this.element.append(child);
  }
  overrideFocusVisible(focusVisible) {
    this.focusVisible = focusVisible;
    const opacity = { true: "1", false: "0", undefined: "" };
    const parent = this.element.parentElement;
    parent?.style.setProperty("opacity", opacity[`${focusVisible}`]);
  }
  // Get the `:focus-visible` CSS state.
  isFocusVisible() {
    const parent = this.element.parentElement;
    return parent != null && getWindow().getComputedStyle(parent).opacity === "1";
  }
};
var FocusSwapChain = class {
  constructor(label1, label2, id, announcerRole) {
    this.label1 = label1;
    this.label2 = label2;
    this.hasFocus = false;
    this.skipDispatch = false;
    this.listeners = {
      blur: [],
      focus: [],
      swap: []
    };
    this.onBlur = (e) => !this.skipDispatch && this.dispatch("blur", e);
    this.onFocus = (e) => !this.skipDispatch && this.dispatch("focus", e);
    setAttribute(this.label1, "id", `${id}-label1`);
    setAttribute(this.label2, "id", `${id}-label2`);
    setElementStyle(this.label1, "display", "none");
    setElementStyle(this.label2, "display", "none");
    this.activeAnnouncer = this.createAnnouncer(announcerRole);
    this.inactiveAnnouncer = this.createAnnouncer(announcerRole);
    setAttribute(this.activeAnnouncer, "tabindex", 0);
    this.label2.insertAdjacentElement("afterend", this.activeAnnouncer);
    this.label2.insertAdjacentElement("afterend", this.inactiveAnnouncer);
    this.swap("");
  }
  createAnnouncer(role) {
    const announcer = createElement("div");
    announcer.role = role;
    announcer.className = "ag-charts-swapchain";
    announcer.addEventListener("blur", this.onBlur);
    announcer.addEventListener("focus", this.onFocus);
    return announcer;
  }
  destroy() {
    for (const announcer of [this.activeAnnouncer, this.inactiveAnnouncer]) {
      announcer.removeEventListener("blur", this.onBlur);
      announcer.removeEventListener("focus", this.onFocus);
      announcer.remove();
    }
  }
  focus() {
    this.activeAnnouncer.focus();
  }
  update(newLabel) {
    this.skipDispatch = true;
    this.swap(newLabel);
    if (this.hasFocus) {
      this.activeAnnouncer.focus();
    }
    this.skipDispatch = false;
  }
  addListener(type, handler) {
    this.listeners[type].push(handler);
    if (type === "swap") {
      const swapHandler = handler;
      swapHandler(this.activeAnnouncer);
    }
  }
  dispatch(type, param) {
    if (type === "focus")
      this.hasFocus = true;
    else if (type === "blur")
      this.hasFocus = false;
    this.listeners[type].forEach((fn) => fn(param));
  }
  swap(newLabel) {
    const userTabIndex = this.activeAnnouncer.tabIndex;
    this.label2.textContent = newLabel;
    [this.inactiveAnnouncer, this.activeAnnouncer] = [this.activeAnnouncer, this.inactiveAnnouncer];
    [this.label1, this.label2] = [this.label2, this.label1];
    setAttributes(this.inactiveAnnouncer, {
      "aria-labelledby": this.label1.id,
      "aria-hidden": true,
      tabindex: void 0
    });
    setAttributes(this.activeAnnouncer, {
      "aria-labelledby": this.label1.id,
      "aria-hidden": false,
      tabindex: userTabIndex
    });
    setElementStyle(this.inactiveAnnouncer, "pointer-events", "none");
    setElementStyle(this.activeAnnouncer, "pointer-events", void 0);
    this.dispatch("swap", this.activeAnnouncer);
  }
};
function computeCenter(hoverRect, pick) {
  const refPoint = getDatumRefPoint(pick.datum);
  if (refPoint != null)
    return { x: refPoint.canvasX, y: refPoint.canvasY };
  const bboxOrPath = pick.bounds;
  if (bboxOrPath == null)
    return;
  if (bboxOrPath instanceof BBox) {
    const { x: centerX, y: centerY } = bboxOrPath.computeCenter();
    return {
      x: hoverRect.x + centerX,
      y: hoverRect.y + centerY
    };
  }
  return Transformable.toCanvas(bboxOrPath).computeCenter();
}
function drawPickedFocus(seriesRect, focusIndicator, pick, fixmeTranslatePathX, fixmeTranslatePathY) {
  const { bounds, showFocusBox, clipFocusBox = true } = pick;
  if (showFocusBox) {
    focusIndicator?.updateBounds(
      bounds,
      clipFocusBox ? seriesRect : void 0,
      fixmeTranslatePathX,
      fixmeTranslatePathY
    );
  }
}
function getPickedFocusBBox({ bounds }) {
  if (bounds instanceof BBox)
    return bounds;
  if (bounds != null)
    return bounds.getBBox();
  return BBox.NaN;
}
function makeKeyboardPointerEvent(hoverRect, pick) {
  const { x: canvasX, y: canvasY } = computeCenter(hoverRect, pick) ?? {};
  if (canvasX !== void 0 && canvasY !== void 0) {
    return { type: "keyboard", canvasX, canvasY };
  }
  return void 0;
}
function calculatePlacement(naturalWidth, naturalHeight, container, bounds) {
  let { top, right, bottom, left, width: width2, height: height2 } = bounds;
  if (left != null) {
    if (width2 != null) {
      right = container.width - left + width2;
    } else if (right != null) {
      width2 = container.width - left - right;
    }
  } else if (right != null && width2 != null) {
    left = container.width - right - width2;
  }
  if (top != null) {
    if (height2 != null) {
      bottom = container.height - top - height2;
    } else if (bottom != null) {
      height2 = container.height - bottom - top;
    }
  } else if (bottom != null && height2 != null) {
    top = container.height - bottom - height2;
  }
  if (width2 == null) {
    if (height2 == null) {
      width2 = naturalWidth;
      height2 = naturalHeight;
    } else {
      width2 = Math.ceil(naturalWidth * height2 / naturalHeight);
    }
  } else if (height2 == null) {
    height2 = Math.ceil(naturalHeight * width2 / naturalWidth);
  }
  if (left == null) {
    if (right == null) {
      left = Math.floor((container.width - width2) / 2);
    } else {
      left = container.width - right - width2;
    }
  }
  if (top == null) {
    if (bottom == null) {
      top = Math.floor((container.height - height2) / 2);
    } else {
      top = container.height - height2 - bottom;
    }
  }
  return { x: left, y: top, width: width2, height: height2 };
}
var element = null;
function sanitizeHtml(text) {
  if (text == null) {
    return;
  } else if (text === "") {
    return "";
  }
  element ?? (element = createElement("div"));
  element.textContent = String(text);
  return element.innerHTML;
}
var BUILTIN_MARKERS = [
  "ArrowDown",
  "ArrowUp",
  "Circle",
  "Cross",
  "Diamond",
  "Heart",
  "MapPin",
  "Plus",
  "Square",
  "Star",
  "Triangle"
];
var DEFAULT_CENTER_POINT = Object.freeze({ x: 0.5, y: 0.5 });
var InternalMarker = class extends Path {
  constructor() {
    super(...arguments);
    this.x = 0;
    this.y = 0;
    this.size = 12;
  }
  isBuiltIn() {
    return BUILTIN_MARKERS.includes(this.constructor.className ?? "");
  }
  computeBBox() {
    if (!this.isBuiltIn()) {
      this.updatePathIfDirty();
      return this.path.computeBBox();
    }
    const { x, y, size } = this;
    const { center: center2 } = this.constructor;
    return new BBox(x - size * center2.x, y - size * center2.y, size, size);
  }
  applyPath(s, moves) {
    const { path } = this;
    let { x, y } = this;
    path.clear();
    for (const { x: mx, y: my, t } of moves) {
      x += mx * s;
      y += my * s;
      if (t === "move") {
        path.moveTo(x, y);
      } else {
        path.lineTo(x, y);
      }
    }
    path.closePath();
  }
  executeFill(ctx, path) {
    if (!path)
      return;
    return super.executeFill(ctx, path);
  }
  executeStroke(ctx, path) {
    if (!path)
      return;
    return super.executeStroke(ctx, path);
  }
};
__decorateClass([
  ScenePathChangeDetection()
], InternalMarker.prototype, "x", 2);
__decorateClass([
  ScenePathChangeDetection()
], InternalMarker.prototype, "y", 2);
__decorateClass([
  ScenePathChangeDetection({ convertor: Math.abs })
], InternalMarker.prototype, "size", 2);
var Marker = class extends Rotatable(Scalable(Translatable(InternalMarker))) {
};
Marker.center = DEFAULT_CENTER_POINT;
var Circle = class extends Marker {
  updatePath() {
    const { x, y, path, size } = this;
    const r = size / 2;
    path.clear();
    path.arc(x, y, r, 0, Math.PI * 2);
    path.closePath();
  }
};
Circle.className = "Circle";
var _Cross = class _Cross2 extends Marker {
  updatePath() {
    const s = this.size / 4.2;
    super.applyPath(s, _Cross2.moves);
  }
};
_Cross.className = "Cross";
_Cross.moves = [
  { x: -1, y: 0, t: "move" },
  { x: -1, y: -1 },
  { x: 1, y: -1 },
  { x: 1, y: 1 },
  { x: 1, y: -1 },
  { x: 1, y: 1 },
  { x: -1, y: 1 },
  { x: 1, y: 1 },
  { x: -1, y: 1 },
  { x: -1, y: -1 },
  { x: -1, y: 1 },
  { x: -1, y: -1 }
];
var Cross = _Cross;
var _Diamond = class _Diamond2 extends Marker {
  updatePath() {
    const s = this.size / 2;
    super.applyPath(s, _Diamond2.moves);
  }
};
_Diamond.className = "Diamond";
_Diamond.moves = [
  { x: 0, y: -1, t: "move" },
  { x: 1, y: 1 },
  { x: -1, y: 1 },
  { x: -1, y: -1 },
  { x: 1, y: -1 }
];
var Diamond = _Diamond;
var _Heart = class _Heart2 extends Marker {
  static rad(degree) {
    return degree / 180 * Math.PI;
  }
  updatePath() {
    const { x, path, size } = this;
    const { rad } = _Heart2;
    const r = size / 4;
    const y = this.y + r / 2;
    path.clear();
    path.arc(x - r, y - r, r, rad(130), rad(330));
    path.arc(x + r, y - r, r, rad(220), rad(50));
    path.lineTo(x, y + r);
    path.closePath();
  }
};
_Heart.className = "Heart";
var Heart = _Heart;
var Pin = class extends Marker {
  updatePath() {
    const { path, x, y } = this;
    const s = this.size;
    const cx = 0.5;
    const cy = 1;
    path.clear();
    path.moveTo(x + (0.15625 - cx) * s, y + (0.34375 - cy) * s);
    path.cubicCurveTo(
      x + (0.15625 - cx) * s,
      y + (0.151491 - cy) * s,
      x + (0.307741 - cx) * s,
      y + (0 - cy) * s,
      x + (0.5 - cx) * s,
      y + (0 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.692259 - cx) * s,
      y + (0 - cy) * s,
      x + (0.84375 - cx) * s,
      y + (0.151491 - cy) * s,
      x + (0.84375 - cx) * s,
      y + (0.34375 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.84375 - cx) * s,
      y + (0.493824 - cy) * s,
      x + (0.784625 - cx) * s,
      y + (0.600181 - cy) * s,
      x + (0.716461 - cx) * s,
      y + (0.695393 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.699009 - cx) * s,
      y + (0.719769 - cy) * s,
      x + (0.681271 - cx) * s,
      y + (0.743104 - cy) * s,
      x + (0.663785 - cx) * s,
      y + (0.766105 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.611893 - cx) * s,
      y + (0.834367 - cy) * s,
      x + (0.562228 - cx) * s,
      y + (0.899699 - cy) * s,
      x + (0.528896 - cx) * s,
      y + (0.980648 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.524075 - cx) * s,
      y + (0.992358 - cy) * s,
      x + (0.512663 - cx) * s,
      y + (1 - cy) * s,
      x + (0.5 - cx) * s,
      y + (1 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.487337 - cx) * s,
      y + (1 - cy) * s,
      x + (0.475925 - cx) * s,
      y + (0.992358 - cy) * s,
      x + (0.471104 - cx) * s,
      y + (0.980648 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.487337 - cx) * s,
      y + (1 - cy) * s,
      x + (0.475925 - cx) * s,
      y + (0.992358 - cy) * s,
      x + (0.471104 - cx) * s,
      y + (0.980648 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.437772 - cx) * s,
      y + (0.899699 - cy) * s,
      x + (0.388107 - cx) * s,
      y + (0.834367 - cy) * s,
      x + (0.336215 - cx) * s,
      y + (0.766105 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.318729 - cx) * s,
      y + (0.743104 - cy) * s,
      x + (0.300991 - cx) * s,
      y + (0.719769 - cy) * s,
      x + (0.283539 - cx) * s,
      y + (0.695393 - cy) * s
    );
    path.cubicCurveTo(
      x + (0.215375 - cx) * s,
      y + (0.600181 - cy) * s,
      x + (0.15625 - cx) * s,
      y + (0.493824 - cy) * s,
      x + (0.15625 - cx) * s,
      y + (0.34375 - cy) * s
    );
    path.closePath();
  }
};
Pin.className = "MapPin";
Pin.center = { x: 0.5, y: 1 };
var _Plus = class _Plus2 extends Marker {
  updatePath() {
    const s = this.size / 3;
    super.applyPath(s, _Plus2.moves);
  }
};
_Plus.className = "Plus";
_Plus.moves = [
  { x: -0.5, y: -0.5, t: "move" },
  { x: 0, y: -1 },
  { x: 1, y: 0 },
  { x: 0, y: 1 },
  { x: 1, y: 0 },
  { x: 0, y: 1 },
  { x: -1, y: 0 },
  { x: 0, y: 1 },
  { x: -1, y: 0 },
  { x: 0, y: -1 },
  { x: -1, y: 0 },
  { x: 0, y: -1 }
];
var Plus = _Plus;
var Square = class extends Marker {
  updatePath() {
    const { path, x, y } = this;
    const hs = this.size / 2;
    path.clear();
    path.moveTo(this.align(x - hs), this.align(y - hs));
    path.lineTo(this.align(x + hs), this.align(y - hs));
    path.lineTo(this.align(x + hs), this.align(y + hs));
    path.lineTo(this.align(x - hs), this.align(y + hs));
    path.closePath();
  }
};
Square.className = "Square";
var Star = class extends Marker {
  updatePath() {
    const { x, y, path, size } = this;
    const spikes = 5;
    const outerRadius = size / 2;
    const innerRadius = outerRadius / 2;
    const rotation = Math.PI / 2;
    path.clear();
    for (let i = 0; i < spikes * 2; i++) {
      const radius = i % 2 === 0 ? outerRadius : innerRadius;
      const angle2 = i * Math.PI / spikes - rotation;
      const xCoordinate = x + Math.cos(angle2) * radius;
      const yCoordinate = y + Math.sin(angle2) * radius;
      path.lineTo(xCoordinate, yCoordinate);
    }
    path.closePath();
  }
};
Star.className = "Star";
var _Triangle = class _Triangle2 extends Marker {
  updatePath() {
    const s = this.size * 1.1;
    super.applyPath(s, _Triangle2.moves);
  }
};
_Triangle.className = "Triangle";
_Triangle.moves = [
  { x: 0, y: -0.48, t: "move" },
  { x: 0.5, y: 0.87 },
  { x: -1, y: 0 }
];
var Triangle = _Triangle;
var MARKER_SHAPES = {
  circle: Circle,
  cross: Cross,
  diamond: Diamond,
  heart: Heart,
  pin: Pin,
  plus: Plus,
  square: Square,
  star: Star,
  triangle: Triangle
};
var MARKER_SUPPORTED_SHAPES = Object.keys(MARKER_SHAPES);
function isSupportedMarkerShape(shape) {
  return typeof shape === "string" && MARKER_SUPPORTED_SHAPES.includes(shape);
}
function markerFactory(pathFn) {
  return class CustomMarker extends Marker {
    updatePath() {
      const { path, x, y, size } = this;
      pathFn({ path, x, y, size });
    }
  };
}
function getMarker(shape = "square") {
  if (isSupportedMarkerShape(shape)) {
    return MARKER_SHAPES[shape];
  }
  if (typeof shape === "function") {
    return markerFactory(shape);
  }
  return Square;
}
function legendSymbolSvg(symbol, size, lineSize = size * (5 / 3)) {
  const group = new Group();
  const markerStrokeWidth = Math.min(symbol.marker.strokeWidth, 2);
  const lineStrokeWidth = Math.min(symbol.line?.strokeWidth ?? 0, 2);
  const width2 = Math.max(symbol.marker.enabled === false ? 0 : size, symbol.line == null ? 0 : lineSize);
  const height2 = Math.max(symbol.marker.enabled === false ? 0 : size, lineStrokeWidth);
  if (symbol.line != null) {
    const { stroke, strokeOpacity, lineDash } = symbol.line;
    const line = new Line();
    line.x1 = 0;
    line.y1 = height2 / 2;
    line.x2 = width2;
    line.y2 = height2 / 2;
    line.stroke = stroke;
    line.strokeOpacity = strokeOpacity;
    line.strokeWidth = lineStrokeWidth;
    line.lineDash = lineDash;
    group.append(line);
  }
  if (symbol.marker.enabled !== false) {
    const { shape, fill, fillOpacity, stroke, strokeOpacity } = symbol.marker;
    const Marker2 = getMarker(shape);
    const marker = new Marker2();
    const { center: center2 } = Marker2;
    marker.size = size;
    marker.translationX = width2 / 2 + (center2.x - 0.5) * size;
    marker.translationY = height2 / 2 + (center2.y - 0.5) * size;
    marker.fill = fill;
    marker.fillOpacity = fillOpacity;
    marker.stroke = stroke;
    marker.strokeOpacity = strokeOpacity;
    marker.strokeWidth = markerStrokeWidth;
    const x = width2 / 2 + (center2.x - 0.5) * size;
    const y = height2 / 2 + (center2.y - 0.5) * size;
    if (typeof shape === "string") {
      const scale2 = size / (size + markerStrokeWidth);
      marker.translationX = x;
      marker.translationY = y;
      marker.scalingX = scale2;
      marker.scalingY = scale2;
    } else {
      const bbox = marker.getBBox();
      const scale2 = Math.min(
        width2 / (bbox.width + markerStrokeWidth),
        height2 / (bbox.height + markerStrokeWidth),
        1
      );
      marker.translationX = x * scale2 - bbox.x * scale2 + (width2 - bbox.width * scale2) / 2;
      marker.translationY = y * scale2 - bbox.y * scale2 + (height2 - bbox.height * scale2) / 2;
      marker.scalingX = scale2;
      marker.scalingY = scale2;
    }
    group.append(marker);
  }
  return Group.toSVG(group, width2, height2);
}
var M = 0.1;
var K = 200;
var C = 12;
var DELTA = 0.5;
var SpringAnimation = class extends Listeners {
  constructor() {
    super(...arguments);
    this.x1 = NaN;
    this.y1 = NaN;
    this.x = NaN;
    this.y = NaN;
    this.vx = 0;
    this.vy = 0;
    this.t0 = NaN;
    this.animationFrameHandle = void 0;
  }
  reset() {
    this.x = NaN;
    this.y = NaN;
    if (this.animationFrameHandle != null) {
      cancelAnimationFrame(this.animationFrameHandle);
      this.animationFrameHandle = void 0;
    }
  }
  update(x, y) {
    if (Number.isNaN(this.x) || Number.isNaN(this.y)) {
      this.x = x;
      this.y = y;
      this.vx = 0;
      this.vy = 0;
      this.emitUpdate();
      if (this.animationFrameHandle != null) {
        cancelAnimationFrame(this.animationFrameHandle);
        this.animationFrameHandle = void 0;
      }
      return;
    }
    this.x1 = x;
    this.y1 = y;
    this.t0 = Date.now();
    if (this.animationFrameHandle == null) {
      this.animationFrameHandle = requestAnimationFrame(this.onFrame.bind(this));
    }
  }
  onFrame() {
    this.animationFrameHandle = void 0;
    const { x1, y1, t0 } = this;
    const t1 = Date.now();
    const dt = t1 - t0;
    this.t0 = t1;
    const stepT = 1e-3;
    const iterations = Math.ceil(dt / (stepT * 1e3)) | 0;
    let { x, y, vx, vy } = this;
    for (let i = 0; i < iterations; i += 1) {
      const dx = x - x1;
      const dy = y - y1;
      const ax = -(K * dx + C * vx) / M;
      const ay = -(K * dy + C * vy) / M;
      vx += ax * stepT;
      vy += ay * stepT;
      x += vx * stepT;
      y += vy * stepT;
    }
    if (Math.hypot(x - x1, y - y1) < DELTA) {
      this.x = this.x1;
      this.y = this.y1;
      this.vx = 0;
      this.vy = 0;
    } else {
      this.x = x;
      this.y = y;
      this.vx = vx;
      this.vy = vy;
      this.animationFrameHandle = requestAnimationFrame(this.onFrame.bind(this));
    }
    this.emitUpdate();
  }
  emitUpdate() {
    this.dispatch("update", { type: "update", x: this.x, y: this.y });
  }
};
var DEFAULT_TOOLTIP_CLASS = "ag-charts-tooltip";
var DEFAULT_TOOLTIP_DARK_CLASS = "ag-charts-tooltip--dark";
function tooltipContentAriaLabel(content) {
  if (typeof content === "string")
    return "";
  const ariaLabel = [];
  if (content.heading != null)
    ariaLabel.push(content.heading);
  if (content.title != null)
    ariaLabel.push(content.title);
  content.data?.forEach((datum) => {
    ariaLabel.push(datum.label ?? datum.fallbackLabel, datum.value);
  });
  return ariaLabel.join("; ");
}
function dataHtml(label, value, inline) {
  let rowHtml = "";
  if (label == null) {
    rowHtml += `<span class="${DEFAULT_TOOLTIP_CLASS}-label">${sanitizeHtml(value)}</span>`;
  } else {
    rowHtml += `<span class="${DEFAULT_TOOLTIP_CLASS}-label">${sanitizeHtml(label)}</span>`;
    rowHtml += " ";
    rowHtml += `<span class="${DEFAULT_TOOLTIP_CLASS}-value">${sanitizeHtml(value)}</span>`;
  }
  const rowClassNames = [`${DEFAULT_TOOLTIP_CLASS}-row`];
  if (inline)
    rowClassNames.push(`${DEFAULT_TOOLTIP_CLASS}-row--inline`);
  rowHtml = `<div class="${rowClassNames.join(" ")}">${rowHtml}</div>`;
  return rowHtml;
}
function tooltipContentHtml(content) {
  if (typeof content === "string")
    return content;
  let html = "";
  if ((content.heading == null || content.title == null) && content.data?.length === 1 && content.data[0].label == null && content.data[0].value != null) {
    const datum = content.data[0];
    html += dataHtml(content.heading ?? content.title, datum.value, false);
  } else {
    const dataInline = content.title == null && content.data?.length === 1;
    if (content.heading != null) {
      html += `<span class="${DEFAULT_TOOLTIP_CLASS}-heading">${sanitizeHtml(content.heading)}</span>`;
      html += " ";
    }
    const symbol = content.symbol == null ? void 0 : legendSymbolSvg(content.symbol, 12);
    if (symbol != null && (content.title != null || content.data?.length)) {
      html += `<span class="${DEFAULT_TOOLTIP_CLASS}-symbol">${symbol}</span>`;
    }
    if (content.title != null) {
      html += `<span class="${DEFAULT_TOOLTIP_CLASS}-title">${sanitizeHtml(content.title)}</span>`;
      html += " ";
    }
    content.data?.forEach((datum) => {
      html += dataHtml(datum.label ?? datum.fallbackLabel, datum.value, dataInline);
      html += " ";
    });
  }
  html = `<div class="${DEFAULT_TOOLTIP_CLASS}-content">${html.trimEnd()}</div>`;
  return html;
}
var TooltipPosition = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.type = "pointer";
    this.xOffset = 0;
    this.yOffset = 0;
  }
};
__decorateClass([
  Validate(
    UNION(
      [
        "pointer",
        "node",
        "top",
        "right",
        "bottom",
        "left",
        "top-left",
        "top-right",
        "bottom-right",
        "bottom-left",
        { value: "sparkline", undocumented: true },
        { value: "sparkline-", undocumented: true }
      ],
      "a position type"
    )
  )
], TooltipPosition.prototype, "type", 2);
__decorateClass([
  Validate(NUMBER)
], TooltipPosition.prototype, "xOffset", 2);
__decorateClass([
  Validate(NUMBER)
], TooltipPosition.prototype, "yOffset", 2);
var Tooltip = class extends BaseProperties {
  constructor() {
    super();
    this.enabled = true;
    this.delay = 0;
    this.range = void 0;
    this.wrapping = "hyphenate";
    this.position = new TooltipPosition();
    this.darkTheme = false;
    this.bounds = "extended";
    this.destroyFns = [];
    this.springAnimation = new SpringAnimation();
    this.enableInteraction = false;
    this.wrapTypes = ["always", "hyphenate", "on-space", "never"];
    this.showTimeout = 0;
    this._showArrow = true;
    this._compact = false;
    this._visible = false;
    this.positionParams = void 0;
    this.destroyFns.push(this.springAnimation.addListener("update", this.updateTooltipPosition.bind(this)));
  }
  get interactive() {
    return this.enableInteraction;
  }
  setup(domManager) {
    if ("togglePopover" in getWindow().HTMLElement.prototype) {
      this.element = domManager.addChild("canvas-overlay", DEFAULT_TOOLTIP_CLASS);
      this.element.setAttribute("popover", "manual");
      this.element.className = DEFAULT_TOOLTIP_CLASS;
    }
  }
  destroy(domManager) {
    domManager.removeChild("canvas-overlay", DEFAULT_TOOLTIP_CLASS);
  }
  isVisible() {
    return this._visible;
  }
  updateTooltipPosition() {
    const { element: element2, positionParams } = this;
    if (element2 == null || positionParams == null)
      return;
    const { canvasRect, relativeRect, meta } = positionParams;
    const { x: canvasX, y: canvasY } = this.springAnimation;
    const positionType = meta.position?.type ?? this.position.type;
    const xOffset = meta.position?.xOffset ?? 0;
    const yOffset = meta.position?.yOffset ?? 0;
    const minX = relativeRect.x;
    const minY = relativeRect.y;
    const maxX = relativeRect.width - element2.clientWidth - 1 + minX;
    const maxY = relativeRect.height - element2.clientHeight + minY;
    let tooltipBounds = this.getTooltipBounds({ positionType, canvasX, canvasY, yOffset, xOffset, canvasRect });
    let position = calculatePlacement(element2.clientWidth, element2.clientHeight, relativeRect, tooltipBounds);
    if (positionType === "sparkline" && (position.x <= minX || position.x >= maxX)) {
      tooltipBounds = this.getTooltipBounds({
        positionType: "sparkline-constrained",
        canvasX,
        canvasY,
        yOffset,
        xOffset,
        canvasRect
      });
      position = calculatePlacement(element2.clientWidth, element2.clientHeight, relativeRect, tooltipBounds);
    }
    const left = clamp(minX, position.x, maxX);
    const top = clamp(minY, position.y, maxY);
    const constrained = left !== position.x || top !== position.y;
    const defaultShowArrow = (positionType === "node" || positionType === "pointer") && !constrained && !xOffset && !yOffset;
    const showArrow = meta.showArrow ?? this.showArrow ?? defaultShowArrow;
    this.updateShowArrow(showArrow);
    this.updateCompact(positionType === "sparkline" || positionType === "sparkline-constrained");
    element2.style.transform = `translate(${left}px, ${top}px)`;
  }
  /**
   * Shows tooltip at the given event's coordinates.
   * If the `html` parameter is missing, moves the existing tooltip to the new position.
   */
  show(boundingRect, canvasRect, meta, content, instantly = false) {
    const { element: element2 } = this;
    if (element2 != null && content != null) {
      element2.innerHTML = tooltipContentHtml(content);
    } else if (element2 == null || element2.innerHTML === "") {
      this.toggle(false);
      return;
    }
    const relativeRect = {
      x: boundingRect.x - canvasRect.x,
      y: boundingRect.y - canvasRect.y,
      width: boundingRect.width,
      height: boundingRect.height
    };
    this.positionParams = {
      canvasRect,
      relativeRect,
      meta
    };
    this.springAnimation.update(meta.canvasX, meta.canvasY);
    element2.style.top = `${canvasRect.top}px`;
    element2.style.left = `${canvasRect.left}px`;
    if (meta.enableInteraction) {
      this.enableInteraction = true;
      element2.style.pointerEvents = "auto";
      element2.removeAttribute("aria-hidden");
    } else {
      this.enableInteraction = false;
      element2.style.pointerEvents = "none";
      element2.setAttribute("aria-hidden", "true");
    }
    if (this.delay > 0 && !instantly) {
      this.toggle(false);
      this.showTimeout = setTimeout(() => {
        this.toggle(true);
      }, this.delay);
    } else {
      this.toggle(true);
    }
  }
  hide() {
    this.springAnimation.reset();
    this.toggle(false);
  }
  toggle(visible) {
    if (!this.element?.isConnected)
      return;
    this._visible = visible;
    const { classList } = this.element;
    const toggleClass = (name, include) => classList.toggle(`${DEFAULT_TOOLTIP_CLASS}--${name}`, include);
    if (!visible) {
      clearTimeout(this.showTimeout);
    }
    toggleClass("no-interaction", !this.enableInteraction);
    toggleClass("arrow", this._showArrow);
    toggleClass("compact", this._compact);
    classList.toggle(DEFAULT_TOOLTIP_DARK_CLASS, this.darkTheme);
    this.element.togglePopover(visible);
    if (visible) {
      this.updateTooltipPosition();
    }
    for (const wrapType of this.wrapTypes) {
      classList.toggle(`${DEFAULT_TOOLTIP_CLASS}--wrap-${wrapType}`, wrapType === this.wrapping);
    }
  }
  updateShowArrow(show) {
    this._showArrow = show;
  }
  updateCompact(compact) {
    this._compact = compact;
  }
  getTooltipBounds(opts) {
    if (!this.element)
      return {};
    const { positionType, canvasX, canvasY, yOffset, xOffset, canvasRect } = opts;
    const { clientWidth: tooltipWidth, clientHeight: tooltipHeight } = this.element;
    const bounds = { width: tooltipWidth, height: tooltipHeight };
    switch (positionType) {
      case "node":
      case "pointer": {
        bounds.top = canvasY + yOffset - tooltipHeight - 8;
        bounds.left = canvasX + xOffset - tooltipWidth / 2;
        return bounds;
      }
      case "top": {
        bounds.top = yOffset;
        bounds.left = canvasRect.width / 2 - tooltipWidth / 2 + xOffset;
        return bounds;
      }
      case "right": {
        bounds.top = canvasRect.height / 2 - tooltipHeight / 2 + yOffset;
        bounds.left = canvasRect.width - tooltipWidth / 2 + xOffset;
        return bounds;
      }
      case "left": {
        bounds.top = canvasRect.height / 2 - tooltipHeight / 2 + yOffset;
        bounds.left = xOffset;
        return bounds;
      }
      case "bottom": {
        bounds.top = canvasRect.height - tooltipHeight + yOffset;
        bounds.left = canvasRect.width / 2 - tooltipWidth / 2 + xOffset;
        return bounds;
      }
      case "top-left": {
        bounds.top = yOffset;
        bounds.left = xOffset;
        return bounds;
      }
      case "top-right": {
        bounds.top = yOffset;
        bounds.left = canvasRect.width - tooltipWidth + xOffset;
        return bounds;
      }
      case "bottom-right": {
        bounds.top = canvasRect.height - tooltipHeight + yOffset;
        bounds.left = canvasRect.width - tooltipWidth + xOffset;
        return bounds;
      }
      case "bottom-left": {
        bounds.top = canvasRect.height - tooltipHeight + yOffset;
        bounds.left = xOffset;
        return bounds;
      }
      case "sparkline": {
        bounds.top = canvasY + yOffset - tooltipHeight / 2;
        bounds.left = canvasX + xOffset + 8;
        return bounds;
      }
      case "sparkline-constrained": {
        bounds.top = canvasY + yOffset - tooltipHeight / 2;
        bounds.left = canvasX + xOffset - 8 - tooltipWidth;
        return bounds;
      }
    }
  }
};
__decorateClass([
  Validate(BOOLEAN)
], Tooltip.prototype, "enabled", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], Tooltip.prototype, "showArrow", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Tooltip.prototype, "delay", 2);
__decorateClass([
  Validate(INTERACTION_RANGE, { optional: true })
], Tooltip.prototype, "range", 2);
__decorateClass([
  Validate(TEXT_WRAP)
], Tooltip.prototype, "wrapping", 2);
__decorateClass([
  Validate(OBJECT)
], Tooltip.prototype, "position", 2);
__decorateClass([
  Validate(BOOLEAN)
], Tooltip.prototype, "darkTheme", 2);
__decorateClass([
  Validate(UNION(["extended", "canvas"]))
], Tooltip.prototype, "bounds", 2);
function pickNode(inputSeries, point, intent, exactMatchOnly) {
  const reverseSeries = [...inputSeries].reverse();
  let result;
  for (const series of reverseSeries) {
    if (!series.visible || !series.contentGroup.visible) {
      continue;
    }
    const { match, distance: distance3 } = series.pickNode(point, intent, exactMatchOnly) ?? {};
    if (!match || distance3 == null) {
      continue;
    }
    if (!result || result.distance > distance3) {
      result = { series, distance: distance3, datum: match };
    }
    if (distance3 === 0) {
      break;
    }
  }
  return result;
}
function datumBoundaryPoints(datum, domain) {
  if (datum == null || domain.length === 0) {
    return [false, false];
  }
  const datumValue = datum.valueOf();
  const d0 = domain[0];
  const d1 = domain[domain.length - 1];
  if (typeof d0 === "string") {
    return [datumValue === d0, datumValue === d1];
  }
  let min = d0.valueOf();
  let max = d1.valueOf();
  if (min > max) {
    [min, max] = [max, min];
  }
  return [datumValue === min, datumValue === max];
}
function datumStylerProperties(datum, xKey, yKey, xDomain, yDomain) {
  const { xValue, yValue } = datum;
  const [min, max] = datumBoundaryPoints(yValue, yDomain);
  const [first, last] = datumBoundaryPoints(xValue, xDomain);
  return {
    datum,
    xKey,
    yKey,
    xValue,
    yValue,
    first,
    last,
    min,
    max
  };
}
function visibleRangeIndices(length2, [range0, range1], xRange) {
  const xMinIndex = findMinIndex(0, length2 - 1, (index) => {
    const x1 = xRange(index)?.[1];
    return !Number.isFinite(x1) || x1 > range0;
  }) ?? 0;
  let xMaxIndex = findMaxIndex(0, length2 - 1, (index) => {
    const x0 = xRange(index)?.[0];
    return !Number.isFinite(x0) || x0 < range1;
  }) ?? length2 - 1;
  xMaxIndex = Math.min(xMaxIndex + 1, length2);
  return [xMinIndex, xMaxIndex];
}
var SeriesAreaManager = class extends BaseManager {
  constructor(chart) {
    super();
    this.chart = chart;
    this.id = createId(this);
    this.series = [];
    this.highlight = {
      /** Last received event that still needs to be applied. */
      pendingHoverEvent: void 0,
      /** Last applied event. */
      appliedHoverEvent: void 0,
      /** Last applied event, which has been temporarily stashed during the main chart update cycle. */
      stashedHoverEvent: void 0
    };
    this.tooltip = {
      lastHover: void 0
    };
    this.hoverDevice = "mouse";
    this.focus = {
      sortedSeries: [],
      series: void 0,
      seriesIndex: 0,
      datumIndex: 0,
      datum: void 0
    };
    this.hoverScheduler = debouncedAnimationFrame(() => {
      if (!this.tooltip.lastHover && !this.highlight.pendingHoverEvent)
        return;
      if (this.chart.getUpdateType() <= 4) {
        this.hoverScheduler.schedule();
        return;
      }
      if (this.highlight.pendingHoverEvent) {
        this.handleHoverHighlight(false);
      }
      if (this.tooltip.lastHover) {
        this.handleHoverTooltip(this.tooltip.lastHover, false);
      }
    });
    const mouseMoveStates = 32 | 8 | 1;
    const keyState = 32 | 2;
    const contextState = 63;
    const { domManager } = chart.ctx;
    const domElementClass = "series-area";
    const label1 = domManager.addChild(domElementClass, "series-area-aria-label1");
    const label2 = domManager.addChild(domElementClass, "series-area-aria-label2");
    this.seriesWidget = new NativeWidget(domManager.getParent(domElementClass));
    this.chartWidget = new NativeWidget(domManager.getParent("canvas-proxy"));
    this.containerWidget = new NativeWidget(domManager.getParent("canvas-container"));
    chart.ctx.regionManager.initRegions(this.containerWidget, this.seriesWidget);
    this.swapChain = new FocusSwapChain(label1, label2, this.id, "img");
    this.swapChain.addListener("blur", () => this.onBlur(keyState));
    this.swapChain.addListener("focus", () => this.onFocus(keyState));
    this.focusIndicator = new FocusIndicator(this.swapChain);
    this.focusIndicator.overrideFocusVisible(chart.mode === "integrated" ? false : void 0);
    this.chart.ctx.keyNavManager.focusIndicator = this.focusIndicator;
    const seriesRegion = chart.ctx.regionManager.getRegion("series");
    this.destroyFns.push(
      () => chart.ctx.domManager.removeChild(domElementClass, "series-area-aria-label1"),
      () => chart.ctx.domManager.removeChild(domElementClass, "series-area-aria-label2"),
      seriesRegion.addListener("drag", (event) => this.onHoverLikeEvent(event), mouseMoveStates),
      seriesRegion.addListener("hover", (event) => this.onHover(event), mouseMoveStates),
      seriesRegion.addListener("leave", () => this.onLeave(), mouseMoveStates),
      chart.ctx.animationManager.addListener("animation-start", () => this.clearAll()),
      chart.ctx.domManager.addListener("resize", () => this.clearAll()),
      chart.ctx.highlightManager.addListener("highlight-change", (event) => this.changeHighlightDatum(event)),
      chart.ctx.keyNavManager.addListener("nav-hori", (event) => this.onNavHori(event), keyState),
      chart.ctx.keyNavManager.addListener("nav-vert", (event) => this.onNavVert(event), keyState),
      chart.ctx.keyNavManager.addListener("submit", (event) => this.onSubmit(event), keyState),
      chart.ctx.layoutManager.addListener("layout:complete", (event) => this.layoutComplete(event)),
      chart.ctx.regionManager.listenAll("contextmenu", (event) => this.onContextMenu(event), contextState),
      chart.ctx.regionManager.listenAll("click", (event) => this.onClick(event)),
      chart.ctx.regionManager.listenAll("dblclick", (event) => this.onClick(event)),
      chart.ctx.updateService.addListener("pre-scene-render", () => this.preSceneRender()),
      chart.ctx.zoomManager.addListener("zoom-change", () => this.clearAll()),
      chart.ctx.zoomManager.addListener("zoom-pan-start", () => this.clearAll())
    );
  }
  dataChanged() {
    var _a;
    (_a = this.highlight).stashedHoverEvent ?? (_a.stashedHoverEvent = this.highlight.appliedHoverEvent);
    this.chart.ctx.tooltipManager.removeTooltip(this.id);
    this.focusIndicator.updateBounds(void 0);
    this.clearHighlight();
  }
  preSceneRender() {
    if (this.focusIndicator.isFocusVisible()) {
      this.handleSeriesFocus(0, 0, true);
    }
    if (this.highlight.stashedHoverEvent != null) {
      this.highlight.pendingHoverEvent = this.highlight.stashedHoverEvent;
      this.highlight.stashedHoverEvent = void 0;
      this.handleHoverHighlight(true);
    }
    if (this.tooltip.lastHover != null) {
      this.handleHoverTooltip(this.tooltip.lastHover, true);
    }
  }
  update(type, opts) {
    this.chart.ctx.updateService.update(type, opts);
  }
  seriesChanged(series) {
    this.focus.sortedSeries = [...series].sort((a, b) => {
      let fpA = a.properties.focusPriority ?? Infinity;
      let fpB = b.properties.focusPriority ?? Infinity;
      if (fpA === fpB) {
        [fpA, fpB] = [a._declarationOrder, b._declarationOrder];
      }
      if (fpA < fpB) {
        return -1;
      } else if (fpA > fpB) {
        return 1;
      }
      return 0;
    });
    this.series = series;
  }
  layoutComplete(event) {
    this.seriesRect = event.series.rect;
    this.hoverRect = event.series.paddedRect;
    this.seriesWidget.setBounds(event.series.paddedRect);
    this.chartWidget.setBounds(event.chart);
  }
  onContextMenu(event) {
    const { Default: Default2, ContextMenu } = InteractionState;
    if (event.region === "root") {
      if (this.chart.ctx.interactionManager.getState() & (Default2 | ContextMenu)) {
        this.chart.ctx.contextMenuRegistry.dispatchContext("all", event, {});
      }
      return;
    }
    let pickedNode;
    let position;
    if (this.focusIndicator.isFocusVisible()) {
      pickedNode = this.chart.ctx.highlightManager.getActiveHighlight();
      if (pickedNode && this.seriesRect && pickedNode.midPoint) {
        position = Transformable.toCanvasPoint(
          pickedNode.series.contentGroup,
          pickedNode.midPoint.x,
          pickedNode.midPoint.y
        );
      }
    } else if (this.chart.ctx.interactionManager.getState() & (Default2 | ContextMenu)) {
      const match = pickNode(this.series, { x: event.regionX, y: event.regionY }, "context-menu");
      if (match) {
        this.chart.ctx.highlightManager.updateHighlight(this.id);
        pickedNode = match.datum;
      }
    }
    const pickedSeries = pickedNode?.series;
    this.clearAll();
    this.chart.ctx.contextMenuRegistry.dispatchContext(
      "series-area",
      event,
      { pickedSeries, pickedNode },
      position
    );
  }
  onLeave() {
    this.chart.ctx.cursorManager.updateCursor(this.id);
    if (!this.focusIndicator.isFocusVisible())
      this.clearAll();
  }
  onHover(event) {
    this.hoverDevice = "mouse";
    this.onHoverLikeEvent(event);
  }
  onHoverLikeEvent(event) {
    if (excludesType(event, "drag")) {
      this.tooltip.lastHover = event;
    }
    this.highlight.pendingHoverEvent = event;
    this.hoverScheduler.schedule();
    if (this.chart.ctx.interactionManager.getState() === 32) {
      const { regionX: x, regionY: y } = event;
      const found = pickNode(this.series, { x, y }, "event");
      if (found?.series.hasEventListener("nodeClick") || found?.series.hasEventListener("nodeDoubleClick")) {
        this.chart.ctx.cursorManager.updateCursor(this.id, "pointer");
      } else {
        this.chart.ctx.cursorManager.updateCursor(this.id);
      }
    }
  }
  onClick(event) {
    this.hoverDevice = "mouse";
    this.onHoverLikeEvent(event);
    if (this.seriesRect?.containsPoint(event.canvasX, event.canvasY) && this.checkSeriesNodeClick(event)) {
      this.update(
        4
        /* SERIES_UPDATE */
      );
      event.preventDefault();
      return;
    }
    const newEvent = { type: event.type === "click" ? "click" : "doubleClick", event: event.sourceEvent };
    this.chart.fireEvent(newEvent);
  }
  onFocus(allowedStates) {
    if (!(this.chart.ctx.interactionManager.getState() & allowedStates))
      return;
    this.hoverDevice = this.focusIndicator.isFocusVisible() ? "keyboard" : "mouse";
    this.handleFocus(0, 0);
  }
  onBlur(allowedStates) {
    if (!(this.chart.ctx.interactionManager.getState() & allowedStates))
      return;
    this.hoverDevice = "mouse";
    this.clearAll();
    this.focusIndicator.overrideFocusVisible(void 0);
  }
  onNavVert(event) {
    this.hoverDevice = "keyboard";
    this.focus.seriesIndex += event.delta;
    this.handleFocus(event.delta, 0);
    event.preventDefault();
  }
  onNavHori(event) {
    this.hoverDevice = "keyboard";
    this.focus.datumIndex += event.delta;
    this.handleFocus(0, event.delta);
    event.preventDefault();
  }
  onSubmit(event) {
    const { series, datum } = this.focus;
    const sourceEvent = event.sourceEvent.sourceEvent;
    if (series !== void 0 && datum !== void 0) {
      series.fireNodeClickEvent(sourceEvent, datum);
    } else {
      this.chart.fireEvent({
        type: "click",
        event: sourceEvent
      });
    }
    event.preventDefault();
  }
  checkSeriesNodeClick(event) {
    let point = { x: event.regionX, y: event.regionY };
    if (event.region !== "series") {
      point = Transformable.fromCanvasPoint(this.chart.seriesRoot, event.canvasX, event.canvasY);
    }
    const result = pickNode(this.series, point, "event");
    if (result == null)
      return false;
    if (event.type === "click") {
      result.series.fireNodeClickEvent(event.sourceEvent, result.datum);
      return true;
    }
    if (event.type === "dblclick") {
      event.preventZoomDblClick = result.distance === 0;
      result.series.fireNodeDoubleClickEvent(event.sourceEvent, result.datum);
      return true;
    }
    return false;
  }
  handleFocus(seriesIndexDelta, datumIndexDelta) {
    const overlayFocus = this.chart.overlays.getFocusInfo(this.chart.ctx.localeManager);
    if (overlayFocus == null) {
      this.handleSeriesFocus(seriesIndexDelta, datumIndexDelta);
    } else {
      this.focusIndicator.updateBounds(new BBox(0, 0, overlayFocus.rect.width, overlayFocus.rect.height));
    }
  }
  handleSeriesFocus(otherIndexDelta, datumIndexDelta, refresh = false) {
    if (this.chart.chartType === "hierarchy") {
      this.handleHierarchySeriesFocus(otherIndexDelta, datumIndexDelta, refresh);
      return;
    }
    const { focus, seriesRect } = this;
    const visibleSeries = focus.sortedSeries.filter((s) => s.visible);
    if (visibleSeries.length === 0)
      return;
    focus.seriesIndex = clamp(0, focus.seriesIndex, visibleSeries.length - 1);
    focus.series = visibleSeries[focus.seriesIndex];
    const { datumIndex, seriesIndex: otherIndex } = focus;
    const pick = focus.series.pickFocus({ datumIndex, datumIndexDelta, otherIndex, otherIndexDelta, seriesRect });
    this.updatePickedFocus(pick, refresh);
  }
  handleHierarchySeriesFocus(otherIndexDelta, datumIndexDelta, refresh) {
    this.focus.series = this.focus.sortedSeries[0];
    const {
      focus: { series, seriesIndex: otherIndex, datumIndex },
      seriesRect
    } = this;
    if (series == null)
      return;
    const pick = series.pickFocus({ datumIndex, datumIndexDelta, otherIndex, otherIndexDelta, seriesRect });
    this.updatePickedFocus(pick, refresh);
  }
  updatePickedFocus(pick, refresh) {
    const { focus, hoverRect, seriesRect } = this;
    if (pick === void 0 || focus.series === void 0 || hoverRect === void 0)
      return;
    const { datum, datumIndex } = pick;
    focus.datumIndex = datumIndex;
    focus.datum = datum;
    if (this.focusIndicator.isFocusVisible()) {
      this.chart.ctx.animationManager.reset();
    }
    if (this.focusIndicator.isFocusVisible()) {
      let focusBBox = getPickedFocusBBox(pick);
      if (seriesRect != null) {
        const newBBox = focusBBox.clone();
        newBBox.x += seriesRect.x;
        newBBox.y += seriesRect.y;
        focusBBox = newBBox;
      }
      const { x, y } = focusBBox.computeCenter();
      if (!hoverRect.containsPoint(x, y)) {
        this.chart.ctx.zoomManager.panToBBox(this.id, hoverRect, focusBBox);
      }
    }
    drawPickedFocus(
      seriesRect != null ? new BBox(0, 0, seriesRect.width, seriesRect?.height) : void 0,
      this.focusIndicator,
      pick,
      seriesRect?.x,
      seriesRect?.y
    );
    const keyboardEvent = makeKeyboardPointerEvent(hoverRect, pick);
    if (keyboardEvent !== void 0 && this.hoverDevice === "keyboard") {
      this.tooltip.lastHover = void 0;
      this.highlight.appliedHoverEvent = void 0;
      this.highlight.pendingHoverEvent = void 0;
      this.highlight.stashedHoverEvent = void 0;
      const tooltipContent = focus.series.getTooltipContent(datum);
      const meta = TooltipManager.makeTooltipMeta(keyboardEvent, datum);
      this.chart.ctx.highlightManager.updateHighlight(this.id, datum);
      this.chart.ctx.tooltipManager.updateTooltip(this.id, meta, tooltipContent);
      if (!refresh) {
        this.swapChain.update(this.getDatumAriaText(datum, tooltipContent));
      }
    }
  }
  getDatumAriaText(datum, tooltipContent) {
    const description = tooltipContent == null ? "" : tooltipContentAriaLabel(tooltipContent);
    return this.chart.ctx.localeManager.t("ariaAnnounceHoverDatum", {
      datum: datum.series.getDatumAriaText?.(datum, description) ?? description
    });
  }
  clearHighlight() {
    this.highlight.pendingHoverEvent = void 0;
    this.highlight.appliedHoverEvent = void 0;
    this.chart.ctx.highlightManager.updateHighlight(this.id);
  }
  clearTooltip() {
    this.chart.ctx.tooltipManager.removeTooltip(this.id);
    this.tooltip.lastHover = void 0;
  }
  clearAll() {
    this.clearHighlight();
    this.clearTooltip();
    this.focusIndicator.updateBounds(void 0);
  }
  handleHoverHighlight(redisplay) {
    this.highlight.appliedHoverEvent = this.highlight.pendingHoverEvent;
    this.highlight.pendingHoverEvent = void 0;
    const event = this.highlight.appliedHoverEvent;
    if (!event)
      return;
    const state = this.chart.ctx.interactionManager.getState();
    if (state !== 32 && state !== 8 && state !== 1)
      return;
    const { canvasX, canvasY } = event;
    if (redisplay ? this.chart.ctx.animationManager.isActive() : !this.hoverRect?.containsPoint(canvasX, canvasY)) {
      this.clearHighlight();
      return;
    }
    let pickCoords = { x: event.regionX, y: event.regionY };
    if (event.region !== "series") {
      pickCoords = Transformable.fromCanvasPoint(this.chart.seriesRoot, canvasX, canvasY);
    }
    const { range: range3 } = this.chart.highlight;
    const intent = range3 === "tooltip" ? "highlight-tooltip" : "highlight";
    const found = pickNode(this.series, pickCoords, intent);
    if (found) {
      this.chart.ctx.highlightManager.updateHighlight(this.id, found.datum);
      this.hoverDevice = "mouse";
      return;
    }
    this.chart.ctx.highlightManager.updateHighlight(this.id);
  }
  handleHoverTooltip(event, redisplay) {
    const state = this.chart.ctx.interactionManager.getState();
    if (state !== 32 && state !== 8 && state !== 1)
      return;
    const { canvasX, canvasY, regionX, regionY } = event;
    const targetElement = event.sourceEvent.target;
    if (redisplay ? this.chart.ctx.animationManager.isActive() : !this.hoverRect?.containsPoint(canvasX, canvasY)) {
      if (this.hoverDevice == "mouse")
        this.clearTooltip();
      return;
    }
    if (targetElement && this.chart.tooltip.interactive && this.chart.ctx.domManager.isManagedChildDOMElement(targetElement, "canvas-overlay", DEFAULT_TOOLTIP_CLASS)) {
      return;
    }
    let pickCoords = { x: regionX, y: regionY };
    if (event.region !== "series") {
      pickCoords = Transformable.fromCanvasPoint(this.chart.seriesRoot, canvasX, canvasY);
    }
    const pick = pickNode(this.series, pickCoords, "tooltip");
    if (!pick) {
      if (this.hoverDevice == "mouse")
        this.clearTooltip();
      return;
    }
    this.hoverDevice = "mouse";
    const content = pick.series.getTooltipContent(pick.datum);
    const tooltipEnabled = this.chart.tooltip.enabled && pick.series.tooltipEnabled;
    const shouldUpdateTooltip = tooltipEnabled && content != null;
    if (shouldUpdateTooltip) {
      const meta = TooltipManager.makeTooltipMeta(event, pick.datum);
      this.chart.ctx.tooltipManager.updateTooltip(this.id, meta, content);
    }
  }
  changeHighlightDatum(event) {
    const seriesToUpdate = /* @__PURE__ */ new Set();
    const { series: newSeries = void 0, datum: newDatum } = event.currentHighlight ?? {};
    const { series: lastSeries = void 0, datum: lastDatum } = event.previousHighlight ?? {};
    if (lastSeries) {
      seriesToUpdate.add(lastSeries);
    }
    if (newSeries) {
      seriesToUpdate.add(newSeries);
    }
    if (lastSeries?.properties.cursor && lastDatum) {
      this.chart.ctx.cursorManager.updateCursor(lastSeries.id);
    }
    if (newSeries?.properties.cursor && newSeries?.properties.cursor !== "default" && newDatum) {
      this.chart.ctx.cursorManager.updateCursor(newSeries.id, newSeries.properties.cursor);
    }
    const updateAll = newSeries == null || lastSeries == null;
    if (updateAll) {
      this.update(
        4
        /* SERIES_UPDATE */
      );
    } else {
      this.update(4, { seriesToUpdate });
    }
  }
};
var SERIES_THRESHOLD_FOR_AGGRESSIVE_LAYER_REDUCTION = 30;
var SeriesLayerManager = class {
  constructor(seriesRoot) {
    this.seriesRoot = seriesRoot;
    this.groups = /* @__PURE__ */ new Map();
    this.series = /* @__PURE__ */ new Map();
    this.expectedSeriesCount = 1;
    this.mode = "normal";
  }
  setSeriesCount(count) {
    this.expectedSeriesCount = count;
  }
  requestGroup(seriesConfig) {
    const { internalId, type, contentGroup: seriesContentGroup, seriesGrouping } = seriesConfig;
    const { groupIndex = internalId } = seriesGrouping ?? {};
    const seriesInfo = this.series.get(internalId);
    if (seriesInfo != null) {
      throw new Error(`AG Charts - series already has an allocated layer: ${JSON.stringify(seriesInfo)}`);
    }
    if (this.series.size === 0) {
      this.mode = this.expectedSeriesCount >= SERIES_THRESHOLD_FOR_AGGRESSIVE_LAYER_REDUCTION ? "aggressive-grouping" : "normal";
    }
    let group = this.groups.get(type);
    if (group == null) {
      group = /* @__PURE__ */ new Map();
      this.groups.set(type, group);
    }
    const lookupIndex = this.lookupIdx(groupIndex);
    let groupInfo = group.get(lookupIndex);
    if (groupInfo == null) {
      groupInfo = {
        type,
        id: lookupIndex,
        seriesIds: [],
        group: this.seriesRoot.appendChild(
          new Group({
            name: `${seriesConfig.contentGroup.name ?? type}-managed-layer`,
            zIndex: seriesConfig.contentGroup.zIndex,
            // Set in updateLayerCompositing
            renderToOffscreenCanvas: false
          })
        )
      };
      group.set(lookupIndex, groupInfo);
    }
    this.series.set(internalId, { layerState: groupInfo, seriesConfig });
    groupInfo.seriesIds.push(internalId);
    groupInfo.group.appendChild(seriesContentGroup);
    return groupInfo.group;
  }
  changeGroup(seriesConfig) {
    const { internalId, seriesGrouping, type, contentGroup, oldGrouping } = seriesConfig;
    const { groupIndex = internalId } = seriesGrouping ?? {};
    if (this.groups.get(type)?.get(groupIndex)?.seriesIds.includes(internalId)) {
      return;
    }
    if (this.series.has(internalId)) {
      this.releaseGroup({
        internalId,
        seriesGrouping: oldGrouping,
        type,
        contentGroup
      });
    }
    this.requestGroup(seriesConfig);
  }
  releaseGroup(seriesConfig) {
    const { internalId, contentGroup, type } = seriesConfig;
    if (!this.series.has(internalId)) {
      throw new Error(`AG Charts - series doesn't have an allocated layer: ${internalId}`);
    }
    const groupInfo = this.series.get(internalId)?.layerState;
    if (groupInfo) {
      groupInfo.seriesIds = groupInfo.seriesIds.filter((v) => v !== internalId);
      groupInfo.group.removeChild(contentGroup);
    }
    if (groupInfo?.seriesIds.length === 0) {
      this.seriesRoot.removeChild(groupInfo.group);
      this.groups.get(groupInfo.type)?.delete(groupInfo.id);
      this.groups.get(type)?.delete(internalId);
    } else if (groupInfo != null && groupInfo.seriesIds.length > 0) {
      groupInfo.group.zIndex = this.getLowestSeriesZIndex(groupInfo.seriesIds);
    }
    this.series.delete(internalId);
  }
  updateLayerCompositing() {
    this.groups.forEach((groups) => {
      groups.forEach((groupInfo) => {
        const { group, seriesIds } = groupInfo;
        let renderToOffscreenCanvas;
        if (seriesIds.length === 0) {
          renderToOffscreenCanvas = false;
        } else if (seriesIds.length > 1) {
          renderToOffscreenCanvas = true;
        } else {
          const series = this.series.get(seriesIds[0]);
          renderToOffscreenCanvas = series?.seriesConfig.renderToOffscreenCanvas() === true;
        }
        group.renderToOffscreenCanvas = renderToOffscreenCanvas;
        group.zIndex = this.getLowestSeriesZIndex(seriesIds);
      });
    });
  }
  lookupIdx(groupIndex) {
    if (this.mode === "normal") {
      return groupIndex;
    }
    if (typeof groupIndex === "string") {
      groupIndex = Number(groupIndex.split("-").at(-1));
      if (!groupIndex) {
        return 0;
      }
    }
    return Math.floor(
      clamp(0, groupIndex / this.expectedSeriesCount, 1) * SERIES_THRESHOLD_FOR_AGGRESSIVE_LAYER_REDUCTION
    );
  }
  destroy() {
    this.groups.forEach((groups) => {
      groups.forEach((groupInfo) => {
        this.seriesRoot.removeChild(groupInfo.group);
      });
    });
    this.groups.clear();
    this.series.clear();
  }
  getLowestSeriesZIndex(seriesIds) {
    const lowestSeriesZIndex = seriesIds.reduce((currentLowest, seriesId) => {
      const series = this.series.get(seriesId);
      const zIndex = series?.seriesConfig.contentGroup.zIndex;
      if (currentLowest == null || zIndex == null)
        return zIndex;
      return compareZIndex(currentLowest, zIndex) <= 0 ? currentLowest : zIndex;
    }, void 0);
    return lowestSeriesZIndex ?? 1;
  }
};
var DataWindowProcessor = class {
  constructor(chart, dataService, updateService, zoomManager, animationManager) {
    this.chart = chart;
    this.dataService = dataService;
    this.updateService = updateService;
    this.zoomManager = zoomManager;
    this.animationManager = animationManager;
    this.dirtyZoom = false;
    this.dirtyDataSource = false;
    this.lastAxisZooms = /* @__PURE__ */ new Map();
    this.destroyFns = [];
    this.destroyFns.push(
      this.dataService.addListener("data-source-change", () => this.onDataSourceChange()),
      this.dataService.addListener("data-load", () => this.onDataLoad()),
      this.dataService.addListener("data-error", () => this.onDataError()),
      this.updateService.addListener("update-complete", () => this.onUpdateComplete()),
      this.zoomManager.addListener("zoom-change", () => this.onZoomChange())
    );
  }
  destroy() {
    this.destroyFns.forEach((cb) => cb());
  }
  onDataLoad() {
    this.animationManager.skip();
    this.updateService.update(
      1
      /* UPDATE_DATA */
    );
  }
  onDataError() {
    this.updateService.update(
      3
      /* PERFORM_LAYOUT */
    );
  }
  onDataSourceChange() {
    this.dirtyDataSource = true;
  }
  onUpdateComplete() {
    if (!this.dirtyZoom && !this.dirtyDataSource)
      return;
    this.updateWindow();
  }
  onZoomChange() {
    this.dirtyZoom = true;
  }
  updateWindow() {
    if (!this.dataService.isLazy())
      return;
    const axis = this.getValidAxis();
    let window2;
    let shouldRefresh = true;
    if (axis) {
      const zoom = this.zoomManager.getAxisZoom(axis.id);
      window2 = this.getAxisWindow(axis, zoom);
      shouldRefresh = this.shouldRefresh(axis, zoom);
    }
    this.dirtyZoom = false;
    this.dirtyDataSource = false;
    if (!shouldRefresh)
      return;
    this.dataService.load({ windowStart: window2?.min, windowEnd: window2?.max });
  }
  getValidAxis() {
    return this.chart.axes.find((axis) => axis.type === "time");
  }
  shouldRefresh(axis, zoom) {
    if (this.dirtyDataSource)
      return true;
    if (!this.dirtyZoom)
      return false;
    const lastZoom = this.lastAxisZooms.get(axis.id);
    if (lastZoom && zoom.min === lastZoom.min && zoom.max === lastZoom.max) {
      return false;
    }
    this.lastAxisZooms.set(axis.id, zoom);
    return true;
  }
  getAxisWindow(axis, zoom) {
    const domain = axis.scale.getDomain?.();
    if (!zoom || !domain || domain.length === 0 || isNaN(Number(domain[0])))
      return;
    const diff2 = Number(domain[1]) - Number(domain[0]);
    const min = new Date(Number(domain[0]) + diff2 * zoom.min);
    const max = new Date(Number(domain[0]) + diff2 * zoom.max);
    return { min, max };
  }
};
var isSafariRegexp = /^((?!chrome|android).)*safari/i;
var safariVersionRegexp = /Version\/(\d+(\.\d+)?)/;
var isChromeRegexp = /Chrome/;
var chromeVersionRegexp = /Chrome\/(\d+)/;
var isEdge = /Edg/;
var isOpera = /OPR/;
function isUnsupportedBrowser() {
  const { userAgent } = getWindow().navigator;
  if (isSafariRegexp.test(userAgent)) {
    const version = parseFloat(safariVersionRegexp.exec(userAgent)?.[1] ?? "0");
    const supported = Math.floor(version) > 16;
    if (!supported) {
      Logger.warnOnce(`Unsupported Safari version: ${version} ; ${userAgent}`);
    }
    return !supported;
  } else if (isChromeRegexp.test(userAgent) && !isEdge.test(userAgent) && !isOpera.test(userAgent)) {
    const version = parseInt(chromeVersionRegexp.exec(userAgent)?.[1] ?? "0", 10);
    const supported = version > 126;
    if (!supported) {
      Logger.warnOnce(`Unsupported Chrome version: ${version} ; ${userAgent}`);
    }
    return !supported;
  }
  return false;
}
var OverlaysProcessor = class {
  constructor(chartLike, overlays, dataService, layoutManager, localeManager, animationManager, domManager) {
    this.chartLike = chartLike;
    this.overlays = overlays;
    this.dataService = dataService;
    this.layoutManager = layoutManager;
    this.localeManager = localeManager;
    this.animationManager = animationManager;
    this.domManager = domManager;
    this.destroyFns = [];
    this.overlayElem = this.domManager.addChild("canvas-overlay", "overlay");
    this.overlayElem.role = "status";
    this.overlayElem.ariaAtomic = "false";
    this.overlayElem.ariaLive = "polite";
    this.overlayElem.classList.toggle(DEFAULT_OVERLAY_CLASS);
    this.destroyFns.push(this.layoutManager.addListener("layout:complete", (e) => this.onLayoutComplete(e)));
  }
  destroy() {
    this.destroyFns.forEach((cb) => cb());
    this.domManager.removeStyles("overlays");
    this.domManager.removeChild("canvas-overlay", "overlay");
  }
  onLayoutComplete({ series: { rect } }) {
    const isLoading = this.dataService.isLoading();
    const hasData = this.chartLike.series.some((s) => s.hasData);
    const anySeriesVisible = this.chartLike.series.some((s) => s.visible);
    if (this.overlays.darkTheme) {
      this.overlayElem.classList.add(DEFAULT_OVERLAY_DARK_CLASS);
    } else {
      this.overlayElem.classList.remove(DEFAULT_OVERLAY_DARK_CLASS);
    }
    this.overlayElem.style.left = `${rect.x}px`;
    this.overlayElem.style.top = `${rect.y}px`;
    this.overlayElem.style.width = `${rect.width}px`;
    this.overlayElem.style.height = `${rect.height}px`;
    const loadingShown = isLoading;
    const noDataShown = !isLoading && !hasData;
    const noVisibleSeriesShown = hasData && !anySeriesVisible;
    const unsupportedBrowser = this.overlays.unsupportedBrowser.enabled && isUnsupportedBrowser();
    if (loadingShown) {
      this.showOverlay(this.overlays.loading, rect);
    } else {
      this.hideOverlay(this.overlays.loading);
    }
    if (noDataShown) {
      this.showOverlay(this.overlays.noData, rect);
    } else {
      this.hideOverlay(this.overlays.noData);
    }
    if (noVisibleSeriesShown) {
      this.showOverlay(this.overlays.noVisibleSeries, rect);
    } else {
      this.hideOverlay(this.overlays.noVisibleSeries);
    }
    if (unsupportedBrowser) {
      this.showOverlay(this.overlays.unsupportedBrowser, rect);
    } else {
      this.hideOverlay(this.overlays.unsupportedBrowser);
    }
    const shown = loadingShown || noDataShown || noVisibleSeriesShown || unsupportedBrowser;
    setAttribute(this.overlayElem, "aria-hidden", !shown);
  }
  showOverlay(overlay, seriesRect) {
    if (!overlay.enabled)
      return;
    const element2 = overlay.getElement(this.animationManager, this.localeManager, seriesRect);
    this.overlayElem.appendChild(element2);
  }
  hideOverlay(overlay) {
    overlay.removeElement(() => {
      this.overlayElem.innerText = "\xA0";
    }, this.animationManager);
  }
};
var debug = Debug.create(true, "opts");
var SeriesArea = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.padding = new Padding(0);
  }
};
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], SeriesArea.prototype, "clip", 2);
__decorateClass([
  Validate(OBJECT)
], SeriesArea.prototype, "padding", 2);
var _Chart = class _Chart2 extends Observable {
  constructor(options, resources) {
    var _a;
    super();
    this.id = createId(this);
    this.seriesRoot = new TranslatableGroup({
      name: `${this.id}-series-root`,
      zIndex: 4
      /* SERIES_LAYER */
    });
    this.annotationRoot = new TranslatableGroup({
      name: `${this.id}-annotation-root`,
      zIndex: 8
      /* SERIES_ANNOTATION */
    });
    this.titleGroup = new Group({
      name: "titles",
      zIndex: 12
      /* SERIES_LABEL */
    });
    this.debug = Debug.create();
    this.extraDebugStats = {};
    this.data = [];
    this._firstAutoSize = true;
    this._autoSizeNotify = new AsyncAwaitQueue();
    this.padding = new Padding(20);
    this.seriesArea = new SeriesArea();
    this.keyboard = new Keyboard();
    this.mode = "standalone";
    this.chartCaptions = new ChartCaptions();
    this.suppressFieldDotNotation = false;
    this.destroyed = false;
    this._destroyFns = [];
    this.skipSync = false;
    this.chartAnimationPhase = "initial";
    this.modulesManager = new ModulesManager();
    this.processors = [];
    this.queuedUserOptions = [];
    this.queuedChartOptions = [];
    this.firstApply = true;
    this._pendingFactoryUpdatesCount = 0;
    this._performUpdateSkipAnimations = false;
    this._performUpdateNotify = new AsyncAwaitQueue();
    this.performUpdateType = 7;
    this.runningUpdateType = 7;
    this.updateShortcutCount = 0;
    this.seriesToUpdate = /* @__PURE__ */ new Set();
    this.updateMutex = new Mutex();
    this.updateRequestors = {};
    this.performUpdateTrigger = debouncedCallback(({ count }) => {
      if (this.destroyed)
        return;
      this.updateMutex.acquire(async () => {
        try {
          await this.performUpdate(count);
        } catch (error) {
          Logger.error("update error", error);
        }
      }).catch((e) => Logger.errorOnce(e));
    });
    this._performUpdateSplits = {};
    this.axes = [];
    this.series = [];
    this._cachedData = void 0;
    this.onSeriesNodeClick = (event) => {
      this.fireEvent({ ...event, type: "seriesNodeClick" });
    };
    this.onSeriesNodeDoubleClick = (event) => {
      this.fireEvent({ ...event, type: "seriesNodeDoubleClick" });
    };
    this.onSeriesVisibilityChange = (event) => {
      this.fireEvent(event);
    };
    this.seriesGroupingChanged = (event) => {
      if (!(event instanceof SeriesGroupingChangedEvent))
        return;
      const { series, seriesGrouping, oldGrouping } = event;
      if (series.contentGroup.isRoot())
        return;
      this.seriesLayerManager.changeGroup({
        internalId: series.internalId,
        type: series.type,
        contentGroup: series.contentGroup,
        renderToOffscreenCanvas: () => series.renderToOffscreenCanvas(),
        seriesGrouping,
        oldGrouping
      });
    };
    this.chartOptions = options;
    const scene = resources?.scene;
    const container = resources?.container ?? options.processedOptions.container ?? void 0;
    const styleContainer = resources?.styleContainer ?? options.specialOverrides.styleContainer;
    const root = new Group({ name: "root" });
    root.visible = false;
    root.append(this.seriesRoot);
    root.append(this.annotationRoot);
    root.append(this.titleGroup);
    this.titleGroup.append(this.title.node);
    this.titleGroup.append(this.subtitle.node);
    this.titleGroup.append(this.footnote.node);
    this.tooltip = new Tooltip();
    this.seriesLayerManager = new SeriesLayerManager(this.seriesRoot);
    this.mode = options.userOptions.mode ?? this.mode;
    const ctx = this.ctx = new ChartContext(this, {
      chartType: this.getChartType(),
      scene,
      root,
      container,
      styleContainer,
      syncManager: new SyncManager(this),
      pixelRatio: options.specialOverrides.overrideDevicePixelRatio,
      updateCallback: (type, opts) => this.update(type, opts),
      updateMutex: this.updateMutex
    });
    this._destroyFns.push(
      ctx.domManager.addListener("resize", () => this.parentResize(ctx.domManager.containerSize))
    );
    this.overlays = new ChartOverlays();
    (_a = this.overlays.loading).renderer ?? (_a.renderer = () => getLoadingSpinner(this.overlays.loading.getText(ctx.localeManager), ctx.animationManager.defaultDuration));
    this.processors = [
      new DataWindowProcessor(this, ctx.dataService, ctx.updateService, ctx.zoomManager, ctx.animationManager),
      new OverlaysProcessor(
        this,
        this.overlays,
        ctx.dataService,
        ctx.layoutManager,
        ctx.localeManager,
        ctx.animationManager,
        ctx.domManager
      )
    ];
    this.highlight = new ChartHighlight();
    this.container = container;
    const moduleContext = this.getModuleContext();
    ctx.domManager.setDataBoolean("animating", false);
    this.seriesAreaManager = new SeriesAreaManager(this.initSeriesAreaDependencies());
    this._destroyFns.push(
      ctx.layoutManager.registerElement(0, (e) => {
        e.layoutBox.shrink(this.padding.toJson());
        this.chartCaptions.positionCaptions(e);
      }),
      ctx.layoutManager.addListener("layout:complete", (e) => this.chartCaptions.positionAbsoluteCaptions(e)),
      ctx.dataService.addListener("data-load", (event) => {
        this.data = event.data;
      }),
      this.title.registerInteraction(moduleContext, "beforebegin"),
      this.subtitle.registerInteraction(moduleContext, "beforebegin"),
      this.footnote.registerInteraction(moduleContext, "afterend"),
      ctx.interactionManager.addListener("page-left", () => this.destroy()),
      ctx.animationManager.addListener("animation-frame", () => {
        this.update(
          6
          /* SCENE_RENDER */
        );
      }),
      ctx.animationManager.addListener("animation-start", () => ctx.domManager.setDataBoolean("animating", true)),
      ctx.animationManager.addListener("animation-stop", () => ctx.domManager.setDataBoolean("animating", false)),
      ctx.zoomManager.addListener("zoom-change", () => {
        this.series.forEach((s) => s.animationState?.transition("updateData"));
        const skipAnimations = this.chartAnimationPhase !== "initial";
        this.update(3, { forceNodeDataRefresh: true, skipAnimations });
      })
    );
    this.parentResize(ctx.domManager.containerSize);
  }
  static getInstance(element2) {
    return _Chart2.chartsInstances.get(element2);
  }
  /** NOTE: This is exposed for use by Integrated charts only. */
  get canvasElement() {
    return this.ctx.scene.canvas.element;
  }
  download(fileName, fileFormat) {
    this.ctx.scene.download(fileName, fileFormat);
  }
  getCanvasDataURL(fileFormat) {
    return this.ctx.scene.getDataURL(fileFormat);
  }
  toSVG() {
    return this.ctx.scene.toSVG();
  }
  getOptions() {
    return this.queuedUserOptions.at(-1) ?? this.chartOptions.userOptions;
  }
  getChartOptions() {
    return this.queuedChartOptions.at(-1) ?? this.chartOptions;
  }
  initSeriesAreaDependencies() {
    const { ctx, tooltip, highlight, overlays, seriesRoot, mode } = this;
    const chartType2 = this.getChartType();
    const fireEvent = this.fireEvent.bind(this);
    const getUpdateType = () => this.performUpdateType;
    return { fireEvent, getUpdateType, chartType: chartType2, ctx, tooltip, highlight, overlays, seriesRoot, mode };
  }
  getModuleContext() {
    return this.ctx;
  }
  getCaptionText() {
    return [this.title, this.subtitle, this.footnote].filter((caption) => caption.enabled && caption.text).map((caption) => caption.text).join(". ");
  }
  getAriaLabel() {
    return this.ctx.localeManager.t("ariaAnnounceChart", { seriesCount: this.series.length });
  }
  resetAnimations() {
    this.chartAnimationPhase = "initial";
    for (const series of this.series) {
      series.resetAnimation(this.chartAnimationPhase);
    }
    for (const axis of this.axes) {
      axis.resetAnimation(this.chartAnimationPhase);
    }
    this.animationRect = void 0;
    this.ctx.animationManager.reset();
  }
  skipAnimations() {
    this.ctx.animationManager.skipCurrentBatch();
    this._performUpdateSkipAnimations = true;
  }
  detachAndClear() {
    this.container = void 0;
    this.ctx.scene.clear();
  }
  destroy(opts) {
    if (this.destroyed) {
      return;
    }
    const keepTransferableResources = opts?.keepTransferableResources;
    let result;
    this.performUpdateType = 7;
    this._destroyFns.forEach((fn) => fn());
    this.processors.forEach((p) => p.destroy());
    this.tooltip.destroy(this.ctx.domManager);
    this.overlays.destroy();
    this.modulesManager.destroy();
    if (keepTransferableResources) {
      this.ctx.scene.strip();
      result = {
        container: this.container,
        scene: this.ctx.scene
      };
    } else {
      this.ctx.scene.destroy();
      this.container = void 0;
    }
    this.destroySeries(this.series);
    this.seriesLayerManager.destroy();
    this.axes.forEach((a) => a.destroy());
    this.axes = [];
    this.animationRect = void 0;
    this.ctx.destroy();
    this.destroyed = true;
    Object.freeze(this);
    return result;
  }
  requestFactoryUpdate(cb) {
    if (this.destroyed)
      return;
    this._pendingFactoryUpdatesCount++;
    this.updateMutex.acquire(async () => {
      if (this.destroyed)
        return;
      try {
        await cb(this);
      } finally {
        if (!this.destroyed) {
          this._pendingFactoryUpdatesCount--;
        }
      }
    }).catch((e) => Logger.errorOnce(e));
  }
  update(type = 0, opts) {
    const {
      forceNodeDataRefresh = false,
      skipAnimations,
      seriesToUpdate = this.series,
      newAnimationBatch
    } = opts ?? {};
    if (forceNodeDataRefresh) {
      this.series.forEach((series) => series.markNodeDataDirty());
    }
    for (const series of seriesToUpdate) {
      this.seriesToUpdate.add(series);
    }
    if (skipAnimations) {
      this.ctx.animationManager.skipCurrentBatch();
      this._performUpdateSkipAnimations = true;
    }
    if (newAnimationBatch && this.ctx.animationManager.isActive()) {
      this._performUpdateSkipAnimations = true;
    }
    this.skipSync = opts?.skipSync ?? false;
    if (this.debug.check()) {
      let stack = new Error().stack ?? "<unknown>";
      stack = stack.replace(/\([^)]*/g, "");
      this.updateRequestors[stack] = type;
    }
    if (type < this.performUpdateType) {
      this.performUpdateType = type;
      this.ctx.domManager.setDataBoolean("updatePending", true);
      this.performUpdateTrigger.schedule(opts?.backOffMs);
    }
  }
  async performUpdate(count) {
    const { performUpdateType, extraDebugStats, _performUpdateSplits: splits, ctx } = this;
    const seriesToUpdate = [...this.seriesToUpdate];
    this.performUpdateType = 7;
    this.seriesToUpdate.clear();
    this.runningUpdateType = performUpdateType;
    if (this.updateShortcutCount === 0 && performUpdateType < 6) {
      ctx.animationManager.startBatch(this._performUpdateSkipAnimations);
      ctx.animationManager.onBatchStop(() => this.chartAnimationPhase = "ready");
    }
    this.debug("Chart.performUpdate() - start", ChartUpdateType[performUpdateType]);
    let previousSplit = performance.now();
    splits.start ?? (splits.start = previousSplit);
    const updateSplits = (splitName) => {
      splits[splitName] ?? (splits[splitName] = 0);
      splits[splitName] += performance.now() - previousSplit;
      previousSplit = performance.now();
    };
    switch (performUpdateType) {
      case 0:
        if (this.checkUpdateShortcut(
          0
          /* FULL */
        ))
          break;
        this.ctx.updateService.dispatchPreDomUpdate();
        this.updateDOM();
      case 1:
        if (this.checkUpdateShortcut(
          1
          /* UPDATE_DATA */
        ))
          break;
        await this.updateData();
        updateSplits("\u2B07\uFE0F");
      case 2:
        if (this.checkUpdateShortcut(
          2
          /* PROCESS_DATA */
        ))
          break;
        await this.processData();
        this.seriesAreaManager.dataChanged();
        updateSplits("\u{1F3ED}");
      case 3:
        await this.checkFirstAutoSize();
        if (this.checkUpdateShortcut(
          3
          /* PERFORM_LAYOUT */
        ))
          break;
        await this.processLayout();
        updateSplits("\u2316");
      case 4: {
        if (this.checkUpdateShortcut(
          4
          /* SERIES_UPDATE */
        ))
          break;
        await this.updateSeries(seriesToUpdate);
        updateSplits("\u{1F914}");
        this.updateAriaLabels();
        this.seriesLayerManager.updateLayerCompositing();
      }
      case 5:
        if (this.checkUpdateShortcut(
          5
          /* PRE_SCENE_RENDER */
        ))
          break;
        ctx.updateService.dispatchPreSceneRender(this.getMinRects());
        updateSplits("\u2196");
      case 6:
        if (this.checkUpdateShortcut(
          6
          /* SCENE_RENDER */
        ))
          break;
        ctx.animationManager.endBatch();
        extraDebugStats["updateShortcutCount"] = this.updateShortcutCount;
        ctx.scene.render({ debugSplitTimes: splits, extraDebugStats, seriesRect: this.seriesRect });
        this.extraDebugStats = {};
        for (const key of Object.keys(splits)) {
          delete splits[key];
        }
        this.ctx.domManager.incrementDataCounter("sceneRenders");
      case 7:
        this.updateShortcutCount = 0;
        this.updateRequestors = {};
        this._performUpdateSkipAnimations = false;
        ctx.animationManager.endBatch();
    }
    if (!this.destroyed) {
      ctx.updateService.dispatchUpdateComplete(this.getMinRects());
      this.ctx.domManager.setDataBoolean("updatePending", false);
      this.runningUpdateType = 7;
    }
    this._performUpdateNotify.notify();
    const end2 = performance.now();
    this.debug("Chart.performUpdate() - end", {
      chart: this,
      durationMs: Math.round((end2 - splits["start"]) * 100) / 100,
      count,
      performUpdateType: ChartUpdateType[performUpdateType]
    });
  }
  updateThemeClassName() {
    const themeClassNamePrefix = "ag-charts-theme-";
    const validThemeClassNames = [`${themeClassNamePrefix}default`, `${themeClassNamePrefix}default-dark`];
    let themeClassName = validThemeClassNames[0];
    let isDark = false;
    let { theme } = this.chartOptions.processedOptions;
    while (typeof theme !== "string" && theme != null) {
      theme = theme.baseTheme;
    }
    if (typeof theme === "string") {
      themeClassName = theme.replace("ag-", themeClassNamePrefix);
      isDark = theme.includes("-dark");
    }
    if (!validThemeClassNames.includes(themeClassName)) {
      themeClassName = isDark ? validThemeClassNames[1] : validThemeClassNames[0];
    }
    this.ctx.domManager.setThemeClass(themeClassName);
  }
  updateDOM() {
    this.updateThemeClassName();
    const { enabled, tabIndex } = this.keyboard;
    this.ctx.domManager.setTabGuardIndex(enabled ? tabIndex ?? 0 : -1);
  }
  updateAriaLabels() {
    this.ctx.domManager.updateCanvasLabel(this.getAriaLabel());
  }
  checkUpdateShortcut(checkUpdateType) {
    const maxShortcuts = 3;
    if (this.destroyed)
      return true;
    if (this.updateShortcutCount > maxShortcuts) {
      Logger.warn(
        `exceeded the maximum number of simultaneous updates (${maxShortcuts + 1}), discarding changes and rendering`,
        this.updateRequestors
      );
      return false;
    }
    if (this.performUpdateType <= checkUpdateType) {
      this.updateShortcutCount++;
      return true;
    }
    return false;
  }
  async checkFirstAutoSize() {
    if (this.width != null && this.height != null) {
    } else if (!this._lastAutoSize) {
      const success = await this._autoSizeNotify.await(500);
      if (!success) {
        this.debug("Chart.checkFirstAutoSize() - timeout for first size update.");
      }
    }
  }
  onAxisChange(newValue, oldValue) {
    if (oldValue == null && newValue.length === 0)
      return;
    this.ctx.axisManager.updateAxes(oldValue ?? [], newValue);
  }
  onSeriesChange(newValue, oldValue) {
    const seriesToDestroy = oldValue?.filter((series) => !newValue.includes(series)) ?? [];
    this.destroySeries(seriesToDestroy);
    this.seriesLayerManager?.setSeriesCount(newValue.length);
    for (const series of newValue) {
      if (oldValue?.includes(series))
        continue;
      const seriesContentNode = this.seriesLayerManager.requestGroup(series);
      series.attachSeries(seriesContentNode, this.seriesRoot, this.annotationRoot);
      const chart = this;
      series.chart = {
        get mode() {
          return chart.mode;
        },
        get isMiniChart() {
          return false;
        },
        get seriesRect() {
          return chart.seriesRect;
        }
      };
      series.resetAnimation(this.chartAnimationPhase);
      this.addSeriesListeners(series);
      series.addChartEventListeners();
    }
    this.seriesAreaManager?.seriesChanged(newValue);
  }
  destroySeries(allSeries) {
    allSeries?.forEach((series) => {
      series.removeEventListener("nodeClick", this.onSeriesNodeClick);
      series.removeEventListener("nodeDoubleClick", this.onSeriesNodeDoubleClick);
      series.removeEventListener("groupingChanged", this.seriesGroupingChanged);
      series.destroy();
      this.seriesLayerManager.releaseGroup(series);
      series.detachSeries(void 0, this.seriesRoot, this.annotationRoot);
      series.chart = void 0;
    });
  }
  addSeriesListeners(series) {
    if (this.hasEventListener("seriesNodeClick")) {
      series.addEventListener("nodeClick", this.onSeriesNodeClick);
    }
    if (this.hasEventListener("seriesNodeDoubleClick")) {
      series.addEventListener("nodeDoubleClick", this.onSeriesNodeDoubleClick);
    }
    if (this.hasEventListener("seriesVisibilityChange")) {
      series.addEventListener("seriesVisibilityChange", this.onSeriesVisibilityChange);
    }
    series.addEventListener("groupingChanged", this.seriesGroupingChanged);
  }
  assignSeriesToAxes() {
    for (const axis of this.axes) {
      axis.boundSeries = this.series.filter((s) => s.axes[axis.direction] === axis);
    }
  }
  assignAxesToSeries() {
    const directionToAxesMap = groupBy(this.axes, (axis) => axis.direction);
    for (const series of this.series) {
      for (const direction of series.directions) {
        const directionAxes = directionToAxesMap[direction];
        if (!directionAxes) {
          Logger.warnOnce(
            `no available axis for direction [${direction}]; check series and axes configuration.`
          );
          return;
        }
        const seriesKeys = series.getKeys(direction);
        const newAxis = directionAxes.find(
          (axis) => !axis.keys.length || seriesKeys.some((key) => axis.keys.includes(key))
        );
        if (!newAxis) {
          Logger.warnOnce(
            `no matching axis for direction [${direction}] and keys [${seriesKeys}]; check series and axes configuration.`
          );
          return;
        }
        series.axes[direction] = newAxis;
      }
    }
  }
  parentResize(size) {
    if (size == null || this.width != null && this.height != null)
      return;
    let { width: width2, height: height2 } = size;
    width2 = Math.floor(width2);
    height2 = Math.floor(height2);
    if (width2 === 0 && height2 === 0)
      return;
    const [autoWidth = 0, authHeight = 0] = this._lastAutoSize ?? [];
    if (autoWidth === width2 && authHeight === height2)
      return;
    this._lastAutoSize = [width2, height2];
    this.resize("SizeMonitor", {});
  }
  resize(source, opts) {
    const { scene, animationManager } = this.ctx;
    const { inWidth, inHeight, inMinWidth, inMinHeight } = opts;
    this.ctx.domManager.setSizeOptions(
      inMinWidth ?? this.minWidth,
      inMinHeight ?? this.minHeight,
      inWidth ?? this.width,
      inHeight ?? this.height
    );
    const width2 = inWidth ?? this.width ?? this._lastAutoSize?.[0];
    const height2 = inHeight ?? this.height ?? this._lastAutoSize?.[1];
    this.debug(`Chart.resize() from ${source}`, { width: width2, height: height2, stack: new Error().stack });
    if (width2 == null || height2 == null || !isFiniteNumber(width2) || !isFiniteNumber(height2))
      return;
    if (scene.resize(width2, height2)) {
      animationManager.reset();
      let skipAnimations = true;
      if ((this.width == null || this.height == null) && this._firstAutoSize) {
        skipAnimations = false;
        this._firstAutoSize = false;
      }
      this.update(3, { forceNodeDataRefresh: true, skipAnimations });
      this._autoSizeNotify.notify();
    }
  }
  async updateData() {
    this.series.forEach((s) => s.setChartData(this.data));
    const modulePromises = this.modulesManager.mapModules((m) => m.updateData?.(this.data));
    await Promise.all(modulePromises);
  }
  async processData() {
    if (this.series.some((s) => s.canHaveAxes)) {
      this.assignAxesToSeries();
      this.assignSeriesToAxes();
    }
    for (const axis of this.axes) {
      axis.processData();
    }
    const dataController = new DataController(this.mode, this.suppressFieldDotNotation);
    const seriesPromises = this.series.map((s) => {
      s.resetDatumCallbackCache();
      return s.processData(dataController);
    });
    const modulePromises = this.modulesManager.mapModules((m) => m.processData?.(dataController));
    this._cachedData = dataController.execute(this._cachedData);
    await Promise.all([...seriesPromises, ...modulePromises]);
    this.updateLegends();
  }
  updateLegends(initialStateLegend) {
    for (const { legend, legendType } of this.modulesManager.legends()) {
      if (legendType === "category") {
        this.setCategoryLegendData(initialStateLegend);
      } else {
        this.setLegendData(legendType, legend);
      }
    }
  }
  setCategoryLegendData(initialState) {
    var _a;
    const {
      ctx: { legendManager, stateManager }
    } = this;
    if (initialState) {
      this.series.forEach((s) => {
        const seriesState = initialState.find((init) => init.seriesId === s.id);
        s.onLegendInitialState("category", seriesState);
      });
    }
    const legendData = this.series.flatMap((s) => {
      const seriesLegendData = s.getLegendData("category");
      legendManager.updateData(s.id, seriesLegendData);
      return seriesLegendData;
    });
    if (initialState) {
      stateManager.setStateAndRestore(legendManager, initialState);
      return;
    }
    if (this.mode !== "integrated") {
      const seriesMarkerFills = {};
      const seriesTypeMap = new Map(this.series.map((s) => [s.id, s.type]));
      for (const {
        seriesId,
        symbol: { marker },
        label
      } of legendData.filter((d) => !d.hideInLegend)) {
        if (marker.fill == null)
          continue;
        const seriesType = seriesTypeMap.get(seriesId);
        const markerFill = seriesMarkerFills[seriesType] ?? (seriesMarkerFills[seriesType] = {});
        markerFill[_a = label.text] ?? (markerFill[_a] = marker.fill);
        if (markerFill[label.text] !== marker.fill) {
          Logger.warnOnce(
            `legend item '${label.text}' has multiple fill colors, this may cause unexpected behaviour.`
          );
        }
      }
    }
    legendManager.update();
  }
  setLegendData(legendType, legend) {
    legend.data = this.series.filter((s) => s.properties.showInLegend).flatMap((s) => s.getLegendData(legendType));
  }
  async processLayout() {
    const oldRect = this.animationRect;
    const { width: width2, height: height2 } = this.ctx.scene;
    const ctx = this.ctx.layoutManager.createContext(width2, height2);
    await this.performLayout(ctx);
    if (oldRect && !this.animationRect?.equals(oldRect)) {
      this.ctx.animationManager.skipCurrentBatch();
    }
    this.debug("Chart.performUpdate() - seriesRect", this.seriesRect);
  }
  async updateSeries(seriesToUpdate) {
    const { seriesRect } = this;
    await Promise.all(seriesToUpdate.map((series) => series.update({ seriesRect })));
    this.ctx.seriesLabelLayoutManager.updateLabels(
      this.series.filter((s) => s.visible && s.usesPlacedLabels),
      this.padding,
      this.seriesRect
    );
  }
  async waitForUpdate(timeoutMs = 1e4, failOnTimeout = false) {
    const start2 = performance.now();
    while (this._pendingFactoryUpdatesCount > 0 || this.performUpdateType !== 7 || this.runningUpdateType !== 7) {
      if (this._pendingFactoryUpdatesCount > 0) {
        await this.updateMutex.waitForClearAcquireQueue();
      }
      if (this.performUpdateType !== 7 || this.runningUpdateType !== 7) {
        await this._performUpdateNotify.await();
      }
      if (performance.now() - start2 > timeoutMs) {
        const message = `Chart.waitForUpdate() timeout of ${timeoutMs} reached - first chart update taking too long.`;
        if (failOnTimeout) {
          throw new Error(message);
        } else {
          Logger.warnOnce(message);
        }
      }
      if (isInputPending()) {
        await pause();
      }
    }
  }
  getMinRects() {
    const { width: width2, height: height2 } = this.ctx.scene;
    const minRects = this.series.map((series) => series.getMinRects(width2, height2)).filter(isDefined);
    if (minRects.length === 0)
      return;
    let maxWidth = 0;
    let maxHeight = 0;
    let maxVisibleWidth = 0;
    let maxVisibleHeight = 0;
    for (const { minRect: minRect2, minVisibleRect: minVisibleRect2 } of minRects) {
      maxWidth = Math.max(maxWidth, minRect2.width);
      maxHeight = Math.max(maxHeight, minRect2.height);
      maxVisibleWidth = Math.max(maxVisibleWidth, minVisibleRect2.width);
      maxVisibleHeight = Math.max(maxVisibleHeight, minVisibleRect2.height);
    }
    const minRect = new BBox(0, 0, maxWidth, maxHeight);
    let minVisibleRect = minRect.clone();
    if (maxVisibleWidth > 0 && maxVisibleHeight > 0) {
      minVisibleRect = new BBox(0, 0, maxVisibleWidth, maxVisibleHeight);
    }
    return { minRect, minVisibleRect };
  }
  filterMiniChartSeries(series) {
    return series?.filter((s) => s.showInMiniChart !== false);
  }
  applyOptions(newChartOptions) {
    const deltaOptions = this.firstApply ? newChartOptions.processedOptions : newChartOptions.diffOptions(this.chartOptions);
    if (deltaOptions == null || Object.keys(deltaOptions).length === 0)
      return;
    const oldOpts = this.firstApply ? {} : this.chartOptions.processedOptions;
    const newOpts = newChartOptions.processedOptions;
    debug("Chart.applyOptions() - applying delta", deltaOptions);
    const modulesChanged = this.applyModules(newOpts);
    const skip = [
      "type",
      "data",
      "series",
      "listeners",
      "preset",
      "theme",
      "legend.listeners",
      "navigator.miniChart.series",
      "navigator.miniChart.label",
      "locale.localeText",
      "axes",
      "topology",
      "nodes",
      "initialState",
      "styleContainer"
    ];
    if (deltaOptions.listeners) {
      this.registerListeners(this, deltaOptions.listeners);
    }
    jsonApply(this, deltaOptions, { skip });
    let forceNodeDataRefresh = false;
    let seriesStatus = "no-op";
    if (deltaOptions.series != null) {
      seriesStatus = this.applySeries(this, deltaOptions.series, oldOpts?.series);
      forceNodeDataRefresh = true;
    }
    if (seriesStatus === "replaced") {
      this.resetAnimations();
    }
    if (this.applyAxes(this, newOpts, oldOpts, seriesStatus, [])) {
      forceNodeDataRefresh = true;
    }
    if (deltaOptions.data) {
      this.data = deltaOptions.data;
    }
    if (deltaOptions.legend?.listeners && this.modulesManager.isEnabled("legend")) {
      Object.assign(this.legend.listeners, deltaOptions.legend.listeners);
    }
    if (deltaOptions.locale?.localeText) {
      this.modulesManager.getModule("locale").localeText = deltaOptions.locale?.localeText;
    }
    this.chartOptions = newChartOptions;
    const navigatorModule = this.modulesManager.getModule("navigator");
    const zoomModule = this.modulesManager.getModule("zoom");
    if (!navigatorModule?.enabled && !zoomModule?.enabled) {
      this.ctx.zoomManager.updateZoom("chart");
    }
    const miniChart = navigatorModule?.miniChart;
    const miniChartSeries = newOpts.navigator?.miniChart?.series ?? newOpts.series;
    if (miniChart?.enabled === true && miniChartSeries != null) {
      this.applyMiniChartOptions(miniChart, miniChartSeries, newOpts, oldOpts);
    } else if (miniChart?.enabled === false) {
      miniChart.series = [];
      miniChart.axes = [];
    }
    this.ctx.annotationManager.setAnnotationStyles(newChartOptions.annotationThemes);
    forceNodeDataRefresh || (forceNodeDataRefresh = this.shouldForceNodeDataRefresh(deltaOptions, seriesStatus));
    const majorChange = forceNodeDataRefresh || modulesChanged;
    const updateType = majorChange ? 0 : 3;
    this.maybeResetAnimations(seriesStatus);
    debug("Chart.applyOptions() - update type", ChartUpdateType[updateType], {
      seriesStatus,
      forceNodeDataRefresh
    });
    this.update(updateType, { forceNodeDataRefresh, newAnimationBatch: true });
    this.ctx.legendManager.clearData();
    this.applyInitialState(newOpts);
    this.firstApply = false;
  }
  applyInitialState(options) {
    const { annotationManager, chartTypeOriginator, historyManager, stateManager, zoomManager } = this.ctx;
    const { initialState } = options;
    if ("annotations" in options && options.annotations?.enabled && initialState?.annotations != null) {
      const annotations = initialState.annotations.map((annotation) => {
        const annotationTheme = annotationManager.getAnnotationTypeStyles(annotation.type);
        return mergeDefaults(annotation, annotationTheme);
      });
      stateManager.setState(annotationManager, annotations);
    }
    if (initialState?.chartType != null) {
      stateManager.setState(chartTypeOriginator, initialState.chartType);
    }
    if ((options.navigator?.enabled || options.zoom?.enabled) && initialState?.zoom != null) {
      stateManager.setState(zoomManager, initialState.zoom);
    }
    if (initialState?.legend != null) {
      this.updateLegends(initialState.legend);
    }
    if (initialState != null) {
      historyManager.clear();
    }
  }
  maybeResetAnimations(seriesStatus) {
    if (this.mode !== "standalone")
      return;
    switch (seriesStatus) {
      case "series-grouping-change":
      case "replaced":
        this.resetAnimations();
        break;
      default:
    }
  }
  shouldForceNodeDataRefresh(deltaOptions, seriesStatus) {
    const seriesDataUpdate = !!deltaOptions.data || seriesStatus === "data-change" || seriesStatus === "replaced";
    const legendKeys = legendRegistry.getKeys();
    const optionsHaveLegend = Object.values(legendKeys).some(
      (legendKey) => deltaOptions[legendKey] != null
    );
    const otherRefreshUpdate = deltaOptions.title != null && deltaOptions.subtitle != null;
    return seriesDataUpdate || optionsHaveLegend || otherRefreshUpdate;
  }
  applyMiniChartOptions(miniChart, miniChartSeries, completeOptions, oldOpts) {
    const oldSeries = oldOpts?.navigator?.miniChart?.series ?? oldOpts?.series;
    const miniChartSeriesStatus = this.applySeries(
      miniChart,
      this.filterMiniChartSeries(miniChartSeries),
      this.filterMiniChartSeries(oldSeries)
    );
    this.applyAxes(miniChart, completeOptions, oldOpts, miniChartSeriesStatus, [
      "axes[].tick",
      "axes[].thickness",
      "axes[].title",
      "axes[].crosshair",
      "axes[].gridLine",
      "axes[].label"
    ]);
    const series = miniChart.series;
    for (const s of series) {
      s.properties.id = void 0;
    }
    const axes = miniChart.axes;
    const horizontalAxis = axes.find(
      (axis) => axis.direction === "x"
      /* X */
    );
    for (const axis of axes) {
      axis.gridLine.enabled = false;
      axis.label.enabled = axis === horizontalAxis;
      axis.tick.enabled = false;
      axis.interactionEnabled = false;
    }
    if (horizontalAxis != null) {
      const miniChartOpts = completeOptions.navigator?.miniChart;
      const labelOptions = miniChartOpts?.label;
      const intervalOptions = miniChartOpts?.label?.interval;
      horizontalAxis.line.enabled = false;
      horizontalAxis.label.set(
        without(labelOptions, ["interval", "rotation", "minSpacing", "autoRotate", "autoRotateAngle"])
      );
      horizontalAxis.tick.set(
        without(intervalOptions, ["enabled", "width", "size", "color", "interval", "step"])
      );
      if (horizontalAxis.type === "grouped-category") {
        horizontalAxis.label.enabled = false;
        horizontalAxis.label.rotation = 0;
        const { depthOptions } = horizontalAxis;
        if (depthOptions.length === 0) {
          depthOptions.set([{ label: { enabled: true } }]);
        } else {
          for (let i = 1; i < depthOptions.length; i++) {
            depthOptions[i].label.enabled = false;
          }
        }
      }
      const step = intervalOptions?.step;
      if (step != null) {
        horizontalAxis.interval.step = step;
      }
    }
  }
  applyModules(options) {
    const { type: chartType2 } = this.constructor;
    let modulesChanged = false;
    for (const module2 of moduleRegistry.byType("root", "legend")) {
      const isConfigured = options[module2.optionsKey] != null;
      const shouldBeEnabled = isConfigured && module2.chartTypes.includes(chartType2);
      if (shouldBeEnabled === this.modulesManager.isEnabled(module2))
        continue;
      if (shouldBeEnabled) {
        this.modulesManager.addModule(module2, (m) => m.moduleFactory(this.getModuleContext()));
        if (module2.type === "legend") {
          this.modulesManager.getModule(module2)?.attachLegend(this.ctx.scene);
        }
        this[module2.optionsKey] = this.modulesManager.getModule(module2);
      } else {
        this.modulesManager.removeModule(module2);
        delete this[module2.optionsKey];
      }
      modulesChanged = true;
    }
    return modulesChanged;
  }
  initSeriesDeclarationOrder(series) {
    for (let idx = 0; idx < series.length; idx++) {
      series[idx].setSeriesIndex(idx);
    }
  }
  applySeries(chart, optSeries, oldOptSeries) {
    if (!optSeries) {
      return "no-change";
    }
    const matchResult = matchSeriesOptions(chart.series, optSeries, oldOptSeries);
    if (matchResult.status === "no-overlap") {
      debug(`Chart.applySeries() - creating new series instances, status: ${matchResult.status}`, matchResult);
      const chartSeries = optSeries.map((opts) => this.createSeries(opts));
      this.initSeriesDeclarationOrder(chartSeries);
      chart.series = chartSeries;
      return "replaced";
    }
    debug(`Chart.applySeries() - matchResult`, matchResult);
    const seriesInstances = [];
    let dataChanged = false;
    let groupingChanged = false;
    let isUpdated = false;
    const changes = matchResult.changes.toSorted((a, b) => a.targetIdx - b.targetIdx);
    for (const change of changes) {
      groupingChanged || (groupingChanged = change.status === "series-grouping");
      dataChanged || (dataChanged = change.diff?.data != null);
      isUpdated || (isUpdated = change.status !== "no-op");
      switch (change.status) {
        case "add": {
          const newSeries = this.createSeries(change.opts);
          seriesInstances.push(newSeries);
          debug(`Chart.applySeries() - created new series`, newSeries);
          break;
        }
        case "remove":
          debug(`Chart.applySeries() - removing series at previous idx ${change.idx}`, change.series);
          break;
        case "no-op":
          seriesInstances.push(change.series);
          debug(`Chart.applySeries() - no change to series at previous idx ${change.idx}`, change.series);
          break;
        case "series-grouping":
        case "update":
        default: {
          const { series, diff: diff2, idx } = change;
          debug(`Chart.applySeries() - applying series diff previous idx ${idx}`, diff2, series);
          this.applySeriesValues(series, diff2);
          series.markNodeDataDirty();
          seriesInstances.push(series);
        }
      }
    }
    this.initSeriesDeclarationOrder(seriesInstances);
    debug(`Chart.applySeries() - final series instances`, seriesInstances);
    chart.series = seriesInstances;
    if (groupingChanged) {
      return "series-grouping-change";
    }
    if (dataChanged) {
      return "data-change";
    }
    return isUpdated ? "updated" : "no-op";
  }
  applyAxes(chart, options, oldOpts, seriesStatus, skip = []) {
    if (!("axes" in options) || !options.axes) {
      return false;
    }
    skip = ["axes[].type", ...skip];
    const { axes } = options;
    const forceRecreate = seriesStatus === "replaced";
    const matchingTypes = !forceRecreate && chart.axes.length === axes.length && chart.axes.every((a, i) => a.type === axes[i].type);
    if (matchingTypes && isAgCartesianChartOptions(oldOpts)) {
      chart.axes.forEach((axis, index) => {
        const previousOpts = oldOpts.axes?.[index] ?? {};
        const axisDiff = jsonDiff(previousOpts, axes[index]);
        debug(`Chart.applyAxes() - applying axis diff idx ${index}`, axisDiff);
        const path = `axes[${index}]`;
        jsonApply(axis, axisDiff, { path, skip });
      });
      return true;
    }
    debug(`Chart.applyAxes() - creating new axes instances; seriesStatus: ${seriesStatus}`);
    chart.axes = this.createAxis(axes, skip);
    return true;
  }
  createSeries(seriesOptions) {
    const seriesInstance = seriesRegistry.create(seriesOptions.type, this.getModuleContext());
    this.applySeriesOptionModules(seriesInstance, seriesOptions);
    this.applySeriesValues(seriesInstance, seriesOptions);
    return seriesInstance;
  }
  applySeriesOptionModules(series, options) {
    const moduleContext = series.createModuleContext();
    const moduleMap = series.getModuleMap();
    for (const module2 of moduleRegistry.byType("series-option")) {
      if (module2.optionsKey in options && module2.seriesTypes.includes(series.type)) {
        moduleMap.addModule(module2, (m) => m.moduleFactory(moduleContext));
      }
    }
  }
  applySeriesValues(target, options) {
    const moduleMap = target.getModuleMap();
    const { type: _, data, listeners, seriesGrouping, showInMiniChart: __, ...seriesOptions } = options;
    for (const moduleDef of EXPECTED_ENTERPRISE_MODULES) {
      if (moduleDef.type !== "series-option")
        continue;
      if (moduleDef.optionsKey in seriesOptions) {
        const module2 = moduleMap.getModule(moduleDef.optionsKey);
        if (module2) {
          const moduleOptions = seriesOptions[moduleDef.optionsKey];
          delete seriesOptions[moduleDef.optionsKey];
          module2.properties.set(moduleOptions);
        }
      }
    }
    target.properties.set(seriesOptions);
    if ("data" in options) {
      target.setOptionsData(data);
    }
    if (listeners) {
      this.registerListeners(target, listeners);
    }
    if ("seriesGrouping" in options) {
      if (seriesGrouping == null) {
        target.seriesGrouping = void 0;
      } else {
        target.seriesGrouping = { ...target.seriesGrouping, ...seriesGrouping };
      }
    }
  }
  createAxis(options, skip) {
    const newAxes = [];
    const moduleContext = this.getModuleContext();
    for (let index = 0; index < options.length; index++) {
      const axisOptions = options[index];
      const axis = axisRegistry.create(axisOptions.type, moduleContext);
      this.applyAxisModules(axis, axisOptions);
      jsonApply(axis, axisOptions, { path: `axes[${index}]`, skip });
      newAxes.push(axis);
    }
    guessInvalidPositions(newAxes);
    return newAxes;
  }
  applyAxisModules(axis, options) {
    const moduleContext = axis.createModuleContext();
    const moduleMap = axis.getModuleMap();
    for (const module2 of moduleRegistry.byType("axis-option")) {
      const shouldBeEnabled = options[module2.optionsKey] != null;
      if (shouldBeEnabled === moduleMap.isEnabled(module2))
        continue;
      if (shouldBeEnabled) {
        moduleMap.addModule(module2, (m) => m.moduleFactory(moduleContext));
        axis[module2.optionsKey] = moduleMap.getModule(module2);
      } else {
        moduleMap.removeModule(module2);
        delete axis[module2.optionsKey];
      }
    }
  }
  registerListeners(source, listeners) {
    source.clearEventListeners();
    for (const [property, listener] of Object.entries(listeners)) {
      if (isFunction(listener)) {
        source.addEventListener(property, listener);
      }
    }
  }
};
_Chart.chartsInstances = /* @__PURE__ */ new WeakMap();
__decorateClass([
  ActionOnSet({
    newValue(value) {
      if (this.destroyed)
        return;
      this.ctx.domManager.setContainer(value);
      _Chart.chartsInstances.set(value, this);
    },
    oldValue(value) {
      _Chart.chartsInstances.delete(value);
    }
  })
], _Chart.prototype, "container", 2);
__decorateClass([
  ActionOnSet({
    newValue(value) {
      this.resize("width option", { inWidth: value });
    }
  })
], _Chart.prototype, "width", 2);
__decorateClass([
  ActionOnSet({
    newValue(value) {
      this.resize("height option", { inHeight: value });
    }
  })
], _Chart.prototype, "height", 2);
__decorateClass([
  ActionOnSet({
    newValue(value) {
      this.resize("minWidth option", { inMinWidth: value });
    }
  })
], _Chart.prototype, "minWidth", 2);
__decorateClass([
  ActionOnSet({
    newValue(value) {
      this.resize("minHeight option", { inMinHeight: value });
    }
  })
], _Chart.prototype, "minHeight", 2);
__decorateClass([
  Validate(OBJECT)
], _Chart.prototype, "padding", 2);
__decorateClass([
  Validate(OBJECT)
], _Chart.prototype, "seriesArea", 2);
__decorateClass([
  Validate(OBJECT)
], _Chart.prototype, "keyboard", 2);
__decorateClass([
  Validate(UNION(["standalone", "integrated"], "a chart mode"))
], _Chart.prototype, "mode", 2);
__decorateClass([
  ProxyProperty("chartCaptions.title")
], _Chart.prototype, "title", 2);
__decorateClass([
  ProxyProperty("chartCaptions.subtitle")
], _Chart.prototype, "subtitle", 2);
__decorateClass([
  ProxyProperty("chartCaptions.footnote")
], _Chart.prototype, "footnote", 2);
__decorateClass([
  Validate(BOOLEAN)
], _Chart.prototype, "suppressFieldDotNotation", 2);
__decorateClass([
  ActionOnSet({
    changeValue(newValue, oldValue) {
      this.onAxisChange(newValue, oldValue);
    }
  })
], _Chart.prototype, "axes", 2);
__decorateClass([
  ActionOnSet({
    changeValue(newValue, oldValue) {
      this.onSeriesChange(newValue, oldValue);
    }
  })
], _Chart.prototype, "series", 2);
var Chart = _Chart;
var QuadtreeNearest = class {
  constructor(capacity, maxdepth, boundary) {
    this.root = new QuadtreeNodeNearest(capacity, maxdepth, boundary);
  }
  clear(boundary) {
    this.root.clear(boundary);
  }
  addValue(hitTester, value) {
    const elem = {
      hitTester,
      value,
      distanceSquared: (x, y) => {
        return hitTester.distanceSquared(x, y);
      }
    };
    this.root.addElem(elem);
  }
  find(x, y) {
    const arg = { best: { nearest: void 0, distanceSquared: Infinity } };
    this.root.find(x, y, arg);
    return arg.best;
  }
};
var QuadtreeSubdivisions = class {
  constructor(nw, ne, sw, se) {
    this.nw = nw;
    this.ne = ne;
    this.sw = sw;
    this.se = se;
  }
  addElem(elem) {
    this.nw.addElem(elem);
    this.ne.addElem(elem);
    this.sw.addElem(elem);
    this.se.addElem(elem);
  }
  find(x, y, arg) {
    this.nw.find(x, y, arg);
    this.ne.find(x, y, arg);
    this.sw.find(x, y, arg);
    this.se.find(x, y, arg);
  }
};
var QuadtreeNode = class {
  constructor(capacity, maxdepth, boundary) {
    this.capacity = capacity;
    this.maxdepth = maxdepth;
    this.boundary = boundary ?? BBox.NaN;
    this.elems = [];
    this.subdivisions = void 0;
  }
  clear(boundary) {
    this.elems.length = 0;
    this.boundary = boundary;
    this.subdivisions = void 0;
  }
  addElem(e) {
    if (this.addCondition(e)) {
      if (this.subdivisions === void 0) {
        if (this.maxdepth === 0 || this.elems.length < this.capacity) {
          this.elems.push(e);
        } else {
          this.subdivide(e);
        }
      } else {
        this.subdivisions.addElem(e);
      }
    }
  }
  find(x, y, arg) {
    if (this.findCondition(x, y, arg)) {
      if (this.subdivisions === void 0) {
        this.findAction(x, y, arg);
      } else {
        this.subdivisions.find(x, y, arg);
      }
    }
  }
  subdivide(newElem) {
    this.subdivisions = this.makeSubdivisions();
    for (const e of this.elems) {
      this.subdivisions.addElem(e);
    }
    this.subdivisions.addElem(newElem);
    this.elems.length = 0;
  }
  makeSubdivisions() {
    const { x, y, width: width2, height: height2 } = this.boundary;
    const { capacity } = this;
    const depth = this.maxdepth - 1;
    const halfWidth = width2 / 2;
    const halfHeight = height2 / 2;
    const nwBoundary = new BBox(x, y, halfWidth, halfHeight);
    const neBoundary = new BBox(x + halfWidth, y, halfWidth, halfHeight);
    const swBoundary = new BBox(x, y + halfHeight, halfWidth, halfHeight);
    const seBoundary = new BBox(x + halfWidth, y + halfHeight, halfWidth, halfHeight);
    return new QuadtreeSubdivisions(
      this.child(capacity, depth, nwBoundary),
      this.child(capacity, depth, neBoundary),
      this.child(capacity, depth, swBoundary),
      this.child(capacity, depth, seBoundary)
    );
  }
};
var QuadtreeNodeNearest = class _QuadtreeNodeNearest extends QuadtreeNode {
  addCondition(e) {
    const { x, y } = e.hitTester.midPoint;
    return this.boundary.containsPoint(x, y);
  }
  findCondition(x, y, arg) {
    const { best } = arg;
    return best.distanceSquared !== 0 && this.boundary.distanceSquared(x, y) < best.distanceSquared;
  }
  findAction(x, y, arg) {
    const other = nearestSquared(x, y, this.elems, arg.best.distanceSquared);
    if (other.nearest !== void 0 && other.distanceSquared < arg.best.distanceSquared) {
      arg.best = other;
    }
  }
  child(capacity, depth, boundary) {
    return new _QuadtreeNodeNearest(capacity, depth, boundary);
  }
};
var DataModelSeries = class extends Series {
  constructor() {
    super(...arguments);
    this.showFocusBox = true;
    this.clipFocusBox = true;
  }
  getScaleInformation({
    xScale,
    yScale
  }) {
    const isContinuousX = ContinuousScale.is(xScale);
    const isContinuousY = ContinuousScale.is(yScale);
    return { isContinuousX, isContinuousY, xScaleType: xScale?.type, yScaleType: yScale?.type };
  }
  getModulePropertyDefinitions() {
    const xScale = this.axes[
      "x"
      /* X */
    ]?.scale;
    const yScale = this.axes[
      "y"
      /* Y */
    ]?.scale;
    return this.moduleMap.mapModules((mod2) => mod2.getPropertyDefinitions(this.getScaleInformation({ xScale, yScale }))).flat();
  }
  // Request data, but with message dispatching to series-options (modules).
  async requestDataModel(dataController, data, opts) {
    opts.props.push(...this.getModulePropertyDefinitions());
    const { dataModel, processedData } = await dataController.request(this.id, data ?? [], opts);
    this.dataModel = dataModel;
    this.processedData = processedData;
    this.dispatch("data-processed", { dataModel, processedData });
    return { dataModel, processedData };
  }
  isProcessedDataAnimatable() {
    const validationResults = this.processedData?.reduced?.animationValidation;
    if (!validationResults) {
      return true;
    }
    const { orderedKeys, uniqueKeys } = validationResults;
    return orderedKeys && uniqueKeys;
  }
  checkProcessedDataAnimatable() {
    if (!this.isProcessedDataAnimatable()) {
      this.ctx.animationManager.skipCurrentBatch();
    }
  }
  pickFocus(opts) {
    const nodeData = this.getNodeData();
    if (nodeData === void 0 || nodeData.length === 0) {
      return;
    }
    const datumIndex = this.computeFocusDatumIndex(opts, nodeData);
    if (datumIndex === void 0) {
      return;
    }
    const { showFocusBox, clipFocusBox } = this;
    const datum = nodeData[datumIndex];
    const derivedOpts = { ...opts, datumIndex };
    const bounds = this.computeFocusBounds(derivedOpts);
    if (bounds !== void 0) {
      return { bounds, showFocusBox, clipFocusBox, datum, datumIndex };
    }
  }
  computeFocusDatumIndex(opts, nodeData) {
    const isDatumEnabled = (datumIndex2) => {
      const { missing = false, enabled = true, focusable = true } = nodeData[datumIndex2];
      return !missing && enabled && focusable;
    };
    const searchBackward = (datumIndex2) => {
      while (datumIndex2 >= 0 && !isDatumEnabled(datumIndex2)) {
        datumIndex2 += opts.datumIndexDelta;
      }
      return datumIndex2 === -1 ? void 0 : datumIndex2;
    };
    const searchForward = (datumIndex2) => {
      while (datumIndex2 < nodeData.length && !isDatumEnabled(datumIndex2)) {
        datumIndex2 += opts.datumIndexDelta;
      }
      return datumIndex2 === nodeData.length ? void 0 : datumIndex2;
    };
    let datumIndex;
    const clampedIndex = clamp(0, opts.datumIndex, nodeData.length - 1);
    if (opts.datumIndexDelta < 0) {
      datumIndex = searchBackward(clampedIndex);
    } else if (opts.datumIndexDelta > 0) {
      datumIndex = searchForward(clampedIndex);
    } else {
      datumIndex = searchForward(clampedIndex) ?? searchBackward(clampedIndex);
    }
    if (datumIndex === void 0) {
      if (opts.datumIndexDelta === 0) {
        return;
      } else {
        return opts.datumIndex - opts.datumIndexDelta;
      }
    } else {
      return datumIndex;
    }
  }
};
var SeriesItemHighlightStyle = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.fill = "rgba(255,255,255, 0.33)";
    this.stroke = `rgba(0, 0, 0, 0.4)`;
    this.strokeWidth = 2;
  }
};
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], SeriesItemHighlightStyle.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], SeriesItemHighlightStyle.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], SeriesItemHighlightStyle.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], SeriesItemHighlightStyle.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], SeriesItemHighlightStyle.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH, { optional: true })
], SeriesItemHighlightStyle.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], SeriesItemHighlightStyle.prototype, "lineDashOffset", 2);
var SeriesHighlightStyle = class extends BaseProperties {
};
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], SeriesHighlightStyle.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], SeriesHighlightStyle.prototype, "dimOpacity", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], SeriesHighlightStyle.prototype, "enabled", 2);
var TextHighlightStyle = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.color = "black";
  }
};
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], TextHighlightStyle.prototype, "color", 2);
var HighlightProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
  }
};
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], HighlightProperties.prototype, "enabled", 2);
var HighlightStyle = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.item = new SeriesItemHighlightStyle();
    this.series = new SeriesHighlightStyle();
    this.text = new TextHighlightStyle();
  }
};
__decorateClass([
  Validate(OBJECT)
], HighlightStyle.prototype, "item", 2);
__decorateClass([
  Validate(OBJECT)
], HighlightStyle.prototype, "series", 2);
__decorateClass([
  Validate(OBJECT)
], HighlightStyle.prototype, "text", 2);
var SeriesProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.visible = true;
    this.focusPriority = Infinity;
    this.showInLegend = true;
    this.cursor = "default";
    this.nodeClickRange = "exact";
    this.highlight = new HighlightProperties();
    this.highlightStyle = new HighlightStyle();
  }
};
__decorateClass([
  Validate(STRING, { optional: true })
], SeriesProperties.prototype, "id", 2);
__decorateClass([
  Validate(BOOLEAN)
], SeriesProperties.prototype, "visible", 2);
__decorateClass([
  Validate(REAL_NUMBER, { optional: true })
], SeriesProperties.prototype, "focusPriority", 2);
__decorateClass([
  Validate(BOOLEAN)
], SeriesProperties.prototype, "showInLegend", 2);
__decorateClass([
  Validate(STRING)
], SeriesProperties.prototype, "cursor", 2);
__decorateClass([
  Validate(INTERACTION_RANGE)
], SeriesProperties.prototype, "nodeClickRange", 2);
__decorateClass([
  Validate(OBJECT)
], SeriesProperties.prototype, "highlight", 2);
__decorateClass([
  Validate(OBJECT)
], SeriesProperties.prototype, "highlightStyle", 2);
var DEFAULT_CARTESIAN_DIRECTION_KEYS = {
  [
    "x"
    /* X */
  ]: ["xKey"],
  [
    "y"
    /* Y */
  ]: ["yKey"]
};
var DEFAULT_CARTESIAN_DIRECTION_NAMES = {
  [
    "x"
    /* X */
  ]: ["xName"],
  [
    "y"
    /* Y */
  ]: ["yName"]
};
var CartesianSeriesNodeEvent = class extends SeriesNodeEvent {
  constructor(type, nativeEvent, datum, series) {
    super(type, nativeEvent, datum, series);
    this.xKey = series.properties.xKey;
    this.yKey = series.properties.yKey;
  }
};
var CartesianSeriesProperties = class extends SeriesProperties {
  constructor() {
    super(...arguments);
    this.pickOutsideVisibleMinorAxis = false;
  }
};
__decorateClass([
  Validate(STRING, { optional: true })
], CartesianSeriesProperties.prototype, "legendItemName", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], CartesianSeriesProperties.prototype, "pickOutsideVisibleMinorAxis", 2);
var RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD = 100;
var CartesianSeries = class extends DataModelSeries {
  constructor({
    pathsPerSeries = ["path"],
    hasMarkers = false,
    hasHighlightedLabels = false,
    pathsZIndexSubOrderOffset = [],
    datumSelectionGarbageCollection = true,
    markerSelectionGarbageCollection = true,
    animationAlwaysUpdateSelections = false,
    animationResetFns,
    directionKeys,
    directionNames,
    ...otherOpts
  }) {
    super({
      directionKeys,
      directionNames,
      canHaveAxes: true,
      ...otherOpts
    });
    this.NodeEvent = CartesianSeriesNodeEvent;
    this.dataNodeGroup = this.contentGroup.appendChild(
      new Group({ name: `${this.id}-series-dataNodes`, zIndex: 0 })
    );
    this.markerGroup = this.contentGroup.appendChild(
      new Group({ name: `${this.id}-series-markers`, zIndex: 1 })
    );
    this.labelGroup = this.contentGroup.appendChild(
      new TranslatableGroup({ name: `${this.id}-series-labels` })
    );
    this.labelSelection = Selection.select(this.labelGroup, Text);
    this.highlightSelection = Selection.select(
      this.highlightNode,
      () => this.opts.hasMarkers ? this.markerFactory() : this.nodeFactory()
    );
    this.highlightLabelSelection = Selection.select(this.highlightLabel, Text);
    this.annotationSelections = /* @__PURE__ */ new Set();
    this.minRectsCache = {
      dirtyNodeData: true
    };
    this.debug = Debug.create();
    if (!directionKeys || !directionNames)
      throw new Error(`Unable to initialise series type ${this.type}`);
    this.opts = {
      pathsPerSeries,
      hasMarkers,
      hasHighlightedLabels,
      pathsZIndexSubOrderOffset,
      directionKeys,
      directionNames,
      animationResetFns,
      animationAlwaysUpdateSelections,
      datumSelectionGarbageCollection,
      markerSelectionGarbageCollection
    };
    this.paths = pathsPerSeries.map((path) => {
      return new Path({ name: `${this.id}-${path}` });
    });
    this.datumSelection = Selection.select(
      this.dataNodeGroup,
      () => this.nodeFactory(),
      datumSelectionGarbageCollection
    );
    this.markerSelection = Selection.select(
      this.markerGroup,
      () => this.markerFactory(),
      markerSelectionGarbageCollection
    );
    this.animationState = new StateMachine(
      "empty",
      {
        empty: {
          update: {
            target: "ready",
            action: (data) => this.animateEmptyUpdateReady(data)
          },
          reset: "empty",
          skip: "ready",
          disable: "disabled"
        },
        ready: {
          updateData: "waiting",
          clear: "clearing",
          highlight: (data) => this.animateReadyHighlight(data),
          highlightMarkers: (data) => this.animateReadyHighlightMarkers(data),
          resize: (data) => this.animateReadyResize(data),
          reset: "empty",
          skip: "ready",
          disable: "disabled"
        },
        waiting: {
          update: {
            target: "ready",
            action: (data) => {
              if (this.ctx.animationManager.isSkipped()) {
                this.resetAllAnimation(data);
              } else {
                this.animateWaitingUpdateReady(data);
              }
            }
          },
          reset: "empty",
          skip: "ready",
          disable: "disabled"
        },
        disabled: {
          update: (data) => this.resetAllAnimation(data),
          reset: "empty"
        },
        clearing: {
          update: {
            target: "empty",
            action: (data) => this.animateClearingUpdateEmpty(data)
          },
          reset: "empty",
          skip: "ready"
        }
      },
      () => this.checkProcessedDataAnimatable()
    );
  }
  get contextNodeData() {
    return this._contextNodeData;
  }
  getNodeData() {
    return this.contextNodeData?.nodeData;
  }
  attachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.attachSeries(seriesContentNode, seriesNode, annotationNode);
    this.attachPaths(this.paths, seriesNode, annotationNode);
  }
  detachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.detachSeries(seriesContentNode, seriesNode, annotationNode);
    this.detachPaths(this.paths, seriesNode, annotationNode);
  }
  attachPaths(paths, _seriesNode, _annotationNode) {
    for (const path of paths) {
      this.contentGroup.appendChild(path);
    }
  }
  detachPaths(paths, _seriesNode, _annotationNode) {
    for (const path of paths) {
      this.contentGroup.removeChild(path);
    }
  }
  renderToOffscreenCanvas() {
    const nodeData = this.getNodeData();
    return nodeData != null && nodeData.length > RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD;
  }
  resetAnimation(phase) {
    if (phase === "initial") {
      this.animationState.transition("reset");
    } else if (phase === "ready") {
      this.animationState.transition("skip");
    } else if (phase === "disabled") {
      this.animationState.transition("disable");
    }
  }
  addChartEventListeners() {
    this.destroyFns.push(
      this.ctx.chartEventManager.addListener("legend-item-click", (event) => this.onLegendItemClick(event)),
      this.ctx.chartEventManager.addListener(
        "legend-item-double-click",
        (event) => this.onLegendItemDoubleClick(event)
      )
    );
  }
  destroy() {
    super.destroy();
    this._contextNodeData = void 0;
  }
  update({ seriesRect }) {
    const { visible, _contextNodeData: previousContextData } = this;
    const series = this.ctx.highlightManager?.getActiveHighlight()?.series;
    const seriesHighlighted = series === this;
    const resize = this.checkResize(seriesRect);
    const highlightItems = this.updateHighlightSelection(seriesHighlighted);
    this.updateSelections(visible);
    this.updateNodes(highlightItems, seriesHighlighted, visible);
    const animationData = this.getAnimationData(seriesRect, previousContextData);
    if (!animationData)
      return;
    if (resize) {
      this.animationState.transition("resize", animationData);
    }
    this.animationState.transition("update", animationData);
  }
  updateSelections(anySeriesItemEnabled) {
    var _a;
    const animationSkipUpdate = !this.opts.animationAlwaysUpdateSelections && this.ctx.animationManager.isSkipped();
    if (!anySeriesItemEnabled && animationSkipUpdate) {
      return;
    }
    if (!this.nodeDataRefresh && !this.isPathOrSelectionDirty()) {
      return;
    }
    if (this.nodeDataRefresh) {
      this.nodeDataRefresh = false;
      this.debug(`CartesianSeries.updateSelections() - calling createNodeData() for`, this.id);
      this.markQuadtreeDirty();
      this._contextNodeData = this.createNodeData();
      const animationValid = this.isProcessedDataAnimatable();
      if (this._contextNodeData) {
        (_a = this._contextNodeData).animationValid ?? (_a.animationValid = animationValid);
      }
      this.minRectsCache.dirtyNodeData = true;
      const { dataModel, processedData } = this;
      if (dataModel !== void 0 && processedData !== void 0) {
        this.dispatch("data-update", { dataModel, processedData });
      }
    }
    this.updateSeriesSelections();
  }
  updateSeriesSelections(seriesHighlighted) {
    const { datumSelection, labelSelection, markerSelection, paths } = this;
    const contextData = this._contextNodeData;
    if (!contextData)
      return;
    const { nodeData, labelData, itemId } = contextData;
    this.updatePaths({ seriesHighlighted, itemId, contextData, paths });
    this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
    this.labelSelection = this.updateLabelSelection({ labelData, labelSelection }) ?? labelSelection;
    if (this.opts.hasMarkers) {
      this.markerSelection = this.updateMarkerSelection({ nodeData, markerSelection });
    }
  }
  markerFactory() {
    const MarkerShape = getMarker();
    return new MarkerShape();
  }
  updateNodes(highlightedItems, seriesHighlighted, anySeriesItemEnabled) {
    const {
      highlightSelection,
      highlightLabelSelection,
      opts: { hasMarkers, hasHighlightedLabels }
    } = this;
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const visible = this.visible && this._contextNodeData != null && anySeriesItemEnabled;
    this.contentGroup.visible = animationEnabled || visible;
    this.highlightGroup.visible = (animationEnabled || visible) && seriesHighlighted;
    const opacity = this.getOpacity();
    if (hasMarkers) {
      this.updateMarkerNodes({
        markerSelection: highlightSelection,
        isHighlight: true
      });
      this.animationState.transition("highlightMarkers", highlightSelection);
    } else {
      this.updateDatumNodes({
        datumSelection: highlightSelection,
        isHighlight: true
      });
      this.animationState.transition("highlight", highlightSelection);
    }
    if (hasHighlightedLabels) {
      this.updateLabelNodes({ labelSelection: highlightLabelSelection });
    }
    const { dataNodeGroup, markerGroup, datumSelection, labelSelection, markerSelection, paths, labelGroup } = this;
    const { itemId } = this.contextNodeData ?? {};
    dataNodeGroup.opacity = opacity;
    dataNodeGroup.visible = animationEnabled || visible;
    labelGroup.visible = visible;
    if (hasMarkers) {
      markerGroup.opacity = opacity;
      markerGroup.visible = visible;
    }
    if (labelGroup) {
      labelGroup.opacity = opacity;
    }
    this.updatePathNodes({
      seriesHighlighted,
      itemId,
      paths,
      opacity,
      visible,
      animationEnabled
    });
    if (!dataNodeGroup.visible) {
      return;
    }
    this.updateDatumNodes({ datumSelection, highlightedItems, isHighlight: false });
    if (!this.usesPlacedLabels) {
      this.updateLabelNodes({ labelSelection });
    }
    if (hasMarkers) {
      this.updateMarkerNodes({ markerSelection, isHighlight: false });
    }
  }
  getHighlightLabelData(labelData, highlightedItem) {
    const labelItems = labelData.filter(
      (ld) => ld.datum === highlightedItem.datum && ld.itemId === highlightedItem.itemId
    );
    return labelItems.length === 0 ? void 0 : labelItems;
  }
  getHighlightData(_nodeData, highlightedItem) {
    return highlightedItem ? [highlightedItem] : void 0;
  }
  updateHighlightSelection(seriesHighlighted) {
    const { highlightSelection, highlightLabelSelection, _contextNodeData: contextNodeData } = this;
    if (!contextNodeData)
      return;
    const highlightedDatum = this.ctx.highlightManager?.getActiveHighlight();
    const item = seriesHighlighted && highlightedDatum?.datum ? highlightedDatum : void 0;
    let labelItems;
    let highlightItems;
    if (item != null) {
      const labelsEnabled = this.isLabelEnabled();
      const { labelData, nodeData } = contextNodeData;
      highlightItems = this.getHighlightData(nodeData, item);
      labelItems = labelsEnabled ? this.getHighlightLabelData(labelData, item) : void 0;
    }
    this.highlightSelection = this.updateHighlightSelectionItem({
      items: highlightItems,
      highlightSelection
    });
    this.highlightLabelSelection = this.updateHighlightSelectionLabel({
      items: labelItems,
      highlightLabelSelection
    });
    return highlightItems;
  }
  markQuadtreeDirty() {
    this.quadtree = void 0;
  }
  *datumNodesIter() {
    for (const { node } of this.datumSelection) {
      if (node.datum.missing === true)
        continue;
      yield node;
    }
  }
  getQuadTree() {
    if (this.quadtree === void 0) {
      const { width: width2, height: height2 } = this.ctx.scene.canvas;
      const canvasRect = new BBox(0, 0, width2, height2);
      this.quadtree = new QuadtreeNearest(100, 10, canvasRect);
      this.initQuadTree(this.quadtree);
    }
    return this.quadtree;
  }
  initQuadTree(_quadtree) {
  }
  pickNodeExactShape(point) {
    const result = super.pickNodeExactShape(point);
    if (result) {
      return result;
    }
    const { x, y } = point;
    const {
      opts: { hasMarkers }
    } = this;
    let match;
    const { dataNodeGroup, markerGroup } = this;
    match = dataNodeGroup.pickNode(x, y);
    if (!match && hasMarkers) {
      match = markerGroup?.pickNode(x, y);
    }
    if (match && match.datum.missing !== true) {
      return { datum: match.datum, distance: 0 };
    }
    for (const mod2 of this.moduleMap.modules()) {
      const { datum } = mod2.pickNodeExact(point) ?? {};
      if (datum == null)
        continue;
      if (datum?.missing === true)
        continue;
      return { datum, distance: 0 };
    }
  }
  pickNodeClosestDatum(point) {
    const { x, y } = point;
    const { axes, _contextNodeData: contextNodeData } = this;
    if (!contextNodeData)
      return;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    const hitPoint = { x, y };
    let minDistance = Infinity;
    let closestDatum;
    for (const datum of contextNodeData.nodeData) {
      const { point: { x: datumX = NaN, y: datumY = NaN } = {} } = datum;
      if (isNaN(datumX) || isNaN(datumY)) {
        continue;
      }
      const isInRange = xAxis?.inRange(datumX) && yAxis?.inRange(datumY);
      if (!isInRange) {
        continue;
      }
      const distance3 = Math.max((hitPoint.x - datumX) ** 2 + (hitPoint.y - datumY) ** 2, 0);
      if (distance3 < minDistance) {
        minDistance = distance3;
        closestDatum = datum;
      }
    }
    for (const mod2 of this.moduleMap.modules()) {
      const modPick = mod2.pickNodeNearest(point);
      if (modPick !== void 0 && modPick.distanceSquared < minDistance) {
        minDistance = modPick.distanceSquared;
        closestDatum = modPick.datum;
        break;
      }
    }
    if (closestDatum) {
      const distance3 = Math.max(Math.sqrt(minDistance) - (closestDatum.point?.size ?? 0), 0);
      return { datum: closestDatum, distance: distance3 };
    }
  }
  pickNodeMainAxisFirst(point, requireCategoryAxis) {
    const { x, y } = point;
    const { axes, _contextNodeData: contextNodeData } = this;
    const { pickOutsideVisibleMinorAxis } = this.properties;
    if (!contextNodeData)
      return;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    const directions2 = [xAxis, yAxis].filter(CategoryAxis.is).map((a) => a.direction);
    if (requireCategoryAxis && directions2.length === 0)
      return;
    const [
      majorDirection = "x"
      /* X */
    ] = directions2;
    const hitPointCoords = [x, y];
    if (majorDirection !== "x")
      hitPointCoords.reverse();
    const minDistance = [Infinity, Infinity];
    let closestDatum;
    for (const datum of contextNodeData.nodeData) {
      const { x: datumX = NaN, y: datumY = NaN } = datum.point ?? datum.midPoint ?? {};
      if (isNaN(datumX) || isNaN(datumY) || datum.missing === true)
        continue;
      const visible = [xAxis?.inRange(datumX), yAxis?.inRange(datumY)];
      if (majorDirection !== "x") {
        visible.reverse();
      }
      if (!visible[0] || !pickOutsideVisibleMinorAxis && !visible[1])
        continue;
      const datumPoint = [datumX, datumY];
      if (majorDirection !== "x") {
        datumPoint.reverse();
      }
      let newMinDistance = true;
      for (let i = 0; i < datumPoint.length; i++) {
        const dist = Math.abs(datumPoint[i] - hitPointCoords[i]);
        if (dist > minDistance[i]) {
          newMinDistance = false;
          break;
        } else if (dist < minDistance[i]) {
          minDistance[i] = dist;
          minDistance.fill(Infinity, i + 1, minDistance.length);
        }
      }
      if (newMinDistance) {
        closestDatum = datum;
      }
    }
    if (closestDatum) {
      let closestDistanceSquared = Math.max(
        minDistance[0] ** 2 + minDistance[1] ** 2 - (closestDatum.point?.size ?? 0),
        0
      );
      for (const mod2 of this.moduleMap.modules()) {
        const modPick = mod2.pickNodeMainAxisFirst(point);
        if (modPick !== void 0 && modPick.distanceSquared < closestDistanceSquared) {
          closestDatum = modPick.datum;
          closestDistanceSquared = modPick.distanceSquared;
          break;
        }
      }
      return { datum: closestDatum, distance: Math.sqrt(closestDistanceSquared) };
    }
  }
  isPathOrSelectionDirty() {
    return false;
  }
  shouldFlipXY() {
    return false;
  }
  /**
   * Get the minimum bounding box that contains any adjacent two nodes. The axes are treated independently, so this
   * may not represent the same two points for both directions. The dimensions represent the greatest distance
   * between any two adjacent nodes.
   */
  getMinRects(width2, height2) {
    const { dirtyNodeData, sizeCache, minRect, minVisibleRect } = this.minRectsCache;
    const newSizeCache = JSON.stringify({ width: width2, height: height2 });
    const dirtySize = newSizeCache !== sizeCache;
    if (!dirtySize && !dirtyNodeData && minRect && minVisibleRect) {
      return { minRect, minVisibleRect };
    }
    const rects = this.computeMinRects(width2, height2);
    this.minRectsCache = {
      dirtyNodeData: false,
      sizeCache: newSizeCache,
      minRect: rects?.minRect,
      minVisibleRect: rects?.minVisibleRect
    };
    return rects;
  }
  computeMinRects(width2, height2) {
    const context = this._contextNodeData;
    if (!context?.nodeData.length) {
      return;
    }
    const { nodeData } = context;
    const minRectXs = Array(nodeData.length);
    const minRectYs = Array(nodeData.length);
    for (const [i, { midPoint }] of nodeData.entries()) {
      minRectXs[i] = midPoint?.x ?? 0;
      minRectYs[i] = midPoint?.y ?? 0;
    }
    minRectXs.sort((a, b) => a - b);
    minRectYs.sort((a, b) => a - b);
    let zeroX, widthX, zeroY, heightY;
    let maxWidth = 0;
    let maxHeight = 0;
    for (let i = 1; i < nodeData.length; i++) {
      if (minRectXs[i] >= 0)
        zeroX ?? (zeroX = i);
      if (minRectXs[i] > width2)
        widthX ?? (widthX = i);
      if (minRectYs[i] >= 0)
        zeroY ?? (zeroY = i);
      if (minRectYs[i] > height2)
        heightY ?? (heightY = i);
      maxWidth = Math.max(maxWidth, minRectXs[i] - minRectXs[i - 1]);
      maxHeight = Math.max(maxHeight, minRectYs[i] - minRectYs[i - 1]);
    }
    widthX ?? (widthX = nodeData.length);
    heightY ?? (heightY = nodeData.length);
    const minVisibleRectXs = zeroX != null && widthX != null ? minRectXs.slice(zeroX, widthX) : [];
    const minVisibleRectYs = zeroY != null && heightY != null ? minRectYs.slice(zeroY, heightY) : [];
    let maxVisibleWidth = 0;
    let maxVisibleHeight = 0;
    for (let i = 1; i < Math.max(minVisibleRectXs.length, minVisibleRectYs.length); i++) {
      const x1 = minVisibleRectXs[i];
      const x2 = minVisibleRectXs[i - 1];
      const y1 = minVisibleRectYs[i];
      const y2 = minVisibleRectYs[i - 1];
      if (x1 != null && x2 != null) {
        maxVisibleWidth = Math.max(maxVisibleWidth, x1 - x2);
      }
      if (y1 != null && y2 != null) {
        maxVisibleHeight = Math.max(maxVisibleHeight, y1 - y2);
      }
    }
    const minRect = new BBox(0, 0, maxWidth, maxHeight);
    const minVisibleRect = new BBox(0, 0, maxVisibleWidth, maxVisibleHeight);
    return { minRect, minVisibleRect };
  }
  updateHighlightSelectionItem(opts) {
    const {
      opts: { hasMarkers }
    } = this;
    const { items, highlightSelection } = opts;
    const nodeData = items ?? [];
    if (hasMarkers) {
      const markerSelection = highlightSelection;
      return this.updateMarkerSelection({ nodeData, markerSelection });
    } else {
      return this.updateDatumSelection({
        nodeData,
        datumSelection: highlightSelection
      });
    }
  }
  updateHighlightSelectionLabel(opts) {
    return this.updateLabelSelection({
      labelData: opts.items ?? [],
      labelSelection: opts.highlightLabelSelection
    });
  }
  updateDatumSelection(opts) {
    return opts.datumSelection;
  }
  updateDatumNodes(_opts) {
  }
  updateMarkerSelection(opts) {
    return opts.markerSelection;
  }
  updateMarkerNodes(_opts) {
  }
  updatePaths(opts) {
    opts.paths.forEach((p) => p.visible = false);
  }
  updatePathNodes(opts) {
    const { paths, opacity, visible } = opts;
    for (const path of paths) {
      path.opacity = opacity;
      path.visible = visible;
    }
  }
  resetPathAnimation(data) {
    const { path } = this.opts?.animationResetFns ?? {};
    if (path) {
      data.paths.forEach((paths) => {
        resetMotion([paths], path);
      });
    }
  }
  resetDatumAnimation(data) {
    const { datum } = this.opts?.animationResetFns ?? {};
    if (datum) {
      resetMotion([data.datumSelection], datum);
    }
  }
  resetLabelAnimation(data) {
    const { label } = this.opts?.animationResetFns ?? {};
    if (label) {
      resetMotion([data.labelSelection], label);
    }
  }
  resetMarkerAnimation(data) {
    const { marker } = this.opts?.animationResetFns ?? {};
    if (marker && this.opts.hasMarkers) {
      resetMotion([data.markerSelection], marker);
    }
  }
  resetAllAnimation(data) {
    this.ctx.animationManager.stopByAnimationGroupId(this.id);
    this.resetPathAnimation(data);
    this.resetDatumAnimation(data);
    this.resetLabelAnimation(data);
    this.resetMarkerAnimation(data);
    if (data.contextData?.animationValid === false) {
      this.ctx.animationManager.skipCurrentBatch();
    }
  }
  animateEmptyUpdateReady(data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation(data);
  }
  animateWaitingUpdateReady(data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation(data);
  }
  animateReadyHighlight(data) {
    const { datum } = this.opts?.animationResetFns ?? {};
    if (datum) {
      resetMotion([data], datum);
    }
  }
  animateReadyHighlightMarkers(data) {
    const { marker } = this.opts?.animationResetFns ?? {};
    if (marker) {
      resetMotion([data], marker);
    }
  }
  animateReadyResize(data) {
    this.resetAllAnimation(data);
  }
  animateClearingUpdateEmpty(data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation(data);
  }
  getAnimationData(seriesRect, previousContextData) {
    const { _contextNodeData: contextData } = this;
    if (!contextData)
      return;
    const animationData = {
      datumSelection: this.datumSelection,
      markerSelection: this.markerSelection,
      labelSelection: this.labelSelection,
      annotationSelections: [...this.annotationSelections],
      contextData,
      previousContextData,
      paths: this.paths,
      seriesRect
    };
    return animationData;
  }
  updateLabelSelection(opts) {
    return opts.labelSelection;
  }
  getScaling(scale2) {
    if (scale2 instanceof LogScale) {
      const { range: range3, domain } = scale2;
      return {
        type: "log",
        convert: (d) => scale2.convert(d),
        domain: [domain[0], domain[1]],
        range: [range3[0], range3[1]]
      };
    } else if (scale2 instanceof ContinuousScale) {
      const { range: range3 } = scale2;
      const domain = scale2.getDomain();
      return {
        type: "continuous",
        domain: [domain[0], domain[1]],
        range: [range3[0], range3[1]]
      };
    } else if (scale2 instanceof BandScale) {
      const { domain } = scale2;
      return {
        type: "category",
        domain,
        inset: scale2.inset,
        step: scale2.step
      };
    }
  }
  calculateScaling() {
    const result = {};
    for (const direction of Object.values(ChartAxisDirection)) {
      const axis = this.axes[direction];
      if (!axis)
        continue;
      const scalingResult = this.getScaling(axis.scale);
      if (scalingResult != null) {
        result[direction] = scalingResult;
      }
    }
    return result;
  }
};
var directions = ["top", "right", "bottom", "left"];
var _CartesianChart = class _CartesianChart2 extends Chart {
  constructor(options, resources) {
    super(options, resources);
    this.paired = true;
    this.firstSeriesTranslation = true;
    this.lastUpdateClipRect = void 0;
  }
  onAxisChange(newValue, oldValue) {
    super.onAxisChange(newValue, oldValue);
    if (this.ctx != null) {
      this.ctx.zoomManager.updateAxes(newValue);
    }
  }
  destroySeries(series) {
    super.destroySeries(series);
    this.firstSeriesTranslation = true;
  }
  getChartType() {
    return "cartesian";
  }
  setRootClipRects(clipRect) {
    const { seriesRoot, annotationRoot } = this;
    seriesRoot.setClipRect(clipRect);
    annotationRoot.setClipRect(clipRect);
  }
  performLayout(ctx) {
    const { firstSeriesTranslation, seriesRoot, annotationRoot } = this;
    const { clipSeries, seriesRect, visible } = this.updateAxes(ctx.layoutBox);
    this.seriesRoot.visible = visible;
    this.seriesRect = seriesRect;
    this.animationRect = ctx.layoutBox;
    const { x, y } = seriesRect;
    if (firstSeriesTranslation) {
      for (const group of [seriesRoot, annotationRoot]) {
        group.translationX = Math.floor(x);
        group.translationY = Math.floor(y);
      }
      this.firstSeriesTranslation = false;
    } else {
      const { translationX, translationY } = seriesRoot;
      staticFromToMotion(
        this.id,
        "seriesRect",
        this.ctx.animationManager,
        [seriesRoot, annotationRoot],
        { translationX, translationY },
        { translationX: Math.floor(x), translationY: Math.floor(y) },
        { phase: "update" }
      );
    }
    const seriesPaddedRect = seriesRect.clone().grow(this.seriesArea.padding);
    const clipRect = this.seriesArea.clip || clipSeries ? seriesPaddedRect : void 0;
    const { lastUpdateClipRect } = this;
    this.lastUpdateClipRect = clipRect;
    if (this.ctx.animationManager.isActive() && lastUpdateClipRect != null) {
      this.ctx.animationManager.animate({
        id: this.id,
        groupId: "clip-rect",
        phase: "update",
        from: lastUpdateClipRect,
        to: seriesPaddedRect,
        onUpdate: (interpolatedClipRect) => this.setRootClipRects(interpolatedClipRect),
        onComplete: () => this.setRootClipRects(clipRect)
      });
    } else {
      this.setRootClipRects(clipRect);
    }
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      axes: this.axes.map((axis) => axis.getLayoutState()),
      series: {
        visible,
        rect: seriesRect,
        paddedRect: seriesPaddedRect,
        shouldFlipXY: this.shouldFlipXY()
      },
      clipSeries
    });
  }
  updateAxes(layoutBox) {
    const { clipSeries, seriesRect, overflows } = this.resolveAxesLayout(layoutBox);
    for (const axis of this.axes) {
      axis.update();
      axis.setCrossLinesVisible(!overflows);
      this.clipAxis(axis, seriesRect, layoutBox);
    }
    return { clipSeries, seriesRect, visible: !overflows };
  }
  // Iteratively try to resolve axis widths - since X axis width affects Y axis range,
  // and vice-versa, we need to iteratively try and find a fit for the axes and their
  // ticks/labels.
  resolveAxesLayout(layoutBox) {
    let newState;
    let prevState;
    let iterations = 0;
    const maxIterations = 10;
    do {
      prevState = newState ?? this.getDefaultState();
      newState = this.updateAxesPass(new Map(prevState.axisAreaWidths), layoutBox.clone());
      if (iterations++ > maxIterations) {
        Logger.warn("Max iterations reached. Unable to stabilize axes layout.");
        break;
      }
    } while (!this.isLayoutStable(newState, prevState));
    this.lastAreaWidths = newState.axisAreaWidths;
    return newState;
  }
  updateAxesPass(axisAreaWidths, axisAreaBound) {
    const axisWidths = /* @__PURE__ */ new Map();
    const primaryTickCounts = {};
    let overflows = false;
    let clipSeries = false;
    for (const dir of directions) {
      const padding = this.seriesArea.padding[dir];
      const axis = this.axes.findLast((a) => a.position === dir);
      if (axis) {
        axis.seriesAreaPadding = padding;
      } else {
        axisAreaBound.shrink(padding, dir);
      }
    }
    const totalWidth = (axisAreaWidths.get("left") ?? 0) + (axisAreaWidths.get("right") ?? 0);
    const totalHeight = (axisAreaWidths.get("top") ?? 0) + (axisAreaWidths.get("bottom") ?? 0);
    const crossLinePadding = this.buildCrossLinePadding(axisAreaWidths);
    if (axisAreaBound.width <= totalWidth + crossLinePadding.hPadding || axisAreaBound.height <= totalHeight + crossLinePadding.vPadding) {
      overflows = true;
    } else {
      axisAreaBound.shrink(crossLinePadding);
    }
    const seriesRect = axisAreaBound.clone().shrink(Object.fromEntries(axisAreaWidths));
    for (const axis of this.axes) {
      const { position = "left", direction } = axis;
      this.sizeAxis(axis, seriesRect, position);
      const syncedDomain = this.getSyncedDomain(axis);
      const isVertical = direction === "y";
      const layout = axis.calculateLayout(syncedDomain, axis.nice ? primaryTickCounts[direction] : void 0);
      primaryTickCounts[direction] ?? (primaryTickCounts[direction] = layout.primaryTickCount);
      clipSeries || (clipSeries = axis.dataDomain.clipped || axis.visibleRange[0] > 0 || axis.visibleRange[1] < 1);
      axisWidths.set(axis.id, Math.ceil(axis.thickness ?? (isVertical ? layout.bbox.width : layout.bbox.height)));
    }
    const axisGroups = Object.entries(groupBy(this.axes, (axis) => axis.position ?? "left"));
    const { width: width2, height: height2, canvas } = this.ctx.scene;
    const newAxisAreaWidths = /* @__PURE__ */ new Map();
    const axisOffsets = /* @__PURE__ */ new Map();
    for (const [position, axes] of axisGroups) {
      const isVertical = position === "left" || position === "right";
      let currentOffset = isVertical ? height2 % canvas.pixelRatio : width2 % canvas.pixelRatio;
      let totalAxisWidth = 0;
      for (const axis of axes) {
        axisOffsets.set(axis.id, currentOffset);
        const axisThickness = axisWidths.get(axis.id) ?? 0;
        totalAxisWidth = Math.max(totalAxisWidth, currentOffset + axisThickness);
        if (axis.layoutConstraints.stacked) {
          currentOffset += axisThickness + _CartesianChart2.AxesPadding;
        }
      }
      newAxisAreaWidths.set(position, Math.ceil(totalAxisWidth));
    }
    for (const [position, axes] of axisGroups) {
      this.positionAxes({
        axes,
        position,
        axisWidths,
        axisOffsets,
        axisAreaWidths: newAxisAreaWidths,
        axisBound: axisAreaBound,
        seriesRect
      });
    }
    return { clipSeries, seriesRect, axisAreaWidths: newAxisAreaWidths, overflows };
  }
  buildCrossLinePadding(axisAreaSize) {
    const crossLinePadding = { top: 0, right: 0, bottom: 0, left: 0, hPadding: 0, vPadding: 0 };
    this.axes.forEach((axis) => {
      axis.crossLines?.forEach((crossLine) => {
        crossLine.calculatePadding?.(crossLinePadding);
      });
    });
    for (const [side, padding = 0] of Object.entries(crossLinePadding)) {
      crossLinePadding[side] = Math.max(padding - (axisAreaSize.get(side) ?? 0), 0);
    }
    crossLinePadding.hPadding = crossLinePadding.left + crossLinePadding.right;
    crossLinePadding.vPadding = crossLinePadding.top + crossLinePadding.bottom;
    return crossLinePadding;
  }
  clampToOutsideSeriesRect(seriesRect, value, dimension, direction) {
    const bound = dimension === "x" ? seriesRect.x : seriesRect.y;
    const size = dimension === "x" ? seriesRect.width : seriesRect.height;
    return direction === 1 ? Math.min(value, bound + size) : Math.max(value, bound);
  }
  getSyncedDomain(axis) {
    const syncModule = this.modulesManager.getModule("sync");
    if (!syncModule?.enabled)
      return;
    const syncedDomain = syncModule.getSyncedDomain(axis);
    if (syncedDomain && axis.dataDomain.domain.length) {
      let shouldUpdate;
      const { domain } = axis.scale;
      if (ContinuousScale.is(axis.scale)) {
        const [min, max] = findMinMax(syncedDomain);
        shouldUpdate = min !== domain[0] || max !== domain[1];
      } else {
        shouldUpdate = !arraysEqual(syncedDomain, domain);
      }
      if (shouldUpdate && !this.skipSync) {
        syncModule.updateSiblings();
      }
    }
    return syncedDomain;
  }
  sizeAxis(axis, seriesRect, position) {
    const isCategory = axis instanceof CategoryAxis;
    const isLeftRight = position === "left" || position === "right";
    const { width: width2, height: height2 } = seriesRect;
    const maxEnd = isLeftRight ? height2 : width2;
    let start2 = 0;
    let end2 = maxEnd;
    let { min, max } = this.ctx.zoomManager.getAxisZoom(axis.id);
    const { width: axisWidth, unit, align } = axis.layoutConstraints;
    if (unit === "px") {
      end2 = start2 + axisWidth;
    } else {
      end2 = end2 * axisWidth / 100;
    }
    if (align === "end") {
      start2 = maxEnd - (end2 - start2);
      end2 = maxEnd;
    }
    if (isLeftRight) {
      if (isCategory) {
        [min, max] = [1 - max, 1 - min];
      } else {
        [start2, end2] = [end2, start2];
      }
    }
    axis.range = [start2, end2];
    axis.visibleRange = [min, max];
    axis.gridLength = isLeftRight ? width2 : height2;
  }
  positionAxes(opts) {
    const { axes, axisBound, axisWidths, axisOffsets, axisAreaWidths, seriesRect, position } = opts;
    const axisAreaWidth = axisAreaWidths.get(position) ?? 0;
    let mainDimension = "x";
    let minorDimension = "y";
    let direction = 1;
    if (position === "top" || position === "bottom") {
      mainDimension = "y";
      minorDimension = "x";
    }
    let axisBoundMainOffset = axisBound[mainDimension];
    if (position === "right" || position === "bottom") {
      direction = -1;
      axisBoundMainOffset += mainDimension === "x" ? axisBound.width : axisBound.height;
    }
    for (const axis of axes) {
      const minorOffset = axisAreaWidths.get(minorDimension === "x" ? "left" : "top") ?? 0;
      const axisThickness = axisWidths.get(axis.id) ?? 0;
      const axisOffset = axisOffsets.get(axis.id) ?? 0;
      axis.gridPadding = axisAreaWidth - axisOffset - axisThickness;
      axis.translation[minorDimension] = axisBound[minorDimension] + minorOffset;
      axis.translation[mainDimension] = this.clampToOutsideSeriesRect(
        seriesRect,
        axisBoundMainOffset + direction * (axisOffset + axisThickness),
        mainDimension,
        direction
      );
    }
  }
  shouldFlipXY() {
    return this.series.every((series) => series instanceof CartesianSeries && series.shouldFlipXY());
  }
  getDefaultState() {
    const axisAreaWidths = /* @__PURE__ */ new Map();
    if (this.lastAreaWidths) {
      for (const { position = "left" } of this.axes) {
        const areaWidth = this.lastAreaWidths.get(position);
        if (areaWidth != null) {
          axisAreaWidths.set(position, areaWidth);
        }
      }
    }
    return { axisAreaWidths, clipSeries: false, overflows: false };
  }
  isLayoutStable(newState, prevState) {
    if (prevState.overflows !== newState.overflows || prevState.clipSeries !== newState.clipSeries) {
      return false;
    }
    for (const key of newState.axisAreaWidths.keys()) {
      if (!prevState.axisAreaWidths.has(key)) {
        return false;
      }
    }
    for (const [p, w] of prevState.axisAreaWidths.entries()) {
      const otherW = newState.axisAreaWidths.get(p);
      if ((w != null || otherW != null) && w !== otherW) {
        return false;
      }
    }
    return true;
  }
  clipAxis(axis, seriesRect, layoutBBox) {
    const gridLinePadding = Math.ceil(axis.gridLine?.width ?? 0);
    const axisLinePadding = Math.ceil(axis.line?.width ?? 0);
    let { width: width2, height: height2 } = seriesRect;
    width2 += axis.direction === "x" ? gridLinePadding : axisLinePadding;
    height2 += axis.direction === "y" ? gridLinePadding : axisLinePadding;
    axis.clipGrid(seriesRect.x, seriesRect.y, width2, height2);
    switch (axis.position) {
      case "left":
      case "right":
        axis.clipTickLines(
          layoutBBox.x,
          seriesRect.y - gridLinePadding,
          layoutBBox.width + gridLinePadding,
          seriesRect.height + gridLinePadding * 2
        );
        break;
      case "top":
      case "bottom":
        axis.clipTickLines(
          seriesRect.x - gridLinePadding,
          layoutBBox.y,
          seriesRect.width + gridLinePadding * 2,
          layoutBBox.height + gridLinePadding
        );
        break;
    }
  }
};
_CartesianChart.className = "CartesianChart";
_CartesianChart.type = "cartesian";
_CartesianChart.AxesPadding = 15;
var CartesianChart = _CartesianChart;
var _AgChartInstanceProxy = class _AgChartInstanceProxy2 {
  constructor(chart, factoryApi, licenseManager) {
    this.factoryApi = factoryApi;
    this.licenseManager = licenseManager;
    this.chart = chart;
  }
  static isInstance(x) {
    if (x instanceof _AgChartInstanceProxy2) {
      return true;
    }
    if (x.constructor?.name === "AgChartInstanceProxy" && x.chart != null) {
      return true;
    }
    return x.chart != null && this.validateImplementation(x);
  }
  static validateImplementation(x) {
    const chartProps = ["getOptions", "destroy"];
    const signatureProps = Object.keys(Object.getPrototypeOf(x) ?? {});
    return chartProps.every((prop) => signatureProps.includes(prop));
  }
  async update(options) {
    this.factoryApi.update(options, this);
    await this.chart.waitForUpdate();
  }
  async updateDelta(deltaOptions) {
    this.factoryApi.updateUserDelta(this, deltaOptions);
    await this.chart.waitForUpdate();
  }
  getOptions() {
    const options = deepClone(this.chart.getOptions());
    for (const key of Object.keys(options)) {
      if (key.startsWith("_")) {
        delete options[key];
      }
    }
    return options;
  }
  waitForUpdate() {
    return this.chart.waitForUpdate();
  }
  async download(opts) {
    const clone2 = await this.prepareResizedChart(this, opts);
    try {
      clone2.chart.download(opts?.fileName, opts?.fileFormat);
    } finally {
      clone2.destroy();
    }
  }
  async __toSVG(opts) {
    const clone2 = await this.prepareResizedChart(this, { width: 600, height: 300, ...opts });
    try {
      return clone2.chart.toSVG();
    } finally {
      clone2.destroy();
    }
  }
  async getImageDataURL(opts) {
    const clone2 = await this.prepareResizedChart(this, opts);
    try {
      return clone2.chart.getCanvasDataURL(opts?.fileFormat);
    } finally {
      clone2.destroy();
    }
  }
  getState() {
    return this.factoryApi.caretaker.save(...this.getEnabledOriginators());
  }
  async setState(state) {
    const originators = this.getEnabledOriginators();
    if (!originators.includes(this.chart.ctx.legendManager)) {
      await this.setStateOriginators(state, originators);
      return;
    }
    await this.setStateOriginators(
      state,
      originators.filter((originator) => originator !== this.chart.ctx.zoomManager)
    );
    await this.setStateOriginators(state, [this.chart.ctx.zoomManager]);
  }
  resetAnimations() {
    this.chart.resetAnimations();
  }
  skipAnimations() {
    this.chart.skipAnimations();
  }
  destroy() {
    if (this.releaseChart) {
      this.releaseChart();
      this.chart = null;
    } else {
      this.chart.publicApi = void 0;
      this.chart.destroy();
    }
  }
  async prepareResizedChart(proxy, opts = {}) {
    const { chart } = proxy;
    const width2 = opts.width ?? chart.width ?? chart.ctx.scene.canvas.width;
    const height2 = opts.height ?? chart.height ?? chart.ctx.scene.canvas.height;
    const state = proxy.getState();
    const isEnterprise = moduleRegistry.hasEnterpriseModules();
    const processedOverrides = {
      ...chart.chartOptions.processedOverrides,
      container: document.createElement("div"),
      width: width2,
      height: height2
    };
    const userOptions = chart.getOptions();
    if (isEnterprise) {
      processedOverrides.animation = { enabled: false };
      if (this.licenseManager?.isDisplayWatermark()) {
        processedOverrides.foreground = {
          text: this.licenseManager.getWatermarkMessage(),
          image: {
            url: `data:image/svg+xml;base64, `,
            width: 170,
            height: 25,
            right: 25,
            bottom: 50,
            opacity: 0.7
          }
        };
      }
    }
    const specialOverrides = { ...chart.chartOptions.specialOverrides };
    const optionsMetadata = { ...chart.chartOptions.optionMetadata };
    if (opts.width != null && opts.height != null) {
      specialOverrides.overrideDevicePixelRatio = 1;
    }
    const cloneProxy = this.factoryApi.create(userOptions, processedOverrides, specialOverrides, optionsMetadata);
    await cloneProxy.setState(state);
    cloneProxy.chart.ctx.zoomManager.updateZoom("chartProxy", chart.ctx.zoomManager.getZoom());
    cloneProxy.chart.ctx.legendManager.clearData();
    cloneProxy.chart.ctx.legendManager.update(chart.ctx.legendManager.getData());
    chart.series.forEach((series, index) => {
      if (!series.visible) {
        cloneProxy.chart.series[index].visible = false;
      }
    });
    const legendPages = [];
    for (const legend of chart.modulesManager.legends()) {
      legendPages.push(legend.legend.pagination?.currentPage ?? 0);
    }
    for (const legend of cloneProxy.chart.modulesManager.legends()) {
      const page = legendPages.shift() ?? 0;
      if (!legend.legend.pagination)
        continue;
      legend.legend.pagination.setPage(page);
    }
    cloneProxy.chart.update(0, { forceNodeDataRefresh: true });
    await cloneProxy.waitForUpdate();
    return cloneProxy;
  }
  getEnabledOriginators() {
    const {
      chartOptions: { processedOptions, optionMetadata },
      ctx: { annotationManager, chartTypeOriginator, zoomManager, legendManager }
    } = this.chart;
    const originators = [];
    if ("annotations" in processedOptions && processedOptions.annotations?.enabled) {
      originators.push(annotationManager);
    }
    const isFinancialChart = optionMetadata.presetType === "price-volume";
    if (isFinancialChart) {
      originators.push(chartTypeOriginator);
    }
    if (processedOptions.navigator?.enabled || processedOptions.zoom?.enabled) {
      originators.push(zoomManager);
    }
    if ("legend" in this.chart) {
      originators.push(legendManager);
    }
    return originators;
  }
  async setStateOriginators(state, originators) {
    this.factoryApi.caretaker.restore(state, ...originators);
    this.chart.ctx.updateService.update(2, { forceNodeDataRefresh: true });
    await this.chart.waitForUpdate();
  }
};
_AgChartInstanceProxy.chartInstances = /* @__PURE__ */ new WeakMap();
__decorateClass([
  ActionOnSet({
    oldValue(chart) {
      if (!chart.destroyed) {
        chart.publicApi = void 0;
      }
      _AgChartInstanceProxy.chartInstances.delete(chart);
    },
    newValue(chart) {
      if (!chart)
        return;
      chart.publicApi = this;
      _AgChartInstanceProxy.chartInstances.set(chart, this);
    }
  })
], _AgChartInstanceProxy.prototype, "chart", 2);
var AgChartInstanceProxy = _AgChartInstanceProxy;
var Locale = class extends BaseModuleInstance {
  constructor(ctx) {
    super();
    this.ctx = ctx;
    this.localeText = void 0;
  }
};
__decorateClass([
  ObserveChanges((target) => {
    target.ctx.localeManager.setLocaleText(target.localeText);
  }),
  Validate(PLAIN_OBJECT, { optional: true })
], Locale.prototype, "localeText", 2);
__decorateClass([
  ObserveChanges((target) => {
    target.ctx.localeManager.setLocaleTextFormatter(target.getLocaleText);
  }),
  Validate(FUNCTION, { optional: true })
], Locale.prototype, "getLocaleText", 2);
var LocaleModule = {
  type: "root",
  optionsKey: "locale",
  packageType: "community",
  chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"],
  moduleFactory: (ctx) => new Locale(ctx)
};
function stringifyValue(value, maxLength = Infinity) {
  switch (typeof value) {
    case "undefined":
      return "undefined";
    case "number":
      if (isNaN(value)) {
        return "NaN";
      } else if (value === Infinity) {
        return "Infinity";
      } else if (value === -Infinity) {
        return "-Infinity";
      }
    default:
      value = JSON.stringify(value);
      if (value.length > maxLength) {
        return `${value.slice(0, maxLength)}... (+${value.length - maxLength} characters)`;
      }
      return value;
  }
}
function countLines(text) {
  let count = 1;
  for (let i = 0; i < text.length; i++) {
    if (text.charCodeAt(i) === 10) {
      count++;
    }
  }
  return count;
}
var memorizedFns = /* @__PURE__ */ new WeakMap();
function memo(params, fnGenerator) {
  const serialisedParams = JSON.stringify(params, null, 0);
  if (!memorizedFns.has(fnGenerator)) {
    memorizedFns.set(fnGenerator, /* @__PURE__ */ new Map());
  }
  if (!memorizedFns.get(fnGenerator)?.has(serialisedParams)) {
    memorizedFns.get(fnGenerator)?.set(serialisedParams, fnGenerator(params));
  }
  return memorizedFns.get(fnGenerator)?.get(serialisedParams);
}
function simpleMemorize(fn) {
  const primitveCache = /* @__PURE__ */ new Map();
  const paramsToKeys = (...params) => {
    return params.map((v) => {
      if (typeof v === "object")
        return v;
      if (typeof v === "symbol")
        return v;
      if (!primitveCache.has(v)) {
        primitveCache.set(v, { v });
      }
      return primitveCache.get(v);
    });
  };
  const empty = {};
  const cache = /* @__PURE__ */ new WeakMap();
  return (...p) => {
    const keys = p.length === 0 ? [empty] : paramsToKeys(...p);
    let currentCache = cache;
    for (const key of keys.slice(0, -1)) {
      if (!currentCache.has(key)) {
        currentCache.set(key, /* @__PURE__ */ new WeakMap());
      }
      currentCache = currentCache.get(key);
    }
    const finalKey = keys.at(-1);
    let cachedValue = currentCache.get(finalKey);
    if (!cachedValue) {
      cachedValue = fn(...p);
      currentCache.set(finalKey, cachedValue);
    }
    return cachedValue;
  };
}
function sumValues(values, accumulator = [0, 0]) {
  for (const value of values) {
    if (typeof value !== "number") {
      continue;
    }
    if (value < 0) {
      accumulator[0] += value;
    }
    if (value > 0) {
      accumulator[1] += value;
    }
  }
  return accumulator;
}
function sum(id, matchGroupId) {
  const result = {
    id,
    matchGroupIds: [matchGroupId],
    type: "aggregate",
    aggregateFunction: (values) => sumValues(values)
  };
  return result;
}
function groupSum(id, matchGroupId) {
  return {
    id,
    type: "aggregate",
    matchGroupIds: matchGroupId ? [matchGroupId] : void 0,
    aggregateFunction: (values) => sumValues(values),
    groupAggregateFunction: (next, acc = [0, 0]) => {
      acc[0] += next?.[0] ?? 0;
      acc[1] += next?.[1] ?? 0;
      return acc;
    }
  };
}
function range2(id, matchGroupId) {
  const result = {
    id,
    matchGroupIds: [matchGroupId],
    type: "aggregate",
    aggregateFunction: (values) => ContinuousDomain.extendDomain(values)
  };
  return result;
}
function groupCount(id) {
  return {
    id,
    type: "aggregate",
    aggregateFunction: () => [0, 1],
    groupAggregateFunction: (next, acc = [0, 0]) => {
      acc[0] += next?.[0] ?? 0;
      acc[1] += next?.[1] ?? 0;
      return acc;
    }
  };
}
function groupAverage(id, matchGroupId) {
  const def = {
    id,
    matchGroupIds: matchGroupId ? [matchGroupId] : void 0,
    type: "aggregate",
    aggregateFunction: (values) => sumValues(values),
    groupAggregateFunction: (next, acc = [0, 0, -1]) => {
      acc[0] += next?.[0] ?? 0;
      acc[1] += next?.[1] ?? 0;
      acc[2]++;
      return acc;
    },
    finalFunction: (acc = [0, 0, 0]) => {
      const result = acc[0] + acc[1];
      if (result >= 0) {
        return [0, result / acc[2]];
      }
      return [result / acc[2], 0];
    }
  };
  return def;
}
function area(id, aggFn, matchGroupId) {
  const result = {
    id,
    matchGroupIds: matchGroupId ? [matchGroupId] : void 0,
    type: "aggregate",
    aggregateFunction: (values, keyRange = []) => {
      const keyWidth = keyRange[1] - keyRange[0];
      return aggFn.aggregateFunction(values).map((v) => v / keyWidth);
    }
  };
  if (aggFn.groupAggregateFunction) {
    result.groupAggregateFunction = aggFn.groupAggregateFunction;
  }
  return result;
}
function accumulatedValue(onlyPositive) {
  return () => {
    let value = 0;
    return (datum) => {
      if (!isFiniteNumber(datum)) {
        return datum;
      }
      value += onlyPositive ? Math.max(0, datum) : datum;
      return value;
    };
  };
}
function trailingAccumulatedValue() {
  return () => {
    let value = 0;
    return (datum) => {
      if (!isFiniteNumber(datum)) {
        return datum;
      }
      const trailingValue = value;
      value += datum;
      return trailingValue;
    };
  };
}
function basicContinuousCheckDatumValidation(value) {
  return value != null && isContinuous(value);
}
function basicDiscreteCheckDatumValidation(value) {
  return value != null;
}
function getValidationFn(scaleType) {
  switch (scaleType) {
    case "number":
    case "log":
    case "ordinal-time":
    case "time":
    case "color":
      return basicContinuousCheckDatumValidation;
    default:
      return basicDiscreteCheckDatumValidation;
  }
}
function getValueType(scaleType) {
  switch (scaleType) {
    case "number":
    case "log":
    case "time":
    case "color":
      return "range";
    default:
      return "category";
  }
}
function keyProperty(propName, scaleType, opts = {}) {
  const result = {
    property: propName,
    type: "key",
    valueType: getValueType(scaleType),
    validation: getValidationFn(scaleType),
    ...opts
  };
  return result;
}
function valueProperty(propName, scaleType, opts = {}) {
  const result = {
    property: propName,
    type: "value",
    valueType: getValueType(scaleType),
    validation: getValidationFn(scaleType),
    ...opts
  };
  return result;
}
function rangedValueProperty(propName, opts = {}) {
  const { min = -Infinity, max = Infinity, ...defOpts } = opts;
  return {
    type: "value",
    property: propName,
    valueType: "range",
    validation: basicContinuousCheckDatumValidation,
    processor: () => (datum) => isFiniteNumber(datum) ? clamp(min, datum, max) : datum,
    ...defOpts
  };
}
function accumulativeValueProperty(propName, scaleType, opts = {}) {
  const { onlyPositive, ...defOpts } = opts;
  const result = {
    ...valueProperty(propName, scaleType, defOpts),
    processor: accumulatedValue(onlyPositive)
  };
  return result;
}
function trailingAccumulatedValueProperty(propName, scaleType, opts = {}) {
  const result = {
    ...valueProperty(propName, scaleType, opts),
    processor: trailingAccumulatedValue()
  };
  return result;
}
function groupAccumulativeValueProperty(propName, mode, sum2, opts, scaleType) {
  return [
    valueProperty(propName, scaleType, opts),
    accumulateGroup(opts.groupId, mode, sum2, opts.separateNegative),
    ...opts.rangeId != null ? [range2(opts.rangeId, opts.groupId)] : []
  ];
}
function groupStackValueProperty(propName, scaleType, opts) {
  return [valueProperty(propName, scaleType, opts), accumulateStack(opts.groupId)];
}
var SMALLEST_KEY_INTERVAL = {
  type: "reducer",
  property: "smallestKeyInterval",
  initialValue: Infinity,
  reducer: () => {
    let prevX = NaN;
    return (smallestSoFar = Infinity, next) => {
      const nextX = next.keys[0];
      const interval = Math.abs(nextX - prevX);
      prevX = nextX;
      if (!isNaN(interval) && interval > 0 && interval < smallestSoFar) {
        return interval;
      }
      return smallestSoFar;
    };
  }
};
var LARGEST_KEY_INTERVAL = {
  type: "reducer",
  property: "largestKeyInterval",
  initialValue: -Infinity,
  reducer: () => {
    let prevX = NaN;
    return (largestSoFar = -Infinity, next) => {
      const nextX = next.keys[0];
      const interval = Math.abs(nextX - prevX);
      prevX = nextX;
      if (!isNaN(interval) && interval > 0 && interval > largestSoFar) {
        return interval;
      }
      return largestSoFar;
    };
  }
};
var SORT_DOMAIN_GROUPS = {
  type: "processor",
  property: "sortedGroupDomain",
  calculate: ({ domain: { groups } }) => groups?.slice().sort((a, b) => {
    for (let i = 0; i < a.length; i++) {
      const result = a[i] - b[i];
      if (result !== 0) {
        return result;
      }
    }
    return 0;
  })
};
function normaliseFnBuilder({ normaliseTo, mode }) {
  const normalise = (val, extent2) => {
    if (extent2 === 0)
      return null;
    const result = (val ?? 0) * normaliseTo / extent2;
    if (result >= 0) {
      return Math.min(normaliseTo, result);
    }
    return Math.max(-normaliseTo, result);
  };
  return () => () => (columns, valueIndexes, datumIndex) => {
    const extent2 = normaliseFindExtent(mode, columns, valueIndexes, datumIndex);
    for (const valueIdx of valueIndexes) {
      const column = columns[valueIdx];
      const value = column[datumIndex];
      if (value == null) {
        column[datumIndex] = void 0;
        continue;
      }
      column[datumIndex] = // eslint-disable-next-line sonarjs/no-nested-functions
      typeof value === "number" ? normalise(value, extent2) : value.map((v) => normalise(v, extent2));
    }
  };
}
function normaliseFindExtent(mode, columns, valueIndexes, datumIndex) {
  const valuesExtent = [0, 0];
  for (const valueIdx of valueIndexes) {
    const column = columns[valueIdx];
    const value = column[datumIndex];
    if (value == null)
      continue;
    const valueExtent = typeof value === "number" ? value : Math.max(...value.map((v) => v ?? 0));
    const valIdx = valueExtent < 0 ? 0 : 1;
    if (mode === "sum") {
      valuesExtent[valIdx] += valueExtent;
    } else if (valIdx === 0) {
      valuesExtent[valIdx] = Math.min(valuesExtent[valIdx], valueExtent);
    } else {
      valuesExtent[valIdx] = Math.max(valuesExtent[valIdx], valueExtent);
    }
  }
  return Math.max(Math.abs(valuesExtent[0]), valuesExtent[1]);
}
function normaliseGroupTo(matchGroupIds, normaliseTo, mode = "sum") {
  return {
    type: "group-value-processor",
    matchGroupIds,
    adjust: memo({ normaliseTo, mode }, normaliseFnBuilder)
  };
}
function normalisePropertyFnBuilder({
  normaliseTo,
  zeroDomain,
  rangeMin,
  rangeMax
}) {
  const normaliseSpan = normaliseTo[1] - normaliseTo[0];
  const normalise = (val, start2, span) => {
    const result = normaliseTo[0] + (val - start2) / span * normaliseSpan;
    if (span === 0) {
      return zeroDomain;
    } else if (result >= normaliseTo[1]) {
      return normaliseTo[1];
    } else if (result < normaliseTo[0]) {
      return normaliseTo[0];
    }
    return result;
  };
  return () => (pData, pIdx) => {
    let [start2, end2] = pData.domain.values[pIdx];
    if (rangeMin != null)
      start2 = rangeMin;
    if (rangeMax != null)
      end2 = rangeMax;
    const span = end2 - start2;
    pData.domain.values[pIdx] = [normaliseTo[0], normaliseTo[1]];
    const { rawData } = pData;
    const column = pData.columns[pIdx];
    for (let datumIndex = 0; datumIndex < rawData.length; datumIndex += 1) {
      column[datumIndex] = normalise(column[datumIndex], start2, span);
    }
  };
}
function normalisePropertyTo(property, normaliseTo, zeroDomain, rangeMin, rangeMax) {
  return {
    type: "property-value-processor",
    property,
    adjust: memo({ normaliseTo, rangeMin, rangeMax, zeroDomain }, normalisePropertyFnBuilder)
  };
}
var ANIMATION_VALIDATION_UNIQUE_KEYS = 1;
var ANIMATION_VALIDATION_ORDERED_KEYS = 2;
var animationValidationProcessKey = (count, def, keyValues, column) => {
  let validation = ANIMATION_VALIDATION_UNIQUE_KEYS | ANIMATION_VALIDATION_ORDERED_KEYS;
  if (def.valueType === "category") {
    if (keyValues.length !== count)
      validation &= ~ANIMATION_VALIDATION_UNIQUE_KEYS;
    return validation;
  }
  let lastValue = column[0]?.valueOf();
  for (let d = 1; validation !== 0 && d < column.length; d++) {
    const keyValue = column[d]?.valueOf();
    if (!Number.isFinite(keyValue) || lastValue > keyValue)
      validation &= ~ANIMATION_VALIDATION_ORDERED_KEYS;
    if (Number.isFinite(keyValue) && lastValue === keyValue)
      validation &= ~ANIMATION_VALIDATION_UNIQUE_KEYS;
    lastValue = keyValue;
  }
  return validation;
};
function animationValidation(valueKeyIds) {
  return {
    type: "processor",
    property: "animationValidation",
    calculate(result) {
      const { keys: keysDefs, values: valuesDef } = result.defs;
      const {
        input: { count },
        domain: { keys: domainKeys, values: domainValues },
        rawData,
        keys,
        columns
      } = result;
      let validation = ANIMATION_VALIDATION_UNIQUE_KEYS | ANIMATION_VALIDATION_ORDERED_KEYS;
      if (rawData.length !== 0) {
        for (let i = 0; validation !== 0 && i < keysDefs.length; i++) {
          validation &= animationValidationProcessKey(count, keysDefs[i], domainKeys[i], keys[i]);
        }
        for (let i = 0; validation !== 0 && i < valuesDef.length; i++) {
          const value = valuesDef[i];
          if (!valueKeyIds?.includes(value.id) === true)
            continue;
          validation &= animationValidationProcessKey(count, value, domainValues[i], columns[i]);
        }
      }
      return {
        uniqueKeys: (validation & ANIMATION_VALIDATION_UNIQUE_KEYS) !== 0,
        orderedKeys: (validation & ANIMATION_VALIDATION_ORDERED_KEYS) !== 0
      };
    }
  };
}
function buildGroupAccFn({ mode, separateNegative }) {
  return () => () => (columns, valueIndexes, datumIndex) => {
    const acc = [0, 0];
    for (const valueIdx of valueIndexes) {
      const column = columns[valueIdx];
      const currentVal = column[datumIndex];
      const accIndex = isNegative(currentVal) && separateNegative ? 0 : 1;
      if (!isFiniteNumber(currentVal))
        continue;
      if (mode === "normal")
        acc[accIndex] += currentVal;
      column[datumIndex] = acc[accIndex];
      if (mode === "trailing")
        acc[accIndex] += currentVal;
    }
  };
}
function buildGroupWindowAccFn({ mode, sum: sum2 }) {
  return () => {
    const lastValues = [];
    let firstRow = true;
    return () => {
      return (columns, valueIndexes, datumIndex) => {
        let acc = 0;
        for (const valueIdx of valueIndexes) {
          const column = columns[valueIdx];
          const currentVal = column[datumIndex];
          const lastValue = firstRow && sum2 === "current" ? 0 : lastValues[valueIdx];
          lastValues[valueIdx] = currentVal;
          const sumValue = sum2 === "current" ? currentVal : lastValue;
          if (!isFiniteNumber(currentVal) || !isFiniteNumber(lastValue)) {
            column[datumIndex] = acc;
            continue;
          }
          if (mode === "normal") {
            acc += sumValue;
          }
          column[datumIndex] = acc;
          if (mode === "trailing") {
            acc += sumValue;
          }
        }
        firstRow = false;
      };
    };
  };
}
function accumulateGroup(matchGroupId, mode, sum2, separateNegative = false) {
  let adjust;
  if (mode.startsWith("window")) {
    const modeParam = mode.endsWith("-trailing") ? "trailing" : "normal";
    adjust = memo({ mode: modeParam, sum: sum2 }, buildGroupWindowAccFn);
  } else {
    adjust = memo({ mode, separateNegative }, buildGroupAccFn);
  }
  return {
    type: "group-value-processor",
    matchGroupIds: [matchGroupId],
    adjust
  };
}
function groupStackAccFn() {
  return () => (columns, valueIndexes, datumIndex) => {
    const acc = new Float64Array(32);
    let stackCount = 0;
    for (const valueIdx of valueIndexes) {
      const column = columns[valueIdx];
      const currentValue = column[datumIndex];
      acc[stackCount] = Number.isFinite(currentValue) ? currentValue : NaN;
      stackCount += 1;
      column[datumIndex] = acc.subarray(0, stackCount);
    }
  };
}
function accumulateStack(matchGroupId) {
  return {
    type: "group-value-processor",
    matchGroupIds: [matchGroupId],
    adjust: groupStackAccFn
  };
}
function valueIdentifier(value) {
  return value.id ?? value.property;
}
function valueIndices(id, previousData, processedData) {
  const properties = /* @__PURE__ */ new Map();
  const previousValues = previousData.defs.values;
  for (let previousIndex = 0; previousIndex < previousValues.length; previousIndex += 1) {
    const previousValue = previousValues[previousIndex];
    if (previousValue.scopes?.includes(id) === false)
      continue;
    const valueId = valueIdentifier(previousValue);
    if (properties.has(valueId))
      return;
    properties.set(valueId, previousIndex);
  }
  const indices = [];
  const nextValues = processedData.defs.values;
  for (let nextIndex = 0; nextIndex < nextValues.length; nextIndex += 1) {
    const nextValue = nextValues[nextIndex];
    if (nextValue.scopes?.includes(id) === false)
      continue;
    const valueId = valueIdentifier(nextValue);
    const previousIndex = properties.get(valueId);
    if (previousIndex == null)
      return;
    properties.delete(valueId);
    indices.push({ previousIndex, nextIndex });
  }
  if (properties.size !== 0)
    return;
  return indices;
}
function columnsEqual(previousColumns, nextColumns, indices, previousDatumIndex, nextDatumIndex) {
  for (const { previousIndex, nextIndex } of indices) {
    const previousColumn = previousColumns[previousIndex];
    const nextColumn = nextColumns[nextIndex];
    const previousValue = previousColumn[previousDatumIndex];
    const nextValue = nextColumn[nextDatumIndex];
    if (previousValue !== nextValue) {
      return false;
    }
  }
  return true;
}
function diff(id, previousData, updateMovedData = true) {
  return {
    type: "processor",
    property: "diff",
    calculate(processedData, previousValue) {
      const moved = /* @__PURE__ */ new Map();
      const added = /* @__PURE__ */ new Map();
      const updated = /* @__PURE__ */ new Map();
      const removed = /* @__PURE__ */ new Map();
      const previousKeys = previousData.keys;
      const keys = processedData.keys;
      const previousColumns = previousData.columns;
      const columns = processedData.columns;
      const indices = valueIndices(id, previousData, processedData);
      if (indices == null)
        return previousValue;
      const length2 = Math.max(previousData.rawData.length, processedData.rawData.length);
      for (let i = 0; i < length2; i++) {
        const hasPreviousDatum = i < previousData.rawData.length;
        const hasDatum = i < processedData.rawData.length;
        const prevKeys = hasPreviousDatum ? datumKeys(previousKeys, i) : void 0;
        const prevId = prevKeys != null ? createDatumId(prevKeys) : "";
        const dKeys = hasDatum ? datumKeys(keys, i) : void 0;
        const datumId = dKeys != null ? createDatumId(dKeys) : "";
        if (hasDatum && hasPreviousDatum && prevId === datumId) {
          if (!columnsEqual(previousColumns, columns, indices, i, i)) {
            updated.set(datumId, i);
          }
          continue;
        }
        const removedIndex = removed.get(datumId);
        if (removedIndex != null) {
          if (updateMovedData || !columnsEqual(previousColumns, columns, indices, removedIndex, i)) {
            updated.set(datumId, i);
            moved.set(datumId, i);
          }
          removed.delete(datumId);
        } else if (hasDatum) {
          added.set(datumId, i);
        }
        const addedIndex = added.get(prevId);
        if (addedIndex != null) {
          if (updateMovedData || !columnsEqual(previousColumns, columns, indices, addedIndex, i)) {
            updated.set(prevId, i);
            moved.set(prevId, i);
          }
          added.delete(prevId);
        } else if (hasPreviousDatum) {
          updated.delete(prevId);
          removed.set(prevId, i);
        }
      }
      const changed = added.size > 0 || updated.size > 0 || removed.size > 0;
      const value = {
        changed,
        added: new Set(added.keys()),
        updated: new Set(updated.keys()),
        removed: new Set(removed.keys()),
        moved: new Set(moved.keys())
      };
      return {
        ...previousValue,
        [id]: value
      };
    }
  };
}
function createDatumId(keys, ...extraKeys) {
  let result;
  if (isArray(keys)) {
    result = keys.map((key) => transformIntegratedCategoryValue(key)).join("___");
  } else {
    result = transformIntegratedCategoryValue(keys);
  }
  const primitiveType = typeof result === "string" || typeof result === "number" || typeof result === "boolean" || result instanceof Date;
  if (primitiveType && extraKeys.length > 0) {
    result += `___${extraKeys.join("___")}`;
  }
  return result;
}
var Dimensions = class {
  constructor() {
    this.top = Infinity;
    this.right = -Infinity;
    this.bottom = -Infinity;
    this.left = Infinity;
  }
  update(x, y) {
    if (x > this.right) {
      this.right = x;
    }
    if (x < this.left) {
      this.left = x;
    }
    if (y > this.bottom) {
      this.bottom = y;
    }
    if (y < this.top) {
      this.top = y;
    }
  }
};
var TreeNode = class _TreeNode {
  constructor(label = "", parent, refId) {
    this.label = label;
    this.parent = parent;
    this.refId = refId;
    this.x = 0;
    this.y = 0;
    this.subtreeLeft = NaN;
    this.subtreeRight = NaN;
    this.children = [];
    this.leafCount = 0;
    this.prelim = 0;
    this.mod = 0;
    this.ancestor = this;
    this.change = 0;
    this.shift = 0;
    this.index = 0;
    this.screenX = 0;
    this.screenY = 0;
    this.depth = parent ? parent.depth + 1 : 0;
  }
  insertTick(tick, index) {
    let root = this;
    for (let i = 0; i < tick.length; i++) {
      const pathPart = tick[i];
      const isNotLeaf = i !== tick.length - 1;
      const { children } = root;
      const existingNode = children.find((child) => child.label === pathPart);
      if (existingNode && isNotLeaf) {
        root = existingNode;
      } else {
        const node = new _TreeNode(pathPart, root, index);
        node.index = children.length;
        children.push(node);
        if (isNotLeaf) {
          root = node;
        }
      }
    }
  }
  getLeftSibling() {
    return this.index > 0 ? this.parent?.children[this.index - 1] : void 0;
  }
  getLeftmostSibling() {
    return this.index > 0 ? this.parent?.children[0] : void 0;
  }
  // traverse the left contour of a subtree, return the successor of v on this contour
  nextLeft() {
    return this.children[0];
  }
  // traverse the right contour of a subtree, return the successor of v on this contour
  nextRight() {
    return this.children.at(-1);
  }
  getSiblings() {
    return this.parent?.children.filter((_, i) => i !== this.index) ?? [];
  }
};
function ticksToTree(ticks) {
  const maxDepth = ticks.reduce((depth, tick) => depth < tick.length ? tick.length : depth, 0);
  const root = new TreeNode();
  for (let i = 0; i < ticks.length; i++) {
    const tick = ticks[i];
    while (tick.length < maxDepth) {
      tick.push("");
    }
    root.insertTick(tick, i);
  }
  return root;
}
function moveSubtree(wm, wp, shift) {
  const subtrees = wp.index - wm.index;
  const ratio2 = shift / subtrees;
  wp.change -= ratio2;
  wp.shift += shift;
  wm.change += ratio2;
  wp.prelim += shift;
  wp.mod += shift;
}
function ancestor(vim, v, defaultAncestor) {
  return v.getSiblings().indexOf(vim.ancestor) >= 0 ? vim.ancestor : defaultAncestor;
}
function executeShifts({ children }) {
  let shift = 0;
  let change = 0;
  for (let i = children.length - 1; i >= 0; i--) {
    const w = children[i];
    w.prelim += shift;
    w.mod += shift;
    change += w.change;
    shift += w.shift + change;
  }
}
function apportion(v, defaultAncestor) {
  const w = v.getLeftSibling();
  if (w) {
    let vop = v;
    let vip = v;
    let vim = w;
    let vom = vip.getLeftmostSibling();
    let sip = vip.mod;
    let sop = vop.mod;
    let sim = vim.mod;
    let som = vom.mod;
    while (vim.nextRight() && vip.nextLeft()) {
      vim = vim.nextRight();
      vip = vip.nextLeft();
      vom = vom.nextLeft();
      vop = vop.nextRight();
      vop.ancestor = v;
      const shift = vim.prelim + sim - (vip.prelim + sip) + 1;
      if (shift > 0) {
        moveSubtree(ancestor(vim, v, defaultAncestor), v, shift);
        sip += shift;
        sop += shift;
      }
      sim += vim.mod;
      sip += vip.mod;
      som += vom.mod;
      sop += vop.mod;
    }
    if (vim.nextRight() && !vop.nextRight()) {
      vop.mod += sim - sop;
    } else {
      if (vip.nextLeft() && !vom.nextLeft()) {
        vom.mod += sip - som;
      }
      defaultAncestor = v;
    }
  }
  return defaultAncestor;
}
function firstWalk(node) {
  const { children } = node;
  if (children.length) {
    let [defaultAncestor] = children;
    for (const child of children) {
      firstWalk(child);
      defaultAncestor = apportion(child, defaultAncestor);
    }
    executeShifts(node);
    const midpoint = (children[0].prelim + children.at(-1).prelim) / 2;
    const leftSibling = node.getLeftSibling();
    if (leftSibling) {
      node.prelim = leftSibling.prelim + 1;
      node.mod = node.prelim - midpoint;
    } else {
      node.prelim = midpoint;
    }
  } else {
    const leftSibling = node.getLeftSibling();
    node.prelim = leftSibling ? leftSibling.prelim + 1 : 0;
  }
}
function secondWalk(v, m, layout) {
  v.x = v.prelim + m;
  v.y = v.depth;
  layout.insertNode(v);
  for (const w of v.children) {
    secondWalk(w, m + v.mod, layout);
  }
}
function thirdWalk(v) {
  const { children } = v;
  let leafCount = 0;
  for (const w of children) {
    thirdWalk(w);
    if (w.children.length) {
      leafCount += w.leafCount;
    } else {
      leafCount++;
    }
  }
  v.leafCount = leafCount;
  if (children.length) {
    v.subtreeLeft = children[0].subtreeLeft;
    v.subtreeRight = children[children.length - 1].subtreeRight;
    v.x = (v.subtreeLeft + v.subtreeRight) / 2;
  } else {
    v.subtreeLeft = v.x;
    v.subtreeRight = v.x;
  }
}
function treeLayout(ticks) {
  const layout = new TreeLayout();
  const root = ticksToTree(ticks);
  firstWalk(root);
  secondWalk(root, -root.prelim, layout);
  thirdWalk(root);
  return layout;
}
var TreeLayout = class {
  constructor() {
    this.dimensions = new Dimensions();
    this.nodes = [];
    this.depth = 0;
  }
  insertNode(node) {
    if (this.depth < node.depth) {
      this.depth = node.depth;
    }
    this.dimensions.update(node.x, node.y);
    this.nodes.push(node);
  }
  scalingX(width2, flip) {
    let scalingX = 1;
    if (width2 > 0) {
      const { left, right } = this.dimensions;
      scalingX = width2 / (right - left);
    }
    if (flip) {
      scalingX *= -1;
    }
    return scalingX;
  }
  scalingY(height2, flip) {
    let scalingY = 1;
    if (height2 > 0) {
      const { top, bottom } = this.dimensions;
      scalingY = height2 / (bottom - top);
    }
    if (flip) {
      scalingY *= -1;
    }
    return scalingY;
  }
};
var DepthLabelProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], DepthLabelProperties.prototype, "enabled", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], DepthLabelProperties.prototype, "avoidCollisions", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], DepthLabelProperties.prototype, "color", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], DepthLabelProperties.prototype, "spacing", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], DepthLabelProperties.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], DepthLabelProperties.prototype, "fontWeight", 2);
__decorateClass([
  Validate(NUMBER.restrict({ min: 1 }), { optional: true })
], DepthLabelProperties.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DepthLabelProperties.prototype, "fontFamily", 2);
var DepthTickProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], DepthTickProperties.prototype, "enabled", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], DepthTickProperties.prototype, "width", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], DepthTickProperties.prototype, "stroke", 2);
var DepthProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.label = new DepthLabelProperties();
    this.tick = new DepthTickProperties();
  }
};
__decorateClass([
  Validate(OBJECT)
], DepthProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], DepthProperties.prototype, "tick", 2);
var GroupedCategoryAxis = class extends CategoryAxis {
  constructor(moduleCtx) {
    super(moduleCtx);
    this.tickScale = new BandScale();
    this.depthOptions = new PropertiesArray(DepthProperties);
    this.includeInvisibleDomains = true;
    this.tickScale.paddingInner = 1;
    this.tickScale.paddingOuter = 0;
  }
  resizeTickTree() {
    if (!this.tickTreeLayout)
      return;
    const { nodes } = this.tickTreeLayout;
    const { range: range3, step, inset, bandwidth } = this.scale;
    const width2 = Math.abs(range3[1] - range3[0]) - step;
    const scalingX = this.tickTreeLayout.scalingX(width2, range3[0] > range3[1]);
    const shiftX = inset + bandwidth / 2;
    let offsetX = 0;
    for (const node of nodes) {
      const screenX = node.x * scalingX;
      if (offsetX > screenX) {
        offsetX = screenX;
      }
      node.screenX = screenX + shiftX;
    }
    for (const node of nodes) {
      node.screenX -= offsetX;
    }
  }
  getDepthOptionsMap(maxDepth) {
    const optionsMap = [];
    const { depthOptions, label } = this;
    for (let i = 0; i < maxDepth; i++) {
      optionsMap.push(
        depthOptions[i]?.label.enabled ?? label.enabled ? {
          enabled: true,
          spacing: depthOptions[i]?.label.spacing ?? label.spacing,
          lineHeight: TextUtils.getLineHeight(depthOptions[i]?.label.fontSize ?? label.fontSize ?? 10),
          avoidCollisions: depthOptions[i]?.label.avoidCollisions ?? label.avoidCollisions
        } : { enabled: false, spacing: 0, lineHeight: 0, avoidCollisions: false }
      );
    }
    return optionsMap;
  }
  updateCategoryLabels() {
    if (!this.computedLayout)
      return;
    this.tickLabelGroupSelection.update(this.computedLayout.tickLabelLayout).each((node, datum) => node.setProperties(datum));
  }
  updateAxisLine() {
    if (!this.computedLayout)
      return;
    this.lineNode.visible = this.line.enabled;
    this.lineNode.stroke = this.line.stroke;
    this.lineNode.strokeWidth = this.line.width;
  }
  computeLayout() {
    this.updateDirection();
    this.updateScale();
    this.updateRange();
    this.resizeTickTree();
    if (!this.tickTreeLayout?.depth) {
      return { bbox: BBox.zero, separatorLayout: [], tickLabelLayout: [] };
    }
    const { step } = this.scale;
    const { title, label, range: range3, depthOptions } = this;
    const { depth: maxDepth, nodes: treeLabels } = this.tickTreeLayout;
    const keepEvery = Math.ceil(label.fontSize / step);
    const rotation = toRadians(this.rotation);
    const isHorizontal = this.position === "top" || this.position === "bottom";
    const sideFlag = label.getSideFlag();
    const tickLabelLayout = [];
    const labelBBoxes = /* @__PURE__ */ new Map();
    const tempText = new TransformableText();
    const { defaultRotation, configuredRotation } = calculateLabelRotation({
      rotation: label.rotation,
      parallel: label.parallel,
      regularFlipRotation: normalizeAngle360(rotation - Math.PI / 2),
      parallelFlipRotation: normalizeAngle360(rotation)
    });
    const labelRotation = defaultRotation + configuredRotation;
    const optionsMap = this.getDepthOptionsMap(maxDepth);
    const setLabelProps = (datum, index) => {
      const depth = maxDepth - datum.depth;
      if (!optionsMap[depth]?.enabled || index % keepEvery !== 0 || !inRange(datum.screenX, range3)) {
        return false;
      }
      const text = this.formatTick(datum.label, index - 1);
      const labelStyles = this.getLabelStyles({ value: text, depth }, depthOptions[depth]?.label);
      tempText.setProperties({
        ...labelStyles,
        text,
        textAlign: "center",
        textBaseline: label.parallel ? "hanging" : "bottom",
        rotation: 0,
        translationX: 0,
        translationY: datum.screenX
      });
      return true;
    };
    let maxLeafLabelWidth = 0;
    const depthLines = {};
    treeLabels.forEach((datum, index) => {
      const depth = maxDepth - datum.depth;
      const nodeLines = countLines(datum.label);
      depthLines[depth] ?? (depthLines[depth] = 1);
      if (depthLines[depth] < nodeLines) {
        depthLines[depth] = nodeLines;
      }
      const isVisible = setLabelProps(datum, index);
      if (!isVisible || !tempText.getBBox())
        return;
      labelBBoxes.set(index, tempText.getBBox());
      if (!datum.leafCount) {
        tempText.rotation = labelRotation;
        const { width: width3 } = tempText.getBBox();
        if (maxLeafLabelWidth < width3) {
          maxLeafLabelWidth = width3;
        }
      }
    });
    const idGenerator = createIdsGenerator();
    const labelX = sideFlag * optionsMap[0].spacing;
    const separatorData = /* @__PURE__ */ new Map();
    const nestedPadding = (d) => {
      let v = maxLeafLabelWidth;
      for (let i = 1; i <= d; i++) {
        v += optionsMap[i].spacing;
        if (label.mirrored || i !== d) {
          v += depthLines[i] * optionsMap[i].lineHeight;
        }
      }
      return v;
    };
    treeLabels.forEach((datum, index) => {
      if (index === 0)
        return;
      const visible = setLabelProps(datum, index);
      const isLeaf = !datum.children.length;
      const depth = maxDepth - datum.depth;
      if (datum.parent) {
        const separatorX = isLeaf ? datum.x : datum.x - (datum.leafCount - 1) / 2;
        if (!separatorData.has(separatorX)) {
          const tickOptions = this.depthOptions[depth]?.tick;
          let v = maxLeafLabelWidth;
          for (let i = 0; i <= depth; i++) {
            v += optionsMap[i].spacing;
            if (i !== 0) {
              v += depthLines[i] * optionsMap[i].lineHeight;
            }
          }
          separatorData.set(separatorX, {
            tickSize: v,
            tickStroke: tickOptions?.stroke,
            tickWidth: tickOptions?.enabled !== false ? tickOptions?.width : 0
          });
        }
      }
      if (!visible)
        return;
      tempText.x = labelX;
      tempText.y = 0;
      if (isLeaf) {
        const { width: width3 } = labelBBoxes.get(index);
        const angleRatio = getAngleRatioRadians(labelRotation);
        tempText.rotation = labelRotation;
        tempText.textAlign = "end";
        tempText.textBaseline = "middle";
        tempText.rotationCenterX = labelX - width3 / 2;
        tempText.translationX = (optionsMap[depth].spacing - width3) / 2 * angleRatio * sideFlag;
        if (label.mirrored) {
          tempText.translationX += width3;
        }
      } else {
        tempText.rotation = isHorizontal ? defaultRotation : -Math.PI / 2;
        tempText.rotationCenterX = labelX;
        tempText.translationX = sideFlag * nestedPadding(depth);
      }
      if (optionsMap[depth].avoidCollisions) {
        const availableRange = isLeaf ? step : datum.leafCount * step;
        if (tempText.getBBox().height > availableRange) {
          labelBBoxes.delete(index);
          return;
        }
      }
      const { text = "" } = tempText;
      tickLabelLayout.push({
        text,
        visible: true,
        range: this.scale.range,
        tickId: idGenerator(text),
        fill: tempText.fill,
        fontFamily: tempText.fontFamily,
        fontSize: tempText.fontSize,
        fontStyle: tempText.fontStyle,
        fontWeight: tempText.fontWeight,
        rotation: tempText.rotation,
        rotationCenterX: tempText.rotationCenterX,
        textAlign: tempText.textAlign,
        textBaseline: tempText.textBaseline,
        translationX: tempText.translationX,
        translationY: tempText.translationY,
        x: tempText.x,
        y: tempText.y
      });
      labelBBoxes.set(index, Transformable.toCanvas(tempText));
    });
    const { enabled, stroke, width: width2 } = this.line;
    this.lineNode.datum = { x: 0, y1: range3[0], y2: range3[1] };
    this.lineNode.setProperties({ stroke, strokeWidth: enabled ? width2 : 0 });
    const separatorLayout = [...separatorData.values()];
    separatorLayout.push(separatorLayout[0]);
    const axisBoxes = [this.lineNode.getBBox(), new BBox(0, 0, separatorLayout[0].tickSize * sideFlag, 0)];
    if (title.enabled) {
      this.updateTitle(false, separatorLayout[0].tickSize);
      axisBoxes.push(title.caption.node.getBBox());
    }
    const mergedBBox = BBox.merge(iterate(labelBBoxes.values(), axisBoxes));
    return {
      bbox: this.getTransformBox(mergedBBox),
      separatorLayout,
      tickLabelLayout
    };
  }
  /**
   * Creates/removes/updates the scene graph nodes that constitute the axis.
   * Supposed to be called _manually_ after changing _any_ of the axis properties.
   * This allows to bulk set axis properties before updating the nodes.
   * The node changes made by this method are rendered on the next animation frame.
   * We could schedule this method call automatically on the next animation frame
   * when any of the axis properties change (the way we do when properties of scene graph's
   * nodes change), but this will mean that we first wait for the next animation
   * frame to make changes to the nodes of the axis, then wait for another animation
   * frame to render those changes. It's nice to have everything update automatically,
   * but this extra level of async indirection will not just introduce an unwanted delay,
   * it will also make it harder to reason about the program.
   */
  update() {
    if (!this.computedLayout)
      return;
    const { tickScale, gridLine, gridLength } = this;
    const { separatorLayout } = this.computedLayout;
    const ticksData = tickScale.ticks().map((tick, index) => ({
      ...separatorLayout[index],
      tick,
      tickId: createDatumId(tick, index),
      tickLabel: tick.filter(Boolean).join(" - "),
      translationY: Math.round(tickScale.convert(tick))
    }));
    this.gridLineGroupSelection.update(gridLine.enabled && gridLength ? ticksData : []);
    this.tickLineGroupSelection.update(this.tick.enabled ? ticksData : []);
    this.updatePosition();
    this.updateCategoryLabels();
    this.updateAxisLine();
    this.updateGridLines();
    this.updateTickLines();
    this.updateTitle();
    this.resetSelectionNodes();
  }
  calculateLayout() {
    const { separatorLayout, tickLabelLayout, bbox } = this.computeLayout();
    this.computedLayout = { separatorLayout, tickLabelLayout };
    return { bbox, primaryTickCount: void 0 };
  }
  /**
   * The length of the grid. The grid is only visible in case of a non-zero value.
   */
  onGridVisibilityChange() {
    this.gridLineGroupSelection.clear();
    this.tickLabelGroupSelection.clear();
  }
  updateRange() {
    super.updateRange();
    this.tickScale.range = this.scale.range;
  }
  calculateDomain() {
    const { direction } = this;
    const flatDomains = this.boundSeries.filter((s) => s.visible).flatMap((series) => series.getDomain(direction));
    this.setDomain(extent(flatDomains) ?? unique(flatDomains));
    const domain = this.dataDomain.domain.map(toArray);
    this.tickTreeLayout = treeLayout(domain);
    const orderedDomain = [];
    for (const node of this.tickTreeLayout.nodes) {
      if (node.leafCount || node.refId == null)
        continue;
      orderedDomain.push(this.dataDomain.domain[node.refId]);
    }
    this.scale.domain = sortBasedOnArray(this.dataDomain.domain, orderedDomain);
    this.tickScale.domain = domain.concat([[""]]);
  }
  updateGridLines() {
    if (!this.gridLength)
      return;
    const { width: width2, style } = this.gridLine;
    const lineSize = this.gridLength * -this.label.getSideFlag();
    this.gridLineGroupSelection.each((line, datum, index) => {
      const { stroke, lineDash } = style[index % style.length];
      const y = datum.translationY;
      line.visible = this.inRange(y);
      line.x1 = 0;
      line.x2 = lineSize;
      line.y = y;
      line.stroke = stroke;
      line.strokeWidth = width2;
      line.lineDash = lineDash;
    });
  }
  updateScale(opts) {
    super.updateScale(opts);
    this.scale.paddingOuter = this.scale.paddingInner / 2;
  }
};
GroupedCategoryAxis.className = "GroupedCategoryAxis";
GroupedCategoryAxis.type = "grouped-category";
__decorateClass([
  Validate(OBJECT_ARRAY)
], GroupedCategoryAxis.prototype, "depthOptions", 2);
function calculateNiceSecondaryAxis(domain, primaryTickCount, reverse) {
  let [start2, stop] = findMinMax(domain);
  start2 = calculateNiceStart(Math.floor(start2), stop, primaryTickCount);
  const step = getTickStep(start2, stop, primaryTickCount);
  const segments = primaryTickCount - 1;
  stop = start2 + segments * step;
  const d = reverse ? [stop, start2] : [start2, stop];
  const ticks = getTicks(start2, step, primaryTickCount);
  return { domain: d, ticks };
}
function calculateNiceStart(a, b, count) {
  const rawStep = Math.abs(b - a) / (count - 1);
  const order = Math.floor(Math.log10(rawStep));
  const magnitude = Math.pow(10, order);
  return Math.floor(a / magnitude) * magnitude;
}
function getTicks(start2, step, count) {
  const stepPower = Math.floor(Math.log10(step));
  const fractionDigits = step > 0 && step < 1 ? Math.abs(stepPower) : 0;
  const f = Math.pow(10, fractionDigits);
  const ticks = [];
  for (let i = 0; i < count; i++) {
    const tick = start2 + step * i;
    ticks[i] = Math.round(tick * f) / f;
  }
  return ticks;
}
function getTickStep(start2, stop, count) {
  const segments = count - 1;
  const rawStep = (stop - start2) / segments;
  return calculateNextNiceStep(rawStep);
}
function calculateNextNiceStep(rawStep) {
  const order = Math.floor(Math.log10(rawStep));
  const magnitude = Math.pow(10, order);
  const step = rawStep / magnitude * 10;
  if (step > 0 && step <= 1) {
    return magnitude / 10;
  }
  if (step > 1 && step <= 2) {
    return 2 * magnitude / 10;
  }
  if (step > 1 && step <= 5) {
    return 5 * magnitude / 10;
  }
  if (step > 5 && step <= 10) {
    return 10 * magnitude / 10;
  }
  if (step > 10 && step <= 20) {
    return 20 * magnitude / 10;
  }
  if (step > 20 && step <= 40) {
    return 40 * magnitude / 10;
  }
  if (step > 40 && step <= 50) {
    return 50 * magnitude / 10;
  }
  if (step > 50 && step <= 100) {
    return 100 * magnitude / 10;
  }
  return step;
}
var LinearScale = class extends ContinuousScale {
  constructor() {
    super([0, 1], [0, 1]);
    this.type = "number";
  }
  toDomain(d) {
    return d;
  }
  ticks() {
    const count = this.tickCount ?? ContinuousScale.defaultTickCount;
    if (!this.domain || this.domain.length < 2 || count < 1 || !this.domain.every(isFinite)) {
      return [];
    }
    this.refresh();
    const [d0, d1] = this.getDomain();
    if (this.interval) {
      const step = Math.abs(this.interval);
      if (!isDenseInterval((d1 - d0) / step, this.getPixelRange())) {
        return range(d0, d1, step);
      }
    }
    return createTicks(d0, d1, count, this.minTickCount, this.maxTickCount);
  }
  update() {
    if (!this.domain || this.domain.length < 2) {
      return;
    }
    if (this.nice) {
      this.updateNiceDomain();
    }
  }
  getTickStep(start2, stop) {
    return this.interval ?? tickStep(start2, stop, this.tickCount, this.minTickCount, this.maxTickCount);
  }
  /**
   * Extends the domain so that it starts and ends on nice round values.
   */
  updateNiceDomain() {
    const count = this.tickCount;
    let [start2, stop] = this.domain;
    if (count === 1) {
      [start2, stop] = niceTicksDomain(start2, stop);
    } else if (count > 1) {
      const roundStart = start2 > stop ? Math.ceil : Math.floor;
      const roundStop = start2 > stop ? Math.floor : Math.ceil;
      const maxAttempts = 4;
      for (let i = 0; i < maxAttempts; i++) {
        const prev0 = start2;
        const prev1 = stop;
        const step = this.getTickStep(start2, stop);
        const [d0, d1] = this.domain;
        start2 = roundStart(d0 / step) * step;
        stop = roundStop(d1 / step) * step;
        if (start2 === prev0 && stop === prev1)
          break;
      }
    }
    this.niceDomain = [start2, stop];
  }
  tickFormat({ ticks: specifiedTicks, specifier }) {
    return tickFormat(specifiedTicks ?? this.ticks(), specifier);
  }
};
var NumberAxis = class extends CartesianAxis {
  constructor(moduleCtx, scale2 = new LinearScale()) {
    super(moduleCtx, scale2);
    this.min = NaN;
    this.max = NaN;
  }
  normaliseDataDomain(d) {
    const { min, max } = this;
    const { extent: extent2, clipped } = normalisedExtentWithMetadata(d, min, max);
    return { domain: extent2, clipped };
  }
  updateSecondaryAxisTicks(primaryTickCount) {
    if (!this.dataDomain?.domain.length) {
      return [];
    }
    const { domain, ticks } = calculateNiceSecondaryAxis(
      this.dataDomain.domain,
      primaryTickCount ?? 0,
      this.reverse
    );
    this.scale.nice = false;
    this.scale.domain = domain;
    this.scale.update();
    return ticks;
  }
};
NumberAxis.className = "NumberAxis";
NumberAxis.type = "number";
__decorateClass([
  Validate(AND(NUMBER_OR_NAN, LESS_THAN("max"))),
  Default(NaN)
], NumberAxis.prototype, "min", 2);
__decorateClass([
  Validate(AND(NUMBER_OR_NAN, GREATER_THAN("min"))),
  Default(NaN)
], NumberAxis.prototype, "max", 2);
var NON_ZERO_NUMBER = predicateWithMessage((value) => isNumber(value) && value !== 0, "a non-zero number");
var LogAxis = class extends NumberAxis {
  constructor(moduleCtx) {
    super(moduleCtx, new LogScale());
    this.min = NaN;
    this.max = NaN;
  }
  normaliseDataDomain(d) {
    const { min, max } = this;
    const { extent: extent2, clipped } = normalisedExtentWithMetadata(d, min, max);
    if (extent2[0] < 0 && extent2[1] > 0) {
      Logger.warn(
        `The log axis domain crosses zero, the chart data cannot be rendered. See log axis documentation for more information.`
      );
      return { domain: [], clipped };
    } else if (extent2[0] === 0 || extent2[1] === 0) {
      Logger.warn(
        `The log axis domain contains a value of 0, the chart data cannot be rendered. See log axis documentation for more information.`
      );
      return { domain: [], clipped };
    }
    return { domain: extent2, clipped };
  }
  set base(value) {
    this.scale.base = value;
  }
  get base() {
    return this.scale.base;
  }
  updateSecondaryAxisTicks(primaryTickCount) {
    if (!this.dataDomain?.domain.length) {
      return [];
    }
    const { domain, ticks } = calculateNiceSecondaryAxis(
      this.dataDomain.domain,
      primaryTickCount ?? 0,
      this.reverse
    );
    this.scale.nice = false;
    this.scale.domain = domain;
    this.scale.update();
    return ticks;
  }
};
LogAxis.className = "LogAxis";
LogAxis.type = "log";
__decorateClass([
  Validate(AND(NUMBER_OR_NAN, NON_ZERO_NUMBER, LESS_THAN("max"))),
  Default(NaN)
], LogAxis.prototype, "min", 2);
__decorateClass([
  Validate(AND(NUMBER_OR_NAN, NON_ZERO_NUMBER, GREATER_THAN("min"))),
  Default(NaN)
], LogAxis.prototype, "max", 2);
var TimeAxis = class extends CartesianAxis {
  constructor(moduleCtx) {
    super(moduleCtx, new TimeScale());
    this.min = void 0;
    this.max = void 0;
  }
  normaliseDataDomain(d) {
    let { min, max } = this;
    let clipped = false;
    if (typeof min === "number") {
      min = new Date(min);
    }
    if (typeof max === "number") {
      max = new Date(max);
    }
    if (d.length > 2) {
      d = extent(d)?.map((x) => new Date(x)) ?? [];
    }
    if (min instanceof Date) {
      clipped || (clipped = min > d[0]);
      d = [min, d[1]];
    }
    if (max instanceof Date) {
      clipped || (clipped = max < d[1]);
      d = [d[0], max];
    }
    if (d[0] > d[1]) {
      d = [];
    }
    return { domain: d, clipped };
  }
  onFormatChange(ticks, fractionDigits, domain, format) {
    if (format) {
      super.onFormatChange(ticks, fractionDigits, domain, format);
    } else {
      this.labelFormatter = this.scale.tickFormat({ ticks, domain });
      this.datumFormatter = this.scale.tickFormat({ ticks, domain, formatOffset: 1 });
    }
  }
  updateSecondaryAxisTicks(primaryTickCount) {
    if (!this.dataDomain?.domain.length) {
      return [];
    }
    const { domain, ticks } = calculateNiceSecondaryAxis(
      this.dataDomain.domain.map(Number),
      primaryTickCount ?? 0,
      this.reverse
    );
    this.scale.nice = false;
    this.scale.domain = domain.map((d) => new Date(d));
    this.scale.update();
    return ticks;
  }
};
TimeAxis.className = "TimeAxis";
TimeAxis.type = "time";
__decorateClass([
  Validate(AND(DATE_OR_DATETIME_MS, LESS_THAN("max")), { optional: true })
], TimeAxis.prototype, "min", 2);
__decorateClass([
  Validate(AND(DATE_OR_DATETIME_MS, GREATER_THAN("min")), { optional: true })
], TimeAxis.prototype, "max", 2);
var drawCorner = (path, { x0, y0, x1, y1, cx, cy }, cornerRadius, move) => {
  if (move) {
    path.moveTo(x0, y0);
  }
  if (x0 !== x1 || y0 !== y1) {
    const r0 = Math.atan2(y0 - cy, x0 - cx);
    const r1 = Math.atan2(y1 - cy, x1 - cx);
    path.arc(cx, cy, cornerRadius, r0, r1);
  } else {
    path.lineTo(x0, y0);
  }
};
var epsilon = 1e-6;
var cornerEdges = (leadingEdge, trailingEdge, leadingInset, trailingInset, cornerRadius) => {
  let leadingClipped = false;
  let trailingClipped = false;
  let leading0 = trailingInset - Math.sqrt(Math.max(cornerRadius ** 2 - leadingInset ** 2, 0));
  let leading1 = 0;
  let trailing0 = 0;
  let trailing1 = leadingInset - Math.sqrt(Math.max(cornerRadius ** 2 - trailingInset ** 2, 0));
  if (leading0 > leadingEdge) {
    leadingClipped = true;
    leading0 = leadingEdge;
    leading1 = leadingInset - Math.sqrt(Math.max(cornerRadius ** 2 - (trailingInset - leadingEdge) ** 2));
  } else if (leading0 < epsilon) {
    leading0 = 0;
  }
  if (trailing1 > trailingEdge) {
    trailingClipped = true;
    trailing0 = trailingInset - Math.sqrt(Math.max(cornerRadius ** 2 - (leadingInset - trailingEdge) ** 2));
    trailing1 = trailingEdge;
  } else if (trailing1 < epsilon) {
    trailing1 = 0;
  }
  return { leading0, leading1, trailing0, trailing1, leadingClipped, trailingClipped };
};
var clippedRoundRect = (path, x, y, width2, height2, cornerRadii, clipBBox) => {
  let {
    topLeft: topLeftCornerRadius,
    topRight: topRightCornerRadius,
    bottomRight: bottomRightCornerRadius,
    bottomLeft: bottomLeftCornerRadius
  } = cornerRadii;
  const maxVerticalCornerRadius = Math.max(
    topLeftCornerRadius + bottomLeftCornerRadius,
    topRightCornerRadius + bottomRightCornerRadius
  );
  const maxHorizontalCornerRadius = Math.max(
    topLeftCornerRadius + topRightCornerRadius,
    bottomLeftCornerRadius + bottomRightCornerRadius
  );
  if (maxVerticalCornerRadius <= 0 && maxHorizontalCornerRadius <= 0) {
    if (clipBBox == null) {
      path.rect(x, y, width2, height2);
    } else {
      path.rect(clipBBox.x, clipBBox.y, clipBBox.width, clipBBox.height);
    }
    return;
  } else if (clipBBox == null && topLeftCornerRadius === topRightCornerRadius && topLeftCornerRadius === bottomRightCornerRadius && topLeftCornerRadius === bottomLeftCornerRadius) {
    path.roundRect(x, y, width2, height2, topLeftCornerRadius);
    return;
  }
  if (width2 < 0) {
    x += width2;
    width2 = Math.abs(width2);
  }
  if (height2 < 0) {
    y += height2;
    height2 = Math.abs(height2);
  }
  if (width2 <= 0 || height2 <= 0)
    return;
  if (clipBBox == null) {
    clipBBox = new BBox(x, y, width2, height2);
  } else {
    const x0 = Math.max(x, clipBBox.x);
    const x1 = Math.min(x + width2, clipBBox.x + clipBBox.width);
    const y0 = Math.max(y, clipBBox.y);
    const y1 = Math.min(y + height2, clipBBox.y + clipBBox.height);
    clipBBox = new BBox(x0, y0, x1 - x0, y1 - y0);
  }
  const borderScale = Math.max(maxVerticalCornerRadius / height2, maxHorizontalCornerRadius / width2, 1);
  if (borderScale > 1) {
    topLeftCornerRadius /= borderScale;
    topRightCornerRadius /= borderScale;
    bottomRightCornerRadius /= borderScale;
    bottomLeftCornerRadius /= borderScale;
  }
  let drawTopLeftCorner = true;
  let drawTopRightCorner = true;
  let drawBottomRightCorner = true;
  let drawBottomLeftCorner = true;
  let topLeftCorner;
  let topRightCorner;
  let bottomRightCorner;
  let bottomLeftCorner;
  if (drawTopLeftCorner) {
    const nodes = cornerEdges(
      clipBBox.height,
      clipBBox.width,
      Math.max(x + topLeftCornerRadius - clipBBox.x, 0),
      Math.max(y + topLeftCornerRadius - clipBBox.y, 0),
      topLeftCornerRadius
    );
    if (nodes.leadingClipped)
      drawBottomLeftCorner = false;
    if (nodes.trailingClipped)
      drawTopRightCorner = false;
    const x0 = Math.max(clipBBox.x + nodes.leading1, clipBBox.x);
    const y0 = Math.max(clipBBox.y + nodes.leading0, clipBBox.y);
    const x1 = Math.max(clipBBox.x + nodes.trailing1, clipBBox.x);
    const y1 = Math.max(clipBBox.y + nodes.trailing0, clipBBox.y);
    const cx = x + topLeftCornerRadius;
    const cy = y + topLeftCornerRadius;
    topLeftCorner = { x0, y0, x1, y1, cx, cy };
  }
  if (drawTopRightCorner) {
    const nodes = cornerEdges(
      clipBBox.width,
      clipBBox.height,
      Math.max(y + topRightCornerRadius - clipBBox.y, 0),
      Math.max(clipBBox.x + clipBBox.width - (x + width2 - topRightCornerRadius), 0),
      topRightCornerRadius
    );
    if (nodes.leadingClipped)
      drawTopLeftCorner = false;
    if (nodes.trailingClipped)
      drawBottomRightCorner = false;
    const x0 = Math.min(clipBBox.x + clipBBox.width - nodes.leading0, clipBBox.x + clipBBox.width);
    const y0 = Math.max(clipBBox.y + nodes.leading1, clipBBox.y);
    const x1 = Math.min(clipBBox.x + clipBBox.width - nodes.trailing0, clipBBox.x + clipBBox.width);
    const y1 = Math.max(clipBBox.y + nodes.trailing1, clipBBox.y);
    const cx = x + width2 - topRightCornerRadius;
    const cy = y + topRightCornerRadius;
    topRightCorner = { x0, y0, x1, y1, cx, cy };
  }
  if (drawBottomRightCorner) {
    const nodes = cornerEdges(
      clipBBox.height,
      clipBBox.width,
      Math.max(clipBBox.x + clipBBox.width - (x + width2 - bottomRightCornerRadius), 0),
      Math.max(clipBBox.y + clipBBox.height - (y + height2 - bottomRightCornerRadius), 0),
      bottomRightCornerRadius
    );
    if (nodes.leadingClipped)
      drawTopRightCorner = false;
    if (nodes.trailingClipped)
      drawBottomLeftCorner = false;
    const x0 = Math.min(clipBBox.x + clipBBox.width - nodes.leading1, clipBBox.x + clipBBox.width);
    const y0 = Math.min(clipBBox.y + clipBBox.height - nodes.leading0, clipBBox.y + clipBBox.height);
    const x1 = Math.min(clipBBox.x + clipBBox.width - nodes.trailing1, clipBBox.x + clipBBox.width);
    const y1 = Math.min(clipBBox.y + clipBBox.height - nodes.trailing0, clipBBox.y + clipBBox.height);
    const cx = x + width2 - bottomRightCornerRadius;
    const cy = y + height2 - bottomRightCornerRadius;
    bottomRightCorner = { x0, y0, x1, y1, cx, cy };
  }
  if (drawBottomLeftCorner) {
    const nodes = cornerEdges(
      clipBBox.width,
      clipBBox.height,
      Math.max(clipBBox.y + clipBBox.height - (y + height2 - bottomLeftCornerRadius), 0),
      Math.max(x + bottomLeftCornerRadius - clipBBox.x, 0),
      bottomLeftCornerRadius
    );
    if (nodes.leadingClipped)
      drawBottomRightCorner = false;
    if (nodes.trailingClipped)
      drawTopLeftCorner = false;
    const x0 = Math.max(clipBBox.x + nodes.leading0, clipBBox.x);
    const y0 = Math.min(clipBBox.y + clipBBox.height - nodes.leading1, clipBBox.y + clipBBox.height);
    const x1 = Math.max(clipBBox.x + nodes.trailing0, clipBBox.x);
    const y1 = Math.min(clipBBox.y + clipBBox.height - nodes.trailing1, clipBBox.y + clipBBox.height);
    const cx = x + bottomLeftCornerRadius;
    const cy = y + height2 - bottomLeftCornerRadius;
    bottomLeftCorner = { x0, y0, x1, y1, cx, cy };
  }
  let didMove = false;
  if (drawTopLeftCorner && topLeftCorner != null) {
    drawCorner(path, topLeftCorner, topLeftCornerRadius, !didMove);
    didMove || (didMove = true);
  }
  if (drawTopRightCorner && topRightCorner != null) {
    drawCorner(path, topRightCorner, topRightCornerRadius, !didMove);
    didMove || (didMove = true);
  }
  if (drawBottomRightCorner && bottomRightCorner != null) {
    drawCorner(path, bottomRightCorner, bottomRightCornerRadius, !didMove);
    didMove || (didMove = true);
  }
  if (drawBottomLeftCorner && bottomLeftCorner != null) {
    drawCorner(path, bottomLeftCorner, bottomLeftCornerRadius, !didMove);
  }
  path.closePath();
};
var Rect = class extends Path {
  constructor() {
    super(...arguments);
    this.borderPath = new ExtendedPath2D();
    this.x = 0;
    this.y = 0;
    this.width = 10;
    this.height = 10;
    this.topLeftCornerRadius = 0;
    this.topRightCornerRadius = 0;
    this.bottomRightCornerRadius = 0;
    this.bottomLeftCornerRadius = 0;
    this.clipBBox = void 0;
    this.crisp = false;
    this.lastUpdatePathStrokeWidth = Shape.defaultStyles.strokeWidth;
    this.effectiveStrokeWidth = Shape.defaultStyles.strokeWidth;
    this.hittester = super.isPointInPath.bind(this);
    this.distanceCalculator = super.distanceSquaredTransformedPoint.bind(this);
    this.microPixelEffectOpacity = 1;
  }
  set cornerRadius(cornerRadius) {
    this.topLeftCornerRadius = cornerRadius;
    this.topRightCornerRadius = cornerRadius;
    this.bottomRightCornerRadius = cornerRadius;
    this.bottomLeftCornerRadius = cornerRadius;
  }
  isDirtyPath() {
    return this.lastUpdatePathStrokeWidth !== this.strokeWidth || Boolean(this.path.isDirty() || this.borderPath.isDirty());
  }
  updatePath() {
    const {
      path,
      borderPath,
      crisp,
      topLeftCornerRadius: topLeft,
      topRightCornerRadius: topRight,
      bottomRightCornerRadius: bottomRight,
      bottomLeftCornerRadius: bottomLeft
    } = this;
    let { x, y, width: w, height: h, strokeWidth, clipBBox } = this;
    const pixelRatio = this.layerManager?.canvas.pixelRatio ?? 1;
    const pixelSize = 1 / pixelRatio;
    let microPixelEffectOpacity = 1;
    path.clear(true);
    borderPath.clear(true);
    if (crisp) {
      if (w <= pixelSize) {
        microPixelEffectOpacity *= w / pixelSize;
      }
      if (h <= pixelSize) {
        microPixelEffectOpacity *= h / pixelSize;
      }
      w = this.align(x, w);
      h = this.align(y, h);
      x = this.align(x);
      y = this.align(y);
      clipBBox = clipBBox != null ? new BBox(
        this.align(clipBBox.x),
        this.align(clipBBox.y),
        this.align(clipBBox.x, clipBBox.width),
        this.align(clipBBox.y, clipBBox.height)
      ) : void 0;
    }
    if (strokeWidth) {
      if (w < pixelSize) {
        const lx = x + pixelSize / 2;
        borderPath.moveTo(lx, y);
        borderPath.lineTo(lx, y + h);
        strokeWidth = pixelSize;
        this.borderClipPath = void 0;
      } else if (h < pixelSize) {
        const ly = y + pixelSize / 2;
        borderPath.moveTo(x, ly);
        borderPath.lineTo(x + w, ly);
        strokeWidth = pixelSize;
        this.borderClipPath = void 0;
      } else if (strokeWidth < w && strokeWidth < h) {
        const halfStrokeWidth = strokeWidth / 2;
        x += halfStrokeWidth;
        y += halfStrokeWidth;
        w -= strokeWidth;
        h -= strokeWidth;
        const adjustedClipBBox = clipBBox?.clone().shrink(halfStrokeWidth);
        const cornerRadii = {
          topLeft: topLeft > 0 ? topLeft - strokeWidth : 0,
          topRight: topRight > 0 ? topRight - strokeWidth : 0,
          bottomRight: bottomRight > 0 ? bottomRight - strokeWidth : 0,
          bottomLeft: bottomLeft > 0 ? bottomLeft - strokeWidth : 0
        };
        this.borderClipPath = void 0;
        if (w > 0 && h > 0 && (adjustedClipBBox == null || adjustedClipBBox?.width > 0 && adjustedClipBBox?.height > 0)) {
          clippedRoundRect(path, x, y, w, h, cornerRadii, adjustedClipBBox);
          clippedRoundRect(borderPath, x, y, w, h, cornerRadii, adjustedClipBBox);
        }
      } else {
        this.borderClipPath = this.borderClipPath ?? new ExtendedPath2D();
        this.borderClipPath.clear(true);
        this.borderClipPath.rect(x, y, w, h);
        borderPath.rect(x, y, w, h);
      }
    } else {
      const cornerRadii = { topLeft, topRight, bottomRight, bottomLeft };
      this.borderClipPath = void 0;
      clippedRoundRect(path, x, y, w, h, cornerRadii, clipBBox);
    }
    if ([topLeft, topRight, bottomRight, bottomLeft].every((r) => r === 0)) {
      const bbox = this.getBBox();
      this.hittester = bbox.containsPoint.bind(bbox);
      this.distanceSquared = (hitX, hitY) => this.getBBox().distanceSquared(hitX, hitY);
    } else {
      this.hittester = super.isPointInPath;
      this.distanceCalculator = super.distanceSquaredTransformedPoint;
    }
    this.effectiveStrokeWidth = strokeWidth;
    this.lastUpdatePathStrokeWidth = strokeWidth;
    this.microPixelEffectOpacity = microPixelEffectOpacity;
  }
  computeBBox() {
    const { x, y, width: width2, height: height2, clipBBox } = this;
    return clipBBox?.clone() ?? new BBox(x, y, width2, height2);
  }
  isPointInPath(x, y) {
    return this.hittester(x, y);
  }
  get midPoint() {
    return { x: this.x + this.width / 2, y: this.y + this.height / 2 };
  }
  distanceSquared(x, y) {
    return this.distanceCalculator(x, y);
  }
  applyFillAlpha(ctx) {
    const { fillOpacity, microPixelEffectOpacity, opacity } = this;
    ctx.globalAlpha *= opacity * fillOpacity * microPixelEffectOpacity;
  }
  renderStroke(ctx) {
    const { stroke, effectiveStrokeWidth } = this;
    if (stroke && effectiveStrokeWidth) {
      const { globalAlpha } = ctx;
      const {
        strokeOpacity,
        lineDash,
        lineDashOffset,
        lineCap,
        lineJoin,
        borderPath,
        borderClipPath,
        opacity,
        microPixelEffectOpacity
      } = this;
      if (borderClipPath) {
        ctx.clip(borderClipPath.getPath2D());
      }
      this.applyStroke(ctx);
      ctx.globalAlpha *= opacity * strokeOpacity * microPixelEffectOpacity;
      ctx.lineWidth = effectiveStrokeWidth;
      if (lineDash) {
        ctx.setLineDash(lineDash);
      }
      if (lineDashOffset) {
        ctx.lineDashOffset = lineDashOffset;
      }
      if (lineCap) {
        ctx.lineCap = lineCap;
      }
      if (lineJoin) {
        ctx.lineJoin = lineJoin;
      }
      ctx.stroke(borderPath.getPath2D());
      ctx.globalAlpha = globalAlpha;
    }
  }
};
Rect.className = "Rect";
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "x", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "y", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "width", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "height", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "topLeftCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "topRightCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "bottomRightCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "bottomLeftCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "clipBBox", 2);
__decorateClass([
  ScenePathChangeDetection()
], Rect.prototype, "crisp", 2);
var Background = class extends BaseModuleInstance {
  constructor(ctx) {
    super();
    this.ctx = ctx;
    this.rectNode = new Rect();
    this.textNode = new Text();
    this.fill = "white";
    this.node = this.createNode();
    this.node.append([this.rectNode, this.textNode]);
    this.visible = true;
    this.destroyFns.push(
      ctx.scene.attachNode(this.node),
      ctx.layoutManager.addListener("layout:complete", (e) => this.onLayoutComplete(e))
    );
  }
  createNode() {
    return new Group({
      name: "background",
      zIndex: 0
      /* CHART_BACKGROUND */
    });
  }
  onLayoutComplete(e) {
    const { width: width2, height: height2 } = e.chart;
    this.rectNode.width = width2;
    this.rectNode.height = height2;
  }
};
__decorateClass([
  Validate(BOOLEAN),
  ProxyPropertyOnWrite("node", "visible")
], Background.prototype, "visible", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true }),
  ProxyPropertyOnWrite("rectNode", "fill")
], Background.prototype, "fill", 2);
__decorateClass([
  Validate(OBJECT, { optional: true })
], Background.prototype, "image", 2);
__decorateClass([
  Validate(STRING, { optional: true }),
  ProxyPropertyOnWrite("textNode")
], Background.prototype, "text", 2);
var BackgroundModule = {
  type: "root",
  optionsKey: "background",
  packageType: "community",
  chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"],
  moduleFactory: (ctx) => new Background(ctx)
};
function gridLayout({
  orientation,
  bboxes,
  maxHeight,
  maxWidth,
  itemPaddingY = 0,
  itemPaddingX = 0,
  forceResult = false
}) {
  const horizontal = orientation === "horizontal";
  const primary = {
    max: horizontal ? maxWidth : maxHeight,
    fn: horizontal ? (b) => b.width : (b) => b.height,
    padding: horizontal ? itemPaddingX : itemPaddingY
  };
  const secondary = {
    max: horizontal ? maxHeight : maxWidth,
    fn: horizontal ? (b) => b.height : (b) => b.width,
    padding: horizontal ? itemPaddingY : itemPaddingX
  };
  let processedBBoxCount = 0;
  const rawPages = [];
  while (processedBBoxCount < bboxes.length) {
    const unprocessedBBoxes = bboxes.slice(processedBBoxCount);
    const result = processBBoxes(unprocessedBBoxes, processedBBoxCount, primary, secondary, forceResult);
    if (!result) {
      return;
    }
    processedBBoxCount += result.processedBBoxCount;
    rawPages.push(result.pageIndices);
  }
  return buildPages(rawPages, orientation, bboxes, itemPaddingY, itemPaddingX);
}
function processBBoxes(bboxes, indexOffset, primary, secondary, forceResult) {
  const minGuess = 1;
  let startingGuess = estimateStartingGuess(bboxes, primary);
  if (startingGuess < minGuess) {
    if (!forceResult) {
      return;
    }
    startingGuess = minGuess;
  }
  let guess = startingGuess;
  while (guess >= minGuess) {
    const pageIndices = calculatePage(bboxes, indexOffset, guess, primary, secondary, forceResult);
    if (pageIndices == null && guess <= minGuess) {
      return;
    }
    if (pageIndices == null) {
      guess--;
      continue;
    }
    if (typeof pageIndices === "number") {
      if (pageIndices <= minGuess) {
        return;
      }
      guess = pageIndices < guess && pageIndices > minGuess ? pageIndices : guess;
      guess--;
      continue;
    }
    const processedBBoxCount = pageIndices.length * pageIndices[0].length;
    return { processedBBoxCount, pageIndices };
  }
}
function calculatePage(bboxes, indexOffset, primaryCount, primary, secondary, forceResult) {
  const result = [];
  let sumSecondary = 0;
  let currentMaxSecondary = 0;
  let currentPrimaryIndices = [];
  const maxPrimaryValues = [];
  for (let bboxIndex = 0; bboxIndex < bboxes.length; bboxIndex++) {
    const primaryValueIdx = (bboxIndex + primaryCount) % primaryCount;
    if (primaryValueIdx === 0) {
      sumSecondary += currentMaxSecondary;
      currentMaxSecondary = 0;
      if (currentPrimaryIndices.length > 0) {
        result.push(currentPrimaryIndices);
      }
      currentPrimaryIndices = [];
    }
    const primaryValue = primary.fn(bboxes[bboxIndex]) + primary.padding;
    maxPrimaryValues[primaryValueIdx] = Math.max(maxPrimaryValues[primaryValueIdx] ?? 0, primaryValue);
    currentMaxSecondary = Math.max(currentMaxSecondary, secondary.fn(bboxes[bboxIndex]) + secondary.padding);
    const currentSecondaryDimension = sumSecondary + currentMaxSecondary;
    const returnResult = !forceResult || result.length > 0;
    if (currentSecondaryDimension > secondary.max && returnResult) {
      currentPrimaryIndices = [];
      break;
    }
    const sumPrimary = maxPrimaryValues.reduce((sum2, next) => sum2 + next, 0);
    if (sumPrimary > primary.max && !forceResult) {
      if (maxPrimaryValues.length < primaryCount) {
        return maxPrimaryValues.length;
      }
      return;
    }
    currentPrimaryIndices.push(bboxIndex + indexOffset);
  }
  if (currentPrimaryIndices.length > 0) {
    result.push(currentPrimaryIndices);
  }
  return result.length > 0 ? result : void 0;
}
function buildPages(rawPages, orientation, bboxes, itemPaddingY, itemPaddingX) {
  let maxPageWidth = 0;
  let maxPageHeight = 0;
  const pages = rawPages.map((indices) => {
    if (orientation === "horizontal") {
      indices = transpose(indices);
    }
    let endIndex = 0;
    const columns = indices.map((colIndices) => {
      const colBBoxes = colIndices.map((bboxIndex) => {
        endIndex = Math.max(bboxIndex, endIndex);
        return bboxes[bboxIndex];
      });
      let columnHeight = 0;
      let columnWidth = 0;
      colBBoxes.forEach((bbox) => {
        columnHeight += bbox.height + itemPaddingY;
        columnWidth = Math.max(columnWidth, bbox.width + itemPaddingX);
      });
      return {
        indices: colIndices,
        bboxes: colBBoxes,
        columnHeight: Math.ceil(columnHeight),
        columnWidth: Math.ceil(columnWidth)
      };
    });
    let pageWidth = 0;
    let pageHeight = 0;
    columns.forEach((column) => {
      pageWidth += column.columnWidth;
      pageHeight = Math.max(pageHeight, column.columnHeight);
    });
    maxPageWidth = Math.max(pageWidth, maxPageWidth);
    maxPageHeight = Math.max(pageHeight, maxPageHeight);
    return {
      columns,
      startIndex: indices[0][0],
      endIndex,
      pageWidth,
      pageHeight
    };
  });
  return { pages, maxPageWidth, maxPageHeight };
}
function transpose(data) {
  const result = [];
  for (const _ of data[0]) {
    result.push([]);
  }
  data.forEach((innerData, dataIdx) => {
    innerData.forEach((item, itemIdx) => {
      result[itemIdx][dataIdx] = item;
    });
  });
  return result;
}
function estimateStartingGuess(bboxes, primary) {
  const n = bboxes.length;
  let primarySum = 0;
  for (let bboxIndex = 0; bboxIndex < n; bboxIndex++) {
    primarySum += primary.fn(bboxes[bboxIndex]) + primary.padding;
    if (primarySum > primary.max) {
      const ratio2 = n / bboxIndex;
      if (ratio2 < 2) {
        return Math.ceil(n / 2);
      }
      return bboxIndex;
    }
  }
  return n;
}
var PaginationLabel = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.color = "black";
    this.fontStyle = void 0;
    this.fontWeight = void 0;
    this.fontSize = 12;
    this.fontFamily = "Verdana, sans-serif";
  }
};
__decorateClass([
  Validate(COLOR_STRING)
], PaginationLabel.prototype, "color", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], PaginationLabel.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], PaginationLabel.prototype, "fontWeight", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PaginationLabel.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING)
], PaginationLabel.prototype, "fontFamily", 2);
var PaginationMarkerStyle = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.size = 15;
    this.fill = void 0;
    this.fillOpacity = void 0;
    this.stroke = void 0;
    this.strokeWidth = 1;
    this.strokeOpacity = 1;
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PaginationMarkerStyle.prototype, "size", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], PaginationMarkerStyle.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], PaginationMarkerStyle.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], PaginationMarkerStyle.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PaginationMarkerStyle.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO)
], PaginationMarkerStyle.prototype, "strokeOpacity", 2);
var PaginationMarker = class extends BaseProperties {
  constructor(parent) {
    super();
    this.parent = parent;
    this.shape = "triangle";
    this.size = 15;
    this.padding = 8;
  }
};
__decorateClass([
  ActionOnSet({
    changeValue() {
      if (this.parent.marker === this) {
        this.parent.onMarkerShapeChange();
      }
    }
  })
], PaginationMarker.prototype, "shape", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PaginationMarker.prototype, "size", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PaginationMarker.prototype, "padding", 2);
var Pagination = class extends BaseProperties {
  constructor(chartUpdateCallback, pageUpdateCallback) {
    super();
    this.chartUpdateCallback = chartUpdateCallback;
    this.pageUpdateCallback = pageUpdateCallback;
    this.id = createId(this);
    this.marker = new PaginationMarker(this);
    this.activeStyle = new PaginationMarkerStyle();
    this.inactiveStyle = new PaginationMarkerStyle();
    this.highlightStyle = new PaginationMarkerStyle();
    this.label = new PaginationLabel();
    this.group = new TranslatableGroup({ name: "pagination" });
    this.labelNode = new Text();
    this.destroyFns = [];
    this.totalPages = 0;
    this.currentPage = 0;
    this.translationX = 0;
    this.translationY = 0;
    this.nextButtonDisabled = false;
    this.previousButtonDisabled = false;
    this._visible = true;
    this._enabled = true;
    this._orientation = "vertical";
    this._nextButton = new Triangle();
    this._previousButton = new Triangle();
    this.labelNode.setProperties({
      textBaseline: "middle",
      fontSize: 12,
      fontFamily: "Verdana, sans-serif",
      fill: "black",
      y: 1
    });
    this.group.append([this.nextButton, this.previousButton, this.labelNode]);
    this.update();
    this.updateMarkers();
  }
  destroy() {
    this.destroyFns.forEach((f) => f());
  }
  set visible(value) {
    this._visible = value;
    this.updateGroupVisibility();
  }
  get visible() {
    return this._visible;
  }
  set enabled(value) {
    this._enabled = value;
    this.updateGroupVisibility();
  }
  get enabled() {
    return this._enabled;
  }
  updateGroupVisibility() {
    this.group.visible = this.enabled && this.visible;
  }
  set orientation(value) {
    this._orientation = value;
    switch (value) {
      case "horizontal": {
        this.previousButton.rotation = -Math.PI / 2;
        this.nextButton.rotation = Math.PI / 2;
        break;
      }
      case "vertical":
      default: {
        this.previousButton.rotation = 0;
        this.nextButton.rotation = Math.PI;
      }
    }
  }
  get orientation() {
    return this._orientation;
  }
  set nextButton(value) {
    if (this._nextButton !== value) {
      this.group.removeChild(this._nextButton);
      this._nextButton = value;
      this.group.appendChild(value);
    }
  }
  get nextButton() {
    return this._nextButton;
  }
  set previousButton(value) {
    if (this._previousButton !== value) {
      this.group.removeChild(this._previousButton);
      this._previousButton = value;
      this.group.appendChild(value);
    }
  }
  get previousButton() {
    return this._previousButton;
  }
  update() {
    this.updateLabel();
    this.updatePositions();
    this.enableOrDisableButtons();
  }
  updatePositions() {
    this.group.translationX = this.translationX;
    this.group.translationY = this.translationY;
    this.updateLabelPosition();
    this.updateNextButtonPosition();
  }
  updateLabelPosition() {
    const { size: markerSize, padding: markerPadding } = this.marker;
    this.nextButton.size = markerSize;
    this.previousButton.size = markerSize;
    this.labelNode.x = markerSize / 2 + markerPadding;
  }
  updateNextButtonPosition() {
    const labelBBox = this.labelNode.getBBox();
    this.nextButton.translationX = labelBBox.width + (this.marker.size / 2 + this.marker.padding) * 2;
  }
  updateLabel() {
    const {
      currentPage,
      totalPages: pages,
      labelNode,
      label: { color, fontStyle, fontWeight, fontSize, fontFamily }
    } = this;
    labelNode.text = `${currentPage + 1} / ${pages}`;
    labelNode.fill = color;
    labelNode.fontStyle = fontStyle;
    labelNode.fontWeight = fontWeight;
    labelNode.fontSize = fontSize;
    labelNode.fontFamily = fontFamily;
  }
  updateMarkers() {
    const {
      nextButton,
      previousButton,
      nextButtonDisabled,
      previousButtonDisabled,
      activeStyle,
      inactiveStyle,
      highlightStyle,
      highlightActive
    } = this;
    const buttonStyle = (button, disabled) => {
      if (disabled) {
        return inactiveStyle;
      } else if (button === highlightActive) {
        return highlightStyle;
      }
      return activeStyle;
    };
    this.updateMarker(nextButton, buttonStyle("next", nextButtonDisabled));
    this.updateMarker(previousButton, buttonStyle("previous", previousButtonDisabled));
  }
  updateMarker(marker, style) {
    const { size } = this.marker;
    marker.size = size;
    marker.fill = style.fill;
    marker.fillOpacity = style.fillOpacity ?? 1;
    marker.stroke = style.stroke;
    marker.strokeWidth = style.strokeWidth;
    marker.strokeOpacity = style.strokeOpacity;
  }
  enableOrDisableButtons() {
    const { currentPage, totalPages } = this;
    const zeroPagesToDisplay = totalPages === 0;
    const onLastPage = currentPage === totalPages - 1;
    const onFirstPage = currentPage === 0;
    this.nextButtonDisabled = onLastPage || zeroPagesToDisplay;
    this.previousButtonDisabled = onFirstPage || zeroPagesToDisplay;
  }
  setPage(pageNumber) {
    pageNumber = clamp(0, pageNumber, Math.max(0, this.totalPages - 1));
    if (this.currentPage !== pageNumber) {
      this.currentPage = pageNumber;
      this.onPaginationChanged();
    }
  }
  getCursor(node) {
    return { previous: this.previousButtonDisabled, next: this.nextButtonDisabled }[node] ? void 0 : "pointer";
  }
  onClick(event, node) {
    event.preventDefault();
    if (node === "next" && !this.nextButtonDisabled) {
      this.incrementPage();
      this.onPaginationChanged();
    } else if (node === "previous" && !this.previousButtonDisabled) {
      this.decrementPage();
      this.onPaginationChanged();
    }
  }
  onMouseHover(node) {
    this.highlightActive = node;
    this.updateMarkers();
    this.chartUpdateCallback(
      6
      /* SCENE_RENDER */
    );
  }
  onPaginationChanged() {
    this.pageUpdateCallback(this.currentPage);
  }
  incrementPage() {
    this.currentPage = Math.min(this.currentPage + 1, this.totalPages - 1);
  }
  decrementPage() {
    this.currentPage = Math.max(this.currentPage - 1, 0);
  }
  onMarkerShapeChange() {
    const Marker2 = Rotatable(getMarker(this.marker.shape || Triangle));
    this.previousButton = new Marker2();
    this.nextButton = new Marker2();
    this.updatePositions();
    this.updateMarkers();
    this.chartUpdateCallback(
      6
      /* SCENE_RENDER */
    );
  }
  attachPagination(node) {
    node.append(this.group);
  }
  getBBox() {
    return this.group.getBBox();
  }
  computeCSSBounds() {
    const prev = Transformable.toCanvas(this.previousButton);
    const next = Transformable.toCanvas(this.nextButton);
    return { prev, next };
  }
};
Pagination.className = "Pagination";
__decorateClass([
  Validate(OBJECT)
], Pagination.prototype, "marker", 2);
__decorateClass([
  Validate(OBJECT)
], Pagination.prototype, "activeStyle", 2);
__decorateClass([
  Validate(OBJECT)
], Pagination.prototype, "inactiveStyle", 2);
__decorateClass([
  Validate(OBJECT)
], Pagination.prototype, "highlightStyle", 2);
__decorateClass([
  Validate(OBJECT)
], Pagination.prototype, "label", 2);
var LegendDOMProxy = class {
  constructor(ctx, idPrefix) {
    this.idPrefix = idPrefix;
    this.dirty = true;
    this.destroyFns = new DestroyFns();
    this.itemList = ctx.proxyInteractionService.createProxyContainer({
      type: "list",
      domManagerId: `${idPrefix}-toolbar`,
      classList: ["ag-charts-proxy-legend-toolbar"],
      ariaLabel: { id: "ariaLabelLegend" }
    });
    this.paginationGroup = ctx.proxyInteractionService.createProxyContainer({
      type: "group",
      domManagerId: `${idPrefix}-pagination`,
      classList: ["ag-charts-proxy-legend-pagination"],
      ariaLabel: { id: "ariaLabelLegendPagination" },
      ariaOrientation: "horizontal"
    });
    this.itemDescription = createElement("p");
    this.itemDescription.style.display = "none";
    this.itemDescription.id = `${idPrefix}-ariaDescription`;
    this.itemDescription.textContent = this.getItemAriaDescription(ctx.localeManager);
    this.itemList.getElement().append(this.itemDescription);
  }
  destroy() {
    this.destroyFns.destroy();
  }
  initLegendList(params) {
    if (!this.dirty)
      return;
    const { ctx, itemSelection, datumReader, itemListener } = params;
    const lm = ctx.localeManager;
    const count = itemSelection.length;
    itemSelection.each((markerLabel, datum, index) => {
      markerLabel.proxyButton?.destroy();
      markerLabel.proxyButton = ctx.proxyInteractionService.createProxyElement({
        type: "listswitch",
        id: `ag-charts-legend-item-${index}`,
        textContent: this.getItemAriaText(lm, datumReader.getItemLabel(datum), index, count),
        ariaChecked: !!markerLabel.datum.enabled,
        ariaDescribedBy: this.itemDescription.id,
        parent: this.itemList
      });
      const button = markerLabel.proxyButton;
      button.addListener("click", (ev) => itemListener.onClick(ev.sourceEvent, markerLabel.datum, button));
      button.addListener("dblclick", (ev) => itemListener.onDoubleClick(ev.sourceEvent, markerLabel.datum));
      button.addListener("mouseenter", (ev) => itemListener.onHover(ev.sourceEvent, markerLabel));
      button.addListener("mouseleave", () => itemListener.onLeave());
      button.addListener("contextmenu", (ev) => itemListener.onContextClick(ev.sourceEvent, markerLabel));
      button.addListener("blur", () => itemListener.onLeave());
      button.addListener("focus", (ev) => itemListener.onHover(ev.sourceEvent, markerLabel));
    });
    this.dirty = false;
  }
  update(params) {
    this.updateVisibility(params.visible);
    if (params.visible) {
      this.initLegendList(params);
      this.updateItemProxyButtons(params);
      this.updatePaginationProxyButtons(params);
    }
  }
  updateVisibility(visible) {
    this.itemList.setHidden(!visible);
    this.paginationGroup.setHidden(!visible);
  }
  updateItemProxyButtons({ itemSelection, group, pagination, interactive }) {
    const groupBBox = Transformable.toCanvas(group);
    this.itemList.setBounds(groupBBox);
    const maxHeight = Math.max(...itemSelection.nodes().map((l) => l.getBBox().height));
    itemSelection.each((l, _datum) => {
      if (l.proxyButton) {
        const visible = l.pageIndex === pagination.currentPage;
        const { x, y, height: height2, width: width2 } = Transformable.toCanvas(l);
        const margin = (maxHeight - height2) / 2;
        const bbox = { x: x - groupBBox.x, y: y - margin - groupBBox.y, height: maxHeight, width: width2 };
        l.proxyButton.setCursor("pointer");
        l.proxyButton.setEnabled(interactive && visible);
        l.proxyButton.setBounds(bbox);
      }
    });
  }
  updatePaginationProxyButtons(params) {
    const { ctx, pagination, oldPages, newPages } = params;
    this.paginationGroup.setHidden(!pagination.visible);
    const oldNeedsButtons = (oldPages?.length ?? newPages.length) > 1;
    const newNeedsButtons = newPages.length > 1;
    if (oldNeedsButtons !== newNeedsButtons) {
      if (newNeedsButtons) {
        this.prevButton = ctx.proxyInteractionService.createProxyElement({
          type: "button",
          id: `${this.idPrefix}-prev-page`,
          textContent: { id: "ariaLabelLegendPagePrevious" },
          tabIndex: 0,
          parent: this.paginationGroup
        });
        this.prevButton.addListener("click", (ev) => pagination.onClick(ev.sourceEvent, "previous"));
        this.prevButton.addListener("mouseenter", () => pagination.onMouseHover("previous"));
        this.prevButton.addListener("mouseleave", () => pagination.onMouseHover(void 0));
        this.nextButton ?? (this.nextButton = ctx.proxyInteractionService.createProxyElement({
          type: "button",
          id: `${this.idPrefix}-next-page`,
          textContent: { id: "ariaLabelLegendPageNext" },
          tabIndex: 0,
          parent: this.paginationGroup
        }));
        this.nextButton.addListener("click", (ev) => pagination.onClick(ev.sourceEvent, "next"));
        this.nextButton.addListener("mouseenter", () => pagination.onMouseHover("next"));
        this.nextButton.addListener("mouseleave", () => pagination.onMouseHover(void 0));
      } else {
        this.nextButton?.destroy();
        this.prevButton?.destroy();
        this.nextButton = void 0;
        this.prevButton = void 0;
      }
    }
    const { prev, next } = pagination.computeCSSBounds();
    this.prevButton?.setBounds(prev);
    this.nextButton?.setBounds(next);
    this.updatePaginationCursors(params);
  }
  updatePaginationCursors({ pagination }) {
    this.nextButton?.setCursor(pagination.getCursor("next"));
    this.prevButton?.setCursor(pagination.getCursor("previous"));
  }
  onDataUpdate(oldData, newData) {
    this.dirty = oldData.length !== newData.length || oldData.some((_v, index, _a) => {
      const [newValue, oldValue] = [newData[index], oldData[index]];
      return newValue.id !== oldValue.id;
    });
  }
  onLocaleChanged(localeManager, itemSelection, datumReader) {
    const count = itemSelection.length;
    itemSelection.each(({ proxyButton }, datum, index) => {
      const button = proxyButton?.getElement();
      if (button != null) {
        const label = datumReader.getItemLabel(datum);
        button.textContent = this.getItemAriaText(localeManager, label, index, count);
      }
    });
    this.itemDescription.textContent = this.getItemAriaDescription(localeManager);
  }
  onPageChange(params) {
    this.updateItemProxyButtons(params);
    this.updatePaginationCursors(params);
  }
  getItemAriaText(localeManager, label, index, count) {
    if (index >= 0 && label) {
      index++;
      return localeManager.t("ariaLabelLegendItem", { label, index, count });
    }
    return localeManager.t("ariaLabelLegendItemUnknown");
  }
  getItemAriaDescription(localeManager) {
    return localeManager.t("ariaDescriptionLegendItem");
  }
};
function makeLegendItemEvent(type, itemId, seriesId, event) {
  const result = {
    defaultPrevented: false,
    apiEvent: {
      type,
      itemId,
      seriesId,
      event,
      preventDefault: () => result.defaultPrevented = true
    }
  };
  return result;
}
var Image = class extends Node {
  constructor(sourceImage) {
    super();
    this.sourceImage = sourceImage;
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
    this.opacity = 1;
  }
  updateBitmap(newBitmap, bitmapPixelRatio, x, y) {
    this.sourceImage = newBitmap;
    this.width = newBitmap.width / bitmapPixelRatio;
    this.height = newBitmap.height / bitmapPixelRatio;
    this.x = x / bitmapPixelRatio;
    this.y = y / bitmapPixelRatio;
    this.markDirty();
  }
  render(renderCtx) {
    const { ctx } = renderCtx;
    const image = this.sourceImage;
    if (image) {
      ctx.globalAlpha = this.opacity;
      ctx.drawImage(image, 0, 0, image.width, image.height, this.x, this.y, this.width, this.height);
    }
    super.render(renderCtx);
  }
};
__decorateClass([
  SceneChangeDetection()
], Image.prototype, "x", 2);
__decorateClass([
  SceneChangeDetection()
], Image.prototype, "y", 2);
__decorateClass([
  SceneChangeDetection()
], Image.prototype, "width", 2);
__decorateClass([
  SceneChangeDetection()
], Image.prototype, "height", 2);
__decorateClass([
  SceneChangeDetection()
], Image.prototype, "opacity", 2);
var LegendMarkerLabel = class extends Translatable(Group) {
  constructor() {
    super({ name: "markerLabelGroup" });
    this.label = new Text();
    this.symbolsGroup = new Group({
      name: "legend-markerLabel-symbols"
    });
    this.bitmap = new Image();
    this.bitmapDirty = true;
    this.enabled = true;
    this.pageIndex = NaN;
    this._marker = void 0;
    this._line = void 0;
    const { marker, label, line } = this;
    label.textBaseline = "middle";
    label.fontSize = 12;
    label.fontFamily = "Verdana, sans-serif";
    label.fill = "black";
    label.y = 1;
    this.updateSymbols(marker, line);
    this.append([this.symbolsGroup, label]);
  }
  destroy() {
    super.destroy();
    this.proxyButton?.destroy();
  }
  get marker() {
    return this._marker;
  }
  get line() {
    return this._line;
  }
  updateSymbols(marker, line) {
    if (this._marker === marker && this._line === line)
      return;
    this.bitmapDirty = true;
    this._marker = marker;
    this._line = line;
    this.symbolsGroup.clear();
    this.symbolsGroup.append([this.bitmap, line, marker].filter(isDefined));
  }
  setEnabled(enabled) {
    this.enabled = enabled;
    this.refreshVisibilities();
  }
  refreshVisibilities() {
    const opacity = this.enabled ? 1 : 0.5;
    this.label.opacity = opacity;
    this.opacity = opacity;
    this.bitmap.opacity = opacity;
    this.setBitmapVisibility(!this.enabled);
  }
  setBitmapVisibility(visible) {
    const { line, marker } = this;
    if (marker != null) {
      marker.visible = !visible;
    }
    if (line != null) {
      line.visible = !visible;
    }
    this.bitmap.visible = visible;
  }
  // The BBox of this.bitmap is `spritePadding` pixels bigger in each direction than BBox of the markers and lines.
  // This padding allows the SpriteRenderer to draw antialiasing pixels that can extend beyond the shapes' bounds.
  update(spriteRenderer, { spriteAAPadding, spritePixelRatio: scale2 }, dimensionProps) {
    const { marker, line } = this;
    const { length: length2, spacing, isCustomMarker } = dimensionProps;
    let lineTop = Infinity;
    let lineX1 = Infinity;
    let lineX2 = Infinity;
    let markerTop = Infinity;
    let markerLeft = Infinity;
    let centerTranslateX = 0;
    let centerTranslateY = 0;
    if (marker) {
      const { size } = marker;
      const center2 = marker.constructor.center;
      const radius = (size + marker.strokeWidth) / 2;
      centerTranslateX = (center2.x - 0.5) * size;
      centerTranslateY = (center2.y - 0.5) * size;
      if (isCustomMarker) {
        marker.x = 0;
        marker.y = 0;
        marker.translationX = centerTranslateX * size + length2 / 2;
        marker.translationY = centerTranslateY * size;
        markerTop = marker.translationY - radius;
        markerLeft = marker.translationX - radius;
      } else {
        marker.x = centerTranslateX + length2 / 2;
        marker.y = centerTranslateY;
        markerTop = marker.y - radius;
        markerLeft = marker.x - radius;
      }
    }
    if (line) {
      line.x1 = 0;
      line.x2 = length2;
      line.y1 = 0;
      line.y2 = 0;
      line.markDirty();
      lineTop = -line.strokeWidth / 2;
      lineX1 = line.x1;
      lineX2 = line.x2;
    }
    const spriteX = Math.min(lineX1, lineX2, markerLeft);
    const spriteY = Math.min(lineTop, markerTop);
    const lineEnd = line?.x2 ?? -Infinity;
    const markerEnd = (marker?.x ?? 0) + (marker?.size ?? 0) / 2;
    this.label.x = Math.max(lineEnd, markerEnd) + spacing;
    if (this.bitmapDirty) {
      this.setBitmapVisibility(false);
      const translateX = centerTranslateX + (spriteAAPadding + spriteX) * scale2;
      const translateY = centerTranslateY + (spriteAAPadding - spriteY) * scale2;
      const sprite = spriteRenderer.renderSprite(this.symbolsGroup, {
        scale: scale2,
        translateX: Math.floor(translateX),
        translateY: Math.floor(translateY)
      });
      this.bitmap.updateBitmap(sprite, scale2, Math.ceil(-translateX), Math.ceil(-translateY));
      this.bitmapDirty = false;
      this.refreshVisibilities();
    }
  }
  computeBBox() {
    const { label, line, marker } = this;
    return this.toParent(Group.computeChildrenBBox([label, line, marker].filter(isDefined), false));
  }
};
LegendMarkerLabel.className = "MarkerLabel";
__decorateClass([
  ProxyPropertyOnWrite("label")
], LegendMarkerLabel.prototype, "text", 2);
__decorateClass([
  ProxyPropertyOnWrite("label")
], LegendMarkerLabel.prototype, "fontStyle", 2);
__decorateClass([
  ProxyPropertyOnWrite("label")
], LegendMarkerLabel.prototype, "fontWeight", 2);
__decorateClass([
  ProxyPropertyOnWrite("label")
], LegendMarkerLabel.prototype, "fontSize", 2);
__decorateClass([
  ProxyPropertyOnWrite("label")
], LegendMarkerLabel.prototype, "fontFamily", 2);
__decorateClass([
  ProxyPropertyOnWrite("label", "fill")
], LegendMarkerLabel.prototype, "color", 2);
var LegendLabel = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.maxLength = void 0;
    this.color = "black";
    this.fontStyle = void 0;
    this.fontWeight = void 0;
    this.fontSize = 12;
    this.fontFamily = "Verdana, sans-serif";
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], LegendLabel.prototype, "maxLength", 2);
__decorateClass([
  Validate(COLOR_STRING)
], LegendLabel.prototype, "color", 2);
__decorateClass([
  Validate(FONT_STYLE, { optional: true })
], LegendLabel.prototype, "fontStyle", 2);
__decorateClass([
  Validate(FONT_WEIGHT, { optional: true })
], LegendLabel.prototype, "fontWeight", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LegendLabel.prototype, "fontSize", 2);
__decorateClass([
  Validate(STRING)
], LegendLabel.prototype, "fontFamily", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], LegendLabel.prototype, "formatter", 2);
var LegendMarker = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.size = 15;
    this.padding = 8;
  }
};
__decorateClass([
  ObserveChanges((target) => target.parent?.onMarkerShapeChange())
], LegendMarker.prototype, "shape", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LegendMarker.prototype, "size", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LegendMarker.prototype, "padding", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], LegendMarker.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(BOOLEAN)
], LegendMarker.prototype, "enabled", 2);
var LegendLine = class extends BaseProperties {
};
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], LegendLine.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], LegendLine.prototype, "length", 2);
var LegendItem = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.paddingX = 16;
    this.paddingY = 8;
    this.showSeriesStroke = false;
    this.marker = new LegendMarker();
    this.label = new LegendLabel();
    this.line = new LegendLine();
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], LegendItem.prototype, "maxWidth", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LegendItem.prototype, "paddingX", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LegendItem.prototype, "paddingY", 2);
__decorateClass([
  Validate(BOOLEAN)
], LegendItem.prototype, "showSeriesStroke", 2);
__decorateClass([
  Validate(OBJECT)
], LegendItem.prototype, "marker", 2);
__decorateClass([
  Validate(OBJECT)
], LegendItem.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], LegendItem.prototype, "line", 2);
var LegendListeners = class extends BaseProperties {
};
__decorateClass([
  Validate(FUNCTION, { optional: true })
], LegendListeners.prototype, "legendItemClick", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], LegendListeners.prototype, "legendItemDoubleClick", 2);
var ID_LEGEND_VISIBILITY = "legend-visibility";
var ID_LEGEND_OTHER_SERIES = "legend-other-series";
var Legend = class extends BaseProperties {
  constructor(ctx) {
    super();
    this.ctx = ctx;
    this.id = createId(this);
    this.group = new TranslatableGroup({
      name: "legend",
      zIndex: 13
      /* LEGEND */
    });
    this.itemSelection = Selection.select(
      this.group,
      LegendMarkerLabel
    );
    this.spriteRenderer = void 0;
    this.oldSize = [0, 0];
    this.pages = [];
    this.maxPageSize = [0, 0];
    this.paginationTrackingIndex = 0;
    this.truncatedItems = /* @__PURE__ */ new Set();
    this._data = [];
    this._symbolsDirty = true;
    this.toggleSeries = true;
    this.item = new LegendItem();
    this.listeners = new LegendListeners();
    this.enabled = true;
    this.position = "bottom";
    this.spacing = 20;
    this.destroyFns = [];
    this.size = [0, 0];
    this._visible = true;
    this.item.marker.parent = this;
    this.pagination = new Pagination(
      (type) => ctx.updateService.update(type),
      (page) => this.updatePageNumber(page)
    );
    this.pagination.attachPagination(this.group);
    this.destroyFns.push(
      ctx.contextMenuRegistry.registerDefaultAction({
        id: ID_LEGEND_VISIBILITY,
        type: "legend",
        label: "contextMenuToggleSeriesVisibility",
        action: (params) => this.contextToggleVisibility(params)
      }),
      ctx.contextMenuRegistry.registerDefaultAction({
        id: ID_LEGEND_OTHER_SERIES,
        type: "legend",
        label: "contextMenuToggleOtherSeries",
        action: (params) => this.contextToggleOtherSeries(params)
      }),
      ctx.legendManager.addListener("legend-change", this.onLegendDataChange.bind(this))
    );
    this.destroyFns.push(
      ctx.layoutManager.registerElement(1, (e) => this.positionLegend(e)),
      ctx.localeManager.addListener("locale-changed", () => this.onLocaleChanged()),
      () => this.group.remove()
    );
    this.domProxy = new LegendDOMProxy(this.ctx, this.id);
    this.ctx.historyManager.addMementoOriginator(ctx.legendManager);
  }
  set data(value) {
    this.domProxy.onDataUpdate(this._data, value);
    this._data = value;
    this._symbolsDirty = true;
    this.updateGroupVisibility();
  }
  get data() {
    return this._data;
  }
  onLegendDataChange({ legendData = [] }) {
    if (!this.enabled)
      return;
    const visibleItems = legendData.filter((datum) => !datum.hideInLegend);
    const { data } = this;
    if (!objectsEqual(legendData, data)) {
      this.data = visibleItems;
    }
  }
  destroy() {
    this.ctx.domManager.removeChild("canvas-overlay", `${this.id}-toolbar`);
    this.ctx.domManager.removeChild("canvas-overlay", `${this.id}-pagination`);
    this.destroyFns.forEach((f) => f());
    this.pagination.destroy();
    this.itemSelection.clear();
    this.domProxy.destroy();
  }
  onMarkerShapeChange() {
    this.itemSelection.clear();
    this.group.markDirty();
  }
  getOrientation() {
    if (this.orientation !== void 0) {
      return this.orientation;
    }
    switch (this.position) {
      case "right":
      case "left":
        return "vertical";
      case "bottom":
      case "top":
        return "horizontal";
    }
  }
  set visible(value) {
    this._visible = value;
    this.updateGroupVisibility();
  }
  get visible() {
    return this._visible;
  }
  updateGroupVisibility() {
    this.group.visible = this.enabled && this.visible && this.data.length > 0;
  }
  attachLegend(scene) {
    scene.appendChild(this.group);
  }
  getItemLabel(datum) {
    const {
      ctx: { callbackCache }
    } = this;
    const { formatter } = this.item.label;
    if (formatter) {
      const seriesDatum = datum.datum;
      return callbackCache.call(formatter, {
        itemId: datum.itemId,
        value: datum.label.text,
        seriesId: datum.seriesId,
        ...seriesDatum && { datum: seriesDatum }
      });
    }
    return datum.label.text;
  }
  /**
   * The method is given the desired size of the legend, which only serves as a hint.
   * The vertically oriented legend will take as much horizontal space as needed, but will
   * respect the height constraints, and the horizontal legend will take as much vertical
   * space as needed in an attempt not to exceed the given width.
   * After the layout is done, the {@link size} will contain the actual size of the legend.
   * If the actual size is not the same as the previous actual size, the legend will fire
   * the 'layoutChange' event to communicate that another layout is needed, and the above
   * process should be repeated.
   * @param width
   * @param height
   */
  calcLayout(width2, height2) {
    const {
      paddingX,
      paddingY,
      label,
      maxWidth,
      label: { maxLength = Infinity, fontStyle, fontWeight, fontSize, fontFamily }
    } = this.item;
    const data = [...this.data];
    if (this.reverseOrder) {
      data.reverse();
    }
    this.itemSelection.update(data);
    const bboxes = [];
    const font = TextUtils.toFontString(label);
    const itemMaxWidthPercentage = 0.8;
    const maxItemWidth = maxWidth ?? width2 * itemMaxWidthPercentage;
    const spriteDims = this.calculateSpriteDimensions();
    this.spriteRenderer ?? (this.spriteRenderer = new SpriteRenderer());
    this.spriteRenderer.resize(spriteDims);
    this.itemSelection.each((markerLabel, datum) => {
      markerLabel.fontStyle = fontStyle;
      markerLabel.fontWeight = fontWeight;
      markerLabel.fontSize = fontSize;
      markerLabel.fontFamily = fontFamily;
      const paddedSymbolWidth = this.updateMarkerLabel(this.spriteRenderer, markerLabel, datum, spriteDims);
      const id = datum.itemId ?? datum.id;
      const labelText = this.getItemLabel(datum);
      const text = (labelText ?? "<unknown>").replace(/\r?\n/g, " ");
      markerLabel.text = this.truncate(text, maxLength, maxItemWidth, paddedSymbolWidth, font, id);
      bboxes.push(markerLabel.getBBox());
    });
    this._symbolsDirty = false;
    width2 = Math.max(1, width2);
    height2 = Math.max(1, height2);
    if (!isFinite(width2)) {
      return {};
    }
    const size = this.size;
    const oldSize = this.oldSize;
    size[0] = width2;
    size[1] = height2;
    if (size[0] !== oldSize[0] || size[1] !== oldSize[1]) {
      oldSize[0] = size[0];
      oldSize[1] = size[1];
    }
    const { pages, maxPageHeight, maxPageWidth } = this.updatePagination(bboxes, width2, height2);
    const oldPages = this.pages;
    this.pages = pages;
    this.maxPageSize = [maxPageWidth - paddingX, maxPageHeight - paddingY];
    const pageNumber = this.pagination.currentPage;
    const page = this.pages[pageNumber];
    if (this.pages.length < 1 || !page) {
      this.visible = false;
      return { oldPages };
    }
    this.visible = true;
    this.updatePositions(pageNumber);
    this.update();
    return { oldPages };
  }
  isCustomMarker(markerEnabled, shape) {
    return markerEnabled && shape !== void 0 && typeof shape !== "string";
  }
  calcSymbolsEnabled(symbol) {
    const { showSeriesStroke, marker } = this.item;
    const markerEnabled = !!marker.enabled || !showSeriesStroke || (symbol.marker.enabled ?? true);
    const lineEnabled = !!(symbol.line && showSeriesStroke);
    const isCustomMarker = this.isCustomMarker(markerEnabled, symbol.marker.shape);
    return { markerEnabled, lineEnabled, isCustomMarker };
  }
  calcSymbolsLengths(symbol) {
    const { marker, line } = this.item;
    const { markerEnabled, lineEnabled } = this.calcSymbolsEnabled(symbol);
    const { strokeWidth: markerStrokeWidth } = this.getMarkerStyles(symbol);
    const { strokeWidth: lineStrokeWidth } = lineEnabled ? this.getLineStyles(symbol) : { strokeWidth: 0 };
    let customMarkerSize;
    const { shape } = symbol.marker;
    if (this.isCustomMarker(markerEnabled, shape)) {
      const Marker2 = getMarker(shape);
      const tmpShape = new Marker2();
      tmpShape.updatePath();
      const bbox = tmpShape.getBBox();
      customMarkerSize = Math.max(bbox.width, bbox.height);
    }
    const markerLength = markerEnabled ? marker.size : 0;
    const lineLength = lineEnabled ? line.length ?? 25 : 0;
    return { markerLength, markerStrokeWidth, lineLength, lineStrokeWidth, customMarkerSize };
  }
  calculateSpriteDimensions() {
    let spriteAAPadding = 0;
    let spriteWidth = 0;
    let spriteHeight = 0;
    let markerWidth = 0;
    this.itemSelection.each((_, datum) => {
      const { symbol } = datum;
      const {
        markerLength,
        markerStrokeWidth,
        lineLength,
        lineStrokeWidth,
        customMarkerSize = -Infinity
      } = this.calcSymbolsLengths(symbol);
      const markerTotalLength = markerLength + markerStrokeWidth;
      markerWidth = Math.max(markerWidth, lineLength, customMarkerSize, markerLength);
      spriteWidth = Math.max(spriteWidth, lineLength, customMarkerSize, markerTotalLength);
      spriteHeight = Math.max(spriteHeight, lineStrokeWidth, markerTotalLength);
      spriteAAPadding = Math.max(spriteAAPadding, markerStrokeWidth + 0.5);
    });
    spriteWidth += spriteAAPadding * 2;
    spriteHeight += spriteAAPadding * 2;
    const spritePixelRatio = getWindow().devicePixelRatio;
    return { spritePixelRatio, spriteAAPadding, spriteWidth, spriteHeight, markerWidth };
  }
  updateMarkerLabel(spriteRenderer, markerLabel, datum, spriteDims) {
    const { marker: itemMarker, paddingX } = this.item;
    const { markerWidth } = spriteDims;
    const { symbol } = datum;
    let paddedSymbolWidth = paddingX;
    const { markerEnabled, lineEnabled, isCustomMarker } = this.calcSymbolsEnabled(symbol);
    if (this._symbolsDirty) {
      const { shape: markerShape = symbol.marker.shape } = itemMarker;
      const MarkerCtr = getMarker(markerShape);
      markerLabel.updateSymbols(new MarkerCtr({ zIndex: 1 }), new Line({ zIndex: 0 }));
    }
    const spacing = itemMarker.padding;
    const { marker, line } = markerLabel;
    if (marker != null) {
      marker.size = markerEnabled || !lineEnabled ? itemMarker.size : 0;
    }
    const dimensionProps = { length: markerWidth, spacing, isCustomMarker };
    if (markerEnabled || lineEnabled) {
      paddedSymbolWidth += spacing + markerWidth;
    }
    if (marker) {
      const { strokeWidth, fill, stroke, fillOpacity, strokeOpacity } = this.getMarkerStyles(symbol);
      marker.fill = fill;
      marker.stroke = stroke;
      marker.strokeWidth = strokeWidth;
      marker.fillOpacity = fillOpacity;
      marker.strokeOpacity = strokeOpacity;
    }
    if (!lineEnabled && line != null) {
      line.strokeWidth = 0;
    } else if (line) {
      const lineStyles = this.getLineStyles(symbol);
      line.stroke = lineStyles.stroke;
      line.strokeOpacity = lineStyles.strokeOpacity;
      line.strokeWidth = lineStyles.strokeWidth;
      line.lineDash = lineStyles.lineDash;
    }
    markerLabel.update(spriteRenderer, spriteDims, dimensionProps);
    return paddedSymbolWidth;
  }
  truncate(text, maxCharLength, maxItemWidth, paddedMarkerWidth, font, id) {
    let addEllipsis = false;
    if (text.length > maxCharLength) {
      text = text.substring(0, maxCharLength);
      addEllipsis = true;
    }
    const measurer = CachedTextMeasurerPool.getMeasurer({ font });
    const result = TextWrapper.truncateLine(text, measurer, maxItemWidth - paddedMarkerWidth, addEllipsis);
    if (result.endsWith(TextUtils.EllipsisChar)) {
      this.truncatedItems.add(id);
    } else {
      this.truncatedItems.delete(id);
    }
    return result;
  }
  updatePagination(bboxes, width2, height2) {
    const orientation = this.getOrientation();
    const trackingIndex = Math.min(this.paginationTrackingIndex, bboxes.length);
    this.pagination.orientation = orientation;
    this.pagination.translationX = 0;
    this.pagination.translationY = 0;
    const { pages, maxPageHeight, maxPageWidth, paginationBBox, paginationVertical } = this.calculatePagination(
      bboxes,
      width2,
      height2
    );
    const newCurrentPage = pages.findIndex((p) => p.endIndex >= trackingIndex);
    this.pagination.currentPage = clamp(0, newCurrentPage, pages.length - 1);
    const { paddingX: itemPaddingX, paddingY: itemPaddingY } = this.item;
    const paginationComponentPadding = 8;
    const legendItemsWidth = maxPageWidth - itemPaddingX;
    const legendItemsHeight = maxPageHeight - itemPaddingY;
    let paginationX = 0;
    let paginationY = -paginationBBox.y - this.item.marker.size / 2;
    if (paginationVertical) {
      paginationY += legendItemsHeight + paginationComponentPadding;
    } else {
      paginationX += -paginationBBox.x + legendItemsWidth + paginationComponentPadding;
      paginationY += (legendItemsHeight - paginationBBox.height) / 2;
    }
    this.pagination.translationX = paginationX;
    this.pagination.translationY = paginationY;
    this.pagination.update();
    this.pagination.updateMarkers();
    let pageIndex = 0;
    this.itemSelection.each((markerLabel, _, nodeIndex) => {
      if (nodeIndex > (pages[pageIndex]?.endIndex ?? Infinity)) {
        pageIndex++;
      }
      markerLabel.pageIndex = pageIndex;
    });
    return {
      maxPageHeight,
      maxPageWidth,
      pages
    };
  }
  calculatePagination(bboxes, width2, height2) {
    const { paddingX: itemPaddingX, paddingY: itemPaddingY } = this.item;
    const orientation = this.getOrientation();
    const paginationVertical = ["left", "right"].includes(this.position);
    let paginationBBox = this.pagination.getBBox();
    let lastPassPaginationBBox = new BBox(0, 0, 0, 0);
    let pages = [];
    let maxPageWidth = 0;
    let maxPageHeight = 0;
    let count = 0;
    const stableOutput = (bbox) => {
      return bbox.width === paginationBBox.width && bbox.height === paginationBBox.height;
    };
    const forceResult = this.maxWidth !== void 0 && this.maxHeight !== void 0;
    do {
      if (count++ > 10) {
        Logger.warn("unable to find stable legend layout.");
        break;
      }
      paginationBBox = lastPassPaginationBBox;
      const maxWidth = width2 - (paginationVertical ? 0 : paginationBBox.width);
      const maxHeight = height2 - (paginationVertical ? paginationBBox.height : 0);
      const layout = gridLayout({
        orientation,
        bboxes,
        maxHeight,
        maxWidth,
        itemPaddingY,
        itemPaddingX,
        forceResult
      });
      pages = layout?.pages ?? [];
      maxPageWidth = layout?.maxPageWidth ?? 0;
      maxPageHeight = layout?.maxPageHeight ?? 0;
      const totalPages = pages.length;
      this.pagination.visible = totalPages > 1;
      this.pagination.totalPages = totalPages;
      this.pagination.update();
      this.pagination.updateMarkers();
      lastPassPaginationBBox = this.pagination.getBBox();
      if (!this.pagination.visible) {
        break;
      }
    } while (!stableOutput(lastPassPaginationBBox));
    return { maxPageWidth, maxPageHeight, pages, paginationBBox: lastPassPaginationBBox, paginationVertical };
  }
  updatePositions(pageNumber = 0) {
    const {
      item: { paddingY },
      itemSelection,
      pages
    } = this;
    if (pages.length < 1 || !pages[pageNumber]) {
      return;
    }
    const { columns, startIndex: visibleStart, endIndex: visibleEnd } = pages[pageNumber];
    let x = 0;
    let y = 0;
    const columnCount = columns.length;
    const rowCount = columns[0].indices.length;
    const horizontal = this.getOrientation() === "horizontal";
    const itemHeight = columns[0].bboxes[0].height + paddingY;
    const rowSumColumnWidths = [];
    itemSelection.each((markerLabel, _, i) => {
      if (i < visibleStart || i > visibleEnd) {
        markerLabel.visible = false;
        return;
      }
      const pageIndex = i - visibleStart;
      let columnIndex;
      let rowIndex;
      if (horizontal) {
        columnIndex = pageIndex % columnCount;
        rowIndex = Math.floor(pageIndex / columnCount);
      } else {
        columnIndex = Math.floor(pageIndex / rowCount);
        rowIndex = pageIndex % rowCount;
      }
      markerLabel.visible = true;
      const column = columns[columnIndex];
      if (!column) {
        return;
      }
      y = Math.floor(itemHeight * rowIndex);
      x = Math.floor(rowSumColumnWidths[rowIndex] ?? 0);
      rowSumColumnWidths[rowIndex] = (rowSumColumnWidths[rowIndex] ?? 0) + column.columnWidth;
      markerLabel.translationX = x;
      markerLabel.translationY = y;
    });
  }
  updatePageNumber(pageNumber) {
    const { itemSelection, group, pagination, pages, toggleSeries: interactive } = this;
    const { startIndex, endIndex } = pages[pageNumber];
    if (startIndex === 0) {
      this.paginationTrackingIndex = 0;
    } else if (pageNumber === pages.length - 1) {
      this.paginationTrackingIndex = endIndex;
    } else {
      this.paginationTrackingIndex = Math.floor((startIndex + endIndex) / 2);
    }
    this.pagination.update();
    this.pagination.updateMarkers();
    this.updatePositions(pageNumber);
    this.domProxy.onPageChange({ itemSelection, group, pagination, interactive });
    this.ctx.updateService.update(
      6
      /* SCENE_RENDER */
    );
  }
  update() {
    const {
      label: { color }
    } = this.item;
    this.itemSelection.each((markerLabel, datum) => {
      markerLabel.setEnabled(datum.enabled);
      markerLabel.color = color;
    });
    this.updateContextMenu();
  }
  updateContextMenu() {
    const {
      toggleSeries,
      ctx: { contextMenuRegistry }
    } = this;
    if (toggleSeries) {
      contextMenuRegistry.hideAction(ID_LEGEND_VISIBILITY);
      contextMenuRegistry.hideAction(ID_LEGEND_OTHER_SERIES);
    } else {
      contextMenuRegistry.showAction(ID_LEGEND_VISIBILITY);
      contextMenuRegistry.showAction(ID_LEGEND_OTHER_SERIES);
    }
  }
  getLineStyles(datum) {
    const { stroke, strokeOpacity = 1, strokeWidth, lineDash } = datum.line ?? {};
    const defaultLineStrokeWidth = Math.min(2, strokeWidth ?? 1);
    return {
      stroke,
      strokeOpacity,
      strokeWidth: this.item.line.strokeWidth ?? defaultLineStrokeWidth,
      lineDash
    };
  }
  getMarkerStyles(datum) {
    const { fill, stroke, strokeOpacity = 1, fillOpacity = 1, strokeWidth } = datum.marker;
    const defaultLineStrokeWidth = Math.min(2, strokeWidth ?? 1);
    return {
      fill,
      stroke,
      strokeOpacity,
      fillOpacity,
      strokeWidth: this.item.marker.strokeWidth ?? defaultLineStrokeWidth
    };
  }
  computePagedBBox() {
    const actualBBox = Group.computeChildrenBBox(this.group.children());
    if (this.pages.length > 1) {
      const [maxPageWidth, maxPageHeight] = this.maxPageSize;
      actualBBox.height = Math.max(maxPageHeight, actualBBox.height);
      actualBBox.width = Math.max(maxPageWidth, actualBBox.width);
    }
    return actualBBox;
  }
  findNode(params) {
    const { datum, proxyButton } = this.itemSelection.select((ml) => ml.datum?.itemId === params.itemId)[0] ?? {};
    if (datum === void 0 || proxyButton === void 0) {
      throw new Error(
        `AG Charts - Missing required properties { datum: ${datum}, proxyButton: ${JSON.stringify(proxyButton)} }`
      );
    }
    return { datum, proxyButton };
  }
  contextToggleVisibility(params) {
    const { datum, proxyButton } = this.findNode(params);
    this.doClick(params.event, datum, proxyButton);
  }
  contextToggleOtherSeries(params) {
    this.doDoubleClick(params.event, this.findNode(params).datum);
  }
  onContextClick(sourceEvent, node) {
    const legendItem = node.datum;
    if (this.preventHidingAll && this.contextMenuDatum?.enabled && this.getVisibleItemCount() <= 1) {
      this.ctx.contextMenuRegistry.disableAction(ID_LEGEND_VISIBILITY);
    } else {
      this.ctx.contextMenuRegistry.enableAction(ID_LEGEND_VISIBILITY);
    }
    const { offsetX, offsetY } = sourceEvent;
    const { x: canvasX, y: canvasY } = Transformable.toCanvasPoint(node, offsetX, offsetY);
    this.ctx.contextMenuRegistry.dispatchContext("legend", { sourceEvent, canvasX, canvasY }, { legendItem });
  }
  onClick(event, datum, proxyButton) {
    if (this.doClick(event, datum, proxyButton)) {
      event.preventDefault();
    }
  }
  getVisibleItemCount() {
    return this.ctx.chartService.series.flatMap((s) => s.getLegendData("category")).filter((d) => d.enabled).length;
  }
  doClick(event, datum, proxyButton) {
    const {
      listeners: { legendItemClick },
      ctx: { chartService, highlightManager },
      preventHidingAll,
      toggleSeries
    } = this;
    if (!datum) {
      return false;
    }
    const { legendType, seriesId, itemId, enabled } = datum;
    const series = chartService.series.find((s) => s.id === seriesId);
    if (!series) {
      return false;
    }
    let newEnabled = enabled;
    const clickEvent = makeLegendItemEvent("click", itemId, series.id, event);
    legendItemClick?.(clickEvent.apiEvent);
    if (clickEvent.defaultPrevented)
      return true;
    if (toggleSeries) {
      newEnabled = !enabled;
      if (preventHidingAll && !newEnabled) {
        const numVisibleItems = this.getVisibleItemCount();
        if (numVisibleItems < 2) {
          newEnabled = true;
        }
      }
      proxyButton.setChecked(newEnabled);
      this.ctx.chartEventManager.legendItemClick(legendType, series, itemId, newEnabled, datum.legendItemName);
    }
    if (newEnabled) {
      highlightManager.updateHighlight(this.id, {
        series,
        itemId,
        datum: void 0
      });
    } else {
      highlightManager.updateHighlight(this.id);
    }
    this.ctx.legendManager.update();
    this.ctx.updateService.update(2, {
      forceNodeDataRefresh: true,
      skipAnimations: datum.skipAnimations ?? false
    });
    return true;
  }
  onDoubleClick(event, datum) {
    if (this.doDoubleClick(event, datum)) {
      event.preventDefault();
    }
  }
  doDoubleClick(event, datum) {
    const {
      listeners: { legendItemDoubleClick },
      ctx: { chartService },
      toggleSeries
    } = this;
    if (chartService.mode === "integrated") {
      return false;
    }
    if (!datum) {
      return false;
    }
    const { legendType, id, itemId, seriesId } = datum;
    const series = chartService.series.find((s) => s.id === id);
    if (!series) {
      return false;
    }
    const doubleClickEvent = makeLegendItemEvent("dblclick", itemId, series.id, event);
    legendItemDoubleClick?.(doubleClickEvent.apiEvent);
    if (doubleClickEvent.defaultPrevented)
      return true;
    if (toggleSeries) {
      const legendData = chartService.series.flatMap((s) => s.getLegendData("category"));
      const numVisibleItems = legendData.filter((d) => d.enabled).length;
      const clickedItem = legendData.find((d) => d.itemId === itemId && d.seriesId === seriesId);
      this.ctx.chartEventManager.legendItemDoubleClick(
        legendType,
        series,
        itemId,
        clickedItem?.enabled ?? false,
        numVisibleItems,
        clickedItem?.legendItemName
      );
    }
    this.ctx.legendManager.update();
    this.ctx.updateService.update(2, { forceNodeDataRefresh: true });
    return true;
  }
  toTooltipMeta(event, node) {
    let lastPointerEvent;
    if (event instanceof FocusEvent) {
      const { x, y } = Transformable.toCanvas(node).computeCenter();
      lastPointerEvent = { type: "keyboard", canvasX: x, canvasY: y };
    } else {
      event.preventDefault();
      const { x, y } = Transformable.toCanvasPoint(node, event.offsetX, event.offsetY);
      lastPointerEvent = { type: "hover", canvasX: x, canvasY: y };
    }
    const { canvasX, canvasY } = lastPointerEvent;
    return { canvasX, canvasY, lastPointerEvent, showArrow: false };
  }
  onHover(event, node) {
    if (!this.enabled)
      throw new Error("AG Charts - onHover handler called on disabled legend");
    this.pagination.setPage(node.pageIndex);
    const datum = node.datum;
    const series = datum ? this.ctx.chartService.series.find((s) => s.id === datum?.id) : void 0;
    if (datum && this.truncatedItems.has(datum.itemId ?? datum.id)) {
      const meta = this.toTooltipMeta(event, node);
      this.ctx.tooltipManager.updateTooltip(this.id, meta, { title: this.getItemLabel(datum) });
    } else {
      this.ctx.tooltipManager.removeTooltip(this.id);
    }
    if (datum?.enabled && series) {
      this.updateHighlight({ series, itemId: datum?.itemId, datum: void 0 });
    } else {
      this.updateHighlight();
    }
  }
  onLeave() {
    this.ctx.tooltipManager.removeTooltip(this.id);
    this.updateHighlight();
  }
  updateHighlight(datum) {
    const state = this.ctx.interactionManager.getState();
    if (state === 32) {
      this.ctx.highlightManager.updateHighlight(this.id, datum);
    } else if (state === 2) {
      this.pendingHighlightDatum = datum;
      this.ctx.animationManager.onBatchStop(() => {
        this.ctx.highlightManager.updateHighlight(this.id, this.pendingHighlightDatum);
      });
    }
  }
  onLocaleChanged() {
    this.domProxy.onLocaleChanged(this.ctx.localeManager, this.itemSelection, this);
  }
  positionLegend(ctx) {
    const oldPages = this.positionLegendScene(ctx);
    this.positionLegendDOM(oldPages);
  }
  positionLegendScene(ctx) {
    if (!this.enabled || !this.data.length)
      return;
    const { layoutBox } = ctx;
    const { x, y, width: width2, height: height2 } = layoutBox;
    const [legendWidth, legendHeight] = this.calculateLegendDimensions(layoutBox);
    const { oldPages } = this.calcLayout(legendWidth, legendHeight);
    const legendBBox = this.computePagedBBox();
    const calculateTranslationPerpendicularDimension = () => {
      switch (this.position) {
        case "top":
        case "left":
          return 0;
        case "bottom":
          return height2 - legendBBox.height;
        case "right":
        default:
          return width2 - legendBBox.width;
      }
    };
    if (this.visible) {
      const legendPadding = this.spacing;
      let translationX;
      let translationY;
      switch (this.position) {
        case "top":
        case "bottom":
          translationX = (width2 - legendBBox.width) / 2;
          translationY = calculateTranslationPerpendicularDimension();
          layoutBox.shrink(legendBBox.height + legendPadding, this.position);
          break;
        case "left":
        case "right":
        default:
          translationX = calculateTranslationPerpendicularDimension();
          translationY = (height2 - legendBBox.height) / 2;
          layoutBox.shrink(legendBBox.width + legendPadding, this.position);
      }
      this.group.translationX = Math.floor(x + translationX - legendBBox.x);
      this.group.translationY = Math.floor(y + translationY - legendBBox.y);
    }
    return oldPages;
  }
  positionLegendDOM(oldPages) {
    const { ctx, itemSelection, pagination, pages: newPages, toggleSeries: interactive, group } = this;
    const visible = this.visible && this.enabled;
    this.domProxy.update({
      visible,
      interactive,
      ctx,
      itemSelection,
      group,
      pagination,
      oldPages,
      newPages,
      datumReader: this,
      itemListener: this
    });
  }
  calculateLegendDimensions(shrinkRect) {
    const { width: width2, height: height2 } = shrinkRect;
    const aspectRatio = width2 / height2;
    const maxCoefficient = 0.5;
    const minHeightCoefficient = 0.2;
    const minWidthCoefficient = 0.25;
    let legendWidth, legendHeight;
    switch (this.position) {
      case "top":
      case "bottom": {
        const heightCoefficient = aspectRatio < 1 ? Math.min(maxCoefficient, minHeightCoefficient * (1 / aspectRatio)) : minHeightCoefficient;
        legendWidth = this.maxWidth ? Math.min(this.maxWidth, width2) : width2;
        legendHeight = this.maxHeight ? Math.min(this.maxHeight, height2) : Math.round(height2 * heightCoefficient);
        break;
      }
      case "left":
      case "right":
      default: {
        const widthCoefficient = aspectRatio > 1 ? Math.min(maxCoefficient, minWidthCoefficient * aspectRatio) : minWidthCoefficient;
        legendWidth = this.maxWidth ? Math.min(this.maxWidth, width2) : Math.round(width2 * widthCoefficient);
        legendHeight = this.maxHeight ? Math.min(this.maxHeight, height2) : height2;
      }
    }
    return [legendWidth, legendHeight];
  }
};
Legend.className = "Legend";
__decorateClass([
  Validate(BOOLEAN)
], Legend.prototype, "toggleSeries", 2);
__decorateClass([
  Validate(OBJECT)
], Legend.prototype, "pagination", 2);
__decorateClass([
  Validate(OBJECT)
], Legend.prototype, "item", 2);
__decorateClass([
  Validate(OBJECT)
], Legend.prototype, "listeners", 2);
__decorateClass([
  ObserveChanges((target, newValue, oldValue) => {
    target.updateGroupVisibility();
    if (newValue === oldValue) {
      return;
    }
    const {
      ctx: { legendManager, stateManager }
    } = target;
    if (oldValue === false && newValue === true) {
      stateManager.restoreState(legendManager);
    }
  }),
  Validate(BOOLEAN)
], Legend.prototype, "enabled", 2);
__decorateClass([
  Validate(POSITION)
], Legend.prototype, "position", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], Legend.prototype, "maxWidth", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], Legend.prototype, "maxHeight", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], Legend.prototype, "reverseOrder", 2);
__decorateClass([
  Validate(UNION(["horizontal", "vertical"], "an orientation"), { optional: true })
], Legend.prototype, "orientation", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], Legend.prototype, "preventHidingAll", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], Legend.prototype, "spacing", 2);
var CommunityLegendModule = {
  type: "legend",
  optionsKey: "legend",
  identifier: "category",
  chartTypes: ["cartesian", "polar", "hierarchy", "topology", "flow-proportion", "standalone", "gauge"],
  moduleFactory: (ctx) => new Legend(ctx),
  packageType: "community",
  removable: "standalone-only"
};
var constants_exports = {};
__export(constants_exports, {
  CARTESIAN_AXIS_TYPE: () => CARTESIAN_AXIS_TYPE,
  CARTESIAN_POSITION: () => CARTESIAN_POSITION,
  FONT_SIZE: () => FONT_SIZE,
  POLAR_AXIS_SHAPE: () => POLAR_AXIS_SHAPE,
  POLAR_AXIS_TYPE: () => POLAR_AXIS_TYPE
});
var FONT_SIZE = /* @__PURE__ */ ((FONT_SIZE2) => {
  FONT_SIZE2[FONT_SIZE2["SMALL"] = 12] = "SMALL";
  FONT_SIZE2[FONT_SIZE2["MEDIUM"] = 13] = "MEDIUM";
  FONT_SIZE2[FONT_SIZE2["LARGE"] = 17] = "LARGE";
  return FONT_SIZE2;
})(FONT_SIZE || {});
var CARTESIAN_POSITION = /* @__PURE__ */ ((CARTESIAN_POSITION2) => {
  CARTESIAN_POSITION2["TOP"] = "top";
  CARTESIAN_POSITION2["RIGHT"] = "right";
  CARTESIAN_POSITION2["BOTTOM"] = "bottom";
  CARTESIAN_POSITION2["LEFT"] = "left";
  return CARTESIAN_POSITION2;
})(CARTESIAN_POSITION || {});
var CARTESIAN_AXIS_TYPE = /* @__PURE__ */ ((CARTESIAN_AXIS_TYPE2) => {
  CARTESIAN_AXIS_TYPE2["CATEGORY"] = "category";
  CARTESIAN_AXIS_TYPE2["GROUPED_CATEGORY"] = "grouped-category";
  CARTESIAN_AXIS_TYPE2["ORDINAL_TIME"] = "ordinal-time";
  CARTESIAN_AXIS_TYPE2["NUMBER"] = "number";
  CARTESIAN_AXIS_TYPE2["TIME"] = "time";
  CARTESIAN_AXIS_TYPE2["LOG"] = "log";
  return CARTESIAN_AXIS_TYPE2;
})(CARTESIAN_AXIS_TYPE || {});
var POLAR_AXIS_TYPE = /* @__PURE__ */ ((POLAR_AXIS_TYPE2) => {
  POLAR_AXIS_TYPE2["ANGLE_CATEGORY"] = "angle-category";
  POLAR_AXIS_TYPE2["ANGLE_NUMBER"] = "angle-number";
  POLAR_AXIS_TYPE2["RADIUS_CATEGORY"] = "radius-category";
  POLAR_AXIS_TYPE2["RADIUS_NUMBER"] = "radius-number";
  return POLAR_AXIS_TYPE2;
})(POLAR_AXIS_TYPE || {});
var POLAR_AXIS_SHAPE = /* @__PURE__ */ ((POLAR_AXIS_SHAPE2) => {
  POLAR_AXIS_SHAPE2["CIRCLE"] = "circle";
  POLAR_AXIS_SHAPE2["POLYGON"] = "polygon";
  return POLAR_AXIS_SHAPE2;
})(POLAR_AXIS_SHAPE || {});
var symbols_exports = {};
__export(symbols_exports, {
  DEFAULT_ANNOTATION_BACKGROUND_FILL: () => DEFAULT_ANNOTATION_BACKGROUND_FILL,
  DEFAULT_ANNOTATION_COLOR: () => DEFAULT_ANNOTATION_COLOR,
  DEFAULT_ANNOTATION_HANDLE_FILL: () => DEFAULT_ANNOTATION_HANDLE_FILL,
  DEFAULT_ANNOTATION_STATISTICS_COLOR: () => DEFAULT_ANNOTATION_STATISTICS_COLOR,
  DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE: () => DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE,
  DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL: () => DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL,
  DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE: () => DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE,
  DEFAULT_ANNOTATION_STATISTICS_FILL: () => DEFAULT_ANNOTATION_STATISTICS_FILL,
  DEFAULT_ANNOTATION_STATISTICS_STROKE: () => DEFAULT_ANNOTATION_STATISTICS_STROKE,
  DEFAULT_AXIS_GRID_COLOUR: () => DEFAULT_AXIS_GRID_COLOUR,
  DEFAULT_AXIS_LINE_COLOUR: () => DEFAULT_AXIS_LINE_COLOUR,
  DEFAULT_BACKGROUND_COLOUR: () => DEFAULT_BACKGROUND_COLOUR,
  DEFAULT_CAPTION_ALIGNMENT: () => DEFAULT_CAPTION_ALIGNMENT,
  DEFAULT_CAPTION_LAYOUT_STYLE: () => DEFAULT_CAPTION_LAYOUT_STYLE,
  DEFAULT_COLOURS: () => DEFAULT_COLOURS,
  DEFAULT_CROSS_LINES_COLOUR: () => DEFAULT_CROSS_LINES_COLOUR,
  DEFAULT_DIVERGING_SERIES_COLOR_RANGE: () => DEFAULT_DIVERGING_SERIES_COLOR_RANGE,
  DEFAULT_FIBONACCI_STROKES: () => DEFAULT_FIBONACCI_STROKES,
  DEFAULT_FONT_FAMILY: () => DEFAULT_FONT_FAMILY,
  DEFAULT_FUNNEL_SERIES_COLOR_RANGE: () => DEFAULT_FUNNEL_SERIES_COLOR_RANGE,
  DEFAULT_GAUGE_SERIES_COLOR_RANGE: () => DEFAULT_GAUGE_SERIES_COLOR_RANGE,
  DEFAULT_GRIDLINE_ENABLED: () => DEFAULT_GRIDLINE_ENABLED,
  DEFAULT_HIERARCHY_FILLS: () => DEFAULT_HIERARCHY_FILLS,
  DEFAULT_HIERARCHY_STROKES: () => DEFAULT_HIERARCHY_STROKES,
  DEFAULT_INSIDE_SERIES_LABEL_COLOUR: () => DEFAULT_INSIDE_SERIES_LABEL_COLOUR,
  DEFAULT_INVERTED_BACKGROUND_COLOUR: () => DEFAULT_INVERTED_BACKGROUND_COLOUR,
  DEFAULT_INVERTED_LABEL_COLOUR: () => DEFAULT_INVERTED_LABEL_COLOUR,
  DEFAULT_LABEL_COLOUR: () => DEFAULT_LABEL_COLOUR,
  DEFAULT_MUTED_LABEL_COLOUR: () => DEFAULT_MUTED_LABEL_COLOUR,
  DEFAULT_NAVIGATOR_STROKE: () => DEFAULT_NAVIGATOR_STROKE,
  DEFAULT_PADDING: () => DEFAULT_PADDING,
  DEFAULT_POLAR_SERIES_STROKE: () => DEFAULT_POLAR_SERIES_STROKE,
  DEFAULT_SEPARATION_LINES_COLOUR: () => DEFAULT_SEPARATION_LINES_COLOUR,
  DEFAULT_SHADOW_COLOUR: () => DEFAULT_SHADOW_COLOUR,
  DEFAULT_SPARKLINE_CROSSHAIR_STROKE: () => DEFAULT_SPARKLINE_CROSSHAIR_STROKE,
  DEFAULT_TEXTBOX_COLOR: () => DEFAULT_TEXTBOX_COLOR,
  DEFAULT_TEXTBOX_FILL: () => DEFAULT_TEXTBOX_FILL,
  DEFAULT_TEXTBOX_STROKE: () => DEFAULT_TEXTBOX_STROKE,
  DEFAULT_TEXT_ANNOTATION_COLOR: () => DEFAULT_TEXT_ANNOTATION_COLOR,
  DEFAULT_TOOLBAR_POSITION: () => DEFAULT_TOOLBAR_POSITION,
  IS_COMMUNITY: () => IS_COMMUNITY,
  IS_DARK_THEME: () => IS_DARK_THEME,
  IS_ENTERPRISE: () => IS_ENTERPRISE,
  PALETTE_ALT_DOWN_FILL: () => PALETTE_ALT_DOWN_FILL,
  PALETTE_ALT_DOWN_STROKE: () => PALETTE_ALT_DOWN_STROKE,
  PALETTE_ALT_NEUTRAL_FILL: () => PALETTE_ALT_NEUTRAL_FILL,
  PALETTE_ALT_NEUTRAL_STROKE: () => PALETTE_ALT_NEUTRAL_STROKE,
  PALETTE_ALT_UP_FILL: () => PALETTE_ALT_UP_FILL,
  PALETTE_ALT_UP_STROKE: () => PALETTE_ALT_UP_STROKE,
  PALETTE_DOWN_FILL: () => PALETTE_DOWN_FILL,
  PALETTE_DOWN_STROKE: () => PALETTE_DOWN_STROKE,
  PALETTE_NEUTRAL_FILL: () => PALETTE_NEUTRAL_FILL,
  PALETTE_NEUTRAL_STROKE: () => PALETTE_NEUTRAL_STROKE,
  PALETTE_UP_FILL: () => PALETTE_UP_FILL,
  PALETTE_UP_STROKE: () => PALETTE_UP_STROKE
});
var IS_DARK_THEME = Symbol("is-dark-theme");
var IS_COMMUNITY = Symbol("is-community");
var IS_ENTERPRISE = Symbol("is-enterprise");
var DEFAULT_FONT_FAMILY = Symbol("default-font");
var DEFAULT_LABEL_COLOUR = Symbol("default-label-colour");
var DEFAULT_INVERTED_LABEL_COLOUR = Symbol("default-inverted-label-colour");
var DEFAULT_INSIDE_SERIES_LABEL_COLOUR = Symbol("default-inside-series-label-colour");
var DEFAULT_MUTED_LABEL_COLOUR = Symbol("default-muted-label-colour");
var DEFAULT_AXIS_GRID_COLOUR = Symbol("default-axis-grid-colour");
var DEFAULT_AXIS_LINE_COLOUR = Symbol("default-axis-line-colour");
var DEFAULT_CROSS_LINES_COLOUR = Symbol("default-cross-lines-colour");
var DEFAULT_SEPARATION_LINES_COLOUR = Symbol("default-separation-lines-colour");
var DEFAULT_BACKGROUND_COLOUR = Symbol("default-background-colour");
var DEFAULT_INVERTED_BACKGROUND_COLOUR = Symbol("default-inverted-background-colour");
var DEFAULT_SHADOW_COLOUR = Symbol("default-shadow-colour");
var DEFAULT_COLOURS = Symbol("default-colours");
var DEFAULT_PADDING = Symbol("default-padding");
var DEFAULT_CAPTION_LAYOUT_STYLE = Symbol("default-caption-layout-style");
var DEFAULT_CAPTION_ALIGNMENT = Symbol("default-caption-alignment");
var DEFAULT_NAVIGATOR_STROKE = Symbol("default-navigator-stroke");
var PALETTE_UP_STROKE = Symbol("palette-up-stroke");
var PALETTE_DOWN_STROKE = Symbol("palette-down-stroke");
var PALETTE_UP_FILL = Symbol("palette-up-fill");
var PALETTE_DOWN_FILL = Symbol("palette-down-fill");
var PALETTE_NEUTRAL_STROKE = Symbol("palette-neutral-stroke");
var PALETTE_NEUTRAL_FILL = Symbol("palette-neutral-fill");
var PALETTE_ALT_UP_STROKE = Symbol("palette-alt-up-stroke");
var PALETTE_ALT_DOWN_STROKE = Symbol("palette-alt-down-stroke");
var PALETTE_ALT_UP_FILL = Symbol("palette-alt-up-fill");
var PALETTE_ALT_DOWN_FILL = Symbol("palette-alt-down-fill");
var PALETTE_ALT_NEUTRAL_FILL = Symbol("palette-gray-fill");
var PALETTE_ALT_NEUTRAL_STROKE = Symbol("palette-gray-stroke");
var DEFAULT_POLAR_SERIES_STROKE = Symbol("default-polar-series-stroke");
var DEFAULT_DIVERGING_SERIES_COLOR_RANGE = Symbol(
  "default-diverging-series-colour-range"
);
var DEFAULT_SPARKLINE_CROSSHAIR_STROKE = Symbol("default-sparkline-crosshair-stroke");
var DEFAULT_GAUGE_SERIES_COLOR_RANGE = Symbol("default-gauge-series-colour-range");
var DEFAULT_FUNNEL_SERIES_COLOR_RANGE = Symbol("default-funnel-series-colour-range");
var DEFAULT_HIERARCHY_FILLS = Symbol("default-hierarchy-fills");
var DEFAULT_HIERARCHY_STROKES = Symbol("default-hierarchy-strokes");
var DEFAULT_ANNOTATION_COLOR = Symbol("default-annotation-stroke");
var DEFAULT_FIBONACCI_STROKES = Symbol("default-hierarchy-strokes");
var DEFAULT_TEXT_ANNOTATION_COLOR = Symbol("default-text-annotation-color");
var DEFAULT_ANNOTATION_BACKGROUND_FILL = Symbol("default-annotation-background-fill");
var DEFAULT_ANNOTATION_HANDLE_FILL = Symbol("default-annotation-handle-fill");
var DEFAULT_ANNOTATION_STATISTICS_FILL = Symbol("default-annotation-statistics-fill");
var DEFAULT_ANNOTATION_STATISTICS_STROKE = Symbol("default-annotation-statistics-stroke");
var DEFAULT_ANNOTATION_STATISTICS_COLOR = Symbol("default-annotation-statistics-color");
var DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE = Symbol(
  "default-annotation-statistics-divider-stroke"
);
var DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL = Symbol(
  "default-annotation-statistics-fill"
);
var DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE = Symbol(
  "default-annotation-statistics-stroke"
);
var DEFAULT_TEXTBOX_FILL = Symbol("default-textbox-fill");
var DEFAULT_TEXTBOX_STROKE = Symbol("default-textbox-stroke");
var DEFAULT_TEXTBOX_COLOR = Symbol("default-textbox-color");
var DEFAULT_TOOLBAR_POSITION = Symbol("default-toolbar-position");
var DEFAULT_GRIDLINE_ENABLED = Symbol("default-gridline-enabled");
function swapAxisCondition(axes, swap) {
  return (series) => {
    if (!swap(series))
      return axes;
    return [
      { ...axes[0], position: axes[1].position },
      { ...axes[1], position: axes[0].position }
    ];
  };
}
function singleSeriesPaletteFactory({ takeColors }) {
  const {
    fills: [fill],
    strokes: [stroke]
  } = takeColors(1);
  return { fill, stroke };
}
function markerPaletteFactory(params) {
  return { marker: singleSeriesPaletteFactory(params) };
}
function pathMotion(groupId, subId, animationManager, paths, fns) {
  const { addPhaseFn, updatePhaseFn, removePhaseFn } = fns;
  const animate = (phase, path, updateFn) => {
    animationManager.animate({
      id: `${groupId}_${subId}_${path.id}_${phase}`,
      groupId,
      from: 0,
      to: 1,
      ease: easeOut,
      collapsable: false,
      onUpdate(ratio2, preInit) {
        if (preInit && phase !== "removed")
          return;
        path.path.clear(true);
        updateFn(ratio2, path);
        path.checkPathDirty();
      },
      onStop() {
        if (phase !== "added")
          return;
        path.path.clear(true);
        updateFn(1, path);
        path.checkPathDirty();
      },
      phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[phase]
    });
  };
  for (const path of paths) {
    if (!animationManager.isSkipped()) {
      animate("removed", path, removePhaseFn);
      animate("updated", path, updatePhaseFn);
    }
    animate("added", path, addPhaseFn);
  }
}
function seriesLabelFadeInAnimation({ id }, subId, animationManager, ...labelSelections) {
  staticFromToMotion(
    id,
    subId,
    animationManager,
    labelSelections,
    { opacity: 0 },
    { opacity: 1 },
    { phase: "trailing" }
  );
}
function seriesLabelFadeOutAnimation({ id }, subId, animationManager, ...labelSelections) {
  staticFromToMotion(
    id,
    subId,
    animationManager,
    labelSelections,
    { opacity: 1 },
    { opacity: 0 },
    { phase: "remove" }
  );
}
function resetLabelFn(_node) {
  return { opacity: 1 };
}
var ChangeDetectableProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this._dirty = true;
  }
  markDirty() {
    this._dirty = true;
  }
  markClean(_opts) {
    this._dirty = false;
  }
  isDirty() {
    return this._dirty;
  }
};
var DropShadow = class extends ChangeDetectableProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
    this.color = "rgba(0, 0, 0, 0.5)";
    this.xOffset = 0;
    this.yOffset = 0;
    this.blur = 5;
  }
};
__decorateClass([
  Validate(BOOLEAN),
  SceneChangeDetection()
], DropShadow.prototype, "enabled", 2);
__decorateClass([
  Validate(COLOR_STRING),
  SceneChangeDetection()
], DropShadow.prototype, "color", 2);
__decorateClass([
  Validate(NUMBER),
  SceneChangeDetection()
], DropShadow.prototype, "xOffset", 2);
__decorateClass([
  Validate(NUMBER),
  SceneChangeDetection()
], DropShadow.prototype, "yOffset", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER),
  SceneChangeDetection()
], DropShadow.prototype, "blur", 2);
var MARKER_SHAPE = predicateWithMessage(
  (value) => isSupportedMarkerShape(value) || typeof value === "function",
  `a marker shape keyword such as 'circle', 'diamond' or 'square' or an object extending the Marker class`
);
var SeriesMarker = class extends ChangeDetectableProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
    this.shape = "circle";
    this.size = 6;
    this.fillOpacity = 1;
    this.strokeWidth = 1;
    this.strokeOpacity = 1;
  }
  getStyle() {
    const { size, shape, fill, fillOpacity, stroke, strokeWidth, strokeOpacity } = this;
    return { size, shape, fill, fillOpacity, stroke, strokeWidth, strokeOpacity };
  }
  getDiameter() {
    return this.size + this.strokeWidth;
  }
};
__decorateClass([
  Validate(BOOLEAN),
  SceneChangeDetection()
], SeriesMarker.prototype, "enabled", 2);
__decorateClass([
  Validate(MARKER_SHAPE),
  SceneChangeDetection()
], SeriesMarker.prototype, "shape", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER),
  SceneChangeDetection()
], SeriesMarker.prototype, "size", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true }),
  SceneChangeDetection()
], SeriesMarker.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO),
  SceneChangeDetection()
], SeriesMarker.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true }),
  SceneChangeDetection()
], SeriesMarker.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER),
  SceneChangeDetection()
], SeriesMarker.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO),
  SceneChangeDetection()
], SeriesMarker.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true }),
  SceneChangeDetection()
], SeriesMarker.prototype, "itemStyler", 2);
var SeriesTooltipInteraction = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = false;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], SeriesTooltipInteraction.prototype, "enabled", 2);
var SeriesTooltip = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.enabled = true;
    this.interaction = new SeriesTooltipInteraction();
    this.position = new TooltipPosition();
    this.range = void 0;
    this.class = void 0;
  }
  formatTooltip(content, params) {
    const overrides = this.renderer?.(params);
    if (typeof overrides === "string")
      return overrides;
    if (overrides != null)
      return { ...content, ...overrides };
    return content;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], SeriesTooltip.prototype, "enabled", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], SeriesTooltip.prototype, "showArrow", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], SeriesTooltip.prototype, "renderer", 2);
__decorateClass([
  Validate(OBJECT)
], SeriesTooltip.prototype, "interaction", 2);
__decorateClass([
  Validate(OBJECT)
], SeriesTooltip.prototype, "position", 2);
__decorateClass([
  Validate(INTERACTION_RANGE, { optional: true })
], SeriesTooltip.prototype, "range", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], SeriesTooltip.prototype, "class", 2);
var INTERPOLATION_TYPE = UNION(["linear", "smooth", "step"], "a line style");
var INTERPOLATION_STEP_POSITION = UNION(["start", "middle", "end"]);
var InterpolationProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.type = "linear";
    this.tension = 1;
    this.position = "end";
  }
};
__decorateClass([
  Validate(INTERPOLATION_TYPE)
], InterpolationProperties.prototype, "type", 2);
__decorateClass([
  Validate(RATIO)
], InterpolationProperties.prototype, "tension", 2);
__decorateClass([
  Validate(INTERPOLATION_STEP_POSITION)
], InterpolationProperties.prototype, "position", 2);
var AreaSeriesProperties = class extends CartesianSeriesProperties {
  constructor() {
    super(...arguments);
    this.xName = void 0;
    this.fill = "#c16068";
    this.fillOpacity = 1;
    this.stroke = "#874349";
    this.strokeWidth = 2;
    this.strokeOpacity = 1;
    this.lineDash = [0];
    this.lineDashOffset = 0;
    this.interpolation = new InterpolationProperties();
    this.shadow = new DropShadow();
    this.marker = new SeriesMarker();
    this.label = new Label();
    this.tooltip = new SeriesTooltip();
    this.connectMissingData = false;
  }
};
__decorateClass([
  Validate(STRING)
], AreaSeriesProperties.prototype, "xKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], AreaSeriesProperties.prototype, "xName", 2);
__decorateClass([
  Validate(STRING)
], AreaSeriesProperties.prototype, "yKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], AreaSeriesProperties.prototype, "yName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], AreaSeriesProperties.prototype, "yFilterKey", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], AreaSeriesProperties.prototype, "normalizedTo", 2);
__decorateClass([
  Validate(COLOR_STRING)
], AreaSeriesProperties.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO)
], AreaSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING)
], AreaSeriesProperties.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AreaSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO)
], AreaSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH)
], AreaSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], AreaSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
  Validate(OBJECT)
], AreaSeriesProperties.prototype, "interpolation", 2);
__decorateClass([
  Validate(OBJECT)
], AreaSeriesProperties.prototype, "shadow", 2);
__decorateClass([
  Validate(OBJECT)
], AreaSeriesProperties.prototype, "marker", 2);
__decorateClass([
  Validate(OBJECT)
], AreaSeriesProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], AreaSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
  Validate(BOOLEAN)
], AreaSeriesProperties.prototype, "connectMissingData", 2);
function spanRange(span) {
  switch (span.type) {
    case "linear":
    case "step":
      return [
        { x: span.x0, y: span.y0 },
        { x: span.x1, y: span.y1 }
      ];
    case "cubic":
      return [
        { x: span.cp0x, y: span.cp0y },
        { x: span.cp3x, y: span.cp3y }
      ];
  }
}
function spanRangeNormalized(span) {
  const range3 = spanRange(span);
  if (range3[0].x > range3[1].x) {
    range3.reverse();
  }
  return range3;
}
function collapseSpanToPoint(span, point) {
  const { x, y } = point;
  switch (span.type) {
    case "linear":
      return {
        type: "linear",
        moveTo: span.moveTo,
        x0: x,
        y0: y,
        x1: x,
        y1: y
      };
    case "step":
      return {
        type: "step",
        moveTo: span.moveTo,
        x0: x,
        y0: y,
        x1: x,
        y1: y,
        stepX: x
      };
    case "cubic":
      return {
        type: "cubic",
        moveTo: span.moveTo,
        cp0x: x,
        cp0y: y,
        cp1x: x,
        cp1y: y,
        cp2x: x,
        cp2y: y,
        cp3x: x,
        cp3y: y
      };
  }
}
function rescaleSpan(span, nextStart, nextEnd) {
  const [prevStart, prevEnd] = spanRange(span);
  const widthScale = prevEnd.x !== prevStart.x ? (nextEnd.x - nextStart.x) / (prevEnd.x - prevStart.x) : 0;
  const heightScale = prevEnd.y !== prevStart.y ? (nextEnd.y - nextStart.y) / (prevEnd.y - prevStart.y) : 0;
  switch (span.type) {
    case "linear":
      return {
        type: "linear",
        moveTo: span.moveTo,
        x0: nextStart.x,
        y0: nextStart.y,
        x1: nextEnd.x,
        y1: nextEnd.y
      };
    case "cubic":
      return {
        type: "cubic",
        moveTo: span.moveTo,
        cp0x: nextStart.x,
        cp0y: nextStart.y,
        cp1x: nextEnd.x - (span.cp2x - prevStart.x) * widthScale,
        cp1y: nextEnd.y - (span.cp2y - prevStart.y) * heightScale,
        cp2x: nextEnd.x - (span.cp1x - prevStart.x) * widthScale,
        cp2y: nextEnd.y - (span.cp1y - prevStart.y) * heightScale,
        cp3x: nextEnd.x,
        cp3y: nextEnd.y
      };
    case "step":
      return {
        type: "step",
        moveTo: span.moveTo,
        x0: nextStart.x,
        y0: nextStart.y,
        x1: nextEnd.x,
        y1: nextEnd.y,
        stepX: nextEnd.x - (span.stepX - prevStart.x) * widthScale
      };
  }
}
function clipSpanX(span, x0, x1) {
  const { moveTo } = span;
  const [start2, end2] = spanRangeNormalized(span);
  const { x: spanX0, y: spanY0 } = start2;
  const { x: spanX1, y: spanY1 } = end2;
  if (x1 < spanX0) {
    return rescaleSpan(span, start2, start2);
  } else if (x0 > spanX1) {
    return rescaleSpan(span, end2, end2);
  }
  switch (span.type) {
    case "linear": {
      const m = spanY0 === spanY1 ? void 0 : (spanY1 - spanY0) / (spanX1 - spanX0);
      const y0 = m == null ? spanY0 : m * (x0 - spanX0) + spanY0;
      const y1 = m == null ? spanY0 : m * (x1 - spanX0) + spanY0;
      return { type: "linear", moveTo, x0, y0, x1, y1 };
    }
    case "step":
      if (x1 <= span.stepX) {
        const y = span.y0;
        return { type: "step", moveTo, x0, y0: y, x1, y1: y, stepX: x1 };
      } else if (x0 >= span.stepX) {
        const y = span.y1;
        return { type: "step", moveTo, x0, y0: y, x1, y1: y, stepX: x0 };
      } else {
        const { y0, y1, stepX } = span;
        return { type: "step", moveTo, x0, y0, x1, y1, stepX };
      }
    case "cubic": {
      const t0 = solveBezier(span.cp0x, span.cp1x, span.cp2x, span.cp3x, x0);
      let [_unused, bezier] = splitBezier(
        span.cp0x,
        span.cp0y,
        span.cp1x,
        span.cp1y,
        span.cp2x,
        span.cp2y,
        span.cp3x,
        span.cp3y,
        t0
      );
      const t1 = solveBezier(bezier[0].x, bezier[1].x, bezier[2].x, bezier[3].x, x1);
      [bezier, _unused] = splitBezier(
        bezier[0].x,
        bezier[0].y,
        bezier[1].x,
        bezier[1].y,
        bezier[2].x,
        bezier[2].y,
        bezier[3].x,
        bezier[3].y,
        t1
      );
      return {
        type: "cubic",
        moveTo,
        cp0x: bezier[0].x,
        cp0y: bezier[0].y,
        cp1x: bezier[1].x,
        cp1y: bezier[1].y,
        cp2x: bezier[2].x,
        cp2y: bezier[2].y,
        cp3x: bezier[3].x,
        cp3y: bezier[3].y
      };
    }
  }
}
function linearPoints(points) {
  const spans = [];
  let i = 0;
  let x0 = NaN;
  let y0 = NaN;
  for (const { x: x1, y: y1 } of points) {
    if (i > 0) {
      const moveTo = i === 1;
      spans.push({ type: "linear", moveTo, x0, y0, x1, y1 });
    }
    i += 1;
    x0 = x1;
    y0 = y1;
  }
  return spans;
}
var lineSteps = {
  start: 0,
  middle: 0.5,
  end: 1
};
function stepPoints(points, position) {
  const spans = [];
  let i = 0;
  let x0 = NaN;
  let y0 = NaN;
  const p0 = typeof position === "number" ? position : lineSteps[position];
  for (const { x: x1, y: y1 } of points) {
    if (i > 0) {
      const moveTo = i === 1;
      const stepX = x0 + (x1 - x0) * p0;
      spans.push({ type: "step", moveTo, x0, y0, x1, y1, stepX });
    }
    i += 1;
    x0 = x1;
    y0 = y1;
  }
  return spans;
}
var flatnessRatio = 0.05;
function smoothPoints(iPoints, tension) {
  const points = Array.isArray(iPoints) ? iPoints : Array.from(iPoints);
  if (points.length <= 1)
    return [];
  const gradients = points.map((c, i) => {
    const p = i === 0 ? c : points[i - 1];
    const n = i === points.length - 1 ? c : points[i + 1];
    const isTerminalPoint = i === 0 || i === points.length - 1;
    if (Math.sign(p.y - c.y) === Math.sign(n.y - c.y)) {
      return 0;
    }
    if (!isTerminalPoint) {
      const range3 = Math.abs(p.y - n.y);
      const prevRatio = Math.abs(c.y - p.y) / range3;
      const nextRatio = Math.abs(c.y - n.y) / range3;
      if (prevRatio <= flatnessRatio || 1 - prevRatio <= flatnessRatio || nextRatio <= flatnessRatio || 1 - nextRatio <= flatnessRatio) {
        return 0;
      }
    }
    return (n.y - p.y) / (n.x - p.x);
  });
  if (gradients[1] === 0) {
    gradients[0] *= 2;
  }
  if (gradients[gradients.length - 2] === 0) {
    gradients[gradients.length - 1] *= 2;
  }
  const spans = [];
  for (let i = 1; i < points.length; i += 1) {
    const prev = points[i - 1];
    const prevM = gradients[i - 1];
    const cur = points[i];
    const curM = gradients[i];
    const dx = cur.x - prev.x;
    const dy = cur.y - prev.y;
    let dcp1x = dx * tension / 3;
    let dcp1y = dx * prevM * tension / 3;
    let dcp2x = dx * tension / 3;
    let dcp2y = dx * curM * tension / 3;
    if (curM === 0 && Math.abs(dcp1y) > Math.abs(dy)) {
      dcp1x *= Math.abs(dy / dcp1y);
      dcp1y = Math.sign(dcp1y) * Math.abs(dy);
    }
    if (prevM === 0 && Math.abs(dcp2y) > Math.abs(dy)) {
      dcp2x *= Math.abs(dy / dcp2y);
      dcp2y = Math.sign(dcp2y) * Math.abs(dy);
    }
    spans.push({
      type: "cubic",
      moveTo: i === 1,
      cp0x: prev.x,
      cp0y: prev.y,
      cp1x: prev.x + dcp1x,
      cp1y: prev.y + dcp1y,
      cp2x: cur.x - dcp2x,
      cp2y: cur.y - dcp2y,
      cp3x: cur.x,
      cp3y: cur.y
    });
  }
  return spans;
}
function lerp2(a, b, ratio2) {
  return (b - a) * ratio2 + a;
}
function linearSupertype(span, stepX) {
  const { x0, y0, x1, y1 } = span;
  const m = (y1 - y0) / (x1 - x0);
  const stepY = m * (stepX - x0) + y0;
  return {
    leftCp1x: x0,
    leftCp1y: y0,
    leftCp2x: stepX,
    leftCp2y: stepY,
    stepX,
    stepY0: stepY,
    stepY1: stepY,
    rightCp1x: stepX,
    rightCp1y: stepY,
    rightCp2x: x1,
    rightCp2y: y1
  };
}
function bezierSupertype(span, stepX) {
  const { cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y } = span;
  const t = solveBezier(cp0x, cp1x, cp2x, cp3x, stepX);
  const [left, right] = splitBezier(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y, t);
  const stepY = left[3].y;
  return {
    leftCp1x: left[1].x,
    leftCp1y: left[1].y,
    leftCp2x: left[2].x,
    leftCp2y: left[2].y,
    stepX,
    stepY0: stepY,
    stepY1: stepY,
    rightCp1x: right[1].x,
    rightCp1y: right[1].y,
    rightCp2x: right[2].x,
    rightCp2y: right[2].y
  };
}
function stepSupertype(span) {
  const { x0, y0, x1, y1, stepX } = span;
  return {
    leftCp1x: (x0 + stepX) / 2,
    leftCp1y: y0,
    leftCp2x: (x0 + stepX) / 2,
    leftCp2y: y0,
    stepX,
    stepY0: y0,
    stepY1: y1,
    rightCp1x: (stepX + x1) / 2,
    rightCp1y: y1,
    rightCp2x: (stepX + x1) / 2,
    rightCp2y: y1
  };
}
function spanSupertype(span, stepX) {
  if (span.type === "linear") {
    return linearSupertype(span, stepX);
  } else if (span.type === "cubic") {
    return bezierSupertype(span, stepX);
  } else {
    return stepSupertype(span);
  }
}
function plotStart(path, moveTo, x0, y0, x1, y1, reversed) {
  switch (moveTo) {
    case 0:
      if (reversed) {
        path.moveTo(x1, y1);
      } else {
        path.moveTo(x0, y0);
      }
      break;
    case 1:
      if (reversed) {
        path.lineTo(x1, y1);
      } else {
        path.lineTo(x0, y0);
      }
      break;
  }
}
function plotLinear(path, x0, y0, x1, y1, reversed) {
  if (reversed) {
    path.lineTo(x0, y0);
  } else {
    path.lineTo(x1, y1);
  }
}
function plotCubic(path, cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y, reversed) {
  if (reversed) {
    path.cubicCurveTo(cp2x, cp2y, cp1x, cp1y, cp0x, cp0y);
  } else {
    path.cubicCurveTo(cp1x, cp1y, cp2x, cp2y, cp3x, cp3y);
  }
}
function plotStep(path, x0, y0, x1, y1, stepX, reversed) {
  if (reversed) {
    path.lineTo(stepX, y1);
    path.lineTo(stepX, y0);
    path.lineTo(x0, y0);
  } else {
    path.lineTo(stepX, y0);
    path.lineTo(stepX, y1);
    path.lineTo(x1, y1);
  }
}
function plotSpan(path, span, moveTo, reversed) {
  const [start2, end2] = spanRange(span);
  plotStart(path, moveTo, start2.x, start2.y, end2.x, end2.y, reversed);
  switch (span.type) {
    case "linear":
      plotLinear(path, span.x0, span.y0, span.x1, span.y1, reversed);
      break;
    case "cubic":
      plotCubic(
        path,
        span.cp0x,
        span.cp0y,
        span.cp1x,
        span.cp1y,
        span.cp2x,
        span.cp2y,
        span.cp3x,
        span.cp3y,
        reversed
      );
      break;
    case "step":
      plotStep(path, span.x0, span.y0, span.x1, span.y1, span.stepX, reversed);
      break;
  }
}
function interpolatedSpanRange(a, b, ratio2) {
  const [aStart, aEnd] = spanRange(a);
  const [bStart, bEnd] = spanRange(b);
  const x0 = lerp2(aStart.x, bStart.x, ratio2);
  const y0 = lerp2(aStart.y, bStart.y, ratio2);
  const x1 = lerp2(aEnd.x, bEnd.x, ratio2);
  const y1 = lerp2(aEnd.y, bEnd.y, ratio2);
  return [
    { x: x0, y: y0 },
    { x: x1, y: y1 }
  ];
}
function plotInterpolatedSpans(path, a, b, ratio2, moveTo, reversed) {
  const [{ x: x0, y: y0 }, { x: x1, y: y1 }] = interpolatedSpanRange(a, b, ratio2);
  plotStart(path, moveTo, x0, y0, x1, y1, reversed);
  if (a.type === "cubic" && b.type === "cubic") {
    const cp1x = lerp2(a.cp1x, b.cp1x, ratio2);
    const cp1y = lerp2(a.cp1y, b.cp1y, ratio2);
    const cp2x = lerp2(a.cp2x, b.cp2x, ratio2);
    const cp2y = lerp2(a.cp2y, b.cp2y, ratio2);
    plotCubic(path, x0, y0, cp1x, cp1y, cp2x, cp2y, x1, y1, reversed);
  } else if (a.type === "step" && b.type === "step") {
    const stepX = lerp2(a.stepX, b.stepX, ratio2);
    plotStep(path, x0, y0, x1, y1, stepX, reversed);
  } else if (a.type === "linear" && b.type === "linear") {
    plotLinear(path, x0, y0, x1, y1, reversed);
  } else {
    let defaultStepX;
    if (a.type === "step") {
      defaultStepX = a.stepX;
    } else if (b.type === "step") {
      defaultStepX = b.stepX;
    } else {
      defaultStepX = (x0 + x1) / 2;
    }
    const as = spanSupertype(a, defaultStepX);
    const bs = spanSupertype(b, defaultStepX);
    const leftCp1x = lerp2(as.leftCp1x, bs.leftCp1x, ratio2);
    const leftCp1y = lerp2(as.leftCp1y, bs.leftCp1y, ratio2);
    const leftCp2x = lerp2(as.leftCp2x, bs.leftCp2x, ratio2);
    const leftCp2y = lerp2(as.leftCp2y, bs.leftCp2y, ratio2);
    const stepX = lerp2(as.stepX, bs.stepX, ratio2);
    const stepY0 = lerp2(as.stepY0, bs.stepY0, ratio2);
    const stepY1 = lerp2(as.stepY1, bs.stepY1, ratio2);
    const rightCp1x = lerp2(as.rightCp1x, bs.rightCp1x, ratio2);
    const rightCp1y = lerp2(as.rightCp1y, bs.rightCp1y, ratio2);
    const rightCp2x = lerp2(as.rightCp2x, bs.rightCp2x, ratio2);
    const rightCp2y = lerp2(as.rightCp2y, bs.rightCp2y, ratio2);
    if (reversed) {
      path.cubicCurveTo(rightCp2x, rightCp2y, rightCp1x, rightCp1y, stepX, stepY1);
      path.lineTo(stepX, stepY0);
      path.cubicCurveTo(leftCp2x, leftCp2y, leftCp1x, leftCp1y, x0, y0);
    } else {
      path.cubicCurveTo(leftCp1x, leftCp1y, leftCp2x, leftCp2y, stepX, stepY0);
      path.lineTo(stepX, stepY1);
      path.cubicCurveTo(rightCp1x, rightCp1y, rightCp2x, rightCp2y, x1, y1);
    }
  }
}
var CollapseMode = /* @__PURE__ */ ((CollapseMode2) => {
  CollapseMode2[CollapseMode2["Zero"] = 0] = "Zero";
  CollapseMode2[CollapseMode2["Split"] = 1] = "Split";
  return CollapseMode2;
})(CollapseMode || {});
function integratedCategoryMatch(a, b) {
  if (a == null || b == null)
    return false;
  if (typeof a !== "object" || typeof b !== "object")
    return false;
  if ("id" in a && "id" in b) {
    return a.id === b.id;
  }
  return a.toString() === b.toString();
}
function scale(val, scaling) {
  if (!scaling)
    return NaN;
  if (val instanceof Date) {
    val = val.getTime();
  }
  if (scaling.type === "continuous" && typeof val === "number") {
    const domainRatio = (val - scaling.domain[0]) / (scaling.domain[1] - scaling.domain[0]);
    return domainRatio * (scaling.range[1] - scaling.range[0]) + scaling.range[0];
  }
  if (scaling.type === "log" && typeof val === "number") {
    return scaling.convert(val);
  }
  if (scaling.type !== "category")
    return NaN;
  const matchingIndex = scaling.domain.findIndex((d) => d === val);
  if (matchingIndex >= 0) {
    return scaling.inset + scaling.step * matchingIndex;
  }
  const matchingIntegratedIndex = scaling.domain.findIndex((d) => integratedCategoryMatch(val, d));
  if (matchingIntegratedIndex >= 0) {
    return scaling.inset + scaling.step * matchingIndex;
  }
  return NaN;
}
function toAxisValue(value) {
  return transformIntegratedCategoryValue(value).valueOf();
}
function getAxisIndices({ data }, values) {
  return data.map((datum, datumIndex) => ({
    xValue0Index: values.indexOf(toAxisValue(datum.xValue0)),
    xValue1Index: values.indexOf(toAxisValue(datum.xValue1)),
    datumIndex
  }));
}
function validateCategorySorting(newData, oldData) {
  const oldScale = oldData.scales.x;
  const newScale = newData.scales.x;
  if (oldScale?.type !== "category" || newScale?.type !== "category")
    return true;
  let x0 = -Infinity;
  for (const oldValue of oldScale.domain) {
    const x = scale(oldValue, newScale);
    if (!Number.isFinite(x)) {
      continue;
    } else if (x < x0) {
      return false;
    } else {
      x0 = x;
    }
  }
  return true;
}
function validateAxisEntriesOrder(axisValues, data) {
  let x0 = -Infinity;
  for (const axisValue of axisValues) {
    const x = scale(axisValue.value, data.scales.x);
    if (!Number.isFinite(x)) {
      continue;
    } else if (x < x0) {
      return false;
    } else {
      x0 = x;
    }
  }
  return true;
}
function spanAxisContext(newData, oldData) {
  const allAxisEntries = /* @__PURE__ */ new Map();
  for (const { xValue0, xValue1 } of newData.data) {
    const xValue0Value = toAxisValue(xValue0);
    const xValue1Value = toAxisValue(xValue1);
    allAxisEntries.set(xValue0Value, xValue0).set(xValue1Value, xValue1);
  }
  const newAxisEntries = Array.from(allAxisEntries, ([axisValue, value]) => ({ axisValue, value }));
  newAxisEntries.sort((a, b) => {
    return scale(a.value, newData.scales.x) - scale(b.value, newData.scales.x);
  });
  const exclusivelyOldAxisEntries = [];
  for (const { xValue0, xValue1 } of oldData.data) {
    const xValue0Value = toAxisValue(xValue0);
    const xValue1Value = toAxisValue(xValue1);
    if (!allAxisEntries.has(xValue0Value)) {
      allAxisEntries.set(xValue0Value, xValue0);
      exclusivelyOldAxisEntries.push({ axisValue: xValue0Value, value: xValue0 });
    }
    if (!allAxisEntries.has(xValue1Value)) {
      allAxisEntries.set(xValue1Value, xValue1);
      exclusivelyOldAxisEntries.push({ axisValue: xValue1Value, value: xValue1 });
    }
  }
  exclusivelyOldAxisEntries.sort((a, b) => {
    return scale(a.value, oldData.scales.x) - scale(b.value, oldData.scales.x);
  });
  const axisEntries = newAxisEntries;
  let insertionIndex = 0;
  for (const oldAxisEntries of exclusivelyOldAxisEntries) {
    for (let i = axisEntries.length - 1; i > insertionIndex; i -= 1) {
      const oldValueX = scale(oldAxisEntries.value, oldData.scales.x);
      const newValueX = scale(axisEntries[i].value, oldData.scales.x);
      if (oldValueX > newValueX) {
        insertionIndex = i + 1;
        break;
      }
    }
    axisEntries.splice(insertionIndex, 0, oldAxisEntries);
    insertionIndex += 1;
  }
  if (!validateAxisEntriesOrder(axisEntries, oldData))
    return;
  const axisValues = axisEntries.map((axisEntry) => axisEntry.axisValue);
  const oldDataAxisIndices = getAxisIndices(oldData, axisValues);
  const newDataAxisIndices = getAxisIndices(newData, axisValues);
  return { axisValues, oldDataAxisIndices, newDataAxisIndices };
}
function clipSpan(span, xValue0Index, xIndices) {
  if (xIndices.xValue1Index === xIndices.xValue0Index + 1)
    return span;
  const range3 = spanRange(span);
  const step = (range3[1].x - range3[0].x) / (xIndices.xValue1Index - xIndices.xValue0Index);
  const start2 = range3[0].x + (xValue0Index - xIndices.xValue0Index) * step;
  const end2 = start2 + step;
  return clipSpanX(span, start2, end2);
}
function axisZeroSpan(span, data) {
  const [r0, r1] = spanRange(span);
  const y0 = scale(0, data.scales.y);
  return rescaleSpan(span, { x: r0.x, y: y0 }, { x: r1.x, y: y0 });
}
function collapseSpanToMidpoint(span) {
  const [r0, r1] = spanRange(span);
  return collapseSpanToPoint(span, {
    x: (r0.x + r1.x) / 2,
    y: (r0.y + r1.y) / 2
  });
}
function collapseSpan(span, collapseMode, data, axisIndices, indices, range3) {
  let xValue;
  let yValue;
  if (indices.xValue0Index >= range3.xValue1Index) {
    const datumIndex = axisIndices.findLast((i) => i.xValue1Index <= range3.xValue1Index)?.datumIndex;
    const datum = datumIndex != null ? data.data[datumIndex] : void 0;
    xValue = datum?.xValue1;
    yValue = datum?.yValue1;
  } else if (indices.xValue0Index <= range3.xValue0Index) {
    const datumIndex = axisIndices.find((i) => i.xValue0Index >= range3.xValue0Index)?.datumIndex;
    const datum = datumIndex != null ? data.data[datumIndex] : void 0;
    xValue = datum?.xValue0;
    yValue = datum?.yValue0;
  }
  if (xValue == null || yValue == null) {
    switch (collapseMode) {
      case 0:
        return axisZeroSpan(span, data);
      case 1:
        return collapseSpanToMidpoint(span);
    }
  }
  const x = scale(xValue, data.scales.x);
  const y = scale(yValue, data.scales.y);
  const point = { x, y };
  return rescaleSpan(span, point, point);
}
function zeroDataSpan(spanDatum, zeroData) {
  if (zeroData == null)
    return;
  const newSpanXValue0 = toAxisValue(spanDatum.xValue0);
  const newSpanXValue1 = toAxisValue(spanDatum.xValue1);
  return zeroData.find(
    (zeroSpanDatum) => toAxisValue(zeroSpanDatum.xValue0) === newSpanXValue0 && toAxisValue(zeroSpanDatum.xValue1) === newSpanXValue1
  )?.span;
}
function addSpan(newData, collapseMode, newAxisIndices, newIndices, oldZeroData, range3, out) {
  const newSpanDatum = newData.data[newIndices.datumIndex];
  const newSpan = newSpanDatum.span;
  const zeroSpan = zeroDataSpan(newSpanDatum, oldZeroData);
  if (zeroSpan != null) {
    out.removed.push({ from: zeroSpan, to: zeroSpan });
    out.moved.push({ from: zeroSpan, to: newSpan });
    out.added.push({ from: newSpan, to: newSpan });
  } else {
    const oldSpan = collapseSpan(newSpan, collapseMode, newData, newAxisIndices, newIndices, range3);
    out.added.push({ from: oldSpan, to: newSpan });
  }
}
function removeSpan(oldData, collapseMode, oldAxisIndices, oldIndices, newZeroData, range3, out) {
  const oldSpanDatum = oldData.data[oldIndices.datumIndex];
  const oldSpan = oldSpanDatum.span;
  const zeroSpan = zeroDataSpan(oldSpanDatum, newZeroData);
  if (zeroSpan != null) {
    out.removed.push({ from: oldSpan, to: oldSpan });
    out.moved.push({ from: oldSpan, to: zeroSpan });
    out.added.push({ from: zeroSpan, to: zeroSpan });
  } else {
    const newSpan = collapseSpan(oldSpan, collapseMode, oldData, oldAxisIndices, oldIndices, range3);
    out.removed.push({ from: oldSpan, to: newSpan });
  }
}
function alignSpanToContainingSpan(span, axisValues, preData, postData, postSpanIndices) {
  const startXValue0 = axisValues[postSpanIndices.xValue0Index];
  const startDatum = preData.data.find((spanDatum) => toAxisValue(spanDatum.xValue0) === startXValue0);
  const endXValue1 = axisValues[postSpanIndices.xValue1Index];
  const endDatum = preData.data.find((spanDatum) => toAxisValue(spanDatum.xValue1) === endXValue1);
  if (startDatum == null || endDatum == null)
    return;
  const [{ x: x0 }, { x: x1 }] = spanRange(span);
  const startX = scale(startDatum.xValue0, preData.scales.x);
  const startY = scale(startDatum.yValue0, preData.scales.y);
  const endX = scale(endDatum.xValue1, preData.scales.x);
  const endY = scale(endDatum.yValue1, preData.scales.y);
  let altSpan = postData.data[postSpanIndices.datumIndex].span;
  altSpan = rescaleSpan(altSpan, { x: startX, y: startY }, { x: endX, y: endY });
  altSpan = clipSpanX(altSpan, x0, x1);
  return altSpan;
}
function appendSpanPhases(newData, oldData, collapseMode, axisValues, xValue0Index, newAxisIndices, oldAxisIndices, range3, out) {
  const xValue1Index = xValue0Index + 1;
  const oldIndices = oldAxisIndices.find((i) => i.xValue0Index <= xValue0Index && i.xValue1Index >= xValue1Index);
  const newIndices = newAxisIndices.find((i) => i.xValue0Index <= xValue0Index && i.xValue1Index >= xValue1Index);
  const oldZeroData = oldData.zeroData;
  const newZeroData = newData.zeroData;
  if (oldIndices == null && newIndices != null) {
    addSpan(newData, collapseMode, newAxisIndices, newIndices, oldZeroData, range3, out);
    return;
  } else if (oldIndices != null && newIndices == null) {
    removeSpan(oldData, collapseMode, oldAxisIndices, oldIndices, newZeroData, range3, out);
    return;
  } else if (oldIndices == null || newIndices == null) {
    return;
  }
  let ordering;
  if (oldIndices.xValue0Index === newIndices.xValue0Index && oldIndices.xValue1Index === newIndices.xValue1Index) {
    ordering = 0;
  } else if (oldIndices.xValue0Index <= newIndices.xValue0Index && oldIndices.xValue1Index >= newIndices.xValue1Index) {
    ordering = -1;
  } else if (oldIndices.xValue0Index >= newIndices.xValue0Index && oldIndices.xValue1Index <= newIndices.xValue1Index) {
    ordering = 1;
  } else {
    ordering = 0;
  }
  const oldSpanDatum = oldData.data[oldIndices.datumIndex];
  const clippedOldSpanOldScale = clipSpan(oldSpanDatum.span, xValue0Index, oldIndices);
  const newSpanDatum = newData.data[newIndices.datumIndex];
  const clippedNewSpanNewScale = clipSpan(newSpanDatum.span, xValue0Index, newIndices);
  if (ordering === 1) {
    const clippedPostRemoveOldSpanOldScale = alignSpanToContainingSpan(
      clippedOldSpanOldScale,
      axisValues,
      oldData,
      newData,
      newIndices
    );
    if (clippedPostRemoveOldSpanOldScale != null) {
      out.removed.push({ from: clippedOldSpanOldScale, to: clippedPostRemoveOldSpanOldScale });
      out.moved.push({ from: clippedPostRemoveOldSpanOldScale, to: clippedNewSpanNewScale });
      out.added.push({ from: clippedNewSpanNewScale, to: clippedNewSpanNewScale });
    } else {
      removeSpan(oldData, collapseMode, oldAxisIndices, oldIndices, newZeroData, range3, out);
    }
  } else if (ordering === -1) {
    const clippedPreAddedNewSpanNewScale = alignSpanToContainingSpan(
      clippedNewSpanNewScale,
      axisValues,
      newData,
      oldData,
      oldIndices
    );
    if (clippedPreAddedNewSpanNewScale != null) {
      out.removed.push({ from: clippedOldSpanOldScale, to: clippedOldSpanOldScale });
      out.moved.push({ from: clippedOldSpanOldScale, to: clippedPreAddedNewSpanNewScale });
      out.added.push({ from: clippedPreAddedNewSpanNewScale, to: clippedNewSpanNewScale });
    } else {
      addSpan(newData, collapseMode, newAxisIndices, newIndices, oldZeroData, range3, out);
    }
  } else {
    out.removed.push({ from: clippedOldSpanOldScale, to: clippedOldSpanOldScale });
    out.moved.push({ from: clippedOldSpanOldScale, to: clippedNewSpanNewScale });
    out.added.push({ from: clippedNewSpanNewScale, to: clippedNewSpanNewScale });
  }
}
function phaseAnimation(axisContext, newData, oldData, collapseMode) {
  const out = {
    removed: [],
    moved: [],
    added: []
  };
  const { axisValues, oldDataAxisIndices, newDataAxisIndices } = axisContext;
  const range3 = {
    xValue0Index: Math.max(
      oldDataAxisIndices.at(0)?.xValue0Index ?? -Infinity,
      newDataAxisIndices.at(0)?.xValue0Index ?? -Infinity
    ),
    xValue1Index: Math.min(
      oldDataAxisIndices.at(-1)?.xValue1Index ?? Infinity,
      newDataAxisIndices.at(-1)?.xValue1Index ?? Infinity
    )
  };
  for (let xValue0Index = 0; xValue0Index < axisValues.length - 1; xValue0Index += 1) {
    appendSpanPhases(
      newData,
      oldData,
      collapseMode,
      axisValues,
      xValue0Index,
      newDataAxisIndices,
      oldDataAxisIndices,
      range3,
      out
    );
  }
  return out;
}
function resetSpan(data, spanDatum, collapseMode) {
  const { span } = spanDatum;
  switch (collapseMode) {
    case 0:
      return zeroDataSpan(spanDatum, data.zeroData) ?? axisZeroSpan(span, data);
    case 1:
      return collapseSpanToMidpoint(span);
  }
}
function resetAnimation(newData, oldData, collapseMode) {
  const added = [];
  const removed = [];
  for (const oldSpanDatum of oldData.data) {
    const oldSpan = oldSpanDatum.span;
    const collapsedSpan = resetSpan(oldData, oldSpanDatum, collapseMode);
    removed.push({ from: oldSpan, to: collapsedSpan });
  }
  for (const newSpanDatum of newData.data) {
    const newSpan = newSpanDatum.span;
    const collapsedSpan = resetSpan(newData, newSpanDatum, collapseMode);
    added.push({ from: collapsedSpan, to: newSpan });
  }
  return {
    removed,
    moved: [],
    added
  };
}
function pairUpSpans(newData, oldData, collapseMode) {
  if (!validateCategorySorting(newData, oldData))
    return;
  const axisContext = spanAxisContext(newData, oldData);
  return axisContext == null ? resetAnimation(newData, oldData, collapseMode) : phaseAnimation(axisContext, newData, oldData, collapseMode);
}
function isContinuousScaling(scaling) {
  return scaling.type === "continuous" || scaling.type === "log";
}
function isCategoryScaling(scaling) {
  return scaling.type === "category";
}
function areScalingEqual(a, b) {
  if (a === void 0 || b === void 0) {
    return a !== void 0 || b !== void 0;
  }
  if (isContinuousScaling(a) && isContinuousScaling(b)) {
    return a.type === b.type && arraysEqual(a.domain, b.domain) && arraysEqual(a.range, b.range);
  }
  if (isCategoryScaling(a) && isCategoryScaling(b)) {
    return a.inset === b.inset && a.step === b.step && arraysEqual(a.domain, b.domain);
  }
  return false;
}
function isScaleValid(scale2) {
  if (scale2 == null)
    return false;
  if (scale2.type === "category")
    return scale2.domain.every((v) => v != null);
  return scale2.domain.every((v) => Number.isFinite(v) || v instanceof Date) && scale2.range.every((v) => Number.isFinite(v));
}
function interpolatePoints(points, interpolation) {
  let spans;
  const pointsIter = points.map((point) => point.point);
  switch (interpolation.type) {
    case "linear":
      spans = linearPoints(pointsIter);
      break;
    case "smooth":
      spans = smoothPoints(pointsIter, interpolation.tension);
      break;
    case "step":
      spans = stepPoints(pointsIter, interpolation.position);
      break;
  }
  return spans.map((span, i) => ({
    span,
    xValue0: points[i].xDatum,
    yValue0: points[i].yDatum,
    xValue1: points[i + 1].xDatum,
    yValue1: points[i + 1].yDatum
  }));
}
function pointsEq(a, b, delta4 = 1e-3) {
  return Math.abs(a.x - b.x) < delta4 && Math.abs(a.y - b.y) < delta4;
}
function plotLinePathStroke({ path }, spans) {
  let lastPoint;
  for (const { span } of spans) {
    const [start2, end2] = spanRange(span);
    const join = lastPoint != null && pointsEq(lastPoint, start2) ? 1 : 0;
    plotSpan(path, span, join, false);
    lastPoint = end2;
  }
}
function plotInterpolatedLinePathStroke(ratio2, path, spans) {
  let lastPoint;
  for (const span of spans) {
    const [start2, end2] = interpolatedSpanRange(span.from, span.to, ratio2);
    const join = lastPoint != null && pointsEq(lastPoint, start2) ? 1 : 0;
    plotInterpolatedSpans(path.path, span.from, span.to, ratio2, join, false);
    lastPoint = end2;
  }
}
function prepareLinePathStrokeAnimationFns(status, spans, visibleToggleMode) {
  const removePhaseFn = (ratio2, path) => plotInterpolatedLinePathStroke(ratio2, path, spans.removed);
  const updatePhaseFn = (ratio2, path) => plotInterpolatedLinePathStroke(ratio2, path, spans.moved);
  const addPhaseFn = (ratio2, path) => plotInterpolatedLinePathStroke(ratio2, path, spans.added);
  const pathProperties = prepareLinePathPropertyAnimation(status, visibleToggleMode);
  return { status, path: { addPhaseFn, updatePhaseFn, removePhaseFn }, pathProperties };
}
function prepareLinePathPropertyAnimation(status, visibleToggleMode) {
  const phase = visibleToggleMode === "none" ? "updated" : status;
  const result = {
    fromFn: (_path) => {
      let mixin;
      if (status === "removed") {
        mixin = { finish: { visible: false } };
      } else if (status === "added") {
        mixin = { start: { visible: true } };
      } else {
        mixin = {};
      }
      return { phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[phase], ...mixin };
    },
    toFn: (_path) => {
      return { phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[phase] };
    }
  };
  if (visibleToggleMode === "fade") {
    return {
      fromFn: (path) => {
        const opacity = status === "added" ? 0 : path.opacity;
        return { opacity, ...result.fromFn(path) };
      },
      toFn: (path) => {
        const opacity = status === "removed" ? 0 : 1;
        return { opacity, ...result.toFn(path) };
      }
    };
  }
  return result;
}
function prepareLinePathAnimation(newData, oldData, diff2) {
  const isCategoryBased = newData.scales.x?.type === "category";
  const wasCategoryBased = oldData.scales.x?.type === "category";
  if (isCategoryBased !== wasCategoryBased || !isScaleValid(newData.scales.x) || !isScaleValid(oldData.scales.x)) {
    return;
  }
  if (newData.strokeData == null || oldData.strokeData == null) {
    return;
  }
  let status = "updated";
  if (oldData.visible && !newData.visible) {
    status = "removed";
  } else if (!oldData.visible && newData.visible) {
    status = "added";
  }
  const strokeSpans = pairUpSpans(
    { scales: newData.scales, data: newData.strokeData.spans },
    { scales: oldData.scales, data: oldData.strokeData.spans },
    1
    /* Split */
  );
  if (strokeSpans == null)
    return;
  const stroke = prepareLinePathStrokeAnimationFns(status, strokeSpans, "fade");
  const hasMotion = (diff2?.changed ?? true) || !areScalingEqual(newData.scales.x, oldData.scales.x) || !areScalingEqual(newData.scales.y, oldData.scales.y) || status !== "updated";
  return { status, stroke, hasMotion };
}
function plotAreaPathFill({ path }, { spans, phantomSpans }) {
  for (let i = 0; i < spans.length; i += 1) {
    const { span } = spans[i];
    const phantomSpan = phantomSpans[i].span;
    plotSpan(path, span, 0, false);
    plotSpan(path, phantomSpan, 1, true);
    path.closePath();
  }
}
function plotInterpolatedAreaSeriesFillSpans(ratio2, { path }, spans, fillPhantomSpans) {
  for (let i = 0; i < spans.length; i += 1) {
    const span = spans[i];
    const reversedPhantomSpan = fillPhantomSpans[i];
    plotInterpolatedSpans(path, span.from, span.to, ratio2, 0, false);
    plotInterpolatedSpans(path, reversedPhantomSpan.from, reversedPhantomSpan.to, ratio2, 1, true);
    path.closePath();
  }
}
function prepareAreaFillAnimationFns(status, spans, fillPhantomSpans, visibleToggleMode) {
  const removePhaseFn = (ratio2, path) => plotInterpolatedAreaSeriesFillSpans(ratio2, path, spans.removed, fillPhantomSpans.removed);
  const updatePhaseFn = (ratio2, path) => plotInterpolatedAreaSeriesFillSpans(ratio2, path, spans.moved, fillPhantomSpans.moved);
  const addPhaseFn = (ratio2, path) => plotInterpolatedAreaSeriesFillSpans(ratio2, path, spans.added, fillPhantomSpans.added);
  const pathProperties = prepareLinePathPropertyAnimation(status, visibleToggleMode);
  return { status, path: { addPhaseFn, updatePhaseFn, removePhaseFn }, pathProperties };
}
function prepareAreaPathAnimation(newData, oldData) {
  const isCategoryBased = newData.scales.x?.type === "category";
  const wasCategoryBased = oldData.scales.x?.type === "category";
  if (isCategoryBased !== wasCategoryBased || !isScaleValid(newData.scales.x) || !isScaleValid(oldData.scales.x)) {
    return;
  }
  let status = "updated";
  if (oldData.visible && !newData.visible) {
    status = "removed";
  } else if (!oldData.visible && newData.visible) {
    status = "added";
  }
  const fillSpans = pairUpSpans(
    { scales: newData.scales, data: newData.fillData.spans },
    { scales: oldData.scales, data: oldData.fillData.spans },
    0
    /* Zero */
  );
  if (fillSpans == null)
    return;
  const fillPhantomSpans = pairUpSpans(
    { scales: newData.scales, data: newData.fillData.phantomSpans },
    { scales: oldData.scales, data: oldData.fillData.phantomSpans },
    0
    /* Zero */
  );
  if (fillPhantomSpans == null)
    return;
  const strokeSpans = pairUpSpans(
    {
      scales: newData.scales,
      data: newData.strokeData.spans,
      zeroData: newData.fillData.phantomSpans
    },
    {
      scales: oldData.scales,
      data: oldData.strokeData.spans,
      zeroData: oldData.fillData.phantomSpans
    },
    0
    /* Zero */
  );
  if (strokeSpans == null)
    return;
  const fadeMode = "none";
  const fill = prepareAreaFillAnimationFns(status, fillSpans, fillPhantomSpans, fadeMode);
  const stroke = prepareLinePathStrokeAnimationFns(status, strokeSpans, fadeMode);
  return { status, fill, stroke };
}
function markerFadeInAnimation({ id }, animationManager, status, ...markerSelections) {
  const params = { phase: status ? NODE_UPDATE_STATE_TO_PHASE_MAPPING[status] : "trailing" };
  staticFromToMotion(id, "markers", animationManager, markerSelections, { opacity: 0 }, { opacity: 1 }, params);
  markerSelections.forEach((s) => s.cleanup());
}
function markerScaleInAnimation({ id }, animationManager, ...markerSelections) {
  staticFromToMotion(
    id,
    "markers",
    animationManager,
    markerSelections,
    { scalingX: 0, scalingY: 0 },
    { scalingX: 1, scalingY: 1 },
    { phase: "initial" }
  );
  markerSelections.forEach((s) => s.cleanup());
}
function markerSwipeScaleInAnimation({ id, nodeDataDependencies }, animationManager, ...markerSelections) {
  const seriesWidth = nodeDataDependencies.seriesRectWidth;
  const fromFn = (_, datum) => {
    const x = datum.midPoint?.x ?? seriesWidth;
    let delay = clamp(0, inverseEaseOut(x / seriesWidth), 1);
    if (isNaN(delay)) {
      delay = 0;
    }
    return { scalingX: 0, scalingY: 0, delay, duration: QUICK_TRANSITION, phase: "initial" };
  };
  const toFn = () => {
    return { scalingX: 1, scalingY: 1 };
  };
  fromToMotion(id, "markers", animationManager, markerSelections, { fromFn, toFn });
}
function resetMarkerFn(_node) {
  return { opacity: 1, scalingX: 1, scalingY: 1 };
}
function resetMarkerPositionFn(_node, datum) {
  return {
    translationX: datum.point?.x ?? NaN,
    translationY: datum.point?.y ?? NaN
  };
}
function prepareMarkerAnimation(pairMap, parentStatus) {
  const readFirstPair = (xValue, type) => {
    const val = pairMap[type][xValue];
    return Array.isArray(val) ? val[0] : val;
  };
  const markerStatus = (datum) => {
    const { xValue } = datum;
    if (pairMap.moved[xValue]) {
      return { point: readFirstPair(xValue, "moved"), status: "updated" };
    } else if (pairMap.removed[xValue]) {
      return { point: readFirstPair(xValue, "removed"), status: "removed" };
    } else if (pairMap.added[xValue]) {
      return { point: readFirstPair(xValue, "added"), status: "added" };
    }
    return { status: "unknown" };
  };
  const fromFn = (marker, datum) => {
    const { status, point } = markerStatus(datum);
    if (status === "unknown")
      return { opacity: 0 };
    const defaults = {
      translationX: point?.from?.x ?? marker.translationX,
      translationY: point?.from?.y ?? marker.translationY,
      opacity: marker.opacity,
      phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[status]
    };
    if (parentStatus === "added") {
      return {
        ...defaults,
        opacity: 0,
        translationX: point?.to?.x,
        translationY: point?.to?.y,
        phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING["added"]
      };
    }
    if (status === "added") {
      defaults.opacity = 0;
    }
    return defaults;
  };
  const toFn = (_marker, datum) => {
    const { status, point } = markerStatus(datum);
    if (status === "unknown")
      return { opacity: 0 };
    const defaults = {
      translationX: datum.point.x,
      translationY: datum.point.y,
      opacity: 1,
      phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING[status]
    };
    if (status === "removed" || parentStatus === "removed") {
      return {
        ...defaults,
        translationX: point?.to?.x,
        translationY: point?.to?.y,
        opacity: 0,
        phase: NODE_UPDATE_STATE_TO_PHASE_MAPPING["removed"]
      };
    }
    return defaults;
  };
  return { fromFn, toFn };
}
function computeMarkerFocusBounds(series, { datumIndex }) {
  const nodeData = series.getNodeData();
  if (nodeData === void 0)
    return void 0;
  const datum = nodeData[datumIndex];
  const { point } = datum;
  if (datum == null || point == null)
    return void 0;
  const size = point.focusSize ?? series.getFormattedMarkerStyle(datum).size;
  const radius = size / 2;
  const x = datum.point.x - radius;
  const y = datum.point.y - radius;
  return new BBox(x, y, size, size);
}
function plotLinearPoints(path, points, continuePath) {
  let didMove = continuePath;
  for (const { x, y } of points) {
    if (didMove) {
      path.lineTo(x, y);
    } else {
      path.moveTo(x, y);
      didMove = true;
    }
  }
}
var flatnessRatio2 = 0.05;
function plotSmoothPoints(path, iPoints, tension, continuePath) {
  const points = Array.isArray(iPoints) ? iPoints : Array.from(iPoints);
  if (points.length === 0)
    return;
  if (continuePath) {
    path.lineTo(points[0].x, points[0].y);
  } else {
    path.moveTo(points[0].x, points[0].y);
  }
  if (points.length <= 1)
    return;
  const gradients = points.map((c, i) => {
    const p = i === 0 ? c : points[i - 1];
    const n = i === points.length - 1 ? c : points[i + 1];
    const isTerminalPoint = i === 0 || i === points.length - 1;
    if (Math.sign(p.y - c.y) === Math.sign(n.y - c.y)) {
      return 0;
    }
    if (!isTerminalPoint) {
      const range3 = Math.abs(p.y - n.y);
      const prevRatio = Math.abs(c.y - p.y) / range3;
      const nextRatio = Math.abs(c.y - n.y) / range3;
      if (prevRatio <= flatnessRatio2 || 1 - prevRatio <= flatnessRatio2 || nextRatio <= flatnessRatio2 || 1 - nextRatio <= flatnessRatio2) {
        return 0;
      }
    }
    return (n.y - p.y) / (n.x - p.x);
  });
  if (gradients[1] === 0) {
    gradients[0] *= 2;
  }
  if (gradients[gradients.length - 2] === 0) {
    gradients[gradients.length - 1] *= 2;
  }
  for (let i = 1; i < points.length; i += 1) {
    const prev = points[i - 1];
    const prevM = gradients[i - 1];
    const cur = points[i];
    const curM = gradients[i];
    const dx = cur.x - prev.x;
    const dy = cur.y - prev.y;
    let dcp1x = dx * tension / 3;
    let dcp1y = dx * prevM * tension / 3;
    let dcp2x = dx * tension / 3;
    let dcp2y = dx * curM * tension / 3;
    if (curM === 0 && Math.abs(dcp1y) > Math.abs(dy)) {
      dcp1x *= Math.abs(dy / dcp1y);
      dcp1y = Math.sign(dcp1y) * Math.abs(dy);
    }
    if (prevM === 0 && Math.abs(dcp2y) > Math.abs(dy)) {
      dcp2x *= Math.abs(dy / dcp2y);
      dcp2y = Math.sign(dcp2y) * Math.abs(dy);
    }
    path.cubicCurveTo(prev.x + dcp1x, prev.y + dcp1y, cur.x - dcp2x, cur.y - dcp2y, cur.x, cur.y);
  }
}
function plotStepPoints(path, points, align, continuePath) {
  let lastPoint;
  for (const point of points) {
    if (lastPoint != null) {
      const directionalAlign = lastPoint.x < point.x ? align : 1 - align;
      const x = (point.x - lastPoint.x) * directionalAlign + lastPoint.x;
      path.lineTo(x, lastPoint?.y ?? point.y);
      path.lineTo(x, point.y);
      path.lineTo(point.x, point.y);
    } else if (continuePath) {
      path.lineTo(point.x, point.y);
    } else {
      path.moveTo(point.x, point.y);
    }
    lastPoint = point;
  }
}
function minMax(nodeData) {
  return nodeData.reduce(
    ({ min, max }, node) => {
      if (min == null || min.point.x > node.point.x) {
        min = node;
      }
      if (max == null || max.point.x < node.point.x) {
        max = node;
      }
      return { min, max };
    },
    {}
  );
}
function intersectionOnLine(a, b, targetX) {
  const m = (b.y - a.y) / (b.x - a.x);
  const y = (targetX - a.x) * m + a.y;
  return { x: targetX, y };
}
function backfillPathPoint(results, process, skip, processFn) {
  let prevMarkerIdx = -1, nextMarkerIdx = 0;
  const toProcess = [];
  while (nextMarkerIdx < results.length) {
    if (results[nextMarkerIdx].change === process) {
      toProcess.push(results[nextMarkerIdx]);
      nextMarkerIdx++;
      continue;
    }
    if (results[nextMarkerIdx].change === skip) {
      nextMarkerIdx++;
      continue;
    }
    if (toProcess.length > 0) {
      processFn(toProcess, prevMarkerIdx, nextMarkerIdx);
      toProcess.length = 0;
    }
    prevMarkerIdx = nextMarkerIdx;
    nextMarkerIdx++;
  }
  if (toProcess.length > 0) {
    processFn(toProcess, prevMarkerIdx, nextMarkerIdx);
  }
}
function backfillPathPointData(result, splitMode) {
  backfillPathPoint(result, "out", "in", (toProcess, sIdx, eIdx) => {
    if (sIdx === -1 && result[eIdx]) {
      toProcess.forEach((d) => d.to = result[eIdx].from);
    } else if (eIdx === result.length && result[sIdx]) {
      toProcess.forEach((d) => d.to = result[sIdx].from);
    } else if (splitMode === "intersect" && result[sIdx]?.from && result[eIdx]?.from) {
      toProcess.forEach((d) => d.to = intersectionOnLine(result[sIdx].from, result[eIdx].from, d.from.x));
    } else {
      toProcess.forEach((d) => d.to = d.from);
    }
  });
  backfillPathPoint(result, "in", "out", (toProcess, sIdx, eIdx) => {
    if (sIdx === -1 && result[eIdx]) {
      toProcess.forEach((d) => d.from = result[eIdx].to);
    } else if (eIdx === result.length && result[sIdx]) {
      toProcess.forEach((d) => d.from = result[sIdx].to);
    } else if (splitMode === "intersect" && result[sIdx]?.to && result[eIdx]?.to) {
      toProcess.forEach((d) => d.from = intersectionOnLine(result[sIdx].to, result[eIdx].to, d.to.x));
    } else {
      toProcess.forEach((d) => d.from = d.to);
    }
  });
}
function calculatePoint(from3, to, ratio2) {
  const x1 = isNaN(from3.x) ? to.x : from3.x;
  const y1 = isNaN(from3.y) ? to.y : from3.y;
  const xd = to.x - from3.x;
  const yd = to.y - from3.y;
  const xr = isNaN(xd) ? 0 : xd * ratio2;
  const yr = isNaN(yd) ? 0 : yd * ratio2;
  return {
    x: x1 + xr,
    y: y1 + yr
  };
}
var lineSteps2 = {
  start: 0,
  middle: 0.5,
  end: 1
};
function plotPath(points, path, interpolation, continuePath = false) {
  const { path: linePath } = path;
  if (interpolation?.type === "smooth") {
    plotSmoothPoints(linePath, points, interpolation.tension ?? 1, continuePath);
  } else if (interpolation?.type === "step") {
    plotStepPoints(linePath, points, lineSteps2[interpolation.position ?? "end"], continuePath);
  } else {
    plotLinearPoints(linePath, points, continuePath);
  }
}
function splitPairData(pairData, ratios) {
  let previousTo;
  let points = void 0;
  const out = [];
  const flushCurrent = () => {
    if (points != null) {
      out.push(points);
      points = void 0;
    }
  };
  for (const data of pairData) {
    const { from: from3, to } = data;
    const ratio2 = ratios[data.change];
    if (ratio2 == null || from3 == null || to == null)
      continue;
    const point = calculatePoint(from3, to, ratio2);
    if (data.moveTo === false) {
      points ?? (points = []);
      points.push(point);
    } else if (data.moveTo === true || !previousTo) {
      flushCurrent();
      points = [point];
    } else if (previousTo) {
      const moveToRatio = data.moveTo === "in" ? ratio2 : 1 - ratio2;
      const { x: midPointX, y: midPointY } = calculatePoint(previousTo, point, moveToRatio);
      points ?? (points = []);
      points.push({ x: midPointX, y: midPointY });
      flushCurrent();
      points = [point];
    }
    previousTo = point;
  }
  flushCurrent();
  return out;
}
function renderPartialPath(pairData, ratios, path, interpolation) {
  splitPairData(pairData, ratios).forEach((points) => {
    plotPath(points, path, interpolation);
  });
}
function pathSwipeInAnimation({ id, visible, nodeDataDependencies }, animationManager, ...paths) {
  const { seriesRectWidth: width2, seriesRectHeight: height2 } = nodeDataDependencies;
  staticFromToMotion(
    id,
    "path_properties",
    animationManager,
    paths,
    { clipX: 0 },
    { clipX: width2 },
    {
      phase: "initial",
      start: { clip: true, clipY: height2, visible },
      finish: { clip: false, visible }
    }
  );
}
function pathFadeInAnimation({ id }, subId, animationManager, phase = "add", ...selection) {
  staticFromToMotion(id, subId, animationManager, selection, { opacity: 0 }, { opacity: 1 }, { phase });
}
function pathFadeOutAnimation({ id }, subId, animationManager, ...selection) {
  staticFromToMotion(id, subId, animationManager, selection, { opacity: 1 }, { opacity: 0 }, { phase: "remove" });
}
function buildResetPathFn(opts) {
  return (_node) => ({
    visible: opts.getVisible(),
    opacity: opts.getOpacity(),
    clipScalingX: 1,
    clip: false
  });
}
function updateClipPath({ nodeDataDependencies }, path) {
  const toFinite = (value) => isFinite(value) ? value : 0;
  path.clipX = toFinite(nodeDataDependencies.seriesRectWidth);
  path.clipY = toFinite(nodeDataDependencies.seriesRectHeight);
}
var CROSS_FILTER_AREA_FILL_OPACITY_FACTOR = 0.125;
var CROSS_FILTER_AREA_STROKE_OPACITY_FACTOR = 0.25;
var AreaSeries = class extends CartesianSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      directionKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS,
      directionNames: DEFAULT_CARTESIAN_DIRECTION_NAMES,
      pathsPerSeries: ["fill", "stroke"],
      pathsZIndexSubOrderOffset: [0, 1e3],
      hasMarkers: true,
      markerSelectionGarbageCollection: false,
      pickModes: [
        2,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      animationResetFns: {
        path: buildResetPathFn({ getVisible: () => this.visible, getOpacity: () => this.getOpacity() }),
        label: resetLabelFn,
        marker: (node, datum) => ({ ...resetMarkerFn(node), ...resetMarkerPositionFn(node, datum) })
      }
    });
    this.properties = new AreaSeriesProperties();
    this.connectsToYAxis = true;
    this.backgroundGroup = new Group({
      name: `${this.id}-background`,
      zIndex: 0
      /* BACKGROUND */
    });
    this._isStacked = void 0;
  }
  get pickModeAxis() {
    return "main";
  }
  renderToOffscreenCanvas() {
    return super.renderToOffscreenCanvas() || this.contextNodeData != null && (this.contextNodeData.fillData.spans.length > RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD || this.contextNodeData.strokeData.spans.length > RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD);
  }
  attachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.attachSeries(seriesContentNode, seriesNode, annotationNode);
    seriesContentNode.appendChild(this.backgroundGroup);
  }
  detachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.detachSeries(seriesContentNode, seriesNode, annotationNode);
    seriesContentNode?.removeChild(this.backgroundGroup);
  }
  attachPaths([fill, stroke]) {
    this.backgroundGroup.appendChild(fill);
    this.contentGroup.appendChild(stroke);
    stroke.zIndex = -1;
  }
  isStacked() {
    const stackCount = this.seriesGrouping?.stackCount ?? 1;
    return stackCount > 1;
  }
  setSeriesIndex(index) {
    const isStacked = this.isStacked();
    if (!super.setSeriesIndex(index) && this._isStacked === isStacked)
      return false;
    this._isStacked = isStacked;
    if (isStacked) {
      this.backgroundGroup.zIndex = [0, index];
      this.contentGroup.zIndex = [
        1,
        index,
        0
        /* FOREGROUND */
      ];
    } else {
      this.backgroundGroup.zIndex = [1, index, 0, 0];
      this.contentGroup.zIndex = [1, index, 0, 1];
    }
    return true;
  }
  async processData(dataController) {
    if (this.data == null || !this.properties.isValid()) {
      return;
    }
    const { data, visible, seriesGrouping: { groupIndex = this.id, stackCount = 1 } = {} } = this;
    const { xKey, yKey, yFilterKey, connectMissingData, normalizedTo } = this.properties;
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const xScale = this.axes[
      "x"
      /* X */
    ]?.scale;
    const yScale = this.axes[
      "y"
      /* Y */
    ]?.scale;
    const { xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
    const idMap = {
      value: `area-stack-${groupIndex}-yValue`,
      values: `area-stack-${groupIndex}-yValues`,
      stack: `area-stack-${groupIndex}-yValue-stack`,
      marker: `area-stack-${groupIndex}-yValues-marker`
    };
    const extraProps = [];
    if (isDefined(normalizedTo)) {
      extraProps.push(normaliseGroupTo(Object.values(idMap), normalizedTo, "range"));
    }
    if (animationEnabled) {
      extraProps.push(animationValidation());
    }
    const common = { invalidValue: null };
    if ((isDefined(normalizedTo) || connectMissingData) && stackCount > 1) {
      common.invalidValue = 0;
    }
    if (!visible) {
      common.forceValue = 0;
    }
    await this.requestDataModel(dataController, data, {
      props: [
        keyProperty(xKey, xScaleType, { id: "xValue" }),
        valueProperty(yKey, yScaleType, { id: `yValueRaw`, ...common }),
        ...yFilterKey != null ? [valueProperty(yFilterKey, yScaleType, { id: "yFilterRaw" })] : [],
        ...groupStackValueProperty(yKey, yScaleType, { id: `yValueStack`, ...common, groupId: idMap.stack }),
        valueProperty(yKey, yScaleType, { id: `yValue`, ...common, groupId: idMap.value }),
        ...groupAccumulativeValueProperty(
          yKey,
          "window",
          "current",
          { id: `yValueEnd`, ...common, groupId: idMap.values },
          yScaleType
        ),
        ...groupAccumulativeValueProperty(
          yKey,
          "normal",
          "current",
          { id: `yValueCumulative`, ...common, groupId: idMap.marker },
          yScaleType
        ),
        ...extraProps
      ],
      groupByKeys: true,
      groupByData: false
    });
    this.animationState.transition("updateData");
  }
  getSeriesDomain(direction) {
    const { processedData, dataModel, axes } = this;
    if (!processedData || !dataModel || !processedData.rawData?.length)
      return [];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    const keyDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
    const keys = dataModel.getDomain(this, `xValue`, "key", processedData);
    const yExtent = dataModel.getDomain(this, `yValueEnd`, "value", processedData);
    if (direction === "x") {
      if (keyDef?.def.type === "key" && keyDef.def.valueType === "category") {
        return keys;
      }
      return fixNumericExtent(extent(keys));
    } else if (yAxis instanceof LogAxis || yAxis instanceof TimeAxis) {
      return fixNumericExtent(yExtent);
    } else {
      const fixedYExtent = [yExtent[0] > 0 ? 0 : yExtent[0], yExtent[1] < 0 ? 0 : yExtent[1]];
      return fixNumericExtent(fixedYExtent);
    }
  }
  getSeriesRange(_direction, visibleRange) {
    const { dataModel, processedData } = this;
    if (!dataModel || !processedData)
      return [NaN, NaN];
    const xScale = this.axes[
      "x"
      /* X */
    ].scale;
    const xValues = dataModel.resolveKeysById(this, `xValue`, processedData);
    const [x0, x1] = visibleRangeIndices(xValues.length, visibleRange, (index) => {
      const x = xScale.convert(xValues[index]);
      return [x, x];
    });
    const [y0, y1] = dataModel.getDomainBetweenRange(this, ["yValueEnd"], [x0, x1], processedData);
    return [Math.min(y0, 0), Math.max(y1, 0)];
  }
  createNodeData() {
    const { axes, data, processedData, dataModel } = this;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!xAxis || !yAxis || !data || !dataModel || !processedData?.rawData.length || processedData.type !== "grouped" || !this.properties.isValid()) {
      return;
    }
    const {
      yKey,
      xKey,
      yFilterKey,
      marker,
      label,
      fill: seriesFill,
      stroke: seriesStroke,
      connectMissingData,
      interpolation
    } = this.properties;
    const { scale: xScale } = xAxis;
    const { scale: yScale } = yAxis;
    const { isContinuousY } = this.getScaleInformation({ xScale, yScale });
    const xOffset = (xScale.bandwidth ?? 0) / 2;
    const xValues = dataModel.resolveKeysById(this, "xValue", processedData);
    const yEndValues = dataModel.resolveColumnById(this, `yValueEnd`, processedData);
    const yRawValues = dataModel.resolveColumnById(this, `yValueRaw`, processedData);
    const yCumulativeValues = dataModel.resolveColumnById(this, `yValueCumulative`, processedData);
    const yFilterValues = yFilterKey != null ? dataModel.resolveColumnById(this, "yFilterRaw", processedData) : void 0;
    const yStackValues = dataModel.resolveColumnById(this, "yValueStack", processedData);
    const createMarkerCoordinate = (xDatum, yEnd, rawYDatum) => {
      let currY;
      if (isDefined(this.properties.normalizedTo) ? isContinuousY && isContinuous(rawYDatum) : !isNaN(rawYDatum)) {
        currY = yEnd;
      }
      return {
        x: xScale.convert(xDatum) + xOffset,
        y: yScale.convert(currY),
        size: marker.size
      };
    };
    const labelData = [];
    const markerData = [];
    const { visibleSameStackCount } = this.ctx.seriesStateManager.getVisiblePeerGroupIndex(this);
    let crossFiltering = false;
    const { rawData } = processedData;
    processedData.groups.forEach(({ datumIndices }) => {
      datumIndices.forEach((datumIndex) => {
        const xDatum = xValues[datumIndex];
        if (xDatum == null)
          return;
        const seriesDatum = rawData[datumIndex];
        const yDatum = yRawValues[datumIndex];
        const yValueCumulative = yCumulativeValues[datumIndex];
        const yValueEnd = yEndValues[datumIndex];
        const validPoint = Number.isFinite(yDatum);
        const point = createMarkerCoordinate(xDatum, +yValueCumulative, yDatum);
        const selected = yFilterValues != null ? yFilterValues[datumIndex] === yDatum : void 0;
        if (selected === false) {
          crossFiltering = true;
        }
        if (validPoint && marker) {
          markerData.push({
            index: datumIndex,
            series: this,
            itemId: yKey,
            datum: seriesDatum,
            datumIndex,
            midPoint: { x: point.x, y: point.y },
            cumulativeValue: yValueEnd,
            yValue: yDatum,
            xValue: xDatum,
            yKey,
            xKey,
            point,
            fill: marker.fill ?? seriesFill,
            stroke: marker.stroke ?? seriesStroke,
            strokeWidth: marker.strokeWidth ?? this.getStrokeWidth(this.properties.strokeWidth),
            selected
          });
        }
        if (validPoint && label) {
          const labelText = this.getLabelText(label, {
            value: yDatum,
            datum: seriesDatum,
            xKey,
            yKey,
            xName: this.properties.xName,
            yName: this.properties.yName
          });
          labelData.push({
            index: datumIndex,
            series: this,
            itemId: yKey,
            datum: seriesDatum,
            x: point.x,
            y: point.y,
            labelText
          });
        }
      });
    });
    const spansForPoints = (points) => {
      return points.flatMap((p) => {
        return Array.isArray(p) ? interpolatePoints(p, interpolation) : new Array(p.skip).fill(null);
      });
    };
    const dataIndices = processedData.groups.flatMap((group) => group.datumIndices);
    const createPoint = (xDatum, yDatum) => ({
      point: {
        x: xScale.convert(xDatum) + xOffset,
        y: yScale.convert(yDatum)
      },
      xDatum,
      yDatum
    });
    const getSeriesSpans = (index) => {
      const points = [];
      for (let dataIndicesIndex = 0; dataIndicesIndex < dataIndices.length; dataIndicesIndex += 1) {
        const datumIndex = dataIndices[dataIndicesIndex];
        const xDatum = xValues[datumIndex];
        const yValueStack = yStackValues[datumIndex];
        const yDatum = yValueStack[index];
        const yDatumIsFinite = Number.isFinite(yDatum);
        if (connectMissingData && !yDatumIsFinite)
          continue;
        const lastYValueStack = dataIndicesIndex > 0 ? yStackValues[dataIndices[dataIndicesIndex - 1]] : void 0;
        const nextYValueStack = dataIndicesIndex < dataIndices.length - 1 ? yStackValues[dataIndices[dataIndicesIndex + 1]] : void 0;
        let yValueEndBackwards = 0;
        let yValueEndForwards = 0;
        for (let j = 0; j <= index; j += 1) {
          const value = yValueStack[j];
          if (Number.isFinite(value)) {
            const lastWasFinite = lastYValueStack == null || Number.isFinite(lastYValueStack[j]);
            const nextWasFinite = nextYValueStack == null || Number.isFinite(nextYValueStack[j]);
            if (lastWasFinite) {
              yValueEndBackwards += value;
            }
            if (nextWasFinite) {
              yValueEndForwards += value;
            }
          }
        }
        const currentPoints = points[points.length - 1];
        if (!connectMissingData && (yValueEndBackwards !== yValueEndForwards || !yDatumIsFinite)) {
          if (!yDatumIsFinite && Array.isArray(currentPoints) && currentPoints.length === 1) {
            points[points.length - 1] = { skip: 1 };
          } else {
            const pointBackwards = createPoint(xDatum, yValueEndBackwards);
            const pointForwards = createPoint(xDatum, yValueEndForwards);
            if (Array.isArray(currentPoints)) {
              currentPoints.push(pointBackwards);
            } else if (currentPoints != null) {
              currentPoints.skip += 1;
            }
            points.push(yDatumIsFinite ? [pointForwards] : { skip: 0 });
          }
        } else {
          const yValueEnd = Math.max(yValueEndBackwards, yValueEndForwards);
          const point = createPoint(xDatum, yValueEnd);
          if (Array.isArray(currentPoints)) {
            currentPoints.push(point);
          } else if (currentPoints != null) {
            currentPoints.skip += 1;
            points.push([point]);
          } else {
            points.push([point]);
          }
        }
      }
      return spansForPoints(points);
    };
    const stackIndex = this.seriesGrouping?.stackIndex ?? 0;
    const getAxisSpans = () => {
      const yValueZeroPoints = dataIndices.map((datumIndex) => {
        const xDatum = xValues[datumIndex];
        const yValueStack = yStackValues[datumIndex];
        const yDatum = yValueStack[stackIndex];
        if (connectMissingData && !Number.isFinite(yDatum))
          return;
        return createPoint(xDatum, 0);
      }).filter((x) => x != null);
      return interpolatePoints(yValueZeroPoints, interpolation);
    };
    const currentSeriesSpans = getSeriesSpans(stackIndex);
    const phantomSpans = currentSeriesSpans.map(() => null);
    for (let j = stackIndex - 1; j >= -1; j -= 1) {
      let spans;
      for (let i = 0; i < phantomSpans.length; i += 1) {
        if (phantomSpans[i] != null)
          continue;
        spans ?? (spans = j !== -1 ? getSeriesSpans(j) : getAxisSpans());
        phantomSpans[i] = spans[i];
      }
    }
    const fillSpans = currentSeriesSpans.map((span, index) => span ?? phantomSpans[index]);
    const strokeSpans = currentSeriesSpans.filter((span) => span != null);
    const context = {
      itemId: yKey,
      fillData: { itemId: yKey, spans: fillSpans, phantomSpans },
      strokeData: { itemId: yKey, spans: strokeSpans },
      labelData,
      nodeData: markerData,
      scales: this.calculateScaling(),
      visible: this.visible,
      stackVisible: visibleSameStackCount > 0,
      crossFiltering
    };
    return context;
  }
  isPathOrSelectionDirty() {
    return this.properties.marker.isDirty();
  }
  markerFactory() {
    const { shape } = this.properties.marker;
    const MarkerShape = getMarker(shape);
    return new MarkerShape();
  }
  updatePathNodes(opts) {
    const { opacity, visible, animationEnabled } = opts;
    const [fill, stroke] = opts.paths;
    const crossFiltering = this.contextNodeData?.crossFiltering === true;
    const strokeWidth = this.getStrokeWidth(this.properties.strokeWidth);
    stroke.setProperties({
      fill: void 0,
      lineCap: "round",
      lineJoin: "round",
      pointerEvents: 1,
      stroke: this.properties.stroke,
      strokeWidth,
      strokeOpacity: this.properties.strokeOpacity * (crossFiltering ? CROSS_FILTER_AREA_STROKE_OPACITY_FACTOR : 1),
      lineDash: this.properties.lineDash,
      lineDashOffset: this.properties.lineDashOffset,
      opacity,
      visible: visible || animationEnabled
    });
    fill.setProperties({
      stroke: void 0,
      lineJoin: "round",
      pointerEvents: 1,
      fill: this.properties.fill,
      fillOpacity: this.properties.fillOpacity * (crossFiltering ? CROSS_FILTER_AREA_FILL_OPACITY_FACTOR : 1),
      fillShadow: this.properties.shadow,
      opacity,
      visible: visible || animationEnabled
    });
    updateClipPath(this, stroke);
    updateClipPath(this, fill);
  }
  updatePaths(opts) {
    this.updateAreaPaths(opts.paths, opts.contextData);
  }
  updateAreaPaths(paths, contextData) {
    for (const path of paths) {
      path.visible = contextData.visible;
    }
    if (contextData.visible) {
      this.updateFillPath(paths, contextData);
      this.updateStrokePath(paths, contextData);
    } else {
      for (const path of paths) {
        path.path.clear();
        path.markDirty();
      }
    }
  }
  updateFillPath(paths, contextData) {
    const [fill] = paths;
    fill.path.clear();
    plotAreaPathFill(fill, contextData.fillData);
    fill.markDirty();
  }
  updateStrokePath(paths, contextData) {
    const { spans } = contextData.strokeData;
    const [, stroke] = paths;
    stroke.path.clear();
    plotLinePathStroke(stroke, spans);
    stroke.markDirty();
  }
  updateMarkerSelection(opts) {
    const { nodeData, markerSelection } = opts;
    const markersEnabled = this.properties.marker.enabled || this.contextNodeData?.crossFiltering === true;
    if (this.properties.marker.isDirty()) {
      markerSelection.clear();
      markerSelection.cleanup();
    }
    return markerSelection.update(markersEnabled ? nodeData : []);
  }
  getMarkerItemBaseStyle(highlighted) {
    const { marker } = this.properties;
    const highlightStyle = highlighted ? this.properties.highlightStyle.item : void 0;
    return {
      fill: highlightStyle?.fill ?? marker.fill,
      fillOpacity: highlightStyle?.fillOpacity ?? marker.fillOpacity,
      stroke: highlightStyle?.stroke ?? marker.stroke,
      strokeWidth: highlightStyle?.strokeWidth ?? marker.strokeWidth,
      strokeOpacity: highlightStyle?.strokeOpacity ?? marker.strokeOpacity
    };
  }
  getMarkerItemStyleOverrides(datumId, datum, xValue, yValue, format, highlighted) {
    const { marker } = this.properties;
    const { itemStyler } = marker;
    if (itemStyler == null)
      return;
    const { id: seriesId, properties } = this;
    const { xKey, yKey } = properties;
    const { xDomain, yDomain } = this.cachedDatumCallback("domain", () => ({
      xDomain: this.getSeriesDomain(
        "x"
        /* X */
      ),
      yDomain: this.getSeriesDomain(
        "y"
        /* Y */
      )
    }));
    return this.cachedDatumCallback(createDatumId(datumId, highlighted ? "highlight" : "node"), () => {
      return itemStyler({
        seriesId,
        ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain),
        xValue,
        yValue,
        highlighted,
        ...format
      });
    });
  }
  updateMarkerNodes(opts) {
    const { markerSelection, isHighlight: highlighted } = opts;
    const { xKey, yKey, marker, fill, stroke, strokeWidth, fillOpacity, strokeOpacity, highlightStyle } = this.properties;
    const xDomain = this.getSeriesDomain(
      "x"
      /* X */
    );
    const yDomain = this.getSeriesDomain(
      "y"
      /* Y */
    );
    const baseStyle = mergeDefaults(highlighted && highlightStyle.item, marker.getStyle(), {
      fill,
      stroke,
      strokeWidth,
      fillOpacity,
      strokeOpacity
    });
    markerSelection.each((node, datum) => {
      this.updateMarkerStyle(
        node,
        marker,
        { ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain), highlighted },
        baseStyle,
        { selected: datum.selected }
      );
    });
    if (!highlighted) {
      this.properties.marker.markClean();
    }
  }
  updateLabelSelection(opts) {
    const { labelData, labelSelection } = opts;
    return labelSelection.update(labelData);
  }
  updateLabelNodes(opts) {
    const { labelSelection } = opts;
    const { enabled: labelEnabled, fontStyle, fontWeight, fontSize, fontFamily, color } = this.properties.label;
    labelSelection.each((text, datum) => {
      const { x, y, labelText } = datum;
      if (labelText && labelEnabled && this.visible) {
        text.fontStyle = fontStyle;
        text.fontWeight = fontWeight;
        text.fontSize = fontSize;
        text.fontFamily = fontFamily;
        text.textAlign = "center";
        text.textBaseline = "bottom";
        text.text = labelText;
        text.x = x;
        text.y = y - 10;
        text.fill = color;
        text.visible = true;
      } else {
        text.visible = false;
      }
    });
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, axes, properties } = this;
    const { xKey, xName, yKey, yName, tooltip } = properties;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!dataModel || !processedData || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
    const yValue = dataModel.resolveColumnById(this, `yValueRaw`, processedData)[datumIndex];
    if (xValue == null)
      return;
    const format = this.getMarkerItemBaseStyle(false);
    Object.assign(
      format,
      this.getMarkerItemStyleOverrides(String(datumIndex), datum, xValue, yValue, format, false)
    );
    return tooltip.formatTooltip(
      {
        heading: xAxis.formatDatum(xValue),
        symbol: this.legendItemSymbol(),
        data: [{ label: yName, fallbackLabel: yKey, value: yAxis.formatDatum(yValue) }]
      },
      {
        seriesId,
        datum,
        title: yName,
        xKey,
        xName,
        yKey,
        yName,
        ...format,
        ...this.getModuleTooltipParams()
      }
    );
  }
  legendItemSymbol() {
    const { fill, stroke, fillOpacity, strokeOpacity, strokeWidth, lineDash, marker } = this.properties;
    const useAreaFill = !marker.enabled || marker.fill === void 0;
    return {
      marker: {
        shape: marker.shape,
        fill: useAreaFill ? fill : marker.fill,
        fillOpacity: useAreaFill ? fillOpacity : marker.fillOpacity,
        stroke: marker.stroke ?? stroke,
        strokeOpacity: marker.strokeOpacity ?? strokeOpacity,
        strokeWidth: marker.strokeWidth ?? 0,
        enabled: marker.enabled || strokeWidth <= 0
      },
      line: {
        stroke,
        strokeOpacity,
        strokeWidth,
        lineDash
      }
    };
  }
  getLegendData(legendType) {
    if (!this.properties.isValid() || legendType !== "category") {
      return [];
    }
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    const { yKey: itemId, yName, legendItemName, showInLegend } = this.properties;
    return [
      {
        legendType,
        id: seriesId,
        itemId,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId }),
        label: {
          text: legendItemName ?? yName ?? itemId
        },
        symbol: this.legendItemSymbol(),
        legendItemName,
        hideInLegend: !showInLegend
      }
    ];
  }
  animateEmptyUpdateReady(animationData) {
    const { markerSelection, labelSelection, contextData, paths } = animationData;
    const { animationManager } = this.ctx;
    this.updateAreaPaths(paths, contextData);
    pathSwipeInAnimation(this, animationManager, ...paths);
    resetMotion([markerSelection], resetMarkerPositionFn);
    markerSwipeScaleInAnimation(this, animationManager, markerSelection);
    seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection);
  }
  animateReadyResize(animationData) {
    const { contextData, paths } = animationData;
    this.updateAreaPaths(paths, contextData);
    super.animateReadyResize(animationData);
  }
  animateWaitingUpdateReady(animationData) {
    const { animationManager } = this.ctx;
    const { markerSelection, labelSelection, contextData, paths, previousContextData } = animationData;
    const [fill, stroke] = paths;
    if (fill == null && stroke == null)
      return;
    this.resetMarkerAnimation(animationData);
    this.resetLabelAnimation(animationData);
    const update = () => {
      this.resetPathAnimation(animationData);
      this.updateAreaPaths(paths, contextData);
    };
    const skip = () => {
      animationManager.skipCurrentBatch();
      update();
    };
    if (contextData == null || previousContextData == null) {
      update();
      markerFadeInAnimation(this, animationManager, "added", markerSelection);
      pathFadeInAnimation(this, "fill_path_properties", animationManager, "add", fill);
      pathFadeInAnimation(this, "stroke_path_properties", animationManager, "add", stroke);
      seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection);
      return;
    }
    if (contextData.crossFiltering !== previousContextData.crossFiltering) {
      skip();
      return;
    }
    const fns = prepareAreaPathAnimation(contextData, previousContextData);
    if (fns === void 0) {
      skip();
      return;
    } else if (fns.status === "no-op") {
      return;
    }
    markerFadeInAnimation(this, animationManager, void 0, markerSelection);
    fromToMotion(this.id, "fill_path_properties", animationManager, [fill], fns.fill.pathProperties);
    pathMotion(this.id, "fill_path_update", animationManager, [fill], fns.fill.path);
    fromToMotion(this.id, "stroke_path_properties", animationManager, [stroke], fns.stroke.pathProperties);
    pathMotion(this.id, "stroke_path_update", animationManager, [stroke], fns.stroke.path);
    seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection);
    this.ctx.animationManager.animate({
      id: this.id,
      groupId: "reset_after_animation",
      phase: "trailing",
      from: {},
      to: {},
      onComplete: () => this.updateAreaPaths(paths, contextData)
    });
  }
  isLabelEnabled() {
    return this.properties.label.enabled;
  }
  nodeFactory() {
    return new Group();
  }
  getFormattedMarkerStyle(datum) {
    const { xKey, yKey } = datum;
    const xDomain = this.getSeriesDomain(
      "x"
      /* X */
    );
    const yDomain = this.getSeriesDomain(
      "y"
      /* Y */
    );
    return this.getMarkerStyle(this.properties.marker, {
      ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain),
      highlighted: true
    });
  }
  computeFocusBounds(opts) {
    return computeMarkerFocusBounds(this, opts);
  }
};
AreaSeries.className = "AreaSeries";
AreaSeries.type = "area";
var AreaSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["cartesian"],
  identifier: "area",
  moduleFactory: (ctx) => new AreaSeries(ctx),
  stackable: true,
  tooltipDefaults: { range: "nearest" },
  defaultAxes: [
    {
      type: "number",
      position: "left"
      /* LEFT */
    },
    {
      type: "category",
      position: "bottom"
      /* BOTTOM */
    }
  ],
  themeTemplate: {
    series: {
      nodeClickRange: "nearest",
      tooltip: { position: { type: "node" } },
      fillOpacity: 0.8,
      strokeOpacity: 1,
      strokeWidth: 0,
      lineDash: [0],
      lineDashOffset: 0,
      shadow: {
        enabled: false,
        color: DEFAULT_SHADOW_COLOUR,
        xOffset: 3,
        yOffset: 3,
        blur: 5
      },
      interpolation: {
        type: "linear",
        // @ts-expect-error - users shouldn't specify all options, but we have to for theming to work
        tension: 1,
        position: "end"
      },
      marker: {
        enabled: false,
        shape: "circle",
        size: 7,
        strokeWidth: 0
      },
      label: {
        enabled: false,
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_LABEL_COLOUR
      }
    }
  },
  paletteFactory: (params) => {
    const { marker } = markerPaletteFactory(params);
    return { fill: marker.fill, stroke: marker.stroke, marker };
  }
};
function addHitTestersToQuadtree(quadtree, hitTesters) {
  for (const node of hitTesters) {
    const datum = node.datum;
    if (datum === void 0) {
      Logger.error("undefined datum");
    } else {
      quadtree.addValue(node, datum);
    }
  }
}
function findQuadtreeMatch(series, point) {
  const { x, y } = point;
  const { nearest, distanceSquared: distanceSquared3 } = series.getQuadTree().find(x, y);
  if (nearest !== void 0) {
    return { datum: nearest.value, distance: Math.sqrt(distanceSquared3) };
  }
  return void 0;
}
var AbstractBarSeriesProperties = class extends CartesianSeriesProperties {
  constructor() {
    super(...arguments);
    this.direction = "vertical";
  }
};
__decorateClass([
  Validate(DIRECTION)
], AbstractBarSeriesProperties.prototype, "direction", 2);
var AbstractBarSeries = class extends CartesianSeries {
  constructor() {
    super(...arguments);
    this.groupScale = new BandScale();
    this.smallestDataInterval = void 0;
    this.largestDataInterval = void 0;
  }
  padBandExtent(keys, alignStart) {
    const ratio2 = typeof alignStart === "boolean" ? 1 : 0.5;
    const scalePadding = isFiniteNumber(this.smallestDataInterval) ? this.smallestDataInterval * ratio2 : 0;
    const keysExtent = extent(keys) ?? [NaN, NaN];
    if (typeof alignStart === "boolean") {
      keysExtent[alignStart ? 0 : 1] -= (alignStart ? 1 : -1) * scalePadding;
    } else {
      keysExtent[0] -= scalePadding;
      keysExtent[1] += scalePadding;
    }
    return fixNumericExtent(keysExtent);
  }
  getBandScalePadding() {
    return { inner: 0.3, outer: 0.15 };
  }
  shouldFlipXY() {
    return !this.isVertical();
  }
  isVertical() {
    return this.properties.direction === "vertical";
  }
  getBarDirection() {
    return this.shouldFlipXY() ? "x" : "y";
  }
  getCategoryDirection() {
    return this.shouldFlipXY() ? "y" : "x";
  }
  getValueAxis() {
    const direction = this.getBarDirection();
    return this.axes[direction];
  }
  getCategoryAxis() {
    const direction = this.getCategoryDirection();
    return this.axes[direction];
  }
  getBandwidth(xAxis) {
    return ContinuousScale.is(xAxis.scale) ? xAxis.scale.calcBandwidth(this.smallestDataInterval) : xAxis.scale.bandwidth;
  }
  updateGroupScale(xAxis) {
    const domain = [];
    const { groupScale } = this;
    const xBandWidth = this.getBandwidth(xAxis);
    const { index: groupIndex, visibleGroupCount } = this.ctx.seriesStateManager.getVisiblePeerGroupIndex(this);
    for (let groupIdx = 0; groupIdx < visibleGroupCount; groupIdx++) {
      domain.push(String(groupIdx));
    }
    groupScale.domain = domain;
    groupScale.range = [0, xBandWidth ?? 0];
    if (xAxis instanceof GroupedCategoryAxis) {
      groupScale.paddingInner = xAxis.groupPaddingInner;
    } else if (xAxis instanceof CategoryAxis) {
      groupScale.paddingInner = xAxis.groupPaddingInner;
      groupScale.round = groupScale.padding !== 0;
    } else {
      groupScale.padding = 0;
    }
    const barWidth = groupScale.bandwidth >= 1 ? (
      // Pixel-rounded value for low-volume bar charts.
      groupScale.bandwidth
    ) : (
      // Handle high-volume bar charts gracefully.
      groupScale.rawBandwidth
    );
    return { barWidth, groupIndex };
  }
  resolveKeyDirection(direction) {
    if (this.getBarDirection() === "x") {
      if (direction === "x") {
        return "y";
      }
      return "x";
    }
    return direction;
  }
  initQuadTree(quadtree) {
    addHitTestersToQuadtree(quadtree, this.datumNodesIter());
  }
  pickNodeClosestDatum(point) {
    return findQuadtreeMatch(this, point);
  }
};
var BarSeriesLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.placement = "inside-center";
    this.padding = 0;
  }
};
__decorateClass([
  Validate(UNION(["inside-center", "inside-start", "inside-end", "outside-start", "outside-end"], "a placement"))
], BarSeriesLabel.prototype, "placement", 2);
__decorateClass([
  Validate(NUMBER)
], BarSeriesLabel.prototype, "padding", 2);
var BarSeriesProperties = class extends AbstractBarSeriesProperties {
  constructor() {
    super(...arguments);
    this.fill = "#c16068";
    this.fillOpacity = 1;
    this.stroke = "#874349";
    this.strokeWidth = 1;
    this.strokeOpacity = 1;
    this.lineDash = [0];
    this.lineDashOffset = 0;
    this.cornerRadius = 0;
    this.crisp = void 0;
    this.shadow = new DropShadow();
    this.label = new BarSeriesLabel();
    this.tooltip = new SeriesTooltip();
    this.sparklineMode = false;
    this.fastDataProcessing = false;
  }
};
__decorateClass([
  Validate(STRING)
], BarSeriesProperties.prototype, "xKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BarSeriesProperties.prototype, "xName", 2);
__decorateClass([
  Validate(STRING)
], BarSeriesProperties.prototype, "yKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BarSeriesProperties.prototype, "yName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BarSeriesProperties.prototype, "yFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BarSeriesProperties.prototype, "stackGroup", 2);
__decorateClass([
  Validate(NUMBER, { optional: true })
], BarSeriesProperties.prototype, "normalizedTo", 2);
__decorateClass([
  Validate(COLOR_STRING)
], BarSeriesProperties.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO)
], BarSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING)
], BarSeriesProperties.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], BarSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO)
], BarSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH)
], BarSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], BarSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], BarSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
  Validate(BOOLEAN, { optional: true })
], BarSeriesProperties.prototype, "crisp", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], BarSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
  Validate(OBJECT, { optional: true })
], BarSeriesProperties.prototype, "shadow", 2);
__decorateClass([
  Validate(OBJECT)
], BarSeriesProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], BarSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
  Validate(BOOLEAN)
], BarSeriesProperties.prototype, "sparklineMode", 2);
__decorateClass([
  Validate(BOOLEAN)
], BarSeriesProperties.prototype, "fastDataProcessing", 2);
function updateRect(rect, config) {
  rect.crisp = config.crisp ?? true;
  rect.fill = config.fill;
  rect.stroke = config.stroke;
  rect.strokeWidth = config.strokeWidth;
  rect.fillOpacity = config.fillOpacity;
  rect.strokeOpacity = config.strokeOpacity;
  rect.lineDash = config.lineDash;
  rect.lineDashOffset = config.lineDashOffset;
  rect.fillShadow = config.fillShadow;
  rect.topLeftCornerRadius = config.topLeftCornerRadius !== false ? config.cornerRadius ?? 0 : 0;
  rect.topRightCornerRadius = config.topRightCornerRadius !== false ? config.cornerRadius ?? 0 : 0;
  rect.bottomRightCornerRadius = config.bottomRightCornerRadius !== false ? config.cornerRadius ?? 0 : 0;
  rect.bottomLeftCornerRadius = config.bottomLeftCornerRadius !== false ? config.cornerRadius ?? 0 : 0;
  rect.visible = config.visible ?? true;
}
function getRectConfig(series, id, {
  datum,
  isHighlighted,
  style,
  highlightStyle,
  itemStyler,
  seriesId,
  ...opts
}) {
  const {
    fill,
    fillOpacity,
    stroke,
    strokeWidth,
    strokeOpacity,
    lineDash,
    lineDashOffset,
    cornerRadius = 0
  } = mergeDefaults(isHighlighted && highlightStyle, style);
  let format;
  if (itemStyler) {
    format = series.cachedDatumCallback(
      createDatumId(id, isHighlighted ? "highlight" : "node"),
      () => itemStyler({
        datum: datum.datum,
        xKey: datum.xKey,
        fill,
        fillOpacity,
        stroke,
        strokeWidth,
        strokeOpacity,
        lineDash,
        lineDashOffset,
        cornerRadius,
        highlighted: isHighlighted,
        seriesId,
        ...opts
      })
    );
  }
  return {
    fill: format?.fill ?? fill,
    fillOpacity: format?.fillOpacity ?? fillOpacity,
    stroke: format?.stroke ?? stroke,
    strokeWidth: format?.strokeWidth ?? strokeWidth,
    strokeOpacity: format?.strokeOpacity ?? strokeOpacity,
    lineDash: format?.lineDash ?? lineDash,
    lineDashOffset: format?.lineDashOffset ?? lineDashOffset,
    cornerRadius: format?.cornerRadius ?? cornerRadius,
    topLeftCornerRadius: style.topLeftCornerRadius,
    topRightCornerRadius: style.topRightCornerRadius,
    bottomRightCornerRadius: style.bottomRightCornerRadius,
    bottomLeftCornerRadius: style.bottomLeftCornerRadius,
    fillShadow: style.fillShadow
  };
}
function checkCrisp(scale2, visibleRange, smallestDataInterval, largestDataInterval) {
  if (visibleRange != null) {
    const [visibleMin, visibleMax] = visibleRange;
    const isZoomed = visibleMin !== 0 || visibleMax !== 1;
    if (isZoomed)
      return false;
  }
  if (ContinuousScale.is(scale2)) {
    const spacing = scale2.calcBandwidth(largestDataInterval) - scale2.calcBandwidth(smallestDataInterval);
    if (spacing > 0 && spacing < 1)
      return false;
  }
  return true;
}
var isDatumNegative = (datum) => {
  return isNegative(datum.yValue ?? 0);
};
function collapsedStartingBarPosition(isVertical, axes, mode) {
  const { startingX, startingY } = getStartingValues(isVertical, axes);
  const calculate = (datum, prevDatum) => {
    let x = isVertical ? datum.x : startingX;
    let y = isVertical ? startingY : datum.y;
    let width2 = isVertical ? datum.width : 0;
    let height2 = isVertical ? 0 : datum.height;
    const { opacity } = datum;
    if (prevDatum && (isNaN(x) || isNaN(y))) {
      ({ x, y } = prevDatum);
      width2 = isVertical ? prevDatum.width : 0;
      height2 = isVertical ? 0 : prevDatum.height;
      if (isVertical && !isDatumNegative(prevDatum)) {
        y += prevDatum.height;
      } else if (!isVertical && isDatumNegative(prevDatum)) {
        x += prevDatum.width;
      }
    }
    let clipBBox;
    if (datum.clipBBox == null) {
      clipBBox = void 0;
    } else if (isDatumNegative(datum)) {
      clipBBox = isVertical ? new BBox(x, y - height2, width2, height2) : new BBox(x - width2, y, width2, height2);
    } else {
      clipBBox = new BBox(x, y, width2, height2);
    }
    return { x, y, width: width2, height: height2, clipBBox, opacity };
  };
  return { isVertical, calculate, mode };
}
function midpointStartingBarPosition(isVertical, mode) {
  return {
    isVertical,
    calculate: (datum) => {
      return {
        x: isVertical ? datum.x : datum.x + datum.width / 2,
        y: isVertical ? datum.y + datum.height / 2 : datum.y,
        width: isVertical ? datum.width : 0,
        height: isVertical ? 0 : datum.height,
        clipBBox: datum.clipBBox,
        opacity: datum.opacity
      };
    },
    mode
  };
}
function prepareBarAnimationFunctions(initPos) {
  const isRemoved = (datum) => datum == null || isNaN(datum.x) || isNaN(datum.y);
  const fromFn = (rect, datum, status) => {
    if (status === "updated" && isRemoved(datum)) {
      status = "removed";
    } else if (status === "updated" && isRemoved(rect.previousDatum)) {
      status = "added";
    }
    let source;
    if (status === "added" && rect.previousDatum == null && initPos.mode === "fade") {
      source = {
        ...resetBarSelectionsFn(rect, datum),
        opacity: 0
      };
    } else if (status === "unknown" || status === "added") {
      source = initPos.calculate(datum, rect.previousDatum);
    } else {
      source = {
        x: rect.x,
        y: rect.y,
        width: rect.width,
        height: rect.height,
        clipBBox: rect.clipBBox,
        opacity: rect.opacity
      };
    }
    const phase = NODE_UPDATE_STATE_TO_PHASE_MAPPING[status];
    return { ...source, phase };
  };
  const toFn = (rect, datum, status) => {
    if (status === "removed" && rect.datum == null && initPos.mode === "fade") {
      return { ...resetBarSelectionsFn(rect, datum), opacity: 0 };
    } else if (status === "removed" || isRemoved(datum)) {
      return initPos.calculate(datum, rect.previousDatum);
    } else {
      return {
        x: datum.x,
        y: datum.y,
        width: datum.width,
        height: datum.height,
        clipBBox: datum.clipBBox,
        opacity: datum.opacity
      };
    }
  };
  return { toFn, fromFn };
}
function getStartingValues(isVertical, axes) {
  const axis = axes[
    isVertical ? "y" : "x"
    /* X */
  ];
  let startingX = Infinity;
  let startingY = 0;
  if (!axis) {
    return { startingX, startingY };
  }
  if (isVertical) {
    startingY = axis.scale.convert(ContinuousScale.is(axis.scale) ? 0 : Math.max(...axis.range));
  } else {
    startingX = axis.scale.convert(ContinuousScale.is(axis.scale) ? 0 : Math.min(...axis.range));
  }
  return { startingX, startingY };
}
function resetBarSelectionsFn(_node, { x, y, width: width2, height: height2, clipBBox, opacity }) {
  return { x, y, width: width2, height: height2, clipBBox, opacity };
}
function computeBarFocusBounds(datum) {
  if (datum === void 0)
    return void 0;
  const { x, y, width: width2, height: height2 } = datum;
  return new BBox(x, y, width2, height2);
}
function updateLabelNode(textNode, label, labelDatum) {
  if (label.enabled && labelDatum) {
    const { x, y, text, textAlign, textBaseline } = labelDatum;
    const { color: fill, fontStyle, fontWeight, fontSize, fontFamily } = label;
    textNode.setProperties({
      visible: true,
      x,
      y,
      text,
      fill,
      fontStyle,
      fontWeight,
      fontSize,
      fontFamily,
      textAlign,
      textBaseline
    });
  } else {
    textNode.visible = false;
  }
}
var placements = {
  "inside-start": { inside: true, direction: -1, textAlignment: 1 },
  "inside-end": { inside: true, direction: 1, textAlignment: -1 },
  "outside-start": { inside: false, direction: -1, textAlignment: -1 },
  "outside-end": { inside: false, direction: 1, textAlignment: 1 }
};
function adjustLabelPlacement({
  isUpward,
  isVertical,
  placement,
  padding = 0,
  rect
}) {
  let x = rect.x + rect.width / 2;
  let y = rect.y + rect.height / 2;
  let textAlign = "center";
  let textBaseline = "middle";
  if (placement !== "inside-center") {
    const barDirection = (isUpward ? 1 : -1) * (isVertical ? -1 : 1);
    const { direction, textAlignment } = placements[placement];
    const displacementRatio = (direction + 1) * 0.5;
    if (isVertical) {
      const y0 = isUpward ? rect.y + rect.height : rect.y;
      const height2 = rect.height * barDirection;
      y = y0 + height2 * displacementRatio + padding * textAlignment * barDirection;
      textBaseline = textAlignment === barDirection ? "top" : "bottom";
    } else {
      const x0 = isUpward ? rect.x : rect.x + rect.width;
      const width2 = rect.width * barDirection;
      x = x0 + width2 * displacementRatio + padding * textAlignment * barDirection;
      textAlign = textAlignment === barDirection ? "left" : "right";
    }
  }
  return { x, y, textAlign, textBaseline };
}
var X_MIN = 0;
var X_MAX = 1;
var Y_MIN = 2;
var Y_MAX = 3;
var SPAN2 = 4;
var BarSeries = class extends AbstractBarSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      directionKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS,
      directionNames: DEFAULT_CARTESIAN_DIRECTION_NAMES,
      pickModes: [
        2,
        // Only used in sparklineMode
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      pathsPerSeries: [],
      hasHighlightedLabels: true,
      datumSelectionGarbageCollection: false,
      animationAlwaysUpdateSelections: true,
      animationResetFns: {
        datum: resetBarSelectionsFn,
        label: resetLabelFn
      }
    });
    this.properties = new BarSeriesProperties();
    this.connectsToYAxis = true;
    this.dataAggregationFilters = void 0;
  }
  get pickModeAxis() {
    return this.properties.sparklineMode ? "main" : void 0;
  }
  crossFilteringEnabled() {
    return this.properties.yFilterKey != null && (this.seriesGrouping == null || this.seriesGrouping.stackIndex === 0);
  }
  async processData(dataController) {
    if (!this.properties.isValid() || !this.data) {
      return;
    }
    const { xKey, yKey, yFilterKey, normalizedTo, fastDataProcessing } = this.properties;
    const { seriesGrouping: { groupIndex = this.id } = {}, data } = this;
    const groupCount2 = this.seriesGrouping?.groupCount ?? 0;
    const stackCount = this.seriesGrouping?.stackCount ?? 0;
    const grouped = !fastDataProcessing || normalizedTo != null || groupCount2 > 1 || stackCount > 1;
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const xScale = this.getCategoryAxis()?.scale;
    const yScale = this.getValueAxis()?.scale;
    const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
    const stackGroupName = `bar-stack-${groupIndex}-yValues`;
    const stackGroupTrailingName = `${stackGroupName}-trailing`;
    const visibleProps = this.visible ? {} : { forceValue: 0 };
    const props = [
      keyProperty(xKey, xScaleType, { id: "xValue" }),
      valueProperty(yKey, yScaleType, { id: `yValue-raw`, invalidValue: null, ...visibleProps })
    ];
    if (this.crossFilteringEnabled()) {
      props.push(
        valueProperty(yFilterKey, yScaleType, {
          id: `yFilterValue`,
          invalidValue: null,
          ...visibleProps
        })
      );
    }
    if (grouped) {
      props.push(
        ...groupAccumulativeValueProperty(
          yKey,
          "normal",
          "current",
          {
            id: `yValue-end`,
            rangeId: `yValue-range`,
            invalidValue: null,
            missingValue: 0,
            groupId: stackGroupName,
            separateNegative: true,
            ...visibleProps
          },
          yScaleType
        ),
        ...groupAccumulativeValueProperty(
          yKey,
          "trailing",
          "current",
          {
            id: `yValue-start`,
            invalidValue: null,
            missingValue: 0,
            groupId: stackGroupTrailingName,
            separateNegative: true,
            ...visibleProps
          },
          yScaleType
        )
      );
    }
    if (isContinuousX) {
      props.push(SMALLEST_KEY_INTERVAL, LARGEST_KEY_INTERVAL);
    }
    if (isFiniteNumber(normalizedTo)) {
      props.push(normaliseGroupTo([stackGroupName, stackGroupTrailingName], Math.abs(normalizedTo), "range"));
    }
    if (animationEnabled && this.processedData) {
      props.push(diff(this.id, this.processedData));
    }
    if (animationEnabled || !grouped) {
      props.push(animationValidation());
    }
    const { dataModel, processedData } = await this.requestDataModel(dataController, data, {
      props,
      groupByKeys: grouped,
      groupByData: !grouped
    });
    this.dataAggregationFilters = this.aggregateData(dataModel, processedData);
    this.smallestDataInterval = processedData.reduced?.smallestKeyInterval;
    this.largestDataInterval = processedData.reduced?.largestKeyInterval;
    this.animationState.transition("updateData");
  }
  getSeriesDomain(direction) {
    const { processedData, dataModel } = this;
    if (dataModel == null || processedData == null)
      return [];
    const rawData = processedData.rawDataSources?.get(this.id) ?? processedData.rawData;
    if (rawData == null || rawData.length === 0)
      return [];
    const keyDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
    const keys = dataModel.getDomain(this, `xValue`, "key", processedData);
    let yExtent = processedData.type === "grouped" ? dataModel.getDomain(this, `yValue-end`, "value", processedData) : dataModel.getDomain(this, `yValue-raw`, "value", processedData);
    const yFilterExtent = this.crossFilteringEnabled() ? dataModel.getDomain(this, `yFilterValue`, "value", processedData) : void 0;
    if (yFilterExtent != null) {
      yExtent = [Math.min(yExtent[0], yFilterExtent[0]), Math.max(yExtent[1], yFilterExtent[1])];
    }
    if (direction === this.getCategoryDirection()) {
      if (keyDef?.def.type === "key" && keyDef.def.valueType === "category") {
        return keys;
      }
      return this.padBandExtent(keys);
    } else if (this.getValueAxis() instanceof LogAxis) {
      return fixNumericExtent(yExtent);
    } else {
      const fixedYExtent = [Math.min(0, yExtent[0]), Math.max(0, yExtent[1])];
      return fixNumericExtent(fixedYExtent);
    }
  }
  getSeriesRange(_direction, visibleRange) {
    const { dataModel, processedData } = this;
    if (!dataModel || !processedData || this.getBarDirection() === "x")
      return [NaN, NaN];
    const xScale = this.axes[
      "x"
      /* X */
    ].scale;
    const xValues = dataModel.resolveKeysById(this, `xValue`, processedData);
    const barWidth = xScale.bandwidth ?? 0;
    const [x0, x1] = visibleRangeIndices(xValues.length, visibleRange, (index) => {
      const x = xScale.convert(xValues[index]);
      return [x, x + barWidth];
    });
    const [y0, y1] = dataModel.getDomainBetweenRange(
      this,
      processedData.type === "ungrouped" ? ["yValue-raw"] : ["yValue-end"],
      [x0, x1],
      processedData
    );
    return [Math.min(y0, 0), Math.max(y1, 0)];
  }
  aggregateData(_dataModel, _processedData) {
    return;
  }
  visibleRange(length2, _x0, _x1, _xFor) {
    return [0, length2];
  }
  createNodeData() {
    const { dataModel, processedData, groupScale, dataAggregationFilters } = this;
    const xAxis = this.getCategoryAxis();
    const yAxis = this.getValueAxis();
    if (!dataModel || !processedData || !xAxis || !yAxis || !this.properties.isValid()) {
      return;
    }
    const rawData = processedData.rawDataSources?.get(this.id) ?? processedData.rawData;
    if (rawData == null || rawData.length === 0)
      return;
    const xScale = xAxis.scale;
    const yScale = yAxis.scale;
    const { xKey, yKey, xName, yName, fill, stroke, strokeWidth, cornerRadius, legendItemName, label } = this.properties;
    const yReversed = yAxis.isReversed();
    const { barWidth, groupIndex: groupScaleIndex } = this.updateGroupScale(xAxis);
    const groupOffset = groupScale.convert(String(groupScaleIndex));
    const barOffset = ContinuousScale.is(xScale) ? barWidth * -0.5 : 0;
    const xValues = dataModel.resolveKeysById(this, `xValue`, processedData);
    const yRawValues = dataModel.resolveColumnById(this, `yValue-raw`, processedData);
    const yFilterValues = this.crossFilteringEnabled() ? dataModel.resolveColumnById(this, `yFilterValue`, processedData) : void 0;
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const xPosition = (index) => xScale.convert(xValues[index]) + groupOffset + barOffset;
    const bboxBottom = yScale.convert(0);
    const nodeDatum = ({
      datum,
      datumIndex,
      valueIndex,
      xValue,
      yValue,
      cumulativeValue,
      phantom,
      currY,
      prevY,
      x,
      width: width2,
      isPositive,
      yRange,
      labelText,
      opacity,
      crossScale = 1
    }) => {
      const isUpward = isPositive !== yReversed;
      const y = yScale.convert(currY);
      const bottomY = yScale.convert(prevY);
      const bboxHeight = yScale.convert(yRange);
      const barAlongX = this.getBarDirection() === "x";
      const xOffset = width2 * 0.5 * (1 - crossScale);
      const rect = {
        x: barAlongX ? Math.min(y, bottomY) : x + xOffset,
        y: barAlongX ? x + xOffset : Math.min(y, bottomY),
        width: barAlongX ? Math.abs(bottomY - y) : width2 * crossScale,
        height: barAlongX ? width2 * crossScale : Math.abs(bottomY - y)
      };
      const clipBBox = new BBox(rect.x, rect.y, rect.width, rect.height);
      const barRect = {
        x: barAlongX ? Math.min(bboxBottom, bboxHeight) : x + xOffset,
        y: barAlongX ? x + xOffset : Math.min(bboxBottom, bboxHeight),
        width: barAlongX ? Math.abs(bboxBottom - bboxHeight) : width2 * crossScale,
        height: barAlongX ? width2 * crossScale : Math.abs(bboxBottom - bboxHeight)
      };
      const lengthRatioMultiplier = this.shouldFlipXY() ? rect.height : rect.width;
      return {
        series: this,
        itemId: phantom ? createDatumId(yKey, phantom) : yKey,
        datum,
        datumIndex,
        valueIndex,
        cumulativeValue,
        phantom,
        xValue,
        yValue,
        yKey,
        xKey,
        capDefaults: {
          lengthRatioMultiplier,
          lengthMax: lengthRatioMultiplier
        },
        x: barRect.x,
        y: barRect.y,
        width: barRect.width,
        height: barRect.height,
        midPoint: { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 },
        fill,
        stroke,
        opacity,
        strokeWidth,
        cornerRadius,
        topLeftCornerRadius: barAlongX !== isUpward,
        topRightCornerRadius: isUpward,
        bottomRightCornerRadius: barAlongX === isUpward,
        bottomLeftCornerRadius: !isUpward,
        clipBBox,
        label: labelText != null ? {
          text: labelText,
          ...adjustLabelPlacement({
            isUpward,
            isVertical: !barAlongX,
            placement: label.placement,
            padding: label.padding,
            rect
          })
        } : void 0,
        missing: yValue == null,
        focusable: !phantom
      };
    };
    const phantomNodes = [];
    const nodes = [];
    const labels = [];
    const handleDatum = (datumIndex, valueIndex, x, width2, yStart, yEnd, yRange, opacity) => {
      const xValue = xValues[datumIndex];
      if (xValue == null)
        return;
      const yRawValue = yRawValues[datumIndex];
      const yFilterValue = yFilterValues != null ? Number(yFilterValues[datumIndex]) : void 0;
      const isPositive = yRawValue >= 0 && !Object.is(yRawValue, -0);
      if (!Number.isFinite(yEnd))
        return;
      if (yFilterValue != null && !Number.isFinite(yFilterValue))
        return;
      const labelText = yRawValue != null ? this.getLabelText(this.properties.label, {
        datum: rawData[datumIndex],
        value: yFilterValue ?? yRawValue,
        xKey,
        yKey,
        xName,
        yName,
        legendItemName
      }) : void 0;
      const inset = yFilterValue != null && yFilterValue > yRawValue;
      const nodeData = nodeDatum({
        datum: rawData[datumIndex],
        datumIndex,
        valueIndex,
        xValue,
        yValue: yFilterValue ?? yRawValue,
        cumulativeValue: yFilterValue ?? yEnd,
        phantom: false,
        currY: yFilterValue != null ? yStart + yFilterValue : yEnd,
        prevY: yStart,
        x,
        width: width2,
        isPositive,
        yRange: Math.max(yStart + (yFilterValue ?? -Infinity), yRange),
        labelText,
        opacity,
        crossScale: inset ? 0.6 : void 0
      });
      nodes.push(nodeData);
      labels.push(nodeData);
      if (yFilterValue != null) {
        const phantomNodeData = nodeDatum({
          datum: rawData[datumIndex],
          datumIndex,
          valueIndex,
          xValue,
          yValue: yFilterValue,
          cumulativeValue: yFilterValue,
          phantom: true,
          currY: yEnd,
          prevY: yStart,
          x,
          width: width2,
          isPositive,
          yRange,
          labelText: void 0,
          opacity,
          crossScale: void 0
        });
        phantomNodes.push(phantomNodeData);
      }
    };
    const [x0, x1] = findMinMax(xAxis.range);
    const [r0, r1] = xScale.range;
    const range3 = r1 - r0;
    const dataAggregationFilter = dataAggregationFilters?.find((f) => f.maxRange > range3);
    if (processedData.type === "grouped") {
      const width2 = barWidth;
      const yStartValues = dataModel.resolveColumnById(this, `yValue-start`, processedData);
      const yEndValues = dataModel.resolveColumnById(this, `yValue-end`, processedData);
      const yRangeIndex = dataModel.resolveProcessedDataIndexById(this, `yValue-range`);
      processedData.groups.forEach(({ datumIndices, aggregation }) => {
        const yRanges = aggregation[yRangeIndex];
        datumIndices.forEach((datumIndex, valueIndex) => {
          const x = xPosition(datumIndex);
          const yRawValue = yRawValues[datumIndex];
          const isPositive = yRawValue >= 0 && !Object.is(yRawValue, -0);
          const yStart = Number(yStartValues[datumIndex]);
          const yEnd = Number(yEndValues[datumIndex]);
          const yRange = yRanges[isPositive ? 1 : 0];
          handleDatum(datumIndex, valueIndex, x, width2, yStart, yEnd, yRange, 1);
        });
      });
    } else if (dataAggregationFilter == null) {
      const width2 = barWidth;
      let [start2, end2] = this.visibleRange(rawData.length, x0, x1, xPosition);
      if (processedData.rawData.length < 1e3) {
        start2 = 0;
        end2 = processedData.rawData.length;
      }
      for (let datumIndex = start2; datumIndex < end2; datumIndex += 1) {
        const x = xPosition(datumIndex);
        const yEnd = Number(yRawValues[datumIndex]);
        handleDatum(datumIndex, 0, x, width2, 0, yEnd, yEnd, 1);
      }
    } else {
      const { maxRange, indexData } = dataAggregationFilter;
      const [start2, end2] = this.visibleRange(maxRange, x0, x1, (index) => {
        const aggIndex = index * SPAN2;
        const xMinIndex = indexData[aggIndex + X_MIN];
        const xMaxIndex = indexData[aggIndex + X_MAX];
        const midDatumIndex = (xMinIndex + xMaxIndex) / 2 | 0;
        return xMinIndex !== -1 ? xPosition(midDatumIndex) : NaN;
      });
      for (let i = start2; i < end2; i += 1) {
        const aggIndex = i * SPAN2;
        const xMinIndex = indexData[aggIndex + X_MIN];
        const xMaxIndex = indexData[aggIndex + X_MAX];
        const yMinIndex = indexData[aggIndex + Y_MIN];
        const yMaxIndex = indexData[aggIndex + Y_MAX];
        if (xMinIndex === -1)
          continue;
        const x = xPosition((xMinIndex + xMaxIndex) / 2 | 0);
        const width2 = Math.abs(xPosition(xMaxIndex) - xPosition(xMinIndex)) + barWidth;
        const yEndMax = xValues[yMaxIndex] != null ? Number(yRawValues[yMaxIndex]) : NaN;
        const yEndMin = xValues[yMinIndex] != null ? Number(yRawValues[yMinIndex]) : NaN;
        if (yEndMax > 0) {
          const opacity = yEndMin >= 0 ? yEndMin / yEndMax : 1;
          handleDatum(yMaxIndex, 0, x, width2, 0, yEndMax, yEndMax, opacity);
        }
        if (yEndMin < 0) {
          const opacity = yEndMax <= 0 ? yEndMax / yEndMin : 1;
          handleDatum(yMinIndex, 1, x, width2, 0, yEndMin, yEndMin, opacity);
        }
      }
    }
    return {
      itemId: yKey,
      nodeData: phantomNodes.length > 0 ? [...phantomNodes, ...nodes] : nodes,
      labelData: labels,
      scales: this.calculateScaling(),
      visible: this.visible || animationEnabled,
      groupScale: this.getScaling(this.groupScale)
    };
  }
  nodeFactory() {
    return new Rect();
  }
  getHighlightData(nodeData, highlightedItem) {
    const highlightItem = nodeData.find(
      (nodeDatum) => nodeDatum.datum === highlightedItem.datum && !nodeDatum.phantom
    );
    return highlightItem != null ? [highlightItem] : void 0;
  }
  updateDatumSelection(opts) {
    return opts.datumSelection.update(opts.nodeData, void 0, (datum) => this.getDatumId(datum));
  }
  getItemBaseStyle(highlighted) {
    const { properties } = this;
    const { cornerRadius } = properties;
    const highlightStyle = highlighted ? properties.highlightStyle.item : void 0;
    return {
      fill: highlightStyle?.fill ?? properties.fill,
      fillOpacity: highlightStyle?.fillOpacity ?? properties.fillOpacity,
      stroke: highlightStyle?.stroke ?? properties.stroke,
      strokeWidth: highlightStyle?.strokeWidth ?? properties.strokeWidth,
      strokeOpacity: highlightStyle?.strokeOpacity ?? properties.strokeOpacity,
      lineDash: highlightStyle?.lineDash ?? properties.lineDash ?? [],
      lineDashOffset: highlightStyle?.lineDashOffset ?? properties.lineDashOffset,
      cornerRadius
    };
  }
  getItemStyleOverrides(datumId, datum, xValue, yValue, format, highlighted) {
    const { id: seriesId, properties } = this;
    const { xKey, yKey, itemStyler } = properties;
    if (itemStyler == null)
      return;
    const { xDomain, yDomain } = this.cachedDatumCallback("domain", () => ({
      xDomain: this.getSeriesDomain(
        "x"
        /* X */
      ),
      yDomain: this.getSeriesDomain(
        "y"
        /* Y */
      )
    }));
    return this.cachedDatumCallback(createDatumId(datumId, highlighted ? "highlight" : "node"), () => {
      return itemStyler({
        seriesId,
        ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain),
        xValue,
        yValue,
        highlighted,
        ...format
      });
    });
  }
  updateDatumNodes(opts) {
    if (!this.properties.isValid()) {
      return;
    }
    const {
      xKey,
      yKey,
      stackGroup,
      fill,
      fillOpacity,
      stroke,
      strokeWidth,
      strokeOpacity,
      lineDash,
      lineDashOffset,
      itemStyler,
      shadow,
      highlightStyle: { item: itemHighlightStyle }
    } = this.properties;
    const xAxis = this.axes[
      "x"
      /* X */
    ];
    const crisp = this.properties.crisp ?? checkCrisp(xAxis?.scale, xAxis?.visibleRange, this.smallestDataInterval, this.largestDataInterval);
    const categoryAlongX = this.getCategoryDirection() === "x";
    const style = {
      fill,
      stroke,
      lineDash,
      lineDashOffset,
      fillShadow: shadow,
      strokeWidth: this.getStrokeWidth(strokeWidth),
      fillOpacity: 0,
      strokeOpacity: 0
    };
    const xDomain = this.getSeriesDomain(
      "x"
      /* X */
    );
    const yDomain = this.getSeriesDomain(
      "y"
      /* Y */
    );
    opts.datumSelection.each((rect, datum) => {
      const rectParams = {
        seriesId: this.id,
        isHighlighted: opts.isHighlight,
        highlightStyle: itemHighlightStyle,
        style,
        itemStyler,
        stackGroup,
        ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain)
      };
      style.fillOpacity = fillOpacity * (datum.phantom ? 0.2 : 1);
      style.strokeOpacity = strokeOpacity * (datum.phantom ? 0.2 : 1);
      style.cornerRadius = datum.cornerRadius;
      style.topLeftCornerRadius = datum.topLeftCornerRadius;
      style.topRightCornerRadius = datum.topRightCornerRadius;
      style.bottomRightCornerRadius = datum.bottomRightCornerRadius;
      style.bottomLeftCornerRadius = datum.bottomLeftCornerRadius;
      const visible = categoryAlongX ? (datum.clipBBox?.width ?? datum.width) > 0 : (datum.clipBBox?.height ?? datum.height) > 0;
      const config = getRectConfig(this, this.getDatumId(datum), rectParams);
      config.crisp = crisp;
      config.visible = visible;
      updateRect(rect, config);
    });
  }
  updateLabelSelection(opts) {
    const data = this.isLabelEnabled() ? opts.labelData : [];
    return opts.labelSelection.update(data, (text) => {
      text.pointerEvents = 1;
    });
  }
  updateLabelNodes(opts) {
    opts.labelSelection.each((textNode, datum) => {
      updateLabelNode(textNode, this.properties.label, datum.label);
    });
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, properties } = this;
    const { xKey, xName, yKey, yName, legendItemName, stackGroup, tooltip } = properties;
    const xAxis = this.getCategoryAxis();
    const yAxis = this.getValueAxis();
    if (!dataModel || !processedData || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
    const yValue = dataModel.resolveColumnById(this, `yValue-raw`, processedData)[datumIndex];
    if (xValue == null)
      return;
    const format = this.getItemBaseStyle(false);
    Object.assign(format, this.getItemStyleOverrides(String(datumIndex), datum, xValue, yValue, format, false));
    return tooltip.formatTooltip(
      {
        heading: xAxis.formatDatum(xValue),
        symbol: this.legendItemSymbol(),
        data: [{ label: yName, fallbackLabel: yKey, value: yAxis.formatDatum(yValue) }]
      },
      {
        seriesId,
        datum,
        title: yName,
        xKey,
        xName,
        yKey,
        yName,
        legendItemName,
        stackGroup,
        ...format,
        ...this.getModuleTooltipParams()
      }
    );
  }
  legendItemSymbol() {
    const { fill, stroke, strokeWidth, fillOpacity, strokeOpacity } = this.properties;
    return {
      marker: {
        fill,
        fillOpacity,
        stroke,
        strokeWidth,
        strokeOpacity
      }
    };
  }
  getLegendData(legendType) {
    const { showInLegend } = this.properties;
    if (legendType !== "category" || !this.properties.isValid()) {
      return [];
    }
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    const { yKey: itemId, yName, legendItemName } = this.properties;
    return [
      {
        legendType: "category",
        id: seriesId,
        itemId,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId }),
        label: { text: legendItemName ?? yName ?? itemId },
        symbol: this.legendItemSymbol(),
        legendItemName,
        hideInLegend: !showInLegend
      }
    ];
  }
  animateEmptyUpdateReady({ datumSelection, labelSelection, annotationSelections }) {
    const fns = prepareBarAnimationFunctions(collapsedStartingBarPosition(this.isVertical(), this.axes, "normal"));
    fromToMotion(this.id, "nodes", this.ctx.animationManager, [datumSelection], fns);
    seriesLabelFadeInAnimation(this, "labels", this.ctx.animationManager, labelSelection);
    seriesLabelFadeInAnimation(this, "annotations", this.ctx.animationManager, ...annotationSelections);
  }
  animateWaitingUpdateReady(data) {
    const { datumSelection, labelSelection, annotationSelections, previousContextData } = data;
    this.ctx.animationManager.stopByAnimationGroupId(this.id);
    let dataDiff = this.processedData?.reduced?.diff?.[this.id];
    if (dataDiff == null && this.processedData?.reduced?.diff != null) {
      dataDiff = {
        changed: true,
        added: new Set(Array.from(datumSelection, ({ datum }) => this.getDatumId(datum))),
        updated: /* @__PURE__ */ new Set(),
        removed: /* @__PURE__ */ new Set(),
        moved: /* @__PURE__ */ new Set()
      };
    }
    const mode = previousContextData == null ? "fade" : "normal";
    const fns = prepareBarAnimationFunctions(collapsedStartingBarPosition(this.isVertical(), this.axes, mode));
    fromToMotion(
      this.id,
      "nodes",
      this.ctx.animationManager,
      [datumSelection],
      fns,
      (_, datum) => this.getDatumId(datum),
      dataDiff
    );
    const scalingChanged = previousContextData != null && (!areScalingEqual(data.contextData.scales.x, previousContextData.scales.x) || !areScalingEqual(data.contextData.scales.y, previousContextData.scales.y) || !areScalingEqual(
      data.contextData.groupScale,
      data.previousContextData.groupScale
    ));
    const hasMotion = (dataDiff?.changed ?? false) || scalingChanged;
    if (hasMotion) {
      seriesLabelFadeInAnimation(this, "labels", this.ctx.animationManager, labelSelection);
      seriesLabelFadeInAnimation(this, "annotations", this.ctx.animationManager, ...annotationSelections);
    }
  }
  getDatumId(datum) {
    return createDatumId(datum.xValue, datum.valueIndex, datum.phantom);
  }
  isLabelEnabled() {
    return this.properties.label.enabled;
  }
  computeFocusBounds({ datumIndex }) {
    const datumBox = this.contextNodeData?.nodeData[datumIndex].clipBBox;
    return computeBarFocusBounds(datumBox);
  }
};
BarSeries.className = "BarSeries";
BarSeries.type = "bar";
var BarSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["cartesian"],
  identifier: "bar",
  moduleFactory: (ctx) => new BarSeries(ctx),
  stackable: true,
  groupable: true,
  tooltipDefaults: { range: "exact" },
  defaultAxes: swapAxisCondition(
    [
      {
        type: "number",
        position: "left"
        /* LEFT */
      },
      {
        type: "category",
        position: "bottom"
        /* BOTTOM */
      }
    ],
    (series) => series?.direction === "horizontal"
  ),
  themeTemplate: {
    series: {
      direction: "vertical",
      fillOpacity: 1,
      strokeWidth: 0,
      lineDash: [0],
      lineDashOffset: 0,
      label: {
        enabled: false,
        fontWeight: "normal",
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_INSIDE_SERIES_LABEL_COLOUR,
        placement: "inside-center"
      },
      shadow: {
        enabled: false,
        color: DEFAULT_SHADOW_COLOUR,
        xOffset: 3,
        yOffset: 3,
        blur: 5
      },
      errorBar: {
        cap: {
          lengthRatio: 0.3
        }
      }
    }
  },
  paletteFactory: singleSeriesPaletteFactory
};
var BubbleSeriesMarker = class extends SeriesMarker {
  constructor() {
    super(...arguments);
    this.maxSize = 30;
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER),
  SceneChangeDetection()
], BubbleSeriesMarker.prototype, "maxSize", 2);
__decorateClass([
  Validate(NUMBER_ARRAY, { optional: true }),
  SceneChangeDetection()
], BubbleSeriesMarker.prototype, "domain", 2);
var BubbleSeriesLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.placement = "top";
  }
};
__decorateClass([
  Validate(LABEL_PLACEMENT)
], BubbleSeriesLabel.prototype, "placement", 2);
var BubbleSeriesProperties = class extends CartesianSeriesProperties {
  constructor() {
    super(...arguments);
    this.colorRange = ["#ffff00", "#00ff00", "#0000ff"];
    this.label = new BubbleSeriesLabel();
    this.tooltip = new SeriesTooltip();
    this.marker = new BubbleSeriesMarker();
  }
};
__decorateClass([
  Validate(STRING)
], BubbleSeriesProperties.prototype, "xKey", 2);
__decorateClass([
  Validate(STRING)
], BubbleSeriesProperties.prototype, "yKey", 2);
__decorateClass([
  Validate(STRING)
], BubbleSeriesProperties.prototype, "sizeKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "colorKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "xFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "yFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "sizeFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "xName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "yName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "sizeName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "labelName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "colorName", 2);
__decorateClass([
  Validate(NUMBER_ARRAY, { optional: true })
], BubbleSeriesProperties.prototype, "colorDomain", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], BubbleSeriesProperties.prototype, "colorRange", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], BubbleSeriesProperties.prototype, "title", 2);
__decorateClass([
  ProxyProperty("marker.shape")
], BubbleSeriesProperties.prototype, "shape", 2);
__decorateClass([
  ProxyProperty("marker.size")
], BubbleSeriesProperties.prototype, "size", 2);
__decorateClass([
  ProxyProperty("marker.maxSize")
], BubbleSeriesProperties.prototype, "maxSize", 2);
__decorateClass([
  ProxyProperty("marker.domain", { optional: true })
], BubbleSeriesProperties.prototype, "domain", 2);
__decorateClass([
  ProxyProperty("marker.fill", { optional: true })
], BubbleSeriesProperties.prototype, "fill", 2);
__decorateClass([
  ProxyProperty("marker.fillOpacity")
], BubbleSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  ProxyProperty("marker.stroke", { optional: true })
], BubbleSeriesProperties.prototype, "stroke", 2);
__decorateClass([
  ProxyProperty("marker.strokeWidth")
], BubbleSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  ProxyProperty("marker.strokeOpacity")
], BubbleSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  ProxyProperty("marker.itemStyler", { optional: true })
], BubbleSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
  Validate(OBJECT)
], BubbleSeriesProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], BubbleSeriesProperties.prototype, "tooltip", 2);
var BubbleSeriesNodeEvent = class extends CartesianSeriesNodeEvent {
  constructor(type, nativeEvent, datum, series) {
    super(type, nativeEvent, datum, series);
    this.sizeKey = series.properties.sizeKey;
  }
};
var BubbleSeries = class extends CartesianSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      directionKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS,
      directionNames: DEFAULT_CARTESIAN_DIRECTION_NAMES,
      pickModes: [
        2,
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      pathsPerSeries: [],
      hasMarkers: true,
      markerSelectionGarbageCollection: false,
      animationResetFns: {
        label: resetLabelFn,
        marker: resetMarkerFn
      },
      usesPlacedLabels: true
    });
    this.NodeEvent = BubbleSeriesNodeEvent;
    this.clipFocusBox = false;
    this.properties = new BubbleSeriesProperties();
    this.sizeScale = new LinearScale();
    this.colorScale = new ColorScale();
  }
  get pickModeAxis() {
    return "main-category";
  }
  async processData(dataController) {
    if (!this.properties.isValid() || this.data == null || !this.visible)
      return;
    const xScale = this.axes[
      "x"
      /* X */
    ]?.scale;
    const yScale = this.axes[
      "y"
      /* Y */
    ]?.scale;
    const { xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
    const colorScaleType = this.colorScale.type;
    const sizeScaleType = this.sizeScale.type;
    const {
      xKey,
      yKey,
      sizeKey,
      xFilterKey,
      yFilterKey,
      sizeFilterKey,
      labelKey,
      colorDomain,
      colorRange,
      colorKey,
      marker
    } = this.properties;
    const { dataModel, processedData } = await this.requestDataModel(dataController, this.data, {
      props: [
        valueProperty(xKey, xScaleType, { id: `xValue` }),
        valueProperty(yKey, yScaleType, { id: `yValue` }),
        ...xFilterKey != null ? [valueProperty(xFilterKey, xScaleType, { id: `xFilterValue` })] : [],
        ...yFilterKey != null ? [valueProperty(yFilterKey, yScaleType, { id: `yFilterValue` })] : [],
        ...sizeFilterKey != null ? [valueProperty(sizeFilterKey, sizeScaleType, { id: `sizeFilterValue` })] : [],
        valueProperty(sizeKey, sizeScaleType, { id: `sizeValue` }),
        ...colorKey ? [valueProperty(colorKey, colorScaleType, { id: `colorValue` })] : [],
        ...labelKey ? [valueProperty(labelKey, "band", { id: `labelValue` })] : []
      ]
    });
    const sizeKeyIdx = dataModel.resolveProcessedDataIndexById(this, `sizeValue`);
    const processedSize = processedData.domain.values[sizeKeyIdx] ?? [];
    this.sizeScale.domain = marker.domain ? marker.domain : processedSize;
    if (colorKey) {
      const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, `colorValue`);
      this.colorScale.domain = colorDomain ?? processedData.domain.values[colorKeyIdx] ?? [];
      this.colorScale.range = colorRange;
      this.colorScale.update();
    }
    this.animationState.transition("updateData");
  }
  getSeriesDomain(direction) {
    const { dataModel, processedData } = this;
    if (!processedData || !dataModel)
      return [];
    const id = direction === "x" ? `xValue` : `yValue`;
    const dataDef = dataModel.resolveProcessedDataDefById(this, id);
    const domain = dataModel.getDomain(this, id, "value", processedData);
    if (dataDef?.def.type === "value" && dataDef?.def.valueType === "category") {
      return domain;
    }
    return fixNumericExtent(extent(domain));
  }
  getSeriesRange(_direction, _visibleRange) {
    return [NaN, NaN];
  }
  createNodeData() {
    const { axes, dataModel, processedData, colorScale, sizeScale, visible } = this;
    const {
      xKey,
      yKey,
      sizeKey,
      xFilterKey,
      yFilterKey,
      sizeFilterKey,
      labelKey,
      xName,
      yName,
      sizeName,
      labelName,
      label,
      colorKey,
      marker
    } = this.properties;
    const markerShape = getMarker(marker.shape);
    const { placement } = label;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!(dataModel && processedData?.rawData.length && visible && xAxis && yAxis)) {
      return;
    }
    const xDataValues = dataModel.resolveColumnById(this, `xValue`, processedData);
    const yDataValues = dataModel.resolveColumnById(this, `yValue`, processedData);
    const sizeDataValues = sizeKey != null ? dataModel.resolveColumnById(this, `sizeValue`, processedData) : void 0;
    const colorDataValues = colorKey != null ? dataModel.resolveColumnById(this, `colorValue`, processedData) : void 0;
    const labelDataValues = labelKey != null ? dataModel.resolveColumnById(this, `labelValue`, processedData) : void 0;
    const xFilterDataValues = xFilterKey != null ? dataModel.resolveColumnById(this, `xFilterValue`, processedData) : void 0;
    const yFilterDataValues = yFilterKey != null ? dataModel.resolveColumnById(this, `yFilterValue`, processedData) : void 0;
    const sizeFilterDataValues = sizeFilterKey != null ? dataModel.resolveColumnById(this, `sizeFilterValue`, processedData) : void 0;
    const xScale = xAxis.scale;
    const yScale = yAxis.scale;
    const xOffset = (xScale.bandwidth ?? 0) / 2;
    const yOffset = (yScale.bandwidth ?? 0) / 2;
    const nodeData = [];
    sizeScale.range = [marker.size, marker.maxSize];
    const font = label.getFont();
    const textMeasurer = CachedTextMeasurerPool.getMeasurer({ font });
    processedData.rawData.forEach((datum, datumIndex) => {
      const xDatum = xDataValues[datumIndex];
      const yDatum = yDataValues[datumIndex];
      const sizeValue = sizeDataValues?.[datumIndex];
      const x = xScale.convert(xDatum) + xOffset;
      const y = yScale.convert(yDatum) + yOffset;
      let selected;
      if (xFilterDataValues != null && yFilterDataValues != null) {
        selected = xFilterDataValues[datumIndex] === xDatum && yFilterDataValues[datumIndex] === yDatum;
        if (sizeFilterDataValues != null) {
          selected && (selected = sizeFilterDataValues[datumIndex] === sizeValue);
        }
      }
      const labelText = this.getLabelText(label, {
        value: labelDataValues != null ? labelDataValues[datumIndex] : yDatum,
        datum,
        xKey,
        yKey,
        sizeKey,
        labelKey,
        xName,
        yName,
        sizeName,
        labelName
      });
      const size = textMeasurer.measureText(String(labelText));
      const markerSize = sizeValue != null ? sizeScale.convert(sizeValue) : marker.size;
      const fill = colorDataValues != null ? colorScale.convert(colorDataValues[datumIndex]) : void 0;
      nodeData.push({
        series: this,
        itemId: yKey,
        yKey,
        xKey,
        datum,
        datumIndex,
        xValue: xDatum,
        yValue: yDatum,
        sizeValue,
        point: { x, y, size: markerSize },
        midPoint: { x, y },
        fill,
        label: { text: labelText, ...size },
        marker: markerShape,
        placement,
        selected
      });
    });
    return {
      itemId: yKey,
      nodeData,
      labelData: nodeData,
      scales: this.calculateScaling(),
      visible: this.visible
    };
  }
  isPathOrSelectionDirty() {
    return this.properties.marker.isDirty();
  }
  getLabelData() {
    if (!this.isLabelEnabled())
      return [];
    return this.contextNodeData?.labelData ?? [];
  }
  markerFactory() {
    const { shape } = this.properties.marker;
    const MarkerShape = getMarker(shape);
    return new MarkerShape();
  }
  updateMarkerSelection(opts) {
    const { nodeData, markerSelection } = opts;
    if (this.properties.marker.isDirty()) {
      markerSelection.clear();
      markerSelection.cleanup();
    }
    const data = this.properties.marker.enabled ? nodeData : [];
    return markerSelection.update(
      data,
      void 0,
      (datum) => createDatumId([datum.xValue, datum.yValue, datum.label.text])
    );
  }
  getMarkerItemBaseStyle(highlighted) {
    const { properties } = this;
    const { marker } = properties;
    const highlightStyle = highlighted ? properties.highlightStyle.item : void 0;
    return {
      fill: highlightStyle?.fill ?? marker.fill,
      fillOpacity: highlightStyle?.fillOpacity ?? marker.fillOpacity,
      stroke: highlightStyle?.stroke ?? marker.stroke,
      strokeWidth: highlightStyle?.strokeWidth ?? marker.strokeWidth,
      strokeOpacity: highlightStyle?.strokeOpacity ?? marker.strokeOpacity
    };
  }
  getMarkerItemStyleOverrides(datumId, datum, format, highlighted) {
    const { id: seriesId, properties } = this;
    const { xKey, yKey, sizeKey, labelKey, marker } = properties;
    const { itemStyler } = marker;
    if (itemStyler == null)
      return;
    return this.cachedDatumCallback(createDatumId(datumId, highlighted ? "highlight" : "node"), () => {
      return itemStyler({
        seriesId,
        datum,
        xKey,
        yKey,
        sizeKey,
        labelKey,
        highlighted,
        ...format
      });
    });
  }
  updateMarkerNodes(opts) {
    const { markerSelection, isHighlight: highlighted } = opts;
    const { xKey, yKey, sizeKey, labelKey, marker } = this.properties;
    const { size, shape, fill, fillOpacity, stroke, strokeWidth, strokeOpacity } = mergeDefaults(
      highlighted && this.properties.highlightStyle.item,
      marker.getStyle()
    );
    const baseStyle = { size, shape, fill, fillOpacity, stroke, strokeWidth, strokeOpacity };
    this.sizeScale.range = [marker.size, marker.maxSize];
    markerSelection.each((node, datum) => {
      this.updateMarkerStyle(node, marker, { datum, highlighted, xKey, yKey, sizeKey, labelKey }, baseStyle, {
        selected: datum.selected
      });
    });
    if (!highlighted) {
      this.properties.marker.markClean();
    }
  }
  updatePlacedLabelData(labelData) {
    this.labelSelection.update(
      labelData.map((v) => ({
        ...v.datum,
        point: {
          x: v.x,
          y: v.y,
          size: v.datum.point.size
        }
      })),
      (text) => {
        text.pointerEvents = 1;
      }
    );
    this.updateLabelNodes({ labelSelection: this.labelSelection });
  }
  updateLabelNodes(opts) {
    const { label } = this.properties;
    opts.labelSelection.each((text, datum) => {
      text.text = datum.label.text;
      text.fill = label.color;
      text.x = datum.point?.x ?? 0;
      text.y = datum.point?.y ?? 0;
      text.fontStyle = label.fontStyle;
      text.fontWeight = label.fontWeight;
      text.fontSize = label.fontSize;
      text.fontFamily = label.fontFamily;
      text.textAlign = "left";
      text.textBaseline = "top";
    });
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, axes, properties } = this;
    const { xKey, xName, yKey, yName, sizeKey, sizeName, labelKey, labelName, title, tooltip } = properties;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!dataModel || !processedData || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const xValue = dataModel.resolveColumnById(this, `xValue`, processedData)[datumIndex];
    const yValue = dataModel.resolveColumnById(this, `yValue`, processedData)[datumIndex];
    if (xValue == null)
      return;
    const data = [
      { label: xName, fallbackLabel: xKey, value: xAxis.formatDatum(xValue) },
      { label: yName, fallbackLabel: yKey, value: yAxis.formatDatum(yValue) }
    ];
    if (sizeKey != null) {
      const sizeValue = dataModel.resolveColumnById(this, `sizeValue`, processedData)[datumIndex];
      data.push({ label: sizeName, fallbackLabel: sizeKey, value: String(sizeValue) });
    }
    const format = this.getMarkerItemBaseStyle(false);
    Object.assign(format, this.getMarkerItemStyleOverrides(String(datumIndex), datum, format, false));
    return tooltip.formatTooltip(
      {
        title,
        symbol: this.legendItemSymbol(),
        data
      },
      {
        seriesId,
        datum,
        title: yKey,
        xKey,
        xName,
        yKey,
        yName,
        sizeKey,
        sizeName,
        labelKey,
        labelName,
        ...format,
        ...this.getModuleTooltipParams()
      }
    );
  }
  legendItemSymbol() {
    const { marker } = this.properties;
    const { shape, fill, stroke, fillOpacity, strokeOpacity, strokeWidth } = marker;
    return {
      marker: {
        shape,
        fill: fill ?? "rgba(0, 0, 0, 0)",
        stroke: stroke ?? "rgba(0, 0, 0, 0)",
        fillOpacity: fillOpacity ?? 1,
        strokeOpacity: strokeOpacity ?? 1,
        strokeWidth: strokeWidth ?? 0
      }
    };
  }
  getLegendData() {
    if (!this.properties.isValid()) {
      return [];
    }
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    const { yKey: itemId, yName, title } = this.properties;
    return [
      {
        legendType: "category",
        id: seriesId,
        itemId,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId }),
        label: {
          text: title ?? yName ?? itemId
        },
        symbol: this.legendItemSymbol()
      }
    ];
  }
  animateEmptyUpdateReady({ markerSelection, labelSelection }) {
    markerScaleInAnimation(this, this.ctx.animationManager, markerSelection);
    seriesLabelFadeInAnimation(this, "labels", this.ctx.animationManager, labelSelection);
  }
  isLabelEnabled() {
    return this.properties.label.enabled;
  }
  nodeFactory() {
    return new Group();
  }
  getFormattedMarkerStyle(datum) {
    const { xKey, yKey, sizeKey, labelKey } = this.properties;
    return this.getMarkerStyle(this.properties.marker, {
      datum,
      xKey,
      yKey,
      sizeKey,
      labelKey,
      highlighted: false
    });
  }
  computeFocusBounds(opts) {
    return computeMarkerFocusBounds(this, opts);
  }
};
BubbleSeries.className = "BubbleSeries";
BubbleSeries.type = "bubble";
var BubbleSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["cartesian"],
  identifier: "bubble",
  moduleFactory: (ctx) => new BubbleSeries(ctx),
  tooltipDefaults: { range: "nearest" },
  defaultAxes: [
    {
      type: "number",
      position: "bottom"
      /* BOTTOM */
    },
    {
      type: "number",
      position: "left"
      /* LEFT */
    }
  ],
  themeTemplate: {
    series: {
      shape: "circle",
      size: 7,
      maxSize: 30,
      fillOpacity: 0.8,
      tooltip: { position: { type: "node" } },
      label: {
        enabled: false,
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_LABEL_COLOUR
      }
    }
  },
  paletteFactory: singleSeriesPaletteFactory
};
var HistogramSeriesProperties = class extends CartesianSeriesProperties {
  constructor() {
    super(...arguments);
    this.fillOpacity = 1;
    this.strokeWidth = 1;
    this.strokeOpacity = 1;
    this.lineDash = [0];
    this.lineDashOffset = 0;
    this.cornerRadius = 0;
    this.areaPlot = false;
    this.aggregation = "sum";
    this.shadow = new DropShadow();
    this.label = new Label();
    this.tooltip = new SeriesTooltip();
  }
};
__decorateClass([
  Validate(STRING)
], HistogramSeriesProperties.prototype, "xKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], HistogramSeriesProperties.prototype, "yKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], HistogramSeriesProperties.prototype, "xName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], HistogramSeriesProperties.prototype, "yName", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], HistogramSeriesProperties.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO)
], HistogramSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(COLOR_STRING, { optional: true })
], HistogramSeriesProperties.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], HistogramSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO)
], HistogramSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH)
], HistogramSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], HistogramSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], HistogramSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
  Validate(BOOLEAN)
], HistogramSeriesProperties.prototype, "areaPlot", 2);
__decorateClass([
  Validate(ARRAY, { optional: true })
], HistogramSeriesProperties.prototype, "bins", 2);
__decorateClass([
  Validate(UNION(["count", "sum", "mean"], "a histogram aggregation"))
], HistogramSeriesProperties.prototype, "aggregation", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], HistogramSeriesProperties.prototype, "binCount", 2);
__decorateClass([
  Validate(OBJECT)
], HistogramSeriesProperties.prototype, "shadow", 2);
__decorateClass([
  Validate(OBJECT)
], HistogramSeriesProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], HistogramSeriesProperties.prototype, "tooltip", 2);
var defaultBinCount = 10;
var HistogramSeries = class extends CartesianSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      directionKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS,
      directionNames: DEFAULT_CARTESIAN_DIRECTION_NAMES,
      pickModes: [
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      datumSelectionGarbageCollection: false,
      animationResetFns: {
        datum: resetBarSelectionsFn,
        label: resetLabelFn
      }
    });
    this.properties = new HistogramSeriesProperties();
    this.calculatedBins = [];
  }
  // During processData phase, used to unify different ways of the user specifying
  // the bins. Returns bins in format[[min1, max1], [min2, max2], ... ].
  deriveBins(xDomain) {
    const binStarts = createTicks(xDomain[0], xDomain[1], defaultBinCount);
    const binSize = tickStep(xDomain[0], xDomain[1], defaultBinCount);
    const [firstBinEnd] = binStarts;
    const expandStartToBin = (n) => [n, n + binSize];
    return [[firstBinEnd - binSize, firstBinEnd], ...binStarts.map(expandStartToBin)];
  }
  calculateNiceBins(domain, binCount) {
    const startGuess = Math.floor(domain[0]);
    const stop = domain[1];
    const segments = binCount || 1;
    const { start: start2, binSize } = this.calculateNiceStart(startGuess, stop, segments);
    return this.getBins(start2, stop, binSize, segments);
  }
  getBins(start2, stop, step, count) {
    const bins = [];
    const precision = this.calculatePrecision(step);
    for (let i = 0; i < count; i++) {
      const a = Math.round((start2 + i * step) * precision) / precision;
      let b = Math.round((start2 + (i + 1) * step) * precision) / precision;
      if (i === count - 1) {
        b = Math.max(b, stop);
      }
      bins[i] = [a, b];
    }
    return bins;
  }
  calculatePrecision(step) {
    let precision = 10;
    if (isFinite(step) && step > 0) {
      while (step < 1) {
        precision *= 10;
        step *= 10;
      }
    }
    return precision;
  }
  calculateNiceStart(a, b, segments) {
    const binSize = Math.abs(b - a) / segments;
    const order = Math.floor(Math.log10(binSize));
    const magnitude = Math.pow(10, order);
    const start2 = Math.floor(a / magnitude) * magnitude;
    return {
      start: start2,
      binSize
    };
  }
  async processData(dataController) {
    if (!this.visible) {
      this.processedData = void 0;
      this.animationState.transition("updateData");
    }
    const { xKey, yKey, areaPlot, aggregation } = this.properties;
    const xScale = this.axes[
      "x"
      /* X */
    ]?.scale;
    const yScale = this.axes[
      "y"
      /* Y */
    ]?.scale;
    const { xScaleType, yScaleType } = this.getScaleInformation({ yScale, xScale });
    const props = [keyProperty(xKey, xScaleType), SORT_DOMAIN_GROUPS];
    if (yKey) {
      let aggProp = groupCount("groupAgg");
      if (aggregation === "count") {
      } else if (aggregation === "sum") {
        aggProp = groupSum("groupAgg");
      } else if (aggregation === "mean") {
        aggProp = groupAverage("groupAgg");
      }
      if (areaPlot) {
        aggProp = area("groupAgg", aggProp);
      }
      props.push(valueProperty(yKey, yScaleType, { invalidValue: void 0 }), aggProp);
    } else {
      let aggProp = groupCount("groupAgg");
      if (areaPlot) {
        aggProp = area("groupAgg", aggProp);
      }
      props.push(aggProp);
    }
    const groupByFn = (dataSet) => {
      const xExtent = fixNumericExtent(dataSet.domain.keys[0]);
      if (xExtent.length === 0) {
        dataSet.domain.groups = [];
        return () => [];
      }
      const bins = isNumber(this.properties.binCount) ? this.calculateNiceBins(xExtent, this.properties.binCount) : this.properties.bins ?? this.deriveBins(xExtent);
      const binCount = bins.length;
      this.calculatedBins = [...bins];
      return (item) => {
        const xValue = item.keys[0];
        for (let i = 0; i < binCount; i++) {
          const nextBin = bins[i];
          if (xValue >= nextBin[0] && xValue < nextBin[1]) {
            return nextBin;
          }
          if (i === binCount - 1 && xValue <= nextBin[1]) {
            return nextBin;
          }
        }
        return [];
      };
    };
    if (!this.ctx.animationManager.isSkipped() && this.processedData) {
      props.push(diff(this.id, this.processedData, false));
    }
    await this.requestDataModel(dataController, this.data, {
      props,
      groupByFn
    });
    this.animationState.transition("updateData");
  }
  getSeriesDomain(direction) {
    const { processedData, dataModel } = this;
    if (!processedData || !dataModel || !this.calculatedBins.length)
      return [];
    const yDomain = dataModel.getDomain(this, `groupAgg`, "aggregate", processedData);
    const xDomainMin = this.calculatedBins?.[0][0];
    const xDomainMax = this.calculatedBins?.[(this.calculatedBins?.length ?? 0) - 1][1];
    if (direction === "x") {
      return fixNumericExtent([xDomainMin, xDomainMax]);
    }
    return fixNumericExtent(yDomain);
  }
  getSeriesRange(_direction, _visibleRange) {
    return [NaN, NaN];
  }
  createNodeData() {
    const { id: seriesId, axes, processedData } = this;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!xAxis || !yAxis) {
      return;
    }
    const { scale: xScale } = xAxis;
    const { scale: yScale } = yAxis;
    const { xKey, yKey, xName, yName, fill, stroke, strokeWidth, cornerRadius } = this.properties;
    const labelFormatter = this.properties.label.formatter ?? ((params) => String(params.value));
    const nodeData = [];
    const context = {
      itemId: this.properties.yKey ?? this.id,
      nodeData,
      labelData: nodeData,
      scales: this.calculateScaling(),
      animationValid: true,
      visible: this.visible
    };
    if (!this.visible || processedData == null || processedData.rawData.length === 0 || processedData.type !== "grouped") {
      return context;
    }
    const { rawData } = processedData;
    processedData.groups.forEach(({ keys, datumIndices, aggregation }, groupIndex) => {
      const [[negativeAgg, positiveAgg] = [0, 0]] = aggregation;
      const frequency = datumIndices.length;
      const domain = keys;
      const [xDomainMin, xDomainMax] = domain;
      const datum = datumIndices.map((datumIndex) => rawData[datumIndex]);
      const xMinPx = xScale.convert(xDomainMin);
      const xMaxPx = xScale.convert(xDomainMax);
      const total = negativeAgg + positiveAgg;
      const yZeroPx = yScale.convert(0);
      const yMaxPx = yScale.convert(total);
      const w = Math.abs(xMaxPx - xMinPx);
      const h = Math.abs(yMaxPx - yZeroPx);
      const x = Math.min(xMinPx, xMaxPx);
      const y = Math.min(yZeroPx, yMaxPx);
      let selectionDatumLabel = void 0;
      if (total !== 0) {
        selectionDatumLabel = {
          x: x + w / 2,
          y: y + h / 2,
          text: this.cachedDatumCallback(
            createDatumId(groupIndex, "label"),
            () => labelFormatter({
              value: total,
              datum,
              seriesId,
              xKey,
              yKey,
              xName,
              yName
            })
          ) ?? String(total)
        };
      }
      const nodeMidPoint = {
        x: x + w / 2,
        y: y + h / 2
      };
      const yAxisReversed = yAxis.isReversed();
      nodeData.push({
        series: this,
        datumIndex: groupIndex,
        datum,
        // required by SeriesNodeDatum, but might not make sense here
        // since each selection is an aggregation of multiple data.
        aggregatedValue: total,
        frequency,
        domain,
        yKey,
        xKey,
        x,
        y,
        xValue: xMinPx,
        yValue: yMaxPx,
        width: w,
        height: h,
        midPoint: nodeMidPoint,
        fill,
        stroke,
        cornerRadius,
        topLeftCornerRadius: !yAxisReversed,
        topRightCornerRadius: !yAxisReversed,
        bottomRightCornerRadius: yAxisReversed,
        bottomLeftCornerRadius: yAxisReversed,
        opacity: 1,
        strokeWidth,
        label: selectionDatumLabel
      });
    });
    nodeData.sort((a, b) => a.x - b.x);
    return context;
  }
  nodeFactory() {
    return new Rect();
  }
  updateDatumSelection(opts) {
    const { nodeData, datumSelection } = opts;
    return datumSelection.update(
      nodeData,
      (rect) => {
        rect.crisp = true;
      },
      (datum) => datum.domain.join("_")
    );
  }
  getItemBaseStyle(highlighted) {
    const { properties } = this;
    const highlightStyle = highlighted ? properties.highlightStyle.item : void 0;
    return {
      fill: highlightStyle?.fill ?? properties.fill,
      fillOpacity: highlightStyle?.fillOpacity ?? properties.fillOpacity,
      stroke: highlightStyle?.stroke ?? properties.stroke,
      strokeWidth: highlightStyle?.strokeWidth ?? properties.strokeWidth,
      strokeOpacity: highlightStyle?.strokeOpacity ?? properties.strokeOpacity
    };
  }
  updateDatumNodes(opts) {
    const { isHighlight: isDatumHighlighted } = opts;
    const {
      fillOpacity: seriesFillOpacity,
      strokeOpacity,
      lineDash,
      lineDashOffset,
      shadow,
      highlightStyle: {
        item: {
          fill: highlightedFill,
          fillOpacity: highlightFillOpacity = seriesFillOpacity,
          stroke: highlightedStroke,
          strokeWidth: highlightedDatumStrokeWidth
        }
      }
    } = this.properties;
    opts.datumSelection.each((rect, datum, index) => {
      const {
        cornerRadius,
        topLeftCornerRadius,
        topRightCornerRadius,
        bottomRightCornerRadius,
        bottomLeftCornerRadius
      } = datum;
      const strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== void 0 ? highlightedDatumStrokeWidth : datum.strokeWidth;
      const fillOpacity = isDatumHighlighted ? highlightFillOpacity : seriesFillOpacity;
      rect.fill = (isDatumHighlighted ? highlightedFill : void 0) ?? datum.fill;
      rect.stroke = (isDatumHighlighted ? highlightedStroke : void 0) ?? datum.stroke;
      rect.fillOpacity = fillOpacity;
      rect.strokeOpacity = strokeOpacity;
      rect.strokeWidth = strokeWidth;
      rect.lineDash = lineDash;
      rect.lineDashOffset = lineDashOffset;
      rect.topLeftCornerRadius = topLeftCornerRadius ? cornerRadius : 0;
      rect.topRightCornerRadius = topRightCornerRadius ? cornerRadius : 0;
      rect.bottomRightCornerRadius = bottomRightCornerRadius ? cornerRadius : 0;
      rect.bottomLeftCornerRadius = bottomLeftCornerRadius ? cornerRadius : 0;
      rect.fillShadow = shadow;
      rect.zIndex = isDatumHighlighted ? Series.highlightedZIndex : index;
      rect.visible = datum.height > 0;
    });
  }
  updateLabelSelection(opts) {
    const { labelData, labelSelection } = opts;
    return labelSelection.update(labelData, (text) => {
      text.pointerEvents = 1;
      text.textAlign = "center";
      text.textBaseline = "middle";
    });
  }
  updateLabelNodes(opts) {
    const { fontStyle, fontWeight, fontFamily, fontSize, color } = this.properties.label;
    const labelEnabled = this.isLabelEnabled();
    opts.labelSelection.each((text, datum) => {
      if (labelEnabled && datum?.label) {
        text.text = datum.label.text;
        text.x = datum.label.x;
        text.y = datum.label.y;
        text.fontStyle = fontStyle;
        text.fontWeight = fontWeight;
        text.fontFamily = fontFamily;
        text.fontSize = fontSize;
        text.fill = color;
        text.visible = true;
      } else {
        text.visible = false;
      }
    });
  }
  initQuadTree(quadtree) {
    const { value: childNode } = this.contentGroup.children().next();
    if (childNode) {
      addHitTestersToQuadtree(quadtree, childNode.children());
    }
  }
  pickNodeClosestDatum(point) {
    return findQuadtreeMatch(this, point);
  }
  getTooltipContent(nodeDatum) {
    const {
      id: seriesId,
      dataModel,
      processedData,
      axes,
      properties,
      ctx: { localeManager }
    } = this;
    const { xKey, xName, yKey, yName, tooltip } = properties;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!dataModel || processedData?.type !== "grouped" || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const groupIndex = nodeDatum.datumIndex;
    const { aggregation, datumIndices, keys } = processedData.groups[groupIndex];
    const [[negativeAgg, positiveAgg] = [0, 0]] = aggregation;
    const frequency = datumIndices.length;
    const domain = keys;
    const [rangeMin, rangeMax] = domain;
    const aggregatedValue = negativeAgg + positiveAgg;
    const datum = {
      data: datumIndices.map((datumIndex) => processedData.rawData[datumIndex]),
      aggregatedValue,
      frequency,
      domain
    };
    const data = [
      {
        label: xName,
        fallbackLabel: xKey,
        value: `${xAxis.formatDatum(rangeMin)} - ${xAxis.formatDatum(rangeMax)}`
      },
      { label: localeManager.t("seriesHistogramTooltipFrequency"), value: yAxis.formatDatum(frequency) }
    ];
    if (yKey != null) {
      let label;
      switch (properties.aggregation) {
        case "sum":
          label = localeManager.t("seriesHistogramTooltipSum", { yName });
          break;
        case "mean":
          label = localeManager.t("seriesHistogramTooltipMean", { yName });
          break;
        case "count":
          label = localeManager.t("seriesHistogramTooltipCount", { yName });
          break;
      }
      data.push({ label, value: yAxis.formatDatum(aggregatedValue) });
    }
    return tooltip.formatTooltip(
      {
        symbol: this.legendItemSymbol(),
        data
      },
      {
        seriesId,
        datum,
        title: yName,
        xKey,
        xName,
        yKey,
        yName,
        xRange: [rangeMin, rangeMax],
        frequency,
        ...this.getItemBaseStyle(false)
      }
    );
  }
  legendItemSymbol() {
    const { fill, fillOpacity, stroke, strokeWidth, strokeOpacity } = this.properties;
    return {
      marker: {
        fill: fill ?? "rgba(0, 0, 0, 0)",
        stroke: stroke ?? "rgba(0, 0, 0, 0)",
        fillOpacity,
        strokeOpacity,
        strokeWidth
      }
    };
  }
  getLegendData(legendType) {
    if (legendType !== "category") {
      return [];
    }
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    const { xKey: itemId, yName, showInLegend } = this.properties;
    return [
      {
        legendType: "category",
        id: seriesId,
        itemId,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId }),
        label: {
          text: yName ?? itemId ?? "Frequency"
        },
        symbol: this.legendItemSymbol(),
        hideInLegend: !showInLegend
      }
    ];
  }
  animateEmptyUpdateReady({ datumSelection, labelSelection }) {
    const fns = prepareBarAnimationFunctions(collapsedStartingBarPosition(true, this.axes, "normal"));
    fromToMotion(this.id, "datums", this.ctx.animationManager, [datumSelection], fns);
    seriesLabelFadeInAnimation(this, "labels", this.ctx.animationManager, labelSelection);
  }
  animateWaitingUpdateReady(data) {
    const dataDiff = this.processedData?.reduced?.diff?.[this.id];
    const fns = prepareBarAnimationFunctions(collapsedStartingBarPosition(true, this.axes, "normal"));
    fromToMotion(
      this.id,
      "datums",
      this.ctx.animationManager,
      [data.datumSelection],
      fns,
      (_, datum) => createDatumId(datum.domain),
      dataDiff
    );
    seriesLabelFadeInAnimation(this, "labels", this.ctx.animationManager, data.labelSelection);
  }
  isLabelEnabled() {
    return this.properties.label.enabled;
  }
  computeFocusBounds({ datumIndex }) {
    return computeBarFocusBounds(this.contextNodeData?.nodeData[datumIndex]);
  }
};
HistogramSeries.className = "HistogramSeries";
HistogramSeries.type = "histogram";
var HistogramSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["cartesian"],
  identifier: "histogram",
  moduleFactory: (ctx) => new HistogramSeries(ctx),
  tooltipDefaults: { range: "exact" },
  defaultAxes: [
    {
      type: "number",
      position: "bottom"
      /* BOTTOM */
    },
    {
      type: "number",
      position: "left"
      /* LEFT */
    }
  ],
  themeTemplate: {
    series: {
      strokeWidth: 1,
      fillOpacity: 1,
      strokeOpacity: 1,
      lineDash: [0],
      lineDashOffset: 0,
      label: {
        enabled: false,
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_INSIDE_SERIES_LABEL_COLOUR
      },
      shadow: {
        enabled: false,
        color: DEFAULT_SHADOW_COLOUR,
        xOffset: 3,
        yOffset: 3,
        blur: 5
      }
    }
  },
  paletteFactory: ({ takeColors }) => {
    const {
      fills: [fill],
      strokes: [stroke]
    } = takeColors(1);
    return { fill, stroke };
  }
};
var LineSeriesProperties = class extends CartesianSeriesProperties {
  constructor() {
    super(...arguments);
    this.stroke = "#874349";
    this.strokeWidth = 2;
    this.strokeOpacity = 1;
    this.lineDash = [0];
    this.lineDashOffset = 0;
    this.interpolation = new InterpolationProperties();
    this.marker = new SeriesMarker();
    this.label = new Label();
    this.tooltip = new SeriesTooltip();
    this.connectMissingData = false;
    this.sparklineMode = false;
  }
};
__decorateClass([
  Validate(STRING)
], LineSeriesProperties.prototype, "xKey", 2);
__decorateClass([
  Validate(STRING)
], LineSeriesProperties.prototype, "yKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], LineSeriesProperties.prototype, "xName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], LineSeriesProperties.prototype, "yName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], LineSeriesProperties.prototype, "yFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], LineSeriesProperties.prototype, "stackGroup", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], LineSeriesProperties.prototype, "normalizedTo", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], LineSeriesProperties.prototype, "title", 2);
__decorateClass([
  Validate(COLOR_STRING)
], LineSeriesProperties.prototype, "stroke", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LineSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(RATIO)
], LineSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH)
], LineSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], LineSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
  Validate(OBJECT)
], LineSeriesProperties.prototype, "interpolation", 2);
__decorateClass([
  Validate(OBJECT)
], LineSeriesProperties.prototype, "marker", 2);
__decorateClass([
  Validate(OBJECT)
], LineSeriesProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], LineSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
  Validate(BOOLEAN)
], LineSeriesProperties.prototype, "connectMissingData", 2);
__decorateClass([
  Validate(BOOLEAN)
], LineSeriesProperties.prototype, "sparklineMode", 2);
var CROSS_FILTER_LINE_STROKE_OPACITY_FACTOR = 0.25;
var LineSeries = class extends CartesianSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      directionKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS,
      directionNames: DEFAULT_CARTESIAN_DIRECTION_NAMES,
      hasMarkers: true,
      pickModes: [
        2,
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      markerSelectionGarbageCollection: false,
      animationResetFns: {
        path: buildResetPathFn({ getVisible: () => this.visible, getOpacity: () => this.getOpacity() }),
        label: resetLabelFn,
        marker: (node, datum) => ({ ...resetMarkerFn(node), ...resetMarkerPositionFn(node, datum) })
      }
    });
    this.clipFocusBox = false;
    this.properties = new LineSeriesProperties();
    this.dataAggregationFilters = void 0;
  }
  get pickModeAxis() {
    return this.properties.sparklineMode ? "main" : "main-category";
  }
  async processData(dataController) {
    if (this.data == null || !this.properties.isValid()) {
      return;
    }
    const { data, visible, seriesGrouping: { groupIndex = this.id, stackCount = 1 } = {} } = this;
    const { xKey, yKey, yFilterKey, connectMissingData, normalizedTo } = this.properties;
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const xScale = this.axes[
      "x"
      /* X */
    ]?.scale;
    const yScale = this.axes[
      "y"
      /* Y */
    ]?.scale;
    const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
    const common = { invalidValue: null };
    if (connectMissingData && stackCount > 1) {
      common.invalidValue = 0;
      if (!visible) {
        common.forceValue = 0;
      }
    }
    const props = [];
    if (!isContinuousX) {
      props.push(keyProperty(xKey, xScaleType, { id: "xKey" }));
    }
    props.push(
      valueProperty(xKey, xScaleType, { id: "xValue" }),
      valueProperty(yKey, yScaleType, {
        id: `yValueRaw`,
        ...common,
        invalidValue: void 0
      })
    );
    if (yFilterKey != null) {
      props.push(valueProperty(yFilterKey, yScaleType, { id: "yFilterRaw" }));
    }
    if (stackCount > 1) {
      const ids = [
        `line-stack-${groupIndex}-yValues`,
        `line-stack-${groupIndex}-yValues-trailing`,
        `line-stack-${groupIndex}-yValues-marker`
      ];
      props.push(
        ...groupAccumulativeValueProperty(
          yKey,
          "window",
          "current",
          { id: `yValueEnd`, ...common, groupId: ids[0] },
          yScaleType
        ),
        ...groupAccumulativeValueProperty(
          yKey,
          "window-trailing",
          "current",
          { id: `yValueStart`, ...common, groupId: ids[1] },
          yScaleType
        ),
        ...groupAccumulativeValueProperty(
          yKey,
          "normal",
          "current",
          { id: `yValueCumulative`, ...common, groupId: ids[2] },
          yScaleType
        )
      );
      if (isDefined(normalizedTo)) {
        props.push(normaliseGroupTo([ids[0], ids[1], ids[2]], normalizedTo, "range"));
      }
    }
    if (animationEnabled) {
      props.push(animationValidation(isContinuousX ? ["xValue"] : void 0));
      if (this.processedData) {
        props.push(diff(this.id, this.processedData));
      }
    }
    const { dataModel, processedData } = await this.requestDataModel(dataController, data, {
      props
    });
    this.dataAggregationFilters = this.aggregateData(dataModel, processedData);
    this.animationState.transition("updateData");
  }
  getSeriesDomain(direction) {
    const { dataModel, processedData } = this;
    if (!dataModel || !processedData?.rawData.length)
      return [];
    const xDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
    if (direction === "x") {
      const domain = dataModel.getDomain(this, `xValue`, "value", processedData);
      if (xDef?.def.type === "value" && xDef.def.valueType === "category") {
        return domain;
      }
      return fixNumericExtent(extent(domain));
    } else {
      const stackCount = this.seriesGrouping?.stackCount ?? 1;
      const domain = stackCount > 1 ? dataModel.getDomain(this, `yValueEnd`, "value", processedData) : dataModel.getDomain(this, `yValueRaw`, "value", processedData);
      return fixNumericExtent(domain);
    }
  }
  visibleRangeIndices(visibleRange, indices) {
    const { dataModel, processedData } = this;
    if (!dataModel || !processedData)
      return [0, 0];
    const xScale = this.axes[
      "x"
      /* X */
    ].scale;
    const xValues = dataModel.resolveColumnById(this, `xValue`, processedData);
    return visibleRangeIndices(indices?.length ?? xValues.length, visibleRange, (index) => {
      const x = xScale.convert(xValues[indices?.[index] ?? index]);
      return [x, x];
    });
  }
  getSeriesRange(_direction, visibleRange) {
    const { dataModel, processedData } = this;
    if (!dataModel || !processedData)
      return [NaN, NaN];
    const [x0, x1] = this.visibleRangeIndices(visibleRange);
    return dataModel.getDomainBetweenRange(this, ["yValueRaw"], [x0, x1], processedData);
  }
  aggregateData(_dataModel, _processedData) {
    return;
  }
  createNodeData() {
    const { dataModel, processedData, axes, dataAggregationFilters } = this;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!dataModel || !processedData || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const {
      xKey,
      yKey,
      yFilterKey,
      xName,
      yName,
      marker,
      label,
      connectMissingData,
      interpolation,
      legendItemName
    } = this.properties;
    const stacked = (this.seriesGrouping?.stackCount ?? 1) > 1;
    const xScale = xAxis.scale;
    const yScale = yAxis.scale;
    const xOffset = (xScale.bandwidth ?? 0) / 2;
    const yOffset = (yScale.bandwidth ?? 0) / 2;
    const size = marker.enabled ? marker.size : 0;
    const { rawData } = processedData;
    const xValues = dataModel.resolveColumnById(this, `xValue`, processedData);
    const yValues = dataModel.resolveColumnById(this, `yValueRaw`, processedData);
    const yEndValues = stacked ? dataModel.resolveColumnById(this, `yValueEnd`, processedData) : void 0;
    const yCumulativeValues = stacked ? dataModel.resolveColumnById(this, `yValueCumulative`, processedData) : yValues;
    const selectionValues = yFilterKey != null ? dataModel.resolveColumnById(this, `yFilterRaw`, processedData) : void 0;
    const xPosition = (index) => xScale.convert(xValues[index]) + xOffset;
    const yPosition = (index) => yScale.convert(yCumulativeValues[index]) + yOffset;
    const capDefaults = {
      lengthRatioMultiplier: this.properties.marker.getDiameter(),
      lengthMax: Infinity
    };
    const nodeData = [];
    let spanPoints;
    const handleDatum = (datumIndex) => {
      const datum = rawData[datumIndex];
      const xDatum = xValues[datumIndex];
      const yDatum = yValues[datumIndex];
      const yEndDatum = yEndValues?.[datumIndex];
      const selected = selectionValues?.[datumIndex];
      const x = xPosition(datumIndex);
      const y = yPosition(datumIndex);
      if (!Number.isFinite(x))
        return;
      if (yDatum != null) {
        const labelText = label.enabled ? this.getLabelText(label, {
          value: yDatum,
          datum,
          xKey,
          yKey,
          xName,
          yName,
          legendItemName
        }) : void 0;
        nodeData.push({
          series: this,
          datum,
          datumIndex,
          yKey,
          xKey,
          point: { x, y, size },
          midPoint: { x, y },
          cumulativeValue: yEndDatum,
          yValue: yDatum,
          xValue: xDatum,
          capDefaults,
          labelText,
          selected
        });
      }
      if (spanPoints == null)
        return;
      const currentSpanPoints = spanPoints[spanPoints.length - 1];
      if (yDatum != null) {
        const spanPoint = {
          point: { x, y },
          xDatum,
          yDatum
        };
        if (Array.isArray(currentSpanPoints)) {
          currentSpanPoints.push(spanPoint);
        } else if (currentSpanPoints != null) {
          currentSpanPoints.skip += 1;
          spanPoints.push([spanPoint]);
        } else {
          spanPoints.push([spanPoint]);
        }
      } else if (!connectMissingData) {
        if (Array.isArray(currentSpanPoints) || currentSpanPoints == null) {
          spanPoints.push({ skip: 0 });
        } else {
          currentSpanPoints.skip += 1;
        }
      }
    };
    const [r0, r1] = xScale.range;
    const range3 = r1 - r0;
    const dataAggregationFilter = dataAggregationFilters?.find((f) => f.maxRange > range3);
    const indices = dataAggregationFilter?.indices;
    let [start2, end2] = this.visibleRangeIndices(xAxis.range, indices);
    start2 = Math.max(start2 - 1, 0);
    end2 = Math.min(end2 + 1, indices?.length ?? xValues.length);
    if (processedData.rawData.length < 1e3) {
      start2 = 0;
      end2 = processedData.rawData.length;
    }
    if (indices == null) {
      spanPoints = [];
    }
    for (let i = start2; i < end2; i += 1) {
      handleDatum(indices?.[i] ?? i);
    }
    const strokeSpans = spanPoints?.flatMap((p) => {
      return Array.isArray(p) ? interpolatePoints(p, interpolation) : [];
    });
    const strokeData = strokeSpans != null ? { itemId: yKey, spans: strokeSpans } : void 0;
    const crossFiltering = selectionValues?.some((selectionValue, index) => selectionValue === yValues[index]) ?? false;
    return {
      itemId: yKey,
      nodeData,
      labelData: nodeData,
      strokeData,
      scales: this.calculateScaling(),
      visible: this.visible,
      crossFiltering
    };
  }
  isPathOrSelectionDirty() {
    return this.properties.marker.isDirty();
  }
  markerFactory() {
    const { shape } = this.properties.marker;
    const MarkerShape = getMarker(shape);
    return new MarkerShape();
  }
  updatePathNodes(opts) {
    const {
      paths: [lineNode],
      opacity,
      visible,
      animationEnabled
    } = opts;
    const crossFiltering = this.contextNodeData?.crossFiltering === true;
    lineNode.setProperties({
      fill: void 0,
      lineJoin: "round",
      pointerEvents: 1,
      opacity,
      stroke: this.properties.stroke,
      strokeWidth: this.getStrokeWidth(this.properties.strokeWidth),
      strokeOpacity: this.properties.strokeOpacity * (crossFiltering ? CROSS_FILTER_LINE_STROKE_OPACITY_FACTOR : 1),
      lineDash: this.properties.lineDash,
      lineDashOffset: this.properties.lineDashOffset
    });
    if (!animationEnabled) {
      lineNode.visible = visible;
    }
    updateClipPath(this, lineNode);
  }
  updateMarkerSelection(opts) {
    let { nodeData } = opts;
    const { markerSelection } = opts;
    const markersEnabled = this.properties.marker.enabled || this.contextNodeData?.crossFiltering === true;
    nodeData = markersEnabled ? nodeData : [];
    if (this.properties.marker.isDirty()) {
      markerSelection.clear();
      markerSelection.cleanup();
    }
    return markerSelection.update(nodeData, void 0, (datum) => createDatumId(datum.xValue));
  }
  updateMarkerNodes(opts) {
    const { markerSelection, isHighlight: highlighted } = opts;
    const { xKey, yKey, stroke, strokeWidth, strokeOpacity, marker, highlightStyle } = this.properties;
    const xDomain = this.getSeriesDomain(
      "x"
      /* X */
    );
    const yDomain = this.getSeriesDomain(
      "y"
      /* Y */
    );
    const baseStyle = mergeDefaults(highlighted && highlightStyle.item, marker.getStyle(), {
      stroke,
      strokeWidth,
      strokeOpacity
    });
    const applyTranslation = this.ctx.animationManager.isSkipped();
    markerSelection.each((node, datum) => {
      this.updateMarkerStyle(
        node,
        marker,
        { ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain), highlighted },
        baseStyle,
        { applyTranslation, selected: datum.selected }
      );
    });
    if (!highlighted) {
      marker.markClean();
    }
  }
  updateLabelSelection(opts) {
    return opts.labelSelection.update(this.isLabelEnabled() ? opts.labelData : []);
  }
  updateLabelNodes(opts) {
    const { enabled, fontStyle, fontWeight, fontSize, fontFamily, color } = this.properties.label;
    opts.labelSelection.each((text, datum) => {
      if (enabled && datum?.labelText) {
        text.fontStyle = fontStyle;
        text.fontWeight = fontWeight;
        text.fontSize = fontSize;
        text.fontFamily = fontFamily;
        text.textAlign = "center";
        text.textBaseline = "bottom";
        text.text = datum.labelText;
        text.x = datum.point.x;
        text.y = datum.point.y - 10;
        text.fill = color;
        text.visible = true;
      } else {
        text.visible = false;
      }
    });
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, axes, properties } = this;
    const { xKey, xName, yKey, yName, tooltip } = properties;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!dataModel || !processedData || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const xValue = dataModel.resolveColumnById(this, `xValue`, processedData)[datumIndex];
    const yValue = dataModel.resolveColumnById(this, `yValueRaw`, processedData)[datumIndex];
    if (xValue == null)
      return;
    return tooltip.formatTooltip(
      {
        heading: xAxis.formatDatum(xValue),
        symbol: this.legendItemSymbol(),
        data: [{ label: yName, fallbackLabel: yKey, value: yAxis.formatDatum(yValue) }]
      },
      {
        seriesId,
        datum,
        title: yName,
        xKey,
        xName,
        yKey,
        yName,
        ...this.getModuleTooltipParams()
      }
    );
  }
  legendItemSymbol() {
    const color0 = "rgba(0, 0, 0, 0)";
    const { stroke, strokeOpacity, strokeWidth, lineDash, marker } = this.properties;
    return {
      marker: {
        shape: marker.shape,
        fill: marker.fill ?? color0,
        stroke: marker.stroke ?? stroke ?? color0,
        fillOpacity: marker.fillOpacity ?? 1,
        strokeOpacity: marker.strokeOpacity ?? strokeOpacity ?? 1,
        strokeWidth: marker.strokeWidth ?? 0,
        enabled: marker.enabled
      },
      line: {
        stroke: stroke ?? color0,
        strokeOpacity,
        strokeWidth,
        lineDash
      }
    };
  }
  getLegendData(legendType) {
    if (!(this.properties.isValid() && legendType === "category")) {
      return [];
    }
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    const { yKey: itemId, yName, title, legendItemName, showInLegend } = this.properties;
    return [
      {
        legendType: "category",
        id: seriesId,
        itemId,
        legendItemName,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId }),
        label: {
          text: legendItemName ?? title ?? yName ?? itemId
        },
        symbol: this.legendItemSymbol(),
        hideInLegend: !showInLegend
      }
    ];
  }
  updatePaths(opts) {
    this.updateLinePaths(opts.paths, opts.contextData);
  }
  plotNodeDataPoints(path, nodeData) {
    if (nodeData.length === 0)
      return;
    const initialPoint = nodeData[0].point;
    path.moveTo(initialPoint.x, initialPoint.y);
    for (let i = 1; i < nodeData.length; i += 1) {
      const { x, y } = nodeData[i].point;
      path.lineTo(x, y);
    }
  }
  updateLinePaths(paths, contextData) {
    const spans = contextData.strokeData?.spans;
    const [lineNode] = paths;
    lineNode.path.clear();
    if (spans != null) {
      plotLinePathStroke(lineNode, spans);
    } else {
      this.plotNodeDataPoints(lineNode.path, contextData.nodeData);
    }
    lineNode.markDirty();
  }
  animateEmptyUpdateReady(animationData) {
    const { markerSelection, labelSelection, annotationSelections, contextData, paths } = animationData;
    const { animationManager } = this.ctx;
    this.updateLinePaths(paths, contextData);
    pathSwipeInAnimation(this, animationManager, ...paths);
    resetMotion([markerSelection], resetMarkerPositionFn);
    markerSwipeScaleInAnimation(this, animationManager, markerSelection);
    seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection);
    seriesLabelFadeInAnimation(this, "annotations", animationManager, ...annotationSelections);
  }
  animateReadyResize(animationData) {
    const { contextData, paths } = animationData;
    this.updateLinePaths(paths, contextData);
    super.animateReadyResize(animationData);
  }
  animateWaitingUpdateReady(animationData) {
    const { animationManager } = this.ctx;
    const {
      markerSelection: markerSelections,
      labelSelection: labelSelections,
      annotationSelections,
      contextData,
      paths,
      previousContextData
    } = animationData;
    const [path] = paths;
    this.resetMarkerAnimation(animationData);
    this.resetLabelAnimation(animationData);
    const update = () => {
      this.resetPathAnimation(animationData);
      this.updateLinePaths(paths, contextData);
    };
    const skip = () => {
      animationManager.skipCurrentBatch();
      update();
    };
    if (contextData == null || previousContextData == null) {
      update();
      markerFadeInAnimation(this, animationManager, "added", markerSelections);
      pathFadeInAnimation(this, "path_properties", animationManager, "add", path);
      seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelections);
      seriesLabelFadeInAnimation(this, "annotations", animationManager, ...annotationSelections);
      return;
    }
    if (contextData.crossFiltering !== previousContextData.crossFiltering) {
      skip();
      return;
    }
    const fns = prepareLinePathAnimation(
      contextData,
      previousContextData,
      this.processedData?.reduced?.diff?.[this.id]
    );
    if (fns === void 0) {
      skip();
      return;
    } else if (fns.status === "no-op") {
      return;
    }
    fromToMotion(this.id, "path_properties", animationManager, [path], fns.stroke.pathProperties);
    if (fns.status === "added") {
      this.updateLinePaths(paths, contextData);
    } else if (fns.status === "removed") {
      this.updateLinePaths(paths, previousContextData);
    } else {
      pathMotion(this.id, "path_update", animationManager, [path], fns.stroke.path);
    }
    if (fns.hasMotion) {
      markerFadeInAnimation(this, animationManager, void 0, markerSelections);
      seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelections);
      seriesLabelFadeInAnimation(this, "annotations", animationManager, ...annotationSelections);
    }
  }
  isLabelEnabled() {
    return this.properties.label.enabled;
  }
  getBandScalePadding() {
    return { inner: 1, outer: 0.1 };
  }
  nodeFactory() {
    return new Group();
  }
  getFormattedMarkerStyle(datum) {
    const { xKey, yKey } = this.properties;
    const xDomain = this.getSeriesDomain(
      "x"
      /* X */
    );
    const yDomain = this.getSeriesDomain(
      "y"
      /* Y */
    );
    return this.getMarkerStyle(this.properties.marker, {
      ...datumStylerProperties(datum, xKey, yKey, xDomain, yDomain),
      highlighted: true
    });
  }
  computeFocusBounds(opts) {
    return computeMarkerFocusBounds(this, opts);
  }
};
LineSeries.className = "LineSeries";
LineSeries.type = "line";
var LineSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["cartesian"],
  identifier: "line",
  moduleFactory: (ctx) => new LineSeries(ctx),
  stackable: true,
  tooltipDefaults: { range: "nearest" },
  defaultAxes: [
    {
      type: "number",
      position: "left"
      /* LEFT */
    },
    {
      type: "category",
      position: "bottom"
      /* BOTTOM */
    }
  ],
  themeTemplate: {
    series: {
      tooltip: { position: { type: "node" } },
      strokeWidth: 2,
      strokeOpacity: 1,
      lineDash: [0],
      lineDashOffset: 0,
      interpolation: {
        type: "linear",
        // @ts-expect-error - users shouldn't specify all options, but we have to for theming to work
        tension: 1,
        position: "end"
      },
      marker: {
        shape: "circle",
        size: 7,
        strokeWidth: 0
      },
      label: {
        enabled: false,
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_LABEL_COLOUR
      },
      errorBar: {
        cap: {
          lengthRatio: 1
        }
      }
    }
  },
  paletteFactory: (params) => {
    const { marker } = markerPaletteFactory(params);
    return { stroke: marker.fill, marker };
  }
};
var ScatterSeriesLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.placement = "top";
  }
};
__decorateClass([
  Validate(LABEL_PLACEMENT)
], ScatterSeriesLabel.prototype, "placement", 2);
var ScatterSeriesProperties = class extends CartesianSeriesProperties {
  constructor() {
    super(...arguments);
    this.colorRange = ["#ffff00", "#00ff00", "#0000ff"];
    this.label = new ScatterSeriesLabel();
    this.tooltip = new SeriesTooltip();
    this.marker = new SeriesMarker();
  }
};
__decorateClass([
  Validate(STRING)
], ScatterSeriesProperties.prototype, "xKey", 2);
__decorateClass([
  Validate(STRING)
], ScatterSeriesProperties.prototype, "yKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "colorKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "xFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "yFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "xName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "yName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "labelName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "colorName", 2);
__decorateClass([
  Validate(NUMBER_ARRAY, { optional: true })
], ScatterSeriesProperties.prototype, "colorDomain", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], ScatterSeriesProperties.prototype, "colorRange", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ScatterSeriesProperties.prototype, "title", 2);
__decorateClass([
  ProxyProperty("marker.shape")
], ScatterSeriesProperties.prototype, "shape", 2);
__decorateClass([
  ProxyProperty("marker.size")
], ScatterSeriesProperties.prototype, "size", 2);
__decorateClass([
  ProxyProperty("marker.fill")
], ScatterSeriesProperties.prototype, "fill", 2);
__decorateClass([
  ProxyProperty("marker.fillOpacity")
], ScatterSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  ProxyProperty("marker.stroke")
], ScatterSeriesProperties.prototype, "stroke", 2);
__decorateClass([
  ProxyProperty("marker.strokeWidth")
], ScatterSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  ProxyProperty("marker.strokeOpacity")
], ScatterSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  ProxyProperty("marker.itemStyler", { optional: true })
], ScatterSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
  Validate(OBJECT)
], ScatterSeriesProperties.prototype, "label", 2);
__decorateClass([
  Validate(OBJECT)
], ScatterSeriesProperties.prototype, "tooltip", 2);
var ScatterSeries = class extends CartesianSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      directionKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS,
      directionNames: DEFAULT_CARTESIAN_DIRECTION_NAMES,
      pickModes: [
        2,
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      pathsPerSeries: [],
      hasMarkers: true,
      markerSelectionGarbageCollection: false,
      animationResetFns: {
        marker: resetMarkerFn,
        label: resetLabelFn
      },
      usesPlacedLabels: true
    });
    this.clipFocusBox = false;
    this.properties = new ScatterSeriesProperties();
    this.colorScale = new ColorScale();
  }
  get pickModeAxis() {
    return "main-category";
  }
  async processData(dataController) {
    if (!this.properties.isValid() || this.data == null || !this.visible)
      return;
    const xScale = this.axes[
      "x"
      /* X */
    ]?.scale;
    const yScale = this.axes[
      "y"
      /* Y */
    ]?.scale;
    const { xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
    const colorScaleType = this.colorScale.type;
    const { xKey, yKey, xFilterKey, yFilterKey, labelKey, colorKey, colorDomain, colorRange } = this.properties;
    const { dataModel, processedData } = await this.requestDataModel(dataController, this.data, {
      props: [
        valueProperty(xKey, xScaleType, { id: `xValue` }),
        valueProperty(yKey, yScaleType, { id: `yValue` }),
        ...xFilterKey != null ? [valueProperty(xFilterKey, xScaleType, { id: "xFilterValue" })] : [],
        ...yFilterKey != null ? [valueProperty(yFilterKey, yScaleType, { id: "yFilterValue" })] : [],
        ...colorKey ? [valueProperty(colorKey, colorScaleType, { id: `colorValue` })] : [],
        ...labelKey ? [valueProperty(labelKey, "band", { id: `labelValue` })] : []
      ]
    });
    if (colorKey) {
      const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, `colorValue`);
      this.colorScale.domain = colorDomain ?? processedData.domain.values[colorKeyIdx] ?? [];
      this.colorScale.range = colorRange;
      this.colorScale.update();
    }
    this.animationState.transition("updateData");
  }
  getSeriesDomain(direction) {
    const { dataModel, processedData } = this;
    if (!processedData || !dataModel)
      return [];
    const id = direction === "x" ? `xValue` : `yValue`;
    const dataDef = dataModel.resolveProcessedDataDefById(this, id);
    const domain = dataModel.getDomain(this, id, "value", processedData);
    if (dataDef?.def.type === "value" && dataDef?.def.valueType === "category") {
      return domain;
    }
    return fixNumericExtent(extent(domain));
  }
  getSeriesRange(_direction, _visibleRange) {
    return [NaN, NaN];
  }
  createNodeData() {
    const { axes, dataModel, processedData, colorScale, visible } = this;
    const { xKey, yKey, xFilterKey, yFilterKey, labelKey, colorKey, xName, yName, labelName, marker, label } = this.properties;
    const { placement } = label;
    const markerShape = getMarker(marker.shape);
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!(dataModel && processedData?.rawData.length && visible && xAxis && yAxis)) {
      return;
    }
    const xDataValues = dataModel.resolveColumnById(this, `xValue`, processedData);
    const yDataValues = dataModel.resolveColumnById(this, `yValue`, processedData);
    const colorDataValues = colorKey != null ? dataModel.resolveColumnById(this, `colorValue`, processedData) : void 0;
    const labelDataValues = labelKey != null ? dataModel.resolveColumnById(this, `labelValue`, processedData) : void 0;
    const xFilterDataValues = xFilterKey != null ? dataModel.resolveColumnById(this, `xFilterValue`, processedData) : void 0;
    const yFilterDataValues = yFilterKey != null ? dataModel.resolveColumnById(this, `yFilterValue`, processedData) : void 0;
    const xScale = xAxis.scale;
    const yScale = yAxis.scale;
    const xOffset = (xScale.bandwidth ?? 0) / 2;
    const yOffset = (yScale.bandwidth ?? 0) / 2;
    const nodeData = [];
    const font = label.getFont();
    const textMeasurer = CachedTextMeasurerPool.getMeasurer({ font });
    processedData.rawData.forEach((datum, datumIndex) => {
      const xDatum = xDataValues[datumIndex];
      const yDatum = yDataValues[datumIndex];
      const x = xScale.convert(xDatum) + xOffset;
      const y = yScale.convert(yDatum) + yOffset;
      const selected = xFilterDataValues != null && yFilterDataValues != null ? xFilterDataValues[datumIndex] === xDatum && yFilterDataValues[datumIndex] === yDatum : void 0;
      const labelText = this.getLabelText(label, {
        value: labelDataValues != null ? labelDataValues?.[datumIndex] : yDatum,
        datum,
        xKey,
        yKey,
        labelKey,
        xName,
        yName,
        labelName
      });
      const size = textMeasurer.measureText(labelText);
      const fill = colorDataValues != null ? colorScale.convert(colorDataValues[datumIndex]) : void 0;
      nodeData.push({
        series: this,
        itemId: yKey,
        yKey,
        xKey,
        datum,
        datumIndex,
        xValue: xDatum,
        yValue: yDatum,
        capDefaults: { lengthRatioMultiplier: marker.getDiameter(), lengthMax: Infinity },
        point: { x, y, size: marker.size },
        midPoint: { x, y },
        fill,
        label: { text: labelText, ...size },
        marker: markerShape,
        placement,
        selected
      });
    });
    return {
      itemId: yKey,
      nodeData,
      labelData: nodeData,
      scales: this.calculateScaling(),
      visible: this.visible
    };
  }
  isPathOrSelectionDirty() {
    return this.properties.marker.isDirty();
  }
  getLabelData() {
    if (!this.isLabelEnabled())
      return [];
    return this.contextNodeData?.labelData ?? [];
  }
  markerFactory() {
    const { shape } = this.properties.marker;
    const MarkerShape = getMarker(shape);
    return new MarkerShape();
  }
  updateMarkerSelection(opts) {
    const { nodeData, markerSelection } = opts;
    if (this.properties.marker.isDirty()) {
      markerSelection.clear();
      markerSelection.cleanup();
    }
    return markerSelection.update(this.properties.marker.enabled ? nodeData : []);
  }
  getMarkerItemBaseStyle(highlighted) {
    const { properties } = this;
    const { marker } = properties;
    const highlightStyle = highlighted ? properties.highlightStyle.item : void 0;
    return {
      fill: highlightStyle?.fill ?? marker.fill,
      fillOpacity: highlightStyle?.fillOpacity ?? marker.fillOpacity,
      stroke: highlightStyle?.stroke ?? marker.stroke,
      strokeWidth: highlightStyle?.strokeWidth ?? marker.strokeWidth,
      strokeOpacity: highlightStyle?.strokeOpacity ?? marker.strokeOpacity
    };
  }
  getMarkerItemStyleOverrides(datumId, datum, format, highlighted) {
    const { id: seriesId, properties } = this;
    const { xKey, yKey, labelKey, marker } = properties;
    const { itemStyler } = marker;
    if (itemStyler == null)
      return;
    return this.cachedDatumCallback(createDatumId(datumId, highlighted ? "highlight" : "node"), () => {
      return itemStyler({
        seriesId,
        datum,
        xKey,
        yKey,
        labelKey,
        highlighted,
        ...format
      });
    });
  }
  updateMarkerNodes(opts) {
    const { markerSelection, isHighlight: highlighted } = opts;
    const { xKey, yKey, labelKey, marker, highlightStyle } = this.properties;
    const baseStyle = mergeDefaults(highlighted && highlightStyle.item, marker.getStyle());
    markerSelection.each((node, datum) => {
      this.updateMarkerStyle(node, marker, { datum, highlighted, xKey, yKey, labelKey }, baseStyle, {
        selected: datum.selected
      });
    });
    if (!highlighted) {
      marker.markClean();
    }
  }
  updatePlacedLabelData(labelData) {
    this.labelSelection.update(
      labelData.map((v) => ({
        ...v.datum,
        point: {
          x: v.x,
          y: v.y,
          size: v.datum.point.size
        }
      })),
      (text) => {
        text.pointerEvents = 1;
      }
    );
    this.updateLabelNodes({ labelSelection: this.labelSelection });
  }
  updateLabelNodes(opts) {
    const { label } = this.properties;
    opts.labelSelection.each((text, datum) => {
      text.text = datum.label.text;
      text.fill = label.color;
      text.x = datum.point?.x ?? 0;
      text.y = datum.point?.y ?? 0;
      text.fontStyle = label.fontStyle;
      text.fontWeight = label.fontWeight;
      text.fontSize = label.fontSize;
      text.fontFamily = label.fontFamily;
      text.textAlign = "left";
      text.textBaseline = "top";
    });
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, axes, properties } = this;
    const { xKey, xName, yKey, yName, labelKey, labelName, title, tooltip } = properties;
    const xAxis = axes[
      "x"
      /* X */
    ];
    const yAxis = axes[
      "y"
      /* Y */
    ];
    if (!dataModel || !processedData || processedData.rawData.length === 0 || !xAxis || !yAxis) {
      return;
    }
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const xValue = dataModel.resolveColumnById(this, `xValue`, processedData)[datumIndex];
    const yValue = dataModel.resolveColumnById(this, `yValue`, processedData)[datumIndex];
    if (xValue == null)
      return;
    const format = this.getMarkerItemBaseStyle(false);
    Object.assign(format, this.getMarkerItemStyleOverrides(String(datumIndex), datum, format, false));
    return tooltip.formatTooltip(
      {
        symbol: this.legendItemSymbol(),
        title,
        data: [
          { label: xName, fallbackLabel: xKey, value: xAxis.formatDatum(xValue) },
          { label: yName, fallbackLabel: yKey, value: yAxis.formatDatum(yValue) }
        ]
      },
      {
        seriesId,
        datum,
        title: yName,
        xKey,
        xName,
        yKey,
        yName,
        labelKey,
        labelName,
        ...format,
        ...this.getModuleTooltipParams()
      }
    );
  }
  legendItemSymbol() {
    const { shape, fill, stroke, fillOpacity, strokeOpacity, strokeWidth } = this.properties.marker;
    return {
      marker: {
        shape,
        fill: fill ?? "rgba(0, 0, 0, 0)",
        stroke: stroke ?? "rgba(0, 0, 0, 0)",
        fillOpacity: fillOpacity ?? 1,
        strokeOpacity: strokeOpacity ?? 1,
        strokeWidth: strokeWidth ?? 0
      }
    };
  }
  getLegendData(legendType) {
    if (!this.properties.isValid() || legendType !== "category") {
      return [];
    }
    const { yKey: itemId, yName, title, showInLegend } = this.properties;
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    return [
      {
        legendType: "category",
        id: seriesId,
        itemId,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId }),
        label: {
          text: title ?? yName ?? itemId
        },
        symbol: this.legendItemSymbol(),
        hideInLegend: !showInLegend
      }
    ];
  }
  animateEmptyUpdateReady(data) {
    const { markerSelection, labelSelection, annotationSelections } = data;
    markerScaleInAnimation(this, this.ctx.animationManager, markerSelection);
    seriesLabelFadeInAnimation(this, "labels", this.ctx.animationManager, labelSelection);
    seriesLabelFadeInAnimation(this, "annotations", this.ctx.animationManager, ...annotationSelections);
  }
  isLabelEnabled() {
    return this.properties.label.enabled;
  }
  nodeFactory() {
    return new Group();
  }
  getFormattedMarkerStyle(datum) {
    const { xKey, yKey, labelKey } = this.properties;
    return this.getMarkerStyle(this.properties.marker, { datum, xKey, yKey, labelKey, highlighted: true });
  }
  computeFocusBounds(opts) {
    return computeMarkerFocusBounds(this, opts);
  }
};
ScatterSeries.className = "ScatterSeries";
ScatterSeries.type = "scatter";
var ScatterSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["cartesian"],
  identifier: "scatter",
  moduleFactory: (ctx) => new ScatterSeries(ctx),
  tooltipDefaults: { range: "nearest" },
  defaultAxes: [
    {
      type: "number",
      position: "bottom"
      /* BOTTOM */
    },
    {
      type: "number",
      position: "left"
      /* LEFT */
    }
  ],
  themeTemplate: {
    series: {
      shape: "circle",
      size: 7,
      fillOpacity: 0.8,
      tooltip: { position: { type: "node" } },
      label: {
        enabled: false,
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_LABEL_COLOUR
      },
      errorBar: {
        cap: {
          lengthRatio: 1
        }
      }
    }
  },
  paletteFactory: singleSeriesPaletteFactory
};
var SectorBox = class _SectorBox {
  constructor(startAngle, endAngle, innerRadius, outerRadius) {
    this.startAngle = startAngle;
    this.endAngle = endAngle;
    this.innerRadius = innerRadius;
    this.outerRadius = outerRadius;
  }
  clone() {
    const { startAngle, endAngle, innerRadius, outerRadius } = this;
    return new _SectorBox(startAngle, endAngle, innerRadius, outerRadius);
  }
  equals(other) {
    return this.startAngle === other.startAngle && this.endAngle === other.endAngle && this.innerRadius === other.innerRadius && this.outerRadius === other.outerRadius;
  }
  [interpolate](other, d) {
    return new _SectorBox(
      this.startAngle * (1 - d) + other.startAngle * d,
      this.endAngle * (1 - d) + other.endAngle * d,
      this.innerRadius * (1 - d) + other.innerRadius * d,
      this.outerRadius * (1 - d) + other.outerRadius * d
    );
  }
};
function sectorBox({ startAngle, endAngle, innerRadius, outerRadius }) {
  let x0 = Infinity;
  let y0 = Infinity;
  let x1 = -Infinity;
  let y1 = -Infinity;
  const addPoint = (x, y) => {
    x0 = Math.min(x, x0);
    y0 = Math.min(y, y0);
    x1 = Math.max(x, x1);
    y1 = Math.max(y, y1);
  };
  addPoint(innerRadius * Math.cos(startAngle), innerRadius * Math.sin(startAngle));
  addPoint(innerRadius * Math.cos(endAngle), innerRadius * Math.sin(endAngle));
  addPoint(outerRadius * Math.cos(startAngle), outerRadius * Math.sin(startAngle));
  addPoint(outerRadius * Math.cos(endAngle), outerRadius * Math.sin(endAngle));
  if (isBetweenAngles(0, startAngle, endAngle)) {
    addPoint(outerRadius, 0);
  }
  if (isBetweenAngles(Math.PI * 0.5, startAngle, endAngle)) {
    addPoint(0, outerRadius);
  }
  if (isBetweenAngles(Math.PI, startAngle, endAngle)) {
    addPoint(-outerRadius, 0);
  }
  if (isBetweenAngles(Math.PI * 1.5, startAngle, endAngle)) {
    addPoint(0, -outerRadius);
  }
  return new BBox(x0, y0, x1 - x0, y1 - y0);
}
function isPointInSector(x, y, sector) {
  const radius = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
  const { innerRadius, outerRadius } = sector;
  if (sector.startAngle === sector.endAngle || radius < Math.min(innerRadius, outerRadius) || radius > Math.max(innerRadius, outerRadius)) {
    return false;
  }
  const startAngle = normalizeAngle180(sector.startAngle);
  const endAngle = normalizeAngle180(sector.endAngle);
  const angle2 = Math.atan2(y, x);
  return startAngle < endAngle ? angle2 <= endAngle && angle2 >= startAngle : angle2 <= endAngle && angle2 >= -Math.PI || angle2 >= startAngle && angle2 <= Math.PI;
}
function lineCollidesSector(line, sector) {
  const { startAngle, endAngle, innerRadius, outerRadius } = sector;
  const outerStart = { x: outerRadius * Math.cos(startAngle), y: outerRadius * Math.sin(startAngle) };
  const outerEnd = { x: outerRadius * Math.cos(endAngle), y: outerRadius * Math.sin(endAngle) };
  const innerStart = innerRadius === 0 ? { x: 0, y: 0 } : { x: innerRadius * Math.cos(startAngle), y: innerRadius * Math.sin(startAngle) };
  const innerEnd = innerRadius === 0 ? { x: 0, y: 0 } : { x: innerRadius * Math.cos(endAngle), y: innerRadius * Math.sin(endAngle) };
  return segmentIntersection(
    line.start.x,
    line.start.y,
    line.end.x,
    line.end.y,
    outerStart.x,
    outerStart.y,
    innerStart.x,
    innerStart.y
  ) || segmentIntersection(
    line.start.x,
    line.start.y,
    line.end.x,
    line.end.y,
    outerEnd.x,
    outerEnd.y,
    innerEnd.x,
    innerEnd.y
  ) || arcIntersections(
    0,
    0,
    outerRadius,
    startAngle,
    endAngle,
    true,
    line.start.x,
    line.start.y,
    line.end.x,
    line.end.y
  );
}
function boxCollidesSector(box, sector) {
  const topLeft = { x: box.x, y: box.y };
  const topRight = { x: box.x + box.width, y: box.y };
  const bottomLeft = { x: box.x, y: box.y + box.height };
  const bottomRight = { x: box.x + box.width, y: box.y + box.height };
  return lineCollidesSector({ start: topLeft, end: topRight }, sector) || lineCollidesSector({ start: bottomLeft, end: bottomRight }, sector);
}
function radiiScalingFactor(r, sweep, a, b) {
  if (a === 0 && b === 0)
    return 0;
  const fs1 = Math.asin(Math.abs(1 * a) / (r + 1 * a)) + Math.asin(Math.abs(1 * b) / (r + 1 * b)) - sweep;
  if (fs1 < 0)
    return 1;
  let start2 = 0;
  let end2 = 1;
  for (let i = 0; i < 8; i += 1) {
    const s = (start2 + end2) / 2;
    const fs = Math.asin(Math.abs(s * a) / (r + s * a)) + Math.asin(Math.abs(s * b) / (r + s * b)) - sweep;
    if (fs < 0) {
      start2 = s;
    } else {
      end2 = s;
    }
  }
  return start2;
}
var delta3 = 1e-6;
function clockwiseAngle2(angle2, relativeToStartAngle) {
  if (angleBetween(angle2, relativeToStartAngle) < delta3) {
    return relativeToStartAngle;
  } else {
    return normalizeAngle360(angle2 - relativeToStartAngle) + relativeToStartAngle;
  }
}
function clockwiseAngles2(startAngle, endAngle, relativeToStartAngle = 0) {
  const fullPie = Math.abs(endAngle - startAngle) >= 2 * Math.PI;
  const sweepAngle = fullPie ? 2 * Math.PI : normalizeAngle360(endAngle - startAngle);
  startAngle = clockwiseAngle2(startAngle, relativeToStartAngle);
  endAngle = startAngle + sweepAngle;
  return { startAngle, endAngle };
}
function arcRadialLineIntersectionAngle(cx, cy, r, startAngle, endAngle, clipAngle) {
  const sinA = Math.sin(clipAngle);
  const cosA = Math.cos(clipAngle);
  const c = cx ** 2 + cy ** 2 - r ** 2;
  let p0x;
  let p0y;
  let p1x;
  let p1y;
  if (cosA > 0.5) {
    const tanA = sinA / cosA;
    const a = 1 + tanA ** 2;
    const b = -2 * (cx + cy * tanA);
    const d = b ** 2 - 4 * a * c;
    if (d < 0)
      return;
    const x0 = (-b + Math.sqrt(d)) / (2 * a);
    const x1 = (-b - Math.sqrt(d)) / (2 * a);
    p0x = x0;
    p0y = x0 * tanA;
    p1x = x1;
    p1y = x1 * tanA;
  } else {
    const cotA = cosA / sinA;
    const a = 1 + cotA ** 2;
    const b = -2 * (cy + cx * cotA);
    const d = b ** 2 - 4 * a * c;
    if (d < 0)
      return;
    const y0 = (-b + Math.sqrt(d)) / (2 * a);
    const y1 = (-b - Math.sqrt(d)) / (2 * a);
    p0x = y0 * cotA;
    p0y = y0;
    p1x = y1 * cotA;
    p1y = y1;
  }
  const normalisedX = cosA;
  const normalisedY = sinA;
  const p0DotNormalized = p0x * normalisedX + p0y * normalisedY;
  const p1DotNormalized = p1x * normalisedX + p1y * normalisedY;
  const a0 = p0DotNormalized > 0 ? clockwiseAngle2(Math.atan2(p0y - cy, p0x - cx), startAngle) : NaN;
  const a1 = p1DotNormalized > 0 ? clockwiseAngle2(Math.atan2(p1y - cy, p1x - cx), startAngle) : NaN;
  if (a0 >= startAngle && a0 <= endAngle) {
    return a0;
  } else if (a1 >= startAngle && a1 <= endAngle) {
    return a1;
  }
}
function arcCircleIntersectionAngle(cx, cy, r, startAngle, endAngle, circleR) {
  const d = Math.hypot(cx, cy);
  const d1 = (d ** 2 - r ** 2 + circleR ** 2) / (2 * d);
  const d2 = d - d1;
  const theta = Math.atan2(cy, cx);
  const deltaTheta = Math.acos(-d2 / r);
  const a0 = clockwiseAngle2(theta + deltaTheta, startAngle);
  const a1 = clockwiseAngle2(theta - deltaTheta, startAngle);
  if (a0 >= startAngle && a0 <= endAngle) {
    return a0;
  } else if (a1 >= startAngle && a1 <= endAngle) {
    return a1;
  }
}
var Arc = class {
  constructor(cx, cy, r, a0, a1) {
    this.cx = cx;
    this.cy = cy;
    this.r = r;
    this.a0 = a0;
    this.a1 = a1;
    if (this.a0 >= this.a1) {
      this.a0 = NaN;
      this.a1 = NaN;
    }
  }
  isValid() {
    return Number.isFinite(this.a0) && Number.isFinite(this.a1);
  }
  pointAt(a) {
    return {
      x: this.cx + this.r * Math.cos(a),
      y: this.cy + this.r * Math.sin(a)
    };
  }
  clipStart(a) {
    if (a == null || !this.isValid() || a < this.a0)
      return;
    this.a0 = a;
    if (Number.isNaN(a) || this.a0 >= this.a1) {
      this.a0 = NaN;
      this.a1 = NaN;
    }
  }
  clipEnd(a) {
    if (a == null || !this.isValid() || a > this.a1)
      return;
    this.a1 = a;
    if (Number.isNaN(a) || this.a0 >= this.a1) {
      this.a0 = NaN;
      this.a1 = NaN;
    }
  }
};
var Sector = class extends Path {
  constructor() {
    super(...arguments);
    this.centerX = 0;
    this.centerY = 0;
    this.innerRadius = 10;
    this.outerRadius = 20;
    this.startAngle = 0;
    this.endAngle = Math.PI * 2;
    this.clipSector = void 0;
    this.concentricEdgeInset = 0;
    this.radialEdgeInset = 0;
    this.startOuterCornerRadius = 0;
    this.endOuterCornerRadius = 0;
    this.startInnerCornerRadius = 0;
    this.endInnerCornerRadius = 0;
  }
  set inset(value) {
    this.concentricEdgeInset = value;
    this.radialEdgeInset = value;
  }
  set cornerRadius(value) {
    this.startOuterCornerRadius = value;
    this.endOuterCornerRadius = value;
    this.startInnerCornerRadius = value;
    this.endInnerCornerRadius = value;
  }
  computeBBox() {
    return sectorBox(this).translate(this.centerX, this.centerY);
  }
  normalizedRadii() {
    const { concentricEdgeInset } = this;
    let { innerRadius, outerRadius } = this;
    innerRadius = innerRadius > 0 ? innerRadius + concentricEdgeInset : 0;
    outerRadius = Math.max(outerRadius - concentricEdgeInset, 0);
    return { innerRadius, outerRadius };
  }
  normalizedClipSector() {
    const { clipSector } = this;
    if (clipSector == null)
      return;
    const { startAngle, endAngle } = clockwiseAngles2(this.startAngle, this.endAngle);
    const { innerRadius, outerRadius } = this.normalizedRadii();
    const clipAngles = clockwiseAngles2(clipSector.startAngle, clipSector.endAngle, startAngle);
    return new SectorBox(
      Math.max(startAngle, clipAngles.startAngle),
      Math.min(endAngle, clipAngles.endAngle),
      Math.max(innerRadius, clipSector.innerRadius),
      Math.min(outerRadius, clipSector.outerRadius)
    );
  }
  getAngleOffset(radius) {
    return radius > 0 ? this.radialEdgeInset / radius : 0;
  }
  arc(r, angleSweep, a0, a1, outerArc, innerArc, start2, inner) {
    if (r <= 0)
      return;
    const { startAngle, endAngle } = clockwiseAngles2(this.startAngle, this.endAngle);
    const { innerRadius, outerRadius } = this.normalizedRadii();
    const clipSector = this.normalizedClipSector();
    if (inner && innerRadius <= 0)
      return;
    const angleOffset = inner ? this.getAngleOffset(innerRadius + r) : this.getAngleOffset(outerRadius - r);
    const angle2 = start2 ? startAngle + angleOffset + angleSweep : endAngle - angleOffset - angleSweep;
    const radius = inner ? innerRadius + r : outerRadius - r;
    const cx = radius * Math.cos(angle2);
    const cy = radius * Math.sin(angle2);
    if (clipSector != null) {
      const delta4 = 1e-6;
      if (!start2 && !(angle2 >= startAngle - delta4 && angle2 <= clipSector.endAngle - delta4))
        return;
      if (start2 && !(angle2 >= clipSector.startAngle + delta4 && angle2 <= endAngle - delta4))
        return;
      if (inner && radius < clipSector.innerRadius - delta4)
        return;
      if (!inner && radius > clipSector.outerRadius + delta4)
        return;
    }
    const arc = new Arc(cx, cy, r, a0, a1);
    if (clipSector != null) {
      if (inner) {
        arc.clipStart(arcRadialLineIntersectionAngle(cx, cy, r, a0, a1, clipSector.endAngle));
        arc.clipEnd(arcRadialLineIntersectionAngle(cx, cy, r, a0, a1, clipSector.startAngle));
      } else {
        arc.clipStart(arcRadialLineIntersectionAngle(cx, cy, r, a0, a1, clipSector.startAngle));
        arc.clipEnd(arcRadialLineIntersectionAngle(cx, cy, r, a0, a1, clipSector.endAngle));
      }
      let circleClipStart;
      let circleClipEnd;
      if (start2) {
        circleClipStart = arcCircleIntersectionAngle(cx, cy, r, a0, a1, clipSector.innerRadius);
        circleClipEnd = arcCircleIntersectionAngle(cx, cy, r, a0, a1, clipSector.outerRadius);
      } else {
        circleClipStart = arcCircleIntersectionAngle(cx, cy, r, a0, a1, clipSector.outerRadius);
        circleClipEnd = arcCircleIntersectionAngle(cx, cy, r, a0, a1, clipSector.innerRadius);
      }
      arc.clipStart(circleClipStart);
      arc.clipEnd(circleClipEnd);
      if (circleClipStart != null) {
        const { x: x2, y: y2 } = arc.pointAt(circleClipStart);
        const theta2 = clockwiseAngle2(Math.atan2(y2, x2), startAngle);
        if (start2) {
          innerArc?.clipStart(theta2);
        } else {
          outerArc.clipEnd(theta2);
        }
      }
      if (circleClipEnd != null) {
        const { x: x2, y: y2 } = arc.pointAt(circleClipEnd);
        const theta2 = clockwiseAngle2(Math.atan2(y2, x2), startAngle);
        if (start2) {
          outerArc.clipStart(theta2);
        } else {
          innerArc?.clipEnd(theta2);
        }
      }
    }
    if (clipSector != null) {
      const { x: x2, y: y2 } = arc.pointAt((arc.a0 + arc.a1) / 2);
      if (!isPointInSector(x2, y2, clipSector))
        return;
    }
    const { x, y } = arc.pointAt(start2 === inner ? arc.a0 : arc.a1);
    const theta = clockwiseAngle2(Math.atan2(y, x), startAngle);
    const radialArc = inner ? innerArc : outerArc;
    if (start2) {
      radialArc?.clipStart(theta);
    } else {
      radialArc?.clipEnd(theta);
    }
    return arc;
  }
  updatePath() {
    const delta4 = 1e-6;
    const { path, centerX, centerY, concentricEdgeInset, radialEdgeInset } = this;
    let { startOuterCornerRadius, endOuterCornerRadius, startInnerCornerRadius, endInnerCornerRadius } = this;
    const { startAngle, endAngle } = clockwiseAngles2(this.startAngle, this.endAngle);
    const { innerRadius, outerRadius } = this.normalizedRadii();
    const clipSector = this.normalizedClipSector();
    const sweepAngle = endAngle - startAngle;
    const fullPie = sweepAngle >= 2 * Math.PI - delta4;
    path.clear();
    if (innerRadius === 0 && outerRadius === 0 || innerRadius > outerRadius) {
      return;
    } else if ((clipSector?.startAngle ?? startAngle) === (clipSector?.endAngle ?? endAngle)) {
      return;
    } else if (fullPie && this.clipSector == null && startOuterCornerRadius === 0 && endOuterCornerRadius === 0 && startInnerCornerRadius === 0 && endInnerCornerRadius === 0) {
      path.moveTo(centerX + outerRadius * Math.cos(startAngle), centerY + outerRadius * Math.sin(startAngle));
      path.arc(centerX, centerY, outerRadius, startAngle, endAngle);
      if (innerRadius > concentricEdgeInset) {
        path.moveTo(centerX + innerRadius * Math.cos(endAngle), centerY + innerRadius * Math.sin(endAngle));
        path.arc(centerX, centerY, innerRadius, endAngle, startAngle, true);
      }
      path.closePath();
      return;
    } else if (this.clipSector == null && Math.abs(innerRadius - outerRadius) < 1e-6) {
      path.arc(centerX, centerY, outerRadius, startAngle, endAngle, false);
      path.arc(centerX, centerY, outerRadius, endAngle, startAngle, true);
      path.closePath();
      return;
    }
    const innerAngleOffset = this.getAngleOffset(innerRadius);
    const outerAngleOffset = this.getAngleOffset(outerRadius);
    const outerAngleExceeded = sweepAngle < 2 * outerAngleOffset;
    if (outerAngleExceeded)
      return;
    const hasInnerSweep = (clipSector?.innerRadius ?? innerRadius) > concentricEdgeInset;
    const innerAngleExceeded = innerRadius < concentricEdgeInset || sweepAngle < 2 * innerAngleOffset;
    const radialLength = outerRadius - innerRadius;
    const maxRadialLength = Math.max(
      startOuterCornerRadius,
      startInnerCornerRadius,
      endOuterCornerRadius,
      endInnerCornerRadius
    );
    const initialScalingFactor = maxRadialLength > 0 ? Math.min(radialLength / maxRadialLength, 1) : 1;
    startOuterCornerRadius *= initialScalingFactor;
    endOuterCornerRadius *= initialScalingFactor;
    startInnerCornerRadius *= initialScalingFactor;
    endInnerCornerRadius *= initialScalingFactor;
    const outerScalingFactor = radiiScalingFactor(
      outerRadius,
      sweepAngle - 2 * outerAngleOffset,
      -startOuterCornerRadius,
      -endOuterCornerRadius
    );
    startOuterCornerRadius *= outerScalingFactor;
    endOuterCornerRadius *= outerScalingFactor;
    if (!innerAngleExceeded && hasInnerSweep) {
      const innerScalingFactor = radiiScalingFactor(
        innerRadius,
        sweepAngle - 2 * innerAngleOffset,
        startInnerCornerRadius,
        endInnerCornerRadius
      );
      startInnerCornerRadius *= innerScalingFactor;
      endInnerCornerRadius *= innerScalingFactor;
    } else {
      startInnerCornerRadius = 0;
      endInnerCornerRadius = 0;
    }
    const maxCombinedRadialLength = Math.max(
      startOuterCornerRadius + startInnerCornerRadius,
      endOuterCornerRadius + endInnerCornerRadius
    );
    const edgesScalingFactor = maxCombinedRadialLength > 0 ? Math.min(radialLength / maxCombinedRadialLength, 1) : 1;
    startOuterCornerRadius *= edgesScalingFactor;
    endOuterCornerRadius *= edgesScalingFactor;
    startInnerCornerRadius *= edgesScalingFactor;
    endInnerCornerRadius *= edgesScalingFactor;
    let startOuterCornerRadiusAngleSweep = 0;
    let endOuterCornerRadiusAngleSweep = 0;
    const startOuterCornerRadiusSweep = startOuterCornerRadius / (outerRadius - startOuterCornerRadius);
    const endOuterCornerRadiusSweep = endOuterCornerRadius / (outerRadius - endOuterCornerRadius);
    if (startOuterCornerRadiusSweep >= 0 && startOuterCornerRadiusSweep < 1 - delta4) {
      startOuterCornerRadiusAngleSweep = Math.asin(startOuterCornerRadiusSweep);
    } else {
      startOuterCornerRadiusAngleSweep = sweepAngle / 2;
      const maxStartOuterCornerRadius = outerRadius / (1 / Math.sin(startOuterCornerRadiusAngleSweep) + 1);
      startOuterCornerRadius = Math.min(maxStartOuterCornerRadius, startOuterCornerRadius);
    }
    if (endOuterCornerRadiusSweep >= 0 && endOuterCornerRadiusSweep < 1 - delta4) {
      endOuterCornerRadiusAngleSweep = Math.asin(endOuterCornerRadiusSweep);
    } else {
      endOuterCornerRadiusAngleSweep = sweepAngle / 2;
      const maxEndOuterCornerRadius = outerRadius / (1 / Math.sin(endOuterCornerRadiusAngleSweep) + 1);
      endOuterCornerRadius = Math.min(maxEndOuterCornerRadius, endOuterCornerRadius);
    }
    const startInnerCornerRadiusAngleSweep = Math.asin(
      startInnerCornerRadius / (innerRadius + startInnerCornerRadius)
    );
    const endInnerCornerRadiusAngleSweep = Math.asin(endInnerCornerRadius / (innerRadius + endInnerCornerRadius));
    const outerArcRadius = clipSector?.outerRadius ?? outerRadius;
    const outerArcRadiusOffset = this.getAngleOffset(outerArcRadius);
    const outerArc = new Arc(
      0,
      0,
      outerArcRadius,
      startAngle + outerArcRadiusOffset,
      endAngle - outerArcRadiusOffset
    );
    const innerArcRadius = clipSector?.innerRadius ?? innerRadius;
    const innerArcRadiusOffset = this.getAngleOffset(innerArcRadius);
    const innerArc = hasInnerSweep ? new Arc(0, 0, innerArcRadius, startAngle + innerArcRadiusOffset, endAngle - innerArcRadiusOffset) : void 0;
    if (clipSector != null) {
      outerArc.clipStart(clipSector.startAngle);
      outerArc.clipEnd(clipSector.endAngle);
      innerArc?.clipStart(clipSector.startAngle);
      innerArc?.clipEnd(clipSector.endAngle);
    }
    const startOuterArc = this.arc(
      startOuterCornerRadius,
      startOuterCornerRadiusAngleSweep,
      startAngle - Math.PI * 0.5,
      startAngle + startOuterCornerRadiusAngleSweep,
      outerArc,
      innerArc,
      true,
      false
    );
    const endOuterArc = this.arc(
      endOuterCornerRadius,
      endOuterCornerRadiusAngleSweep,
      endAngle - endOuterCornerRadiusAngleSweep,
      endAngle + Math.PI * 0.5,
      outerArc,
      innerArc,
      false,
      false
    );
    const endInnerArc = this.arc(
      endInnerCornerRadius,
      endInnerCornerRadiusAngleSweep,
      endAngle + Math.PI * 0.5,
      endAngle + Math.PI - endInnerCornerRadiusAngleSweep,
      outerArc,
      innerArc,
      false,
      true
    );
    const startInnerArc = this.arc(
      startInnerCornerRadius,
      startInnerCornerRadiusAngleSweep,
      startAngle + Math.PI + startInnerCornerRadiusAngleSweep,
      startAngle + Math.PI * 1.5,
      outerArc,
      innerArc,
      true,
      true
    );
    if (innerAngleExceeded) {
      const x = sweepAngle < Math.PI * 0.5 ? radialEdgeInset * (1 + Math.cos(sweepAngle)) / Math.sin(sweepAngle) : NaN;
      let r;
      if (x > 0 && x < outerRadius) {
        r = Math.max(Math.hypot(radialEdgeInset, x), innerRadius);
      } else {
        r = radialEdgeInset;
      }
      r = Math.max(r, innerRadius);
      const midAngle = startAngle + sweepAngle * 0.5;
      path.moveTo(centerX + r * Math.cos(midAngle), centerY + r * Math.sin(midAngle));
    } else if (startInnerArc?.isValid() === true || innerArc?.isValid() === true) {
    } else {
      const midAngle = startAngle + sweepAngle / 2;
      const cx = innerRadius * Math.cos(midAngle);
      const cy = innerRadius * Math.sin(midAngle);
      path.moveTo(centerX + cx, centerY + cy);
    }
    if (startOuterArc?.isValid() === true) {
      const { cx, cy, r, a0, a1 } = startOuterArc;
      path.arc(centerX + cx, centerY + cy, r, a0, a1);
    }
    if (outerArc.isValid()) {
      const { r, a0, a1 } = outerArc;
      path.arc(centerX, centerY, r, a0, a1);
    }
    if (endOuterArc?.isValid() === true) {
      const { cx, cy, r, a0, a1 } = endOuterArc;
      path.arc(centerX + cx, centerY + cy, r, a0, a1);
    }
    if (!innerAngleExceeded) {
      if (endInnerArc?.isValid() === true) {
        const { cx, cy, r, a0, a1 } = endInnerArc;
        path.arc(centerX + cx, centerY + cy, r, a0, a1);
      }
      if (innerArc?.isValid() === true) {
        const { r, a0, a1 } = innerArc;
        path.arc(centerX, centerY, r, a1, a0, true);
      }
      if (startInnerArc?.isValid() === true) {
        const { cx, cy, r, a0, a1 } = startInnerArc;
        path.arc(centerX + cx, centerY + cy, r, a0, a1);
      }
    }
    path.closePath();
  }
  isPointInPath(x, y) {
    const { startAngle, endAngle, innerRadius, outerRadius } = this.clipSector ?? this;
    return isPointInSector(x - this.centerX, y - this.centerY, {
      startAngle,
      endAngle,
      innerRadius: Math.min(innerRadius, outerRadius),
      outerRadius: Math.max(innerRadius, outerRadius)
    });
  }
};
Sector.className = "Sector";
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "centerX", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "centerY", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "innerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "outerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "startAngle", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "endAngle", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "clipSector", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "concentricEdgeInset", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "radialEdgeInset", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "startOuterCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "endOuterCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "startInnerCornerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Sector.prototype, "endInnerCornerRadius", 2);
var DEFAULT_FILLS = {
  BLUE: "#5090dc",
  ORANGE: "#ffa03a",
  GREEN: "#459d55",
  CYAN: "#34bfe1",
  YELLOW: "#e1cc00",
  VIOLET: "#9669cb",
  GRAY: "#b5b5b5",
  MAGENTA: "#bd5aa7",
  BROWN: "#8a6224",
  RED: "#ef5452"
};
var DEFAULT_STROKES = {
  BLUE: "#2b5c95",
  ORANGE: "#cc6f10",
  GREEN: "#1e652e",
  CYAN: "#18859e",
  YELLOW: "#a69400",
  VIOLET: "#603c88",
  GRAY: "#575757",
  MAGENTA: "#7d2f6d",
  BROWN: "#4f3508",
  RED: "#a82529"
};
var DonutTitle = class extends Caption {
  constructor() {
    super(...arguments);
    this.showInLegend = false;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], DonutTitle.prototype, "showInLegend", 2);
var DonutInnerLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.spacing = 2;
  }
  set(properties, _reset) {
    return super.set(properties);
  }
};
__decorateClass([
  Validate(STRING)
], DonutInnerLabel.prototype, "text", 2);
__decorateClass([
  Validate(NUMBER)
], DonutInnerLabel.prototype, "spacing", 2);
var DonutInnerCircle = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.fill = "transparent";
    this.fillOpacity = 1;
  }
};
__decorateClass([
  Validate(COLOR_STRING)
], DonutInnerCircle.prototype, "fill", 2);
__decorateClass([
  Validate(RATIO)
], DonutInnerCircle.prototype, "fillOpacity", 2);
var DonutSeriesCalloutLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.offset = 3;
    this.minAngle = 0;
    this.minSpacing = 4;
    this.maxCollisionOffset = 50;
    this.avoidCollisions = true;
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesCalloutLabel.prototype, "offset", 2);
__decorateClass([
  Validate(NUMBER.restrict({ min: 0, max: 360 }))
], DonutSeriesCalloutLabel.prototype, "minAngle", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesCalloutLabel.prototype, "minSpacing", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesCalloutLabel.prototype, "maxCollisionOffset", 2);
__decorateClass([
  Validate(BOOLEAN)
], DonutSeriesCalloutLabel.prototype, "avoidCollisions", 2);
var DonutSeriesSectorLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.positionOffset = 0;
    this.positionRatio = 0.5;
  }
};
__decorateClass([
  Validate(NUMBER)
], DonutSeriesSectorLabel.prototype, "positionOffset", 2);
__decorateClass([
  Validate(RATIO)
], DonutSeriesSectorLabel.prototype, "positionRatio", 2);
var DonutSeriesCalloutLine = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.length = 10;
    this.strokeWidth = 1;
  }
};
__decorateClass([
  Validate(COLOR_STRING_ARRAY, { optional: true })
], DonutSeriesCalloutLine.prototype, "colors", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesCalloutLine.prototype, "length", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesCalloutLine.prototype, "strokeWidth", 2);
var DonutSeriesProperties = class extends SeriesProperties {
  constructor() {
    super(...arguments);
    this.fills = Object.values(DEFAULT_FILLS);
    this.strokes = Object.values(DEFAULT_STROKES);
    this.fillOpacity = 1;
    this.strokeOpacity = 1;
    this.lineDash = [0];
    this.lineDashOffset = 0;
    this.cornerRadius = 0;
    this.rotation = 0;
    this.outerRadiusOffset = 0;
    this.outerRadiusRatio = 1;
    this.strokeWidth = 1;
    this.sectorSpacing = 0;
    this.hideZeroValueSectorsInLegend = false;
    this.innerLabels = new PropertiesArray(DonutInnerLabel);
    this.title = new DonutTitle();
    this.innerCircle = new DonutInnerCircle();
    this.shadow = new DropShadow();
    this.calloutLabel = new DonutSeriesCalloutLabel();
    this.sectorLabel = new DonutSeriesSectorLabel();
    this.calloutLine = new DonutSeriesCalloutLine();
    this.tooltip = new SeriesTooltip();
  }
  isValid() {
    const superIsValid = super.isValid();
    if (this.innerRadiusRatio == null && this.innerRadiusOffset == null) {
      Logger.warnOnce(
        "Either an [innerRadiusRatio] or an [innerRadiusOffset] must be set to render a donut series."
      );
      return false;
    }
    return superIsValid;
  }
};
__decorateClass([
  Validate(STRING)
], DonutSeriesProperties.prototype, "angleKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "angleName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "angleFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "radiusKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "radiusName", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], DonutSeriesProperties.prototype, "radiusMin", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], DonutSeriesProperties.prototype, "radiusMax", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "calloutLabelKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "calloutLabelName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "sectorLabelKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "sectorLabelName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], DonutSeriesProperties.prototype, "legendItemKey", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], DonutSeriesProperties.prototype, "fills", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], DonutSeriesProperties.prototype, "strokes", 2);
__decorateClass([
  Validate(RATIO)
], DonutSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(RATIO)
], DonutSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH)
], DonutSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], DonutSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
  Validate(NUMBER)
], DonutSeriesProperties.prototype, "rotation", 2);
__decorateClass([
  Validate(NUMBER)
], DonutSeriesProperties.prototype, "outerRadiusOffset", 2);
__decorateClass([
  Validate(RATIO)
], DonutSeriesProperties.prototype, "outerRadiusRatio", 2);
__decorateClass([
  Validate(NUMBER, { optional: true })
], DonutSeriesProperties.prototype, "innerRadiusOffset", 2);
__decorateClass([
  Validate(RATIO, { optional: true })
], DonutSeriesProperties.prototype, "innerRadiusRatio", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], DonutSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(NUMBER)
], DonutSeriesProperties.prototype, "sectorSpacing", 2);
__decorateClass([
  Validate(BOOLEAN)
], DonutSeriesProperties.prototype, "hideZeroValueSectorsInLegend", 2);
__decorateClass([
  Validate(OBJECT_ARRAY)
], DonutSeriesProperties.prototype, "innerLabels", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "title", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "innerCircle", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "shadow", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "calloutLabel", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "sectorLabel", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "calloutLine", 2);
__decorateClass([
  Validate(OBJECT)
], DonutSeriesProperties.prototype, "tooltip", 2);
function preparePieSeriesAnimationFunctions(initialLoad, rotationDegrees, scaleFn, oldScaleFn) {
  const scale2 = [scaleFn.convert(0), scaleFn.convert(1)];
  const oldScale = [oldScaleFn.convert(0), oldScaleFn.convert(1)];
  const rotation = Math.PI / -2 + toRadians(rotationDegrees);
  const phase = initialLoad ? "initial" : "update";
  const scaleToNewRadius = ({ radius }) => {
    return { innerRadius: scale2[0], outerRadius: scale2[0] + (scale2[1] - scale2[0]) * radius };
  };
  const scaleToOldRadius = ({ radius }) => {
    return { innerRadius: oldScale[0], outerRadius: oldScale[0] + (oldScale[1] - oldScale[0]) * radius };
  };
  const fromFn = (sect, datum, status, { prevFromProps }) => {
    let { startAngle, endAngle, innerRadius, outerRadius } = sect;
    let { fill, stroke } = datum.sectorFormat;
    if (status === "unknown" || status === "added" && !prevFromProps) {
      startAngle = rotation;
      endAngle = rotation;
      innerRadius = datum.innerRadius;
      outerRadius = datum.outerRadius;
    } else if (status === "added" && prevFromProps) {
      startAngle = prevFromProps.endAngle ?? rotation;
      endAngle = prevFromProps.endAngle ?? rotation;
      innerRadius = prevFromProps.innerRadius ?? datum.innerRadius;
      outerRadius = prevFromProps.outerRadius ?? datum.outerRadius;
    }
    if (status === "added" && !initialLoad) {
      const radii = scaleToOldRadius(datum);
      innerRadius = radii.innerRadius;
      outerRadius = radii.outerRadius;
    }
    if (status === "updated") {
      fill = sect.fill ?? fill;
      stroke = (typeof sect.stroke === "string" ? sect.stroke : void 0) ?? stroke;
    }
    return { startAngle, endAngle, innerRadius, outerRadius, fill, stroke, phase };
  };
  const toFn = (_sect, datum, status, { prevLive }) => {
    let { startAngle, endAngle, innerRadius, outerRadius } = datum;
    const { stroke, fill } = datum.sectorFormat;
    if (status === "removed" && prevLive) {
      startAngle = prevLive.datum?.endAngle;
      endAngle = prevLive.datum?.endAngle;
    } else if (status === "removed" && !prevLive) {
      startAngle = rotation;
      endAngle = rotation;
    }
    if (status === "removed") {
      const radii = scaleToNewRadius(datum);
      innerRadius = radii.innerRadius;
      outerRadius = radii.outerRadius;
    }
    return { startAngle, endAngle, outerRadius, innerRadius, stroke, fill };
  };
  const innerCircleFromFn = (node, _) => {
    return { size: node.previousDatum?.radius ?? node.size ?? 0, phase };
  };
  const innerCircleToFn = (_, datum) => {
    return { size: datum.radius ?? 0 };
  };
  return { nodes: { toFn, fromFn }, innerCircle: { fromFn: innerCircleFromFn, toFn: innerCircleToFn } };
}
function resetPieSelectionsFn(_node, datum) {
  return {
    startAngle: datum.startAngle,
    endAngle: datum.endAngle,
    innerRadius: datum.innerRadius,
    outerRadius: datum.outerRadius,
    fill: datum.sectorFormat.fill,
    stroke: datum.sectorFormat.stroke
  };
}
function pickByMatchingAngle(series, point) {
  const dy = point.y - series.centerY;
  const dx = point.x - series.centerX;
  const angle2 = Math.atan2(dy, dx);
  const sectors = series.getItemNodes();
  for (const sector of sectors) {
    if (sector.datum.missing === true)
      continue;
    if (isBetweenAngles(angle2, sector.startAngle, sector.endAngle)) {
      const radius = Math.sqrt(dx * dx + dy * dy);
      let distance3 = 0;
      if (radius < sector.innerRadius) {
        distance3 = sector.innerRadius - radius;
      } else if (radius > sector.outerRadius) {
        distance3 = radius - sector.outerRadius;
      }
      return { datum: sector.datum, distance: distance3 };
    }
  }
  return void 0;
}
var PolarZIndexMap = /* @__PURE__ */ ((PolarZIndexMap2) => {
  PolarZIndexMap2[PolarZIndexMap2["BACKGROUND"] = 0] = "BACKGROUND";
  PolarZIndexMap2[PolarZIndexMap2["FOREGROUND"] = 1] = "FOREGROUND";
  PolarZIndexMap2[PolarZIndexMap2["HIGHLIGHT"] = 2] = "HIGHLIGHT";
  PolarZIndexMap2[PolarZIndexMap2["LABEL"] = 3] = "LABEL";
  return PolarZIndexMap2;
})(PolarZIndexMap || {});
var PolarSeries = class extends DataModelSeries {
  constructor({
    useLabelLayer = false,
    pickModes = [
      1,
      0
      /* EXACT_SHAPE_MATCH */
    ],
    canHaveAxes = false,
    animationResetFns,
    ...opts
  }) {
    super({
      ...opts,
      useLabelLayer,
      pickModes,
      directionKeys: {
        [
          "x"
          /* X */
        ]: ["angleKey"],
        [
          "y"
          /* Y */
        ]: ["radiusKey"]
      },
      directionNames: {
        [
          "x"
          /* X */
        ]: ["angleName"],
        [
          "y"
          /* Y */
        ]: ["radiusName"]
      },
      canHaveAxes
    });
    this.itemGroup = this.contentGroup.appendChild(new Group());
    this.nodeData = [];
    this.itemSelection = Selection.select(
      this.itemGroup,
      () => this.nodeFactory(),
      false
    );
    this.labelSelection = Selection.select(
      this.labelGroup,
      () => this.labelFactory(),
      false
    );
    this.highlightSelection = Selection.select(
      this.highlightGroup,
      () => this.nodeFactory()
    );
    this.highlightLabelSelection = Selection.select(
      this.highlightLabel,
      () => this.labelFactory()
    );
    this.centerX = 0;
    this.centerY = 0;
    this.radius = 0;
    this.animationResetFns = animationResetFns;
    this.animationState = new StateMachine(
      "empty",
      {
        empty: {
          update: {
            target: "ready",
            action: (data) => this.animateEmptyUpdateReady(data)
          },
          reset: "empty",
          skip: "ready"
        },
        ready: {
          updateData: "waiting",
          clear: "clearing",
          highlight: (data) => this.animateReadyHighlight(data),
          highlightMarkers: (data) => this.animateReadyHighlightMarkers(data),
          resize: (data) => this.animateReadyResize(data),
          reset: "empty",
          skip: "ready"
        },
        waiting: {
          update: {
            target: "ready",
            action: (data) => this.animateWaitingUpdateReady(data)
          },
          reset: "empty",
          skip: "ready"
        },
        clearing: {
          update: {
            target: "empty",
            action: (data) => this.animateClearingUpdateEmpty(data)
          },
          reset: "empty",
          skip: "ready"
        }
      },
      () => this.checkProcessedDataAnimatable()
    );
  }
  getItemNodes() {
    return [...this.itemGroup.children()];
  }
  getNodeData() {
    return this.nodeData;
  }
  setSeriesIndex(index) {
    if (!super.setSeriesIndex(index))
      return false;
    this.contentGroup.zIndex = [
      index,
      1
      /* FOREGROUND */
    ];
    this.highlightGroup.zIndex = [
      index,
      2
      /* HIGHLIGHT */
    ];
    this.labelGroup.zIndex = [
      index,
      3
      /* LABEL */
    ];
    return true;
  }
  resetAnimation(phase) {
    if (phase === "initial") {
      this.animationState.transition("reset");
    } else if (phase === "ready") {
      this.animationState.transition("skip");
    }
  }
  labelFactory() {
    const text = new Text();
    text.pointerEvents = 1;
    return text;
  }
  addChartEventListeners() {
    this.destroyFns.push(
      this.ctx.chartEventManager?.addListener("legend-item-click", (event) => this.onLegendItemClick(event))
    );
  }
  getInnerRadius() {
    return 0;
  }
  computeLabelsBBox(_options, _seriesRect) {
    return null;
  }
  resetAllAnimation() {
    const { item, label } = this.animationResetFns ?? {};
    this.ctx.animationManager.stopByAnimationGroupId(this.id);
    if (item) {
      resetMotion([this.itemSelection, this.highlightSelection], item);
    }
    if (label) {
      resetMotion([this.labelSelection, this.highlightLabelSelection], label);
    }
    this.itemSelection.cleanup();
    this.labelSelection.cleanup();
    this.highlightSelection.cleanup();
    this.highlightLabelSelection.cleanup();
  }
  animateEmptyUpdateReady(_data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation();
  }
  animateWaitingUpdateReady(_data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation();
  }
  animateReadyHighlight(_data) {
    const { item, label } = this.animationResetFns ?? {};
    if (item) {
      resetMotion([this.highlightSelection], item);
    }
    if (label) {
      resetMotion([this.highlightLabelSelection], label);
    }
  }
  animateReadyHighlightMarkers(_data) {
  }
  animateReadyResize(_data) {
    this.resetAllAnimation();
  }
  animateClearingUpdateEmpty(_data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation();
  }
  computeFocusBounds(opts) {
    const datum = this.getNodeData()?.[opts.datumIndex];
    if (datum !== void 0) {
      return this.itemSelection.select((node) => node instanceof Path && node.datum === datum)[0];
    }
    return void 0;
  }
  getSeriesRange(_direction, _visibleRange) {
    return [NaN, NaN];
  }
};
var DonutSeriesNodeEvent = class extends SeriesNodeEvent {
  constructor(type, nativeEvent, datum, series) {
    super(type, nativeEvent, datum, series);
    this.angleKey = series.properties.angleKey;
    this.radiusKey = series.properties.radiusKey;
    this.calloutLabelKey = series.properties.calloutLabelKey;
    this.sectorLabelKey = series.properties.sectorLabelKey;
  }
};
var DonutSeries = class extends PolarSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      pickModes: [
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      useLabelLayer: true,
      animationResetFns: { item: resetPieSelectionsFn, label: resetLabelFn }
    });
    this.properties = new DonutSeriesProperties();
    this.phantomNodeData = void 0;
    this.backgroundGroup = new TranslatableGroup({
      name: `${this.id}-background`,
      zIndex: 0
      /* BACKGROUND */
    });
    this.noVisibleData = false;
    this.previousRadiusScale = new LinearScale();
    this.radiusScale = new LinearScale();
    this.phantomGroup = this.backgroundGroup.appendChild(new Group({ name: "phantom" }));
    this.phantomSelection = Selection.select(
      this.phantomGroup,
      () => this.nodeFactory(),
      false
    );
    this.calloutLabelGroup = this.contentGroup.appendChild(new Group({ name: "pieCalloutLabels" }));
    this.calloutLabelSelection = new Selection(
      this.calloutLabelGroup,
      Group
    );
    this.zerosumRingsGroup = this.backgroundGroup.appendChild(new Group({ name: `${this.id}-zerosumRings` }));
    this.zerosumOuterRing = this.zerosumRingsGroup.appendChild(new Circle());
    this.zerosumInnerRing = this.zerosumRingsGroup.appendChild(new Circle());
    this.innerLabelsGroup = this.contentGroup.appendChild(new Group({ name: "innerLabels" }));
    this.innerCircleGroup = this.backgroundGroup.appendChild(new Group({ name: `${this.id}-innerCircle` }));
    this.innerLabelsSelection = Selection.select(this.innerLabelsGroup, Text);
    this.innerCircleSelection = Selection.select(
      this.innerCircleGroup,
      Circle
    );
    this.surroundingRadius = void 0;
    this.NodeEvent = DonutSeriesNodeEvent;
    this.angleScale = new LinearScale();
    this.angleScale.domain = [0, 1];
    this.angleScale.range = [-Math.PI, Math.PI].map((angle2) => angle2 + Math.PI / 2);
    this.phantomGroup.opacity = 0.2;
  }
  get calloutNodeData() {
    return this.phantomNodeData ?? this.nodeData;
  }
  attachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.attachSeries(seriesContentNode, seriesNode, annotationNode);
    seriesContentNode?.appendChild(this.backgroundGroup);
  }
  detachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.detachSeries(seriesContentNode, seriesNode, annotationNode);
    seriesContentNode?.removeChild(this.backgroundGroup);
  }
  setSeriesIndex(index) {
    if (!super.setSeriesIndex(index))
      return false;
    this.backgroundGroup.zIndex = [0, index];
    return true;
  }
  nodeFactory() {
    return new Sector();
  }
  getSeriesDomain(direction) {
    if (direction === "x") {
      return this.angleScale.domain;
    } else {
      return this.radiusScale.domain;
    }
  }
  async processData(dataController) {
    if (this.data == null || !this.properties.isValid()) {
      return;
    }
    const { visible, id: seriesId } = this;
    const { angleKey, angleFilterKey, radiusKey, calloutLabelKey, sectorLabelKey, legendItemKey } = this.properties;
    const validSector = (_value, _datum, index) => {
      return visible && this.ctx.legendManager.getItemEnabled({ seriesId, itemId: index });
    };
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const extraKeyProps = [];
    const extraProps = [];
    if (legendItemKey) {
      extraKeyProps.push(keyProperty(legendItemKey, "band", { id: `legendItemKey` }));
    } else if (calloutLabelKey) {
      extraKeyProps.push(keyProperty(calloutLabelKey, "band", { id: `calloutLabelKey` }));
    } else if (sectorLabelKey) {
      extraKeyProps.push(keyProperty(sectorLabelKey, "band", { id: `sectorLabelKey` }));
    }
    const radiusScaleType = this.radiusScale.type;
    const angleScaleType = this.angleScale.type;
    if (radiusKey) {
      extraProps.push(
        rangedValueProperty(radiusKey, {
          id: "radiusValue",
          min: this.properties.radiusMin ?? 0,
          max: this.properties.radiusMax
        }),
        valueProperty(radiusKey, radiusScaleType, { id: `radiusRaw` }),
        // Raw value pass-through.
        normalisePropertyTo("radiusValue", [0, 1], 1, this.properties.radiusMin ?? 0, this.properties.radiusMax)
      );
    }
    if (calloutLabelKey) {
      extraProps.push(valueProperty(calloutLabelKey, "band", { id: `calloutLabelValue` }));
    }
    if (sectorLabelKey) {
      extraProps.push(valueProperty(sectorLabelKey, "band", { id: `sectorLabelValue` }));
    }
    if (legendItemKey) {
      extraProps.push(valueProperty(legendItemKey, "band", { id: `legendItemValue` }));
    }
    if (angleFilterKey) {
      extraProps.push(
        accumulativeValueProperty(angleFilterKey, angleScaleType, {
          id: `angleFilterValue`,
          onlyPositive: true,
          validation: validSector,
          invalidValue: 0
        }),
        valueProperty(angleFilterKey, angleScaleType, { id: `angleFilterRaw` }),
        normalisePropertyTo("angleFilterValue", [0, 1], 0, 0)
      );
    }
    if (animationEnabled && this.processedData && extraKeyProps.length > 0) {
      extraProps.push(diff(this.id, this.processedData));
    }
    extraProps.push(animationValidation());
    await this.requestDataModel(dataController, this.data, {
      props: [
        ...extraKeyProps,
        accumulativeValueProperty(angleKey, angleScaleType, {
          id: `angleValue`,
          onlyPositive: true,
          validation: validSector,
          invalidValue: 0
        }),
        valueProperty(angleKey, angleScaleType, { id: `angleRaw` }),
        // Raw value pass-through.
        normalisePropertyTo("angleValue", [0, 1], 0, 0),
        ...extraProps
      ]
    });
    for (const valueDef of this.processedData?.defs?.values ?? []) {
      const { id, missing, property } = valueDef;
      const missCount = getMissCount(this, missing);
      if (id !== "angleRaw" && missCount > 0) {
        Logger.warnOnce(
          `no value was found for the key '${String(property)}' on ${missCount} data element${missCount > 1 ? "s" : ""}`
        );
      }
    }
    this.animationState.transition("updateData");
  }
  maybeRefreshNodeData() {
    if (!this.nodeDataRefresh)
      return;
    const { nodeData = [], phantomNodeData } = this.createNodeData() ?? {};
    this.nodeData = nodeData;
    this.phantomNodeData = phantomNodeData;
    this.nodeDataRefresh = false;
  }
  getProcessedDataValues(dataModel, processedData) {
    const angleValues = dataModel.resolveColumnById(this, `angleValue`, processedData);
    const angleRawValues = dataModel.resolveColumnById(this, `angleRaw`, processedData);
    const angleFilterValues = this.properties.angleFilterKey != null ? dataModel.resolveColumnById(this, `angleFilterValue`, processedData) : void 0;
    const angleFilterRawValues = this.properties.angleFilterKey != null ? dataModel.resolveColumnById(this, `angleFilterRaw`, processedData) : void 0;
    const radiusValues = this.properties.radiusKey ? dataModel.resolveColumnById(this, `radiusValue`, processedData) : void 0;
    const radiusRawValues = this.properties.radiusKey ? dataModel.resolveColumnById(this, `radiusRaw`, processedData) : void 0;
    const calloutLabelValues = this.properties.calloutLabelKey ? dataModel.resolveColumnById(this, `calloutLabelValue`, processedData) : void 0;
    const sectorLabelValues = this.properties.sectorLabelKey ? dataModel.resolveColumnById(this, `sectorLabelValue`, processedData) : void 0;
    const legendItemValues = this.properties.legendItemKey ? dataModel.resolveColumnById(this, `legendItemValue`, processedData) : void 0;
    return {
      angleValues,
      angleRawValues,
      angleFilterValues,
      angleFilterRawValues,
      radiusValues,
      radiusRawValues,
      calloutLabelValues,
      sectorLabelValues,
      legendItemValues
    };
  }
  createNodeData() {
    const {
      id: seriesId,
      processedData,
      dataModel,
      angleScale,
      ctx: { legendManager },
      visible
    } = this;
    const { rotation, innerRadiusRatio } = this.properties;
    if (!this.properties.isValid()) {
      this.zerosumOuterRing.visible = true;
      this.zerosumInnerRing.visible = true;
      return { itemId: seriesId, nodeData: [], labelData: [] };
    }
    if (!processedData?.rawData.length || !dataModel || processedData.type !== "ungrouped")
      return;
    const {
      angleValues,
      angleRawValues,
      angleFilterValues,
      angleFilterRawValues,
      radiusValues,
      radiusRawValues,
      calloutLabelValues,
      sectorLabelValues,
      legendItemValues
    } = this.getProcessedDataValues(dataModel, processedData);
    const useFilterAngles = angleFilterRawValues?.some((filterRawValue, index) => {
      return filterRawValue > angleRawValues[index];
    }) ?? false;
    let currentStart = 0;
    let sum2 = 0;
    const nodes = [];
    const phantomNodes = angleFilterRawValues != null ? [] : void 0;
    processedData.rawData.forEach((datum, datumIndex) => {
      const currentValue = useFilterAngles ? angleFilterValues[datumIndex] : angleValues[datumIndex];
      const crossFilterScale = angleFilterRawValues != null && !useFilterAngles ? Math.sqrt(angleFilterRawValues[datumIndex] / angleRawValues[datumIndex]) : 1;
      const startAngle = angleScale.convert(currentStart) + toRadians(rotation);
      currentStart = currentValue;
      sum2 += currentValue;
      const endAngle = angleScale.convert(currentStart) + toRadians(rotation);
      const span = Math.abs(endAngle - startAngle);
      const midAngle = startAngle + span / 2;
      const angleValue = angleRawValues[datumIndex];
      const radiusRaw = radiusValues?.[datumIndex] ?? 1;
      const radius = radiusRaw * crossFilterScale;
      const radiusValue = radiusRawValues?.[datumIndex];
      const legendItemValue = legendItemValues?.[datumIndex];
      const nodeLabels = this.getLabels(
        datum,
        midAngle,
        span,
        true,
        calloutLabelValues?.[datumIndex],
        sectorLabelValues?.[datumIndex],
        legendItemValue
      );
      const sectorFormat = this.getSectorFormat(datum, datumIndex, false);
      const node = {
        itemId: datumIndex,
        series: this,
        datum,
        datumIndex,
        angleValue,
        midAngle,
        midCos: Math.cos(midAngle),
        midSin: Math.sin(midAngle),
        startAngle,
        endAngle,
        radius,
        innerRadius: Math.max(this.radiusScale.convert(0), 0),
        outerRadius: Math.max(this.radiusScale.convert(radius), 0),
        sectorFormat,
        radiusValue,
        legendItemValue,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex }),
        focusable: true,
        ...nodeLabels
      };
      nodes.push(node);
      if (phantomNodes != null) {
        phantomNodes.push({
          ...node,
          radius: 1,
          innerRadius: Math.max(this.radiusScale.convert(0), 0),
          outerRadius: Math.max(this.radiusScale.convert(1), 0),
          focusable: false
        });
      }
    });
    this.zerosumOuterRing.visible = sum2 === 0;
    this.zerosumInnerRing.visible = sum2 === 0 && innerRadiusRatio != null && innerRadiusRatio !== 1 && innerRadiusRatio > 0;
    return {
      itemId: seriesId,
      nodeData: nodes,
      labelData: nodes,
      phantomNodeData: phantomNodes
    };
  }
  getLabels(datum, midAngle, span, skipDisabled, calloutLabelValue, sectorLabelValue, legendItemValue) {
    const { calloutLabel, sectorLabel, legendItemKey } = this.properties;
    const calloutLabelKey = !skipDisabled || calloutLabel.enabled ? this.properties.calloutLabelKey : void 0;
    const sectorLabelKey = !skipDisabled || sectorLabel.enabled ? this.properties.sectorLabelKey : void 0;
    if (!calloutLabelKey && !sectorLabelKey && !legendItemKey) {
      return {};
    }
    const labelFormatterParams = {
      datum,
      angleKey: this.properties.angleKey,
      angleName: this.properties.angleName,
      radiusKey: this.properties.radiusKey,
      radiusName: this.properties.radiusName,
      calloutLabelKey: this.properties.calloutLabelKey,
      calloutLabelName: this.properties.calloutLabelName,
      sectorLabelKey: this.properties.sectorLabelKey,
      sectorLabelName: this.properties.sectorLabelName,
      legendItemKey: this.properties.legendItemKey
    };
    const result = {};
    if (calloutLabelKey && span > toRadians(calloutLabel.minAngle)) {
      result.calloutLabel = {
        ...this.getTextAlignment(midAngle),
        text: this.getLabelText(calloutLabel, {
          ...labelFormatterParams,
          value: calloutLabelValue
        }),
        hidden: false,
        collisionTextAlign: void 0,
        collisionOffsetY: 0,
        box: void 0
      };
    }
    if (sectorLabelKey) {
      result.sectorLabel = {
        text: this.getLabelText(sectorLabel, {
          ...labelFormatterParams,
          value: sectorLabelValue
        })
      };
    }
    if (legendItemKey != null && legendItemValue != null) {
      result.legendItem = { key: legendItemKey, text: legendItemValue };
    }
    return result;
  }
  getTextAlignment(midAngle) {
    const quadrantTextOpts = [
      { textAlign: "center", textBaseline: "bottom" },
      { textAlign: "left", textBaseline: "middle" },
      { textAlign: "center", textBaseline: "hanging" },
      { textAlign: "right", textBaseline: "middle" }
    ];
    const midAngle180 = normalizeAngle180(midAngle);
    const quadrantStart = -0.75 * Math.PI;
    const quadrantOffset = midAngle180 - quadrantStart;
    const quadrant = Math.floor(quadrantOffset / (Math.PI / 2));
    const quadrantIndex = mod(quadrant, quadrantTextOpts.length);
    return quadrantTextOpts[quadrantIndex];
  }
  getSectorFormat(datum, datumIndex, highlighted) {
    const { angleKey, radiusKey, calloutLabelKey, sectorLabelKey, legendItemKey, fills, strokes, itemStyler } = this.properties;
    const defaultStroke = strokes[datumIndex % strokes.length];
    const { fill, fillOpacity, stroke, strokeWidth, strokeOpacity, lineDash, lineDashOffset, cornerRadius } = mergeDefaults(
      highlighted && this.properties.highlightStyle.item,
      {
        fill: fills.length > 0 ? fills[datumIndex % fills.length] : void 0,
        stroke: defaultStroke,
        strokeWidth: this.getStrokeWidth(this.properties.strokeWidth),
        strokeOpacity: this.getOpacity()
      },
      this.properties
    );
    let format;
    if (itemStyler) {
      format = this.cachedDatumCallback(
        createDatumId(this.getDatumIdFromData(datum), highlighted ? "highlight" : "hide"),
        () => itemStyler({
          datum,
          angleKey,
          radiusKey,
          calloutLabelKey,
          sectorLabelKey,
          legendItemKey,
          fill,
          fillOpacity,
          stroke,
          strokeWidth,
          strokeOpacity,
          lineDash,
          lineDashOffset,
          cornerRadius,
          highlighted,
          seriesId: this.id
        })
      );
    }
    return {
      fill: format?.fill ?? fill,
      fillOpacity: format?.fillOpacity ?? fillOpacity,
      stroke: format?.stroke ?? stroke,
      strokeWidth: format?.strokeWidth ?? strokeWidth,
      strokeOpacity: format?.strokeOpacity ?? strokeOpacity,
      lineDash: format?.lineDash ?? lineDash,
      lineDashOffset: format?.lineDashOffset ?? lineDashOffset,
      cornerRadius: format?.cornerRadius ?? cornerRadius
    };
  }
  getInnerRadius() {
    const { radius } = this;
    const { innerRadiusRatio = 1, innerRadiusOffset = 0 } = this.properties;
    const innerRadius = radius * innerRadiusRatio + innerRadiusOffset;
    if (innerRadius === radius || innerRadius < 0) {
      return 0;
    }
    return innerRadius;
  }
  getOuterRadius() {
    const { outerRadiusRatio, outerRadiusOffset } = this.properties;
    return Math.max(this.radius * outerRadiusRatio + outerRadiusOffset, 0);
  }
  updateRadiusScale(resize) {
    const newRange = [this.getInnerRadius(), this.getOuterRadius()];
    this.radiusScale.range = newRange;
    if (resize) {
      this.previousRadiusScale.range = newRange;
    }
    const setRadii = (d) => ({
      ...d,
      innerRadius: Math.max(this.radiusScale.convert(0), 0),
      outerRadius: Math.max(this.radiusScale.convert(d.radius), 0)
    });
    this.nodeData = this.nodeData.map(setRadii);
    this.phantomNodeData = this.phantomNodeData?.map(setRadii);
  }
  getTitleTranslationY() {
    const outerRadius = Math.max(0, this.radiusScale.range[1]);
    if (outerRadius === 0) {
      return NaN;
    }
    const spacing = this.properties.title?.spacing ?? 0;
    const titleOffset = 2 + spacing;
    const dy = Math.max(0, -outerRadius);
    return -outerRadius - titleOffset - dy;
  }
  update({ seriesRect }) {
    const { title } = this.properties;
    const newNodeDataDependencies = {
      seriesRectWidth: seriesRect?.width,
      seriesRectHeight: seriesRect?.height
    };
    const resize = jsonDiff(this.nodeDataDependencies, newNodeDataDependencies) != null;
    if (resize) {
      this._nodeDataDependencies = newNodeDataDependencies;
    }
    this.maybeRefreshNodeData();
    this.updateTitleNodes();
    this.updateRadiusScale(resize);
    this.contentGroup.translationX = this.centerX;
    this.contentGroup.translationY = this.centerY;
    this.highlightGroup.translationX = this.centerX;
    this.highlightGroup.translationY = this.centerY;
    this.backgroundGroup.translationX = this.centerX;
    this.backgroundGroup.translationY = this.centerY;
    if (this.labelGroup) {
      this.labelGroup.translationX = this.centerX;
      this.labelGroup.translationY = this.centerY;
    }
    if (title) {
      const dy = this.getTitleTranslationY();
      title.node.y = isFinite(dy) ? dy : 0;
      const titleBox = title.node.getBBox();
      title.node.visible = title.enabled && isFinite(dy) && !this.bboxIntersectsSurroundingSeries(titleBox);
    }
    for (const circle of [this.zerosumInnerRing, this.zerosumOuterRing]) {
      circle.fillOpacity = 0;
      circle.stroke = this.properties.calloutLabel.color;
      circle.strokeWidth = 1;
      circle.strokeOpacity = 1;
    }
    this.updateNodeMidPoint();
    this.updateSelections();
    this.updateNodes(seriesRect);
  }
  updateTitleNodes() {
    const { oldTitle } = this;
    const { title } = this.properties;
    if (oldTitle !== title) {
      if (oldTitle) {
        this.labelGroup?.removeChild(oldTitle.node);
      }
      if (title) {
        title.node.textBaseline = "bottom";
        this.labelGroup?.appendChild(title.node);
      }
      this.oldTitle = title;
    }
  }
  updateNodeMidPoint() {
    const setMidPoint = (d) => {
      const radius = d.innerRadius + (d.outerRadius - d.innerRadius) / 2;
      d.midPoint = {
        x: d.midCos * Math.max(0, radius),
        y: d.midSin * Math.max(0, radius)
      };
    };
    this.nodeData.forEach(setMidPoint);
    this.phantomNodeData?.forEach(setMidPoint);
  }
  updateSelections() {
    this.updateGroupSelection();
    this.updateInnerCircleSelection();
  }
  updateGroupSelection() {
    const {
      itemSelection,
      highlightSelection,
      phantomSelection,
      highlightLabelSelection,
      calloutLabelSelection,
      labelSelection,
      innerLabelsSelection
    } = this;
    const highlightedNodeData = this.nodeData.map((datum) => ({
      ...datum,
      // Allow mutable sectorFormat, so formatted sector styles can be updated and varied
      // between normal and highlighted cases.
      sectorFormat: { ...datum.sectorFormat }
    }));
    const update = (selection, nodeData) => {
      selection.update(nodeData, void 0, (datum) => this.getDatumId(datum));
      if (this.ctx.animationManager.isSkipped()) {
        selection.cleanup();
      }
    };
    update(itemSelection, this.nodeData);
    update(highlightSelection, highlightedNodeData);
    update(phantomSelection, this.phantomNodeData ?? []);
    calloutLabelSelection.update(this.calloutNodeData, (group) => {
      const line = new Line();
      line.tag = 0;
      line.pointerEvents = 1;
      group.appendChild(line);
      const text = new Text();
      text.tag = 1;
      text.pointerEvents = 1;
      group.appendChild(text);
    });
    labelSelection.update(this.nodeData);
    highlightLabelSelection.update(highlightedNodeData);
    innerLabelsSelection.update(this.properties.innerLabels, (node) => {
      node.pointerEvents = 1;
    });
  }
  updateInnerCircleSelection() {
    const { innerCircle } = this.properties;
    let radius = 0;
    const innerRadius = this.getInnerRadius();
    if (innerRadius > 0) {
      const circleRadius = Math.min(innerRadius, this.getOuterRadius());
      const antiAliasingPadding = 1;
      radius = Math.ceil(circleRadius * 2 + antiAliasingPadding);
    }
    const datums = innerCircle ? [{ radius }] : [];
    this.innerCircleSelection.update(datums);
  }
  updateNodes(seriesRect) {
    const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
    const { visible } = this;
    this.backgroundGroup.visible = visible;
    this.contentGroup.visible = visible;
    this.highlightGroup.visible = visible && highlightedDatum?.series === this;
    this.highlightLabel.visible = visible && highlightedDatum?.series === this;
    this.labelGroup.visible = visible;
    this.contentGroup.opacity = this.getOpacity();
    this.innerCircleSelection.each((node, { radius }) => {
      node.setProperties({
        fill: this.properties.innerCircle?.fill,
        opacity: this.properties.innerCircle?.fillOpacity,
        size: radius
      });
    });
    const animationDisabled = this.ctx.animationManager.isSkipped();
    const updateSectorFn = (sector, datum, _index, isDatumHighlighted) => {
      const format = this.getSectorFormat(datum.datum, datum.itemId, isDatumHighlighted);
      datum.sectorFormat.fill = format.fill;
      datum.sectorFormat.stroke = format.stroke;
      if (animationDisabled) {
        sector.startAngle = datum.startAngle;
        sector.endAngle = datum.endAngle;
        sector.innerRadius = datum.innerRadius;
        sector.outerRadius = datum.outerRadius;
      }
      if (isDatumHighlighted || animationDisabled) {
        sector.fill = format.fill;
        sector.stroke = format.stroke;
      }
      sector.strokeWidth = format.strokeWidth;
      sector.fillOpacity = format.fillOpacity;
      sector.strokeOpacity = format.strokeOpacity;
      sector.lineDash = format.lineDash;
      sector.lineDashOffset = format.lineDashOffset;
      sector.cornerRadius = format.cornerRadius;
      sector.fillShadow = this.properties.shadow;
      const inset = Math.max(
        (this.properties.sectorSpacing + (format.stroke != null ? format.strokeWidth : 0)) / 2,
        0
      );
      sector.inset = inset;
      sector.lineJoin = this.properties.sectorSpacing >= 0 || inset > 0 ? "miter" : "round";
    };
    this.itemSelection.each((node, datum, index) => updateSectorFn(node, datum, index, false));
    this.highlightSelection.each((node, datum, index) => {
      updateSectorFn(node, datum, index, true);
      node.visible = datum.itemId === highlightedDatum?.itemId;
    });
    this.phantomSelection.each((node, datum, index) => updateSectorFn(node, datum, index, false));
    this.updateCalloutLineNodes();
    this.updateCalloutLabelNodes(seriesRect);
    this.updateSectorLabelNodes();
    this.updateInnerLabelNodes();
    this.updateZerosumRings();
    this.animationState.transition("update");
  }
  updateCalloutLineNodes() {
    const { calloutLine } = this.properties;
    const calloutLength = calloutLine.length;
    const calloutStrokeWidth = calloutLine.strokeWidth;
    const calloutColors = calloutLine.colors ?? this.properties.strokes;
    const { offset: offset4 } = this.properties.calloutLabel;
    this.calloutLabelSelection.selectByTag(
      0
      /* Callout */
    ).forEach((line, index) => {
      const datum = line.datum;
      const { calloutLabel: label, outerRadius } = datum;
      if (label?.text && !label.hidden && outerRadius !== 0) {
        line.visible = true;
        line.strokeWidth = calloutStrokeWidth;
        line.stroke = calloutColors[index % calloutColors.length];
        line.fill = void 0;
        const x1 = datum.midCos * outerRadius;
        const y1 = datum.midSin * outerRadius;
        let x2 = datum.midCos * (outerRadius + calloutLength);
        let y2 = datum.midSin * (outerRadius + calloutLength);
        const isMoved = label.collisionTextAlign ?? label.collisionOffsetY !== 0;
        if (isMoved && label.box != null) {
          const box = label.box;
          let cx = x2;
          let cy = y2;
          if (x2 < box.x) {
            cx = box.x;
          } else if (x2 > box.x + box.width) {
            cx = box.x + box.width;
          }
          if (y2 < box.y) {
            cy = box.y;
          } else if (y2 > box.y + box.height) {
            cy = box.y + box.height;
          }
          const dx = cx - x2;
          const dy = cy - y2;
          const length2 = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
          const paddedLength = length2 - offset4;
          if (paddedLength > 0) {
            x2 = x2 + dx * paddedLength / length2;
            y2 = y2 + dy * paddedLength / length2;
          }
        }
        line.x1 = x1;
        line.y1 = y1;
        line.x2 = x2;
        line.y2 = y2;
      } else {
        line.visible = false;
      }
    });
  }
  getLabelOverflow(text, box, seriesRect) {
    const seriesLeft = -this.centerX;
    const seriesRight = seriesLeft + seriesRect.width;
    const seriesTop = -this.centerY;
    const seriesBottom = seriesTop + seriesRect.height;
    const errPx = 1;
    let visibleTextPart = 1;
    if (box.x + errPx < seriesLeft) {
      visibleTextPart = (box.x + box.width - seriesLeft) / box.width;
    } else if (box.x + box.width - errPx > seriesRight) {
      visibleTextPart = (seriesRight - box.x) / box.width;
    }
    const hasVerticalOverflow = box.y + errPx < seriesTop || box.y + box.height - errPx > seriesBottom;
    const textLength = visibleTextPart === 1 ? text.length : Math.floor(text.length * visibleTextPart) - 1;
    const hasSurroundingSeriesOverflow = this.bboxIntersectsSurroundingSeries(box);
    return { textLength, hasVerticalOverflow, hasSurroundingSeriesOverflow };
  }
  bboxIntersectsSurroundingSeries(box) {
    const { surroundingRadius } = this;
    if (surroundingRadius == null) {
      return false;
    }
    const corners = [
      { x: box.x, y: box.y },
      { x: box.x + box.width, y: box.y },
      { x: box.x + box.width, y: box.y + box.height },
      { x: box.x, y: box.y + box.height }
    ];
    const sur2 = surroundingRadius ** 2;
    return corners.some((corner) => corner.x ** 2 + corner.y ** 2 > sur2);
  }
  computeCalloutLabelCollisionOffsets() {
    const { radiusScale } = this;
    const { calloutLabel, calloutLine } = this.properties;
    const { offset: offset4, minSpacing } = calloutLabel;
    const innerRadius = radiusScale.convert(0);
    const shouldSkip = (datum) => {
      const label = datum.calloutLabel;
      return !label || datum.outerRadius === 0;
    };
    const fullData = this.calloutNodeData;
    const data = fullData.filter((t) => !shouldSkip(t));
    data.forEach((datum) => {
      const label = datum.calloutLabel;
      if (label == null)
        return;
      label.hidden = false;
      label.collisionTextAlign = void 0;
      label.collisionOffsetY = 0;
    });
    if (data.length <= 1) {
      return;
    }
    const leftLabels = data.filter((d) => d.midCos < 0).sort((a, b) => a.midSin - b.midSin);
    const rightLabels = data.filter((d) => d.midCos >= 0).sort((a, b) => a.midSin - b.midSin);
    const topLabels = data.filter((d) => d.midSin < 0 && d.calloutLabel?.textAlign === "center").sort((a, b) => a.midCos - b.midCos);
    const bottomLabels = data.filter((d) => d.midSin >= 0 && d.calloutLabel?.textAlign === "center").sort((a, b) => a.midCos - b.midCos);
    const getTextBBox = (datum) => {
      const label = datum.calloutLabel;
      if (label == null)
        return BBox.zero.clone();
      const labelRadius = datum.outerRadius + calloutLine.length + offset4;
      const x = datum.midCos * labelRadius;
      const y = datum.midSin * labelRadius + label.collisionOffsetY;
      const textAlign = label.collisionTextAlign ?? label.textAlign;
      const textBaseline = label.textBaseline;
      return Text.computeBBox(label.text, x, y, {
        font: this.properties.calloutLabel,
        textAlign,
        textBaseline
      });
    };
    const avoidNeighbourYCollision = (label, next, direction) => {
      const box = getTextBBox(label).grow(minSpacing / 2);
      const other = getTextBBox(next).grow(minSpacing / 2);
      const collidesOrBehind = box.x < other.x + other.width && box.x + box.width > other.x && (direction === "to-top" ? box.y < other.y + other.height : box.y + box.height > other.y);
      if (collidesOrBehind) {
        const dy = direction === "to-top" ? box.y - other.y - other.height : box.y + box.height - other.y;
        next.calloutLabel.collisionOffsetY = dy;
      }
    };
    const avoidYCollisions = (labels) => {
      const midLabel = labels.slice().sort((a, b) => Math.abs(a.midSin) - Math.abs(b.midSin))[0];
      const midIndex = labels.indexOf(midLabel);
      for (let i = midIndex - 1; i >= 0; i--) {
        const prev = labels[i + 1];
        const next = labels[i];
        avoidNeighbourYCollision(prev, next, "to-top");
      }
      for (let i = midIndex + 1; i < labels.length; i++) {
        const prev = labels[i - 1];
        const next = labels[i];
        avoidNeighbourYCollision(prev, next, "to-bottom");
      }
    };
    const avoidXCollisions = (labels) => {
      const labelsCollideLabelsByY = data.some((datum) => datum.calloutLabel.collisionOffsetY !== 0);
      const boxes = labels.map((label) => getTextBBox(label));
      const paddedBoxes = boxes.map((box) => box.clone().grow(minSpacing / 2));
      let labelsCollideLabelsByX = false;
      for (let i = 0; i < paddedBoxes.length && !labelsCollideLabelsByX; i++) {
        const box = paddedBoxes[i];
        for (let j = i + 1; j < labels.length; j++) {
          const other = paddedBoxes[j];
          if (box.collidesBBox(other)) {
            labelsCollideLabelsByX = true;
            break;
          }
        }
      }
      const sectors = fullData.map((datum) => {
        const { startAngle, endAngle, outerRadius } = datum;
        return { startAngle, endAngle, innerRadius, outerRadius };
      });
      const labelsCollideSectors = boxes.some((box) => {
        return sectors.some((sector) => boxCollidesSector(box, sector));
      });
      if (!labelsCollideLabelsByX && !labelsCollideLabelsByY && !labelsCollideSectors) {
        return;
      }
      labels.filter((d) => d.calloutLabel.textAlign === "center").forEach((d) => {
        const label = d.calloutLabel;
        if (d.midCos < 0) {
          label.collisionTextAlign = "right";
        } else if (d.midCos > 0) {
          label.collisionTextAlign = "left";
        } else {
          label.collisionTextAlign = "center";
        }
      });
    };
    avoidYCollisions(leftLabels);
    avoidYCollisions(rightLabels);
    avoidXCollisions(topLabels);
    avoidXCollisions(bottomLabels);
  }
  updateCalloutLabelNodes(seriesRect) {
    const { radiusScale } = this;
    const { calloutLabel, calloutLine } = this.properties;
    const calloutLength = calloutLine.length;
    const { offset: offset4, color } = calloutLabel;
    const tempTextNode = new Text();
    this.calloutLabelSelection.selectByTag(
      1
      /* Label */
    ).forEach((text) => {
      const { datum } = text;
      const label = datum.calloutLabel;
      const radius = radiusScale.convert(datum.radius);
      const outerRadius = Math.max(0, radius);
      if (!label?.text || outerRadius === 0 || label.hidden) {
        text.visible = false;
        return;
      }
      const labelRadius = outerRadius + calloutLength + offset4;
      const x = datum.midCos * labelRadius;
      const y = datum.midSin * labelRadius + label.collisionOffsetY;
      const align = {
        textAlign: label.collisionTextAlign ?? label.textAlign,
        textBaseline: label.textBaseline
      };
      tempTextNode.text = label.text;
      tempTextNode.x = x;
      tempTextNode.y = y;
      tempTextNode.setFont(this.properties.calloutLabel);
      tempTextNode.setAlign(align);
      const box = tempTextNode.getBBox();
      let displayText = label.text;
      let visible = true;
      if (calloutLabel.avoidCollisions) {
        const { textLength, hasVerticalOverflow } = this.getLabelOverflow(label.text, box, seriesRect);
        displayText = label.text.length === textLength ? label.text : `${label.text.substring(0, textLength)}\u2026`;
        visible = !hasVerticalOverflow;
      }
      text.text = displayText;
      text.x = x;
      text.y = y;
      text.setFont(this.properties.calloutLabel);
      text.setAlign(align);
      text.fill = color;
      text.visible = visible;
    });
  }
  computeLabelsBBox(options, seriesRect) {
    const { calloutLabel, calloutLine } = this.properties;
    const calloutLength = calloutLine.length;
    const { offset: offset4, maxCollisionOffset, minSpacing } = calloutLabel;
    if (!calloutLabel.avoidCollisions) {
      return null;
    }
    this.maybeRefreshNodeData();
    this.updateRadiusScale(false);
    this.computeCalloutLabelCollisionOffsets();
    const textBoxes = [];
    const text = new Text();
    let titleBox;
    const { title } = this.properties;
    if (title?.text && title.enabled) {
      const dy = this.getTitleTranslationY();
      if (isFinite(dy)) {
        text.text = title.text;
        text.x = 0;
        text.y = dy;
        text.setFont(title);
        text.setAlign({
          textBaseline: "bottom",
          textAlign: "center"
        });
        titleBox = text.getBBox();
        textBoxes.push(titleBox);
      }
    }
    this.calloutNodeData.forEach((datum) => {
      const label = datum.calloutLabel;
      if (!label || datum.outerRadius === 0) {
        return null;
      }
      const labelRadius = datum.outerRadius + calloutLength + offset4;
      const x = datum.midCos * labelRadius;
      const y = datum.midSin * labelRadius + label.collisionOffsetY;
      text.text = label.text;
      text.x = x;
      text.y = y;
      text.setFont(this.properties.calloutLabel);
      text.setAlign({
        textAlign: label.collisionTextAlign ?? label.textAlign,
        textBaseline: label.textBaseline
      });
      const box = text.getBBox();
      label.box = box;
      if (Math.abs(label.collisionOffsetY) > maxCollisionOffset) {
        label.hidden = true;
        return;
      }
      if (titleBox) {
        const seriesTop = -this.centerY;
        const titleCleanArea = new BBox(
          titleBox.x - minSpacing,
          seriesTop,
          titleBox.width + 2 * minSpacing,
          titleBox.y + titleBox.height + minSpacing - seriesTop
        );
        if (box.collidesBBox(titleCleanArea)) {
          label.hidden = true;
          return;
        }
      }
      if (options.hideWhenNecessary) {
        const { textLength, hasVerticalOverflow, hasSurroundingSeriesOverflow } = this.getLabelOverflow(
          label.text,
          box,
          seriesRect
        );
        const isTooShort = label.text.length > 2 && textLength < 2;
        if (hasVerticalOverflow || isTooShort || hasSurroundingSeriesOverflow) {
          label.hidden = true;
          return;
        }
      }
      label.hidden = false;
      textBoxes.push(box);
    });
    if (textBoxes.length === 0) {
      return null;
    }
    return BBox.merge(textBoxes);
  }
  updateSectorLabelNodes() {
    const { radiusScale } = this;
    const innerRadius = radiusScale.convert(0);
    const { fontSize, fontStyle, fontWeight, fontFamily, positionOffset, positionRatio, color } = this.properties.sectorLabel;
    const updateSectorLabel = (text, datum) => {
      const { sectorLabel, outerRadius } = datum;
      let isTextVisible = false;
      if (sectorLabel && outerRadius !== 0) {
        const labelRadius = innerRadius * (1 - positionRatio) + outerRadius * positionRatio + positionOffset;
        text.fill = color;
        text.fontStyle = fontStyle;
        text.fontWeight = fontWeight;
        text.fontSize = fontSize;
        text.fontFamily = fontFamily;
        text.text = sectorLabel.text;
        text.x = datum.midCos * labelRadius;
        text.y = datum.midSin * labelRadius;
        text.textAlign = "center";
        text.textBaseline = "middle";
        const bbox = text.getBBox();
        const corners = [
          [bbox.x, bbox.y],
          [bbox.x + bbox.width, bbox.y],
          [bbox.x + bbox.width, bbox.y + bbox.height],
          [bbox.x, bbox.y + bbox.height]
        ];
        const { startAngle, endAngle } = datum;
        const sectorBounds = { startAngle, endAngle, innerRadius, outerRadius };
        if (corners.every(([x, y]) => isPointInSector(x, y, sectorBounds))) {
          isTextVisible = true;
        }
      }
      text.visible = isTextVisible;
    };
    this.labelSelection.each(updateSectorLabel);
    this.highlightLabelSelection.each(updateSectorLabel);
  }
  updateInnerLabelNodes() {
    const textBBoxes = [];
    const margins = [];
    this.innerLabelsSelection.each((text, datum) => {
      const { fontStyle, fontWeight, fontSize, fontFamily, color } = datum;
      text.fontStyle = fontStyle;
      text.fontWeight = fontWeight;
      text.fontSize = fontSize;
      text.fontFamily = fontFamily;
      text.text = datum.text;
      text.x = 0;
      text.y = 0;
      text.fill = color;
      text.textAlign = "center";
      text.textBaseline = "alphabetic";
      textBBoxes.push(text.getBBox());
      margins.push(datum.spacing);
    });
    const getMarginTop = (index) => index === 0 ? 0 : margins[index];
    const getMarginBottom = (index) => index === margins.length - 1 ? 0 : margins[index];
    const totalHeight = textBBoxes.reduce((sum2, bbox, i) => {
      return sum2 + bbox.height + getMarginTop(i) + getMarginBottom(i);
    }, 0);
    const totalWidth = Math.max(...textBBoxes.map((bbox) => bbox.width));
    const innerRadius = this.getInnerRadius();
    const labelRadius = Math.sqrt(Math.pow(totalWidth / 2, 2) + Math.pow(totalHeight / 2, 2));
    const labelsVisible = labelRadius <= (innerRadius > 0 ? innerRadius : this.getOuterRadius());
    const textBottoms = [];
    for (let i = 0, prev = -totalHeight / 2; i < textBBoxes.length; i++) {
      const bbox = textBBoxes[i];
      const bottom = bbox.height + prev + getMarginTop(i);
      textBottoms.push(bottom);
      prev = bottom + getMarginBottom(i);
    }
    this.innerLabelsSelection.each((text, _datum, index) => {
      text.y = textBottoms[index];
      text.visible = labelsVisible;
    });
  }
  updateZerosumRings() {
    this.zerosumOuterRing.size = this.getOuterRadius() * 2;
    this.zerosumInnerRing.size = this.getInnerRadius() * 2;
  }
  pickNodeClosestDatum(point) {
    return pickByMatchingAngle(this, point);
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, properties } = this;
    const {
      legendItemKey,
      calloutLabelKey,
      calloutLabelName,
      sectorLabelKey,
      sectorLabelName,
      angleKey,
      angleName,
      radiusKey,
      radiusName,
      tooltip
    } = properties;
    const title = this.properties.title.text;
    if (!dataModel || !processedData || processedData.rawData.length === 0)
      return;
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const { angleRawValues, legendItemValues, calloutLabelValues, sectorLabelValues } = this.getProcessedDataValues(
      dataModel,
      processedData
    );
    const angleRawValue = angleRawValues[datumIndex];
    const label = legendItemValues?.[datumIndex] ?? (calloutLabelKey === angleKey ? void 0 : calloutLabelValues?.[datumIndex]) ?? (sectorLabelKey === angleKey ? void 0 : sectorLabelValues?.[datumIndex]) ?? angleName;
    return tooltip.formatTooltip(
      {
        title,
        symbol: this.legendItemSymbol(datumIndex),
        data: [
          {
            label,
            fallbackLabel: angleKey,
            value: String(angleRawValue)
          }
        ]
      },
      {
        seriesId,
        datum,
        title: angleName,
        legendItemKey,
        calloutLabelKey,
        calloutLabelName,
        sectorLabelKey,
        sectorLabelName,
        angleKey,
        angleName,
        radiusKey,
        radiusName,
        ...this.getSectorFormat(datum, datumIndex, false)
      }
    );
  }
  legendItemSymbol(datumIndex) {
    const datum = this.processedData?.rawData[datumIndex];
    const sectorFormat = this.getSectorFormat(datum, datumIndex, false);
    return {
      marker: {
        fill: sectorFormat.fill,
        stroke: sectorFormat.stroke,
        fillOpacity: this.properties.fillOpacity,
        strokeOpacity: this.properties.strokeOpacity,
        strokeWidth: this.properties.strokeWidth
      }
    };
  }
  getLegendData(legendType) {
    const {
      visible,
      processedData,
      dataModel,
      id: seriesId,
      ctx: { legendManager }
    } = this;
    if (!dataModel || !processedData || !this.properties.isValid() || legendType !== "category") {
      return [];
    }
    const { angleKey, calloutLabelKey, sectorLabelKey, legendItemKey, showInLegend } = this.properties;
    if (!legendItemKey && (!calloutLabelKey || calloutLabelKey === angleKey) && (!sectorLabelKey || sectorLabelKey === angleKey))
      return [];
    const { angleRawValues, calloutLabelValues, sectorLabelValues, legendItemValues } = this.getProcessedDataValues(
      dataModel,
      processedData
    );
    const titleText = this.properties.title?.showInLegend && this.properties.title.text;
    const legendData = [];
    const hideZeros = this.properties.hideZeroValueSectorsInLegend;
    for (let datumIndex = 0; datumIndex < processedData.rawData.length; datumIndex++) {
      const datum = processedData.rawData[datumIndex];
      const angleRawValue = angleRawValues[datumIndex];
      if (hideZeros && angleRawValue === 0) {
        continue;
      }
      const labelParts = [];
      if (titleText) {
        labelParts.push(titleText);
      }
      const labels = this.getLabels(
        datum,
        2 * Math.PI,
        2 * Math.PI,
        false,
        calloutLabelValues?.[datumIndex],
        sectorLabelValues?.[datumIndex],
        legendItemValues?.[datumIndex]
      );
      if (legendItemKey && labels.legendItem !== void 0) {
        labelParts.push(labels.legendItem.text);
      } else if (calloutLabelKey && calloutLabelKey !== angleKey && labels.calloutLabel?.text !== void 0) {
        labelParts.push(labels.calloutLabel?.text);
      } else if (sectorLabelKey && sectorLabelKey !== angleKey && labels.sectorLabel?.text !== void 0) {
        labelParts.push(labels.sectorLabel?.text);
      }
      if (labelParts.length === 0)
        continue;
      legendData.push({
        legendType: "category",
        id: seriesId,
        datum,
        itemId: datumIndex,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex }),
        label: {
          text: labelParts.join(" - ")
        },
        symbol: this.legendItemSymbol(datumIndex),
        legendItemName: legendItemKey != null ? datum[legendItemKey] : void 0,
        hideInLegend: !showInLegend
      });
    }
    return legendData;
  }
  // Used for grid
  setLegendState(enabledItems) {
    const {
      id: seriesId,
      ctx: { legendManager, updateService }
    } = this;
    enabledItems.forEach((enabled, itemId) => legendManager.toggleItem({ enabled, seriesId, itemId }));
    legendManager.update();
    updateService.update(
      4
      /* SERIES_UPDATE */
    );
  }
  animateEmptyUpdateReady(_data) {
    const { animationManager } = this.ctx;
    const fns = preparePieSeriesAnimationFunctions(
      true,
      this.properties.rotation,
      this.radiusScale,
      this.previousRadiusScale
    );
    fromToMotion(
      this.id,
      "nodes",
      animationManager,
      [this.itemSelection, this.highlightSelection, this.phantomSelection],
      fns.nodes,
      (_, datum) => this.getDatumId(datum)
    );
    fromToMotion(this.id, `innerCircle`, animationManager, [this.innerCircleSelection], fns.innerCircle);
    seriesLabelFadeInAnimation(this, "callout", animationManager, this.calloutLabelSelection);
    seriesLabelFadeInAnimation(this, "sector", animationManager, this.labelSelection);
    seriesLabelFadeInAnimation(this, "highlight", animationManager, this.highlightLabelSelection);
    seriesLabelFadeInAnimation(this, "inner", animationManager, this.innerLabelsSelection);
    this.previousRadiusScale.range = this.radiusScale.range;
  }
  animateWaitingUpdateReady() {
    const { itemSelection, highlightSelection, phantomSelection, processedData, radiusScale, previousRadiusScale } = this;
    const { animationManager } = this.ctx;
    const dataDiff = processedData?.reduced?.diff?.[this.id];
    this.ctx.animationManager.stopByAnimationGroupId(this.id);
    const supportedDiff = (dataDiff?.moved.size ?? 0) === 0;
    const hasKeys = (processedData?.defs.keys.length ?? 0) > 0;
    const hasUniqueKeys = processedData?.reduced?.animationValidation?.uniqueKeys ?? true;
    if (!supportedDiff || !hasKeys || !hasUniqueKeys) {
      this.ctx.animationManager.skipCurrentBatch();
    }
    const noVisibleData = !this.nodeData.some((n) => n.enabled);
    const fns = preparePieSeriesAnimationFunctions(
      false,
      this.properties.rotation,
      radiusScale,
      previousRadiusScale
    );
    fromToMotion(
      this.id,
      "nodes",
      animationManager,
      [itemSelection, highlightSelection, phantomSelection],
      fns.nodes,
      (_, datum) => this.getDatumId(datum),
      dataDiff
    );
    fromToMotion(this.id, `innerCircle`, animationManager, [this.innerCircleSelection], fns.innerCircle);
    seriesLabelFadeInAnimation(this, "callout", this.ctx.animationManager, this.calloutLabelSelection);
    seriesLabelFadeInAnimation(this, "sector", this.ctx.animationManager, this.labelSelection);
    seriesLabelFadeInAnimation(this, "highlight", this.ctx.animationManager, this.highlightLabelSelection);
    if (this.noVisibleData !== noVisibleData) {
      this.noVisibleData = noVisibleData;
      seriesLabelFadeInAnimation(this, "inner", this.ctx.animationManager, this.innerLabelsSelection);
    }
    this.previousRadiusScale.range = this.radiusScale.range;
  }
  animateClearingUpdateEmpty() {
    const { itemSelection, highlightSelection, phantomSelection, radiusScale, previousRadiusScale } = this;
    const { animationManager } = this.ctx;
    const fns = preparePieSeriesAnimationFunctions(
      false,
      this.properties.rotation,
      radiusScale,
      previousRadiusScale
    );
    fromToMotion(
      this.id,
      "nodes",
      animationManager,
      [itemSelection, highlightSelection, phantomSelection],
      fns.nodes,
      (_, datum) => this.getDatumId(datum)
    );
    fromToMotion(this.id, `innerCircle`, animationManager, [this.innerCircleSelection], fns.innerCircle);
    seriesLabelFadeOutAnimation(this, "callout", this.ctx.animationManager, this.calloutLabelSelection);
    seriesLabelFadeOutAnimation(this, "sector", this.ctx.animationManager, this.labelSelection);
    seriesLabelFadeOutAnimation(this, "highlight", this.ctx.animationManager, this.highlightLabelSelection);
    seriesLabelFadeOutAnimation(this, "inner", this.ctx.animationManager, this.innerLabelsSelection);
    this.previousRadiusScale.range = this.radiusScale.range;
  }
  getDatumIdFromData(datum) {
    const { calloutLabelKey, sectorLabelKey, legendItemKey } = this.properties;
    if (!this.processedData?.reduced?.animationValidation?.uniqueKeys) {
      return;
    }
    if (legendItemKey) {
      return datum[legendItemKey];
    } else if (calloutLabelKey) {
      return datum[calloutLabelKey];
    } else if (sectorLabelKey) {
      return datum[sectorLabelKey];
    }
  }
  getDatumId(datum) {
    const { datumIndex } = datum;
    const datumId = this.getDatumIdFromData(datum.datum);
    return String(datumId ?? datumIndex);
  }
};
DonutSeries.className = "DonutSeries";
DonutSeries.type = "donut";
var donutTheme = {
  series: {
    title: {
      enabled: true,
      fontWeight: "normal",
      fontSize: 14,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_MUTED_LABEL_COLOUR,
      spacing: 5
    },
    calloutLabel: {
      enabled: true,
      fontSize: 12,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_LABEL_COLOUR,
      offset: 3,
      minAngle: 0
    },
    sectorLabel: {
      enabled: true,
      fontWeight: "normal",
      fontSize: 12,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_INSIDE_SERIES_LABEL_COLOUR,
      positionOffset: 0,
      positionRatio: 0.5
    },
    calloutLine: {
      length: 10,
      strokeWidth: 2
    },
    fillOpacity: 1,
    strokeOpacity: 1,
    strokeWidth: 0,
    lineDash: [0],
    lineDashOffset: 0,
    rotation: 0,
    sectorSpacing: 1,
    shadow: {
      enabled: false,
      color: DEFAULT_SHADOW_COLOUR,
      xOffset: 3,
      yOffset: 3,
      blur: 5
    },
    innerLabels: {
      fontSize: 12,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_LABEL_COLOUR,
      spacing: 2
    }
  }
};
var pieTheme = {
  series: {
    title: {
      enabled: true,
      fontWeight: "normal",
      fontSize: 14,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_MUTED_LABEL_COLOUR,
      spacing: 5
    },
    calloutLabel: {
      enabled: true,
      fontSize: 12,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_LABEL_COLOUR,
      offset: 3,
      minAngle: 0
    },
    sectorLabel: {
      enabled: true,
      fontWeight: "normal",
      fontSize: 12,
      fontFamily: DEFAULT_FONT_FAMILY,
      color: DEFAULT_INSIDE_SERIES_LABEL_COLOUR,
      positionOffset: 0,
      positionRatio: 0.5
    },
    calloutLine: {
      length: 10,
      strokeWidth: 2
    },
    fillOpacity: 1,
    strokeOpacity: 1,
    strokeWidth: 0,
    lineDash: [0],
    lineDashOffset: 0,
    rotation: 0,
    sectorSpacing: 1,
    shadow: {
      enabled: false,
      color: DEFAULT_SHADOW_COLOUR,
      xOffset: 3,
      yOffset: 3,
      blur: 5
    }
  }
};
var piePaletteFactory = ({ takeColors, colorsCount }) => {
  const { fills, strokes } = takeColors(colorsCount);
  return { fills, strokes, calloutLine: { colors: strokes } };
};
var DonutSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["polar"],
  identifier: "donut",
  moduleFactory: (ctx) => new DonutSeries(ctx),
  tooltipDefaults: { range: "exact" },
  themeTemplate: donutTheme,
  paletteFactory: piePaletteFactory
};
var PieTitle = class extends Caption {
  constructor() {
    super(...arguments);
    this.showInLegend = false;
  }
};
__decorateClass([
  Validate(BOOLEAN)
], PieTitle.prototype, "showInLegend", 2);
var PieSeriesCalloutLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.offset = 3;
    this.minAngle = 0;
    this.minSpacing = 4;
    this.maxCollisionOffset = 50;
    this.avoidCollisions = true;
  }
};
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesCalloutLabel.prototype, "offset", 2);
__decorateClass([
  Validate(NUMBER.restrict({ min: 0, max: 360 }))
], PieSeriesCalloutLabel.prototype, "minAngle", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesCalloutLabel.prototype, "minSpacing", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesCalloutLabel.prototype, "maxCollisionOffset", 2);
__decorateClass([
  Validate(BOOLEAN)
], PieSeriesCalloutLabel.prototype, "avoidCollisions", 2);
var PieSeriesSectorLabel = class extends Label {
  constructor() {
    super(...arguments);
    this.positionOffset = 0;
    this.positionRatio = 0.5;
  }
};
__decorateClass([
  Validate(NUMBER)
], PieSeriesSectorLabel.prototype, "positionOffset", 2);
__decorateClass([
  Validate(RATIO)
], PieSeriesSectorLabel.prototype, "positionRatio", 2);
var PieSeriesCalloutLine = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.length = 10;
    this.strokeWidth = 1;
  }
};
__decorateClass([
  Validate(COLOR_STRING_ARRAY, { optional: true })
], PieSeriesCalloutLine.prototype, "colors", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesCalloutLine.prototype, "length", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesCalloutLine.prototype, "strokeWidth", 2);
var PieSeriesProperties = class extends SeriesProperties {
  constructor() {
    super(...arguments);
    this.fills = Object.values(DEFAULT_FILLS);
    this.strokes = Object.values(DEFAULT_STROKES);
    this.fillOpacity = 1;
    this.strokeOpacity = 1;
    this.lineDash = [0];
    this.lineDashOffset = 0;
    this.cornerRadius = 0;
    this.rotation = 0;
    this.outerRadiusOffset = 0;
    this.outerRadiusRatio = 1;
    this.strokeWidth = 1;
    this.sectorSpacing = 0;
    this.hideZeroValueSectorsInLegend = false;
    this.title = new PieTitle();
    this.shadow = new DropShadow();
    this.calloutLabel = new PieSeriesCalloutLabel();
    this.sectorLabel = new PieSeriesSectorLabel();
    this.calloutLine = new PieSeriesCalloutLine();
    this.tooltip = new SeriesTooltip();
  }
};
__decorateClass([
  Validate(STRING)
], PieSeriesProperties.prototype, "angleKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "angleName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "angleFilterKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "radiusKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "radiusName", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], PieSeriesProperties.prototype, "radiusMin", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER, { optional: true })
], PieSeriesProperties.prototype, "radiusMax", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "calloutLabelKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "calloutLabelName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "sectorLabelKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "sectorLabelName", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], PieSeriesProperties.prototype, "legendItemKey", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], PieSeriesProperties.prototype, "fills", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], PieSeriesProperties.prototype, "strokes", 2);
__decorateClass([
  Validate(RATIO)
], PieSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
  Validate(RATIO)
], PieSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
  Validate(LINE_DASH)
], PieSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
  Validate(FUNCTION, { optional: true })
], PieSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
  Validate(NUMBER)
], PieSeriesProperties.prototype, "rotation", 2);
__decorateClass([
  Validate(NUMBER)
], PieSeriesProperties.prototype, "outerRadiusOffset", 2);
__decorateClass([
  Validate(RATIO)
], PieSeriesProperties.prototype, "outerRadiusRatio", 2);
__decorateClass([
  Validate(POSITIVE_NUMBER)
], PieSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
  Validate(NUMBER)
], PieSeriesProperties.prototype, "sectorSpacing", 2);
__decorateClass([
  Validate(BOOLEAN)
], PieSeriesProperties.prototype, "hideZeroValueSectorsInLegend", 2);
__decorateClass([
  Validate(OBJECT)
], PieSeriesProperties.prototype, "title", 2);
__decorateClass([
  Validate(OBJECT)
], PieSeriesProperties.prototype, "shadow", 2);
__decorateClass([
  Validate(OBJECT)
], PieSeriesProperties.prototype, "calloutLabel", 2);
__decorateClass([
  Validate(OBJECT)
], PieSeriesProperties.prototype, "sectorLabel", 2);
__decorateClass([
  Validate(OBJECT)
], PieSeriesProperties.prototype, "calloutLine", 2);
__decorateClass([
  Validate(OBJECT)
], PieSeriesProperties.prototype, "tooltip", 2);
var PieSeriesNodeEvent = class extends SeriesNodeEvent {
  constructor(type, nativeEvent, datum, series) {
    super(type, nativeEvent, datum, series);
    this.angleKey = series.properties.angleKey;
    this.radiusKey = series.properties.radiusKey;
    this.calloutLabelKey = series.properties.calloutLabelKey;
    this.sectorLabelKey = series.properties.sectorLabelKey;
  }
};
var PieSeries = class extends PolarSeries {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      pickModes: [
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ],
      useLabelLayer: true,
      animationResetFns: { item: resetPieSelectionsFn, label: resetLabelFn }
    });
    this.properties = new PieSeriesProperties();
    this.phantomNodeData = void 0;
    this.backgroundGroup = new TranslatableGroup({
      name: `${this.id}-background`,
      zIndex: 0
      /* BACKGROUND */
    });
    this.previousRadiusScale = new LinearScale();
    this.radiusScale = new LinearScale();
    this.phantomGroup = this.backgroundGroup.appendChild(new Group({ name: "phantom" }));
    this.phantomSelection = Selection.select(
      this.phantomGroup,
      () => this.nodeFactory(),
      false
    );
    this.calloutLabelGroup = this.contentGroup.appendChild(new Group({ name: "pieCalloutLabels" }));
    this.calloutLabelSelection = new Selection(
      this.calloutLabelGroup,
      Group
    );
    this.zerosumRingsGroup = this.backgroundGroup.appendChild(new Group({ name: `${this.id}-zerosumRings` }));
    this.zerosumOuterRing = this.zerosumRingsGroup.appendChild(new Circle());
    this.surroundingRadius = void 0;
    this.NodeEvent = PieSeriesNodeEvent;
    this.angleScale = new LinearScale();
    this.angleScale.domain = [0, 1];
    this.angleScale.range = [-Math.PI, Math.PI].map((angle2) => angle2 + Math.PI / 2);
    this.phantomGroup.opacity = 0.2;
  }
  get calloutNodeData() {
    return this.phantomNodeData ?? this.nodeData;
  }
  attachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.attachSeries(seriesContentNode, seriesNode, annotationNode);
    seriesContentNode.appendChild(this.backgroundGroup);
  }
  detachSeries(seriesContentNode, seriesNode, annotationNode) {
    super.detachSeries(seriesContentNode, seriesNode, annotationNode);
    seriesContentNode?.removeChild(this.backgroundGroup);
  }
  setSeriesIndex(index) {
    if (!super.setSeriesIndex(index))
      return false;
    this.backgroundGroup.zIndex = [0, index];
    return true;
  }
  nodeFactory() {
    const sector = new Sector();
    sector.miterLimit = 1e9;
    return sector;
  }
  getSeriesDomain(direction) {
    if (direction === "x") {
      return this.angleScale.domain;
    } else {
      return this.radiusScale.domain;
    }
  }
  async processData(dataController) {
    if (this.data == null || !this.properties.isValid()) {
      return;
    }
    const {
      visible,
      id: seriesId,
      ctx: { legendManager }
    } = this;
    const { angleKey, angleFilterKey, radiusKey, calloutLabelKey, sectorLabelKey, legendItemKey } = this.properties;
    const validSector = (_value, _datum, index) => {
      return visible && legendManager.getItemEnabled({ seriesId, itemId: index });
    };
    const animationEnabled = !this.ctx.animationManager.isSkipped();
    const extraKeyProps = [];
    const extraProps = [];
    if (legendItemKey) {
      extraKeyProps.push(keyProperty(legendItemKey, "band", { id: `legendItemKey` }));
    } else if (calloutLabelKey) {
      extraKeyProps.push(keyProperty(calloutLabelKey, "band", { id: `calloutLabelKey` }));
    } else if (sectorLabelKey) {
      extraKeyProps.push(keyProperty(sectorLabelKey, "band", { id: `sectorLabelKey` }));
    }
    const radiusScaleType = this.radiusScale.type;
    const angleScaleType = this.angleScale.type;
    if (radiusKey) {
      extraProps.push(
        rangedValueProperty(radiusKey, {
          id: "radiusValue",
          min: this.properties.radiusMin ?? 0,
          max: this.properties.radiusMax
        }),
        valueProperty(radiusKey, radiusScaleType, { id: `radiusRaw` }),
        // Raw value pass-through.
        normalisePropertyTo("radiusValue", [0, 1], 1, this.properties.radiusMin ?? 0, this.properties.radiusMax)
      );
    }
    if (calloutLabelKey) {
      extraProps.push(valueProperty(calloutLabelKey, "band", { id: `calloutLabelValue` }));
    }
    if (sectorLabelKey) {
      extraProps.push(valueProperty(sectorLabelKey, "band", { id: `sectorLabelValue` }));
    }
    if (legendItemKey) {
      extraProps.push(valueProperty(legendItemKey, "band", { id: `legendItemValue` }));
    }
    if (angleFilterKey) {
      extraProps.push(
        accumulativeValueProperty(angleFilterKey, angleScaleType, {
          id: `angleFilterValue`,
          onlyPositive: true,
          validation: validSector,
          invalidValue: 0
        }),
        valueProperty(angleFilterKey, angleScaleType, { id: `angleFilterRaw` }),
        normalisePropertyTo("angleFilterValue", [0, 1], 0, 0)
      );
    }
    if (animationEnabled && this.processedData?.reduced?.animationValidation?.uniqueKeys && extraKeyProps.length > 0) {
      extraProps.push(diff(this.id, this.processedData));
    }
    extraProps.push(animationValidation());
    await this.requestDataModel(dataController, this.data, {
      props: [
        ...extraKeyProps,
        accumulativeValueProperty(angleKey, angleScaleType, {
          id: `angleValue`,
          onlyPositive: true,
          validation: validSector,
          invalidValue: 0
        }),
        valueProperty(angleKey, angleScaleType, { id: `angleRaw` }),
        // Raw value pass-through.
        normalisePropertyTo("angleValue", [0, 1], 0, 0),
        ...extraProps
      ]
    });
    for (const valueDef of this.processedData?.defs?.values ?? []) {
      const { id, missing, property } = valueDef;
      const missCount = getMissCount(this, missing);
      if (id !== "angleRaw" && missCount > 0) {
        Logger.warnOnce(
          `no value was found for the key '${String(property)}' on ${missCount} data element${missCount > 1 ? "s" : ""}`
        );
      }
    }
    this.animationState.transition("updateData");
  }
  maybeRefreshNodeData() {
    if (!this.nodeDataRefresh)
      return;
    const { nodeData = [], phantomNodeData } = this.createNodeData() ?? {};
    this.nodeData = nodeData;
    this.phantomNodeData = phantomNodeData;
    this.nodeDataRefresh = false;
  }
  getProcessedDataValues(dataModel, processedData) {
    const angleValues = dataModel.resolveColumnById(this, `angleValue`, processedData);
    const angleRawValues = dataModel.resolveColumnById(this, `angleRaw`, processedData);
    const angleFilterValues = this.properties.angleFilterKey != null ? dataModel.resolveColumnById(this, `angleFilterValue`, processedData) : void 0;
    const angleFilterRawValues = this.properties.angleFilterKey != null ? dataModel.resolveColumnById(this, `angleFilterRaw`, processedData) : void 0;
    const radiusValues = this.properties.radiusKey ? dataModel.resolveColumnById(this, `radiusValue`, processedData) : void 0;
    const radiusRawValues = this.properties.radiusKey ? dataModel.resolveColumnById(this, `radiusRaw`, processedData) : void 0;
    const calloutLabelValues = this.properties.calloutLabelKey ? dataModel.resolveColumnById(this, `calloutLabelValue`, processedData) : void 0;
    const sectorLabelValues = this.properties.sectorLabelKey ? dataModel.resolveColumnById(this, `sectorLabelValue`, processedData) : void 0;
    const legendItemValues = this.properties.legendItemKey ? dataModel.resolveColumnById(this, `legendItemValue`, processedData) : void 0;
    return {
      angleValues,
      angleRawValues,
      angleFilterValues,
      angleFilterRawValues,
      radiusValues,
      radiusRawValues,
      calloutLabelValues,
      sectorLabelValues,
      legendItemValues
    };
  }
  createNodeData() {
    const {
      id: seriesId,
      processedData,
      dataModel,
      angleScale,
      ctx: { legendManager },
      visible
    } = this;
    const { rotation } = this.properties;
    if (!processedData?.rawData.length || !dataModel || processedData.type !== "ungrouped")
      return;
    const {
      angleValues,
      angleRawValues,
      angleFilterValues,
      angleFilterRawValues,
      radiusValues,
      radiusRawValues,
      calloutLabelValues,
      sectorLabelValues,
      legendItemValues
    } = this.getProcessedDataValues(dataModel, processedData);
    const useFilterAngles = angleFilterRawValues?.some((filterRawValue, index) => {
      return filterRawValue > angleRawValues[index];
    }) ?? false;
    let currentStart = 0;
    let sum2 = 0;
    const nodes = [];
    const phantomNodes = angleFilterRawValues != null ? [] : void 0;
    processedData.rawData.forEach((datum, datumIndex) => {
      const currentValue = useFilterAngles ? angleFilterValues[datumIndex] : angleValues[datumIndex];
      const crossFilterScale = angleFilterRawValues != null && !useFilterAngles ? Math.sqrt(angleFilterRawValues[datumIndex] / angleRawValues[datumIndex]) : 1;
      const startAngle = angleScale.convert(currentStart) + toRadians(rotation);
      currentStart = currentValue;
      sum2 += currentValue;
      const endAngle = angleScale.convert(currentStart) + toRadians(rotation);
      const span = Math.abs(endAngle - startAngle);
      const midAngle = startAngle + span / 2;
      const angleValue = angleRawValues[datumIndex];
      const radiusRaw = radiusValues?.[datumIndex] ?? 1;
      const radius = radiusRaw * crossFilterScale;
      const radiusValue = radiusRawValues?.[datumIndex];
      const legendItemValue = legendItemValues?.[datumIndex];
      const nodeLabels = this.getLabels(
        datum,
        midAngle,
        span,
        true,
        calloutLabelValues?.[datumIndex],
        sectorLabelValues?.[datumIndex],
        legendItemValue
      );
      const sectorFormat = this.getSectorFormat(datum, datumIndex, false);
      const node = {
        itemId: datumIndex,
        series: this,
        datum,
        datumIndex,
        angleValue,
        midAngle,
        midCos: Math.cos(midAngle),
        midSin: Math.sin(midAngle),
        startAngle,
        endAngle,
        radius,
        innerRadius: Math.max(this.radiusScale.convert(0), 0),
        outerRadius: Math.max(this.radiusScale.convert(radius), 0),
        sectorFormat,
        radiusValue,
        legendItemValue,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex }),
        ...nodeLabels
      };
      nodes.push(node);
      if (phantomNodes != null) {
        phantomNodes.push({
          ...node,
          radius: 1,
          innerRadius: Math.max(this.radiusScale.convert(0), 0),
          outerRadius: Math.max(this.radiusScale.convert(1), 0)
        });
      }
    });
    this.zerosumOuterRing.visible = sum2 === 0;
    return {
      itemId: seriesId,
      nodeData: nodes,
      labelData: nodes,
      phantomNodeData: phantomNodes
    };
  }
  getLabels(datum, midAngle, span, skipDisabled, calloutLabelValue, sectorLabelValue, legendItemValue) {
    const { calloutLabel, sectorLabel, legendItemKey } = this.properties;
    const calloutLabelKey = !skipDisabled || calloutLabel.enabled ? this.properties.calloutLabelKey : void 0;
    const sectorLabelKey = !skipDisabled || sectorLabel.enabled ? this.properties.sectorLabelKey : void 0;
    if (!calloutLabelKey && !sectorLabelKey && !legendItemKey) {
      return {};
    }
    const labelFormatterParams = {
      datum,
      angleKey: this.properties.angleKey,
      angleName: this.properties.angleName,
      radiusKey: this.properties.radiusKey,
      radiusName: this.properties.radiusName,
      calloutLabelKey: this.properties.calloutLabelKey,
      calloutLabelName: this.properties.calloutLabelName,
      sectorLabelKey: this.properties.sectorLabelKey,
      sectorLabelName: this.properties.sectorLabelName,
      legendItemKey: this.properties.legendItemKey
    };
    const result = {};
    if (calloutLabelKey && span > toRadians(calloutLabel.minAngle)) {
      result.calloutLabel = {
        ...this.getTextAlignment(midAngle),
        text: this.getLabelText(calloutLabel, {
          ...labelFormatterParams,
          value: calloutLabelValue
        }),
        hidden: false,
        collisionTextAlign: void 0,
        collisionOffsetY: 0,
        box: void 0
      };
    }
    if (sectorLabelKey) {
      result.sectorLabel = {
        text: this.getLabelText(sectorLabel, {
          ...labelFormatterParams,
          value: sectorLabelValue
        })
      };
    }
    if (legendItemKey != null && legendItemValue != null) {
      result.legendItem = { key: legendItemKey, text: legendItemValue };
    }
    return result;
  }
  getTextAlignment(midAngle) {
    const quadrantTextOpts = [
      { textAlign: "center", textBaseline: "bottom" },
      { textAlign: "left", textBaseline: "middle" },
      { textAlign: "center", textBaseline: "hanging" },
      { textAlign: "right", textBaseline: "middle" }
    ];
    const midAngle180 = normalizeAngle180(midAngle);
    const quadrantStart = -0.75 * Math.PI;
    const quadrantOffset = midAngle180 - quadrantStart;
    const quadrant = Math.floor(quadrantOffset / (Math.PI / 2));
    const quadrantIndex = mod(quadrant, quadrantTextOpts.length);
    return quadrantTextOpts[quadrantIndex];
  }
  getSectorFormat(datum, datumIndex, highlighted) {
    const { angleKey, radiusKey, calloutLabelKey, sectorLabelKey, legendItemKey, fills, strokes, itemStyler } = this.properties;
    const defaultStroke = strokes[datumIndex % strokes.length];
    const { fill, fillOpacity, stroke, strokeWidth, strokeOpacity, lineDash, lineDashOffset, cornerRadius } = mergeDefaults(
      highlighted && this.properties.highlightStyle.item,
      {
        fill: fills.length > 0 ? fills[datumIndex % fills.length] : void 0,
        stroke: defaultStroke,
        strokeWidth: this.getStrokeWidth(this.properties.strokeWidth),
        strokeOpacity: this.getOpacity()
      },
      this.properties
    );
    let format;
    if (itemStyler) {
      format = this.cachedDatumCallback(
        createDatumId(this.getDatumIdFromData(datum), highlighted ? "highlight" : "hide"),
        () => itemStyler({
          datum,
          angleKey,
          radiusKey,
          calloutLabelKey,
          sectorLabelKey,
          legendItemKey,
          fill,
          strokeOpacity,
          stroke,
          strokeWidth,
          fillOpacity,
          lineDash,
          lineDashOffset,
          cornerRadius,
          highlighted,
          seriesId: this.id
        })
      );
    }
    return {
      fill: format?.fill ?? fill,
      fillOpacity: format?.fillOpacity ?? fillOpacity,
      stroke: format?.stroke ?? stroke,
      strokeWidth: format?.strokeWidth ?? strokeWidth,
      strokeOpacity: format?.strokeOpacity ?? strokeOpacity,
      lineDash: format?.lineDash ?? lineDash,
      lineDashOffset: format?.lineDashOffset ?? lineDashOffset,
      cornerRadius: format?.cornerRadius ?? cornerRadius
    };
  }
  getOuterRadius() {
    return Math.max(this.radius * this.properties.outerRadiusRatio + this.properties.outerRadiusOffset, 0);
  }
  updateRadiusScale(resize) {
    const newRange = [0, this.getOuterRadius()];
    this.radiusScale.range = newRange;
    if (resize) {
      this.previousRadiusScale.range = newRange;
    }
    const setRadii = (d) => ({
      ...d,
      innerRadius: Math.max(this.radiusScale.convert(0), 0),
      outerRadius: Math.max(this.radiusScale.convert(d.radius), 0)
    });
    this.nodeData = this.nodeData.map(setRadii);
    this.phantomNodeData = this.phantomNodeData?.map(setRadii);
  }
  getTitleTranslationY() {
    const outerRadius = Math.max(0, this.radiusScale.range[1]);
    if (outerRadius === 0) {
      return NaN;
    }
    const spacing = this.properties.title?.spacing ?? 0;
    const titleOffset = 2 + spacing;
    const dy = Math.max(0, -outerRadius);
    return -outerRadius - titleOffset - dy;
  }
  update({ seriesRect }) {
    const { title } = this.properties;
    const newNodeDataDependencies = {
      seriesRectWidth: seriesRect?.width,
      seriesRectHeight: seriesRect?.height
    };
    const resize = jsonDiff(this.nodeDataDependencies, newNodeDataDependencies) != null;
    if (resize) {
      this._nodeDataDependencies = newNodeDataDependencies;
    }
    this.maybeRefreshNodeData();
    this.updateTitleNodes();
    this.updateRadiusScale(resize);
    this.contentGroup.translationX = this.centerX;
    this.contentGroup.translationY = this.centerY;
    this.highlightGroup.translationX = this.centerX;
    this.highlightGroup.translationY = this.centerY;
    this.backgroundGroup.translationX = this.centerX;
    this.backgroundGroup.translationY = this.centerY;
    if (this.labelGroup) {
      this.labelGroup.translationX = this.centerX;
      this.labelGroup.translationY = this.centerY;
    }
    if (title) {
      const dy = this.getTitleTranslationY();
      title.node.y = isFinite(dy) ? dy : 0;
      const titleBox = title.node.getBBox();
      title.node.visible = title.enabled && isFinite(dy) && !this.bboxIntersectsSurroundingSeries(titleBox);
    }
    this.zerosumOuterRing.fillOpacity = 0;
    this.zerosumOuterRing.stroke = this.properties.calloutLabel.color;
    this.zerosumOuterRing.strokeWidth = 1;
    this.zerosumOuterRing.strokeOpacity = 1;
    this.updateNodeMidPoint();
    this.updateSelections();
    this.updateNodes(seriesRect);
  }
  updateTitleNodes() {
    const { oldTitle } = this;
    const { title } = this.properties;
    if (oldTitle !== title) {
      if (oldTitle) {
        this.labelGroup?.removeChild(oldTitle.node);
      }
      if (title) {
        title.node.textBaseline = "bottom";
        this.labelGroup?.appendChild(title.node);
      }
      this.oldTitle = title;
    }
  }
  updateNodeMidPoint() {
    const setMidPoint = (d) => {
      const radius = d.innerRadius + (d.outerRadius - d.innerRadius) / 2;
      d.midPoint = {
        x: d.midCos * Math.max(0, radius),
        y: d.midSin * Math.max(0, radius)
      };
    };
    this.nodeData.forEach(setMidPoint);
    this.phantomNodeData?.forEach(setMidPoint);
  }
  updateSelections() {
    this.updateGroupSelection();
  }
  updateGroupSelection() {
    const {
      itemSelection,
      highlightSelection,
      phantomSelection,
      highlightLabelSelection,
      calloutLabelSelection,
      labelSelection
    } = this;
    const highlightedNodeData = this.nodeData.map((datum) => ({
      ...datum,
      // Allow mutable sectorFormat, so formatted sector styles can be updated and varied
      // between normal and highlighted cases.
      sectorFormat: { ...datum.sectorFormat }
    }));
    const update = (selection, nodeData) => {
      selection.update(nodeData, void 0, (datum) => this.getDatumId(datum));
      if (this.ctx.animationManager.isSkipped()) {
        selection.cleanup();
      }
    };
    update(itemSelection, this.nodeData);
    update(highlightSelection, highlightedNodeData);
    update(phantomSelection, this.phantomNodeData ?? []);
    calloutLabelSelection.update(this.calloutNodeData, (group) => {
      const line = new Line();
      line.tag = 0;
      line.pointerEvents = 1;
      group.appendChild(line);
      const text = new Text();
      text.tag = 1;
      text.pointerEvents = 1;
      group.appendChild(text);
    });
    labelSelection.update(this.nodeData);
    highlightLabelSelection.update(highlightedNodeData);
  }
  updateNodes(seriesRect) {
    const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
    const { visible } = this;
    this.backgroundGroup.visible = visible;
    this.contentGroup.visible = visible;
    this.highlightGroup.visible = visible && highlightedDatum?.series === this;
    this.highlightLabel.visible = visible && highlightedDatum?.series === this;
    if (this.labelGroup) {
      this.labelGroup.visible = visible;
    }
    this.contentGroup.opacity = this.getOpacity();
    const animationDisabled = this.ctx.animationManager.isSkipped();
    const updateSectorFn = (sector, datum, _index, isDatumHighlighted) => {
      const format = this.getSectorFormat(datum.datum, datum.itemId, isDatumHighlighted);
      datum.sectorFormat.fill = format.fill;
      datum.sectorFormat.stroke = format.stroke;
      if (animationDisabled) {
        sector.startAngle = datum.startAngle;
        sector.endAngle = datum.endAngle;
        sector.innerRadius = datum.innerRadius;
        sector.outerRadius = datum.outerRadius;
      }
      if (isDatumHighlighted || animationDisabled) {
        sector.fill = format.fill;
        sector.stroke = format.stroke;
      }
      sector.strokeWidth = format.strokeWidth;
      sector.fillOpacity = format.fillOpacity;
      sector.strokeOpacity = format.strokeOpacity;
      sector.lineDash = format.lineDash;
      sector.lineDashOffset = format.lineDashOffset;
      sector.cornerRadius = format.cornerRadius;
      sector.fillShadow = this.properties.shadow;
      const inset = Math.max(
        (this.properties.sectorSpacing + (format.stroke != null ? format.strokeWidth : 0)) / 2,
        0
      );
      sector.inset = inset;
      sector.lineJoin = this.properties.sectorSpacing >= 0 || inset > 0 ? "miter" : "round";
    };
    this.itemSelection.each((node, datum, index) => updateSectorFn(node, datum, index, false));
    this.highlightSelection.each((node, datum, index) => {
      updateSectorFn(node, datum, index, true);
      node.visible = datum.itemId === highlightedDatum?.itemId;
    });
    this.phantomSelection.each((node, datum, index) => updateSectorFn(node, datum, index, false));
    this.updateCalloutLineNodes();
    this.updateCalloutLabelNodes(seriesRect);
    this.updateSectorLabelNodes();
    this.updateZerosumRings();
    this.animationState.transition("update");
  }
  updateCalloutLineNodes() {
    const { calloutLine } = this.properties;
    const calloutLength = calloutLine.length;
    const calloutStrokeWidth = calloutLine.strokeWidth;
    const calloutColors = calloutLine.colors ?? this.properties.strokes;
    const { offset: offset4 } = this.properties.calloutLabel;
    this.calloutLabelSelection.selectByTag(
      0
      /* Callout */
    ).forEach((line, index) => {
      const datum = line.datum;
      const { calloutLabel: label, outerRadius } = datum;
      if (label?.text && !label.hidden && outerRadius !== 0) {
        line.visible = true;
        line.strokeWidth = calloutStrokeWidth;
        line.stroke = calloutColors[index % calloutColors.length];
        line.fill = void 0;
        const x1 = datum.midCos * outerRadius;
        const y1 = datum.midSin * outerRadius;
        let x2 = datum.midCos * (outerRadius + calloutLength);
        let y2 = datum.midSin * (outerRadius + calloutLength);
        const isMoved = label.collisionTextAlign ?? label.collisionOffsetY !== 0;
        if (isMoved && label.box != null) {
          const box = label.box;
          let cx = x2;
          let cy = y2;
          if (x2 < box.x) {
            cx = box.x;
          } else if (x2 > box.x + box.width) {
            cx = box.x + box.width;
          }
          if (y2 < box.y) {
            cy = box.y;
          } else if (y2 > box.y + box.height) {
            cy = box.y + box.height;
          }
          const dx = cx - x2;
          const dy = cy - y2;
          const length2 = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
          const paddedLength = length2 - offset4;
          if (paddedLength > 0) {
            x2 = x2 + dx * paddedLength / length2;
            y2 = y2 + dy * paddedLength / length2;
          }
        }
        line.x1 = x1;
        line.y1 = y1;
        line.x2 = x2;
        line.y2 = y2;
      } else {
        line.visible = false;
      }
    });
  }
  getLabelOverflow(text, box, seriesRect) {
    const seriesLeft = -this.centerX;
    const seriesRight = seriesLeft + seriesRect.width;
    const seriesTop = -this.centerY;
    const seriesBottom = seriesTop + seriesRect.height;
    const errPx = 1;
    let visibleTextPart = 1;
    if (box.x + errPx < seriesLeft) {
      visibleTextPart = (box.x + box.width - seriesLeft) / box.width;
    } else if (box.x + box.width - errPx > seriesRight) {
      visibleTextPart = (seriesRight - box.x) / box.width;
    }
    const hasVerticalOverflow = box.y + errPx < seriesTop || box.y + box.height - errPx > seriesBottom;
    const textLength = visibleTextPart === 1 ? text.length : Math.floor(text.length * visibleTextPart) - 1;
    const hasSurroundingSeriesOverflow = this.bboxIntersectsSurroundingSeries(box);
    return { textLength, hasVerticalOverflow, hasSurroundingSeriesOverflow };
  }
  bboxIntersectsSurroundingSeries(box) {
    const { surroundingRadius } = this;
    if (surroundingRadius == null) {
      return false;
    }
    const corners = [
      { x: box.x, y: box.y },
      { x: box.x + box.width, y: box.y },
      { x: box.x + box.width, y: box.y + box.height },
      { x: box.x, y: box.y + box.height }
    ];
    const sur2 = surroundingRadius ** 2;
    return corners.some((corner) => corner.x ** 2 + corner.y ** 2 > sur2);
  }
  computeCalloutLabelCollisionOffsets() {
    const { radiusScale } = this;
    const { calloutLabel, calloutLine } = this.properties;
    const { offset: offset4, minSpacing } = calloutLabel;
    const innerRadius = radiusScale.convert(0);
    const shouldSkip = (datum) => {
      const label = datum.calloutLabel;
      return !label || datum.outerRadius === 0;
    };
    const fullData = this.calloutNodeData;
    const data = fullData.filter((t) => !shouldSkip(t));
    data.forEach((datum) => {
      const label = datum.calloutLabel;
      if (label == null)
        return;
      label.hidden = false;
      label.collisionTextAlign = void 0;
      label.collisionOffsetY = 0;
    });
    if (data.length <= 1) {
      return;
    }
    const leftLabels = data.filter((d) => d.midCos < 0).sort((a, b) => a.midSin - b.midSin);
    const rightLabels = data.filter((d) => d.midCos >= 0).sort((a, b) => a.midSin - b.midSin);
    const topLabels = data.filter((d) => d.midSin < 0 && d.calloutLabel?.textAlign === "center").sort((a, b) => a.midCos - b.midCos);
    const bottomLabels = data.filter((d) => d.midSin >= 0 && d.calloutLabel?.textAlign === "center").sort((a, b) => a.midCos - b.midCos);
    const getTextBBox = (datum) => {
      const label = datum.calloutLabel;
      if (label == null)
        return BBox.zero.clone();
      const labelRadius = datum.outerRadius + calloutLine.length + offset4;
      const x = datum.midCos * labelRadius;
      const y = datum.midSin * labelRadius + label.collisionOffsetY;
      const textAlign = label.collisionTextAlign ?? label.textAlign;
      const textBaseline = label.textBaseline;
      return Text.computeBBox(label.text, x, y, {
        font: this.properties.calloutLabel,
        textAlign,
        textBaseline
      });
    };
    const avoidNeighbourYCollision = (label, next, direction) => {
      const box = getTextBBox(label).grow(minSpacing / 2);
      const other = getTextBBox(next).grow(minSpacing / 2);
      const collidesOrBehind = box.x < other.x + other.width && box.x + box.width > other.x && (direction === "to-top" ? box.y < other.y + other.height : box.y + box.height > other.y);
      if (collidesOrBehind) {
        const dy = direction === "to-top" ? box.y - other.y - other.height : box.y + box.height - other.y;
        next.calloutLabel.collisionOffsetY = dy;
      }
    };
    const avoidYCollisions = (labels) => {
      const midLabel = labels.slice().sort((a, b) => Math.abs(a.midSin) - Math.abs(b.midSin))[0];
      const midIndex = labels.indexOf(midLabel);
      for (let i = midIndex - 1; i >= 0; i--) {
        const prev = labels[i + 1];
        const next = labels[i];
        avoidNeighbourYCollision(prev, next, "to-top");
      }
      for (let i = midIndex + 1; i < labels.length; i++) {
        const prev = labels[i - 1];
        const next = labels[i];
        avoidNeighbourYCollision(prev, next, "to-bottom");
      }
    };
    const avoidXCollisions = (labels) => {
      const labelsCollideLabelsByY = data.some((datum) => datum.calloutLabel.collisionOffsetY !== 0);
      const boxes = labels.map((label) => getTextBBox(label));
      const paddedBoxes = boxes.map((box) => box.clone().grow(minSpacing / 2));
      let labelsCollideLabelsByX = false;
      for (let i = 0; i < paddedBoxes.length && !labelsCollideLabelsByX; i++) {
        const box = paddedBoxes[i];
        for (let j = i + 1; j < labels.length; j++) {
          const other = paddedBoxes[j];
          if (box.collidesBBox(other)) {
            labelsCollideLabelsByX = true;
            break;
          }
        }
      }
      const sectors = fullData.map((datum) => {
        const { startAngle, endAngle, outerRadius } = datum;
        return { startAngle, endAngle, innerRadius, outerRadius };
      });
      const labelsCollideSectors = boxes.some((box) => {
        return sectors.some((sector) => boxCollidesSector(box, sector));
      });
      if (!labelsCollideLabelsByX && !labelsCollideLabelsByY && !labelsCollideSectors) {
        return;
      }
      labels.filter((d) => d.calloutLabel.textAlign === "center").forEach((d) => {
        const label = d.calloutLabel;
        if (d.midCos < 0) {
          label.collisionTextAlign = "right";
        } else if (d.midCos > 0) {
          label.collisionTextAlign = "left";
        } else {
          label.collisionTextAlign = "center";
        }
      });
    };
    avoidYCollisions(leftLabels);
    avoidYCollisions(rightLabels);
    avoidXCollisions(topLabels);
    avoidXCollisions(bottomLabels);
  }
  updateCalloutLabelNodes(seriesRect) {
    const { radiusScale } = this;
    const { calloutLabel, calloutLine } = this.properties;
    const calloutLength = calloutLine.length;
    const { offset: offset4, color } = calloutLabel;
    const tempTextNode = new Text();
    this.calloutLabelSelection.selectByTag(
      1
      /* Label */
    ).forEach((text) => {
      const { datum } = text;
      const label = datum.calloutLabel;
      const radius = radiusScale.convert(datum.radius);
      const outerRadius = Math.max(0, radius);
      if (!label?.text || outerRadius === 0 || label.hidden) {
        text.visible = false;
        return;
      }
      const labelRadius = outerRadius + calloutLength + offset4;
      const x = datum.midCos * labelRadius;
      const y = datum.midSin * labelRadius + label.collisionOffsetY;
      const align = {
        textAlign: label.collisionTextAlign ?? label.textAlign,
        textBaseline: label.textBaseline
      };
      tempTextNode.text = label.text;
      tempTextNode.x = x;
      tempTextNode.y = y;
      tempTextNode.setFont(this.properties.calloutLabel);
      tempTextNode.setAlign(align);
      const box = tempTextNode.getBBox();
      let displayText = label.text;
      let visible = true;
      if (calloutLabel.avoidCollisions) {
        const { textLength, hasVerticalOverflow } = this.getLabelOverflow(label.text, box, seriesRect);
        displayText = label.text.length === textLength ? label.text : `${label.text.substring(0, textLength)}\u2026`;
        visible = !hasVerticalOverflow;
      }
      text.text = displayText;
      text.x = x;
      text.y = y;
      text.setFont(this.properties.calloutLabel);
      text.setAlign(align);
      text.fill = color;
      text.visible = visible;
    });
  }
  computeLabelsBBox(options, seriesRect) {
    const { calloutLabel, calloutLine } = this.properties;
    const calloutLength = calloutLine.length;
    const { offset: offset4, maxCollisionOffset, minSpacing } = calloutLabel;
    if (!calloutLabel.avoidCollisions) {
      return null;
    }
    this.maybeRefreshNodeData();
    this.updateRadiusScale(false);
    this.computeCalloutLabelCollisionOffsets();
    const textBoxes = [];
    const text = new Text();
    let titleBox;
    const { title } = this.properties;
    if (title?.text && title.enabled) {
      const dy = this.getTitleTranslationY();
      if (isFinite(dy)) {
        text.text = title.text;
        text.x = 0;
        text.y = dy;
        text.setFont(title);
        text.setAlign({
          textBaseline: "bottom",
          textAlign: "center"
        });
        titleBox = text.getBBox();
        textBoxes.push(titleBox);
      }
    }
    this.calloutNodeData.forEach((datum) => {
      const label = datum.calloutLabel;
      if (!label || datum.outerRadius === 0) {
        return null;
      }
      const labelRadius = datum.outerRadius + calloutLength + offset4;
      const x = datum.midCos * labelRadius;
      const y = datum.midSin * labelRadius + label.collisionOffsetY;
      text.text = label.text;
      text.x = x;
      text.y = y;
      text.setFont(this.properties.calloutLabel);
      text.setAlign({
        textAlign: label.collisionTextAlign ?? label.textAlign,
        textBaseline: label.textBaseline
      });
      const box = text.getBBox();
      label.box = box;
      if (Math.abs(label.collisionOffsetY) > maxCollisionOffset) {
        label.hidden = true;
        return;
      }
      if (titleBox) {
        const seriesTop = -this.centerY;
        const titleCleanArea = new BBox(
          titleBox.x - minSpacing,
          seriesTop,
          titleBox.width + 2 * minSpacing,
          titleBox.y + titleBox.height + minSpacing - seriesTop
        );
        if (box.collidesBBox(titleCleanArea)) {
          label.hidden = true;
          return;
        }
      }
      if (options.hideWhenNecessary) {
        const { textLength, hasVerticalOverflow, hasSurroundingSeriesOverflow } = this.getLabelOverflow(
          label.text,
          box,
          seriesRect
        );
        const isTooShort = label.text.length > 2 && textLength < 2;
        if (hasVerticalOverflow || isTooShort || hasSurroundingSeriesOverflow) {
          label.hidden = true;
          return;
        }
      }
      label.hidden = false;
      textBoxes.push(box);
    });
    if (textBoxes.length === 0) {
      return null;
    }
    return BBox.merge(textBoxes);
  }
  updateSectorLabelNodes() {
    const { radiusScale } = this;
    const innerRadius = radiusScale.convert(0);
    const { fontSize, fontStyle, fontWeight, fontFamily, positionOffset, positionRatio, color } = this.properties.sectorLabel;
    const isDonut = innerRadius > 0;
    const singleVisibleSector = this.ctx.legendManager.getData(this.id)?.filter((d) => d.enabled).length === 1;
    const updateSectorLabel = (text, datum) => {
      const { sectorLabel, outerRadius, startAngle, endAngle } = datum;
      let isTextVisible = false;
      if (sectorLabel && outerRadius !== 0) {
        const labelRadius = innerRadius * (1 - positionRatio) + outerRadius * positionRatio + positionOffset;
        text.fill = color;
        text.fontStyle = fontStyle;
        text.fontWeight = fontWeight;
        text.fontSize = fontSize;
        text.fontFamily = fontFamily;
        text.text = sectorLabel.text;
        const shouldPutTextInCenter = !isDonut && singleVisibleSector;
        if (shouldPutTextInCenter) {
          text.x = 0;
          text.y = 0;
        } else {
          text.x = datum.midCos * labelRadius;
          text.y = datum.midSin * labelRadius;
        }
        text.textAlign = "center";
        text.textBaseline = "middle";
        const bbox = text.getBBox();
        const corners = [
          [bbox.x, bbox.y],
          [bbox.x + bbox.width, bbox.y],
          [bbox.x + bbox.width, bbox.y + bbox.height],
          [bbox.x, bbox.y + bbox.height]
        ];
        const sectorBounds = { startAngle, endAngle, innerRadius, outerRadius };
        if (corners.every(([x, y]) => isPointInSector(x, y, sectorBounds))) {
          isTextVisible = true;
        }
      }
      text.visible = isTextVisible;
    };
    this.labelSelection.each(updateSectorLabel);
    this.highlightLabelSelection.each(updateSectorLabel);
  }
  updateZerosumRings() {
    this.zerosumOuterRing.size = this.getOuterRadius() * 2;
  }
  pickNodeClosestDatum(point) {
    return pickByMatchingAngle(this, point);
  }
  getTooltipContent(nodeDatum) {
    const { id: seriesId, dataModel, processedData, properties } = this;
    const {
      legendItemKey,
      calloutLabelKey,
      calloutLabelName,
      sectorLabelKey,
      sectorLabelName,
      angleKey,
      angleName,
      radiusKey,
      radiusName,
      tooltip
    } = properties;
    const title = this.properties.title.text;
    if (!dataModel || !processedData || processedData.rawData.length === 0)
      return;
    const { datumIndex } = nodeDatum;
    const datum = processedData.rawData[datumIndex];
    const { angleRawValues, legendItemValues, calloutLabelValues, sectorLabelValues } = this.getProcessedDataValues(
      dataModel,
      processedData
    );
    const angleRawValue = angleRawValues[datumIndex];
    const label = legendItemValues?.[datumIndex] ?? (calloutLabelKey === angleKey ? void 0 : calloutLabelValues?.[datumIndex]) ?? (sectorLabelKey === angleKey ? void 0 : sectorLabelValues?.[datumIndex]) ?? angleName;
    return tooltip.formatTooltip(
      {
        title,
        symbol: this.legendItemSymbol(datumIndex),
        data: [
          {
            label,
            fallbackLabel: angleKey,
            value: String(angleRawValue)
          }
        ]
      },
      {
        seriesId,
        datum,
        title: angleName,
        legendItemKey,
        calloutLabelKey,
        calloutLabelName,
        sectorLabelKey,
        sectorLabelName,
        angleKey,
        angleName,
        radiusKey,
        radiusName,
        ...this.getSectorFormat(datum, datumIndex, false)
      }
    );
  }
  legendItemSymbol(datumIndex) {
    const datum = this.processedData?.rawData[datumIndex];
    const sectorFormat = this.getSectorFormat(datum, datumIndex, false);
    return {
      marker: {
        fill: sectorFormat.fill,
        stroke: sectorFormat.stroke,
        fillOpacity: this.properties.fillOpacity,
        strokeOpacity: this.properties.strokeOpacity,
        strokeWidth: this.properties.strokeWidth
      }
    };
  }
  getLegendData(legendType) {
    const {
      id: seriesId,
      visible,
      processedData,
      dataModel,
      ctx: { legendManager }
    } = this;
    if (!dataModel || !processedData || legendType !== "category") {
      return [];
    }
    const { angleKey, calloutLabelKey, sectorLabelKey, legendItemKey, showInLegend } = this.properties;
    if (!legendItemKey && (!calloutLabelKey || calloutLabelKey === angleKey) && (!sectorLabelKey || sectorLabelKey === angleKey)) {
      return [];
    }
    const { calloutLabelValues, sectorLabelValues, legendItemValues, angleRawValues } = this.getProcessedDataValues(
      dataModel,
      processedData
    );
    const titleText = this.properties.title?.showInLegend && this.properties.title.text;
    const legendData = [];
    const hideZeros = this.properties.hideZeroValueSectorsInLegend;
    for (let datumIndex = 0; datumIndex < processedData.rawData.length; datumIndex++) {
      const datum = processedData.rawData[datumIndex];
      const angleRawValue = angleRawValues[datumIndex];
      if (hideZeros && angleRawValue === 0) {
        continue;
      }
      const labelParts = [];
      if (titleText) {
        labelParts.push(titleText);
      }
      const labels = this.getLabels(
        datum,
        2 * Math.PI,
        2 * Math.PI,
        false,
        calloutLabelValues?.[datumIndex],
        sectorLabelValues?.[datumIndex],
        legendItemValues?.[datumIndex]
      );
      if (legendItemKey && labels.legendItem !== void 0) {
        labelParts.push(labels.legendItem.text);
      } else if (calloutLabelKey && calloutLabelKey !== angleKey && labels.calloutLabel?.text !== void 0) {
        labelParts.push(labels.calloutLabel?.text);
      } else if (sectorLabelKey && sectorLabelKey !== angleKey && labels.sectorLabel?.text !== void 0) {
        labelParts.push(labels.sectorLabel?.text);
      }
      if (labelParts.length === 0)
        continue;
      legendData.push({
        legendType: "category",
        id: seriesId,
        datum,
        itemId: datumIndex,
        seriesId,
        enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex }),
        label: {
          text: labelParts.join(" - ")
        },
        symbol: this.legendItemSymbol(datumIndex),
        legendItemName: legendItemKey != null ? datum[legendItemKey] : void 0,
        hideInLegend: !showInLegend
      });
    }
    return legendData;
  }
  // Used for grid
  setLegendState(enabledItems) {
    const {
      id: seriesId,
      ctx: { legendManager, updateService }
    } = this;
    enabledItems.forEach((enabled, itemId) => legendManager.toggleItem({ enabled, seriesId, itemId }));
    legendManager.update();
    updateService.update(
      4
      /* SERIES_UPDATE */
    );
  }
  animateEmptyUpdateReady(_data) {
    const { animationManager } = this.ctx;
    const fns = preparePieSeriesAnimationFunctions(
      true,
      this.properties.rotation,
      this.radiusScale,
      this.previousRadiusScale
    );
    fromToMotion(
      this.id,
      "nodes",
      animationManager,
      [this.itemSelection, this.highlightSelection, this.phantomSelection],
      fns.nodes,
      (_, datum) => this.getDatumId(datum)
    );
    seriesLabelFadeInAnimation(this, "callout", animationManager, this.calloutLabelSelection);
    seriesLabelFadeInAnimation(this, "sector", animationManager, this.labelSelection);
    seriesLabelFadeInAnimation(this, "highlight", animationManager, this.highlightLabelSelection);
    this.previousRadiusScale.range = this.radiusScale.range;
  }
  animateWaitingUpdateReady() {
    const { itemSelection, highlightSelection, phantomSelection, processedData, radiusScale, previousRadiusScale } = this;
    const { animationManager } = this.ctx;
    const dataDiff = processedData?.reduced?.diff?.[this.id];
    this.ctx.animationManager.stopByAnimationGroupId(this.id);
    const supportedDiff = (dataDiff?.moved.size ?? 0) === 0;
    const hasKeys = (processedData?.defs.keys.length ?? 0) > 0;
    const hasUniqueKeys = processedData?.reduced?.animationValidation?.uniqueKeys ?? true;
    if (!supportedDiff || !hasKeys || !hasUniqueKeys) {
      this.ctx.animationManager.skipCurrentBatch();
    }
    const fns = preparePieSeriesAnimationFunctions(
      false,
      this.properties.rotation,
      radiusScale,
      previousRadiusScale
    );
    fromToMotion(
      this.id,
      "nodes",
      animationManager,
      [itemSelection, highlightSelection, phantomSelection],
      fns.nodes,
      (_, datum) => this.getDatumId(datum),
      dataDiff
    );
    seriesLabelFadeInAnimation(this, "callout", this.ctx.animationManager, this.calloutLabelSelection);
    seriesLabelFadeInAnimation(this, "sector", this.ctx.animationManager, this.labelSelection);
    seriesLabelFadeInAnimation(this, "highlight", this.ctx.animationManager, this.highlightLabelSelection);
    this.previousRadiusScale.range = this.radiusScale.range;
  }
  animateClearingUpdateEmpty() {
    const { itemSelection, highlightSelection, phantomSelection, radiusScale, previousRadiusScale } = this;
    const { animationManager } = this.ctx;
    const fns = preparePieSeriesAnimationFunctions(
      false,
      this.properties.rotation,
      radiusScale,
      previousRadiusScale
    );
    fromToMotion(
      this.id,
      "nodes",
      animationManager,
      [itemSelection, highlightSelection, phantomSelection],
      fns.nodes,
      (_, datum) => this.getDatumId(datum)
    );
    seriesLabelFadeOutAnimation(this, "callout", this.ctx.animationManager, this.calloutLabelSelection);
    seriesLabelFadeOutAnimation(this, "sector", this.ctx.animationManager, this.labelSelection);
    seriesLabelFadeOutAnimation(this, "highlight", this.ctx.animationManager, this.highlightLabelSelection);
    this.previousRadiusScale.range = this.radiusScale.range;
  }
  getDatumIdFromData(datum) {
    const { calloutLabelKey, sectorLabelKey, legendItemKey } = this.properties;
    if (!this.processedData?.reduced?.animationValidation?.uniqueKeys) {
      return;
    }
    if (legendItemKey) {
      return datum[legendItemKey];
    } else if (calloutLabelKey) {
      return datum[calloutLabelKey];
    } else if (sectorLabelKey) {
      return datum[sectorLabelKey];
    }
  }
  getDatumId(datum) {
    const { datumIndex } = datum;
    const datumId = this.getDatumIdFromData(datum.datum);
    return datumId != null ? String(datumId) : `${datumIndex}`;
  }
};
PieSeries.className = "PieSeries";
PieSeries.type = "pie";
var PieSeriesModule = {
  type: "series",
  optionsKey: "series[]",
  packageType: "community",
  chartTypes: ["polar"],
  identifier: "pie",
  moduleFactory: (ctx) => new PieSeries(ctx),
  tooltipDefaults: { range: "exact" },
  themeTemplate: pieTheme,
  paletteFactory: piePaletteFactory
};
function registerInbuiltModules() {
  moduleRegistry.register(
    BackgroundModule,
    CommunityLegendModule,
    LocaleModule,
    AreaSeriesModule,
    BarSeriesModule,
    BubbleSeriesModule,
    LineSeriesModule,
    ScatterSeriesModule,
    DonutSeriesModule,
    PieSeriesModule,
    HistogramSeriesModule
  );
  for (const AxisConstructor of [NumberAxis, CategoryAxis, TimeAxis, GroupedCategoryAxis, LogAxis]) {
    axisRegistry.register(AxisConstructor.type, {
      moduleFactory: (ctx) => new AxisConstructor(ctx),
      hidden: AxisConstructor === GroupedCategoryAxis
    });
  }
}
function setupModules() {
  for (const m of moduleRegistry.modules) {
    if (m.packageType === "enterprise" && !verifyIfModuleExpected(m)) {
      Logger.errorOnce("Unexpected enterprise module registered: " + m.identifier);
    }
    if (m.type === "root" && m.themeTemplate) {
      for (const chartType2 of m.chartTypes) {
        chartDefaults.set(chartType2, m.themeTemplate);
      }
    }
    if (m.type === "series") {
      if (m.chartTypes.length > 1) {
        throw new Error(`AG Charts - Module definition error: ${m.identifier}`);
      }
      seriesRegistry.register(m.identifier, m);
    }
    if (m.type === "series-option" && m.themeTemplate) {
      for (const seriesType of m.seriesTypes) {
        seriesRegistry.setThemeTemplate(seriesType, m.themeTemplate);
      }
    }
    if (m.type === "axis-option" && m.themeTemplate) {
      for (const axisType of m.axisTypes) {
        const axisTypeTheme = axisRegistry.getThemeTemplate(axisType);
        const theme = mergeDefaults(m.themeTemplate, axisTypeTheme);
        axisRegistry.setThemeTemplate(axisType, theme);
      }
    }
    if (m.type === "axis") {
      axisRegistry.register(m.identifier, m);
    }
    if (m.type === "legend") {
      legendRegistry.register(m.identifier, m);
    }
  }
  if (moduleRegistry.hasEnterpriseModules()) {
    const expectedButUnused = getUnusedExpectedModules();
    if (expectedButUnused.length > 0) {
      Logger.errorOnce("Enterprise modules expected but not registered: ", expectedButUnused);
    }
  }
}
function isFlowProportion(series) {
  return series.type === "sankey" || series.type === "chord";
}
var FlowProportionChart = class extends Chart {
  getChartType() {
    return "flow-proportion";
  }
  async updateData() {
    await super.updateData();
    const { nodes } = this.getOptions();
    this.series.forEach((series) => {
      if (isFlowProportion(series)) {
        series.setChartNodes(nodes);
      }
    });
  }
  performLayout(ctx) {
    const { seriesRoot, annotationRoot } = this;
    const { layoutBox } = ctx;
    layoutBox.shrink(this.seriesArea.padding.toJson());
    const seriesRect = layoutBox.clone();
    this.seriesRect = seriesRect;
    this.animationRect = seriesRect;
    seriesRoot.visible = this.series.some((s) => s.visible);
    for (const group of [seriesRoot, annotationRoot]) {
      group.translationX = Math.floor(seriesRect.x);
      group.translationY = Math.floor(seriesRect.y);
    }
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      series: { visible: seriesRoot.visible, rect: seriesRect, paddedRect: seriesRect }
    });
  }
};
FlowProportionChart.className = "FlowProportionChart";
FlowProportionChart.type = "flow-proportion";
var PolarAxis = class extends Axis {
  constructor() {
    super(...arguments);
    this.shape = "polygon";
    this.innerRadiusRatio = 0;
    this.defaultTickMinSpacing = 20;
  }
  computeLabelsBBox(_options, _seriesRect) {
    return null;
  }
  computeRange() {
  }
  getAxisLinePoints() {
    return void 0;
  }
};
__decorateClass([
  Validate(UNION(["polygon", "circle"], "a polar axis shape"))
], PolarAxis.prototype, "shape", 2);
__decorateClass([
  Validate(RATIO)
], PolarAxis.prototype, "innerRadiusRatio", 2);
function isRadialGaugeSeries(series) {
  return series.type === "radial-gauge";
}
function isLinearGaugeSeries(series) {
  return series.type === "linear-gauge";
}
var GaugeChart = class extends Chart {
  getChartType() {
    return "gauge";
  }
  updateRadialGauge(seriesRect, series) {
    const angleAxis = this.axes.find(
      (axis) => axis.direction === "x"
      /* X */
    );
    if (!(angleAxis instanceof PolarAxis))
      return;
    angleAxis.computeRange();
    const seriesRectX0 = seriesRect.x;
    const seriesRectX1 = seriesRectX0 + seriesRect.width;
    const seriesRectY0 = seriesRect.y;
    const seriesRectY1 = seriesRectY0 + seriesRect.height;
    const [startAngle, endAngle] = angleAxis.range;
    const sweepAngle = normalizeAngle360Inclusive(endAngle - startAngle);
    const largerThanHalf = sweepAngle > Math.PI;
    const containsTop = largerThanHalf || isBetweenAngles(1.5 * Math.PI, startAngle, endAngle);
    const containsRight = largerThanHalf || isBetweenAngles(0 * Math.PI, startAngle, endAngle);
    const containsBottom = largerThanHalf || isBetweenAngles(0.5 * Math.PI, startAngle, endAngle);
    const containsLeft = largerThanHalf || isBetweenAngles(1 * Math.PI, startAngle, endAngle);
    let textAlign;
    if (containsLeft && !containsRight) {
      textAlign = "right";
    } else if (!containsLeft && containsRight) {
      textAlign = "left";
    } else {
      textAlign = "center";
    }
    let verticalAlign;
    if (containsTop && !containsBottom) {
      verticalAlign = "bottom";
    } else if (!containsTop && containsBottom) {
      verticalAlign = "top";
    } else {
      verticalAlign = "middle";
    }
    const unitBox = sectorBox({
      startAngle,
      endAngle,
      innerRadius: 0,
      outerRadius: 0.5
    });
    const centerXOffset = -(unitBox.x + unitBox.width / 2) * 2;
    const centerYOffset = -(unitBox.y + unitBox.height / 2) * 2;
    const { minimumRadius = 0, maximumRadius } = series;
    const radiusBounds = Math.max(
      0.5 * Math.min(seriesRect.width / unitBox.width, seriesRect.height / unitBox.height),
      // seriesRect may have negative size
      0
    );
    let radius = Math.min(maximumRadius ?? Infinity, Math.max(radiusBounds, minimumRadius ?? 0));
    const MAX_ITERATIONS = 8;
    for (let i = 0; i < MAX_ITERATIONS; i += 1) {
      const isFinalIteration = radius <= minimumRadius || i === MAX_ITERATIONS - 1;
      const centerX = seriesRect.x + seriesRect.width / 2 + centerXOffset * radius;
      const centerY = seriesRect.y + seriesRect.height / 2 + centerYOffset * radius;
      angleAxis.translation.x = centerX;
      angleAxis.translation.y = centerY;
      angleAxis.gridLength = radius;
      angleAxis.calculateLayout();
      const bbox = angleAxis.computeLabelsBBox({ hideWhenNecessary: isFinalIteration }, seriesRect);
      if (isFinalIteration)
        break;
      let shrinkDelta = 0;
      if (bbox != null) {
        const bboxX0 = bbox.x + centerX;
        const bboxX1 = bboxX0 + bbox.width;
        const bboxY0 = bbox.y + centerY;
        const bboxY1 = bboxY0 + bbox.height;
        shrinkDelta = Math.max(
          seriesRectY0 - bboxY0,
          seriesRectX0 - bboxX0,
          bboxY1 - seriesRectY1,
          bboxX1 - seriesRectX1,
          0
        );
      }
      if (shrinkDelta > 0) {
        radius = Math.max(radius - shrinkDelta, minimumRadius);
      } else {
        break;
      }
    }
    angleAxis.translation.x = seriesRect.x + seriesRect.width / 2 + centerXOffset * radius;
    angleAxis.translation.y = seriesRect.y + seriesRect.height / 2 + centerYOffset * radius;
    series.centerX = seriesRect.width / 2 + centerXOffset * radius;
    series.centerY = seriesRect.height / 2 + centerYOffset * radius;
    series.radius = radius;
    series.textAlign = textAlign;
    series.verticalAlign = verticalAlign;
    if (radius === 0 || radius > radiusBounds) {
      Logger.warnOnce("There was insufficient space to display the Radial Gauge.");
    }
  }
  updateLinearGauge(seriesRect, series) {
    const xAxis = this.axes.find(
      (axis) => axis.direction === "x"
      /* X */
    );
    const yAxis = this.axes.find(
      (axis) => axis.direction === "y"
      /* Y */
    );
    if (!(xAxis instanceof CartesianAxis))
      return seriesRect;
    if (!(yAxis instanceof CartesianAxis))
      return seriesRect;
    const { horizontal, thickness } = series;
    let horizontalInset = 0;
    let verticalInset = 0;
    const scale2 = new LinearScale();
    scale2.domain = [0, 100];
    scale2.range = horizontal ? xAxis.range : yAxis.range;
    const ticks = scale2.ticks();
    if (horizontal) {
      horizontalInset = series.computeInset("x", ticks);
    } else {
      verticalInset = series.computeInset("y", ticks);
    }
    const seriesWidth = seriesRect.width - Math.abs(horizontalInset);
    const seriesHeight = seriesRect.height - Math.abs(verticalInset);
    const width2 = Math.max(horizontal ? seriesWidth : thickness, 0);
    const height2 = Math.max(horizontal ? thickness : seriesHeight, 0);
    const x0 = seriesRect.x + (seriesWidth - width2) / 2 + Math.max(horizontalInset, 0);
    const y0 = seriesRect.y + (seriesHeight - height2) / 2 - Math.min(verticalInset, 0);
    xAxis.range = [0, width2];
    xAxis.gridLength = width2;
    xAxis.calculateLayout();
    xAxis.translation.x = x0;
    xAxis.translation.y = y0 + (xAxis.position === "bottom" ? thickness : 0);
    yAxis.range = [0, height2];
    yAxis.gridLength = height2;
    yAxis.calculateLayout();
    yAxis.translation.x = x0 + (yAxis.position === "right" ? thickness : 0);
    yAxis.translation.y = y0;
    series.originX = x0 - seriesRect.x;
    series.originY = y0 - seriesRect.y;
    if (width2 === 0 || height2 === 0) {
      Logger.warnOnce("There was insufficient space to display the Linear Gauge.");
    }
  }
  performLayout(ctx) {
    const { seriesRoot, annotationRoot, series, seriesArea } = this;
    const { layoutBox } = ctx;
    const seriesRect = layoutBox.clone();
    layoutBox.shrink(seriesArea.padding.toJson());
    const firstSeries = this.series[0];
    if (isRadialGaugeSeries(firstSeries)) {
      this.updateRadialGauge(layoutBox, firstSeries);
    } else if (isLinearGaugeSeries(firstSeries)) {
      this.updateLinearGauge(layoutBox, firstSeries);
    }
    this.axes.forEach((axis) => axis.update());
    this.seriesRect = seriesRect.clone().translate(seriesRect.x - layoutBox.x, seriesRect.y - layoutBox.y);
    this.animationRect = layoutBox;
    seriesRoot.visible = series.some((s) => s.visible);
    for (const group of [seriesRoot, annotationRoot]) {
      group.translationX = Math.floor(layoutBox.x);
      group.translationY = Math.floor(layoutBox.y);
    }
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      series: { visible: seriesRoot.visible, rect: seriesRect, paddedRect: layoutBox }
    });
  }
  getAriaLabel() {
    const captions = [];
    const chartCaption = this.getCaptionText();
    if (chartCaption.length !== 0) {
      captions.push(chartCaption);
    }
    for (const series of this.series) {
      captions.push(series.getCaptionText());
    }
    const caption = captions.join(". ");
    return this.ctx.localeManager.t("ariaAnnounceGaugeChart", { caption });
  }
};
GaugeChart.className = "GaugeChart";
GaugeChart.type = "gauge";
var HierarchyChart = class extends Chart {
  constructor(options, resources) {
    super(options, resources);
  }
  getChartType() {
    return "hierarchy";
  }
  performLayout(ctx) {
    const { seriesRoot, annotationRoot } = this;
    const { layoutBox } = ctx;
    layoutBox.shrink(this.seriesArea.padding.toJson());
    const seriesRect = layoutBox.clone();
    this.seriesRect = seriesRect;
    this.animationRect = seriesRect;
    for (const group of [seriesRoot, annotationRoot]) {
      group.translationX = Math.floor(seriesRect.x);
      group.translationY = Math.floor(seriesRect.y);
    }
    seriesRoot.visible = this.series[0].visible;
    seriesRoot.setClipRect(seriesRect.clone());
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      series: { visible: true, rect: seriesRect, paddedRect: seriesRect }
    });
  }
  getAriaLabel() {
    const caption = this.getCaptionText();
    return this.ctx.localeManager.t("ariaAnnounceHierarchyChart", { caption });
  }
};
HierarchyChart.className = "HierarchyChart";
HierarchyChart.type = "hierarchy";
var PolarChart = class extends Chart {
  constructor(options, resources) {
    super(options, resources);
    this.padding = new Padding(40);
    this.ctx.axisManager.axisGroup.zIndex = 5;
  }
  getChartType() {
    return "polar";
  }
  async performLayout(ctx) {
    const { layoutBox } = ctx;
    layoutBox.shrink(this.seriesArea.padding.toJson());
    const seriesRect = layoutBox.clone();
    this.seriesRect = seriesRect;
    this.animationRect = seriesRect;
    this.seriesRoot.translationX = seriesRect.x;
    this.seriesRoot.translationY = seriesRect.y;
    await this.computeCircle(seriesRect);
    this.axes.forEach((axis) => axis.update());
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      series: { visible: true, rect: seriesRect, paddedRect: seriesRect }
    });
  }
  updateAxes(seriesBox, cx, cy, radius) {
    const angleAxis = this.axes.find(
      (axis) => axis.direction === "x"
      /* X */
    );
    const radiusAxis = this.axes.find(
      (axis) => axis.direction === "y"
      /* Y */
    );
    if (!(angleAxis instanceof PolarAxis) || !(radiusAxis instanceof PolarAxis))
      return;
    const angleScale = angleAxis.scale;
    const innerRadiusRatio = radiusAxis.innerRadiusRatio;
    angleAxis.innerRadiusRatio = innerRadiusRatio;
    angleAxis.computeRange();
    angleAxis.gridLength = radius;
    radiusAxis.gridAngles = angleScale.ticks?.().map((value) => angleScale.convert(value));
    radiusAxis.gridRange = angleAxis.range;
    radiusAxis.range = [radius, radius * innerRadiusRatio];
    [angleAxis, radiusAxis].forEach((axis) => {
      axis.translation.x = seriesBox.x + cx;
      axis.translation.y = seriesBox.y + cy;
      axis.calculateLayout();
    });
  }
  async computeCircle(seriesBox) {
    const polarSeries = this.series.filter(isPolarSeries);
    const polarAxes = this.axes.filter(isPolarAxis);
    const setSeriesCircle = (cx, cy, r) => {
      this.updateAxes(seriesBox, cx, cy, r);
      polarSeries.forEach((series) => {
        series.centerX = cx;
        series.centerY = cy;
        series.radius = r;
      });
      const pieSeries = polarSeries.filter((s) => s.type === "donut" || s.type === "pie");
      if (pieSeries.length > 1) {
        const innerRadii = pieSeries.map((series) => {
          const innerRadius = series.getInnerRadius();
          return { series, innerRadius };
        }).sort((a, b) => a.innerRadius - b.innerRadius);
        innerRadii.at(-1).series.surroundingRadius = void 0;
        for (let i = 0; i < innerRadii.length - 1; i++) {
          innerRadii[i].series.surroundingRadius = innerRadii[i + 1].innerRadius;
        }
      }
    };
    const centerX = seriesBox.width / 2;
    const centerY = seriesBox.height / 2;
    const initialRadius = Math.max(0, Math.min(seriesBox.width, seriesBox.height) / 2);
    let radius = initialRadius;
    setSeriesCircle(centerX, centerY, radius);
    const shake = async ({ hideWhenNecessary = false } = {}) => {
      const labelBoxes = [];
      for (const series of iterate(polarAxes, polarSeries)) {
        const box = await series.computeLabelsBBox({ hideWhenNecessary }, seriesBox);
        if (box) {
          labelBoxes.push(box);
        }
      }
      if (labelBoxes.length === 0) {
        setSeriesCircle(centerX, centerY, initialRadius);
        return;
      }
      const labelBox = BBox.merge(labelBoxes);
      const refined = this.refineCircle(labelBox, radius, seriesBox);
      setSeriesCircle(refined.centerX, refined.centerY, refined.radius);
      radius = refined.radius;
    };
    await shake();
    await shake();
    await shake();
    await shake({ hideWhenNecessary: true });
    await shake({ hideWhenNecessary: true });
    for (const series of iterate(polarAxes, polarSeries)) {
      await series.computeLabelsBBox({ hideWhenNecessary: true }, seriesBox);
    }
    return { radius, centerX, centerY };
  }
  refineCircle(labelsBox, radius, seriesBox) {
    const minCircleRatio = 0.5;
    const circleLeft = -radius;
    const circleTop = -radius;
    const circleRight = radius;
    const circleBottom = radius;
    let padLeft = Math.max(0, circleLeft - labelsBox.x);
    let padTop = Math.max(0, circleTop - labelsBox.y);
    let padRight = Math.max(0, labelsBox.x + labelsBox.width - circleRight);
    let padBottom = Math.max(0, labelsBox.y + labelsBox.height - circleBottom);
    padLeft = padRight = Math.max(padLeft, padRight);
    padTop = padBottom = Math.max(padTop, padBottom);
    const availCircleWidth = seriesBox.width - padLeft - padRight;
    const availCircleHeight = seriesBox.height - padTop - padBottom;
    let newRadius = Math.min(availCircleWidth, availCircleHeight) / 2;
    const minHorizontalRadius = minCircleRatio * seriesBox.width / 2;
    const minVerticalRadius = minCircleRatio * seriesBox.height / 2;
    const minRadius = Math.min(minHorizontalRadius, minVerticalRadius);
    if (newRadius < minRadius) {
      newRadius = minRadius;
      const horizontalPadding = padLeft + padRight;
      const verticalPadding = padTop + padBottom;
      if (2 * newRadius + verticalPadding > seriesBox.height) {
        const padHeight = seriesBox.height - 2 * newRadius;
        if (Math.min(padTop, padBottom) * 2 > padHeight) {
          padTop = padHeight / 2;
          padBottom = padHeight / 2;
        } else if (padTop > padBottom) {
          padTop = padHeight - padBottom;
        } else {
          padBottom = padHeight - padTop;
        }
      }
      if (2 * newRadius + horizontalPadding > seriesBox.width) {
        const padWidth = seriesBox.width - 2 * newRadius;
        if (Math.min(padLeft, padRight) * 2 > padWidth) {
          padLeft = padWidth / 2;
          padRight = padWidth / 2;
        } else if (padLeft > padRight) {
          padLeft = padWidth - padRight;
        } else {
          padRight = padWidth - padLeft;
        }
      }
    }
    const newWidth = padLeft + 2 * newRadius + padRight;
    const newHeight = padTop + 2 * newRadius + padBottom;
    return {
      centerX: (seriesBox.width - newWidth) / 2 + padLeft + newRadius,
      centerY: (seriesBox.height - newHeight) / 2 + padTop + newRadius,
      radius: newRadius
    };
  }
};
PolarChart.className = "PolarChart";
PolarChart.type = "polar";
function isPolarSeries(series) {
  return series instanceof PolarSeries;
}
function isPolarAxis(axis) {
  return axis instanceof PolarAxis;
}
var StandaloneChart = class extends Chart {
  constructor(options, resources) {
    super(options, resources);
  }
  getChartType() {
    return "standalone";
  }
  performLayout(ctx) {
    const { seriesRoot, annotationRoot } = this;
    const { layoutBox } = ctx;
    const seriesRect = layoutBox.clone();
    layoutBox.shrink(this.seriesArea.padding.toJson());
    this.seriesRect = layoutBox;
    this.animationRect = layoutBox;
    for (const group of [seriesRoot, annotationRoot]) {
      group.translationX = Math.floor(layoutBox.x);
      group.translationY = Math.floor(layoutBox.y);
    }
    seriesRoot.visible = this.series[0].visible;
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      series: { visible: true, rect: seriesRect, paddedRect: layoutBox }
    });
  }
  getAriaLabel() {
    const caption = this.getCaptionText();
    return this.ctx.localeManager.t("ariaAnnounceHierarchyChart", { caption });
  }
};
StandaloneChart.className = "StandaloneChart";
StandaloneChart.type = "standalone";
var radsInDeg = Math.PI / 180;
var lonX = (lon) => lon * radsInDeg;
var latY = (lat) => -Math.log(Math.tan(Math.PI * 0.25 + lat * radsInDeg * 0.5));
var xLon = (x) => x / radsInDeg;
var yLat = (y) => (Math.atan(Math.exp(-y)) - Math.PI * 0.25) / (radsInDeg * 0.5);
var MercatorScale = class _MercatorScale {
  constructor(domain, range3) {
    this.domain = domain;
    this.range = range3;
    this.type = "mercator";
    this.bounds = _MercatorScale.bounds(domain);
  }
  static bounds(domain) {
    const [[lon0, lat0], [lon1, lat1]] = domain;
    const x0 = lonX(lon0);
    const y0 = latY(lat0);
    const x1 = lonX(lon1);
    const y1 = latY(lat1);
    return new BBox(Math.min(x0, x1), Math.min(y0, y1), Math.abs(x1 - x0), Math.abs(y1 - y0));
  }
  static fixedScale() {
    return new _MercatorScale(
      [
        [xLon(0), yLat(0)],
        [xLon(1), yLat(1)]
      ],
      [
        [0, 0],
        [1, 1]
      ]
    );
  }
  convert([lon, lat]) {
    const [[x0, y0], [x1, y1]] = this.range;
    const xScale = (x1 - x0) / this.bounds.width;
    const yScale = (y1 - y0) / this.bounds.height;
    return [(lonX(lon) - this.bounds.x) * xScale + x0, (latY(lat) - this.bounds.y) * yScale + y0];
  }
  invert([x, y]) {
    const [[x0, y0], [x1, y1]] = this.range;
    const xScale = (x1 - x0) / this.bounds.width;
    const yScale = (y1 - y0) / this.bounds.height;
    return [xLon((x - x0) / xScale + this.bounds.x), yLat((y - y0) / yScale + this.bounds.y)];
  }
};
function isTopologySeries(series) {
  return series.type === "map-shape" || series.type === "map-line" || series.type === "map-marker" || series.type === "map-shape-background" || series.type === "map-line-background";
}
var TopologyChart = class extends Chart {
  constructor(options, resources) {
    super(options, resources);
    this.xAxis = new NumberAxis(this.getModuleContext());
    this.xAxis.position = "bottom";
    this.yAxis = new NumberAxis(this.getModuleContext());
    this.yAxis.position = "left";
    this.ctx.zoomManager.updateAxes([this.xAxis, this.yAxis]);
  }
  getChartType() {
    return "topology";
  }
  async updateData() {
    await super.updateData();
    const { topology } = this.getOptions();
    this.series.forEach((series) => {
      if (isTopologySeries(series)) {
        series.setChartTopology(topology);
      }
    });
  }
  performLayout(ctx) {
    const { seriesRoot, annotationRoot } = this;
    const { layoutBox } = ctx;
    layoutBox.shrink(this.seriesArea.padding.toJson());
    const seriesRect = layoutBox.clone();
    this.seriesRect = seriesRect;
    this.animationRect = seriesRect;
    const mapSeries = this.series.filter(isTopologySeries);
    const combinedBbox = mapSeries.reduce((combined, series) => {
      if (!series.visible)
        return combined;
      const bbox = series.topologyBounds;
      if (bbox == null)
        return combined;
      if (combined == null)
        return bbox;
      combined.merge(bbox);
      return combined;
    }, void 0);
    let scale2;
    if (combinedBbox != null) {
      const { lon0, lat0, lon1, lat1 } = combinedBbox;
      const domain = [
        [lon0, lat0],
        [lon1, lat1]
      ];
      const bounds = MercatorScale.bounds(domain);
      const { width: width2, height: height2 } = seriesRect;
      const viewBoxScale = Math.min(width2 / bounds.width, height2 / bounds.height);
      const viewBoxWidth = bounds.width * viewBoxScale;
      const viewBoxHeight = bounds.height * viewBoxScale;
      const viewBoxOriginX = (width2 - viewBoxWidth) / 2;
      const viewBoxOriginY = (height2 - viewBoxHeight) / 2;
      const x0 = viewBoxOriginX;
      const y0 = viewBoxOriginY;
      const x1 = viewBoxOriginX + viewBoxWidth;
      const y1 = viewBoxOriginY + viewBoxHeight;
      const xZoom = this.ctx.zoomManager.getAxisZoom(this.xAxis.id);
      const yZoom = this.ctx.zoomManager.getAxisZoom(this.yAxis.id);
      const xSpan = (x1 - x0) / (xZoom.max - xZoom.min);
      const xStart = x0 - xSpan * xZoom.min;
      const ySpan = (y1 - y0) / (1 - yZoom.min - (1 - yZoom.max));
      const yStart = y0 - ySpan * (1 - yZoom.max);
      scale2 = new MercatorScale(domain, [
        [xStart, yStart],
        [xStart + xSpan, yStart + ySpan]
      ]);
    }
    mapSeries.forEach((series) => {
      series.scale = scale2;
    });
    const seriesVisible = this.series.some((s) => s.visible);
    seriesRoot.visible = seriesVisible;
    for (const group of [seriesRoot, annotationRoot]) {
      group.translationX = Math.floor(seriesRect.x);
      group.translationY = Math.floor(seriesRect.y);
      group.setClipRect(seriesRect.clone());
    }
    this.ctx.layoutManager.emitLayoutComplete(ctx, {
      series: { visible: seriesVisible, rect: seriesRect, paddedRect: seriesRect }
    });
  }
};
TopologyChart.className = "TopologyChart";
TopologyChart.type = "topology";
var enterpriseModule = {
  isEnterprise: false
};
var IGNORED_PROP = Symbol("IGNORED_PROP");
function pickProps(opts, values) {
  const out = {};
  for (const [key, value] of Object.entries(values)) {
    if (value !== IGNORED_PROP && Object.hasOwn(opts, key)) {
      out[key] = value;
    }
  }
  return out;
}
function isRadialGauge(opts) {
  return opts.type === "radial-gauge";
}
function isLinearGauge(opts) {
  return opts.type === "linear-gauge";
}
function radialGaugeOptions(opts) {
  const {
    animation,
    background,
    container,
    contextMenu,
    footnote,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    subtitle,
    theme,
    title,
    width: width2,
    type,
    cursor,
    nodeClickRange,
    tooltip,
    value,
    scale: scale2 = {},
    startAngle,
    endAngle,
    highlightStyle,
    segmentation,
    bar,
    needle,
    targets,
    outerRadius,
    innerRadius,
    outerRadiusRatio,
    innerRadiusRatio,
    cornerRadius,
    cornerMode,
    label,
    secondaryLabel,
    spacing,
    ...rest
  } = opts;
  const {
    fills: scaleFills,
    fillMode: scaleFillMode,
    fill: scaleFill,
    fillOpacity: scaleFillOpacity,
    stroke: scaleStroke,
    strokeWidth: scaleStrokeWidth,
    strokeOpacity: scaleStrokeOpacity,
    lineDash: scaleLineDash,
    lineDashOffset: scaleLineDashOffset,
    min: scaleMin = 0,
    max: scaleMax = 1,
    interval: scaleInterval = {},
    label: scaleLabel = {}
  } = scale2;
  const chartOpts = pickProps(opts, {
    animation,
    background,
    container,
    contextMenu,
    footnote,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    subtitle,
    theme,
    title,
    width: width2
  });
  const scaleOpts = pickProps(scale2, {
    fills: scaleFills,
    fillMode: scaleFillMode,
    fill: scaleFill,
    fillOpacity: scaleFillOpacity,
    stroke: scaleStroke,
    strokeWidth: scaleStrokeWidth,
    strokeOpacity: scaleStrokeOpacity,
    lineDash: scaleLineDash,
    lineDashOffset: scaleLineDashOffset
  });
  const seriesOpts = pickProps(opts, {
    startAngle: IGNORED_PROP,
    endAngle: IGNORED_PROP,
    needle: needle != null ? { enabled: true, ...needle } : IGNORED_PROP,
    scale: scaleOpts,
    type,
    cursor,
    nodeClickRange,
    listeners,
    tooltip,
    value,
    highlightStyle,
    segmentation,
    bar,
    targets,
    outerRadius,
    innerRadius,
    outerRadiusRatio,
    innerRadiusRatio,
    cornerRadius,
    cornerMode,
    label,
    secondaryLabel,
    spacing,
    ...rest
  });
  const axesOpts = [
    {
      type: "angle-number",
      min: scaleMin,
      max: scaleMax,
      startAngle,
      endAngle,
      interval: scaleInterval ?? {},
      label: scaleLabel ?? {}
    },
    { type: "radius-number" }
  ];
  return {
    ...chartOpts,
    series: [seriesOpts],
    axes: axesOpts
  };
}
function linearGaugeOptions(opts) {
  const {
    animation,
    background,
    container,
    contextMenu,
    footnote,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    subtitle,
    theme,
    title,
    width: width2,
    type,
    cursor,
    nodeClickRange,
    tooltip,
    value,
    scale: scale2 = {},
    direction = "vertical",
    thickness,
    highlightStyle,
    segmentation,
    bar,
    targets,
    cornerRadius,
    cornerMode,
    label,
    ...rest
  } = opts;
  const {
    fills: scaleFills,
    fillMode: scaleFillMode,
    fill: scaleFill,
    fillOpacity: scaleFillOpacity,
    stroke: scaleStroke,
    strokeWidth: scaleStrokeWidth,
    strokeOpacity: scaleStrokeOpacity,
    lineDash: scaleLineDash,
    lineDashOffset: scaleLineDashOffset,
    min: scaleMin = 0,
    max: scaleMax = 1,
    interval: scaleInterval = {},
    label: scaleLabel = {}
  } = scale2;
  const chartOpts = pickProps(opts, {
    animation,
    background,
    container,
    contextMenu,
    footnote,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    subtitle,
    theme,
    title,
    width: width2
  });
  const scaleOpts = pickProps(scale2, {
    fills: scaleFills,
    fillMode: scaleFillMode,
    fill: scaleFill,
    fillOpacity: scaleFillOpacity,
    stroke: scaleStroke,
    strokeWidth: scaleStrokeWidth,
    strokeOpacity: scaleStrokeOpacity,
    lineDash: scaleLineDash,
    lineDashOffset: scaleLineDashOffset
  });
  const seriesOpts = pickProps(opts, {
    scale: scaleOpts,
    type,
    cursor,
    nodeClickRange,
    listeners,
    tooltip,
    value,
    direction,
    thickness,
    highlightStyle,
    segmentation,
    bar,
    targets,
    cornerRadius,
    cornerMode,
    label,
    ...rest
  });
  const { placement: labelPlacement, ...axisLabel } = scaleLabel;
  let mainAxisPosition;
  let crossAxisPosition;
  const horizontal = direction === "horizontal";
  if (horizontal) {
    mainAxisPosition = labelPlacement === "before" ? "top" : "bottom";
    crossAxisPosition = "left";
  } else {
    mainAxisPosition = labelPlacement === "after" ? "right" : "left";
    crossAxisPosition = "bottom";
  }
  const mainAxis = {
    type: "number",
    position: mainAxisPosition,
    min: scaleMin,
    max: scaleMax,
    reverse: !horizontal,
    interval: scaleInterval,
    label: axisLabel,
    nice: false
  };
  const crossAxis = {
    type: "number",
    position: crossAxisPosition,
    min: 0,
    max: 1,
    label: {
      enabled: false
    }
  };
  const axesOpts = horizontal ? [mainAxis, crossAxis] : [crossAxis, mainAxis];
  return {
    ...chartOpts,
    series: [seriesOpts],
    axes: axesOpts
  };
}
function applyThemeDefaults(opts, presetTheme) {
  if (presetTheme == null)
    return opts;
  const { targets: targetsTheme, ...gaugeTheme } = presetTheme;
  opts = mergeDefaults(opts, gaugeTheme);
  if (opts.targets != null && targetsTheme != null) {
    opts.targets = mergeArrayDefaults(opts.targets, targetsTheme);
  }
  return opts;
}
function gauge(opts, presetTheme) {
  if (isRadialGauge(opts)) {
    const radialGaugeOpts = applyThemeDefaults(opts, presetTheme);
    return radialGaugeOptions(radialGaugeOpts);
  } else if (isLinearGauge(opts)) {
    const linearGaugeOpts = applyThemeDefaults(opts, presetTheme);
    return linearGaugeOptions(linearGaugeOpts);
  }
  const {
    animation,
    background,
    container,
    contextMenu,
    footnote,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    subtitle,
    theme,
    title,
    width: width2
  } = opts;
  return pickProps(opts, {
    animation,
    background,
    container,
    contextMenu,
    footnote,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    subtitle,
    theme,
    title,
    width: width2
  });
}
function fromTheme(theme, cb) {
  if (isObject(theme)) {
    return cb(theme);
  }
}
var chartTypes3 = ["ohlc", "line", "step-line", "hlc", "high-low", "candlestick", "hollow-candlestick"];
function priceVolume(opts, _presetTheme, getTheme) {
  const {
    dateKey = "date",
    highKey = "high",
    openKey = "open",
    lowKey = "low",
    closeKey = "close",
    volumeKey = "volume",
    chartType: chartType2 = "candlestick",
    navigator = false,
    volume = true,
    rangeButtons = true,
    statusBar = true,
    toolbar = true,
    zoom = true,
    theme,
    data,
    ...unusedOpts
  } = opts;
  const priceSeries = createPriceSeries(theme, chartType2, dateKey, highKey, lowKey, openKey, closeKey);
  const volumeSeries = createVolumeSeries(theme, getTheme, openKey, closeKey, volume, volumeKey);
  const miniChart = volume ? {
    miniChart: {
      enabled: navigator,
      series: [
        {
          type: "line",
          xKey: dateKey,
          yKey: volumeKey,
          marker: { enabled: false }
        }
      ]
    },
    height: 40,
    minHandle: {
      height: 46
    },
    maxHandle: {
      height: 46
    }
  } : null;
  const navigatorOpts = {
    navigator: {
      enabled: navigator,
      ...miniChart
    }
  };
  const annotationOpts = {
    annotations: {
      enabled: toolbar,
      toolbar: {
        enabled: toolbar
      },
      optionsToolbar: {
        enabled: toolbar
      },
      // @ts-expect-error undocumented option
      data,
      xKey: dateKey,
      volumeKey: volume ? volumeKey : void 0
    }
  };
  const statusBarOpts = statusBar ? {
    statusBar: {
      enabled: true,
      data,
      highKey,
      openKey,
      lowKey,
      closeKey,
      volumeKey: volume ? volumeKey : void 0
    }
  } : null;
  const zoomOpts = {
    zoom: {
      enabled: zoom,
      // @todo(AG-13612) autoScaling?: AgZoomAutoScaling;
      // autoScaling: {
      //     enabled: true,
      // },
      // @ts-expect-error undocumented option
      enableIndependentAxes: true
    }
  };
  const toolbarOpts = {
    ranges: {
      enabled: rangeButtons
    }
  };
  const volumeAxis = volume ? [
    {
      type: "number",
      position: "left",
      keys: [volumeKey],
      label: { enabled: false },
      crosshair: { enabled: false },
      gridLine: { enabled: false },
      nice: false,
      // @ts-expect-error undocumented option
      layoutConstraints: {
        stacked: false,
        width: 20,
        unit: "percentage",
        align: "end"
      }
    }
  ] : [];
  return {
    theme: {
      baseTheme: typeof theme === "string" ? theme : "ag-financial",
      ...mergeDefaults(typeof theme === "object" ? theme : null, {
        overrides: {
          common: {
            title: { padding: 4 },
            padding: {
              top: 6,
              right: 8,
              bottom: 5
            },
            chartToolbar: {
              enabled: toolbar
            }
          }
        }
      })
    },
    animation: { enabled: false },
    legend: { enabled: false },
    series: [...volumeSeries, ...priceSeries],
    seriesArea: { clip: true },
    axes: [
      {
        type: "number",
        position: "right",
        keys: [openKey, closeKey, highKey, lowKey],
        interval: {
          maxSpacing: fromTheme(theme, (t) => t.overrides?.common?.axes?.number?.interval?.maxSpacing) ?? 45
        },
        label: {
          format: fromTheme(theme, (t) => t.overrides?.common?.axes?.number?.label?.format) ?? ".2f"
        },
        crosshair: {
          enabled: true,
          snap: false
        },
        // @ts-expect-error undocumented option
        layoutConstraints: {
          stacked: false,
          width: 100,
          unit: "percentage",
          align: "start"
        }
      },
      ...volumeAxis,
      {
        type: "ordinal-time",
        position: "bottom",
        line: {
          enabled: false
        },
        label: {
          enabled: true
        },
        crosshair: {
          enabled: true
        }
      }
    ],
    tooltip: { enabled: false },
    data,
    ...annotationOpts,
    ...navigatorOpts,
    ...statusBarOpts,
    ...zoomOpts,
    ...toolbarOpts,
    ...unusedOpts
  };
}
function createVolumeSeries(theme, getTheme, openKey, closeKey, volume, volumeKey) {
  if (!volume)
    return [];
  const barSeriesFill = fromTheme(theme, (t) => t.overrides?.bar?.series?.fill);
  const itemStyler = barSeriesFill ? { fill: barSeriesFill } : {
    itemStyler({ datum }) {
      const { up, down } = getTheme().palette;
      return { fill: datum[openKey] < datum[closeKey] ? up?.fill : down?.fill };
    }
  };
  return [
    {
      type: "bar",
      xKey: "date",
      yKey: volumeKey,
      tooltip: { enabled: false },
      highlight: { enabled: false },
      fillOpacity: fromTheme(theme, (t) => t.overrides?.bar?.series?.fillOpacity) ?? 0.5,
      ...itemStyler,
      // @ts-expect-error undocumented option
      focusPriority: 1,
      fastDataProcessing: true
    }
  ];
}
var RANGE_AREA_TYPE = "range-area";
function createPriceSeries(theme, chartType2, xKey, highKey, lowKey, openKey, closeKey) {
  const keys = {
    xKey,
    openKey,
    closeKey,
    highKey,
    lowKey
  };
  const singleKeys = {
    xKey,
    yKey: closeKey
  };
  const common = {
    pickOutsideVisibleMinorAxis: true
  };
  switch (chartType2 ?? "candlestick") {
    case "ohlc":
      return createPriceSeriesOHLC(common, keys);
    case "line":
      return createPriceSeriesLine(common, theme, singleKeys);
    case "step-line":
      return createPriceSeriesStepLine(common, theme, singleKeys);
    case "hlc":
      return createPriceSeriesHLC(common, theme, singleKeys, keys);
    case "high-low":
      return createPriceSeriesHighLow(common, theme, keys);
    case "candlestick":
      return createPriceSeriesCandlestick(common, keys);
    case "hollow-candlestick":
      return createPriceSeriesHollowCandlestick(common, theme, keys);
    default:
      Logger.warnOnce(`unknown chart type: ${chartType2}; expected one of: ${chartTypes3.join(", ")}`);
      return createPriceSeriesCandlestick(common, keys);
  }
}
function createPriceSeriesOHLC(common, keys) {
  return [
    {
      type: "ohlc",
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      ...keys
    }
  ];
}
function createPriceSeriesLine(common, theme, singleKeys) {
  return [
    {
      type: "line",
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      ...singleKeys,
      stroke: fromTheme(theme, (t) => t.overrides?.line?.series?.stroke) ?? PALETTE_NEUTRAL_STROKE,
      marker: fromTheme(theme, (t) => t.overrides?.line?.series?.marker) ?? { enabled: false }
    }
  ];
}
function createPriceSeriesStepLine(common, theme, singleKeys) {
  return [
    {
      type: "line",
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      ...singleKeys,
      stroke: fromTheme(theme, (t) => t.overrides?.line?.series?.stroke) ?? PALETTE_NEUTRAL_STROKE,
      interpolation: fromTheme(theme, (t) => t.overrides?.line?.series?.interpolation) ?? {
        type: "step"
      },
      marker: fromTheme(theme, (t) => t.overrides?.line?.series?.marker) ?? { enabled: false }
    }
  ];
}
function createPriceSeriesHLC(common, theme, singleKeys, { xKey, highKey, closeKey, lowKey }) {
  const rangeAreaColors = getThemeColors(RANGE_AREA_TYPE, theme);
  return [
    {
      type: RANGE_AREA_TYPE,
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      xKey,
      yHighKey: highKey,
      yLowKey: closeKey,
      fill: rangeAreaColors.fill ?? PALETTE_UP_FILL,
      stroke: rangeAreaColors.stroke ?? PALETTE_UP_STROKE,
      fillOpacity: fromTheme(theme, (t) => t.overrides?.["range-area"]?.series?.fillOpacity) ?? 0.3,
      strokeWidth: fromTheme(theme, (t) => t.overrides?.["range-area"]?.series?.strokeWidth) ?? 2
    },
    {
      type: RANGE_AREA_TYPE,
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      xKey,
      yHighKey: closeKey,
      yLowKey: lowKey,
      fill: rangeAreaColors.fill ?? PALETTE_DOWN_FILL,
      stroke: rangeAreaColors.stroke ?? PALETTE_DOWN_STROKE,
      fillOpacity: fromTheme(theme, (t) => t.overrides?.["range-area"]?.series?.fillOpacity) ?? 0.3,
      strokeWidth: fromTheme(theme, (t) => t.overrides?.["range-area"]?.series?.strokeWidth) ?? 2
    },
    {
      type: "line",
      ...common,
      ...singleKeys,
      stroke: fromTheme(theme, (t) => t.overrides?.line?.series?.stroke) ?? PALETTE_ALT_NEUTRAL_STROKE,
      strokeWidth: fromTheme(theme, (t) => t.overrides?.line?.series?.strokeWidth) ?? 2,
      marker: fromTheme(theme, (t) => t.overrides?.line?.series?.marker) ?? { enabled: false }
    }
  ];
}
function createPriceSeriesHighLow(common, theme, { xKey, highKey, lowKey }) {
  const rangeBarColors = getThemeColors("range-bar", theme);
  return [
    {
      type: "range-bar",
      ...common,
      xKey,
      yHighKey: highKey,
      yLowKey: lowKey,
      fill: rangeBarColors.fill ?? PALETTE_NEUTRAL_FILL,
      stroke: rangeBarColors.stroke ?? PALETTE_NEUTRAL_STROKE,
      tooltip: {
        range: "nearest"
      },
      // @ts-expect-error undocumented option
      focusPriority: 0,
      fastDataProcessing: true
    }
  ];
}
function createPriceSeriesCandlestick(common, keys) {
  return [
    {
      type: "candlestick",
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      ...keys
    }
  ];
}
function createPriceSeriesHollowCandlestick(common, theme, keys) {
  const item = fromTheme(theme, (t) => t.overrides?.candlestick?.series?.item);
  return [
    {
      type: "candlestick",
      // @ts-expect-error undocumented option
      focusPriority: 0,
      ...common,
      ...keys,
      item: {
        up: {
          fill: item?.up?.fill ?? "transparent"
        }
      }
    }
  ];
}
function getThemeColors(seriesType, theme) {
  const fill = fromTheme(theme, (t) => t.overrides?.[seriesType]?.series?.fill);
  const stroke = fromTheme(theme, (t) => t.overrides?.[seriesType]?.series?.stroke);
  return { fill, stroke };
}
var commonAxisProperties = {
  title: {
    enabled: false
  },
  label: {
    enabled: false
  },
  line: {
    enabled: false
  },
  gridLine: {
    enabled: false
  },
  crosshair: {
    enabled: false,
    stroke: DEFAULT_SPARKLINE_CROSSHAIR_STROKE,
    lineDash: [0],
    label: {
      enabled: false
    }
  }
};
var numericAxisProperties = {
  ...commonAxisProperties,
  nice: false
};
var tooltipDefaults = {
  position: {
    type: "sparkline"
  }
};
var barGridLineDefaults = {
  style: [{ stroke: DEFAULT_AXIS_GRID_COLOUR }],
  width: 2
};
var barAxisDefaults = {
  number: {
    gridLine: barGridLineDefaults
  },
  time: {
    gridLine: barGridLineDefaults
  },
  category: {
    gridLine: barGridLineDefaults
  }
};
var SPARKLINE_THEME = {
  overrides: {
    common: {
      animation: { enabled: false },
      contextMenu: { enabled: false },
      keyboard: { enabled: false },
      background: { visible: false },
      padding: {
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
      },
      axes: {
        number: {
          ...numericAxisProperties,
          interval: {
            values: [0]
          }
        },
        log: {
          ...numericAxisProperties
        },
        time: {
          ...numericAxisProperties
        },
        category: {
          ...commonAxisProperties
        }
      }
    },
    bar: {
      series: {
        crisp: false,
        label: {
          placement: "inside-end",
          padding: 4
        },
        // @ts-expect-error undocumented option
        sparklineMode: true
      },
      tooltip: {
        ...tooltipDefaults,
        range: "nearest"
      },
      axes: barAxisDefaults
    },
    line: {
      seriesArea: {
        padding: {
          top: 2,
          right: 2,
          bottom: 2,
          left: 2
        }
      },
      series: {
        // @ts-expect-error undocumented option
        sparklineMode: true,
        strokeWidth: 1,
        marker: {
          enabled: false,
          size: 3
        },
        tooltip: tooltipDefaults
      }
    },
    area: {
      seriesArea: {
        padding: {
          top: 1,
          right: 0,
          bottom: 1,
          left: 0
        }
      },
      series: {
        strokeWidth: 1,
        fillOpacity: 0.4,
        tooltip: tooltipDefaults
      }
    }
  }
};
var setInitialBaseTheme = simpleMemorize(createInitialBaseTheme);
function createInitialBaseTheme(baseTheme, initialBaseTheme) {
  if (typeof baseTheme === "string") {
    return {
      ...initialBaseTheme,
      baseTheme
    };
  }
  if (baseTheme != null) {
    return {
      ...baseTheme,
      // @ts-expect-error internal implementation
      baseTheme: setInitialBaseTheme(baseTheme.baseTheme, initialBaseTheme)
    };
  }
  return initialBaseTheme;
}
function sparklineDataPreset(data) {
  if (Array.isArray(data) && data.length !== 0) {
    const firstItem = data[0];
    if (typeof firstItem === "number") {
      const mappedData = data.map((y, x) => ({ x, y }));
      return { data: mappedData, series: [{ xKey: "x", yKey: "y" }], datumKey: "y" };
    } else if (Array.isArray(firstItem)) {
      const mappedData = data.map((datum) => ({ x: datum[0], y: datum[1], datum }));
      return { data: mappedData, series: [{ xKey: "x", yKey: "y" }], datumKey: "datum" };
    }
  }
  return { data };
}
function axisPreset(opts, defaultType) {
  switch (opts?.type) {
    case "number": {
      const { type, visible: _visible, stroke: _stroke, strokeWidth: _strokeWidth, min, max, reverse } = opts;
      return pickProps(opts, {
        type,
        reverse,
        min,
        max
      });
    }
    case "time": {
      const { type, visible: _visible, stroke: _stroke, strokeWidth: _strokeWidth, min, max, reverse } = opts;
      return pickProps(opts, {
        type,
        reverse,
        min,
        max
      });
    }
    case "category": {
      const {
        type,
        visible: _visible,
        stroke: _stroke,
        strokeWidth: _strokeWidth,
        paddingInner,
        paddingOuter,
        reverse
      } = opts;
      return pickProps(opts, {
        type,
        reverse,
        paddingInner,
        paddingOuter
      });
    }
  }
  return { type: defaultType };
}
function gridLinePreset(opts, defaultEnabled, sparkOpts) {
  const gridLineOpts = {};
  if (opts?.stroke != null) {
    gridLineOpts.style = [{ stroke: opts?.stroke }];
    gridLineOpts.enabled ?? (gridLineOpts.enabled = true);
  }
  if (opts?.strokeWidth != null) {
    gridLineOpts.width = opts?.strokeWidth;
    gridLineOpts.enabled ?? (gridLineOpts.enabled = true);
  }
  if (sparkOpts.type === "bar" && sparkOpts.direction !== "horizontal") {
    gridLineOpts.enabled ?? (gridLineOpts.enabled = true);
  }
  if (opts?.visible != null) {
    gridLineOpts.enabled = opts.visible;
  }
  gridLineOpts.enabled ?? (gridLineOpts.enabled = defaultEnabled);
  return gridLineOpts;
}
var tooltipRendererFn = simpleMemorize((context, tooltip, datumKey) => {
  return (params) => {
    const xValue = params.datum[params.xKey];
    const yValue = params.datum[params.yKey];
    const datum = datumKey != null ? params.datum[datumKey] : params.datum;
    const userContent = tooltip?.renderer?.({ context, datum, xValue, yValue });
    if (typeof userContent === "string")
      return userContent;
    const title = userContent?.title;
    const content = userContent?.content;
    return title != null && content != null ? {
      heading: title,
      title: void 0,
      // Undocumented 'compact' tooltip mode
      data: [{ label: void 0, value: content }]
    } : {
      heading: title ?? content ?? yValue.toFixed(2),
      title: void 0,
      data: []
    };
  };
});
function sparkline(opts) {
  const {
    background,
    container,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    width: width2,
    theme: baseTheme,
    data: baseData,
    crosshair,
    axis,
    min,
    max,
    tooltip,
    context,
    ...optsRest
  } = opts;
  const chartOpts = pickProps(opts, {
    background,
    container,
    height: height2,
    listeners,
    locale,
    minHeight,
    minWidth,
    padding,
    width: width2,
    tooltip: IGNORED_PROP,
    context: IGNORED_PROP,
    data: IGNORED_PROP,
    crosshair: IGNORED_PROP,
    axis: IGNORED_PROP,
    min: IGNORED_PROP,
    max: IGNORED_PROP,
    theme: IGNORED_PROP
  });
  const { data, series: [seriesOverrides] = [], datumKey } = sparklineDataPreset(baseData);
  const seriesOptions = optsRest;
  if (seriesOverrides != null)
    Object.assign(seriesOptions, seriesOverrides);
  seriesOptions.tooltip = {
    ...tooltip,
    renderer: tooltipRendererFn(context, tooltip, datumKey)
  };
  chartOpts.theme = setInitialBaseTheme(baseTheme, SPARKLINE_THEME);
  chartOpts.data = data;
  chartOpts.series = [seriesOptions];
  const swapAxes = seriesOptions.type !== "bar" || seriesOptions.direction !== "horizontal";
  const [xAxisPosition, yAxisPosition] = swapAxes ? ["bottom", "left"] : ["left", "bottom"];
  const xAxis = {
    ...axisPreset(axis, "category"),
    position: xAxisPosition,
    ...pickProps(opts, { crosshair })
  };
  const yAxis = {
    type: "number",
    gridLine: gridLinePreset(axis, false, opts),
    position: yAxisPosition,
    ...pickProps(opts, { min, max })
  };
  chartOpts.axes = swapAxes ? [yAxis, xAxis] : [xAxis, yAxis];
  return chartOpts;
}
var PRESETS = {
  "price-volume": priceVolume,
  gauge,
  sparkline
};
var PRESET_DATA_PROCESSORS = {
  sparkline: sparklineDataPreset
};
function removeUsedEnterpriseOptions(options, silent) {
  let usedOptions = [];
  const isGaugeChart = isAgGaugeChartOptions(options);
  const optsType = optionsType(options);
  const optionsChartType = optsType ? chartTypes2.get(optsType) : "unknown";
  for (const module2 of EXPECTED_ENTERPRISE_MODULES) {
    if (optionsChartType !== "unknown" && !module2.chartTypes.includes(optionsChartType))
      continue;
    if (module2.type === "root" || module2.type === "legend") {
      const optionValue = options[module2.optionsKey];
      if (optionValue == null)
        continue;
      if (!module2.optionsInnerKey) {
        usedOptions.push(module2.optionsKey);
        delete options[module2.optionsKey];
      } else if (optionValue[module2.optionsInnerKey]) {
        usedOptions.push(`${module2.optionsKey}.${module2.optionsInnerKey}`);
        delete optionValue[module2.optionsInnerKey];
      }
    } else if (module2.type === "axis") {
      if (!("axes" in options) || !options.axes?.some((axis) => axis.type === module2.identifier))
        continue;
      usedOptions.push(`axis[type=${module2.identifier}]`);
      options.axes = options.axes.filter((axis) => axis.type !== module2.identifier);
    } else if (module2.type === "axis-option") {
      if (!("axes" in options) || !options.axes?.some((axis) => axis[module2.optionsKey]))
        continue;
      usedOptions.push(`axis.${module2.optionsKey}`);
      options.axes.forEach((axis) => {
        if (axis[module2.optionsKey]) {
          delete axis[module2.optionsKey];
        }
      });
    } else if (module2.type === "series") {
      if (module2.community)
        continue;
      if (!options.series?.some((series) => series.type === module2.identifier))
        continue;
      usedOptions.push(`series[type=${module2.identifier}]`);
      options.series = options.series.filter((series) => series.type !== module2.identifier);
    } else if (module2.type === "series-option") {
      if (!options.series?.some((series) => series[module2.optionsKey]))
        continue;
      usedOptions.push(`series.${module2.optionsKey}`);
      options.series.forEach((series) => {
        if (series[module2.optionsKey]) {
          delete series[module2.optionsKey];
        }
      });
    }
  }
  if (usedOptions.length && !silent) {
    if (isGaugeChart) {
      usedOptions = ["AgCharts.createGauge"];
    }
    let enterprisePackageName = "ag-charts-enterprise";
    let enterpriseReferenceUrl = "https://ag-grid.com/charts/javascript/installation/";
    if (options.mode === "integrated") {
      enterprisePackageName = "ag-grid-charts-enterprise' or 'ag-grid-enterprise/charts-enterprise";
      enterpriseReferenceUrl = "https://www.ag-grid.com/javascript-data-grid/integrated-charts-installation/";
    }
    Logger.warnOnce(
      [
        `unable to use these enterprise features as '${enterprisePackageName}' has not been loaded:`,
        "",
        ...usedOptions,
        "",
        `See: ${enterpriseReferenceUrl}`
      ].join("\n")
    );
  }
}
function removeUnusedEnterpriseOptions(options) {
  const integratedMode = "mode" in options && options.mode === "integrated";
  for (const module2 of moduleRegistry.byType("root", "legend")) {
    const moduleOptions = options[module2.optionsKey];
    const isPresentAndDisabled = moduleOptions != null && moduleOptions.enabled === false;
    const removable = !("removable" in module2) || module2.removable === true || module2.removable === "standalone-only" && !integratedMode;
    if (isPresentAndDisabled && removable) {
      delete options[module2.optionsKey];
    }
  }
}
var descriptionSymbol = Symbol("description");
var requiredSymbol = Symbol("required");
function isValid(options, optionsDefs, path) {
  const { errors } = validate(options, optionsDefs, path);
  for (const { message } of errors) {
    Logger.warn(message);
  }
  return errors.length === 0;
}
function validateMessage(path, value, validatorOrDefs) {
  const description = isString(validatorOrDefs) ? validatorOrDefs : validatorOrDefs[descriptionSymbol];
  const expecting = description ? `; expecting ${description}` : "";
  const prefix = path ? `Option \`${path}\`` : "Value";
  return `${prefix} cannot be set to \`${stringifyValue(value)}\`${expecting}, ignoring.`;
}
function validate(options, optionsDefs, path = "") {
  if (!isObject(options)) {
    return {
      valid: null,
      errors: [{ path, value: options, message: validateMessage(path, options, "an object") }]
    };
  }
  const optionsKeys = new Set(Object.keys(options));
  const errors = [];
  const valid = {};
  function extendPath(key) {
    if (isArray(optionsDefs)) {
      return `${path}[${key}]`;
    }
    return path ? `${path}.${key}` : key;
  }
  for (const [key, validatorOrDefs] of Object.entries(optionsDefs)) {
    optionsKeys.delete(key);
    const value = options[key];
    if (!validatorOrDefs[requiredSymbol] && typeof value === "undefined")
      continue;
    if (isFunction(validatorOrDefs)) {
      if (validatorOrDefs(value)) {
        valid[key] = value;
      } else {
        errors.push({ key, path, value, message: validateMessage(extendPath(key), value, validatorOrDefs) });
      }
    } else {
      const nestedResult = validate(value, validatorOrDefs, extendPath(key));
      valid[key] = nestedResult.valid;
      errors.push(...nestedResult.errors);
    }
  }
  for (const key of optionsKeys) {
    errors.push({
      key,
      path,
      unknown: true,
      message: `Unknown option \`${extendPath(key)}\`, ignoring.`
    });
  }
  return { valid, errors };
}
function attachDescription(validator, description) {
  return Object.assign((value) => validator(value), { [descriptionSymbol]: description });
}
var or = (...validators) => attachDescription(
  (value) => validators.some((validator) => validator(value)),
  validators.map((v) => v[descriptionSymbol]).filter(Boolean).join(" or ")
);
var array = attachDescription(isArray, "an array");
var boolean = attachDescription(isBoolean, "a boolean");
var callback = attachDescription(isFunction, "a function");
var number = attachDescription(isFiniteNumber, "a number");
var object = attachDescription(isObject, "an object");
var string = attachDescription(isString, "a string");
var numberMin = (min, inclusive = true) => attachDescription(
  (value) => isFiniteNumber(value) && (value > min || inclusive && value === min),
  `a number greater than ${inclusive ? "or equal to " : ""}${min}`
);
var numberRange = (min, max) => attachDescription(
  (value) => isFiniteNumber(value) && value >= min && value <= max,
  `a number between ${min} and ${max} inclusive`
);
var positiveNumber = numberMin(0);
var ratio = numberRange(0, 1);
var arrayOf = (validator, description) => attachDescription(
  (value) => isArray(value) && value.every(validator),
  description ?? `${validator[descriptionSymbol]} array`
);
function paletteType(partial) {
  if (partial?.up || partial?.down || partial?.neutral) {
    return "user-full";
  } else if (partial?.fills || partial?.strokes) {
    return "user-indexed";
  }
  return "inbuilt";
}
var DEFAULT_BACKGROUND_FILL = "white";
var CHART_TYPE_CONFIG = {
  get cartesian() {
    return { seriesTypes: chartTypes2.cartesianTypes, commonOptions: ["zoom", "navigator"] };
  },
  get polar() {
    return { seriesTypes: chartTypes2.polarTypes, commonOptions: [] };
  },
  get hierarchy() {
    return { seriesTypes: chartTypes2.hierarchyTypes, commonOptions: [] };
  },
  get topology() {
    return { seriesTypes: chartTypes2.topologyTypes, commonOptions: [] };
  },
  get "flow-proportion"() {
    return { seriesTypes: chartTypes2.flowProportionTypes, commonOptions: [] };
  },
  get standalone() {
    return { seriesTypes: chartTypes2.standaloneTypes, commonOptions: [] };
  },
  get gauge() {
    return { seriesTypes: chartTypes2.gaugeTypes, commonOptions: [] };
  }
};
var PRESET_OVERRIDES_TYPES = {
  "radial-gauge": true,
  "linear-gauge": true
};
function isPresetOverridesType(type) {
  return PRESET_OVERRIDES_TYPES[type] === true;
}
var CHART_TYPE_SPECIFIC_COMMON_OPTIONS = Object.values(CHART_TYPE_CONFIG).reduce((r, { commonOptions }) => r.concat(commonOptions), []);
var _ChartTheme = class _ChartTheme2 {
  static getAxisDefaults(overrideDefaults) {
    return mergeDefaults(overrideDefaults, {
      title: {
        enabled: false,
        text: "Axis Title",
        spacing: 25,
        fontWeight: "normal",
        fontSize: 13,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_LABEL_COLOUR
      },
      label: {
        fontSize: 12,
        fontFamily: DEFAULT_FONT_FAMILY,
        spacing: 11,
        color: DEFAULT_LABEL_COLOUR,
        avoidCollisions: true
      },
      line: {
        enabled: true,
        width: 1,
        stroke: DEFAULT_AXIS_LINE_COLOUR
      },
      tick: {
        enabled: false,
        width: 1,
        stroke: DEFAULT_AXIS_LINE_COLOUR
      },
      gridLine: {
        enabled: true,
        style: [{ stroke: DEFAULT_AXIS_GRID_COLOUR, lineDash: [] }]
      },
      crossLines: {
        enabled: false,
        fill: DEFAULT_CROSS_LINES_COLOUR,
        stroke: DEFAULT_CROSS_LINES_COLOUR,
        fillOpacity: 0.1,
        strokeWidth: 1,
        label: {
          enabled: false,
          fontSize: 12,
          fontFamily: DEFAULT_FONT_FAMILY,
          padding: 5,
          color: DEFAULT_LABEL_COLOUR
        }
      },
      crosshair: {
        enabled: true
      }
    });
  }
  getChartDefaults() {
    return {
      minHeight: 300,
      minWidth: 300,
      background: { visible: true, fill: DEFAULT_BACKGROUND_COLOUR },
      padding: { top: DEFAULT_PADDING, right: DEFAULT_PADDING, bottom: DEFAULT_PADDING, left: DEFAULT_PADDING },
      keyboard: { enabled: true },
      title: {
        enabled: false,
        text: "Title",
        fontWeight: "normal",
        fontSize: 17,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_LABEL_COLOUR,
        wrapping: "hyphenate",
        layoutStyle: DEFAULT_CAPTION_LAYOUT_STYLE,
        textAlign: DEFAULT_CAPTION_ALIGNMENT
      },
      subtitle: {
        enabled: false,
        text: "Subtitle",
        spacing: 20,
        fontSize: 13,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: DEFAULT_MUTED_LABEL_COLOUR,
        wrapping: "hyphenate",
        layoutStyle: DEFAULT_CAPTION_LAYOUT_STYLE,
        textAlign: DEFAULT_CAPTION_ALIGNMENT
      },
      footnote: {
        enabled: false,
        text: "Footnote",
        spacing: 20,
        fontSize: 13,
        fontFamily: DEFAULT_FONT_FAMILY,
        color: "rgb(140, 140, 140)",
        wrapping: "hyphenate",
        layoutStyle: DEFAULT_CAPTION_LAYOUT_STYLE,
        textAlign: DEFAULT_CAPTION_ALIGNMENT
      },
      legend: {
        position: "bottom",
        spacing: 30,
        listeners: {},
        toggleSeries: true,
        item: {
          paddingX: 16,
          paddingY: 8,
          marker: { size: 15, padding: 8 },
          showSeriesStroke: true,
          label: {
            color: DEFAULT_LABEL_COLOUR,
            fontSize: 12,
            fontFamily: DEFAULT_FONT_FAMILY
          }
        },
        reverseOrder: false,
        pagination: {
          marker: { size: 12 },
          activeStyle: { fill: DEFAULT_LABEL_COLOUR },
          inactiveStyle: { fill: DEFAULT_MUTED_LABEL_COLOUR },
          highlightStyle: { fill: DEFAULT_LABEL_COLOUR },
          label: { color: DEFAULT_LABEL_COLOUR }
        }
      },
      tooltip: {
        enabled: true,
        darkTheme: IS_DARK_THEME,
        delay: 0
      },
      overlays: { darkTheme: IS_DARK_THEME },
      listeners: {}
    };
  }
  constructor(options = {}) {
    const { overrides, palette } = deepClone(options);
    const defaults = this.createChartConfigPerChartType(this.getDefaults());
    const presets = {};
    if (overrides) {
      this.mergeOverrides(defaults, presets, overrides);
    }
    const { fills, strokes, ...otherColors } = this.getDefaultColors();
    this.palette = deepFreeze(
      mergeDefaults(palette, {
        fills: Object.values(fills),
        strokes: Object.values(strokes),
        ...otherColors
      })
    );
    this.paletteType = paletteType(palette);
    this.config = deepFreeze(this.templateTheme(defaults));
    this.presets = deepFreeze(presets);
  }
  mergeOverrides(defaults, presets, overrides) {
    for (const { seriesTypes, commonOptions } of Object.values(CHART_TYPE_CONFIG)) {
      const cleanedCommon = { ...overrides.common };
      for (const commonKey of CHART_TYPE_SPECIFIC_COMMON_OPTIONS) {
        if (!commonOptions.includes(commonKey)) {
          delete cleanedCommon[commonKey];
        }
      }
      if (!cleanedCommon)
        continue;
      for (const s of seriesTypes) {
        const seriesType = s;
        if (!isPresetOverridesType(seriesType)) {
          defaults[seriesType] = mergeDefaults(cleanedCommon, defaults[seriesType]);
        }
      }
    }
    chartTypes2.seriesTypes.forEach((s) => {
      const seriesType = s;
      const seriesOverrides = overrides[seriesType];
      if (isPresetOverridesType(seriesType)) {
        presets[seriesType] = seriesOverrides;
      } else {
        defaults[seriesType] = mergeDefaults(seriesOverrides, defaults[seriesType]);
      }
    });
  }
  createChartConfigPerChartType(config) {
    for (const [nextType, { seriesTypes }] of Object.entries(CHART_TYPE_CONFIG)) {
      const typeDefaults = chartDefaults.get(nextType);
      for (const seriesType of seriesTypes) {
        config[seriesType] ?? (config[seriesType] = deepClone(typeDefaults));
      }
    }
    return config;
  }
  getDefaults() {
    const getOverridesByType = (chartType2, seriesTypes) => {
      const result = {};
      const chartTypeDefaults = {
        axes: {},
        ...legendRegistry.getThemeTemplates(),
        ...this.getChartDefaults(),
        ...chartDefaults.get(chartType2)
      };
      for (const seriesType of seriesTypes) {
        result[seriesType] = mergeDefaults(
          seriesRegistry.getThemeTemplate(seriesType),
          result[seriesType] ?? deepClone(chartTypeDefaults)
        );
        const { axes } = result[seriesType];
        for (const axisType of axisRegistry.keys()) {
          axes[axisType] = mergeDefaults(
            axes[axisType],
            axisRegistry.getThemeTemplate(axisType),
            _ChartTheme2.cartesianAxisDefault[axisType]
          );
        }
      }
      return result;
    };
    return mergeDefaults(
      getOverridesByType("cartesian", chartTypes2.cartesianTypes),
      getOverridesByType("polar", chartTypes2.polarTypes),
      getOverridesByType("hierarchy", chartTypes2.hierarchyTypes),
      getOverridesByType("topology", chartTypes2.topologyTypes),
      getOverridesByType("flow-proportion", chartTypes2.flowProportionTypes),
      getOverridesByType("standalone", chartTypes2.standaloneTypes),
      getOverridesByType("gauge", chartTypes2.gaugeTypes)
    );
  }
  static applyTemplateTheme(node, _other, params) {
    if (isArray(node)) {
      for (let i = 0; i < node.length; i++) {
        const symbol = node[i];
        if (typeof symbol === "symbol" && params?.has(symbol)) {
          node[i] = params.get(symbol);
        }
      }
    } else {
      for (const [name, value] of Object.entries(node)) {
        if (typeof value === "symbol" && params?.has(value)) {
          node[name] = params.get(value);
        }
      }
    }
  }
  templateTheme(themeTemplate, clone2 = true) {
    const themeInstance = clone2 ? deepClone(themeTemplate) : themeTemplate;
    const params = this.getTemplateParameters();
    jsonWalk(themeInstance, _ChartTheme2.applyTemplateTheme, void 0, void 0, params);
    return themeInstance;
  }
  getDefaultColors() {
    return {
      fills: DEFAULT_FILLS,
      strokes: DEFAULT_STROKES,
      up: { fill: DEFAULT_FILLS.GREEN, stroke: DEFAULT_STROKES.GREEN },
      down: { fill: DEFAULT_FILLS.RED, stroke: DEFAULT_STROKES.RED },
      neutral: { fill: DEFAULT_FILLS.GRAY, stroke: DEFAULT_STROKES.GRAY },
      altUp: { fill: DEFAULT_FILLS.BLUE, stroke: DEFAULT_STROKES.BLUE },
      altDown: { fill: DEFAULT_FILLS.ORANGE, stroke: DEFAULT_STROKES.ORANGE },
      altNeutral: { fill: DEFAULT_FILLS.GRAY, stroke: DEFAULT_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const { isEnterprise } = enterpriseModule;
    const params = /* @__PURE__ */ new Map();
    params.set(IS_DARK_THEME, false);
    params.set(IS_ENTERPRISE, isEnterprise);
    params.set(IS_COMMUNITY, !isEnterprise);
    params.set(DEFAULT_FONT_FAMILY, "Verdana, sans-serif");
    params.set(DEFAULT_LABEL_COLOUR, "#464646");
    params.set(DEFAULT_INVERTED_LABEL_COLOUR, "#fff");
    params.set(DEFAULT_MUTED_LABEL_COLOUR, "#8c8c8c");
    params.set(DEFAULT_AXIS_GRID_COLOUR, "#e0eaf1");
    params.set(DEFAULT_AXIS_LINE_COLOUR, "#c3c3c3");
    params.set(DEFAULT_CROSS_LINES_COLOUR, "#464646");
    params.set(DEFAULT_SEPARATION_LINES_COLOUR, "#d9d9d9");
    params.set(DEFAULT_NAVIGATOR_STROKE, "#ddd");
    params.set(DEFAULT_INSIDE_SERIES_LABEL_COLOUR, DEFAULT_BACKGROUND_FILL);
    params.set(DEFAULT_BACKGROUND_COLOUR, DEFAULT_BACKGROUND_FILL);
    params.set(DEFAULT_INVERTED_BACKGROUND_COLOUR, "black");
    params.set(DEFAULT_SHADOW_COLOUR, "#00000080");
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      DEFAULT_FILLS.ORANGE,
      DEFAULT_FILLS.YELLOW,
      DEFAULT_FILLS.GREEN
    ]);
    params.set(DEFAULT_SPARKLINE_CROSSHAIR_STROKE, "#aaa");
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [DEFAULT_FILLS.GREEN, DEFAULT_FILLS.YELLOW, DEFAULT_FILLS.RED]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      "#5090dc",
      "#629be0",
      "#73a6e3",
      "#85b1e7",
      "#96bcea",
      "#a8c8ee",
      "#b9d3f1",
      "#cbdef5"
    ]);
    params.set(DEFAULT_PADDING, 20);
    params.set(DEFAULT_CAPTION_LAYOUT_STYLE, "block");
    params.set(DEFAULT_CAPTION_ALIGNMENT, "center");
    params.set(DEFAULT_HIERARCHY_FILLS, ["#fff", "#e0e5ea", "#c1ccd5", "#a3b4c1", "#859cad"]);
    params.set(DEFAULT_HIERARCHY_STROKES, ["#fff", "#c5cbd1", "#a4b1bd", "#8498a9", "#648096"]);
    params.set(DEFAULT_FIBONACCI_STROKES, [
      "#797b86",
      "#e24c4a",
      "#f49d2d",
      "#65ab58",
      "#409682",
      "#4db9d2",
      "#5090dc",
      "#3068f9",
      "#e24c4a",
      "#913aac",
      "#d93e64"
    ]);
    params.set(DEFAULT_POLAR_SERIES_STROKE, DEFAULT_BACKGROUND_FILL);
    params.set(DEFAULT_ANNOTATION_COLOR, DEFAULT_FILLS.BLUE);
    params.set(DEFAULT_TEXT_ANNOTATION_COLOR, DEFAULT_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, DEFAULT_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_HANDLE_FILL, DEFAULT_BACKGROUND_FILL);
    params.set(DEFAULT_ANNOTATION_STATISTICS_FILL, "#fafafa");
    params.set(DEFAULT_ANNOTATION_STATISTICS_STROKE, "#ddd");
    params.set(DEFAULT_ANNOTATION_STATISTICS_COLOR, "#000");
    params.set(DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE, "#181d1f");
    params.set(DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL, "#e35c5c");
    params.set(DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE, "#e35c5c");
    params.set(DEFAULT_TEXTBOX_FILL, "#fafafa");
    params.set(DEFAULT_TEXTBOX_STROKE, "#ddd");
    params.set(DEFAULT_TEXTBOX_COLOR, "#000");
    params.set(DEFAULT_TOOLBAR_POSITION, "top");
    params.set(DEFAULT_GRIDLINE_ENABLED, false);
    const defaultColors = this.getDefaultColors();
    params.set(PALETTE_UP_STROKE, this.palette.up?.stroke ?? defaultColors.up.stroke);
    params.set(PALETTE_UP_FILL, this.palette.up?.fill ?? defaultColors.up.fill);
    params.set(PALETTE_DOWN_STROKE, this.palette.down?.stroke ?? defaultColors.down.stroke);
    params.set(PALETTE_DOWN_FILL, this.palette.down?.fill ?? defaultColors.down.fill);
    params.set(PALETTE_NEUTRAL_STROKE, this.palette.neutral?.stroke ?? defaultColors.neutral.stroke);
    params.set(PALETTE_NEUTRAL_FILL, this.palette.neutral?.fill ?? defaultColors.neutral.fill);
    params.set(PALETTE_ALT_UP_STROKE, this.palette.altUp?.stroke ?? defaultColors.up.stroke);
    params.set(PALETTE_ALT_UP_FILL, this.palette.altUp?.fill ?? defaultColors.up.fill);
    params.set(PALETTE_ALT_DOWN_STROKE, this.palette.altDown?.stroke ?? defaultColors.down.stroke);
    params.set(PALETTE_ALT_DOWN_FILL, this.palette.altDown?.fill ?? defaultColors.down.fill);
    params.set(PALETTE_ALT_NEUTRAL_FILL, this.palette.altNeutral?.fill ?? defaultColors.altNeutral.fill);
    params.set(PALETTE_ALT_NEUTRAL_STROKE, this.palette.altNeutral?.stroke ?? defaultColors.altNeutral.stroke);
    return params;
  }
};
_ChartTheme.cartesianAxisDefault = {
  [
    "number"
    /* NUMBER */
  ]: _ChartTheme.getAxisDefaults({
    line: { enabled: false }
  }),
  [
    "log"
    /* LOG */
  ]: _ChartTheme.getAxisDefaults({
    base: 10,
    line: { enabled: false },
    interval: { minSpacing: NaN }
  }),
  [
    "category"
    /* CATEGORY */
  ]: _ChartTheme.getAxisDefaults({
    groupPaddingInner: 0.1,
    label: { autoRotate: true },
    gridLine: { enabled: DEFAULT_GRIDLINE_ENABLED },
    crosshair: { enabled: false }
  }),
  [
    "grouped-category"
    /* GROUPED_CATEGORY */
  ]: _ChartTheme.getAxisDefaults({
    tick: { enabled: true, stroke: DEFAULT_SEPARATION_LINES_COLOUR },
    label: { spacing: 10, rotation: 270 },
    paddingInner: 0.4,
    groupPaddingInner: 0.2,
    crosshair: { enabled: false }
  }),
  [
    "time"
    /* TIME */
  ]: _ChartTheme.getAxisDefaults({ gridLine: { enabled: DEFAULT_GRIDLINE_ENABLED } }),
  [
    "ordinal-time"
    /* ORDINAL_TIME */
  ]: _ChartTheme.getAxisDefaults({
    groupPaddingInner: 0,
    label: { autoRotate: false },
    gridLine: { enabled: DEFAULT_GRIDLINE_ENABLED }
  }),
  [
    "angle-category"
    /* ANGLE_CATEGORY */
  ]: _ChartTheme.getAxisDefaults({
    label: { spacing: 5 },
    gridLine: { enabled: DEFAULT_GRIDLINE_ENABLED }
  }),
  [
    "angle-number"
    /* ANGLE_NUMBER */
  ]: _ChartTheme.getAxisDefaults({
    label: { spacing: 5 },
    gridLine: { enabled: DEFAULT_GRIDLINE_ENABLED }
  }),
  [
    "radius-category"
    /* RADIUS_CATEGORY */
  ]: _ChartTheme.getAxisDefaults({
    line: { enabled: false }
  }),
  [
    "radius-number"
    /* RADIUS_NUMBER */
  ]: _ChartTheme.getAxisDefaults({
    line: { enabled: false }
  })
};
var ChartTheme = _ChartTheme;
var DEFAULT_DARK_BACKGROUND_FILL = "#192232";
var DEFAULT_DARK_FILLS = {
  BLUE: "#5090dc",
  ORANGE: "#ffa03a",
  GREEN: "#459d55",
  CYAN: "#34bfe1",
  YELLOW: "#e1cc00",
  VIOLET: "#9669cb",
  GRAY: "#b5b5b5",
  MAGENTA: "#bd5aa7",
  BROWN: "#8a6224",
  RED: "#ef5452"
};
var DEFAULT_DARK_STROKES = {
  BLUE: "#74a8e6",
  ORANGE: "#ffbe70",
  GREEN: "#6cb176",
  CYAN: "#75d4ef",
  YELLOW: "#f6e559",
  VIOLET: "#aa86d8",
  GRAY: "#a1a1a1",
  MAGENTA: "#ce7ab9",
  BROWN: "#997b52",
  RED: "#ff7872"
};
var DarkTheme = class extends ChartTheme {
  getDefaultColors() {
    return {
      fills: DEFAULT_DARK_FILLS,
      strokes: DEFAULT_DARK_STROKES,
      up: { fill: DEFAULT_DARK_FILLS.GREEN, stroke: DEFAULT_DARK_STROKES.GREEN },
      down: { fill: DEFAULT_DARK_FILLS.RED, stroke: DEFAULT_DARK_STROKES.RED },
      neutral: { fill: DEFAULT_DARK_FILLS.GRAY, stroke: DEFAULT_DARK_STROKES.GRAY },
      altUp: { fill: DEFAULT_DARK_FILLS.BLUE, stroke: DEFAULT_DARK_STROKES.BLUE },
      altDown: { fill: DEFAULT_DARK_FILLS.ORANGE, stroke: DEFAULT_DARK_STROKES.ORANGE },
      altNeutral: { fill: DEFAULT_DARK_FILLS.GRAY, stroke: DEFAULT_DARK_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(IS_DARK_THEME, true);
    params.set(DEFAULT_POLAR_SERIES_STROKE, DEFAULT_DARK_BACKGROUND_FILL);
    params.set(DEFAULT_NAVIGATOR_STROKE, "#4b525d");
    params.set(DEFAULT_LABEL_COLOUR, "#fff");
    params.set(DEFAULT_MUTED_LABEL_COLOUR, "#7d91a0");
    params.set(DEFAULT_AXIS_GRID_COLOUR, "#545a6e");
    params.set(DEFAULT_CROSS_LINES_COLOUR, "#fff");
    params.set(DEFAULT_SEPARATION_LINES_COLOUR, "#7f8389");
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      DEFAULT_DARK_FILLS.ORANGE,
      DEFAULT_DARK_FILLS.YELLOW,
      DEFAULT_DARK_FILLS.GREEN
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [
      DEFAULT_DARK_FILLS.GREEN,
      DEFAULT_DARK_FILLS.YELLOW,
      DEFAULT_DARK_FILLS.RED
    ]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      "#5090dc",
      "#4882c6",
      "#4073b0",
      "#38659a",
      "#305684",
      "#28486e",
      "#203a58",
      "#182b42"
    ]);
    params.set(DEFAULT_HIERARCHY_FILLS, ["#192834", "#253746", "#324859", "#3f596c", "#4d6a80"]);
    params.set(DEFAULT_HIERARCHY_STROKES, ["#192834", "#3b5164", "#496275", "#577287", "#668399"]);
    params.set(DEFAULT_BACKGROUND_COLOUR, DEFAULT_DARK_BACKGROUND_FILL);
    params.set(DEFAULT_INVERTED_BACKGROUND_COLOUR, "white");
    params.set(DEFAULT_INSIDE_SERIES_LABEL_COLOUR, DEFAULT_DARK_BACKGROUND_FILL);
    params.set(DEFAULT_ANNOTATION_COLOR, DEFAULT_DARK_FILLS.BLUE);
    params.set(DEFAULT_TEXT_ANNOTATION_COLOR, "#fff");
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, DEFAULT_DARK_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_HANDLE_FILL, DEFAULT_DARK_BACKGROUND_FILL);
    params.set(DEFAULT_ANNOTATION_STATISTICS_FILL, "#28313e");
    params.set(DEFAULT_ANNOTATION_STATISTICS_STROKE, "#4b525d");
    params.set(DEFAULT_ANNOTATION_STATISTICS_COLOR, "#fff");
    params.set(DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE, "#fff");
    params.set(DEFAULT_TEXTBOX_FILL, "#28313e");
    params.set(DEFAULT_TEXTBOX_STROKE, "#4b525d");
    params.set(DEFAULT_TEXTBOX_COLOR, "#fff");
    return params;
  }
  constructor(options) {
    super(options);
  }
};
var FINANCIAL_DARK_FILLS = {
  GREEN: "#089981",
  RED: "#F23645",
  BLUE: "#5090dc",
  GRAY: "#A9A9A9"
};
var FINANCIAL_DARK_STROKES = {
  GREEN: "#089981",
  RED: "#F23645",
  BLUE: "#5090dc",
  GRAY: "#909090"
};
var FinancialDark = class extends DarkTheme {
  getDefaultColors() {
    return {
      fills: { ...FINANCIAL_DARK_FILLS },
      strokes: { ...FINANCIAL_DARK_STROKES },
      up: { fill: FINANCIAL_DARK_FILLS.GREEN, stroke: FINANCIAL_DARK_STROKES.GREEN },
      down: { fill: FINANCIAL_DARK_FILLS.RED, stroke: FINANCIAL_DARK_STROKES.RED },
      neutral: { fill: FINANCIAL_DARK_FILLS.BLUE, stroke: FINANCIAL_DARK_STROKES.BLUE },
      altUp: { fill: FINANCIAL_DARK_FILLS.GREEN, stroke: FINANCIAL_DARK_STROKES.GREEN },
      altDown: { fill: FINANCIAL_DARK_FILLS.RED, stroke: FINANCIAL_DARK_STROKES.RED },
      altNeutral: { fill: FINANCIAL_DARK_FILLS.GRAY, stroke: FINANCIAL_DARK_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      FINANCIAL_DARK_FILLS.GREEN,
      FINANCIAL_DARK_FILLS.BLUE,
      FINANCIAL_DARK_FILLS.RED
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, FINANCIAL_DARK_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, FINANCIAL_DARK_FILLS.BLUE);
    params.set(DEFAULT_AXIS_GRID_COLOUR, "#343A4E");
    params.set(DEFAULT_PADDING, 0);
    params.set(DEFAULT_CAPTION_LAYOUT_STYLE, "overlay");
    params.set(DEFAULT_CAPTION_ALIGNMENT, "left");
    params.set(DEFAULT_TOOLBAR_POSITION, "bottom");
    params.set(DEFAULT_GRIDLINE_ENABLED, true);
    return params;
  }
};
var FINANCIAL_LIGHT_FILLS = {
  GREEN: "#089981",
  RED: "#F23645",
  BLUE: "#5090dc",
  GRAY: "#A9A9A9"
};
var FINANCIAL_LIGHT_STROKES = {
  GREEN: "#089981",
  RED: "#F23645",
  BLUE: "#5090dc",
  GRAY: "#909090"
};
var FinancialLight = class extends ChartTheme {
  getDefaultColors() {
    return {
      fills: { ...FINANCIAL_LIGHT_FILLS },
      strokes: { ...FINANCIAL_LIGHT_STROKES },
      up: { fill: FINANCIAL_LIGHT_FILLS.GREEN, stroke: FINANCIAL_LIGHT_STROKES.GREEN },
      down: { fill: FINANCIAL_LIGHT_FILLS.RED, stroke: FINANCIAL_LIGHT_STROKES.RED },
      neutral: { fill: FINANCIAL_LIGHT_FILLS.BLUE, stroke: FINANCIAL_LIGHT_STROKES.BLUE },
      altUp: { fill: FINANCIAL_LIGHT_FILLS.GREEN, stroke: FINANCIAL_LIGHT_STROKES.GREEN },
      altDown: { fill: FINANCIAL_LIGHT_FILLS.RED, stroke: FINANCIAL_LIGHT_STROKES.RED },
      altNeutral: { fill: FINANCIAL_LIGHT_FILLS.GRAY, stroke: FINANCIAL_LIGHT_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      FINANCIAL_LIGHT_FILLS.GREEN,
      FINANCIAL_LIGHT_FILLS.BLUE,
      FINANCIAL_LIGHT_FILLS.RED
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, FINANCIAL_LIGHT_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, FINANCIAL_LIGHT_FILLS.BLUE);
    params.set(DEFAULT_AXIS_GRID_COLOUR, "#F2F3F3");
    params.set(DEFAULT_PADDING, 0);
    params.set(DEFAULT_CAPTION_LAYOUT_STYLE, "overlay");
    params.set(DEFAULT_CAPTION_ALIGNMENT, "left");
    params.set(DEFAULT_TOOLBAR_POSITION, "bottom");
    params.set(DEFAULT_GRIDLINE_ENABLED, true);
    return params;
  }
};
var MATERIAL_DARK_FILLS = {
  BLUE: "#2196F3",
  ORANGE: "#FF9800",
  GREEN: "#4CAF50",
  CYAN: "#00BCD4",
  YELLOW: "#FFEB3B",
  VIOLET: "#7E57C2",
  GRAY: "#9E9E9E",
  MAGENTA: "#F06292",
  BROWN: "#795548",
  RED: "#F44336"
};
var MATERIAL_DARK_STROKES = {
  BLUE: "#90CAF9",
  ORANGE: "#FFCC80",
  GREEN: "#A5D6A7",
  CYAN: "#80DEEA",
  YELLOW: "#FFF9C4",
  VIOLET: "#B39DDB",
  GRAY: "#E0E0E0",
  MAGENTA: "#F48FB1",
  BROWN: "#A1887F",
  RED: "#EF9A9A"
};
var MaterialDark = class extends DarkTheme {
  getDefaultColors() {
    return {
      fills: MATERIAL_DARK_FILLS,
      strokes: MATERIAL_DARK_STROKES,
      up: { fill: MATERIAL_DARK_FILLS.GREEN, stroke: MATERIAL_DARK_STROKES.GREEN },
      down: { fill: MATERIAL_DARK_FILLS.RED, stroke: MATERIAL_DARK_STROKES.RED },
      neutral: { fill: MATERIAL_DARK_FILLS.GRAY, stroke: MATERIAL_DARK_STROKES.GRAY },
      altUp: { fill: MATERIAL_DARK_FILLS.BLUE, stroke: MATERIAL_DARK_STROKES.BLUE },
      altDown: { fill: MATERIAL_DARK_FILLS.RED, stroke: MATERIAL_DARK_STROKES.RED },
      altNeutral: { fill: MATERIAL_DARK_FILLS.GRAY, stroke: MATERIAL_DARK_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      MATERIAL_DARK_FILLS.ORANGE,
      MATERIAL_DARK_FILLS.YELLOW,
      MATERIAL_DARK_FILLS.GREEN
    ]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      "#2196f3",
      // 500
      "#208FEC",
      // (interpolated)
      "#1E88E5",
      // 600
      "#1C7FDC",
      // (interpolated)
      "#1976d2",
      // 700
      "#176EC9",
      // (interpolated)
      "#1565c0"
      // 800
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [
      MATERIAL_DARK_FILLS.GREEN,
      MATERIAL_DARK_FILLS.YELLOW,
      MATERIAL_DARK_FILLS.RED
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, MATERIAL_DARK_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, MATERIAL_DARK_FILLS.BLUE);
    return params;
  }
};
var MATERIAL_LIGHT_FILLS = {
  BLUE: "#2196F3",
  ORANGE: "#FF9800",
  GREEN: "#4CAF50",
  CYAN: "#00BCD4",
  YELLOW: "#FFEB3B",
  VIOLET: "#7E57C2",
  GRAY: "#9E9E9E",
  MAGENTA: "#F06292",
  BROWN: "#795548",
  RED: "#F44336"
};
var MATERIAL_LIGHT_STROKES = {
  BLUE: "#1565C0",
  ORANGE: "#E65100",
  GREEN: "#2E7D32",
  CYAN: "#00838F",
  YELLOW: "#F9A825",
  VIOLET: "#4527A0",
  GRAY: "#616161",
  MAGENTA: "#C2185B",
  BROWN: "#4E342E",
  RED: "#B71C1C"
};
var MaterialLight = class extends ChartTheme {
  getDefaultColors() {
    return {
      fills: MATERIAL_LIGHT_FILLS,
      strokes: MATERIAL_LIGHT_STROKES,
      up: { fill: MATERIAL_LIGHT_FILLS.GREEN, stroke: MATERIAL_LIGHT_STROKES.GREEN },
      down: { fill: MATERIAL_LIGHT_FILLS.RED, stroke: MATERIAL_LIGHT_STROKES.RED },
      neutral: { fill: MATERIAL_LIGHT_FILLS.GRAY, stroke: MATERIAL_LIGHT_STROKES.GRAY },
      altUp: { fill: MATERIAL_LIGHT_FILLS.BLUE, stroke: MATERIAL_LIGHT_STROKES.BLUE },
      altDown: { fill: MATERIAL_LIGHT_FILLS.RED, stroke: MATERIAL_LIGHT_STROKES.RED },
      altNeutral: { fill: MATERIAL_LIGHT_FILLS.GRAY, stroke: MATERIAL_LIGHT_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      MATERIAL_LIGHT_FILLS.ORANGE,
      MATERIAL_LIGHT_FILLS.YELLOW,
      MATERIAL_LIGHT_FILLS.GREEN
    ]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      "#2196f3",
      // 500
      "#329EF4",
      // (interpolated)
      "#42a5f5",
      // 400
      "#53ADF6",
      // (interpolated)
      "#64b5f6",
      // 300
      "#7AC0F8",
      // (interpolated)
      "#90caf9"
      // 200
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [
      MATERIAL_LIGHT_FILLS.GREEN,
      MATERIAL_LIGHT_FILLS.YELLOW,
      MATERIAL_LIGHT_FILLS.RED
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, MATERIAL_LIGHT_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, MATERIAL_LIGHT_FILLS.BLUE);
    return params;
  }
};
var POLYCHROMA_DARK_FILLS = {
  BLUE: "#436ff4",
  PURPLE: "#9a7bff",
  MAGENTA: "#d165d2",
  PINK: "#f0598b",
  RED: "#f47348",
  ORANGE: "#f2a602",
  YELLOW: "#e9e201",
  GREEN: "#21b448",
  CYAN: "#00b9a2",
  MODERATE_BLUE: "#00aee4",
  GRAY: "#bbbbbb"
};
var POLYCHROMA_DARK_STROKES = {
  BLUE: "#6698ff",
  PURPLE: "#c0a3ff",
  MAGENTA: "#fc8dfc",
  PINK: "#ff82b1",
  RED: "#ff9b70",
  ORANGE: "#ffcf4e",
  YELLOW: "#ffff58",
  GREEN: "#58dd70",
  CYAN: "#51e2c9",
  MODERATE_BLUE: "#4fd7ff",
  GRAY: "#eeeeee"
};
var PolychromaDark = class extends DarkTheme {
  getDefaultColors() {
    return {
      fills: POLYCHROMA_DARK_FILLS,
      strokes: POLYCHROMA_DARK_STROKES,
      up: { fill: POLYCHROMA_DARK_FILLS.GREEN, stroke: POLYCHROMA_DARK_STROKES.GREEN },
      down: { fill: POLYCHROMA_DARK_FILLS.RED, stroke: POLYCHROMA_DARK_STROKES.RED },
      neutral: { fill: POLYCHROMA_DARK_FILLS.GRAY, stroke: POLYCHROMA_DARK_STROKES.GRAY },
      altUp: { fill: POLYCHROMA_DARK_FILLS.BLUE, stroke: POLYCHROMA_DARK_STROKES.BLUE },
      altDown: { fill: POLYCHROMA_DARK_FILLS.RED, stroke: POLYCHROMA_DARK_STROKES.RED },
      altNeutral: { fill: POLYCHROMA_DARK_FILLS.GRAY, stroke: POLYCHROMA_DARK_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [POLYCHROMA_DARK_FILLS.BLUE, POLYCHROMA_DARK_FILLS.RED]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      POLYCHROMA_DARK_FILLS.BLUE,
      POLYCHROMA_DARK_FILLS.PURPLE,
      POLYCHROMA_DARK_FILLS.MAGENTA,
      POLYCHROMA_DARK_FILLS.PINK,
      POLYCHROMA_DARK_FILLS.RED,
      POLYCHROMA_DARK_FILLS.ORANGE,
      POLYCHROMA_DARK_FILLS.YELLOW,
      POLYCHROMA_DARK_FILLS.GREEN
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [POLYCHROMA_DARK_FILLS.BLUE, POLYCHROMA_DARK_FILLS.RED]);
    params.set(DEFAULT_ANNOTATION_COLOR, POLYCHROMA_DARK_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, POLYCHROMA_DARK_FILLS.BLUE);
    return params;
  }
};
var POLYCHROMA_LIGHT_FILLS = {
  BLUE: "#436ff4",
  PURPLE: "#9a7bff",
  MAGENTA: "#d165d2",
  PINK: "#f0598b",
  RED: "#f47348",
  ORANGE: "#f2a602",
  YELLOW: "#e9e201",
  GREEN: "#21b448",
  CYAN: "#00b9a2",
  MODERATE_BLUE: "#00aee4",
  GRAY: "#bbbbbb"
};
var POLYCHROMA_LIGHT_STROKES = {
  BLUE: "#2346c9",
  PURPLE: "#7653d4",
  MAGENTA: "#a73da9",
  PINK: "#c32d66",
  RED: "#c84b1c",
  ORANGE: "#c87f00",
  YELLOW: "#c1b900",
  GREEN: "#008c1c",
  CYAN: "#00927c",
  MODERATE_BLUE: "#0087bb",
  GRAY: "#888888"
};
var PolychromaLight = class extends ChartTheme {
  getDefaultColors() {
    return {
      fills: POLYCHROMA_LIGHT_FILLS,
      strokes: POLYCHROMA_LIGHT_STROKES,
      up: { fill: POLYCHROMA_LIGHT_FILLS.GREEN, stroke: POLYCHROMA_LIGHT_STROKES.GREEN },
      down: { fill: POLYCHROMA_LIGHT_FILLS.RED, stroke: POLYCHROMA_LIGHT_STROKES.RED },
      neutral: { fill: POLYCHROMA_LIGHT_FILLS.GRAY, stroke: POLYCHROMA_LIGHT_STROKES.GRAY },
      altUp: { fill: POLYCHROMA_LIGHT_FILLS.BLUE, stroke: POLYCHROMA_LIGHT_STROKES.BLUE },
      altDown: { fill: POLYCHROMA_LIGHT_FILLS.RED, stroke: POLYCHROMA_LIGHT_STROKES.RED },
      altNeutral: { fill: POLYCHROMA_LIGHT_FILLS.GRAY, stroke: POLYCHROMA_LIGHT_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [POLYCHROMA_LIGHT_FILLS.BLUE, POLYCHROMA_LIGHT_FILLS.RED]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      POLYCHROMA_LIGHT_FILLS.BLUE,
      POLYCHROMA_LIGHT_FILLS.PURPLE,
      POLYCHROMA_LIGHT_FILLS.MAGENTA,
      POLYCHROMA_LIGHT_FILLS.PINK,
      POLYCHROMA_LIGHT_FILLS.RED,
      POLYCHROMA_LIGHT_FILLS.ORANGE,
      POLYCHROMA_LIGHT_FILLS.YELLOW,
      POLYCHROMA_LIGHT_FILLS.GREEN
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [POLYCHROMA_LIGHT_FILLS.BLUE, POLYCHROMA_LIGHT_FILLS.RED]);
    params.set(DEFAULT_ANNOTATION_COLOR, POLYCHROMA_LIGHT_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, POLYCHROMA_LIGHT_FILLS.BLUE);
    return params;
  }
};
var SHEETS_DARK_FILLS = {
  BLUE: "#4472C4",
  ORANGE: "#ED7D31",
  GRAY: "#A5A5A5",
  YELLOW: "#FFC000",
  MODERATE_BLUE: "#5B9BD5",
  GREEN: "#70AD47",
  DARK_GRAY: "#7B7B7B",
  DARK_BLUE: "#264478",
  VERY_DARK_GRAY: "#636363",
  DARK_YELLOW: "#997300"
};
var SHEETS_DARK_STROKES = {
  BLUE: "#6899ee",
  ORANGE: "#ffa55d",
  GRAY: "#cdcdcd",
  YELLOW: "#ffea53",
  MODERATE_BLUE: "#82c3ff",
  GREEN: "#96d56f",
  DARK_GRAY: "#a1a1a1",
  DARK_BLUE: "#47689f",
  VERY_DARK_GRAY: "#878787",
  DARK_YELLOW: "#c0993d"
};
var SheetsDark = class extends DarkTheme {
  getDefaultColors() {
    return {
      fills: { ...SHEETS_DARK_FILLS, RED: SHEETS_DARK_FILLS.ORANGE },
      strokes: { ...SHEETS_DARK_STROKES, RED: SHEETS_DARK_STROKES.ORANGE },
      up: { fill: SHEETS_DARK_FILLS.GREEN, stroke: SHEETS_DARK_STROKES.GREEN },
      down: { fill: SHEETS_DARK_FILLS.ORANGE, stroke: SHEETS_DARK_STROKES.ORANGE },
      neutral: { fill: SHEETS_DARK_FILLS.GRAY, stroke: SHEETS_DARK_STROKES.GRAY },
      altUp: { fill: SHEETS_DARK_FILLS.BLUE, stroke: SHEETS_DARK_STROKES.BLUE },
      altDown: { fill: SHEETS_DARK_FILLS.ORANGE, stroke: SHEETS_DARK_STROKES.ORANGE },
      altNeutral: { fill: SHEETS_DARK_FILLS.GRAY, stroke: SHEETS_DARK_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      SHEETS_DARK_FILLS.ORANGE,
      SHEETS_DARK_FILLS.YELLOW,
      SHEETS_DARK_FILLS.GREEN
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [
      SHEETS_DARK_FILLS.GREEN,
      SHEETS_DARK_FILLS.YELLOW,
      SHEETS_DARK_FILLS.ORANGE
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, SHEETS_DARK_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, SHEETS_DARK_FILLS.BLUE);
    return params;
  }
};
var SHEETS_LIGHT_FILLS = {
  BLUE: "#5281d5",
  ORANGE: "#ff8d44",
  GRAY: "#b5b5b5",
  YELLOW: "#ffd02f",
  MODERATE_BLUE: "#6aabe6",
  GREEN: "#7fbd57",
  DARK_GRAY: "#8a8a8a",
  DARK_BLUE: "#335287",
  VERY_DARK_GRAY: "#717171",
  DARK_YELLOW: "#a98220"
};
var SHEETS_LIGHT_STROKES = {
  BLUE: "#214d9b",
  ORANGE: "#c25600",
  GRAY: "#7f7f7f",
  YELLOW: "#d59800",
  MODERATE_BLUE: "#3575ac",
  GREEN: "#4b861a",
  DARK_GRAY: "#575757",
  DARK_BLUE: "#062253",
  VERY_DARK_GRAY: "#414141",
  DARK_YELLOW: "#734f00"
};
var SheetsLight = class extends ChartTheme {
  getDefaultColors() {
    return {
      fills: { ...SHEETS_LIGHT_FILLS, RED: SHEETS_LIGHT_FILLS.ORANGE },
      strokes: { ...SHEETS_LIGHT_STROKES, RED: SHEETS_LIGHT_STROKES.ORANGE },
      up: { fill: SHEETS_LIGHT_FILLS.GREEN, stroke: SHEETS_LIGHT_STROKES.GREEN },
      down: { fill: SHEETS_LIGHT_FILLS.ORANGE, stroke: SHEETS_LIGHT_STROKES.ORANGE },
      neutral: { fill: SHEETS_LIGHT_STROKES.GRAY, stroke: SHEETS_LIGHT_STROKES.GRAY },
      altUp: { fill: SHEETS_LIGHT_FILLS.BLUE, stroke: SHEETS_LIGHT_STROKES.BLUE },
      altDown: { fill: SHEETS_LIGHT_FILLS.ORANGE, stroke: SHEETS_LIGHT_STROKES.ORANGE },
      altNeutral: { fill: SHEETS_LIGHT_FILLS.GRAY, stroke: SHEETS_LIGHT_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      SHEETS_LIGHT_FILLS.ORANGE,
      SHEETS_LIGHT_FILLS.YELLOW,
      SHEETS_LIGHT_FILLS.GREEN
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [
      SHEETS_LIGHT_FILLS.GREEN,
      SHEETS_LIGHT_FILLS.YELLOW,
      SHEETS_LIGHT_FILLS.ORANGE
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, SHEETS_LIGHT_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, SHEETS_LIGHT_FILLS.BLUE);
    return params;
  }
};
var VIVID_DARK_FILLS = {
  BLUE: "#0083ff",
  ORANGE: "#ff6600",
  GREEN: "#00af00",
  CYAN: "#00ccff",
  YELLOW: "#f7c700",
  VIOLET: "#ac26ff",
  GRAY: "#a7a7b7",
  MAGENTA: "#e800c5",
  BROWN: "#b54300",
  RED: "#ff0000"
};
var VIVID_DARK_STROKES = {
  BLUE: "#67b7ff",
  ORANGE: "#ffc24d",
  GREEN: "#5cc86f",
  CYAN: "#54ebff",
  VIOLET: "#fff653",
  YELLOW: "#c18aff",
  GRAY: "#aeaeae",
  MAGENTA: "#f078d4",
  BROWN: "#ba8438",
  RED: "#ff726e"
};
var VividDark = class extends DarkTheme {
  getDefaultColors() {
    return {
      fills: VIVID_DARK_FILLS,
      strokes: VIVID_DARK_STROKES,
      up: { fill: VIVID_DARK_FILLS.GREEN, stroke: VIVID_DARK_STROKES.GREEN },
      down: { fill: VIVID_DARK_FILLS.RED, stroke: VIVID_DARK_STROKES.RED },
      neutral: { fill: VIVID_DARK_FILLS.GRAY, stroke: VIVID_DARK_STROKES.GRAY },
      altUp: { fill: VIVID_DARK_FILLS.BLUE, stroke: VIVID_DARK_STROKES.BLUE },
      altDown: { fill: VIVID_DARK_FILLS.ORANGE, stroke: VIVID_DARK_STROKES.ORANGE },
      altNeutral: { fill: VIVID_DARK_FILLS.GRAY, stroke: VIVID_DARK_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [
      VIVID_DARK_FILLS.ORANGE,
      VIVID_DARK_FILLS.YELLOW,
      VIVID_DARK_FILLS.GREEN
    ]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      "#0083ff",
      "#0076e6",
      "#0069cc",
      "#005cb3",
      "#004f99",
      "#004280",
      "#003466",
      "#00274c"
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [
      VIVID_DARK_FILLS.GREEN,
      VIVID_DARK_FILLS.YELLOW,
      VIVID_DARK_FILLS.RED
    ]);
    params.set(DEFAULT_ANNOTATION_COLOR, VIVID_DARK_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, VIVID_DARK_FILLS.BLUE);
    return params;
  }
};
var VIVID_FILLS = {
  BLUE: "#0083ff",
  ORANGE: "#ff6600",
  GREEN: "#00af00",
  CYAN: "#00ccff",
  YELLOW: "#f7c700",
  VIOLET: "#ac26ff",
  GRAY: "#a7a7b7",
  MAGENTA: "#e800c5",
  BROWN: "#b54300",
  RED: "#ff0000"
};
var VIVID_STROKES = {
  BLUE: "#0f68c0",
  ORANGE: "#d47100",
  GREEN: "#007922",
  CYAN: "#009ac2",
  VIOLET: "#bca400",
  YELLOW: "#753cac",
  GRAY: "#646464",
  MAGENTA: "#9b2685",
  BROWN: "#6c3b00",
  RED: "#cb0021"
};
var VividLight = class extends ChartTheme {
  getDefaultColors() {
    return {
      fills: VIVID_FILLS,
      strokes: VIVID_STROKES,
      up: { fill: VIVID_FILLS.GREEN, stroke: VIVID_STROKES.GREEN },
      down: { fill: VIVID_FILLS.RED, stroke: VIVID_STROKES.RED },
      neutral: { fill: VIVID_FILLS.GRAY, stroke: VIVID_STROKES.GRAY },
      altUp: { fill: VIVID_FILLS.BLUE, stroke: VIVID_STROKES.BLUE },
      altDown: { fill: VIVID_FILLS.ORANGE, stroke: VIVID_STROKES.ORANGE },
      altNeutral: { fill: VIVID_FILLS.GRAY, stroke: VIVID_STROKES.GRAY }
    };
  }
  getTemplateParameters() {
    const params = super.getTemplateParameters();
    params.set(DEFAULT_DIVERGING_SERIES_COLOR_RANGE, [VIVID_FILLS.ORANGE, VIVID_FILLS.YELLOW, VIVID_FILLS.GREEN]);
    params.set(DEFAULT_FUNNEL_SERIES_COLOR_RANGE, [
      "#0083ff",
      "#1a8fff",
      "#339cff",
      "#4da8ff",
      "#66b5ff",
      "#80c1ff",
      "#99cdff",
      "#b3daff"
    ]);
    params.set(DEFAULT_GAUGE_SERIES_COLOR_RANGE, [VIVID_FILLS.GREEN, VIVID_FILLS.YELLOW, VIVID_FILLS.RED]);
    params.set(DEFAULT_ANNOTATION_COLOR, VIVID_FILLS.BLUE);
    params.set(DEFAULT_ANNOTATION_BACKGROUND_FILL, VIVID_FILLS.BLUE);
    return params;
  }
};
var lightTheme = simpleMemorize(() => new ChartTheme());
var darkTheme = simpleMemorize(() => new DarkTheme());
var themes = {
  // darkThemes,
  "ag-default-dark": darkTheme,
  "ag-sheets-dark": simpleMemorize(() => new SheetsDark()),
  "ag-polychroma-dark": simpleMemorize(() => new PolychromaDark()),
  "ag-vivid-dark": simpleMemorize(() => new VividDark()),
  "ag-material-dark": simpleMemorize(() => new MaterialDark()),
  "ag-financial-dark": simpleMemorize(() => new FinancialDark()),
  // lightThemes,
  null: lightTheme,
  undefined: lightTheme,
  "ag-default": lightTheme,
  "ag-sheets": simpleMemorize(() => new SheetsLight()),
  "ag-polychroma": simpleMemorize(() => new PolychromaLight()),
  "ag-vivid": simpleMemorize(() => new VividLight()),
  "ag-material": simpleMemorize(() => new MaterialLight()),
  "ag-financial": simpleMemorize(() => new FinancialLight())
};
var getChartTheme = simpleMemorize(createChartTheme);
function createChartTheme(value) {
  if (value instanceof ChartTheme) {
    return value;
  }
  if (value == null || typeof value === "string") {
    const stockTheme = themes[value];
    if (stockTheme) {
      return stockTheme();
    }
    Logger.warnOnce(`the theme [${value}] is invalid, using [ag-default] instead.`);
    return lightTheme();
  }
  if (isValid(value, themeOptionsDef, "theme")) {
    const flattenedTheme = reduceThemeOptions(value);
    const baseTheme = flattenedTheme.baseTheme ? getChartTheme(flattenedTheme.baseTheme) : lightTheme();
    return new baseTheme.constructor(flattenedTheme);
  }
  return lightTheme();
}
function reduceThemeOptions(options) {
  let maybeNested = options;
  let palette;
  const overrides = [];
  while (typeof maybeNested === "object") {
    palette ?? (palette = maybeNested.palette);
    if (maybeNested.overrides) {
      overrides.push(maybeNested.overrides);
    }
    maybeNested = maybeNested.baseTheme;
  }
  return {
    baseTheme: maybeNested,
    overrides: mergeDefaults(...overrides),
    palette
  };
}
var themeOptionsDef = {
  baseTheme: or(string, object),
  overrides: object,
  palette: {
    fills: arrayOf(string),
    strokes: arrayOf(string),
    up: { fill: string, stroke: string },
    down: { fill: string, stroke: string },
    neutral: { fill: string, stroke: string }
  }
};
var unthemedSeries = /* @__PURE__ */ new Set(["map-shape-background", "map-line-background"]);
var _ChartOptions = class _ChartOptions2 {
  constructor(userOptions, processedOverrides, specialOverrides, metadata, deltaOptions) {
    this.debug = Debug.create(true, "opts");
    this.optionMetadata = metadata ?? {};
    this.processedOverrides = processedOverrides ?? {};
    let baseChartOptions = null;
    if (userOptions instanceof _ChartOptions2) {
      baseChartOptions = userOptions;
      this.specialOverrides = baseChartOptions.specialOverrides;
      if (!deltaOptions)
        throw new Error("AG Charts - internal error: deltaOptions must be supplied.");
      this.userOptions = mergeDefaults(
        deltaOptions,
        deepClone(baseChartOptions.userOptions, _ChartOptions2.OPTIONS_CLONE_OPTS)
      );
    } else {
      this.userOptions = userOptions;
      this.specialOverrides = this.specialOverridesDefaults({ ...specialOverrides });
    }
    let activeTheme, processedOptions, defaultAxes, fastDelta;
    if (deltaOptions != null && _ChartOptions2.isFastPathDelta(deltaOptions) && baseChartOptions != null) {
      ({ activeTheme, processedOptions, defaultAxes, fastDelta } = this.fastSetup(
        deltaOptions,
        baseChartOptions
      ));
    } else {
      ({ activeTheme, processedOptions, defaultAxes } = this.slowSetup(processedOverrides, deltaOptions));
    }
    this.activeTheme = activeTheme;
    this.processedOptions = processedOptions;
    this.defaultAxes = defaultAxes;
    this.fastDelta = fastDelta;
  }
  static isFastPathDelta(deltaOptions) {
    for (const key of Object.keys(deltaOptions)) {
      if (!this.FAST_PATH_OPTIONS.has(key))
        return false;
    }
    return true;
  }
  fastSetup(deltaOptions, baseChartOptions) {
    const { activeTheme, defaultAxes, processedOptions: baseOptions } = baseChartOptions;
    const { presetType } = this.optionMetadata;
    const processor = presetType ? PRESET_DATA_PROCESSORS[presetType] : void 0;
    if (presetType != null && deltaOptions.data != null && processor != null) {
      deltaOptions = mergeDefaults(processor(deltaOptions.data), deltaOptions);
    }
    this.fastSeriesSetup(deltaOptions, baseOptions);
    const processedOptions = mergeDefaults(deltaOptions, baseOptions);
    return { activeTheme, defaultAxes, processedOptions, fastDelta: deltaOptions };
  }
  fastSeriesSetup(deltaOptions, baseOptions) {
    if (!deltaOptions.series)
      return;
    if (deltaOptions.series?.every((s, i) => jsonPropertyCompare(s, baseOptions.series?.[i] ?? {}))) {
      delete deltaOptions["series"];
    } else {
      deltaOptions.series = deltaOptions.series.map((s, i) => {
        return mergeDefaults(s, baseOptions.series?.[i] ?? {});
      });
    }
  }
  slowSetup(processedOverrides, deltaOptions) {
    let options = deepClone(this.userOptions, _ChartOptions2.OPTIONS_CLONE_OPTS);
    if (deltaOptions) {
      options = mergeDefaults(deltaOptions, options);
    }
    const { presetType } = this.optionMetadata;
    if (presetType != null) {
      const presetConstructor = PRESETS[presetType];
      const presetParams = this.userOptions;
      const presetSubType = this.userOptions.type;
      const presetTheme = presetSubType != null ? getChartTheme(this.userOptions.theme).presets[presetSubType] : void 0;
      this.debug(">>> AgCharts.createOrUpdate() - applying preset", presetParams);
      options = presetConstructor?.(presetParams, presetTheme, () => this.activeTheme) ?? options;
    }
    if (!enterpriseModule.isEnterprise) {
      removeUsedEnterpriseOptions(options);
    }
    const activeTheme = getChartTheme(options.theme);
    this.sanityCheck(options);
    this.removeDisabledOptions(options);
    const defaultAxes = this.getDefaultAxes(options);
    const chartType2 = this.optionsType(options);
    const {
      axes: axesThemes = {},
      annotations = {},
      series: _,
      ...themeDefaults
    } = this.getSeriesThemeConfig(chartType2, activeTheme);
    const [annotationsOptions, annotationsThemes] = this.splitAnnotationsOptions(annotations);
    let processedOptions = mergeDefaults(
      processedOverrides,
      options,
      annotationsOptions,
      themeDefaults,
      defaultAxes
    );
    this.processAxesOptions(processedOptions, axesThemes);
    this.processSeriesOptions(processedOptions, activeTheme);
    this.processMiniChartSeriesOptions(processedOptions, activeTheme);
    this.annotationThemes = annotationsThemes;
    processedOptions = deepClone(processedOptions, _ChartOptions2.OPTIONS_CLONE_OPTS);
    if ((isAgCartesianChartOptions(processedOptions) || isAgStandaloneChartOptions(processedOptions) || isAgPolarChartOptionsWithSeriesBasedLegend(processedOptions)) && processedOptions.legend?.enabled == null) {
      processedOptions.legend ?? (processedOptions.legend = {});
      processedOptions.legend.enabled = processedOptions.series.length > 1;
    }
    this.enableConfiguredOptions(processedOptions, this.userOptions);
    activeTheme.templateTheme(processedOptions, false);
    this.removeDisabledOptions(options);
    removeUnusedEnterpriseOptions(processedOptions);
    if (!enterpriseModule.isEnterprise) {
      removeUsedEnterpriseOptions(processedOptions, true);
    }
    this.debug("AgCharts.createOrUpdate() - processed options", processedOptions);
    return { activeTheme, processedOptions, defaultAxes };
  }
  diffOptions(other) {
    if (this === other)
      return {};
    if (other == null)
      return this.processedOptions;
    return this.fastDelta ?? jsonDiff(other.processedOptions, this.processedOptions);
  }
  getSeriesThemeConfig(seriesType, activeTheme) {
    return activeTheme?.config[seriesType] ?? {};
  }
  getDefaultAxes(options) {
    const optionsType2 = this.optionsType(options);
    const firstSeriesOptions = options.series?.find((series) => (series.type ?? "line") === optionsType2) ?? {};
    return seriesRegistry.cloneDefaultAxes(optionsType2, firstSeriesOptions);
  }
  optionsType(options) {
    return options.series?.[0]?.type ?? "line";
  }
  sanityCheck(options) {
    this.axesTypeIntegrity(options);
    this.seriesTypeIntegrity(options);
    this.soloSeriesIntegrity(options);
  }
  splitAnnotationsOptions(annotations) {
    const {
      axesButtons = null,
      enabled = null,
      optionsToolbar = null,
      toolbar = null,
      ...annotationsThemes
    } = annotations;
    if (axesButtons == null && enabled == null && optionsToolbar == null && toolbar == null) {
      return [{}, annotationsThemes];
    }
    return [{ annotations: { axesButtons, enabled, optionsToolbar, toolbar } }, annotationsThemes];
  }
  processAxesOptions(options, axesThemes) {
    if (!("axes" in options))
      return;
    options.axes = options.axes?.map((axis) => {
      const { crossLines: crossLinesTheme, ...axisTheme } = mergeDefaults(
        axesThemes[axis.type]?.[axis.position],
        axesThemes[axis.type]
      );
      if (axis.crossLines) {
        axis.crossLines = mergeArrayDefaults(axis.crossLines, crossLinesTheme);
      }
      const gridLineStyle = axisTheme.gridLine?.style;
      if (axis.gridLine?.style && gridLineStyle?.length) {
        axis.gridLine.style = axis.gridLine.style.map(
          (style, index) => style.stroke != null || style.lineDash != null ? mergeDefaults(style, gridLineStyle.at(index % gridLineStyle.length)) : style
        );
      }
      const { top: _1, right: _2, bottom: _3, left: _4, ...axisOptions } = mergeDefaults(axis, axisTheme);
      return axisOptions;
    });
  }
  processSeriesOptions(options, activeTheme) {
    const defaultTooltipPosition = this.getTooltipPositionDefaults(options);
    const userPalette = isObject(options.theme) ? paletteType(options.theme?.palette) : "inbuilt";
    const paletteOptions = {
      colourIndex: 0,
      userPalette
    };
    const processedSeries = options.series?.map((series) => {
      series.type ?? (series.type = this.getDefaultSeriesType(options));
      const { innerLabels: innerLabelsTheme, ...seriesTheme } = this.getSeriesThemeConfig(series.type, activeTheme).series ?? {};
      const seriesPaletteOptions = unthemedSeries.has(series.type) ? { colourIndex: 0, userPalette } : paletteOptions;
      const palette = this.getSeriesPalette(series.type, seriesPaletteOptions, activeTheme);
      const defaultTooltipRange = this.getTooltipRangeDefaults(options, series.type);
      const seriesOptions = mergeDefaults(
        this.getSeriesGroupingOptions(series),
        series,
        defaultTooltipPosition,
        defaultTooltipRange,
        seriesTheme,
        palette,
        { visible: true }
      );
      if (seriesOptions.innerLabels) {
        seriesOptions.innerLabels = mergeArrayDefaults(seriesOptions.innerLabels, innerLabelsTheme);
      }
      return seriesOptions;
    });
    options.series = this.setSeriesGroupingOptions(processedSeries ?? []);
  }
  processMiniChartSeriesOptions(options, activeTheme) {
    let miniChartSeries = options.navigator?.miniChart?.series;
    if (miniChartSeries == null)
      return;
    const paletteOptions = {
      colourIndex: 0,
      userPalette: isObject(options.theme) ? paletteType(options.theme.palette) : "inbuilt"
    };
    miniChartSeries = miniChartSeries.map((series) => {
      series.type ?? (series.type = "line");
      const { innerLabels: _, ...seriesTheme } = this.getSeriesThemeConfig(series.type, activeTheme).series ?? {};
      return mergeDefaults(
        this.getSeriesGroupingOptions(series),
        series,
        seriesTheme,
        this.getSeriesPalette(series.type, paletteOptions, activeTheme)
      );
    });
    options.navigator.miniChart.series = this.setSeriesGroupingOptions(miniChartSeries);
  }
  getSeriesPalette(seriesType, options, activeTheme) {
    const paletteFactory = seriesRegistry.getPaletteFactory(seriesType);
    const { colourIndex: colourOffset, userPalette } = options;
    const { fills = [], strokes = [] } = activeTheme.palette;
    return paletteFactory?.({
      userPalette,
      colorsCount: Math.max(fills.length, strokes.length),
      themeTemplateParameters: activeTheme.getTemplateParameters(),
      palette: activeTheme.palette,
      takeColors(count) {
        options.colourIndex += count;
        return {
          fills: circularSliceArray(fills, count, colourOffset),
          strokes: circularSliceArray(strokes, count, colourOffset)
        };
      }
    });
  }
  getSeriesGroupingOptions(series) {
    const groupable = seriesRegistry.isGroupable(series.type);
    const stackable = seriesRegistry.isStackable(series.type);
    const stackedByDefault = seriesRegistry.isStackedByDefault(series.type);
    if (series.grouped && !groupable) {
      Logger.warnOnce(`unsupported grouping of series type "${series.type}".`);
    }
    if ((series.stacked || series.stackGroup) && !stackable) {
      Logger.warnOnce(`unsupported stacking of series type "${series.type}".`);
    }
    let { grouped, stacked } = series;
    stacked ?? (stacked = (stackedByDefault || series.stackGroup != null) && !(groupable && grouped));
    grouped ?? (grouped = true);
    return {
      stacked: stackable && stacked,
      grouped: groupable && grouped && !(stackable && stacked)
    };
  }
  setSeriesGroupingOptions(allSeries) {
    const seriesGroups = this.getSeriesGrouping(allSeries);
    this.debug("setSeriesGroupingOptions() - series grouping: ", seriesGroups);
    const groupIdx = {};
    const groupCount2 = seriesGroups.reduce((countMap, seriesGroup) => {
      var _a;
      if (seriesGroup.groupType === "default") {
        return countMap;
      }
      countMap[_a = seriesGroup.seriesType] ?? (countMap[_a] = 0);
      countMap[seriesGroup.seriesType] += seriesGroup.groupType === "stack" ? 1 : seriesGroup.series.length;
      return countMap;
    }, {});
    return seriesGroups.flatMap((seriesGroup) => {
      var _a;
      groupIdx[_a = seriesGroup.seriesType] ?? (groupIdx[_a] = 0);
      switch (seriesGroup.groupType) {
        case "stack": {
          const groupIndex = groupIdx[seriesGroup.seriesType]++;
          return seriesGroup.series.map(
            (series, stackIndex) => Object.assign(series, {
              seriesGrouping: {
                groupId: seriesGroup.groupId,
                groupIndex,
                groupCount: groupCount2[seriesGroup.seriesType],
                stackIndex,
                stackCount: seriesGroup.series.length
              }
            })
          );
        }
        case "group":
          return seriesGroup.series.map(
            (series) => Object.assign(series, {
              seriesGrouping: {
                groupId: seriesGroup.groupId,
                groupIndex: groupIdx[seriesGroup.seriesType]++,
                groupCount: groupCount2[seriesGroup.seriesType],
                stackIndex: 0,
                stackCount: 0
              }
            })
          );
      }
      return seriesGroup.series;
    }).map(({ stacked: _, grouped: __, ...seriesOptions }) => seriesOptions);
  }
  getSeriesGroupId(series) {
    return [series.type, series.xKey, series.stacked ? series.stackGroup ?? "stacked" : "grouped"].filter(Boolean).join("-");
  }
  getSeriesGrouping(allSeries) {
    const groupMap = /* @__PURE__ */ new Map();
    return allSeries.reduce((result, series) => {
      const seriesType = series.type;
      if (!series.stacked && !series.grouped) {
        result.push({ groupType: "default", seriesType, series: [series], groupId: "__default__" });
      } else {
        const groupId = this.getSeriesGroupId(series);
        if (!groupMap.has(groupId)) {
          const groupType = series.stacked ? "stack" : "group";
          const record = { groupType, seriesType, series: [], groupId };
          groupMap.set(groupId, record);
          result.push(record);
        }
        groupMap.get(groupId).series.push(series);
      }
      return result;
    }, []);
  }
  getDefaultSeriesType(options) {
    if (isAgCartesianChartOptions(options)) {
      return "line";
    } else if (isAgPolarChartOptions(options)) {
      return "pie";
    } else if (isAgHierarchyChartOptions(options)) {
      return "treemap";
    } else if (isAgTopologyChartOptions(options)) {
      return "map-shape";
    } else if (isAgFlowProportionChartOptions(options)) {
      return "sankey";
    } else if (isAgStandaloneChartOptions(options)) {
      return "pyramid";
    } else if (isAgGaugeChartOptions(options)) {
      return "radial-gauge";
    }
    throw new Error("Invalid chart options type detected.");
  }
  getTooltipPositionDefaults(options) {
    const position = options.tooltip?.position;
    if (!isPlainObject(position)) {
      return;
    }
    const { type, xOffset, yOffset } = position;
    const result = {};
    if (isString(type) && isEnumValue(AgTooltipPositionType, type)) {
      result.type = type;
    }
    if (isFiniteNumber(xOffset)) {
      result.xOffset = xOffset;
    }
    if (isFiniteNumber(yOffset)) {
      result.yOffset = yOffset;
    }
    return { tooltip: { position: result } };
  }
  // AG-11591 Support for new series-specific & legacy chart-global 'tooltip.range' options
  //
  // The `chart.series[].tooltip.range` option is a bit different for legacy reason. This use to be
  // global option (`chart.tooltip.range`) that could override the theme. But now, the tooltip range
  // option is series-specific.
  //
  // To preserve backward compatibility, the `chart.tooltip.range` theme default has been changed from
  // 'nearest' to undefined.
  getTooltipRangeDefaults(options, seriesType) {
    return {
      tooltip: {
        range: options.tooltip?.range ?? seriesRegistry.getTooltipDefauls(seriesType)?.range
      }
    };
  }
  axesTypeIntegrity(options) {
    if ("axes" in options && options.axes) {
      const axes = options.axes;
      for (const { type } of axes) {
        if (!isAxisOptionType(type)) {
          delete options.axes;
          const expectedTypes = axisRegistry.publicKeys().join(", ");
          Logger.warnOnce(`unknown axis type: ${type}; expected one of: ${expectedTypes}`);
        }
      }
    }
  }
  seriesTypeIntegrity(options) {
    options.series = options.series?.filter(({ type }) => {
      if (type == null || isSeriesOptionType(type) || isEnterpriseSeriesType(type)) {
        return true;
      }
      Logger.warnOnce(
        `unknown series type: ${JSON.stringify(type)}; expected one of: ${publicChartTypes.seriesTypes.join(", ")}`
      );
    });
  }
  soloSeriesIntegrity(options) {
    const allSeries = options.series;
    if (allSeries && allSeries.length > 1 && allSeries.some((series) => seriesRegistry.isSolo(series.type))) {
      const mainSeriesType = this.optionsType(options);
      if (seriesRegistry.isSolo(mainSeriesType)) {
        Logger.warn(
          `series[0] of type '${mainSeriesType}' is incompatible with other series types. Only processing series[0]`
        );
        options.series = allSeries.slice(0, 1);
      } else {
        const { solo, nonSolo } = groupBy(
          allSeries,
          (s) => seriesRegistry.isSolo(s.type) ? "solo" : "nonSolo"
        );
        const rejects = unique(solo.map((s) => s.type)).join(", ");
        Logger.warn(`Unable to mix these series types with the lead series type: ${rejects}`);
        options.series = nonSolo;
      }
    }
  }
  static enableConfiguredJsonOptions(visitingUserOpts, visitingMergedOpts) {
    if (visitingMergedOpts && "enabled" in visitingMergedOpts && !visitingMergedOpts._enabledFromTheme && visitingUserOpts.enabled == null) {
      visitingMergedOpts.enabled = true;
    }
  }
  static cleanupEnabledFromThemeJsonOptions(visitingMergedOpts) {
    if (visitingMergedOpts._enabledFromTheme != null) {
      delete visitingMergedOpts._enabledFromTheme;
    }
  }
  enableConfiguredOptions(options, userOptions) {
    jsonWalk(userOptions, _ChartOptions2.enableConfiguredJsonOptions, /* @__PURE__ */ new Set(["data", "theme"]), options);
    jsonWalk(options, _ChartOptions2.cleanupEnabledFromThemeJsonOptions, /* @__PURE__ */ new Set(["data", "theme"]));
  }
  static removeDisabledOptionJson(optionsNode) {
    if ("enabled" in optionsNode && optionsNode.enabled === false) {
      Object.keys(optionsNode).forEach((key) => {
        if (key === "enabled")
          return;
        delete optionsNode[key];
      });
    }
  }
  removeDisabledOptions(options) {
    jsonWalk(options, _ChartOptions2.removeDisabledOptionJson, /* @__PURE__ */ new Set(["data", "theme"]));
  }
  specialOverridesDefaults(options) {
    if (options.window != null) {
      setWindow(options.window);
    } else if (typeof window !== "undefined") {
      options.window = window;
    } else if (typeof global !== "undefined") {
      options.window = global.window;
    }
    if (options.document != null) {
      setDocument(options.document);
    } else if (typeof document !== "undefined") {
      options.document = document;
    } else if (typeof global !== "undefined") {
      options.document = global.document;
    }
    if (options.window == null) {
      throw new Error("AG Charts - unable to resolve global window");
    }
    if (options.document == null) {
      throw new Error("AG Charts - unable to resolve global document");
    }
    return options;
  }
};
_ChartOptions.OPTIONS_CLONE_OPTS = /* @__PURE__ */ new Set(["data", "container"]);
_ChartOptions.FAST_PATH_OPTIONS = /* @__PURE__ */ new Set(["data", "width", "height"]);
var ChartOptions = _ChartOptions;
var CLEANUP_TIMEOUT_MS = 100;
var _Pool = class _Pool2 {
  constructor(name, buildItem, releaseItem, destroyItem, maxPoolSize, cleanupTimeMs = CLEANUP_TIMEOUT_MS) {
    this.name = name;
    this.buildItem = buildItem;
    this.releaseItem = releaseItem;
    this.destroyItem = destroyItem;
    this.maxPoolSize = maxPoolSize;
    this.cleanupTimeMs = cleanupTimeMs;
    this.freePool = [];
    this.busyPool = /* @__PURE__ */ new Set();
  }
  static getPool(name, buildItem, releaseItem, destroyItem, maxPoolSize) {
    if (!this.pools.has(name)) {
      this.pools.set(name, new _Pool2(name, buildItem, releaseItem, destroyItem, maxPoolSize));
    }
    return this.pools.get(name);
  }
  isFull() {
    return this.freePool.length + this.busyPool.size >= this.maxPoolSize;
  }
  obtain(params) {
    if (this.freePool.length === 0 && this.isFull()) {
      throw new Error("AG Charts - pool exhausted");
    }
    let nextFree = this.freePool.pop();
    if (nextFree == null) {
      nextFree = this.buildItem(params);
      _Pool2.debug(
        `Pool[name=${this.name}]: Created instance (${this.freePool.length} / ${this.busyPool.size + 1} / ${this.maxPoolSize})`,
        nextFree
      );
    } else {
      _Pool2.debug(
        `Pool[name=${this.name}]: Re-used instance (${this.freePool.length} / ${this.busyPool.size + 1} / ${this.maxPoolSize})`,
        nextFree
      );
    }
    this.busyPool.add(nextFree);
    return { item: nextFree, release: () => this.release(nextFree) };
  }
  release(item) {
    if (!this.busyPool.has(item)) {
      throw new Error("AG Charts - cannot free item from pool which is not tracked as busy.");
    }
    _Pool2.debug(
      `Pool[name=${this.name}]: Releasing instance (${this.freePool.length} / ${this.busyPool.size} / ${this.maxPoolSize})`,
      item
    );
    this.releaseItem(item);
    this.busyPool.delete(item);
    this.freePool.push(item);
    _Pool2.debug(
      `Pool[name=${this.name}]: Returned instance to free pool (${this.freePool.length} / ${this.busyPool.size} / ${this.maxPoolSize})`,
      item
    );
    if (this.cleanPoolTimer) {
      clearTimeout(this.cleanPoolTimer);
    }
    this.cleanPoolTimer = setTimeout(() => {
      this.cleanPool();
    }, this.cleanupTimeMs);
  }
  cleanPool() {
    const itemsToFree = this.freePool.splice(0);
    for (const item of itemsToFree) {
      this.destroyItem(item);
    }
    _Pool2.debug(
      `Pool[name=${this.name}]: Cleaned pool of ${itemsToFree.length} items (${this.freePool.length} / ${this.busyPool.size} / ${this.maxPoolSize})`
    );
  }
  destroy() {
    this.cleanPool();
    for (const item of this.busyPool.values()) {
      this.destroyItem(item);
    }
    this.busyPool.clear();
  }
};
_Pool.pools = /* @__PURE__ */ new Map();
_Pool.debug = Debug.create(true, "pool");
var Pool = _Pool;
var debug2 = Debug.create(true, "opts");
function chartType(options) {
  if (isAgCartesianChartOptions(options)) {
    return "cartesian";
  } else if (isAgPolarChartOptions(options)) {
    return "polar";
  } else if (isAgHierarchyChartOptions(options)) {
    return "hierarchy";
  } else if (isAgTopologyChartOptions(options)) {
    return "topology";
  } else if (isAgFlowProportionChartOptions(options)) {
    return "flow-proportion";
  } else if (isAgStandaloneChartOptions(options)) {
    return "standalone";
  } else if (isAgGaugeChartOptions(options)) {
    return "gauge";
  }
  throw new Error(`AG Chart - unknown type of chart for options with type: ${options.type}`);
}
var AgCharts = class {
  static licenseCheck(options) {
    if (this.licenseChecked)
      return;
    this.licenseManager = enterpriseModule.licenseManager?.(options);
    this.licenseManager?.validateLicense();
    this.licenseChecked = true;
  }
  static getLicenseDetails(licenseKey) {
    return enterpriseModule.licenseManager?.({}).getLicenseDetails(licenseKey);
  }
  /**
   * Returns the `AgChartInstance` for a DOM node, if there is one.
   */
  static getInstance(element2) {
    return AgChartsInternal.getInstance(element2);
  }
  /**
   * Create a new `AgChartInstance` based upon the given configuration options.
   */
  static create(userOptions, optionsMetadata) {
    this.licenseCheck(userOptions);
    const chart = AgChartsInternal.createOrUpdate({
      userOptions,
      licenseManager: this.licenseManager,
      optionsMetadata
    });
    if (this.licenseManager?.isDisplayWatermark() && this.licenseManager) {
      enterpriseModule.injectWatermark?.(chart.chart.ctx.domManager, this.licenseManager.getWatermarkMessage());
    }
    return chart;
  }
  static createFinancialChart(options) {
    return this.create(options, { presetType: "price-volume" });
  }
  static createGauge(options) {
    return this.create(options, { presetType: "gauge" });
  }
  static __createSparkline(options) {
    const { pool, ...normalOptions } = options;
    return this.create(normalOptions, { presetType: "sparkline", pool: pool ?? true });
  }
};
AgCharts.licenseChecked = false;
var _AgChartsInternal = class _AgChartsInternal2 {
  static getInstance(element2) {
    const chart = Chart.getInstance(element2);
    return chart ? AgChartInstanceProxy.chartInstances.get(chart) : void 0;
  }
  static initialiseModules() {
    if (_AgChartsInternal2.initialised)
      return;
    registerInbuiltModules();
    setupModules();
    _AgChartsInternal2.initialised = true;
  }
  static createOrUpdate(opts) {
    let { proxy } = opts;
    const {
      userOptions,
      licenseManager,
      processedOverrides = proxy?.chart.chartOptions.processedOverrides ?? {},
      specialOverrides = proxy?.chart.chartOptions.specialOverrides ?? {},
      optionsMetadata = proxy?.chart.chartOptions.optionMetadata ?? {},
      deltaOptions
    } = opts;
    const styles = enterpriseModule.styles != null ? [["ag-charts-enterprise", enterpriseModule.styles]] : [];
    const { presetType } = optionsMetadata;
    _AgChartsInternal2.initialiseModules();
    debug2(">>> AgCharts.createOrUpdate() user options", userOptions);
    let mutableOptions = userOptions;
    if (AgCharts.optionsMutationFn && mutableOptions) {
      mutableOptions = AgCharts.optionsMutationFn(deepClone(mutableOptions), presetType);
      debug2(">>> AgCharts.createOrUpdate() MUTATED user options", mutableOptions);
    }
    const {
      overrideDevicePixelRatio,
      document: document2,
      window: userWindow,
      styleContainer,
      ...options
    } = mutableOptions ?? {};
    const baseOptions = (deltaOptions ? proxy?.chart.getChartOptions() : options) ?? options;
    const chartOptions = new ChartOptions(
      baseOptions,
      processedOverrides,
      {
        ...specialOverrides,
        document: document2,
        window: userWindow,
        overrideDevicePixelRatio,
        styleContainer
      },
      optionsMetadata,
      deltaOptions
    );
    let create = false;
    let chart = proxy?.chart;
    let poolResult;
    if (chart == null || chartType(chartOptions.processedOptions) !== chartType(chart?.chartOptions.processedOptions)) {
      poolResult = this.getPool(chartOptions)?.obtain(chartOptions);
      if (poolResult) {
        chart = poolResult.item;
      } else {
        create = true;
        chart = _AgChartsInternal2.createChartInstance(chartOptions, chart);
      }
      styles?.forEach(([id, css]) => {
        chart?.ctx.domManager.addStyles(id, css);
      });
    }
    if (proxy == null) {
      proxy = new AgChartInstanceProxy(chart, _AgChartsInternal2.callbackApi, licenseManager);
      proxy.releaseChart = poolResult?.release;
    } else if (poolResult || create) {
      proxy.releaseChart?.();
      proxy.chart = chart;
      proxy.releaseChart = poolResult?.release;
    }
    if (debug2.check() && typeof window !== "undefined") {
      window.agChartInstances ?? (window.agChartInstances = {});
      window.agChartInstances[chart.id] = chart;
    }
    chart.queuedUserOptions.push(chartOptions.userOptions);
    chart.queuedChartOptions.push(chartOptions);
    chart.requestFactoryUpdate((chartRef) => {
      chartRef.applyOptions(chartOptions);
      const queueIdx = chartRef.queuedUserOptions.indexOf(chartOptions.userOptions) + 1;
      chartRef.queuedUserOptions.splice(0, queueIdx);
      chartRef.queuedChartOptions.splice(0, queueIdx);
    });
    return proxy;
  }
  static markRemovedProperties(node) {
    if (typeof node !== "object")
      return;
    for (const [key, value] of Object.entries(node)) {
      if (typeof value === "undefined") {
        Object.assign(node, { [key]: Symbol("UNSET") });
      }
    }
  }
  static updateUserDelta(proxy, deltaOptions) {
    deltaOptions = deepClone(deltaOptions, /* @__PURE__ */ new Set(["data"]));
    jsonWalk(deltaOptions, _AgChartsInternal2.markRemovedProperties, /* @__PURE__ */ new Set(["data"]));
    debug2(">>> AgCharts.updateUserDelta() user delta", deltaOptions);
    _AgChartsInternal2.createOrUpdate({ proxy, deltaOptions });
  }
  static createChartInstance(options, oldChart) {
    const transferableResource = oldChart?.destroy({ keepTransferableResources: true });
    const ChartConstructor = _AgChartsInternal2.getChartByOptions(options.processedOptions);
    return new ChartConstructor(options, transferableResource);
  }
  static getChartByOptions(options) {
    if (isAgCartesianChartOptions(options)) {
      return CartesianChart;
    } else if (isAgHierarchyChartOptions(options)) {
      return HierarchyChart;
    } else if (isAgPolarChartOptions(options)) {
      return PolarChart;
    } else if (isAgTopologyChartOptions(options)) {
      return TopologyChart;
    } else if (isAgFlowProportionChartOptions(options)) {
      return FlowProportionChart;
    } else if (isAgStandaloneChartOptions(options)) {
      return StandaloneChart;
    } else if (isAgGaugeChartOptions(options)) {
      return GaugeChart;
    }
    throw new Error(
      `AG Charts - couldn't apply configuration, check options are correctly structured and series types are specified`
    );
  }
  static getPool(options) {
    if (options.optionMetadata.pool !== true)
      return;
    return Pool.getPool(
      options.optionMetadata.presetType ?? "default",
      this.createChartInstance,
      this.detachAndClear,
      this.destroy,
      Infinity
      // AG-13480 - Prevent Grid exhausting pool during sorting.
    );
  }
};
_AgChartsInternal.caretaker = new MementoCaretaker(VERSION);
_AgChartsInternal.initialised = false;
_AgChartsInternal.callbackApi = {
  caretaker: _AgChartsInternal.caretaker,
  create(userOptions, processedOverrides, specialOverrides, optionsMetadata) {
    return _AgChartsInternal.createOrUpdate({
      userOptions,
      processedOverrides,
      specialOverrides,
      optionsMetadata
    });
  },
  update(opts, chart) {
    return _AgChartsInternal.createOrUpdate({ userOptions: opts, proxy: chart });
  },
  updateUserDelta(chart, deltaOptions) {
    return _AgChartsInternal.updateUserDelta(chart, deltaOptions);
  }
};
_AgChartsInternal.detachAndClear = (chart) => chart.detachAndClear();
_AgChartsInternal.destroy = (chart) => chart.destroy();
var AgChartsInternal = _AgChartsInternal;
var integrated_charts_scene_exports = {};
__export(integrated_charts_scene_exports, {
  Arc: () => Arc2,
  BBox: () => BBox,
  BandScale: () => BandScale,
  Caption: () => Caption,
  Circle: () => Circle,
  Group: () => Group,
  Line: () => Line,
  LinearScale: () => LinearScale,
  Path: () => Path,
  RadialColumnShape: () => RadialColumnShape,
  Rect: () => Rect,
  Scene: () => Scene,
  Sector: () => Sector,
  Shape: () => Shape,
  TranslatableGroup: () => TranslatableGroup,
  getRadialColumnWidth: () => getRadialColumnWidth,
  toRadians: () => toRadians
});
var Arc2 = class extends Path {
  constructor() {
    super();
    this.centerX = 0;
    this.centerY = 0;
    this.radius = 10;
    this.startAngle = 0;
    this.endAngle = Math.PI * 2;
    this.counterClockwise = false;
    this.type = 0;
    this.restoreOwnStyles();
  }
  get fullPie() {
    return isNumberEqual(normalizeAngle360(this.startAngle), normalizeAngle360(this.endAngle));
  }
  updatePath() {
    const path = this.path;
    path.clear();
    path.arc(this.centerX, this.centerY, this.radius, this.startAngle, this.endAngle, this.counterClockwise);
    if (this.type === 1) {
      path.closePath();
    } else if (this.type === 2 && !this.fullPie) {
      path.lineTo(this.centerX, this.centerY);
      path.closePath();
    }
  }
  computeBBox() {
    return new BBox(this.centerX - this.radius, this.centerY - this.radius, this.radius * 2, this.radius * 2);
  }
  isPointInPath(x, y) {
    const bbox = this.getBBox();
    return this.type !== 0 && bbox.containsPoint(x, y) && this.path.isPointInPath(x, y);
  }
};
Arc2.className = "Arc";
Arc2.defaultStyles = { ...Shape.defaultStyles, lineWidth: 1, fillStyle: null };
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "centerX", 2);
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "centerY", 2);
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "radius", 2);
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "startAngle", 2);
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "endAngle", 2);
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "counterClockwise", 2);
__decorateClass([
  ScenePathChangeDetection()
], Arc2.prototype, "type", 2);
function rotatePoint(x, y, rotation) {
  const radius = Math.sqrt(x ** 2 + y ** 2);
  const angle2 = Math.atan2(y, x);
  const rotated = angle2 + rotation;
  return {
    x: Math.cos(rotated) * radius,
    y: Math.sin(rotated) * radius
  };
}
var RadialColumnShape = class extends Path {
  constructor() {
    super(...arguments);
    this.isBeveled = true;
    this.columnWidth = 0;
    this.startAngle = 0;
    this.endAngle = 0;
    this.outerRadius = 0;
    this.innerRadius = 0;
    this.axisInnerRadius = 0;
    this.axisOuterRadius = 0;
    this.isRadiusAxisReversed = false;
  }
  set cornerRadius(_value) {
  }
  computeBBox() {
    const { innerRadius, outerRadius, columnWidth } = this;
    const rotation = this.getRotation();
    const left = -columnWidth / 2;
    const right = columnWidth / 2;
    const top = -outerRadius;
    const bottom = -innerRadius;
    let x0 = Infinity;
    let y0 = Infinity;
    let x1 = -Infinity;
    let y1 = -Infinity;
    for (let i = 0; i < 4; i += 1) {
      const { x, y } = rotatePoint(i % 2 === 0 ? left : right, i < 2 ? top : bottom, rotation);
      x0 = Math.min(x, x0);
      y0 = Math.min(y, y0);
      x1 = Math.max(x, x1);
      y1 = Math.max(y, y1);
    }
    return new BBox(x0, y0, x1 - x0, y1 - y0);
  }
  getRotation() {
    const { startAngle, endAngle } = this;
    const midAngle = angleBetween(startAngle, endAngle);
    return normalizeAngle360(startAngle + midAngle / 2 + Math.PI / 2);
  }
  updatePath() {
    const { isBeveled } = this;
    if (isBeveled) {
      this.updateBeveledPath();
    } else {
      this.updateRectangularPath();
    }
    this.checkPathDirty();
  }
  updateRectangularPath() {
    const { columnWidth, innerRadius, outerRadius, path } = this;
    const left = -columnWidth / 2;
    const right = columnWidth / 2;
    const top = -outerRadius;
    const bottom = -innerRadius;
    const rotation = this.getRotation();
    const points = [
      [left, bottom],
      [left, top],
      [right, top],
      [right, bottom]
    ].map(([x, y]) => rotatePoint(x, y, rotation));
    path.clear(true);
    path.moveTo(points[0].x, points[0].y);
    path.lineTo(points[1].x, points[1].y);
    path.lineTo(points[2].x, points[2].y);
    path.lineTo(points[3].x, points[3].y);
    path.closePath();
  }
  updateBeveledPath() {
    const { columnWidth, path, outerRadius, innerRadius, axisInnerRadius, axisOuterRadius, isRadiusAxisReversed } = this;
    const isStackBottom = isNumberEqual(innerRadius, axisInnerRadius);
    const sideRotation = Math.asin(columnWidth / 2 / innerRadius);
    const pointRotation = this.getRotation();
    const rotate2 = (x, y) => rotatePoint(x, y, pointRotation);
    const getTriangleHypotenuse = (leg, otherLeg) => Math.sqrt(leg ** 2 + otherLeg ** 2);
    const getTriangleLeg = (hypotenuse, otherLeg) => {
      if (otherLeg > hypotenuse) {
        return 0;
      }
      return Math.sqrt(hypotenuse ** 2 - otherLeg ** 2);
    };
    const compare = (value, otherValue, lessThan) => lessThan ? value < otherValue : value > otherValue;
    const shouldConnectBottomCircle = isStackBottom && !isNaN(sideRotation) && sideRotation < Math.PI / 6;
    let left = -columnWidth / 2;
    let right = columnWidth / 2;
    const top = -outerRadius;
    const bottom = -innerRadius * (shouldConnectBottomCircle ? Math.cos(sideRotation) : 1);
    const hasBottomIntersection = compare(
      axisOuterRadius,
      getTriangleHypotenuse(innerRadius, columnWidth / 2),
      !isRadiusAxisReversed
    );
    if (hasBottomIntersection) {
      const bottomIntersectionX = getTriangleLeg(axisOuterRadius, innerRadius);
      left = -bottomIntersectionX;
      right = bottomIntersectionX;
    }
    path.clear(true);
    const bottomLeftPt = rotate2(left, bottom);
    path.moveTo(bottomLeftPt.x, bottomLeftPt.y);
    const isEmpty2 = isNumberEqual(innerRadius, outerRadius);
    const hasSideIntersection = compare(
      axisOuterRadius,
      getTriangleHypotenuse(outerRadius, columnWidth / 2),
      !isRadiusAxisReversed
    );
    if (isEmpty2 && shouldConnectBottomCircle) {
      path.arc(
        0,
        0,
        innerRadius,
        normalizeAngle360(-sideRotation - Math.PI / 2) + pointRotation,
        normalizeAngle360(sideRotation - Math.PI / 2) + pointRotation,
        false
      );
    } else if (hasSideIntersection) {
      const sideIntersectionY = -getTriangleLeg(axisOuterRadius, columnWidth / 2);
      const topIntersectionX = getTriangleLeg(axisOuterRadius, outerRadius);
      if (!hasBottomIntersection) {
        const topLeftPt = rotate2(left, sideIntersectionY);
        path.lineTo(topLeftPt.x, topLeftPt.y);
      }
      path.arc(
        0,
        0,
        axisOuterRadius,
        Math.atan2(sideIntersectionY, left) + pointRotation,
        Math.atan2(top, -topIntersectionX) + pointRotation,
        false
      );
      if (!isNumberEqual(topIntersectionX, 0)) {
        const topRightBevelPt = rotate2(topIntersectionX, top);
        path.lineTo(topRightBevelPt.x, topRightBevelPt.y);
      }
      path.arc(
        0,
        0,
        axisOuterRadius,
        Math.atan2(top, topIntersectionX) + pointRotation,
        Math.atan2(sideIntersectionY, right) + pointRotation,
        false
      );
    } else {
      const topLeftPt = rotate2(left, top);
      const topRightPt = rotate2(right, top);
      path.lineTo(topLeftPt.x, topLeftPt.y);
      path.lineTo(topRightPt.x, topRightPt.y);
    }
    const bottomRightPt = rotate2(right, bottom);
    path.lineTo(bottomRightPt.x, bottomRightPt.y);
    if (shouldConnectBottomCircle) {
      path.arc(
        0,
        0,
        innerRadius,
        normalizeAngle360(sideRotation - Math.PI / 2) + pointRotation,
        normalizeAngle360(-sideRotation - Math.PI / 2) + pointRotation,
        true
      );
    } else {
      const rotatedBottomLeftPt = rotate2(left, bottom);
      path.lineTo(rotatedBottomLeftPt.x, rotatedBottomLeftPt.y);
    }
    path.closePath();
  }
};
RadialColumnShape.className = "RadialColumnShape";
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "isBeveled", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "columnWidth", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "startAngle", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "endAngle", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "outerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "innerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "axisInnerRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "axisOuterRadius", 2);
__decorateClass([
  ScenePathChangeDetection()
], RadialColumnShape.prototype, "isRadiusAxisReversed", 2);
function getRadialColumnWidth(startAngle, endAngle, axisOuterRadius, columnWidthRatio, maxColumnWidthRatio) {
  const rotation = angleBetween(startAngle, endAngle);
  const pad2 = rotation * (1 - columnWidthRatio) / 2;
  startAngle += pad2;
  endAngle -= pad2;
  if (rotation < 1e-3) {
    return 2 * axisOuterRadius * maxColumnWidthRatio;
  }
  if (rotation >= 2 * Math.PI) {
    const midAngle = startAngle + rotation / 2;
    startAngle = midAngle - Math.PI;
    endAngle = midAngle + Math.PI;
  }
  const startX = axisOuterRadius * Math.cos(startAngle);
  const startY = axisOuterRadius * Math.sin(startAngle);
  const endX = axisOuterRadius * Math.cos(endAngle);
  const endY = axisOuterRadius * Math.sin(endAngle);
  const colWidth = Math.floor(Math.sqrt((startX - endX) ** 2 + (startY - endY) ** 2));
  const maxWidth = 2 * axisOuterRadius * maxColumnWidthRatio;
  return Math.max(1, Math.min(maxWidth, colWidth));
}
var integrated_charts_theme_exports = {};
__export(integrated_charts_theme_exports, {
  ChartTheme: () => ChartTheme,
  DEFAULT_ANNOTATION_BACKGROUND_FILL: () => DEFAULT_ANNOTATION_BACKGROUND_FILL,
  DEFAULT_ANNOTATION_COLOR: () => DEFAULT_ANNOTATION_COLOR,
  DEFAULT_ANNOTATION_HANDLE_FILL: () => DEFAULT_ANNOTATION_HANDLE_FILL,
  DEFAULT_ANNOTATION_STATISTICS_COLOR: () => DEFAULT_ANNOTATION_STATISTICS_COLOR,
  DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE: () => DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE,
  DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL: () => DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL,
  DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE: () => DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE,
  DEFAULT_ANNOTATION_STATISTICS_FILL: () => DEFAULT_ANNOTATION_STATISTICS_FILL,
  DEFAULT_ANNOTATION_STATISTICS_STROKE: () => DEFAULT_ANNOTATION_STATISTICS_STROKE,
  DEFAULT_AXIS_GRID_COLOUR: () => DEFAULT_AXIS_GRID_COLOUR,
  DEFAULT_AXIS_LINE_COLOUR: () => DEFAULT_AXIS_LINE_COLOUR,
  DEFAULT_BACKGROUND_COLOUR: () => DEFAULT_BACKGROUND_COLOUR,
  DEFAULT_CAPTION_ALIGNMENT: () => DEFAULT_CAPTION_ALIGNMENT,
  DEFAULT_CAPTION_LAYOUT_STYLE: () => DEFAULT_CAPTION_LAYOUT_STYLE,
  DEFAULT_COLOURS: () => DEFAULT_COLOURS,
  DEFAULT_CROSS_LINES_COLOUR: () => DEFAULT_CROSS_LINES_COLOUR,
  DEFAULT_DIVERGING_SERIES_COLOR_RANGE: () => DEFAULT_DIVERGING_SERIES_COLOR_RANGE,
  DEFAULT_FIBONACCI_STROKES: () => DEFAULT_FIBONACCI_STROKES,
  DEFAULT_FONT_FAMILY: () => DEFAULT_FONT_FAMILY,
  DEFAULT_FUNNEL_SERIES_COLOR_RANGE: () => DEFAULT_FUNNEL_SERIES_COLOR_RANGE,
  DEFAULT_GAUGE_SERIES_COLOR_RANGE: () => DEFAULT_GAUGE_SERIES_COLOR_RANGE,
  DEFAULT_GRIDLINE_ENABLED: () => DEFAULT_GRIDLINE_ENABLED,
  DEFAULT_HIERARCHY_FILLS: () => DEFAULT_HIERARCHY_FILLS,
  DEFAULT_HIERARCHY_STROKES: () => DEFAULT_HIERARCHY_STROKES,
  DEFAULT_INSIDE_SERIES_LABEL_COLOUR: () => DEFAULT_INSIDE_SERIES_LABEL_COLOUR,
  DEFAULT_INVERTED_BACKGROUND_COLOUR: () => DEFAULT_INVERTED_BACKGROUND_COLOUR,
  DEFAULT_INVERTED_LABEL_COLOUR: () => DEFAULT_INVERTED_LABEL_COLOUR,
  DEFAULT_LABEL_COLOUR: () => DEFAULT_LABEL_COLOUR,
  DEFAULT_MUTED_LABEL_COLOUR: () => DEFAULT_MUTED_LABEL_COLOUR,
  DEFAULT_NAVIGATOR_STROKE: () => DEFAULT_NAVIGATOR_STROKE,
  DEFAULT_PADDING: () => DEFAULT_PADDING,
  DEFAULT_POLAR_SERIES_STROKE: () => DEFAULT_POLAR_SERIES_STROKE,
  DEFAULT_SEPARATION_LINES_COLOUR: () => DEFAULT_SEPARATION_LINES_COLOUR,
  DEFAULT_SHADOW_COLOUR: () => DEFAULT_SHADOW_COLOUR,
  DEFAULT_SPARKLINE_CROSSHAIR_STROKE: () => DEFAULT_SPARKLINE_CROSSHAIR_STROKE,
  DEFAULT_TEXTBOX_COLOR: () => DEFAULT_TEXTBOX_COLOR,
  DEFAULT_TEXTBOX_FILL: () => DEFAULT_TEXTBOX_FILL,
  DEFAULT_TEXTBOX_STROKE: () => DEFAULT_TEXTBOX_STROKE,
  DEFAULT_TEXT_ANNOTATION_COLOR: () => DEFAULT_TEXT_ANNOTATION_COLOR,
  DEFAULT_TOOLBAR_POSITION: () => DEFAULT_TOOLBAR_POSITION,
  IS_COMMUNITY: () => IS_COMMUNITY,
  IS_DARK_THEME: () => IS_DARK_THEME,
  IS_ENTERPRISE: () => IS_ENTERPRISE,
  PALETTE_ALT_DOWN_FILL: () => PALETTE_ALT_DOWN_FILL,
  PALETTE_ALT_DOWN_STROKE: () => PALETTE_ALT_DOWN_STROKE,
  PALETTE_ALT_NEUTRAL_FILL: () => PALETTE_ALT_NEUTRAL_FILL,
  PALETTE_ALT_NEUTRAL_STROKE: () => PALETTE_ALT_NEUTRAL_STROKE,
  PALETTE_ALT_UP_FILL: () => PALETTE_ALT_UP_FILL,
  PALETTE_ALT_UP_STROKE: () => PALETTE_ALT_UP_STROKE,
  PALETTE_DOWN_FILL: () => PALETTE_DOWN_FILL,
  PALETTE_DOWN_STROKE: () => PALETTE_DOWN_STROKE,
  PALETTE_NEUTRAL_FILL: () => PALETTE_NEUTRAL_FILL,
  PALETTE_NEUTRAL_STROKE: () => PALETTE_NEUTRAL_STROKE,
  PALETTE_UP_FILL: () => PALETTE_UP_FILL,
  PALETTE_UP_STROKE: () => PALETTE_UP_STROKE,
  getChartTheme: () => getChartTheme,
  themeNames: () => themeNames,
  themeSymbols: () => symbols_exports,
  themes: () => themes
});
var themeNames = Object.keys(themes);
var integrated_charts_util_exports = {};
__export(integrated_charts_util_exports, {
  Color: () => Color,
  interpolateColor: () => interpolateColor
});
var AgChartsCommunityModule = {
  VERSION,
  _Scene: integrated_charts_scene_exports,
  _Theme: integrated_charts_theme_exports,
  _Util: integrated_charts_util_exports,
  create: AgCharts.create.bind(AgCharts),
  createSparkline: AgCharts.__createSparkline.bind(AgCharts),
  setup: registerInbuiltModules,
  isEnterprise: false
};
var module_support_exports = {};
__export(module_support_exports, {
  AND: () => AND,
  ARRAY: () => ARRAY,
  ARRAY_OF: () => ARRAY_OF,
  AbstractBarSeries: () => AbstractBarSeries,
  AbstractBarSeriesProperties: () => AbstractBarSeriesProperties,
  ActionOnSet: () => ActionOnSet,
  AnchoredPopover: () => AnchoredPopover,
  Animation: () => Animation,
  AnimationManager: () => AnimationManager,
  Arc: () => Arc2,
  ArrowDown: () => ArrowDown,
  ArrowUp: () => ArrowUp,
  Axis: () => Axis,
  AxisInterval: () => AxisInterval,
  AxisLabel: () => AxisLabel,
  AxisTick: () => AxisTick,
  AxisTicks: () => AxisTicks,
  BBox: () => BBox,
  BBoxValues: () => BBoxValues,
  BOOLEAN: () => BOOLEAN,
  BOOLEAN_ARRAY: () => BOOLEAN_ARRAY,
  Background: () => Background,
  BackgroundModule: () => BackgroundModule,
  BandScale: () => BandScale,
  BarSeries: () => BarSeries,
  BarSeriesModule: () => BarSeriesModule,
  BaseModuleInstance: () => BaseModuleInstance,
  BaseProperties: () => BaseProperties,
  BaseToolbar: () => BaseToolbar,
  ButtonWidget: () => ButtonWidget,
  COLOR_STRING: () => COLOR_STRING,
  COLOR_STRING_ARRAY: () => COLOR_STRING_ARRAY,
  CachedTextMeasurer: () => CachedTextMeasurer,
  CachedTextMeasurerPool: () => CachedTextMeasurerPool,
  Caption: () => Caption,
  CartesianAxis: () => CartesianAxis,
  CartesianSeries: () => CartesianSeries,
  CartesianSeriesNodeEvent: () => CartesianSeriesNodeEvent,
  CartesianSeriesProperties: () => CartesianSeriesProperties,
  CategoryAxis: () => CategoryAxis,
  ChangeDetectableProperties: () => ChangeDetectableProperties,
  ChartAxisDirection: () => ChartAxisDirection,
  ChartEventManager: () => ChartEventManager,
  ChartOptions: () => ChartOptions,
  ChartUpdateType: () => ChartUpdateType,
  Circle: () => Circle,
  CollapseMode: () => CollapseMode,
  Color: () => Color,
  ColorScale: () => ColorScale,
  ConicGradient: () => ConicGradient,
  ContextMenuRegistry: () => ContextMenuRegistry,
  ContinuousScale: () => ContinuousScale,
  Cursor: () => Cursor,
  CursorManager: () => CursorManager,
  DATE: () => DATE,
  DATE_ARRAY: () => DATE_ARRAY,
  DATE_OR_DATETIME_MS: () => DATE_OR_DATETIME_MS,
  DEFAULT_CARTESIAN_DIRECTION_KEYS: () => DEFAULT_CARTESIAN_DIRECTION_KEYS,
  DEFAULT_CARTESIAN_DIRECTION_NAMES: () => DEFAULT_CARTESIAN_DIRECTION_NAMES,
  DEFAULT_TOOLTIP_CLASS: () => DEFAULT_TOOLTIP_CLASS,
  DEFAULT_TOOLTIP_DARK_CLASS: () => DEFAULT_TOOLTIP_DARK_CLASS,
  DIRECTION: () => DIRECTION,
  DOMManager: () => DOMManager,
  DataController: () => DataController,
  DataModel: () => DataModel,
  DataModelSeries: () => DataModelSeries,
  DataService: () => DataService,
  Debug: () => Debug,
  Default: () => Default,
  Deprecated: () => Deprecated,
  DeprecatedAndRenamedTo: () => DeprecatedAndRenamedTo,
  Diamond: () => Diamond,
  DraggablePopover: () => DraggablePopover,
  DropShadow: () => DropShadow,
  ExtendedPath2D: () => ExtendedPath2D,
  FONT_STYLE: () => FONT_STYLE,
  FONT_WEIGHT: () => FONT_WEIGHT,
  FUNCTION: () => FUNCTION,
  FloatingToolbar: () => FloatingToolbar,
  GREATER_THAN: () => GREATER_THAN,
  GestureDetector: () => GestureDetector,
  Gradient: () => Gradient,
  Group: () => Group,
  GroupedCategoryAxis: () => GroupedCategoryAxis,
  HdpiCanvas: () => HdpiCanvas,
  HierarchyNode: () => HierarchyNode,
  HierarchySeries: () => HierarchySeries,
  HierarchySeriesProperties: () => HierarchySeriesProperties,
  HighlightManager: () => HighlightManager,
  HighlightProperties: () => HighlightProperties,
  HighlightStyle: () => HighlightStyle,
  INTERACTION_RANGE: () => INTERACTION_RANGE,
  INTERPOLATION_STEP_POSITION: () => INTERPOLATION_STEP_POSITION,
  INTERPOLATION_TYPE: () => INTERPOLATION_TYPE,
  Image: () => Image,
  InteractionManager: () => InteractionManager,
  InteractionState: () => InteractionState,
  InterpolationProperties: () => InterpolationProperties,
  Invalidating: () => Invalidating,
  KeyNavManager: () => KeyNavManager,
  LABEL_PLACEMENT: () => LABEL_PLACEMENT,
  LARGEST_KEY_INTERVAL: () => LARGEST_KEY_INTERVAL,
  LESS_THAN: () => LESS_THAN,
  LINE_CAP: () => LINE_CAP,
  LINE_DASH: () => LINE_DASH,
  LINE_JOIN: () => LINE_JOIN,
  LINE_STYLE: () => LINE_STYLE,
  Label: () => Label,
  LayoutElement: () => LayoutElement,
  LayoutManager: () => LayoutManager,
  LegendMarkerLabel: () => LegendMarkerLabel,
  Line: () => Line,
  LineSeries: () => LineSeries,
  LineSeriesModule: () => LineSeriesModule,
  LinearGradient: () => LinearGradient,
  LinearScale: () => LinearScale,
  Listeners: () => Listeners,
  Logger: () => Logger,
  LonLatBBox: () => LonLatBBox,
  MARKER_SHAPE: () => MARKER_SHAPE,
  MATCHING_CROSSLINE_TYPE: () => MATCHING_CROSSLINE_TYPE,
  MAX_SPACING: () => MAX_SPACING,
  MIN_SPACING: () => MIN_SPACING,
  Marker: () => Marker,
  Menu: () => Menu,
  MercatorScale: () => MercatorScale,
  ModuleRegistry: () => ModuleRegistry,
  Motion: () => easing_exports,
  NAN: () => NAN,
  NODE_UPDATE_STATE_TO_PHASE_MAPPING: () => NODE_UPDATE_STATE_TO_PHASE_MAPPING,
  NUMBER: () => NUMBER,
  NUMBER_ARRAY: () => NUMBER_ARRAY,
  NUMBER_OR_NAN: () => NUMBER_OR_NAN,
  NativeWidget: () => NativeWidget,
  Node: () => Node,
  OBJECT: () => OBJECT,
  OBJECT_ARRAY: () => OBJECT_ARRAY,
  OR: () => OR,
  OVERFLOW_STRATEGY: () => OVERFLOW_STRATEGY,
  ObserveChanges: () => ObserveChanges,
  OrdinalTimeScale: () => OrdinalTimeScale,
  PHASE_METADATA: () => PHASE_METADATA,
  PHASE_ORDER: () => PHASE_ORDER,
  PLACEMENT: () => PLACEMENT,
  PLAIN_OBJECT: () => PLAIN_OBJECT,
  POINTER_INTERACTION_TYPES: () => POINTER_INTERACTION_TYPES,
  POSITION: () => POSITION,
  POSITION_TOP_COORDINATES: () => POSITION_TOP_COORDINATES,
  POSITIVE_NUMBER: () => POSITIVE_NUMBER,
  PREV_NEXT_KEYS: () => PREV_NEXT_KEYS,
  Padding: () => Padding,
  ParallelStateMachine: () => ParallelStateMachine,
  Path: () => Path,
  PointerEvents: () => PointerEvents,
  PolarAxis: () => PolarAxis,
  PolarSeries: () => PolarSeries,
  PolarZIndexMap: () => PolarZIndexMap,
  Popover: () => Popover,
  PropertiesArray: () => PropertiesArray,
  ProxyInteractionService: () => ProxyInteractionService,
  ProxyOnWrite: () => ProxyOnWrite,
  ProxyProperty: () => ProxyProperty,
  ProxyPropertyOnWrite: () => ProxyPropertyOnWrite,
  QUICK_TRANSITION: () => QUICK_TRANSITION,
  RATIO: () => RATIO,
  REAL_NUMBER: () => REAL_NUMBER,
  RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD: () => RENDER_TO_OFFSCREEN_CANVAS_THRESHOLD,
  RadialColumnShape: () => RadialColumnShape,
  Range: () => Range,
  Rect: () => Rect,
  RegionManager: () => RegionManager,
  RepeatType: () => RepeatType,
  Rotatable: () => Rotatable,
  RotatableGroup: () => RotatableGroup,
  RotatableText: () => RotatableText,
  SKIP_JS_BUILTINS: () => SKIP_JS_BUILTINS,
  SMALLEST_KEY_INTERVAL: () => SMALLEST_KEY_INTERVAL,
  SORT_DOMAIN_GROUPS: () => SORT_DOMAIN_GROUPS,
  STRING: () => STRING,
  STRING_ARRAY: () => STRING_ARRAY,
  Scalable: () => Scalable,
  ScalableGroup: () => ScalableGroup,
  Scene: () => Scene,
  SceneChangeDetection: () => SceneChangeDetection,
  ScenePathChangeDetection: () => ScenePathChangeDetection,
  Sector: () => Sector,
  SectorBox: () => SectorBox,
  Selection: () => Selection,
  Series: () => Series,
  SeriesContentZIndexMap: () => SeriesContentZIndexMap,
  SeriesGroupingChangedEvent: () => SeriesGroupingChangedEvent,
  SeriesItemHighlightStyle: () => SeriesItemHighlightStyle,
  SeriesMarker: () => SeriesMarker,
  SeriesNodeEvent: () => SeriesNodeEvent,
  SeriesNodePickMode: () => SeriesNodePickMode,
  SeriesProperties: () => SeriesProperties,
  SeriesTooltip: () => SeriesTooltip,
  SeriesZIndexMap: () => SeriesZIndexMap,
  Shape: () => Shape,
  SimpleTextMeasurer: () => SimpleTextMeasurer,
  SliderWidget: () => SliderWidget,
  Square: () => Square,
  StateMachine: () => StateMachine,
  StateMachineProperty: () => StateMachineProperty,
  SvgPath: () => SvgPath,
  TEXT_ALIGN: () => TEXT_ALIGN,
  TEXT_WRAP: () => TEXT_WRAP,
  TICK_INTERVAL: () => TICK_INTERVAL,
  Text: () => Text,
  TextUtils: () => TextUtils,
  TextWrapper: () => TextWrapper,
  ThemeConstants: () => constants_exports,
  ThemeSymbols: () => symbols_exports,
  TimeScale: () => TimeScale,
  Toolbar: () => Toolbar,
  ToolbarButtonProperties: () => ToolbarButtonProperties,
  ToolbarButtonWidget: () => ToolbarButtonWidget,
  ToolbarWidget: () => ToolbarWidget,
  Tooltip: () => Tooltip,
  TooltipManager: () => TooltipManager,
  TooltipPosition: () => TooltipPosition,
  Transformable: () => Transformable,
  TransformableText: () => TransformableText,
  Translatable: () => Translatable,
  TranslatableGroup: () => TranslatableGroup,
  Triangle: () => Triangle,
  UNION: () => UNION,
  UpdateService: () => UpdateService,
  VERTICAL_ALIGN: () => VERTICAL_ALIGN,
  Validate: () => Validate,
  Vec2: () => Vec2,
  Vec4: () => Vec4,
  WIDGET_HTML_EVENTS: () => WIDGET_HTML_EVENTS,
  Widget: () => Widget,
  WidgetEventUtil: () => WidgetEventUtil,
  ZIndexMap: () => ZIndexMap,
  ZoomManager: () => ZoomManager,
  __FORCE_MODULE_DETECTION: () => __FORCE_MODULE_DETECTION,
  accumulateGroup: () => accumulateGroup,
  accumulateStack: () => accumulateStack,
  accumulatedValue: () => accumulatedValue,
  accumulativeValueProperty: () => accumulativeValueProperty,
  addHitTestersToQuadtree: () => addHitTestersToQuadtree,
  adjustLabelPlacement: () => adjustLabelPlacement,
  angleBetween: () => angleBetween,
  angleDiff: () => angleDiff,
  animationValidation: () => animationValidation,
  areScalingEqual: () => areScalingEqual,
  area: () => area,
  arraysEqual: () => arraysEqual,
  backfillPathPointData: () => backfillPathPointData,
  buildFormatter: () => buildFormatter,
  buildResetPathFn: () => buildResetPathFn,
  calculateDefaultTimeTickFormat: () => calculateDefaultTimeTickFormat,
  calculateDerivativeExtrema: () => calculateDerivativeExtrema,
  calculateDerivativeExtremaXY: () => calculateDerivativeExtremaXY,
  calculateLabelChartPadding: () => calculateLabelChartPadding,
  calculateLabelTranslation: () => calculateLabelTranslation,
  calculatePlacement: () => calculatePlacement,
  checkCrisp: () => checkCrisp,
  circularSliceArray: () => circularSliceArray,
  clamp: () => clamp,
  clampArray: () => clampArray,
  clippedRoundRect: () => clippedRoundRect,
  clockwiseAngle: () => clockwiseAngle,
  clockwiseAngles: () => clockwiseAngles,
  collapsedStartingBarPosition: () => collapsedStartingBarPosition,
  compareDates: () => compareDates,
  computeBarFocusBounds: () => computeBarFocusBounds,
  computeMarkerFocusBounds: () => computeMarkerFocusBounds,
  countFractionDigits: () => countFractionDigits,
  createButton: () => createButton,
  createCheckbox: () => createCheckbox,
  createDatumId: () => createDatumId,
  createDeprecationWarning: () => createDeprecationWarning,
  createElement: () => createElement,
  createElementId: () => createElementId,
  createElementNS: () => createElementNS,
  createIcon: () => createIcon,
  createId: () => createId,
  createSelect: () => createSelect,
  createTextArea: () => createTextArea,
  dateToNumber: () => dateToNumber,
  datesSortOrder: () => datesSortOrder,
  datumKeys: () => datumKeys,
  datumStylerProperties: () => datumStylerProperties,
  debounce: () => debounce,
  deconstructSelectionsOrNodes: () => deconstructSelectionsOrNodes,
  deepClone: () => deepClone,
  deepFreeze: () => deepFreeze,
  deepMerge: () => deepMerge,
  defaultTimeTickFormat: () => defaultTimeTickFormat,
  diff: () => diff,
  displacePointFromVector: () => displacePointFromVector,
  doOnce: () => doOnce,
  downloadUrl: () => downloadUrl,
  drawCorner: () => drawCorner,
  easing: () => easing_exports,
  enterpriseModule: () => enterpriseModule,
  evaluateBezier: () => evaluateBezier,
  excludesType: () => excludesType,
  extent: () => extent,
  extractDecoratedProperties: () => extractDecoratedProperties,
  findMaxIndex: () => findMaxIndex,
  findMaxValue: () => findMaxValue,
  findMinIndex: () => findMinIndex,
  findMinMax: () => findMinMax,
  findMinValue: () => findMinValue,
  findQuadtreeMatch: () => findQuadtreeMatch,
  findRangeExtent: () => findRangeExtent,
  fixNumericExtent: () => fixNumericExtent,
  focusCursorAtEnd: () => focusCursorAtEnd,
  formatNumber: () => formatNumber,
  formatPercent: () => formatPercent,
  formatValue: () => formatValue,
  fromToMotion: () => fromToMotion,
  generateUUID: () => generateUUID,
  getAngleRatioRadians: () => getAngleRatioRadians,
  getDatumRefPoint: () => getDatumRefPoint,
  getDocument: () => getDocument,
  getElementBBox: () => getElementBBox,
  getIconClassNames: () => getIconClassNames,
  getLastFocus: () => getLastFocus,
  getMarker: () => getMarker,
  getMissCount: () => getMissCount,
  getPath: () => getPath,
  getPathComponents: () => getPathComponents,
  getRadialColumnWidth: () => getRadialColumnWidth,
  getRectConfig: () => getRectConfig,
  getWindow: () => getWindow,
  groupAccumulativeValueProperty: () => groupAccumulativeValueProperty,
  groupAverage: () => groupAverage,
  groupBy: () => groupBy,
  groupCount: () => groupCount,
  groupStackValueProperty: () => groupStackValueProperty,
  groupSum: () => groupSum,
  hasNoModifiers: () => hasNoModifiers,
  identity: () => identity,
  inRange: () => inRange,
  includes: () => includes,
  initMenuKeyNav: () => initMenuKeyNav,
  initRovingTabIndex: () => initRovingTabIndex,
  initToolbarKeyNav: () => initToolbarKeyNav,
  interpolatePoints: () => interpolatePoints,
  isArray: () => isArray,
  isBetweenAngles: () => isBetweenAngles,
  isBoolean: () => isBoolean,
  isButtonClickEvent: () => isButtonClickEvent,
  isContinuous: () => isContinuous,
  isDate: () => isDate,
  isDecoratedObject: () => isDecoratedObject,
  isDefined: () => isDefined,
  isDenseInterval: () => isDenseInterval,
  isEnumKey: () => isEnumKey,
  isEnumValue: () => isEnumValue,
  isFiniteNumber: () => isFiniteNumber,
  isFunction: () => isFunction,
  isHtmlElement: () => isHtmlElement,
  isInputPending: () => isInputPending,
  isInteger: () => isInteger,
  isNegative: () => isNegative,
  isNumber: () => isNumber,
  isNumberEqual: () => isNumberEqual,
  isObject: () => isObject,
  isObjectLike: () => isObjectLike,
  isPlainObject: () => isPlainObject,
  isProperties: () => isProperties,
  isRegExp: () => isRegExp,
  isScaleValid: () => isScaleValid,
  isString: () => isString,
  isSymbol: () => isSymbol,
  isValidDate: () => isValidDate,
  jsonApply: () => jsonApply,
  jsonDiff: () => jsonDiff,
  jsonPropertyCompare: () => jsonPropertyCompare,
  jsonWalk: () => jsonWalk,
  keyProperty: () => keyProperty,
  labelDirectionHandling: () => labelDirectionHandling,
  legendSymbolSvg: () => legendSymbolSvg,
  lineDistanceSquared: () => lineDistanceSquared,
  listDecoratedProperties: () => listDecoratedProperties,
  makeAccessibleClickListener: () => makeAccessibleClickListener,
  mapValues: () => mapValues,
  markerFadeInAnimation: () => markerFadeInAnimation,
  markerPaletteFactory: () => markerPaletteFactory,
  markerScaleInAnimation: () => markerScaleInAnimation,
  markerSwipeScaleInAnimation: () => markerSwipeScaleInAnimation,
  mergeArrayDefaults: () => mergeArrayDefaults,
  mergeDefaults: () => mergeDefaults,
  midpointStartingBarPosition: () => midpointStartingBarPosition,
  minMax: () => minMax,
  mod: () => mod,
  moduleRegistry: () => moduleRegistry,
  motion: () => motion,
  nearestSquared: () => nearestSquared,
  nearestSquaredInContainer: () => nearestSquaredInContainer,
  normaliseGroupTo: () => normaliseGroupTo,
  normalisePropertyTo: () => normalisePropertyTo,
  normalisedExtentWithMetadata: () => normalisedExtentWithMetadata,
  normalizeAngle180: () => normalizeAngle180,
  normalizeAngle360: () => normalizeAngle360,
  normalizeAngle360Inclusive: () => normalizeAngle360Inclusive,
  objectsEqual: () => objectsEqual,
  objectsEqualWith: () => objectsEqualWith,
  pairUpSpans: () => pairUpSpans,
  partialAssign: () => partialAssign,
  pathFadeInAnimation: () => pathFadeInAnimation,
  pathFadeOutAnimation: () => pathFadeOutAnimation,
  pathMotion: () => pathMotion,
  pathSwipeInAnimation: () => pathSwipeInAnimation,
  pickByMatchingAngle: () => pickByMatchingAngle,
  pickNode: () => pickNode,
  plotAreaPathFill: () => plotAreaPathFill,
  plotInterpolatedAreaSeriesFillSpans: () => plotInterpolatedAreaSeriesFillSpans,
  plotInterpolatedLinePathStroke: () => plotInterpolatedLinePathStroke,
  plotLinePathStroke: () => plotLinePathStroke,
  plotPath: () => plotPath,
  predicateWithMessage: () => predicateWithMessage,
  prepareAreaFillAnimationFns: () => prepareAreaFillAnimationFns,
  prepareAreaPathAnimation: () => prepareAreaPathAnimation,
  prepareAxisAnimationContext: () => prepareAxisAnimationContext,
  prepareAxisAnimationFunctions: () => prepareAxisAnimationFunctions,
  prepareBarAnimationFunctions: () => prepareBarAnimationFunctions,
  prepareLinePathAnimation: () => prepareLinePathAnimation,
  prepareLinePathPropertyAnimation: () => prepareLinePathPropertyAnimation,
  prepareLinePathStrokeAnimationFns: () => prepareLinePathStrokeAnimationFns,
  prepareMarkerAnimation: () => prepareMarkerAnimation,
  preparePieSeriesAnimationFunctions: () => preparePieSeriesAnimationFunctions,
  range: () => range,
  rangedValueProperty: () => rangedValueProperty,
  renderPartialPath: () => renderPartialPath,
  resetAxisGroupFn: () => resetAxisGroupFn,
  resetAxisLabelSelectionFn: () => resetAxisLabelSelectionFn,
  resetAxisLineSelectionFn: () => resetAxisLineSelectionFn,
  resetAxisSelectionFn: () => resetAxisSelectionFn,
  resetBarSelectionsFn: () => resetBarSelectionsFn,
  resetIds: () => resetIds,
  resetLabelFn: () => resetLabelFn,
  resetMarkerFn: () => resetMarkerFn,
  resetMarkerPositionFn: () => resetMarkerPositionFn,
  resetMotion: () => resetMotion,
  resetPieSelectionsFn: () => resetPieSelectionsFn,
  round: () => round,
  sanitizeHtml: () => sanitizeHtml,
  scale: () => scale,
  sectorBox: () => sectorBox,
  seriesLabelFadeInAnimation: () => seriesLabelFadeInAnimation,
  seriesLabelFadeOutAnimation: () => seriesLabelFadeOutAnimation,
  setAttribute: () => setAttribute,
  setAttributes: () => setAttributes,
  setDocument: () => setDocument,
  setElementBBox: () => setElementBBox,
  setElementStyle: () => setElementStyle,
  setPath: () => setPath,
  setWindow: () => setWindow,
  shallowClone: () => shallowClone,
  singleSeriesPaletteFactory: () => singleSeriesPaletteFactory,
  solveBezier: () => solveBezier,
  sortAndUniqueDates: () => sortAndUniqueDates,
  sortBasedOnArray: () => sortBasedOnArray,
  splitBezier: () => splitBezier,
  splitPairData: () => splitPairData,
  staticFromToMotion: () => staticFromToMotion,
  stopPageScrolling: () => stopPageScrolling,
  stringify: () => stringify,
  sum: () => sum,
  sumValues: () => sumValues,
  swapAxisCondition: () => swapAxisCondition,
  throttle: () => throttle,
  toArray: () => toArray,
  toDegrees: () => toDegrees,
  toRadians: () => toRadians,
  tooltipContentAriaLabel: () => tooltipContentAriaLabel,
  trailingAccumulatedValue: () => trailingAccumulatedValue,
  trailingAccumulatedValueProperty: () => trailingAccumulatedValueProperty,
  unique: () => unique,
  updateClipPath: () => updateClipPath,
  updateLabelNode: () => updateLabelNode,
  updateRect: () => updateRect,
  validateCrossLineValues: () => validateCrossLineValues,
  valueProperty: () => valueProperty,
  visibleRangeIndices: () => visibleRangeIndices,
  without: () => without
});
function createDeprecationWarning() {
  return (key, message) => {
    const msg = [`Property [${key}] is deprecated.`, message].filter(Boolean).join(" ");
    Logger.warnOnce(msg);
  };
}
function Deprecated(message, opts) {
  const warnDeprecated = createDeprecationWarning();
  const def = opts?.default;
  return addTransformToInstanceProperty((_, key, value) => {
    if (value !== def) {
      warnDeprecated(key.toString(), message);
    }
    return value;
  });
}
function DeprecatedAndRenamedTo(newPropName, mapValue) {
  const warnDeprecated = createDeprecationWarning();
  return addTransformToInstanceProperty(
    (target, key, value) => {
      if (value !== target[newPropName]) {
        warnDeprecated(key.toString(), `Use [${newPropName}] instead.`);
        setPath(target, newPropName, mapValue ? mapValue(value) : value);
      }
      return BREAK_TRANSFORM_CHAIN;
    },
    (target, key) => {
      warnDeprecated(key.toString(), `Use [${newPropName}] instead.`);
      return getPath(target, newPropName);
    }
  );
}
var Vec2 = {
  add,
  angle,
  apply,
  equal,
  distance: distance2,
  distanceSquared: distanceSquared2,
  from: from2,
  gradient,
  intercept,
  intersectAtX,
  intersectAtY,
  length,
  lengthSquared,
  multiply,
  normalized,
  origin: origin2,
  required,
  rotate,
  round: round4,
  sub
};
function add(a, b) {
  if (typeof b === "number") {
    return { x: a.x + b, y: a.y + b };
  }
  return { x: a.x + b.x, y: a.y + b.y };
}
function sub(a, b) {
  if (typeof b === "number") {
    return { x: a.x - b, y: a.y - b };
  }
  return { x: a.x - b.x, y: a.y - b.y };
}
function multiply(a, b) {
  if (typeof b === "number") {
    return { x: a.x * b, y: a.y * b };
  }
  return { x: a.x * b.x, y: a.y * b.y };
}
function length(a) {
  return Math.sqrt(a.x * a.x + a.y * a.y);
}
function lengthSquared(a) {
  return a.x * a.x + a.y * a.y;
}
function distance2(a, b) {
  const d = sub(a, b);
  return Math.sqrt(d.x * d.x + d.y * d.y);
}
function distanceSquared2(a, b) {
  const d = sub(a, b);
  return d.x * d.x + d.y * d.y;
}
function normalized(a) {
  const l = length(a);
  return { x: a.x / l, y: a.y / l };
}
function angle(a, b = origin2()) {
  return Math.atan2(a.y, a.x) - Math.atan2(b.y, b.x);
}
function rotate(a, theta, b = origin2()) {
  const l = length(a);
  return { x: b.x + l * Math.cos(theta), y: b.y + l * Math.sin(theta) };
}
function gradient(a, b, reflection) {
  const dx = b.x - a.x;
  const dy = reflection == null ? b.y - a.y : reflection - b.y - (reflection - a.y);
  return dy / dx;
}
function intercept(a, gradient2, reflection) {
  const y = reflection == null ? a.y : reflection - a.y;
  return y - gradient2 * a.x;
}
function intersectAtY(gradient2, coefficient, y = 0, reflection) {
  return {
    x: gradient2 === Infinity ? Infinity : (y - coefficient) / gradient2,
    y: reflection == null ? y : reflection - y
  };
}
function intersectAtX(gradient2, coefficient, x = 0, reflection) {
  const y = gradient2 === Infinity ? Infinity : gradient2 * x + coefficient;
  return { x, y: reflection == null ? y : reflection - y };
}
function round4(a) {
  return { x: Math.round(a.x), y: Math.round(a.y) };
}
function equal(a, b) {
  return a.x === b.x && a.y === b.y;
}
function from2(a, b) {
  if (typeof a === "number") {
    return { x: a, y: b };
  }
  if ("regionX" in a) {
    return { x: a.regionX, y: a.regionY };
  }
  if ("offsetWidth" in a) {
    return { x: a.offsetWidth, y: a.offsetHeight };
  }
  if ("width" in a) {
    return [
      { x: a.x, y: a.y },
      { x: a.x + a.width, y: a.y + a.height }
    ];
  }
  if ("x1" in a) {
    return [
      { x: a.x1, y: a.y1 },
      { x: a.x2, y: a.y2 }
    ];
  }
  throw new Error(`Values can not be converted into a vector: [${JSON.stringify(a)}] [${b}]`);
}
function apply(a, b) {
  a.x = b.x;
  a.y = b.y;
  return a;
}
function required(a) {
  return { x: a?.x ?? 0, y: a?.y ?? 0 };
}
function origin2() {
  return { x: 0, y: 0 };
}
var _HierarchyNode = class _HierarchyNode2 {
  constructor(series, index, rootIndex, datum, sizeValue, colorValue, sumSize, depth, parent, children) {
    this.series = series;
    this.index = index;
    this.rootIndex = rootIndex;
    this.datum = datum;
    this.sizeValue = sizeValue;
    this.colorValue = colorValue;
    this.sumSize = sumSize;
    this.depth = depth;
    this.parent = parent;
    this.children = children;
    this.midPoint = { x: 0, y: 0 };
  }
  contains(other) {
    let current = other;
    while (current != null && current.index >= this.index) {
      if (current === this) {
        return true;
      }
      current = current.parent;
    }
    return false;
  }
  walk(callback2, order = _HierarchyNode2.Walk.PreOrder) {
    if (order === _HierarchyNode2.Walk.PreOrder) {
      callback2(this);
    }
    this.children.forEach((child) => {
      child.walk(callback2, order);
    });
    if (order === _HierarchyNode2.Walk.PostOrder) {
      callback2(this);
    }
  }
  *[Symbol.iterator]() {
    yield this;
    for (const child of this.children) {
      yield* child;
    }
  }
};
_HierarchyNode.Walk = {
  PreOrder: 0,
  PostOrder: 1
};
var HierarchyNode = _HierarchyNode;
var HierarchySeries = class extends Series {
  constructor(moduleCtx) {
    super({
      moduleCtx,
      pickModes: [
        1,
        0
        /* EXACT_SHAPE_MATCH */
      ]
    });
    this.rootNode = new HierarchyNode(this, 0, 0, void 0, 0, void 0, 0, void 0, void 0, []);
    this.colorDomain = [0, 0];
    this.maxDepth = 0;
    this.colorScale = new ColorScale();
    this.focusPath = [];
    this.animationState = new StateMachine(
      "empty",
      {
        empty: {
          update: {
            target: "ready",
            action: (data) => this.animateEmptyUpdateReady(data)
          },
          reset: "empty",
          skip: "ready"
        },
        ready: {
          updateData: "waiting",
          clear: "clearing",
          highlight: (data) => this.animateReadyHighlight(data),
          resize: (data) => this.animateReadyResize(data),
          reset: "empty",
          skip: "ready"
        },
        waiting: {
          update: {
            target: "ready",
            action: (data) => this.animateWaitingUpdateReady(data)
          },
          reset: "empty",
          skip: "ready"
        },
        clearing: {
          update: {
            target: "empty",
            action: (data) => this.animateClearingUpdateEmpty(data)
          },
          reset: "empty",
          skip: "ready"
        }
      },
      () => this.checkProcessedDataAnimatable()
    );
  }
  resetAnimation(phase) {
    if (phase === "initial") {
      this.animationState.transition("reset");
    } else if (phase === "ready") {
      this.animationState.transition("skip");
    }
  }
  processData() {
    const { childrenKey, sizeKey, colorKey, colorRange } = this.properties;
    let index = 0;
    const getIndex = () => {
      index += 1;
      return index;
    };
    let maxDepth = 0;
    let minColor = Infinity;
    let maxColor = -Infinity;
    const createNode = (datum, rootIndex, parent) => {
      const nodeIndex = getIndex();
      const depth = parent.depth != null ? parent.depth + 1 : 0;
      const children = childrenKey != null ? datum[childrenKey] : void 0;
      const isLeaf = children == null || children.length === 0;
      let sizeValue = sizeKey != null ? datum[sizeKey] : void 0;
      if (Number.isFinite(sizeValue)) {
        sizeValue = Math.max(sizeValue, 0);
      } else {
        sizeValue = isLeaf ? 1 : 0;
      }
      const sumSize = sizeValue;
      maxDepth = Math.max(maxDepth, depth);
      const colorValue = colorKey != null ? datum[colorKey] : void 0;
      if (typeof colorValue === "number") {
        minColor = Math.min(minColor, colorValue);
        maxColor = Math.max(maxColor, colorValue);
      }
      return appendChildren(
        new HierarchyNode(
          this,
          nodeIndex,
          rootIndex ?? 0,
          datum,
          sizeValue,
          colorValue,
          sumSize,
          depth,
          parent,
          []
        ),
        rootIndex,
        children
      );
    };
    const appendChildren = (node, rootIndex, data) => {
      data?.forEach((datum, childIndex) => {
        const child = createNode(datum, rootIndex ?? childIndex, node);
        node.children.push(child);
        node.sumSize += child.sumSize;
      });
      return node;
    };
    const rootNode = appendChildren(
      new HierarchyNode(this, 0, 0, void 0, 0, void 0, 0, void 0, void 0, []),
      void 0,
      this.data
    );
    const colorDomain = [minColor, maxColor];
    this.colorScale.domain = minColor < maxColor ? [minColor, maxColor] : [0, 1];
    this.colorScale.range = colorRange ?? ["black"];
    this.colorScale.update();
    this.rootNode = rootNode;
    this.maxDepth = maxDepth;
    this.colorDomain = colorDomain;
    this.focusPath = [{ nodeDatum: this.rootNode, childIndex: 0 }];
  }
  update({ seriesRect }) {
    this.updateSelections();
    this.updateNodes();
    const animationData = this.getAnimationData();
    const resize = this.checkResize(seriesRect);
    if (resize) {
      this.animationState.transition("resize", animationData);
    }
    this.animationState.transition("update", animationData);
  }
  resetAllAnimation(data) {
    const datum = this.animationResetFns?.datum;
    this.ctx.animationManager.stopByAnimationGroupId(this.id);
    if (datum != null) {
      resetMotion(data.datumSelections, datum);
    }
  }
  animateEmptyUpdateReady(data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation(data);
  }
  animateWaitingUpdateReady(data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation(data);
  }
  animateReadyHighlight(data) {
    const datum = this.animationResetFns?.datum;
    if (datum != null) {
      resetMotion([data], datum);
    }
  }
  animateReadyResize(data) {
    this.resetAllAnimation(data);
  }
  animateClearingUpdateEmpty(data) {
    this.ctx.animationManager.skipCurrentBatch();
    this.resetAllAnimation(data);
  }
  isProcessedDataAnimatable() {
    return true;
  }
  checkProcessedDataAnimatable() {
    if (!this.isProcessedDataAnimatable()) {
      this.ctx.animationManager.skipCurrentBatch();
    }
  }
  getSeriesDomain() {
    return [NaN, NaN];
  }
  getSeriesRange(_direction, _visibleRange) {
    return [NaN, NaN];
  }
  getLegendData(legendType) {
    const { colorKey, colorName, colorRange } = this.properties;
    const {
      id: seriesId,
      ctx: { legendManager },
      visible
    } = this;
    return legendType === "gradient" && colorKey != null && colorRange != null ? [
      {
        legendType: "gradient",
        enabled: visible && legendManager.getItemEnabled({ seriesId }),
        seriesId,
        colorName,
        colorRange,
        colorDomain: this.colorDomain
      }
    ] : [];
  }
  getDatumIdFromData(node) {
    return `${node.index}`;
  }
  getDatumId(node) {
    return this.getDatumIdFromData(node);
  }
  pickFocus(opts) {
    if (this.rootNode.children.length === 0)
      return void 0;
    if (this.focusPath.length === 0) {
      Logger.error("this.focusPath should not be empty");
    }
    const { datumIndexDelta: childDelta, otherIndexDelta: depthDelta } = opts;
    const { focusPath: path } = this;
    const depth = path.length - 2;
    if (depthDelta !== 0 || path.length === 1) {
      const targetDepth = Math.max(0, depth + depthDelta);
      if (path[targetDepth + 1] == null) {
        let deepest = path[path.length - 1];
        while (deepest.nodeDatum.children.length > 0 && (deepest.nodeDatum.depth ?? -1) < targetDepth) {
          const nextDeepest = { nodeDatum: deepest.nodeDatum.children[0], childIndex: 0 };
          path.push(nextDeepest);
          deepest = nextDeepest;
        }
        return this.computeFocusOutputs(deepest);
      } else {
        path.length = targetDepth + 2;
        return this.computeFocusOutputs(path[targetDepth + 1]);
      }
    } else if (childDelta === 0) {
      return this.computeFocusOutputs(path[path.length - 1]);
    } else {
      const targetChild = path[depth + 1].childIndex + childDelta;
      const currentParent = path[depth].nodeDatum;
      const childCount = currentParent?.children?.length;
      if (childCount != null) {
        const newChild = clamp(0, targetChild, childCount - 1);
        const newFocus = { nodeDatum: currentParent.children[newChild], childIndex: newChild };
        path[depth + 1] = newFocus;
        path.length = depth + 2;
        return this.computeFocusOutputs(newFocus);
      }
    }
  }
  getDatumAriaText(datum, description) {
    if (!(datum instanceof HierarchyNode)) {
      Logger.error(`datum is not HierarchyNode: ${JSON.stringify(datum)}`);
      return;
    }
    return this.ctx.localeManager.t("ariaAnnounceHierarchyDatum", {
      level: (datum.depth ?? -1) + 1,
      count: datum.children.length,
      description
    });
  }
  computeFocusOutputs({ nodeDatum, childIndex }) {
    const bounds = this.computeFocusBounds(nodeDatum);
    if (bounds) {
      return {
        datum: nodeDatum,
        datumIndex: childIndex,
        otherIndex: nodeDatum.depth,
        bounds,
        showFocusBox: true,
        clipFocusBox: true
      };
    }
    return void 0;
  }
};
var HierarchySeriesProperties = class extends SeriesProperties {
  constructor() {
    super(...arguments);
    this.childrenKey = "children";
    this.fills = Object.values(DEFAULT_FILLS);
    this.strokes = Object.values(DEFAULT_STROKES);
  }
};
__decorateClass([
  Validate(STRING)
], HierarchySeriesProperties.prototype, "childrenKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], HierarchySeriesProperties.prototype, "sizeKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], HierarchySeriesProperties.prototype, "colorKey", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], HierarchySeriesProperties.prototype, "colorName", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], HierarchySeriesProperties.prototype, "fills", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY)
], HierarchySeriesProperties.prototype, "strokes", 2);
__decorateClass([
  Validate(COLOR_STRING_ARRAY, { optional: true })
], HierarchySeriesProperties.prototype, "colorRange", 2);
var LonLatBBox = class {
  constructor(lon0, lat0, lon1, lat1) {
    this.lon0 = lon0;
    this.lat0 = lat0;
    this.lon1 = lon1;
    this.lat1 = lat1;
  }
  merge(other) {
    this.lon0 = Math.min(this.lon0, other.lon0);
    this.lat0 = Math.min(this.lat0, other.lat0);
    this.lon1 = Math.max(this.lon1, other.lon1);
    this.lat1 = Math.max(this.lat1, other.lat1);
  }
};
var _AxisTicks = class _AxisTicks2 {
  constructor() {
    this.id = createId(this);
    this.axisGroup = new TranslatableGroup({
      name: `${this.id}-AxisTicks`,
      zIndex: 2
      /* AXIS */
    });
    this.labelSelection = Selection.select(this.axisGroup, Text);
    this.interval = new AxisInterval();
    this.label = new AxisLabel();
    this.scale = new LinearScale();
    this.position = "bottom";
    this.translationX = 0;
    this.translationY = 0;
    this.padding = 0;
  }
  attachAxis(axisNode) {
    axisNode.appendChild(this.axisGroup);
  }
  calculateLayout() {
    this.scale.interval = this.interval.step;
    const boxes = [];
    const tickData = this.generateTicks();
    const { translationX, translationY } = this;
    this.labelSelection.update(
      tickData.ticks.map((d) => this.createLabelDatum(d)),
      void 0,
      (datum) => datum.tickId
    );
    this.labelSelection.each((node, datum) => {
      node.setProperties(datum);
      if (datum.visible) {
        boxes.push(node.getBBox());
      }
    });
    this.axisGroup.setProperties({ translationX, translationY });
    return BBox.merge(boxes);
  }
  getLabelParams(datum) {
    const { padding } = this;
    const { translate } = datum;
    switch (this.position) {
      case "top":
      case "bottom":
        return {
          x: translate,
          y: padding,
          textAlign: "center",
          textBaseline: "top"
        };
      case "left":
      case "right":
        return {
          x: padding,
          y: translate,
          textAlign: "start",
          textBaseline: "middle"
        };
    }
  }
  inRange(x, tolerance = 1e-3) {
    const [min, max] = findMinMax(this.scale.range);
    return x >= min - tolerance && x <= max + tolerance;
  }
  createLabelDatum(datum) {
    const { x, y, textBaseline, textAlign } = this.getLabelParams(datum);
    return {
      visible: Boolean(datum.tickLabel),
      tickId: datum.tickId,
      fill: this.label.color,
      fontFamily: this.label.fontFamily,
      fontSize: this.label.fontSize,
      fontStyle: this.label.fontStyle,
      fontWeight: this.label.fontWeight,
      rotation: 0,
      rotationCenterX: 0,
      text: datum.tickLabel,
      textAlign,
      textBaseline,
      x,
      y
    };
  }
  generateTicks() {
    const { minSpacing, maxSpacing } = this.interval;
    const extentWithBleed = round(findRangeExtent(this.scale.range), 2);
    const { maxTickCount, minTickCount, tickCount } = estimateTickCount(
      extentWithBleed,
      minSpacing,
      maxSpacing,
      _AxisTicks2.DefaultTickCount,
      _AxisTicks2.DefaultMinSpacing
    );
    if (tickCount) {
      this.scale.tickCount = tickCount;
      this.scale.minTickCount = minTickCount;
      this.scale.maxTickCount = maxTickCount;
    }
    const tickData = this.getTicksData();
    if (this.position === "bottom" || this.position === "top") {
      const measurer = CachedTextMeasurerPool.getMeasurer({ font: this.label });
      const domain = this.scale.getDomain();
      const reversed = domain[0] > domain[1];
      const direction = reversed ? -1 : 1;
      let lastTickPosition = -Infinity * direction;
      tickData.ticks = tickData.ticks.filter((data) => {
        if (Math.sign(data.translate - lastTickPosition) !== direction)
          return false;
        lastTickPosition = data.translate + measurer.textWidth(data.tickLabel, true) * direction;
        return true;
      });
    }
    return tickData;
  }
  getTicksData() {
    const ticks = [];
    const rawTicks = this.scale.ticks();
    const fractionDigits = rawTicks.reduce((max, tick) => Math.max(max, countFractionDigits(tick)), 0);
    const idGenerator = createIdsGenerator();
    const labelFormatter = this.label.format ? this.scale.tickFormat({ ticks: rawTicks, specifier: this.label.format }) : (x) => formatValue(x, fractionDigits);
    for (let index = 0; index < rawTicks.length; index++) {
      const tick = rawTicks[index];
      const translate = this.scale.convert(tick);
      if (!this.inRange(translate))
        continue;
      const tickLabel = this.label.formatter?.({ value: tick, index, fractionDigits }) ?? labelFormatter(tick);
      const tickId = idGenerator(tickLabel);
      ticks.push({ tick, tickId, tickLabel, translate });
    }
    return { rawTicks, fractionDigits, ticks };
  }
};
_AxisTicks.DefaultTickCount = 5;
_AxisTicks.DefaultMinSpacing = 50;
var AxisTicks = _AxisTicks;
var __FORCE_MODULE_DETECTION = 0;
function createButton(options, attrs) {
  const button = createElement("button", getClassName("ag-charts-input ag-charts-button", attrs));
  if (options.label !== void 0) {
    button.append(options.label);
  } else {
    button.append(createIcon(options.icon));
    button.ariaLabel = options.altText;
  }
  button.addEventListener("click", options.onPress);
  setAttributes(button, attrs);
  return button;
}
function createCheckbox(options, attrs) {
  const checkbox = createElement("input", getClassName("ag-charts-input ag-charts-checkbox", attrs));
  checkbox.type = "checkbox";
  checkbox.checked = options.checked;
  checkbox.addEventListener("change", (event) => options.onChange(checkbox.checked, event));
  checkbox.addEventListener("keydown", (event) => {
    if (isButtonClickEvent(event)) {
      event.preventDefault();
      checkbox.click();
    }
  });
  setAttributes(checkbox, attrs);
  return checkbox;
}
function createSelect(options, attrs) {
  const select = createElement("select", getClassName("ag-charts-input ag-charts-select", attrs));
  select.append(
    ...options.options.map((option) => {
      const optionEl = createElement("option");
      optionEl.value = option.value;
      optionEl.textContent = option.label;
      return optionEl;
    })
  );
  setAttribute(select, "data-preventdefault", false);
  select.value = options.value;
  select.addEventListener("change", (event) => options.onChange(select.value, event));
  setAttributes(select, attrs);
  return select;
}
function createTextArea(options, attrs) {
  const textArea = createElement("textarea", getClassName("ag-charts-input ag-charts-textarea", attrs));
  textArea.value = options.value;
  textArea.addEventListener("input", (event) => options.onChange(textArea.value, event));
  setAttributes(textArea, attrs);
  return textArea;
}
function createIcon(icon) {
  const el = createElement("span", `ag-charts-icon ag-charts-icon-${icon}`);
  setAttribute(el, "aria-hidden", true);
  return el;
}
function getClassName(baseClass, attrs) {
  if (attrs == null)
    return baseClass;
  return `${baseClass} ${attrs.class}`;
}
var ConicGradient = class extends Gradient {
  constructor(colorSpace, stops, angle2 = 0, bbox) {
    super(colorSpace, stops, bbox);
    this.angle = angle2;
  }
  createCanvasGradient(ctx, bbox) {
    const angleOffset = 90;
    const { angle: angle2 } = this;
    const radians = normalizeAngle360(toRadians(angle2 + angleOffset));
    const cx = bbox.x + bbox.width * 0.5;
    const cy = bbox.y + bbox.height * 0.5;
    return ctx.createConicGradient(radians, cx, cy);
  }
};
var SvgPath = class extends Path {
  constructor(d = "") {
    super();
    this.x = 0;
    this.y = 0;
    this.commands = [];
    this._d = "";
    this.d = d;
  }
  get d() {
    return this._d;
  }
  set d(d) {
    if (d === this._d)
      return;
    this._d = d;
    this.commands.length = 0;
    for (const [_, command, paramsString] of d.matchAll(/([A-Z])([0-9. ]*)/g)) {
      const params = paramsString.split(/\s+/g).map(Number);
      this.commands.push([command, params]);
    }
    this.checkPathDirty();
  }
  updatePath() {
    const { path, x, y } = this;
    path.clear();
    let lastX = x;
    let lastY = y;
    for (const [command, params] of this.commands) {
      switch (command) {
        case "M":
          path.moveTo(x + params[0], y + params[1]);
          lastX = x + params[0];
          break;
        case "C":
          path.cubicCurveTo(
            x + params[0],
            y + params[1],
            x + params[2],
            y + params[3],
            x + params[4],
            y + params[5]
          );
          lastX = x + params[4];
          lastY = y + params[5];
          break;
        case "H":
          path.lineTo(x + params[0], lastY);
          lastX = y + params[0];
          break;
        case "L":
          path.lineTo(x + params[0], y + params[1]);
          lastX = x + params[0];
          lastY = y + params[1];
          break;
        case "V":
          path.lineTo(lastX, y + params[0]);
          lastY = y + params[0];
          break;
        case "Z":
          path.closePath();
          break;
        default:
          throw new Error(`Could not translate command '${command}' with '${params.join(" ")}'`);
      }
    }
    path.closePath();
  }
};
__decorateClass([
  ScenePathChangeDetection()
], SvgPath.prototype, "x", 2);
__decorateClass([
  ScenePathChangeDetection()
], SvgPath.prototype, "y", 2);
var _ArrowUp = class _ArrowUp2 extends Marker {
  updatePath() {
    const s = this.size / 2;
    super.applyPath(s, _ArrowUp2.moves);
  }
};
_ArrowUp.className = "ArrowUp";
_ArrowUp.moves = [
  { x: 0, y: 0, t: "move" },
  { x: 1, y: 1.2 },
  { x: -0.5, y: 0 },
  { x: 0, y: 0.8 },
  { x: -1, y: 0 },
  { x: 0, y: -0.8 },
  { x: -0.5, y: 0 }
];
var ArrowUp = _ArrowUp;
var ArrowDown = class extends Marker {
  updatePath() {
    const s = this.size / 2;
    super.applyPath(
      s,
      ArrowUp.moves.map((m) => ({ x: m.x * -1, y: m.y * -1 }))
    );
  }
};
ArrowDown.className = "ArrowDown";
var exports_exports = {};
__export(exports_exports, {
  ButtonWidget: () => ButtonWidget,
  NativeWidget: () => NativeWidget,
  SliderWidget: () => SliderWidget,
  ToolbarWidget: () => ToolbarWidget,
  WIDGET_HTML_EVENTS: () => WIDGET_HTML_EVENTS,
  Widget: () => Widget,
  WidgetEventUtil: () => WidgetEventUtil
});
var canvasOverlay = "canvas-overlay";
var Popover = class extends BaseModuleInstance {
  constructor(ctx, id, options) {
    super();
    this.ctx = ctx;
    this.hideFns = [];
    this.moduleId = `popover-${id}`;
    if (options?.detached) {
      this.element = createElement("div");
    } else {
      this.element = ctx.domManager.addChild(canvasOverlay, this.moduleId);
    }
    this.element.setAttribute("role", "presentation");
    this.destroyFns.push(() => ctx.domManager.removeChild(canvasOverlay, this.moduleId));
  }
  attachTo(popover) {
    if (this.element.parentElement)
      return;
    popover.element.append(this.element);
  }
  hide(opts) {
    const { lastFocus = this.lastFocus } = opts ?? {};
    if (this.element.children.length === 0)
      return;
    this.hideFns.forEach((fn) => fn());
    lastFocus?.focus();
    this.lastFocus = void 0;
  }
  removeChildren() {
    this.element.replaceChildren();
  }
  showWithChildren(children, options) {
    if (!this.element.parentElement) {
      throw new Error("Can not show popover that has not been attached to a parent.");
    }
    const popover = createElement("div", "ag-charts-popover");
    if (options.ariaLabel != null) {
      popover.setAttribute("aria-label", options.ariaLabel);
    }
    if (options.class != null) {
      popover.classList.add(options.class);
    }
    popover.replaceChildren(...children);
    this.element.replaceChildren(popover);
    this.hideFns.push(() => this.removeChildren());
    if (options.onHide) {
      this.hideFns.push(options.onHide);
    }
    if (options.initialFocus && options.sourceEvent) {
      const lastFocus = getLastFocus(options.sourceEvent);
      if (lastFocus !== void 0) {
        this.lastFocus = lastFocus;
        this.initialFocus = options.initialFocus;
      }
    }
    return popover;
  }
  getPopoverElement() {
    return this.element.firstElementChild;
  }
  updatePosition(position) {
    const popover = this.getPopoverElement();
    if (!popover)
      return;
    popover.style.setProperty("right", "unset");
    popover.style.setProperty("bottom", "unset");
    if (position.x != null)
      popover.style.setProperty("left", `${Math.floor(position.x)}px`);
    if (position.y != null)
      popover.style.setProperty("top", `${Math.floor(position.y)}px`);
    this.initialFocus?.focus();
    this.initialFocus = void 0;
  }
};
var AnchoredPopover = class extends Popover {
  setAnchor(anchor, fallbackAnchor) {
    this.anchor = anchor;
    this.fallbackAnchor = fallbackAnchor;
    this.updatePosition(anchor);
    this.repositionWithinBounds();
  }
  showWithChildren(children, options) {
    const anchor = options.anchor ?? this.anchor;
    const fallbackAnchor = options.fallbackAnchor ?? this.fallbackAnchor;
    const popover = super.showWithChildren(children, options);
    if (anchor) {
      this.setAnchor(anchor, fallbackAnchor);
    }
    getWindow().requestAnimationFrame(() => {
      this.repositionWithinBounds();
    });
    return popover;
  }
  repositionWithinBounds() {
    const { anchor, ctx, fallbackAnchor } = this;
    const popover = this.getPopoverElement();
    if (!anchor || !popover)
      return;
    const canvasRect = ctx.domManager.getBoundingClientRect();
    const { offsetWidth: width2, offsetHeight: height2 } = popover;
    let x = clamp(0, anchor.x, canvasRect.width - width2);
    let y = clamp(0, anchor.y, canvasRect.height - height2);
    if (x !== anchor.x && fallbackAnchor?.x != null) {
      x = clamp(0, fallbackAnchor.x - width2, canvasRect.width - width2);
    }
    if (y !== anchor.y && fallbackAnchor?.y != null) {
      y = clamp(0, fallbackAnchor.y - height2, canvasRect.height - height2);
    }
    this.updatePosition({ x, y });
  }
};
var Menu = class extends AnchoredPopover {
  show(options) {
    const rows = options.items.map((item) => this.createRow(options, item));
    const popover = this.showWithChildren(rows, options);
    popover.classList.add("ag-charts-menu");
    popover.setAttribute("role", "menu");
    this.menuCloser = initMenuKeyNav({
      orientation: "vertical",
      menu: popover,
      buttons: rows,
      sourceEvent: options.sourceEvent,
      closeCallback: () => this.hide()
    });
    this.hideFns.push(() => {
      this.menuCloser?.finishClosing();
      this.menuCloser = void 0;
    });
  }
  createRow(options, item) {
    const { menuItemRole = "menuitem" } = options;
    const active = item.value === options.value;
    const row = createElement("div", "ag-charts-menu__row");
    row.setAttribute("role", menuItemRole);
    if (menuItemRole === "menuitemradio") {
      row.setAttribute("aria-checked", (options.value === item.value).toString());
    }
    if (typeof item.value === "string") {
      row.dataset.popoverId = item.value;
    }
    row.classList.toggle(`ag-charts-menu__row--active`, active);
    if (item.icon != null) {
      const icon = createElement("span", `ag-charts-menu__icon ${getIconClassNames(item.icon)}`);
      row.appendChild(icon);
    }
    const strokeWidthVisible = item.strokeWidth != null;
    if (strokeWidthVisible) {
      row.classList.toggle(`ag-charts-menu__row--stroke-width-visible`, strokeWidthVisible);
      row.style.setProperty("--strokeWidth", strokeWidthVisible ? `${item.strokeWidth}px` : null);
    }
    if (item.label != null) {
      const label = createElement("span", "ag-charts-menu__label");
      label.textContent = this.ctx.localeManager.t(item.label);
      row.appendChild(label);
    }
    if ("altText" in item) {
      row.ariaLabel = this.ctx.localeManager.t(item.altText);
    }
    const select = () => {
      options.onPress?.(item);
    };
    const onclick = (e) => {
      if (isButtonClickEvent(e)) {
        select();
        e.preventDefault();
        e.stopPropagation();
      }
    };
    row.addEventListener("keydown", onclick);
    row.addEventListener("click", onclick);
    row.addEventListener("mousemove", () => {
      row.focus({ preventScroll: true });
    });
    return row;
  }
};
var DraggablePopover = class extends Popover {
  constructor() {
    super(...arguments);
    this.dragged = false;
  }
  setDragHandle(dragHandle) {
    dragHandle.addListener("drag-start", (event) => {
      dragHandle.addClass(this.dragHandleDraggingClass);
      this.onDragStart(event);
    });
    dragHandle.addListener("drag-move", this.onDragMove.bind(this));
    dragHandle.addListener("drag-end", () => {
      dragHandle.removeClass(this.dragHandleDraggingClass);
      this.onDragEnd.bind(this);
    });
  }
  onDragStart(event) {
    const popover = this.getPopoverElement();
    if (!popover)
      return;
    event.sourceEvent.preventDefault();
    this.dragged = true;
    this.dragStartState = {
      client: Vec2.from(event.clientX, event.clientY),
      position: Vec2.from(
        Number(popover.style.getPropertyValue("left").replace("px", "")),
        Number(popover.style.getPropertyValue("top").replace("px", ""))
      )
    };
  }
  onDragMove(event) {
    const { dragStartState } = this;
    const popover = this.getPopoverElement();
    if (!dragStartState || !popover)
      return;
    const offset4 = Vec2.sub(Vec2.from(event.clientX, event.clientY), dragStartState.client);
    const position = Vec2.add(dragStartState.position, offset4);
    const bounds = this.ctx.domManager.getBoundingClientRect();
    const partialPosition = {};
    if (position.x >= bounds.x && position.x + popover.offsetWidth <= bounds.width) {
      partialPosition.x = position.x;
    }
    if (position.y >= bounds.y && position.y + popover.offsetHeight <= bounds.height) {
      partialPosition.y = position.y;
    }
    this.updatePosition(partialPosition);
  }
  onDragEnd() {
    this.dragStartState = void 0;
  }
};
var ToolbarButtonProperties = class extends BaseProperties {
};
__decorateClass([
  Validate(STRING, { optional: true })
], ToolbarButtonProperties.prototype, "icon", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ToolbarButtonProperties.prototype, "label", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ToolbarButtonProperties.prototype, "ariaLabel", 2);
__decorateClass([
  Validate(STRING, { optional: true })
], ToolbarButtonProperties.prototype, "tooltip", 2);
var ToolbarButtonWidget = class extends ButtonWidget {
  constructor(localeManager) {
    super();
    this.localeManager = localeManager;
  }
  update(options) {
    const { localeManager } = this;
    if (options.tooltip) {
      this.elem.title = localeManager.t(options.tooltip);
    }
    let innerHTML = "";
    if (options.icon != null) {
      innerHTML = `<span class="${getIconClassNames(options.icon)} ag-charts-toolbar__icon"></span>`;
    }
    if (options.label != null) {
      const label = localeManager.t(options.label);
      innerHTML = `${innerHTML}<span class="ag-charts-toolbar__label">${label}</span>`;
    }
    this.elem.innerHTML = innerHTML;
  }
  setChecked(checked) {
    setAttribute(this.elem, "aria-checked", checked);
  }
};
var BUTTON_ACTIVE_CLASS = "ag-charts-toolbar__button--active";
var BaseToolbar = class extends ToolbarWidget {
  constructor(localeManager, orientation = "horizontal") {
    super(orientation);
    this.localeManager = localeManager;
    this.horizontalSpacing = 10;
    this.verticalSpacing = 10;
    this.events = new Listeners();
    this.hasPrefix = false;
    this.buttonWidgets = [];
    this.addClass("ag-charts-toolbar");
    this.toggleClass("ag-charts-toolbar--horizontal", orientation === "horizontal");
    this.toggleClass("ag-charts-toolbar--vertical", orientation === "vertical");
  }
  addToolbarListener(eventType, handler) {
    return this.events.addListener(eventType, handler);
  }
  clearButtons() {
    for (const button of this.buttonWidgets) {
      button.destroy();
    }
    this.buttonWidgets.splice(0);
  }
  updateButtons(buttons) {
    const { buttonWidgets } = this;
    for (const [index, button] of buttons.entries()) {
      const buttonWidget = this.buttonWidgets.at(index) ?? this.createButton(index, button);
      buttonWidget.update(button);
    }
    for (let index = buttons.length; index < buttonWidgets.length; index++) {
      const button = this.buttonWidgets.at(index);
      button?.destroy();
    }
    this.buttonWidgets.splice(buttons.length);
    this.refreshButtonClasses();
  }
  updateButtonByIndex(index, button) {
    this.buttonWidgets.at(index)?.update(button);
  }
  clearActiveButton() {
    for (const button of this.buttonWidgets) {
      button.toggleClass(BUTTON_ACTIVE_CLASS, false);
    }
  }
  toggleActiveButtonByIndex(index) {
    if (index === -1)
      return;
    for (const [buttonIndex, button] of this.buttonWidgets.entries()) {
      button.toggleClass(BUTTON_ACTIVE_CLASS, index != null && index === buttonIndex);
    }
  }
  toggleButtonEnabledByIndex(index, enabled) {
    if (index === -1)
      return;
    this.buttonWidgets.at(index)?.setEnabled(enabled);
  }
  toggleSwitchCheckedByIndex(index, checked) {
    if (index === -1)
      return;
    this.buttonWidgets.at(index)?.setChecked(checked);
  }
  getButtonBounds() {
    return this.buttonWidgets.map((buttonWidget) => this.getButtonWidgetBounds(buttonWidget));
  }
  setButtonHiddenByIndex(index, hidden) {
    this.buttonWidgets.at(index)?.setHidden(hidden);
  }
  getButtonWidgetBounds(buttonWidget) {
    const parent = this.getBounds();
    const bounds = buttonWidget.getBounds();
    return new BBox(bounds.x + parent.x, bounds.y + parent.y, bounds.width, bounds.height);
  }
  refreshButtonClasses() {
    const { buttonWidgets, hasPrefix } = this;
    let first;
    let last;
    let section;
    for (const [index, buttonWidget] of buttonWidgets.entries()) {
      first = !hasPrefix && index === 0 || section != buttonWidget.section;
      last = index === buttonWidgets.length - 1 || buttonWidget.section != buttonWidgets.at(index + 1)?.section;
      buttonWidget.toggleClass("ag-charts-toolbar__button--first", first);
      buttonWidget.toggleClass("ag-charts-toolbar__button--last", last);
      buttonWidget.toggleClass("ag-charts-toolbar__button--gap", index > 0 && first);
      section = buttonWidget.section;
    }
  }
  createButton(index, button) {
    const buttonWidget = this.createButtonWidget();
    buttonWidget.addClass("ag-charts-toolbar__button");
    buttonWidget.addListener("click", (event) => {
      const buttonOptions = { index, ...button instanceof BaseProperties ? button.toJson() : button };
      const buttonBounds = this.getButtonWidgetBounds(buttonWidget);
      this.events.dispatch("button-pressed", { event, button: buttonOptions, buttonBounds });
    });
    buttonWidget.addListener("focus", () => {
      this.events.dispatch("button-focused", { button: { index } });
    });
    if (button.section) {
      buttonWidget.section = button.section;
    }
    this.buttonWidgets.push(buttonWidget);
    this.addChild(buttonWidget);
    return buttonWidget;
  }
};
var Toolbar = class extends BaseToolbar {
  createButtonWidget() {
    return new ToolbarButtonWidget(this.localeManager);
  }
};
var FloatingToolbarPopover = class extends DraggablePopover {
  constructor(ctx, id, onPopoverMoved) {
    super(ctx, id);
    this.onPopoverMoved = onPopoverMoved;
    this.dragHandleDraggingClass = "ag-charts-floating-toolbar__drag-handle--dragging";
  }
  show(children, options) {
    this.showWithChildren(children, {
      ...options,
      class: "ag-charts-floating-toolbar"
    });
  }
  hide() {
    this.dragged = false;
    super.hide();
  }
  getBounds() {
    const element2 = this.getPopoverElement();
    return new BBox(
      element2?.offsetLeft ?? 0,
      element2?.offsetTop ?? 0,
      element2?.offsetWidth ?? 0,
      element2?.offsetHeight ?? 0
    );
  }
  hasBeenDragged() {
    return this.dragged;
  }
  setAnchor(anchor, horizontalSpacing, verticalSpacing) {
    const element2 = this.getPopoverElement();
    if (!element2)
      return;
    const position = anchor.position ?? "above";
    const { offsetWidth: width2, offsetHeight: height2 } = element2;
    let top = anchor.y - height2 - verticalSpacing;
    let left = anchor.x - width2 / 2;
    if (position === "below") {
      top = anchor.y + verticalSpacing;
    } else if (position === "right") {
      top = anchor.y - height2 / 2;
      left = anchor.x + horizontalSpacing;
    } else if (position === "above-left") {
      left = anchor.x;
    }
    this.updatePosition({ x: left, y: top });
  }
  ignorePointerEvents() {
    const element2 = this.getPopoverElement();
    if (element2)
      element2.style.pointerEvents = "none";
  }
  capturePointerEvents() {
    const element2 = this.getPopoverElement();
    if (element2)
      element2.style.pointerEvents = "unset";
  }
  updatePosition(position) {
    const bounds = this.getBounds();
    const canvasRect = this.ctx.domManager.getBoundingClientRect();
    position.x = Math.floor(clamp(0, position.x, canvasRect.width - bounds.width));
    position.y = Math.floor(clamp(0, position.y, canvasRect.height - bounds.height));
    super.updatePosition(position);
    this.onPopoverMoved();
  }
};
var FloatingToolbar = class extends BaseToolbar {
  constructor(ctx, id) {
    super(ctx.localeManager);
    this.hasPrefix = true;
    this.popover = new FloatingToolbarPopover(ctx, id, this.onPopoverMoved.bind(this));
    this.dragHandle = new DragHandleWidget(ctx.localeManager.t("toolbarAnnotationsDragHandle"));
    this.popover.setDragHandle(this.dragHandle);
  }
  show(options) {
    this.popover.show([this.dragHandle.getElement(), this.getElement()], options);
  }
  hide() {
    this.popover.hide();
  }
  setAnchor(anchor) {
    this.popover.setAnchor(anchor, this.horizontalSpacing, this.verticalSpacing);
  }
  hasBeenDragged() {
    return this.popover.hasBeenDragged();
  }
  ignorePointerEvents() {
    this.popover.ignorePointerEvents();
  }
  capturePointerEvents() {
    this.popover.capturePointerEvents();
  }
  onPopoverMoved() {
    const popoverBounds = this.popover.getBounds();
    if (this.popoverBounds?.equals(popoverBounds))
      return;
    this.popoverBounds = popoverBounds.clone();
    const buttonBounds = this.getButtonBounds();
    this.events.dispatch("toolbar-moved", { popoverBounds, buttonBounds });
  }
  getButtonWidgetBounds(buttonWidget) {
    const popoverBounds = this.popover.getBounds();
    const bounds = super.getButtonWidgetBounds(buttonWidget);
    const dragHandleBounds = this.dragHandle.getBounds();
    return new BBox(
      bounds.x + popoverBounds.x - dragHandleBounds.width,
      bounds.y + popoverBounds.y,
      bounds.width,
      bounds.height
    );
  }
};
var DragHandleWidget = class extends NativeWidget {
  constructor(title) {
    super(createElement("div", "ag-charts-floating-toolbar__drag-handle"));
    const icon = new NativeWidget(
      createElement("span", `${getIconClassNames("drag-handle")} ag-charts-toolbar__icon`)
    );
    icon.setAriaHidden(true);
    this.addChild(icon);
    this.elem.title = title;
  }
};
var motion = { ...fromToMotion_exports, ...resetMotion_exports };
if (typeof module.exports == "object" && typeof exports == "object") {
  var __cp = (to, from, except, desc) => {
    if ((from && typeof from === "object") || typeof from === "function") {
      for (let key of Object.getOwnPropertyNames(from)) {
        if (!Object.prototype.hasOwnProperty.call(to, key) && key !== except)
        Object.defineProperty(to, key, {
          get: () => from[key],
          enumerable: !(desc = Object.getOwnPropertyDescriptor(from, key)) || desc.enumerable,
        });
      }
    }
    return to;
  };
  module.exports = __cp(module.exports, exports);
}
return module.exports;
}))
