'use strict';

const array = require('./array-249289f2.js');
const typography = require('./typography-4560e7f1.js');
const pixel = require('./pixel-98f2a10c.js');

/** The GraphContextFactory class provides a method to create and return either a HTMLCanvasElement or SVGElement based on the specified mode and container element. */
class GraphContextFactory {
  /**
   * This function returns either a HTMLCanvasElement or an SVGElement based on the specified mode and container.
   *
   * @param {ChartGraphMode} mode - A string that specifies the mode of the chart graph. It can be either 'canvas' or 'svg'.
   * @param {HTMLElement} container - HTMLElement - the HTML element that will contain the chart/graph.
   * @returns {SVGElement | HTMLCanvasElement} either a HTMLCanvasElement or an SVGElement depending on the value of the `mode` parameter.
   */
  static get(mode, container) {
    if (mode === 'canvas') {
      const canvas = container.querySelector('canvas');
      let context;
      if (canvas) {
        context = canvas;
      }
      else {
        // eslint-disable-next-line no-restricted-globals
        context = document.createElement('canvas');
        context = container.appendChild(context);
      }
      return context;
    }
    else {
      const svg = container.querySelector('svg');
      let context;
      if (svg) {
        context = svg;
      }
      else {
        // eslint-disable-next-line no-restricted-globals
        context = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        context = container.appendChild(context);
      }
      return context;
    }
  }
}

/**
 * defining an abstract class called `BaseRenderer` that takes a generic type `T` which
 * can be either an `SVGElement` or a `HTMLCanvasElement`
 */
class BaseRenderer {
  /**
   * This is a constructor function that takes a parameter of type T and sets it as a protected property called "context".
   *
   * @param {unknown} context - The "context" parameter is a protected property of a class constructor that is
   * of type "T". It is used to store a reference to an object or data that is required by the class
   * methods to perform their tasks
   */
  constructor(context) {
    this.context = context;
  }
}

/**
 * D3 Selection Polyfill - A lightweight DOM selection and manipulation utility.
 *
 * This is a drop-in replacement for d3-selection, implementing only the methods
 * used in the Vega chart rendering system.
 *
 * Supported methods: select, selectAll, append, attr, property, text, datum,
 * call, node, nodes, each, remove, clone, transition, duration.
 *
 * @see VD-5022 - [Zero Dependencies] remove d3 dependency
 */
/**
 * A lightweight selection class mimicking d3-selection's chainable API.
 * Wraps an array of DOM elements and provides attribute/property/child manipulation.
 */
class D3SelectionPolyfill {
  /**
   * @param {Element[]} elements - Array of DOM elements to wrap.
   * @param {*} [datum] - Optional bound datum for the selection.
   */
  constructor(elements, datum) {
    this._groups = elements;
    this._datum = datum;
  }
  /**
   * Selects the first descendant element matching the selector.
   *
   * @template DescElement
   * @template Datum
   * @template GElement
   * @param {string} selector - CSS selector string.
   * @returns {D3SelectionPolyfill<DescElement, Datum, GElement, Datum>} A new selection wrapping the matched element.
   */
  select(selector) {
    const el = this._groups[0];
    if (!el) {
      return new D3SelectionPolyfill([]);
    }
    const found = el.querySelector(selector);
    return new D3SelectionPolyfill(found ? [found] : []);
  }
  /**
   * Selects all descendant elements matching the selector.
   *
   * @template DescElement
   * @template NewDatum
   * @template GElement
   * @template Datum
   * @param {string} selector - CSS selector string.
   * @returns {D3SelectionPolyfill<DescElement, NewDatum, GElement, Datum>} A new selection wrapping all matched elements.
   */
  selectAll(selector) {
    const el = this._groups[0];
    if (!el) {
      return new D3SelectionPolyfill([]);
    }
    const found = Array.from(el.querySelectorAll(selector));
    return new D3SelectionPolyfill(found);
  }
  /**
   * Appends a new child element to each element in the selection.
   * Accepts either a tag name string or a factory function that returns a DOM element.
   *
   * @template ChildElement
   * @template Datum
   * @template GElement
   * @param {string | Function} tagOrFactory - Tag name (e.g. 'g', 'path') or a factory function.
   * @returns {D3SelectionPolyfill<ChildElement, Datum, GElement, Datum>} A new selection wrapping the appended elements.
   */
  append(tagOrFactory) {
    const results = [];
    for (const parent of this._groups) {
      let child;
      if (typeof tagOrFactory === 'function') {
        child = tagOrFactory();
      }
      else {
        child = parent.ownerDocument.createElementNS('http://www.w3.org/2000/svg', tagOrFactory);
      }
      parent.appendChild(child);
      results.push(child);
    }
    return new D3SelectionPolyfill(results, this._datum);
  }
  /**
   * Sets or gets an attribute on each element.
   * If value is a function, it is called with the bound datum.
   *
   * @param {...*} args - Attribute name, and optionally a value or function returning a value.
   * @returns {any} This selection for chaining, or the attribute value if getting.
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  attr(...args) {
    const name = args[0];
    if (args.length === 1) {
      const el = this._groups[0];
      return el ? el.getAttribute(name) : null;
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const value = args[1];
    for (let i = 0; i < this._groups.length; i++) {
      const el = this._groups[i];
      const resolvedValue = typeof value === 'function' ? value.call(el, this._datum, i, this._groups) : value;
      if (resolvedValue === null || resolvedValue === undefined) {
        el.removeAttribute(name);
      }
      else {
        el.setAttribute(name, String(resolvedValue));
      }
    }
    return this;
  }
  /**
   * Sets a JavaScript property on each element.
   *
   * @param {string} name - Property name.
   * @param {unknown} value - Property value.
   * @returns {this} This selection for chaining.
   */
  property(name, value) {
    for (const el of this._groups) {
      el[name] = value;
    }
    return this;
  }
  /**
   * Sets the text content of each element.
   *
   * @param {string} value - Text content string.
   * @returns {this} This selection for chaining.
   */
  text(value) {
    for (const el of this._groups) {
      el.textContent = value;
    }
    return this;
  }
  /**
   * Binds a datum to the selection.
   *
   * @template NewDatum
   * @template GElement
   * @template PElement
   * @template PDatum
   * @param {*} data - The datum to bind.
   * @returns {D3SelectionPolyfill<GElement, NewDatum, PElement, PDatum>} A new selection with the bound datum.
   */
  datum(data) {
    return new D3SelectionPolyfill(this._groups, data);
  }
  /**
   * Calls a function with this selection as argument. Used for grouping operations.
   *
   * @param {Function} fn - Function to call.
   * @param {...*} args - Additional arguments.
   * @returns {this} This selection for chaining.
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  call(fn, ...args) {
    fn(this, ...args);
    return this;
  }
  /**
   * Returns the first DOM node in the selection, or null.
   *
   * @template GElement
   * @returns {GElement | null} The first element or null.
   */
  node() {
    return this._groups[0] || null;
  }
  /**
   * Returns all DOM nodes in the selection as an array.
   *
   * @template GElement
   * @returns {GElement[]} Array of elements.
   */
  nodes() {
    return [...this._groups];
  }
  /**
   * Iterates over each element, calling the provided function.
   * The function is called with `this` set to the current DOM element.
   *
   * @param {Function} fn - Callback function.
   * @returns {this} This selection for chaining.
   */
  each(fn) {
    for (let i = 0; i < this._groups.length; i++) {
      fn.call(this._groups[i], this._datum, i, this._groups);
    }
    return this;
  }
  /**
   * Removes all elements in the selection from the DOM.
   *
   * @returns {this} This selection for chaining.
   */
  remove() {
    var _a;
    for (const el of this._groups) {
      (_a = el.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(el);
    }
    return this;
  }
  /**
   * Clones each element in the selection (shallow clone) and inserts after the original.
   *
   * @template GElement
   * @template Datum
   * @template PElement
   * @template PDatum
   * @returns {D3SelectionPolyfill<GElement, Datum, PElement, PDatum>} A new selection wrapping the cloned elements.
   */
  clone() {
    var _a;
    const clones = [];
    for (const el of this._groups) {
      const cloned = el.cloneNode(false);
      (_a = el.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(cloned, el.nextSibling);
      clones.push(cloned);
    }
    return new D3SelectionPolyfill(clones, this._datum);
  }
  /**
   * Creates a transition-like object. This is a simplified polyfill that
   * applies attribute changes immediately (no actual animation), which is
   * sufficient for Vega's usage of hover path swapping.
   *
   * @param {*} [_name] - Transition name (ignored in polyfill).
   * @returns {this} This selection for chaining (acts as a no-op).
   */
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  transition(_name) {
    return this;
  }
  /**
   * Sets the transition duration. No-op in this polyfill since
   * transitions are applied immediately.
   *
   * @param {number} _ms - Duration in milliseconds (ignored).
   * @returns {this} This selection for chaining.
   */
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  duration(_ms) {
    return this;
  }
}
/**
 * Selects a DOM element by wrapping it in a D3SelectionPolyfill.
 * Mimics d3.select().
 *
 * @template GElement
 * @param {Element | EventTarget} element - A DOM element or EventTarget to wrap.
 * @returns {D3SelectionPolyfill<GElement>} A new D3SelectionPolyfill wrapping the element.
 */
function select(element) {
  return new D3SelectionPolyfill([element]);
}
/**
 * Creates a detached SVG element (e.g., 'svg:text', 'svg:circle', 'svg:path').
 * Mimics d3.create().
 *
 * @template GElement
 * @param {string} qualifiedName - A qualified name like 'svg:text' or 'svg:circle'.
 * @returns {D3SelectionPolyfill<GElement>} A new D3SelectionPolyfill wrapping the created element.
 */
function create(qualifiedName) {
  const parts = qualifiedName.split(':');
  const tagName = parts.length > 1 ? parts[1] : parts[0];
  // eslint-disable-next-line no-restricted-globals
  const el = document.createElementNS('http://www.w3.org/2000/svg', tagName);
  return new D3SelectionPolyfill([el]);
}

/* eslint-disable jsdoc/require-param-type, jsdoc/require-returns-type, jsdoc/require-param, jsdoc/require-returns */
/**
 * D3 Shape Polyfill - Lightweight SVG shape generators.
 *
 * This is a drop-in replacement for d3-shape, implementing only the methods
 * used in the Vega chart rendering system: line, arc, and pie.
 *
 * @see VD-5022 - [Zero Dependencies] remove d3 dependency
 */
/**
 * A line generator that creates SVG path data strings from data arrays.
 * Mimics d3.line() with .x() and .y() value extractors.
 */
class LineGenerator {
  constructor() {
    /** Default x value extractor: reads `.x` property or first array index. */
    this.xAccessor = (d) => { var _a; return (_a = d.x) !== null && _a !== void 0 ? _a : d[0]; };
    /** Default y value extractor: reads `.y` property or second array index. */
    this.yAccessor = (d) => { var _a; return (_a = d.y) !== null && _a !== void 0 ? _a : d[1]; };
  }
  /**
   * Sets the x accessor function.
   *
   * @param accessor - Function that returns the x value for a datum.
   * @returns This generator for chaining.
   */
  x(accessor) {
    this.xAccessor = accessor;
    return this;
  }
  /**
   * Sets the y accessor function.
   *
   * @param accessor - Function that returns the y value for a datum.
   * @returns This generator for chaining.
   */
  y(accessor) {
    this.yAccessor = accessor;
    return this;
  }
  /**
   * Generates an SVG path data string for the given data.
   * Called as a function (used by d3's attr('d', lineGenerator)).
   *
   * @param data - Array of data points.
   * @returns SVG path data string (M...L...L...).
   */
  generate(data) {
    if (!data || data.length === 0) {
      return '';
    }
    const parts = [];
    for (let i = 0; i < data.length; i++) {
      const xVal = this.xAccessor(data[i], i);
      const yVal = this.yAccessor(data[i], i);
      parts.push(i === 0 ? `M${xVal},${yVal}` : `L${xVal},${yVal}`);
    }
    return parts.join('');
  }
}
/**
 * Creates a line generator. Mimics d3.line<T>().
 * The returned object is also callable as a function for d3 compatibility.
 *
 * @returns A new LineGenerator with callable function interface.
 */
function line() {
  const generator = new LineGenerator();
  /* eslint-disable jsdoc/require-jsdoc */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const fn = (data) => generator.generate(data);
  fn.x = (accessor) => {
    generator.x(accessor);
    return fn;
  };
  fn.y = (accessor) => {
    generator.y(accessor);
    return fn;
  };
  fn.generate = (data) => generator.generate(data);
  /* eslint-enable jsdoc/require-jsdoc */
  return fn;
}
// ─── Arc Generator ──────────────────────────────────────────────────
/**
 * An arc generator that creates SVG path data strings for arc/pie slices.
 * Mimics d3.arc<T>() with .innerRadius() and .outerRadius() value setters.
 */
class ArcGenerator {
  constructor() {
    /** Inner radius value for the arc. */
    this.innerRadiusValue = 0;
    /** Outer radius value for the arc. */
    this.outerRadiusValue = 0;
  }
  /**
   * Sets the inner radius for the arc.
   *
   * @param radius - Inner radius value.
   * @returns This generator for chaining.
   */
  innerRadius(radius) {
    this.innerRadiusValue = radius;
    return this;
  }
  /**
   * Sets the outer radius for the arc.
   *
   * @param radius - Outer radius value.
   * @returns This generator for chaining.
   */
  outerRadius(radius) {
    this.outerRadiusValue = radius;
    return this;
  }
  /**
   * Generates an SVG path data string for an arc datum.
   * The datum must have startAngle and endAngle properties (in angle units).
   *
   * @param d - Arc datum with startAngle and endAngle.
   * @returns SVG path data string for the arc.
   */
  generate(d) {
    const datum = d;
    const startAngle = datum.startAngle - Math.PI / 2;
    const endAngle = datum.endAngle - Math.PI / 2;
    const innerR = this.innerRadiusValue;
    const outerR = this.outerRadiusValue;
    const angleDiff = endAngle - startAngle;
    const largeArcFlag = Math.abs(angleDiff) >= Math.PI ? 1 : 0;
    // Outer arc endpoints
    const outerStartX = outerR * Math.cos(startAngle);
    const outerStartY = outerR * Math.sin(startAngle);
    const outerEndX = outerR * Math.cos(endAngle);
    const outerEndY = outerR * Math.sin(endAngle);
    if (innerR > 0) {
      // Donut arc: outer arc clockwise + inner arc counter-clockwise
      const innerEndX = innerR * Math.cos(endAngle);
      const innerEndY = innerR * Math.sin(endAngle);
      const innerStartX = innerR * Math.cos(startAngle);
      const innerStartY = innerR * Math.sin(startAngle);
      return [
        `M${outerStartX},${outerStartY}`,
        `A${outerR},${outerR},0,${largeArcFlag},1,${outerEndX},${outerEndY}`,
        `L${innerEndX},${innerEndY}`,
        `A${innerR},${innerR},0,${largeArcFlag},0,${innerStartX},${innerStartY}`,
        'Z',
      ].join('');
    }
    else {
      // Pie arc: start at outer edge, arc, line to center, close
      return [
        `M${outerStartX},${outerStartY}`,
        `A${outerR},${outerR},0,${largeArcFlag},1,${outerEndX},${outerEndY}`,
        'L0,0',
        'Z',
      ].join('');
    }
  }
}
/**
 * Creates an arc generator. Mimics d3.arc<T>().
 * The returned object is also callable as a function for d3 compatibility.
 *
 * @returns A new ArcGenerator with callable function interface.
 */
function arc() {
  const generator = new ArcGenerator();
  /* eslint-disable jsdoc/require-jsdoc */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const fn = (d) => generator.generate(d);
  fn.innerRadius = (radius) => {
    generator.innerRadius(radius);
    return fn;
  };
  fn.outerRadius = (radius) => {
    generator.outerRadius(radius);
    return fn;
  };
  fn.generate = (d) => generator.generate(d);
  /* eslint-enable jsdoc/require-jsdoc */
  return fn;
}
/**
 * A pie layout generator that computes start/end angles for data items.
 * Mimics d3.pie<T>() with .value() setter.
 */
class PieGenerator {
  constructor() {
    /** Default value extractor: reads `.value` property or falls back to 0. */
    this.valueAccessor = (d) => { var _a; return (_a = d.value) !== null && _a !== void 0 ? _a : 0; };
  }
  /**
   * Sets the value accessor function.
   *
   * @param accessor - Function that returns the numeric value for each datum.
   * @returns This generator for chaining.
   */
  value(accessor) {
    this.valueAccessor = accessor;
    return this;
  }
  /**
   * Computes pie arc data from the input data array.
   *
   * @param data - Array of data items.
   * @returns Array of PieArcDatum with computed angles.
   */
  generate(data) {
    const values = data.map((d) => this.valueAccessor(d));
    const total = values.reduce((sum, v) => sum + v, 0);
    const n = data.length;
    // Sort indices by descending value (d3.pie default sort)
    const indices = Array.from({ length: n }, (_, i) => i);
    indices.sort((a, b) => values[b] - values[a]);
    // Assign angles in sorted order, place arcs at original indices
    const arcs = new Array(n);
    let currentAngle = 0;
    for (const index of indices) {
      const angle = total > 0 ? (values[index] / total) * 2 * Math.PI : 0;
      arcs[index] = {
        data: data[index],
        index: index,
        value: values[index],
        startAngle: currentAngle,
        endAngle: currentAngle + angle,
        padAngle: 0,
      };
      currentAngle += angle;
    }
    return arcs;
  }
}
/**
 * Creates a pie layout generator. Mimics d3.pie<T>().
 * The returned object is also callable as a function for d3 compatibility.
 *
 * @returns A new PieGenerator with callable function interface.
 */
function pie() {
  const generator = new PieGenerator();
  /* eslint-disable jsdoc/require-jsdoc */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const fn = (data) => generator.generate(data);
  fn.value = (accessor) => {
    generator.value(accessor);
    return fn;
  };
  fn.generate = (data) => generator.generate(data);
  /* eslint-enable jsdoc/require-jsdoc */
  return fn;
}

/**
 * D3 Axis Polyfill - Lightweight SVG axis generators.
 *
 * This is a drop-in replacement for d3-axis, implementing only the methods
 * used in the Vega chart rendering system: axisBottom and axisLeft.
 *
 * @see VD-5022 - [Zero Dependencies] remove d3 dependency
 */
/**
 * Internal axis generator class.
 */
class AxisGenerator {
  /**
   * @param {AxisScale} scale - The scale to use for the axis.
   * @param {string} orientation - 'bottom' for x-axis, 'left' for y-axis.
   */
  constructor(scale, orientation) {
    this._tickCount = 10;
    this._tickFormatter = null;
    this._scale = scale;
    this._orientation = orientation;
  }
  /**
   * Sets the number of ticks.
   *
   * @param {number} count - Desired number of ticks.
   */
  setTickCount(count) {
    this._tickCount = count;
  }
  /**
   * Sets a custom tick format function.
   *
   * @param {Function} formatter - Function to format tick labels.
   */
  setTickFormatter(formatter) {
    this._tickFormatter = formatter;
  }
  /**
   * Renders the axis into the given SVG <g> selection.
   * Creates a domain path, tick lines, and tick text labels.
   *
   * @param {D3SelectionPolyfill} selection - A D3SelectionPolyfill wrapping an SVG <g> element.
   */
  render(selection) {
    const g = selection.node();
    if (!g)
      return;
    const doc = g.ownerDocument;
    const tickValues = this.getTickValues();
    const formatter = this.getFormatter();
    const offset = 0.5;
    // Compute band centering offset (d3's center() function)
    const bandOffset = typeof this._scale.bandwidth === 'function'
      ? Math.max(0, this._scale.bandwidth() - offset * 2) / 2
      : 0;
    const range = this._scale.range();
    const range0 = +range[0] + offset;
    const range1 = +range[range.length - 1] + offset;
    // Create domain path (with outer tick marks, matching d3's tickSizeOuter = 6)
    const domain = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
    domain.setAttribute('class', 'domain');
    domain.setAttribute('stroke', 'currentColor');
    if (this._orientation === 'bottom') {
      domain.setAttribute('d', `M${range0},6V${offset}H${range1}V6`);
    }
    else {
      domain.setAttribute('d', `M-6,${range0}H${offset}V${range1}H-6`);
    }
    g.appendChild(domain);
    // Create ticks
    for (const tickValue of tickValues) {
      const position = this._scale(tickValue);
      if (position === undefined)
        continue;
      const finalPosition = position + bandOffset + offset;
      const tickG = doc.createElementNS('http://www.w3.org/2000/svg', 'g');
      tickG.setAttribute('class', 'tick');
      tickG.setAttribute('opacity', '1');
      const tickLine = doc.createElementNS('http://www.w3.org/2000/svg', 'line');
      tickLine.setAttribute('stroke', 'currentColor');
      const tickText = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
      tickText.setAttribute('fill', 'currentColor');
      tickText.textContent = formatter(tickValue);
      // eslint-disable-next-line spellcheck/spell-checker
      const verticalOffset = this._orientation === 'bottom' ? '0.71em' : '0.32em';
      if (this._orientation === 'bottom') {
        tickG.setAttribute('transform', `translate(${finalPosition},0)`);
        tickLine.setAttribute('y2', '6');
        tickText.setAttribute('y', '9');
        // eslint-disable-next-line spellcheck/spell-checker
        tickText.setAttribute('dy', verticalOffset);
      }
      else {
        tickG.setAttribute('transform', `translate(0,${finalPosition})`);
        tickLine.setAttribute('x2', '-6');
        tickText.setAttribute('x', '-9');
        // eslint-disable-next-line spellcheck/spell-checker
        tickText.setAttribute('dy', verticalOffset);
      }
      tickG.appendChild(tickLine);
      tickG.appendChild(tickText);
      g.appendChild(tickG);
    }
    // Set axis group attributes (matching d3)
    g.setAttribute('fill', 'none');
    g.setAttribute('font-size', '10');
    g.setAttribute('font-family', 'sans-serif');
    g.setAttribute('text-anchor', this._orientation === 'bottom' ? 'middle' : 'end');
  }
  /**
   * Gets tick values from the scale.
   *
   * @template Domain
   * @returns {Domain[]} Array of tick domain values.
   */
  getTickValues() {
    if (this._scale.ticks) {
      return this._scale.ticks(this._tickCount);
    }
    if (this._scale.domain) {
      return this._scale.domain();
    }
    return [];
  }
  /**
   * Gets the tick formatter function.
   *
   * @template Domain
   * @returns {(d: Domain) => string} A function that converts tick values to strings.
   */
  getFormatter() {
    if (this._tickFormatter) {
      return this._tickFormatter;
    }
    if (this._scale.tickFormat) {
      return this._scale.tickFormat(this._tickCount);
    }
    return (d) => String(d);
  }
}
/**
 * Creates a bottom-oriented axis generator. Mimics d3.axisBottom().
 *
 * @template Domain
 * @param {AxisScale} scale - The scale to use.
 * @returns {Axis<Domain>} An Axis callable that renders into a <g> element.
 */
function axisBottom(scale) {
  const generator = new AxisGenerator(scale, 'bottom');
  /* eslint-disable jsdoc/require-jsdoc */
  const axisFn = Object.assign(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (selection) => {
    generator.render(selection);
  }, {
    ticks: (count) => {
      generator.setTickCount(count);
      return axisFn;
    },
    tickFormat: (formatter) => {
      generator.setTickFormatter(formatter);
      return axisFn;
    },
  });
  /* eslint-enable jsdoc/require-jsdoc */
  return axisFn;
}
/**
 * Creates a left-oriented axis generator. Mimics d3.axisLeft().
 *
 * @template Domain
 * @param {AxisScale} scale - The scale to use.
 * @returns {Axis<Domain>} An Axis callable that renders into a <g> element.
 */
function axisLeft(scale) {
  const generator = new AxisGenerator(scale, 'left');
  /* eslint-disable jsdoc/require-jsdoc */
  const axisFn = Object.assign(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (selection) => {
    generator.render(selection);
  }, {
    ticks: (count) => {
      generator.setTickCount(count);
      return axisFn;
    },
    tickFormat: (formatter) => {
      generator.setTickFormatter(formatter);
      return axisFn;
    },
  });
  /* eslint-enable jsdoc/require-jsdoc */
  return axisFn;
}

/**  This class is used to render charts using SVG elements. */
class SVGRenderer extends BaseRenderer {
  /**
   * The function sets the layout of a chart using D3 and SVG.
   *
   * @param {number} width - chart width
   * @param {number} height - chart height
   * @param {number} top - chart margin top
   * @param {number} left - chart margin left
   */
  setLayout(width, height, top, left) {
    select(this.context)
      .attr('width', width)
      .attr('height', height)
      .attr('viewBox', [0, 0, width, height])
      .property('style', 'display:block;max-width:100%;height:auto;')
      .call((g) => {
      g.append('g')
        .attr('class', 'vega-chart-draw-g')
        .attr('transform', `translate(${left},${top})`);
    })
      .call((g) => {
      g.append('g')
        .attr('class', 'vega-chart-legend-g')
        .attr('transform', `translate(${left / 3},${top / 4})`);
    });
  }
  /**
   * This function draws a line on a chart using D3.js library.
   *
   * @param {ChartPosition} from - The starting position of the line to be drawn on the chart. It is an
   * object with two properties: x and y, representing the x and y coordinates of the starting point respectively.
   * @param {ChartPosition} to - The "to" parameter is a ChartPosition object that represents the ending
   * point of the line to be drawn. It contains the x and y coordinates of the point on the chart where the line should end.
   * @param {string} color - The color of the line
   */
  drawLine(from, to, color) {
    select(this.context)
      .select('.vega-chart-draw-g')
      .append('line')
      .attr('x1', from.x)
      .attr('y1', from.y)
      .attr('x2', to.x)
      .attr('y2', to.y)
      .attr('stroke', color);
  }
  /**
   * This function draws an x-axis on a chart using D3 and a given scale and end point.
   *
   * @param {ChartExtend<unknown>} extend - which is an object that contains information about the chart's scale and end position on the y-axis. The `scale` property
   * is a D3 scale object that maps data values to pixel positions on the x-axis
   * @param {string} color - The stroke color of axis
   * @param {string} textStyle - The text style of the axis
   */
  drawXAxis(extend, color, textStyle) {
    const { scale, end, labelFormatter, direction, height } = extend;
    let axis = axisBottom(scale);
    if (labelFormatter) {
      axis = axis.tickFormat(labelFormatter);
    }
    select(this.context)
      .select('.vega-chart-draw-g')
      .append('g')
      .attr('class', 'vega-chart-x-axis')
      .attr('transform', `translate(0, ${end.y})`)
      .call(axis)
      .call((g) => {
      g.select('.domain').attr('stroke-width', 2).attr('stroke', color);
    })
      .call((g) => {
      g.selectAll('line').attr('stroke', color);
      g.selectAll('text').property('style', textStyle);
    })
      .call((g) => {
      if (direction === 'horizontal') {
        g.selectAll('line').clone().attr('y2', `${-height}`);
        g.select('.domain').attr('stroke-width', 0);
      }
    });
  }
  /**
   * This function draws the Y-axis of a chart using D3 and a given scale.
   *
   * @param {ChartExtend<unknown>} extend -  It likely contains additional information or settings related to the chart being drawn, but without more context it's
   * difficult to say exactly what it contains.
   * @param {string} color - The stroke color of the axis
   * @param {string} textStyle - The text style of the axis
   */
  drawYAxis(extend, color, textStyle) {
    const { scale, labelFormatter, width, tickSize, direction } = extend;
    let axis = axisLeft(scale).ticks(tickSize);
    if (labelFormatter) {
      axis = axis.tickFormat(labelFormatter);
    }
    select(this.context)
      .select('.vega-chart-draw-g')
      .append('g')
      .attr('class', 'vega-chart-y-axis')
      .call(axis)
      .call((g) => {
      g.select('.domain').attr('stroke-width', 0).attr('stroke', color);
    })
      .call((g) => {
      g.selectAll('line').attr('stroke-width', 2).attr('stroke', color);
      g.selectAll('text').property('style', textStyle);
    })
      .call((g) => {
      if (direction !== 'horizontal') {
        g.selectAll('line').clone().attr('x2', `${width}`);
      }
      else {
        g.select('.domain').attr('stroke-width', 2).attr('stroke', color);
      }
    });
  }
  /**
   * This function draws a circle with a given center, radius, and color using D3.js.
   *
   * @param {ChartPosition} center - ChartPosition, which is an object containing the x and y coordinates of the center of the circle.
   * @param {number} radius - The radius parameter is a number that specifies the radius of the circle to be drawn.
   * @param {string} fillColor - The color parameter is a string that represents the color of the circle to be drawn
   * @param {number} strokeWidth - the border width
   * @param {string} strokeColor - the border color
   */
  drawCircle(center, radius, fillColor, strokeWidth, strokeColor) {
    select(this.context)
      .select('.vega-chart-draw-g')
      .append(() => this.getCircleNode(center, radius, fillColor, strokeWidth, strokeColor));
  }
  /**
   * This function draws text on a chart at a specified position using D3.js.
   *
   * @param {ChartPosition} position - ChartPosition is an object that contains the x and y coordinates where the text will be positioned on the chart.
   * @param {string} text - The text parameter is a string that represents the text that will be
   * displayed on the chart. It is the content that will be added to the text element created by this function.
   * @param {string} textStyle - The text style of the axis
   * @param {TextAnchorType} textAnchor - text anchor
   * @param {number} rotate - rotate of the text
   */
  drawText(position, text, textStyle, textAnchor, rotate) {
    select(this.context)
      .select('.vega-chart-draw-g')
      .append(() => this.getTextNode(position, text, textStyle, textAnchor, rotate));
  }
  /**
   * This function draws a legend item with a colored circle and text at a specified position on a chart.
   *
   * @param {ChartPosition} position - The position parameter is an object that contains the x and y
   * coordinates where the legend should be placed on the chart.
   * @param {string} text - The text to be displayed in the legend.
   * @param {string} color - Background color token type, which is a type of color
   * used in the chart's background.
   * @param {string} textStyle - The text style of the axis
   * @returns {SVGGElement} svg g element
   */
  drawLegend(position, text, color, textStyle) {
    return select(this.context)
      .select('.vega-chart-legend-g')
      .append('g')
      .attr('class', 'vega-chart-legend-item')
      .attr('data-legend', text)
      .attr('transform', `translate(${position.x},${position.y})`)
      .call((g) => {
      g.append(() => this.getCircleNode({
        x: -4,
        y: -4,
      }, 4, color));
      g.append(() => this.getTextNode({ x: 8, y: 0 }, text, textStyle));
    })
      .node();
  }
  /**
   * This function draws a rectangle with a specified position, width, height, and optional color using D3.js.
   *
   * @param {ChartPosition} position - The position parameter is an object that contains the x and y coordinates of the top-left corner of the rectangle.
   * @param {number} width - The width of the rectangle to be drawn.
   * @param {number} height - The height parameter is a number that represents the height of the rectangle to be drawn.
   * @param {string} [color] - The color parameter is an optional string that represents the color of the rectangle to be drawn. If it is not provided, the rectangle will have no fill color.
   */
  drawRect(position, width, height, color) {
    select(this.context)
      .select('.vega-chart-draw-g')
      .append('rect')
      .attr('fill', color)
      .attr('x', position.x)
      .attr('y', position.y)
      .attr('width', width)
      .attr('height', height);
  }
  /**
   * This function draws a path on a chart using D3 and SVG based on the provided positions and color.
   *
   * @param {ChartPosition[]} positions - An array of ChartPosition objects that represent the
   * coordinates of the points on the path to be drawn. Each ChartPosition object contains an x and y
   * value that represent the position of the point on the chart.
   * @param {string} color - line color
   * represents a color value. It is likely used to specify the color of the path that will be drawn on the chart.
   */
  drawLinePath(positions, color) {
    select(this.context)
      .select('.vega-chart-draw-g')
      .append('path')
      .attr('class', 'vega-chart-line-path')
      .datum(positions)
      .attr('fill', 'none')
      .attr('stroke', color)
      .attr('stroke-width', 3)
      .attr('stroke-linecap', 'round')
      .attr('stroke-linejoin', 'round')
      .attr('d', line()
      .x((position) => position.x)
      .y((position) => position.y));
  }
  /**
   * This function draws an arc path using D3 library and applies color and radius based on input parameters.
   *
   * @param {ChartPosition} center - the arc center position
   * @param {ArcPathItem} record - an object containing data for the arc path to be drawn
   * @param {string} color - The color parameter
   * and is used to set the fill color of the arc path.
   * @param {number} outerRadius - The outer radius parameter is a number that determines the outer
   * radius of the arc path being drawn.
   * @param {number} innerRadius - The inner radius of the arc path, specified as a number.
   * @returns {SVGPathElement} svg arc path element.
   */
  drawArcPath(center, record, color, outerRadius, innerRadius) {
    return select(this.context)
      .select('.vega-chart-draw-g')
      .append('path')
      .datum(record)
      .attr('class', 'vega-chart-arc-path')
      .attr('data-name', (item) => item.data.name)
      .attr('transform', `translate(${center.x},${center.y})`)
      .attr('fill', color)
      .attr('stroke-width', 0)
      .attr('d', arc().innerRadius(innerRadius).outerRadius(outerRadius))
      .attr('data-d', arc()
      .innerRadius(innerRadius)
      .outerRadius(outerRadius + 10))
      .node();
  }
  /**
   * This function clears all elements within two specific classes in a D3 selection.
   */
  clear() {
    select(this.context).selectAll('.vega-chart-draw-g').remove();
    select(this.context).selectAll('.vega-chart-legend-g').remove();
  }
  /**
   * This TypeScript function creates and returns an SVG text element with the given position and text.
   *
   * @param {ChartPosition} position - The position parameter is an object that contains the x and y
   * coordinates where the text element will be placed on the SVG canvas.
   * @param {string} text - The text parameter is a string that represents the text content that will be
   * displayed in the SVGTextElement.
   * @param {string} textStyle - The text style of the axis
   * @param {TextAnchorType} textAnchor - text anchor
   * @param {number} rotate - rotate of the text
   * @returns {SVGTextElement} an SVGTextElement node.
   */
  getTextNode(position, text, textStyle, textAnchor = 'start', rotate = 0) {
    const TextSelectionType = create('svg:text')
      .property('style', textStyle)
      .attr('x', position.x)
      .attr('y', position.y)
      .attr('text-anchor', textAnchor)
      .attr('rotate', rotate)
      .text(text);
    return TextSelectionType.node();
  }
  /**
   * This TypeScript function creates an SVG circle element with a specified center, radius, and color.
   *
   * @param {ChartPosition} center - The center position of the circle on the chart, specified as an
   * object with `x` and `y` properties.
   * @param {number} radius - The radius parameter is a number that represents the radius of the circle
   * to be created.
   * @param {string} fillColor - The color parameter
   * and is used to determine the fill color of the circle. It is likely an enum or string type that maps
   * to a specific color value.
   * @param {number} strokeWidth - the border width
   * @param {string} strokeColor - the border color
   * @returns {SVGCircleElement} an SVG circle element.
   */
  getCircleNode(center, radius, fillColor, strokeWidth, strokeColor) {
    const circleSelection = create('svg:circle')
      .attr('r', radius)
      .attr('cx', center.x)
      .attr('cy', center.y)
      .attr('fill', fillColor)
      .attr('stroke-width', strokeWidth || 0)
      .attr('stroke', strokeColor);
    return circleSelection.node();
  }
}

/**
 * The CanvasRenderer class is a TypeScript class that extends the BaseRenderer class and provides
 * methods for drawing various shapes and elements on a canvas.
 */
class CanvasRenderer extends BaseRenderer {
  /**
   * The function sets the layout of a chart.
   *
   * @param {number} width - chart width
   * @param {number} height - chart height
   */
  setLayout(width, height) {
    this.context.width = width;
    this.context.height = height;
    this.context.style.display = 'block';
    this.initCanvasContext2d();
  }
  /**
   * The function `drawLine` takes two `ChartPosition` parameters and draws a line between them.
   *
   * @param {ChartPosition} from - The starting position of the line on the chart. It is of type ChartPosition.
   * @param {ChartPosition} to - The "to" parameter in the "drawLine" function is a ChartPosition object
   * that represents the end point of the line to be drawn. It contains information about the x and y
   * coordinates of the point on the chart where the line should end.
   */
  drawLine(from, to) {
    const context2d = this.getContext2d();
    context2d.beginPath();
    context2d.moveTo(from.x, from.y);
    context2d.lineTo(to.x, to.y);
    context2d.closePath();
  }
  /**
   * This function draws the X-axis on a chart and takes in a parameter of type ChartExtend.
   *
   * @param {ChartExtend<unknown>} extend - The parameter "extend" is of type "ChartExtend" which is a generic type that can
   * take any data type as an argument. It is likely used to extend or modify the properties of the chart's X-axis
   */
  drawXAxis(extend) {
    this.drawLine(extend.start, extend.end);
  }
  /**
   * This function draws the Y-axis on a chart.
   *
   * @param {ChartExtend<unknown>} extend - The parameter "extend" is of type ChartExtend, which is a generic type that
   * represents the range of values for a chart axis. It contains information such as the minimum and
   * maximum values for the axis
   */
  drawYAxis(extend) {
    this.drawLine(extend.start, extend.end);
  }
  /**
   * The function `drawCircle` takes in a center position, radius, and color and draws a circle.
   *
   * @param {ChartPosition} center - The center of the circle, represented by a ChartPosition object
   * that contains the x and y coordinates of the center point.
   * @param {number} radius - The _radius parameter is a number that represents the radius of the
   * circle to be drawn. The radius is the distance from the center of the circle to any point on its circumference.
   * @param {string} fillColor - The _color,
   * which is a type that represents a color value that can be used as a background color for a chart element
   * @param {number} strokeWidth - the border width
   * @param {string} strokeColor - the border color
   */
  drawCircle(center, radius, fillColor, strokeWidth, strokeColor) {
    const context2d = this.getContext2d();
    if (strokeWidth && strokeColor) {
      context2d.fillStyle = strokeColor;
      context2d.beginPath();
      context2d.arc(center.x, center.y, radius, 0, Math.PI * 2);
      context2d.fill();
    }
    context2d.fillStyle = fillColor;
    context2d.beginPath();
    context2d.arc(center.x, center.y, radius - (strokeWidth || 0), 0, Math.PI * 2);
    context2d.fill();
  }
  /**
   * The function draws a legend on a chart with a circle and text at a specified position and color.
   *
   * @param {ChartPosition} position - ChartPosition is a type that represents the position of an
   * element on a chart. It could be an object with properties like x and y coordinates or a string that
   * represents a predefined position.
   * @param {string} text - The text parameter is a string that represents the label or name of the
   * legend that will be displayed on the chart.
   * @param {string} color - color string
   * represents a color for the legend. It could be a string or a number that corresponds to a specific
   * color value.
   * @returns {HTMLCanvasElement} chart canvas element
   */
  drawLegend(position, text, color) {
    this.drawCircle(position, 4, color);
    this.drawText(position, text);
    return this.context;
  }
  /**
   * The function `drawText` takes a position and a string of text as parameters and does not return anything.
   *
   * @param {ChartPosition} position - ChartPosition is a data type that represents the position of the
   * text on a chart. It could be an object with properties such as x and y coordinates, or it could be
   * a string that represents a pre-defined position on the chart (e.g. "top-left", "bottom-right",
   * etc.).
   * @param {string} text - The text parameter is a string that represents the text that needs to be drawn on the chart.
   */
  drawText(position, text) {
    this.getContext2d().fillText(text, position.x, position.y);
  }
  /**
   * The function `drawRect` takes in a position, width, height, and optional color parameter to draw a rectangle.
   *
   * @param {ChartPosition} position - The position parameter is of type ChartPosition and represents
   * the position of the rectangle on the chart. It could be an object with x and y properties
   * representing the coordinates of the top-left corner of the rectangle.
   * @param {number} width - The width parameter is a number that represents the width of the rectangle
   * to be drawn. It determines how wide the rectangle will be on the chart.
   * @param {number} height - The `height` parameter in the `drawRect` function specifies the height of
   * the rectangle to be drawn. It is a required parameter and must be a number value.
   * @param {string} [color] - The color parameter is an optional parameter that
   * specifies the background color of the rectangle. It is of type string, which is
   * a custom type that represents a color token
   */
  drawRect(position, width, height, color) {
    const context2d = this.getContext2d();
    context2d.fillStyle = color;
    context2d.fillRect(position.x, position.y, width, height);
  }
  /**
   * The function `drawLinePath` takes in an array of `ChartPosition` objects and a `string` color and draws a path.
   *
   * @param {ChartPosition[]} positions - An array of ChartPosition objects that represent the
   * coordinates of points on a chart. Each ChartPosition object has an x and y property that represent
   * the horizontal and vertical position of the point on the chart.
   * @param {string} color - The `color` parameter is of type
   * `string` and represents the color of the path to be drawn. This parameter is
   * used to set the background color of the chart.
   */
  drawLinePath(positions, color) {
    const pathNode = create('svg:path')
      .datum(positions)
      .attr('d', line()
      .x((position) => position.x)
      .y((position) => position.y))
      .node();
    const path = new Path2D(pathNode.getAttribute('d'));
    const context2d = this.getContext2d();
    context2d.lineWidth = 3;
    context2d.strokeStyle = color;
    context2d.stroke(path);
  }
  /**
   * This function draws an arc path using D3 library and applies color and radius based on input parameters.
   *
   * @param {ChartPosition} center - arc center position
   * @param {ArcPathItem} record - an object containing data for the arc path to be drawn
   * @param {string} color - The color parameter
   * and is used to set the fill color of the arc path.
   * @param {number} outerRadius - The outer radius parameter is a number that determines the outer
   * radius of the arc path being drawn.
   * @param {number} innerRadius - The inner radius of the arc path, specified as a number.
   * @returns {HTMLCanvasElement} chart canvas element.
   */
  drawArcPath(center, record, color, outerRadius, innerRadius) {
    const context2d = this.getContext2d();
    context2d.beginPath();
    context2d.moveTo(center.x, center.y);
    context2d.arc(center.x, center.y, outerRadius, record.startAngle, record.endAngle);
    context2d.fillStyle = color;
    context2d.fill();
    if (innerRadius) {
      this.drawCircle(center, innerRadius, '#F0F3F7');
    }
    return this.context;
  }
  /**
   * The function "clear"
   */
  clear() {
    this.getContext2d().clearRect(0, 0, this.context.width, this.context.height);
  }
  /**
   * This function initializes a 2D canvas context.
   */
  initCanvasContext2d() {
    this.canvasContext2d = this.context.getContext('2d');
  }
  /**
   * This function returns the canvas 2D rendering context and initializes it if it doesn't exist.
   *
   * @returns {CanvasRenderingContext2D} The function `getContext2d()` returns the `CanvasRenderingContext2D` object.
   */
  getContext2d() {
    if (!this.canvasContext2d) {
      this.initCanvasContext2d();
    }
    return this.canvasContext2d;
  }
}

/** The RendererFactory class provides a static method to create a renderer based on the type of context provided. */
class RendererFactory {
  /**
   * This function returns a renderer based on the type of context provided (SVG or Canvas).
   *
   * @param {SVGElement | HTMLCanvasElement} context - The `context` parameter is either an
   * SVGElement or a HTMLCanvasElement. It is used to determine which renderer to instantiate and
   * return
   * @returns {BaseRenderer<SVGElement | HTMLCanvasElement> } based on the type of the `context` parameter. If
   * the `context` is an instance of `SVGElement`, an `SVGRenderer` object is returned
   */
  static get(context) {
    if (context instanceof SVGElement) {
      return new SVGRenderer(context);
    }
    else if (context instanceof HTMLCanvasElement) {
      return new CanvasRenderer(context);
    }
    else {
      throw new Error('Invalid context');
    }
  }
}

const DEFAULT_LAYOUT = {
  width: undefined,
  height: undefined,
  margin: {
    top: 30,
    right: 30,
    bottom: 30,
    left: 30,
  },
};
const DEFAULT_MARGIN_TOP_WITH_LEGENDS = 60;
const DEFAULT_MARGIN_LEFT_WITH_AXIS = 60;
/** The ChartDimensionController class contains methods for setting and retrieving the width and height of a chart container element. */
class ChartDimensionController {
  /**
   * This is a constructor function that takes an HTMLElement as a parameter and assigns it to a private property called "container".
   *
   * @param {HTMLElement} container - The "container" parameter is a reference to an HTML element that
   * will be used as a container for the component or module being constructed. This parameter is
   * typically passed in during the instantiation of the component or module and is used to specify
   * where the component or module should be rendered in the DOM.
   */
  constructor(container) {
    this.container = container;
  }
  /**
   * This function sets the width and height of a container element based on a given layout object. if the layout is null, then will not update,
   * prevent the original style is changed
   *
   * @param {ChartLayout} layout - ChartLayout object that contains the width and height values for the chart container.
   */
  setContainerWidthAndHeight(layout) {
    const { width, height } = layout;
    if (width !== undefined) {
      this.container.style.width = pixel.parseNumberToPixelString(width);
    }
    if (height !== undefined) {
      this.container.style.height = pixel.parseNumberToPixelString(height);
    }
  }
  /**
   * This function returns the client width of a container or parses the width from a layout object.
   *
   * @param {ChartLayout} layout - In this function, the layout parameter is used to determine the width of the chart container. If the container's
   * clientWidth property is not available,
   * @returns {number} returning a number. The number is either the client width of the container element or the parsed width value from the `ChartLayout` object.
   */
  getContainerClientWidth(layout) {
    return (this.container.clientWidth ||
      pixel.parsePixelStringToNumber((layout === null || layout === void 0 ? void 0 : layout.width) || this.container.style.width));
  }
  /**
   * This function returns the height of a container element in pixels, either by accessing its clientHeight property or by parsing a string value from the layout object.
   *
   * @param {ChartLayout} layout -  the layout parameter is used to determine the height of the chart container if it is not already set.
   * @returns {number} The function `getContainerClientHeight` returns a number which represents the height of
   * the container client or the parsed height value from the `ChartLayout` object.
   */
  getContainerClientHeight(layout) {
    return (this.container.clientHeight ||
      pixel.parsePixelStringToNumber((layout === null || layout === void 0 ? void 0 : layout.height) || this.container.style.height));
  }
  /**
   * This function calculates the inner width of a chart container by subtracting the left and right margins from the client width.
   *
   * @param {ChartLayout} layout - ChartLayout object that contains information about the chart layout,
   * including the container width and margin.
   * @returns {number} the inner width of a container element, which is calculated by subtracting the left and
   * right margins from the client width of the container.
   */
  getContainerInnerWidth(layout) {
    const width = this.getContainerClientWidth(layout);
    const { left, right } = ((layout === null || layout === void 0 ? void 0 : layout.margin) || DEFAULT_LAYOUT.margin);
    return width ? width - right - left : 0;
  }
  /**
   * This function calculates the inner height of a chart container by subtracting the top and bottom margins from the client height.
   *
   * @param {ChartLayout} layout - The `layout` parameter is an object of type `ChartLayout` which
   * contains information about the layout of a chart, including its dimensions and margins.
   * @returns {number} the inner height of a container element, which is calculated by subtracting the top and
   * bottom margins from the client height of the container. The returned value is a number.
   */
  getContainerInnerHeight(layout) {
    const height = this.getContainerClientHeight(layout);
    const { top, bottom } = ((layout === null || layout === void 0 ? void 0 : layout.margin) || DEFAULT_LAYOUT.margin);
    return height ? height - top - bottom : 0;
  }
  /**
   * This function merges a given chart layout with default values and returns the updated layout.
   *
   * @param {string} chartName - A string representing the name of the chart.
   * @param {ChartLayout} layout - The `layout` parameter is an optional object that contains properties
   * for the width, height, and margin of a chart. If provided, it will be merged with the default
   * layout settings to create a new layout object. If not provided, the default layout settings will be
   * used.
   * @param {boolean} hasLegends - A boolean value indicating whether the chart has legends or not.
   * @returns {ChartLayout} a ChartLayout object.
   */
  mergeLayout(chartName, layout, hasLegends) {
    const defaultTop = hasLegends ? DEFAULT_MARGIN_TOP_WITH_LEGENDS : DEFAULT_LAYOUT.margin.top;
    const defaultLeft = chartName === 'VEGA-LINE-CHART' || chartName === 'VEGA-BAR-CHART'
      ? DEFAULT_MARGIN_LEFT_WITH_AXIS
      : DEFAULT_LAYOUT.margin.left;
    const newLayout = {
      width: layout && layout.width ? layout.width : DEFAULT_LAYOUT.width,
      height: layout && layout.height ? layout.height : DEFAULT_LAYOUT.height,
      margin: Object.assign({}, DEFAULT_LAYOUT.margin, { top: defaultTop, left: defaultLeft }, layout && layout.margin ? layout.margin : {}),
    };
    return newLayout;
  }
}

/**
 * This is a TypeScript code that defines an abstract class `BaseInteractor` with a generic type `T` that extends either `SVGElement` or `HTMLCanvasElement`.
 */
class BaseInteractor {
  /**
   * This is a constructor function that takes a parameter of type T and sets it as a protected property called "context".
   *
   * @param {SVGElement | HTMLCanvasElement} context - The "context" parameter is a protected property of a class constructor that is
   * of type "T". It is used to store a reference to an object or data that is required by the class
   * methods to perform their tasks. The "protected" keyword means that the property can only be
   * accessed within the class
   */
  constructor(context) {
    this.context = context;
    this.interactingEntryForEventRegistry = new Map();
    this.interactingEntryForDrawerRegistry = new WeakMap();
  }
  /**
   * This function registers an interacting entry with a drawer, draw piece, and event type in an interactor registry.
   *
   * @param {BaseDrawer<unknown>} drawer - The drawer parameter is an instance of a class that extends the BaseDrawer class,
   * which is used for drawing on a canvas or other graphical surface.
   * @param {DrawPiece} drawPiece - DrawPiece is a type that represents a specific piece that can be
   * drawn on a canvas or other graphical surface. It could include information such as the shape,
   * color, size, and position of the piece.
   * @param {InteractingEntry} interactingEntry - InteractingEntry is a data structure that represents
   * an interaction between a user and a graphical element on the screen. It contains information such
   * as the type of event that triggered the interaction (e.g. mouse click, touch)
   */
  register(drawer, drawPiece, interactingEntry) {
    /* eslint-disable @typescript-eslint/no-non-null-assertion */
    const eventType = interactingEntry.eventType;
    if (!this.interactingEntryForEventRegistry.get(eventType)) {
      this.interactingEntryForEventRegistry.set(eventType, []);
    }
    this.interactingEntryForEventRegistry.get(eventType).push(interactingEntry);
    if (!this.interactingEntryForDrawerRegistry.get(drawer)) {
      this.interactingEntryForDrawerRegistry.set(drawer, new WeakMap());
    }
    if (!this.interactingEntryForDrawerRegistry.get(drawer).get(drawPiece)) {
      this.interactingEntryForDrawerRegistry.get(drawer).set(drawPiece, []);
    }
    this.interactingEntryForDrawerRegistry.get(drawer).get(drawPiece).push(interactingEntry);
    /* eslint-enable @typescript-eslint/no-non-null-assertion */
  }
  /**
   * This function unregisters a drawer from the interactor registry.
   *
   * @param {BaseDrawer<unknown>} drawer - The parameter `drawer` is of type `BaseDrawer<unknown>`. It is an object that
   * represents a drawer and is used to unregister the drawer from the `interactorRegistry`. The
   * `interactorRegistry` is a `WeakMap` that stores a mapping between an `Interactor` and
   */
  unregisterByDrawer(drawer) {
    /* eslint-disable @typescript-eslint/no-non-null-assertion */
    const drawPiece = drawer.drawPiece;
    if (drawPiece &&
      this.interactingEntryForDrawerRegistry.has(drawer) &&
      this.interactingEntryForDrawerRegistry.get(drawer) &&
      this.interactingEntryForDrawerRegistry.get(drawer).has(drawPiece) &&
      this.interactingEntryForDrawerRegistry.get(drawer).get(drawPiece)) {
      this.interactingEntryForEventRegistry.forEach((value, key) => {
        this.interactingEntryForEventRegistry.set(key, value.filter((interactingEntry) => {
          return (this.interactingEntryForDrawerRegistry
            .get(drawer)
            .get(drawPiece)
            .indexOf(interactingEntry) < 0);
        }));
      });
      /* eslint-enable @typescript-eslint/no-non-null-assertion */
    }
    this.interactingEntryForDrawerRegistry.delete(drawer);
  }
  /**
   * This function handles mouse events for registered interactor and drawers.
   *
   * @param {EventType} eventType - The type of event being registered in the registry, such as "click" or "mousemove".
   * @param {MouseEvent} event - The `event` parameter is of type `MouseEvent`, which represents a
   * mouse-related event (such as a click, double-click, or mouse movement) that occurred on the web
   * page. It contains information about the event, such as the type of event, the target element that
   * triggered the event
   */
  callRegistry(eventType, event) {
    const interactingEntryArray = this.interactingEntryForEventRegistry.get(eventType);
    if (interactingEntryArray) {
      interactingEntryArray.forEach((interactingEntry) => {
        if (interactingEntry.shouldHandle(event)) {
          interactingEntry.handle(event);
        }
      });
    }
  }
}

/**
 * The CanvasInteractor class extends the BaseInteractor class and provides empty methods for handling mouse move, click, and hover events on a HTML canvas element.
 */
class CanvasInteractor extends BaseInteractor {
}

/**
 *  The SVGInteractor class extends the BaseInteractor class and provides methods for handling mouse events on SVG elements.
 */
class SVGInteractor extends BaseInteractor {
  /**
   * This is a constructor function that adds event listeners for click and mouseover events to an SVG element.
   *
   * @param {SVGElement} context - The context parameter is an SVGElement, which is the element that the
   * constructor is being called on. It is used to add event listeners to the element for mouseover and
   * click events.
   */
  constructor(context) {
    super(context);
    this.addContextListener();
  }
  /**
   * This function adds event listeners for click and mouseover events to the context element and calls
   * a registry function with the corresponding event type and event object.
   */
  addContextListener() {
    this.context.addEventListener('click', (event) => {
      this.callRegistry('click', event);
    });
    this.context.addEventListener('mouseover', (event) => {
      this.callRegistry('mouseover', event);
    });
  }
}

/** The InteractorFactory class provides a static method to create and return an appropriate interactor based on the type of context provided. */
class InteractorFactory {
  /**
   * This function returns a BaseInteractor object based on the type of context passed in (SVGElement or HTMLCanvasElement).
   *
   * @param {SVGElement | HTMLCanvasElement} context - The `context` parameter is either an SVGElement
   * or an HTMLCanvasElement. It is used to determine which type of interactor to create and return. If
   * the context is an SVGElement, an instance of SVGInteractor is returned. If the context is an
   * HTMLCanvasElement, an instance of
   * @returns {BaseInteractor<SVGElement | HTMLCanvasElement>} A `BaseInteractor` object that is either an instance of `SVGInteractor` or
   * `CanvasInteractor`, depending on the type of the `context` parameter passed to the `get` method.
   */
  static get(context) {
    if (context instanceof SVGElement) {
      return new SVGInteractor(context);
    }
    else if (context instanceof HTMLCanvasElement) {
      return new CanvasInteractor(context);
    }
    else {
      throw new Error('Invalid context');
    }
  }
}

/** This is a TypeScript class called `BaseChart` that serves as a base class for creating charts */
class BaseChart {
  /**
   * This is a constructor function that initializes a chart with options and creates a chain of drawers for rendering.
   *
   * @param {ChartOptions<unknown>} options - generic type that represents the configuration options for the chart
   */
  constructor(options) {
    this.options = options;
    this.isLayoutSet = false;
    this.drawers = [];
    const context = GraphContextFactory.get(options.mode, options.container.shadowRoot ? options.container.shadowRoot : options.container);
    this.dimensionController = new ChartDimensionController(options.container);
    this.renderer = RendererFactory.get(context);
    this.interactor = InteractorFactory.get(context);
    this.initLayoutOptions(options);
  }
  /**
   * The function clears the renderer.
   */
  clear() {
    this.renderer.clear();
  }
  /**
   * This function updates the chart options, creates a new drawer chain, resets the layout, and renders the chart.
   *
   * @param {ChartOptions<unknown>} options - ChartOptions<T> is a generic type that represents the configuration options for a
   * chart. It can include properties such as the chart type, data, labels, colors, and other stylingoptions
   */
  updateOptions(options) {
    this.initLayoutOptions(options);
    this.isLayoutSet = false;
    this.render();
  }
  /**
   * re render the chart using existing options
   */
  reRender() {
    this.updateOptions(this.options);
  }
  /**
   * sets the layout if it hasn't been set yet, and executes all the drawers. unregister the interactor by drawer
   */
  render() {
    this.unregisterByDrawer();
    this.drawers = this.createDrawerChain(this.renderer, this.interactor);
    this.clear();
    if (!this.isLayoutSet) {
      this.setLayout();
      this.isLayoutSet = true;
    }
    this.drawers.forEach((drawer) => drawer.execute());
  }
  /**
   * sets the layout of a renderer using the options provided.
   */
  setLayout() {
    const layout = this.options.layout;
    const width = this.dimensionController.getContainerClientWidth(layout), height = this.dimensionController.getContainerClientHeight(layout), margin = (layout === null || layout === void 0 ? void 0 : layout.margin) || DEFAULT_LAYOUT.margin;
    this.renderer.setLayout(width, height, margin.top, margin.left);
  }
  /**
   * This function initializes layout options for a chart.
   *
   * @param {ChartOptions} options - ChartOptions<T> is a generic type that represents the configuration options for a
   * chart. It includes properties such as data, layout, and style.
   */
  initLayoutOptions(options) {
    const newLayout = this.dimensionController.mergeLayout(options.container.tagName, options.layout, options.legends && options.legends.length ? true : false);
    this.options = Object.assign(options, { layout: newLayout });
    this.dimensionController.setContainerWidthAndHeight(newLayout);
    this.options.container.style.display = 'block';
  }
  /**
   * This function un-registers drawers from the interactor.
   */
  unregisterByDrawer() {
    if (this.drawers) {
      this.drawers.forEach((drawer) => {
        this.interactor.unregisterByDrawer(drawer);
      });
    }
  }
}

/* This file is generated by vega-design 2.0.77 */
/* eslint-disable */
/* tslint:disable */
// prettier-ignore
const BackgroundColorsMappingLight = {
  "bg-brand": "#33393D",
  "bg-page": "#F0F3F7",
  "bg-primary": "#FCFCFC",
  "bg-secondary": "#F5F7F7",
  "bg-tertiary": "#F0F3F7",
  "bg-quaternary": "#F1F8FB",
  "bg-inverted-primary": "#04041C",
  "bg-inverted-secondary": "#121227",
  "bg-inverted-tertiary": "#181830",
  "bg-inverted-quaternary": "#464765",
  "bg-action": "#1362E2",
  "bg-action-hover": "#0470EC",
  "bg-action-focus": "#1362E2",
  "bg-action-active": "#1D41C3",
  "bg-action-quaternary": "#DEE1E3",
  "bg-action-quaternary-hover": "#EFEFEF",
  "bg-action-quaternary-active": "#CDD1D3",
  "bg-action-secondary": "#FCFCFC",
  "bg-action-secondary-hover": "#0470EC",
  "bg-action-secondary-active": "#1D41C3",
  "bg-action-tertiary": "#000000",
  "bg-action-tertiary-hover": "#04041C",
  "bg-action-tertiary-active": "#04041C",
  "bg-app-header": "#F0F3F7",
  "bg-backdrop-modal": "#121227",
  "bg-backdrop-popover": "#203645",
  "bg-backdrop-sidebar": "#121227",
  "bg-chip": "#203645",
  "bg-chip-hover": "#203645",
  "bg-chip-active": "#203645",
  "bg-danger": "#BD2947",
  "bg-danger-hover": "#E94768",
  "bg-danger-focus": "#BD2947",
  "bg-danger-active": "#E63257",
  "bg-danger-tertiary": "#000000",
  "bg-danger-tertiary-hover": "#FF5772",
  "bg-danger-tertiary-active": "#BD2947",
  "bg-disabled": "#B0B4B5",
  "bg-divider": "#ABC6D8",
  "bg-divider-secondary": "#C7D9E5",
  "bg-keypad-btn-active": "#E5EFFF",
  "bg-loading-progress": "#99C0FF",
  "bg-loading-track": "#E5EFFF",
  "bg-segment-hover": "#CDD1D3",
  "bg-segment-control": "#596063",
  "bg-selected": "#0097FF",
  "bg-sidebar": "#121227",
  "bg-sidebar-icon": "#BCBAD5",
  "bg-sidebar-icon-hover": "#121227",
  "bg-sidebar-icon-selected": "#FCFCFC",
  "bg-sidebar-item-hover": "#FCFCFC",
  "bg-sidebar-item-selected": "#1362E2",
  "bg-site-footer": "#33393D",
  "bg-site-footer-action": "#ABC6D8",
  "bg-site-footer-action-hover": "#C7D9E5",
  "bg-site-footer-action-active": "#8FB3CB",
  "bg-site-footer-field": "#596063",
  "bg-slider-handle": "#FCFCFC",
  "bg-status-error": "#FF6E8B",
  "bg-status-info": "#CDD1D3",
  "bg-status-success": "#A0E9A7",
  "bg-status-warning": "#FFDC83",
  "bg-tab": "#F0F3F7",
  "bg-tab-hover": "#F5F7F7",
  "bg-tab-selected": "#203645",
  "bg-table-alt-row": "#F5F7F7",
  "bg-table-header": "#F0F3F7",
  "bg-table-row-hover": "#F1F8FB",
  "bg-table-row-selected-expanded": "#E5EFFF",
  "bg-table-selected-row": "#CCDFFF",
  "bg-textarea-count": "#04041C",
  "bg-tile": "#FCFCFC",
  "bg-tile-hover": "#F5F7F7",
  "bg-tile-selected": "#F2F7FF",
  "bg-tile-selected-hover": "#E5EFFF",
  "bg-toggle-switch": "#6B747D",
  "bg-toggle-switch-hover": "#6B747D",
  "bg-toggle-switch-selected-disabled": "#99C0FF",
  "bg-transparent": "#000000",
  "bg-accent1-primary": "#73E6DC",
  "bg-accent1-secondary": "#C1F4EF",
  "bg-accent1-tertiary": "#E0F9F7",
  "bg-accent2-primary": "#806BFF",
  "bg-accent2-secondary": "#C7BDFF",
  "bg-accent2-tertiary": "#E3DEFF",
  "bg-accent3-primary": "#FFDC83",
  "bg-accent3-secondary": "#FFEFC8",
  "bg-accent3-tertiary": "#FFF7E3",
  "bg-accent4-primary": "#FF9571",
  "bg-accent4-secondary": "#FFD0C0",
  "bg-accent4-tertiary": "#FFE7DF",
  "bg-accent5-primary": "#00BBFF",
  "bg-accent5-secondary": "#8EDFF9",
  "bg-accent5-tertiary": "#E3F7FD",
  "bg-accent6-primary": "#FF82C9",
  "bg-accent6-secondary": "#FFC7E7",
  "bg-accent6-tertiary": "#FFE3F3",
  "bg-accent7-primary": "#259F9F",
  "bg-accent7-secondary": "#9BD4D6",
  "bg-accent7-tertiary": "#D0EFEF",
  "bg-accent8-primary": "#563D82",
  "bg-accent8-secondary": "#C7A2CC",
  "bg-accent8-tertiary": "#E6D6EA",
  "bg-accent9-primary": "#FFBF3F",
  "bg-accent9-secondary": "#FED78E",
  "bg-accent9-tertiary": "#FBE2B9",
  "bg-accent10-primary": "#ED7A23",
  "bg-accent10-secondary": "#F19255",
  "bg-accent10-tertiary": "#F5BB94",
  "bg-date-picker-range": "#E5EFFF"
};

const CHART_DEFAULT_COLORS = [
  'bg-accent1-primary',
  'bg-accent2-primary',
  'bg-accent3-primary',
  'bg-accent4-primary',
  'bg-accent5-primary',
  'bg-accent6-primary',
  'bg-accent7-primary',
  'bg-accent8-primary',
  'bg-accent9-primary',
  'bg-accent10-primary',
];
const DEFAULT_FONT_FAMILY = 'font-family:"Inter", sans-serif;';
const FONTSTYLEMAPPING = Object.keys(typography.Typography).reduce((result, key) => {
  result[key] =
    DEFAULT_FONT_FAMILY +
      typography.Typography[key].filter((str) => str.indexOf('@apply') < 0).join(';');
  return result;
}, { 'v-text-secondary': `color:rgba(107, 116, 125, 1);` });
/**
 * base drawer that provides a common structure for drawing charts using a renderer and options.
 */
class BaseDrawer {
  /**
   * This is a constructor function that takes in a renderer and options for a chart drawer.
   *
   * @param {BaseRenderer<SVGElement | HTMLCanvasElement>} renderer - `renderer` parameter is an instance of a `BaseRenderer` class that can render either SVG elements or a 2D canvas context
   * @param {BaseInteractor<SVGElement | HTMLCanvasElement>} interactor - `renderer` parameter is an instance of a `BaseInteractor` class
   * @param {ChartDrawerOptions<unknown>} options - where `T` is a generic type parameter. This parameter contains various options that can be used to customize the chart being drawn
   */
  constructor(renderer, interactor, options) {
    this.renderer = renderer;
    this.interactor = interactor;
    this.options = options;
  }
  /**
   * The function executes a draw method.
   */
  execute() {
    const drawPiece = this.draw();
    this.drawPiece = drawPiece;
    this.addInteractionSupport(drawPiece);
  }
  /**
   * returns a color token based on an index and an optional array of colors.
   *
   * @param {number} index - The index parameter is a number that represents the index of the color to be returned from the colors array.
   * @param {BackgroundColorsTokenType[]} [colors] - `colors` is an optional parameter of type `BackgroundColorsTokenType[]`
   * @returns {BackgroundColorsTokenType} color token
   */
  getColorByIndex(index, colors) {
    colors = colors && colors.length ? colors : CHART_DEFAULT_COLORS;
    index = index % colors.length;
    return colors[index];
  }
  /**
   * This function takes a token representing a background color and returns the corresponding color value from a predefined mapping.
   *
   * @param {BackgroundColorsTokenType} token - a string representing the token for a background color
   * @returns {string} The string value returned is the color code
   */
  getColorFromToken(token) {
    return BackgroundColorsMappingLight[token];
  }
  /**
   * The function takes a token as input and returns the corresponding CSS style text from a predefined mapping.
   *
   * @param {string} token - The `token` parameter is a string that represents a specific style mapping
   * in the `FONTSTYLEMAPPING` object. The function returns the CSS style text associated with the given `token`.
   * @returns {string} a string that represents the CSS style associated with the input token. If the input token
   * matches a key in the `FONTSTYLEMAPPING` object, the corresponding CSS style string is returned.
   */
  getStyleTextFromToken(token) {
    return token
      .split(' ')
      .map((item) => FONTSTYLEMAPPING[item])
      .join(';');
  }
}

/** The code is defining an abstract class called `InteractingEntryGenerator` with a generic type `T`. This class is responsible for generating an `InteractingEntry` object based on the provided options. */
class InteractingEntryGenerator {
  /**
   * The function generates an InteractingEntry object based on the provided options.
   *
   * @param {unknown} options - The `options` parameter is a generic type `T` that represents the options or configuration for the `generate` function. It can be any type that you define when calling the `generate` function.
   * @returns {InteractingEntry} An object of type InteractingEntry is being returned.
   */
  generate(options) {
    return {
      eventType: this.eventType,
      shouldHandle: this.createShouldHandle(options),
      handle: this.createHandle(options),
    };
  }
}

/** The PieLegendHoverGenerator class generates an InteractingEntry object that handles mouseover events on a legend of a D3 pie chart and triggers a mouseover event on the corresponding path element. */
class PieLegendHoverGenerator extends InteractingEntryGenerator {
  constructor() {
    super(...arguments);
    this.eventType = 'mouseover';
  }
  /**
   * The function "createShouldHandle" returns a function that takes an event as a parameter and returns a boolean value.
   *
   * @returns {InteractingEntry['shouldHandle']} A function that takes an event as an argument and returns a boolean value.
   */
  createShouldHandle() {
    return this.shouldHandle;
  }
  /**
   * The function "createHandle" returns the handle property of an InteractingEntry object.
   *
   * @param {LegendInputType} options the legend render options
   * @returns {InteractingEntry['handle']} The `handle` property of the `InteractingEntry` object is being returned.
   */
  createHandle(options) {
    // eslint-disable-next-line jsdoc/require-jsdoc
    return (event) => {
      this.handle(event, options);
    };
  }
  /**
   * This function checks if a mouse event should be handled based on whether the target or its parent element has a specific class.
   *
   * @param {MouseEvent} event - MouseEvent is a type of event that is triggered by a mouse action, such
   * as clicking, hovering, or scrolling. It contains information about the event, such as the target
   * element and the position of the mouse.
   * @returns {boolean} A boolean value is being returned. The method `shouldHandle` checks if the target element
   * or its parent element has a class of `vega-chart-legend-item` and returns `true` if it does, and
   * `false` otherwise.
   */
  shouldHandle(event) {
    var _a;
    const target = event.target;
    const currentTarget = event.currentTarget;
    const container = currentTarget.parentElement && currentTarget.parentElement.nodeType !== 11
      ? currentTarget.parentElement
      : currentTarget.parentNode['host'];
    return (container.tagName === 'VEGA-PIE-CHART' &&
      (target.classList.contains('vega-chart-legend-item') ||
        !!((_a = target.parentElement) === null || _a === void 0 ? void 0 : _a.classList.contains('vega-chart-legend-item'))));
  }
  /**
   * The function handles a mouse event on a legend and triggers a mouseover event on the corresponding path element in a D3 chart.
   *
   * @param {MouseEvent} event - The event parameter is a MouseEvent, which represents a user action
   * (such as a click or hover) on a specific element in the DOM.
   * @param {LegendInputType} options - LegendInputType is a custom type that likely contains
   * information about the data being displayed in the chart, such as the names of the categories or
   * series being plotted. It may also include information about the chart's appearance or behavior,
   * such as the colors or labels used in the legend. Without more information about
   */
  handle(event, options) {
    var _a;
    const svgSelection = select(event.currentTarget);
    const target = event.target;
    const targetTextNode = target.tagName === 'text'
      ? target
      : target.tagName === 'circle'
        ? target.nextElementSibling
        : target.querySelector('text');
    const name = targetTextNode ? targetTextNode.textContent : '';
    const index = name ? options.data.indexOf(name) : 0;
    const paths = svgSelection
      .selectAll(`path.vega-chart-arc-path`)
      .nodes();
    (_a = paths[index]) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
  }
}

/** The LegendDrawer class draws circles and text for each legend in a chart. */
class LegendDrawer extends BaseDrawer {
  constructor() {
    super(...arguments);
    this.pieLegendHoverGenerator = new PieLegendHoverGenerator();
  }
  /**
   * This function adds interaction support to a chart by registering it with an interactor and providing a hover generator.
   *
   * @param {(SVGGElement | HTMLCanvasElement)[]} drawPiece - `drawPiece` is a parameter of type array
   * that contains either `SVGGElement` or `HTMLCanvasElement` elements. It is used as a callback
   * function to draw the legend items on the chart.
   */
  addInteractionSupport(drawPiece) {
    var _a;
    if ((_a = this.options.renderOptions.data) === null || _a === void 0 ? void 0 : _a.length) {
      this.interactor.register(this, drawPiece, this.pieLegendHoverGenerator.generate(this.options.renderOptions));
    }
  }
  /**
   * This function draws a legend on a chart using input options.
   *
   * @returns {(SVGGElement | HTMLCanvasElement)[] | undefined}  draw piece
   */
  draw() {
    const { data = [], colors, position, width } = this.options.renderOptions;
    const options = this.getChartLegendOptions(data, colors, position);
    if (options) {
      const longestLegendLength = array.getLongestTextLengthFromArray(data);
      return options.legends.map((legend, index) => {
        const position = this.getLegendPosition(options.position, index, longestLegendLength, width);
        return this.renderer.drawLegend(position, legend.field, legend.color, this.getStyleTextFromToken('v-font-footnote2-short'));
      });
    }
  }
  /**
   * This function takes in an array of strings and an optional position parameter, and returns an object containing legend options for a chart.
   *
   * @param {string[]} data - an array of strings representing the legend labels
   * @param {BackgroundColorsTokenType[]} [colors] - bg color token array
   * @param {ChartPosition} [position] - The `position` parameter is an optional parameter of type
   * `ChartPosition` which specifies the x and y coordinates of the chart legend on the chart. If it is
   * not provided, the default position is `{x: 10, y: 0}`.
   * @returns {ChartLegendOptions | undefined} an object of type `ChartLegendOptions`.
   */
  getChartLegendOptions(data, colors, position) {
    if (data && data.length) {
      position = position ? Object.assign({ x: 10, y: 0 }, position) : { x: 10, y: 0 };
      const legendsMap = {
        position,
        legends: data.map((text, index) => {
          return {
            field: text,
            color: this.getColorFromToken(this.getColorByIndex(index, colors)),
            icon: '',
          };
        }),
      };
      return legendsMap;
    }
  }
  /**
   * This function calculates the position of a legend on a chart based on its index and the chart layout.
   *
   * @param {ChartPosition} position - The initial position of the legend on the chart, with x and y coordinates.
   * @param {number} index - The index parameter is a number that represents the index of the legend item in the array of legends. It is used to calculate the position of the legend item on the chart.
   * @param {number} longestTextLength - text length
   * @param {number} width - chart width
   * @returns {ChartPosition} an object of type `ChartPosition` with `x` and `y` properties.
   */
  getLegendPosition(position, index, longestTextLength, width) {
    const maxWidth = width;
    if (maxWidth) {
      const restWidth = maxWidth - position.x;
      const singleWidth = longestTextLength * 7 + 24;
      const singleHeight = 18;
      const column = Math.max(Number((restWidth / singleWidth).toFixed(0)), 1);
      const row = parseInt((index / column).toString());
      const x = position.x + singleWidth * (index % column);
      const y = position.y + row * singleHeight;
      return { x, y };
    }
    return { x: 0, y: 0 };
  }
}

/** The LayoutInputProcessor class processes input chart options to calculate layout dimensions and margins. */
class LayoutInputProcessor {
  /**
   * This function processes chart options and returns layout dimensions and margins.
   *
   * @param {ChartOptions<unknown>} input - A ChartOptions object containing the container and layout properties.
   * @returns {LayoutProcessResultType} An object with properties `width`, `height`, `innerWidth`, `innerHeight`, `top`, `right`,
   * `bottom`, and `left`.
   */
  process(input) {
    const { container, layout } = input;
    const { top, right, bottom, left } = ((layout === null || layout === void 0 ? void 0 : layout.margin) ||
      DEFAULT_LAYOUT.margin);
    const dimensionController = new ChartDimensionController(container);
    return {
      width: dimensionController.getContainerClientWidth(layout),
      height: dimensionController.getContainerClientHeight(layout),
      innerWidth: dimensionController.getContainerInnerWidth(layout),
      innerHeight: dimensionController.getContainerInnerHeight(layout),
      top,
      right,
      bottom,
      left,
    };
  }
}

/** The `ProcessorChain` class takes an array of input processors, processes input through them, and returns the final output. */
class ProcessorChain {
  /**
   * This is a constructor function that takes an array of input processors as a parameter.
   *
   * @param {InputProcessor<unknown, unknown, unknown>[]} processors - The `processors` parameter is a
   * private property of the class that is of type `InputProcessor` which is an interface that takes
   * three type parameters - `Input`, `Output`, and `Context`. It is an array of instances of classes
   * that implement the `InputProcessor` interface. These processors are
   */
  constructor(processors) {
    this.processors = processors;
  }
  /**
   * This function processes input through a series of processors and returns the final output.
   *
   * @typedef T generic type
   * @param {unknown} input - The input parameter is of type unknown, which means it can be any type of
   * value. It is the data that will be processed by the processors.
   * @returns {T} the output of the last processor in the `this.processors` array.
   */
  process(input) {
    let previousOutput;
    for (const processor of this.processors) {
      previousOutput = processor.process(input, previousOutput);
    }
    return previousOutput;
  }
}

/** The `LegendInputProcessor` class processes chart options and previous layout results to generate a legend input object for a line chart. */
class LegendInputProcessor {
  /**
   * This function takes in chart options and previous layout results, and returns a legend input object with data, colors, position, width, and height properties.
   *
   *  @param {ChartOptions<LineChartDataType>} input - The input parameter is an object of type ChartOptions that contains the data and
   * configuration options for a line chart.
   * @param {LayoutProcessResultType} previousOutput - `previousOutput` is an optional parameter of
   * type `LayoutProcessResultType` that represents the output of the previous layout process. It is
   * used to retrieve the width and height of the chart, which are needed to properly position the
   * legend. If no previous output is provided, the width and height will
   * @returns {LegendInputType} an object of type `LegendInputType`. The object contains the following properties:
   * - `data`: an array of legend items
   * - `colors`: an array of colors used in the chart
   * - `position`: an object with `x` and `y` properties representing the position of the legend
   * - `width`: the width of the chart
   * - `height`: the
   */
  process(input, previousOutput) {
    const { colors, legends = [] } = input;
    const { width, height } = previousOutput;
    return {
      data: legends,
      colors,
      position: { x: 10, y: 10 },
      width,
      height,
    };
  }
}

exports.BaseChart = BaseChart;
exports.BaseDrawer = BaseDrawer;
exports.InteractingEntryGenerator = InteractingEntryGenerator;
exports.LayoutInputProcessor = LayoutInputProcessor;
exports.LegendDrawer = LegendDrawer;
exports.LegendInputProcessor = LegendInputProcessor;
exports.ProcessorChain = ProcessorChain;
exports.pie = pie;
exports.select = select;
