UNPKG

ag-charts-community

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

8,493 lines 270 kB
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
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;
};

// packages/ag-charts-community/src/chart/caption.ts
import { createId as createId2, isArray as isArray6, toPlainText as toPlainText2 } from "ag-charts-core";

// packages/ag-charts-community/src/scene/node.ts
import { Logger, createId, createSvgElement } from "ag-charts-core";

// packages/ag-charts-community/src/util/object.ts
import { entries, isArray, isObject, isPlainObject } from "ag-charts-core";

// packages/ag-charts-community/src/util/decorator.ts
var BREAK_TRANSFORM_CHAIN = Symbol("BREAK");
var CONFIG_KEY = "__decorator_config";
var ACCESSORS_KEY = "__decorator_accessors";
function addFakeTransformToInstanceProperty(target, propertyKeyOrSymbol) {
  initialiseConfig(target, propertyKeyOrSymbol).optional = true;
}
function initialiseConfig(target, propertyKeyOrSymbol) {
  if (Object.getOwnPropertyDescriptor(target, CONFIG_KEY) == null) {
    Object.defineProperty(target, CONFIG_KEY, { value: {} });
  }
  if (Object.getOwnPropertyDescriptor(target, ACCESSORS_KEY) == null) {
    const parentAccessors = Object.getPrototypeOf(target)?.[ACCESSORS_KEY];
    const accessors = parentAccessors?.slice() ?? [];
    Object.defineProperty(target, ACCESSORS_KEY, { value: accessors });
  }
  const config = target[CONFIG_KEY];
  const propertyKey = propertyKeyOrSymbol.toString();
  if (config[propertyKey] != null) {
    return config[propertyKey];
  }
  config[propertyKey] = { setters: [], getters: [], observers: [] };
  const descriptor = Object.getOwnPropertyDescriptor(target, propertyKeyOrSymbol);
  let prevGet = descriptor?.get;
  let prevSet = descriptor?.set;
  if (prevGet == null || prevSet == null) {
    const accessors = target[ACCESSORS_KEY];
    let index = accessors.indexOf(propertyKeyOrSymbol);
    if (index === -1) {
      index = accessors.push(propertyKeyOrSymbol) - 1;
    }
    prevGet ?? (prevGet = function() {
      let accessorValues = this.__accessors;
      if (accessorValues == null) {
        accessorValues = accessors.slice().fill(void 0);
        Object.defineProperty(this, "__accessors", { value: accessorValues });
      }
      return accessorValues[index];
    });
    prevSet ?? (prevSet = function(value) {
      let accessorValues = this.__accessors;
      if (accessorValues == null) {
        accessorValues = accessors.slice().fill(void 0);
        Object.defineProperty(this, "__accessors", { value: accessorValues });
      }
      accessorValues[index] = value;
    });
  }
  const getter = function() {
    let value = prevGet.call(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.call(this);
    }
    for (const transformFn of setters) {
      value = transformFn(this, propertyKeyOrSymbol, value, oldValue);
      if (value === BREAK_TRANSFORM_CHAIN) {
        return;
      }
    }
    prevSet.call(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));
}

// packages/ag-charts-community/src/util/object.ts
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) {
  if (Object.is(a, b))
    return true;
  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 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 merge(...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] = merge(target[key], source[key]);
      } else if (!(key in target)) {
        target[key] ?? (target[key] = source[key]);
      }
    }
  }
  return target;
}

// packages/ag-charts-community/src/scene/bbox.ts
import { boxContains, boxesEqual, clamp } from "ag-charts-core";

// packages/ag-charts-community/src/util/interpolating.ts
var interpolate = Symbol("interpolate");

// packages/ag-charts-community/src/util/nearest.ts
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;
}

// packages/ag-charts-community/src/scene/bbox.ts
var _BBox = class _BBox {
  constructor(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
  }
  static fromDOMRect({ x, y, width, height }) {
    return new _BBox(x, y, width, height);
  }
  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 _BBox(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, height } = this;
    return new _BBox(x, y, width, height);
  }
  equals(other) {
    return boxesEqual(this, other);
  }
  containsPoint(x, y) {
    return boxContains(this, x, y);
  }
  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 _BBox(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 of Object.keys(amount)) {
        const value = amount[key];
        if (typeof value === "number") {
          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 of Object.keys(amount)) {
        const value = amount[key];
        if (typeof value === "number") {
          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;
  }
  [interpolate](other, d) {
    return new _BBox(
      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;

// packages/ag-charts-community/src/scene/changeDetectable.ts
import { arraysEqual } from "ag-charts-core";
var TRIPLE_EQ = (lhs, rhs) => lhs === rhs;
function SceneChangeDetection(opts) {
  return function(target, key) {
    const privateKey = `__${key}`;
    if (target[key])
      return;
    prepareGetSet(target, key, privateKey, opts);
  };
}
function SceneRefChangeDetection(opts) {
  return SceneChangeDetection(opts);
}
function SceneObjectChangeDetection(opts) {
  return SceneChangeDetection(opts);
}
function SceneArrayChangeDetection(opts) {
  const baseOpts = opts ?? {};
  baseOpts.equals = arraysEqual;
  return SceneChangeDetection(opts);
}
function prepareGetSet(target, key, privateKey, opts) {
  const { changeCb, convertor, checkDirtyOnAssignment = false } = opts ?? {};
  const requiredOpts = { changeCb, checkDirtyOnAssignment, convertor };
  const setter = buildCheckDirtyChain(
    privateKey,
    buildChangeCallbackChain(
      buildConvertorChain(buildSetter(privateKey, requiredOpts), 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(privateKey, setterFn, opts) {
  const { checkDirtyOnAssignment } = opts;
  if (checkDirtyOnAssignment) {
    return function(value) {
      const change = setterFn.call(this, value);
      if (value?._dirty === true) {
        this.markDirty(privateKey);
      }
      return change;
    };
  }
  return setterFn;
}
function buildSetter(privateKey, opts) {
  const { equals = TRIPLE_EQ } = opts;
  return function(value) {
    const oldValue = this[privateKey];
    if (!equals(value, oldValue)) {
      this[privateKey] = value;
      this.onChangeDetection(privateKey);
      return value;
    }
    return NO_CHANGE;
  };
}

// packages/ag-charts-community/src/scene/zIndex.ts
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 length = Math.min(aArray.length, bArray.length);
  for (let i = 0; i < length; i += 1) {
    const diff = cmp(aArray[i], bArray[i]);
    if (diff !== 0)
      return diff;
  }
  return cmp(aArray.length, bArray.length);
}

// packages/ag-charts-community/src/scene/node.ts
var MAX_ERROR_COUNT = 5;
var _Node = class _Node {
  constructor(options) {
    /** Unique number to allow creation order to be easily determined. */
    this.serialNumber = _Node._nextSerialNumber++;
    this.childNodeCounts = { groups: 0, nonGroups: 0, thisComplexity: 0, complexity: 0 };
    /** Unique node ID in the form `ClassName-NaturalNumber`. */
    this.id = createId(this);
    this.name = void 0;
    this.transitionOut = void 0;
    this.pointerEvents = 0 /* All */;
    this._datum = void 0;
    this._previousDatum = void 0;
    this.scene = void 0;
    this._debugDirtyProperties = void 0;
    this.parentNode = void 0;
    this.cachedBBox = void 0;
    /**
     * To simplify the type system (especially in Selections) we don't have the `Parent` node
     * (one that has children). Instead, we mimic HTML DOM, where any node can have children.
     * But we still need to distinguish regular leaf nodes from container leafs somehow.
     */
    this.isContainerNode = false;
    this.visible = true;
    this.zIndex = 0;
    this.batchLevel = 0;
    this.batchDirty = false;
    this.name = options?.name;
    this.tag = options?.tag ?? NaN;
    this.zIndex = options?.zIndex ?? 0;
    this.scene = options?.scene;
    if (options?.debugDirty ?? _Node._debugEnabled) {
      this._debugDirtyProperties = /* @__PURE__ */ new Map([["__first__", []]]);
    }
  }
  static toSVG(node, width, height) {
    const svg = node?.toSVG();
    if (svg == null || !svg.elements.length && !svg.defs?.length)
      return;
    const root = createSvgElement("svg");
    root.setAttribute("width", String(width));
    root.setAttribute("height", String(height));
    root.setAttribute("viewBox", `0 0 ${width} ${height}`);
    root.setAttribute("overflow", "visible");
    if (svg.defs?.length) {
      const defs = createSvgElement("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;
  }
  set datum(datum) {
    if (this._datum !== datum) {
      this._previousDatum = this._datum;
      this._datum = datum;
    }
  }
  get previousDatum() {
    return this._previousDatum;
  }
  get layerManager() {
    return this.scene?.layersManager;
  }
  get imageLoader() {
    return this.scene?.imageLoader;
  }
  closestDatum() {
    for (const { datum } of this.traverseUp(true)) {
      if (datum != null) {
        return datum;
      }
    }
  }
  /** Perform any pre-rendering initialization. */
  preRender(_renderCtx, thisComplexity = 1) {
    this.childNodeCounts.groups = 0;
    this.childNodeCounts.nonGroups = 1;
    this.childNodeCounts.complexity = thisComplexity;
    this.childNodeCounts.thisComplexity = thisComplexity;
    if (this.batchLevel > 0 || this.batchDirty) {
      throw new Error("AG Charts - illegal rendering state; batched update in progress");
    }
    return this.childNodeCounts;
  }
  /** Guaranteed isolated render - if there is any failure, the Cavans2D context is returned to its prior state. */
  isolatedRender(renderCtx) {
    renderCtx.ctx.save();
    try {
      this.render(renderCtx);
    } catch (e) {
      const errorCount = e.errorCount ?? 1;
      if (errorCount >= MAX_ERROR_COUNT) {
        e.errorCount = errorCount;
        throw e;
      }
      Logger.warnOnce("Error during rendering", e, e.stack);
    } finally {
      renderCtx.ctx.restore();
    }
  }
  render(renderCtx) {
    const { stats } = renderCtx;
    this.debugDirtyProperties();
    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;
    }
  }
  setScene(scene) {
    this.scene = scene;
  }
  *traverseUp(includeSelf) {
    let node = this;
    if (includeSelf) {
      yield node;
    }
    while (node = node.parentNode) {
      yield node;
    }
  }
  /**
   * Checks if the node is the root (has no parent).
   */
  isRoot() {
    return !this.parentNode;
  }
  removeChild(node) {
    throw new Error(
      `AG Charts - internal error, unknown child node ${node.name ?? node.id} in $${this.name ?? this.id}`
    );
  }
  remove() {
    this.parentNode?.removeChild(this);
  }
  destroy() {
    this.parentNode?.removeChild(this);
  }
  batchedUpdate(fn) {
    this.batchLevel++;
    fn();
    this.batchLevel--;
    if (this.batchLevel === 0 && this.batchDirty) {
      this.markDirty();
      this.batchDirty = false;
    }
  }
  setProperties(styles) {
    this.batchLevel++;
    Object.assign(this, styles);
    this.batchLevel--;
    if (this.batchLevel === 0 && this.batchDirty) {
      this.markDirty();
      this.batchDirty = false;
    }
    return this;
  }
  containsPoint(_x, _y) {
    return false;
  }
  pickNode(x, y) {
    if (this.containsPoint(x, y)) {
      return this;
    }
  }
  pickNodes(x, y, into = []) {
    if (this.containsPoint(x, y)) {
      into.push(this);
    }
    return into;
  }
  getBBox() {
    this.cachedBBox ?? (this.cachedBBox = Object.freeze(this.computeBBox()));
    return this.cachedBBox;
  }
  computeBBox() {
    return;
  }
  onChangeDetection(property) {
    this.markDirty(property);
  }
  markDirtyChildrenOrder() {
    this.cachedBBox = void 0;
  }
  markDirty(property) {
    if (this.batchLevel > 0) {
      this.batchDirty = true;
      return;
    }
    if (property != null && this._debugDirtyProperties) {
      this.markDebugProperties(property);
    }
    this.cachedBBox = void 0;
    this.parentNode?.markDirty();
  }
  markDebugProperties(property) {
    const sources = this._debugDirtyProperties?.get(property) ?? [];
    const caller = new Error().stack?.split("\n").filter((line) => {
      return line !== "Error" && !line.includes(".markDebugProperties") && !line.includes(".markDirty") && !line.includes("Object.assign ") && !line.includes(`${this.constructor.name}.`);
    }) ?? "unknown";
    sources.push(caller[0].replace(" at ", "").trim());
    this._debugDirtyProperties?.set(property, sources);
  }
  debugDirtyProperties() {
    if (this._debugDirtyProperties == null)
      return;
    if (!this._debugDirtyProperties.has("__first__")) {
      this._debugDirtyProperties.forEach((sources, property) => {
        if (sources.length > 1) {
          console.groupCollapsed(
            `Property changed multiple times before render: ${this.constructor.name}.${property} (${sources.length}x)`
          );
          sources.forEach((source) => console.log(source));
          console.groupEnd();
        }
      });
    }
    this._debugDirtyProperties.clear();
  }
  onZIndexChange() {
    this.parentNode?.markDirtyChildrenOrder();
  }
  toSVG() {
    return;
  }
};
_Node._nextSerialNumber = 0;
// eslint-disable-next-line sonarjs/public-static-readonly
_Node._debugEnabled = false;
__decorateClass([
  SceneChangeDetection()
], _Node.prototype, "visible", 2);
__decorateClass([
  SceneObjectChangeDetection({
    equals: objectsEqual,
    changeCb: (target) => target.onZIndexChange()
  })
], _Node.prototype, "zIndex", 2);
var Node = _Node;

// packages/ag-charts-community/src/scene/shape/text.ts
import { createSvgElement as createSvgElement10, isArray as isArray4, isString as isString3, toPlainText } from "ag-charts-core";

// packages/ag-charts-community/src/util/debug.ts
import { Logger as Logger2, getWindow, toArray } from "ag-charts-core";
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);
    Logger2.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();
        Logger2.log(...logContent);
      }
    };
    return Object.assign(resultFn, {
      check: () => Debug.check(...debugSelectors),
      group: (name, cb) => {
        if (Debug.check(...debugSelectors)) {
          return Logger2.logGroup(name, cb);
        }
        return cb();
      }
    });
  },
  check(...debugSelectors) {
    if (debugSelectors.length === 0) {
      debugSelectors.push(true);
    }
    const chartDebug = toArray(getWindow("agChartsDebug"));
    return chartDebug.some((selector) => debugSelectors.includes(selector));
  },
  inDevelopmentMode(fn) {
    if (Debug.check("dev")) {
      return fn();
    }
  }
};

// packages/ag-charts-community/src/util/canvas.util.ts
function createCanvasContext(width = 0, height = 0) {
  return new OffscreenCanvas(width, height).getContext("2d");
}

// packages/ag-charts-community/src/util/lruCache.ts
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();
  }
};

// packages/ag-charts-community/src/util/textMeasurer.ts
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 = TextUtils.toFontString(options.font);
    const key = `${font}-${options.textAlign ?? "start"}-${options.textBaseline ?? "top"}`;
    return this.instanceMap.get(key) ?? this.createFontMeasurer(font, options, key);
  }
  static clear() {
    this.instanceMap.clear();
  }
  // 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 ?? "top";
    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;
    // cached text measurements
    this.measureMap = new LRUCache(100);
    if (options.textAlign) {
      ctx.textAlign = options.textAlign;
    }
    if (options.textBaseline) {
      ctx.textBaseline = options.textBaseline;
    }
    ctx.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 }) {
    let fontString = "";
    if (fontStyle && fontStyle !== "normal") {
      fontString += `${fontStyle} `;
    }
    if (fontWeight && fontWeight !== "normal" && fontWeight !== 400) {
      fontString += `${fontWeight} `;
    }
    fontString += `${fontSize}px`;
    fontString += ` ${fontFamily}`;
    return fontString.trim();
  }
  static getLineHeight(fontSize) {
    return Math.ceil(fontSize * this.defaultLineHeight);
  }
  static getHorizontalModifier(textAlign) {
    switch (textAlign) {
      case "left":
      case "start":
        return 0;
      case "center":
        return 0.5;
      case "right":
      case "end":
        return 1;
      default:
        return 0;
    }
  }
  // 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";
// Representation for text clipping.
TextUtils.defaultLineHeight = 1.15;
// Normally between 1.1 and 1.2
TextUtils.lineSplitter = /\r?\n/g;
var SimpleTextMeasurer = class {
  constructor(measureTextFn, textBaseline = "alphabetic") {
    this.measureTextFn = measureTextFn;
    this.textBaseline = textBaseline;
    // local chars width cache per TextMeasurer
    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
    };
  }
  // Calculates aggregated metrics for multiline text.
  getMultilineMetrics(lines) {
    let width = 0;
    let height = 0;
    let offsetTop = 0;
    let offsetLeft = 0;
    let baselineDistance = 0;
    let alphabeticBaseline = 0;
    const verticalModifier = TextUtils.getVerticalModifier(this.textBaseline);
    const lineMetrics = [];
    let index = 0;
    const length = 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 (width < m.width) {
        width = m.width;
      }
      if (offsetLeft < m.actualBoundingBoxLeft) {
        offsetLeft = m.actualBoundingBoxLeft;
      }
      if (index === 0) {
        height += m.actualBoundingBoxAscent;
        offsetTop += m.actualBoundingBoxAscent;
        alphabeticBaseline = m.alphabeticBaseline;
      } else {
        baselineDistance += m.fontBoundingBoxAscent;
      }
      if (index === length - 1) {
        height += 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++;
    }
    height += baselineDistance;
    offsetTop += baselineDistance * verticalModifier;
    return { width, height, offsetTop, offsetLeft, alphabeticBaseline, 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 } = this.measureTextFn(char);
    this.charMap.set(char, width);
    return width;
  }
};

// packages/ag-charts-community/src/scene/group.ts
import { clamp as clamp5, toIterable } from "ag-charts-core";

// packages/ag-charts-community/src/scene/canvas/canvasUtil.ts
function clearContext({
  context,
  pixelRatio,
  width,
  height
}) {
  context.save();
  try {
    context.resetTransform();
    context.clearRect(0, 0, Math.ceil(width * pixelRatio), Math.ceil(height * pixelRatio));
  } finally {
    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}`);
        }
      }
    });
  }
}

// packages/ag-charts-community/src/scene/canvas/hdpiOffscreenCanvas.ts
function canvasDimensions(width, height, pixelRatio) {
  return [Math.floor(width * pixelRatio), Math.floor(height * pixelRatio)];
}
var HdpiOffscreenCanvas = class {
  constructor(options) {
    const { width, height, pixelRatio, willReadFrequently = false } = options;
    this.width = width;
    this.height = height;
    this.pixelRatio = pixelRatio;
    const [canvasWidth, canvasHeight] = canvasDimensions(width, height, pixelRatio);
    this.canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
    this.context = this.canvas.getContext("2d", { willReadFrequently });
    this.context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
    debugContext(this.context);
  }
  drawImage(context, dx = 0, dy = 0) {
    return context.drawImage(this.canvas, dx, dy);
  }
  transferToImageBitmap() {
    return this.canvas.transferToImageBitmap();
  }
  resize(width, height, pixelRatio) {
    if (!(width > 0 && height > 0))
      return;
    const { canvas, context } = this;
    if (width !== this.width || height !== this.height || pixelRatio !== this.pixelRatio) {
      const [canvasWidth, canvasHeight] = canvasDimensions(width, height, pixelRatio);
      canvas.width = canvasWidth;
      canvas.height = canvasHeight;
    }
    context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
    this.width = width;
    this.height = height;
    this.pixelRatio = pixelRatio;
  }
  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);
  }
};

// packages/ag-charts-community/src/scene/shape/shape.ts
import { boxesEqual as boxesEqual2, clamp as clamp4, generateUUID, isString } from "ag-charts-core";

// packages/ag-charts-community/src/scene/gradient/conicGradient.ts
import { createSvgElement as createSvgElement3 } from "ag-charts-core";

// packages/ag-charts-community/src/util/angle.ts
var twoPi = Math.PI * 2;
var halfPi = Math.PI / 2;
function normalizeAngle360(radians) {
  radians %= twoPi;
  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 startAngle !== endAngle;
  }
}
function toRadians(degrees) {
  return degrees / 180 * Math.PI;
}
function angleBetween(angle0, angle1) {
  angle0 = normalizeAngle360(angle0);
  angle1 = normalizeAngle360(angle1);
  return angle1 - angle0 + (angle0 > angle1 ? twoPi : 0);
}
function normalizeAngle360FromDegrees(degrees) {
  return degrees ? normalizeAngle360(toRadians(degrees)) : 0;
}

// packages/ag-charts-community/src/scene/gradient/gradient.ts
import { createSvgElement as createSvgElement2 } from "ag-charts-core";

// packages/ag-charts-community/src/scale/colorScale.ts
import { Logger as Logger3, clamp as clamp3 } from "ag-charts-core";

// packages/ag-charts-community/src/util/color.ts
import { clamp as clamp2 } from "ag-charts-core";
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 _Color {
  /**
   * 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 = clamp2(0, r || 0, 1);
    this.g = clamp2(0, g || 0, 1);
    this.b = clamp2(0, b || 0, 1);
    this.a = clamp2(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 !!_Color.parseHex(str);
    }
    if (str.indexOf("rgb") >= 0) {
      return !!_Color.stringToRgba(str);
    }
    return _Color.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 _Color.fromHexString(str);
    }
    const hex = _Color.nameToHex.get(str.toLowerCase());
    if (hex) {
      return _Color.fromHexString(hex);
    }
    if (str.indexOf("rgb") >= 0) {
      return _Color.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 = _Color.parseHex(str);
    if (values) {
      const [r, g, b, a] = values;
      return new _Color(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 = clamp2(0, value, 100);
        value /= 100;
      } else if (i === 3) {
        value = clamp2(0, value, 1);
      } else {
        value = clamp2(0, value, 255);
        value /= 255;
      }
      rgba.push(value);
    }
    return rgba;
  }
  static fromRgbaString(str) {
    const rgba = _Color.stringToRgba(str);
    if (rgba) {
      if (rgba.length === 3) {
        return new _Color(rgba[0], rgba[1], rgba[2]);
      } else if (rgba.length === 4) {
        return new _Color(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 _Color(arr[0], arr[1], arr[2], arr[3]);
    }
    if (arr.length === 3) {
      return new _Color(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 = _Color.HSBtoRGB(h, s, b);
    return new _Color(rgb[0], rgb[1], rgb[2], alpha);
  }
  static fromHSL(h, s, l, alpha = 1) {
    const rgb = _Color.HSLtoRGB(h, s, l);
    return new _Color(rgb[0], rgb[1], rgb[2], alpha);
  }
  static fromOKLCH(l, c, h, alpha = 1) {
    const rgb = _Color.OKLCHtoRGB(l, c, h);
    return new _Color(rgb[0], rgb[1], rgb[2], alpha);
  }
  static padHex(str) {
    return str.length === 1 ? "0" + str : str;
  }
  toHexString() {
    let hex = "#" + _Color.padHex(Math.round(this.r * 255).toString(16)) + _Color.padHex(Math.round(this.g * 255).toString(16)) + _Color.padHex(Math.round(this.b * 255).toString(16));
    if (this.a < 1) {
      hex += _Color.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 _Color.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 delta3 = max - min;
      s = l > 0.5 ? delta3 / (2 - max - min) : delta3 / (max + min);
      if (max === r) {
        h = (g - b) / delta3 + (g < b ? 6 : 0);
      } else if (max === g) {
        h = (b - r) / delta3 + 2;
      } else {
        h = (r - g) / delta3 + 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 delta3 = max - min;
      const rc = (max - r) / delta3;
      const gc = (max - g) / delta3;
      const bc = (max - b) / delta3;
      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 _Color(lerp(c0.r, c1.r, t), lerp(c0.g, c1.g, t), lerp(c0.b, c1.b, t), lerp(c0.a, c1.a, t));
  }
  static lighten(c, t) {
    const oklch = _Color.RGBtoOKLCH(c.r, c.g, c.b);
    return _Color.fromOKLCH(clamp2(0, oklch[0] + t, 1), oklch[1], oklch[2]);
  }
  static darken(c, t) {
    const oklch = _Color.RGBtoOKLCH(c.r, c.g, c.b);
    return _Color.fromOKLCH(clamp2(0, oklch[0] - t, 1), oklch[1], oklch[2]);
  }
  static interpolate(colors, count) {
    const step = 1 / (colors.length - 1);
    const oklchColors = colors.map((c) => _Color.RGBtoOKLCH(c.r, c.g, c.b));
    return Array.from({ length: count }, (_, i) => {
      const t = i / (count - 1);
      const index = colors.length <= 2 ? 0 : Math.min(Math.floor(t * (colors.length - 1)), colors.length - 2);
      const q = (t - index * step) / step;
      const c0 = oklchColors[index];
      const c1 = oklchColors[index + 1];
      return _Color.fromOKLCH(lerp(c0[0], c1[0], q), lerp(c0[1], c1[1], q), lerp(c0[2], c1[2], q));
    });
  }
};
/**
 * CSS Color Module Level 4:
 * https://drafts.csswg.org/css-color/#named-colors
 */
_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;

// packages/ag-charts-community/src/scale/abstractScale.ts
var AbstractScale = class {
  ticks(_ticks, _domain, _visibleRange) {
    return void 0;
  }
  niceDomain(_ticks, domain = this.domain) {
    return domain;
  }
  get bandwidth() {
    return void 0;
  }
  get step() {
    return void 0;
  }
  get inset() {
    return void 0;
  }
};

// packages/ag-charts-community/src/scale/invalidating.ts
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
  });
};

// packages/ag-charts-community/src/scale/colorScale.ts
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 delta = 1e-6;
var isAchromatic = (x) => x.c < delta || x.l < delta || x.l > 1 - delta;
var interpolateOklch = (x, y, d) => {
  d = clamp3(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 extends AbstractScale {
  constructor() {
    super(...arguments);
    this.type = "color";
    this.defaultTickCount = 0;
    this.invalid = true;
    this.domain = [0, 1];
    this.range = ["red", "blue"];
    this.parsedRange = this.range.map(convertColorStringToOklcha);
  }
  update() {
    const { domain, range: range2 } = this;
    if (domain.length < 2) {
      Logger3.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) {
        Logger3.warnOnce("`colorDomain` values should be supplied in ascending order.");
        domain.sort((a2, b2) => a2 - b2);
        break;
      }
    }
    if (range2.length < domain.length) {
      for (let i = range2.length; i < domain.length; i++) {
        range2.push(range2.length > 0 ? range2[0] : "black");
      }
    }
    this.parsedRange = this.range.map(convertColorStringToOklcha);
  }
  normalizeDomains(...domains) {
    return { domain: domains.flat(), animatable: true };
  }
  toDomain() {
    return;
  }
  convert(x) {
    this.refresh();
    const { domain, range: range2, parsedRange } = this;
    const d0 = domain[0];
    const d1 = domain.at(-1);
    const r0 = range2[0];
    const r1 = range2[range2.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 / (range2.length - 1);
      index = range2.length <= 2 ? 0 : Math.min(Math.floor(t * (range2.length - 1)), range2.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();
  }
  invert() {
    return;
  }
  refresh() {
    if (!this.invalid)
      return;
    this.invalid = false;
    this.update();
    if (this.invalid) {
      Logger3.warnOnce("Expected update to not invalidate scale");
    }
  }
};
__decorateClass([
  Invalidating
], ColorScale.prototype, "domain", 2);
__decorateClass([
  Invalidating
], ColorScale.prototype, "range", 2);

// packages/ag-charts-community/src/scene/gradient/gradient.ts
var Gradient = class {
  constructor(colorSpace, stops = [], bbox) {
    this.colorSpace = colorSpace;
    this.stops = stops;
    this.bbox = bbox;
    this._cache = void 0;
  }
  createGradient(ctx, shapeBbox, params) {
    const bbox = this.bbox ?? shapeBbox;
    if (!bbox.isFinite()) {
      return;
    }
    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 gradient = this.createCanvasGradient(ctx, bbox, params);
    if (gradient == null)
      return;
    const isOkLch = colorSpace === "oklch";
    const step = 0.05;
    let c0 = stops[0];
    gradient.addColorStop(c0.stop, c0.color);
    for (let i = 1; i < stops.length; i += 1) {
      const c1 = stops[i];
      if (isOkLch) {
        const scale = new ColorScale();
        scale.domain = [c0.stop, c1.stop];
        scale.range = [c0.color, c1.color];
        for (let stop = c0.stop + step; stop < c1.stop; stop += step) {
          gradient.addColorStop(stop, scale.convert(stop));
        }
      }
      gradient.addColorStop(c1.stop, c1.color);
      c0 = c1;
    }
    if ("createPattern" in gradient) {
      gradient = gradient.createPattern();
    }
    this._cache = { ctx, bbox, gradient };
    return gradient;
  }
  toSvg(shapeBbox) {
    const bbox = this.bbox ?? shapeBbox;
    const gradient = this.createSvgGradient(bbox);
    this.stops.forEach(({ stop: offset, color }) => {
      const stop = createSvgElement2("stop");
      stop.setAttribute("offset", `${offset}`);
      stop.setAttribute("stop-color", `${color}`);
      gradient.appendChild(stop);
    });
    return gradient;
  }
};

// packages/ag-charts-community/src/scene/gradient/conicGradient.ts
var ConicGradient = class extends Gradient {
  constructor(colorSpace, stops, angle = 0, bbox) {
    super(colorSpace, stops, bbox);
    this.angle = angle;
  }
  createCanvasGradient(ctx, bbox, params) {
    const angleOffset = -90;
    const { angle } = this;
    const radians = normalizeAngle360FromDegrees(angle + angleOffset);
    const cx = params?.centerX ?? bbox.x + bbox.width * 0.5;
    const cy = params?.centerY ?? bbox.y + bbox.height * 0.5;
    return ctx.createConicGradient(radians, cx, cy);
  }
  createSvgGradient(_bbox) {
    return createSvgElement3("linearGradient");
  }
};

// packages/ag-charts-community/src/scene/gradient/linearGradient.ts
import { createSvgElement as createSvgElement4 } from "ag-charts-core";
var LinearGradient = class extends Gradient {
  constructor(colorSpace, stops, angle = 0, bbox) {
    super(colorSpace, stops, bbox);
    this.angle = angle;
  }
  getGradientPoints(bbox) {
    const angleOffset = 90;
    const { angle } = this;
    const radians = normalizeAngle360FromDegrees(angle + 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 { x0: cx + cos * l, y0: cy + sin * l, x1: cx - cos * l, y1: cy - sin * l };
  }
  createCanvasGradient(ctx, bbox) {
    const { x0, y0, x1, y1 } = this.getGradientPoints(bbox);
    if (isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) {
      return void 0;
    }
    return ctx.createLinearGradient(x0, y0, x1, y1);
  }
  createSvgGradient(bbox) {
    const { x0, y0, x1, y1 } = this.getGradientPoints(bbox);
    const gradient = createSvgElement4("linearGradient");
    gradient.setAttribute("x1", String(x0));
    gradient.setAttribute("y1", String(y0));
    gradient.setAttribute("x2", String(x1));
    gradient.setAttribute("y2", String(y1));
    gradient.setAttribute("gradientUnits", "userSpaceOnUse");
    return gradient;
  }
};

// packages/ag-charts-community/src/scene/gradient/radialGradient.ts
import { createSvgElement as createSvgElement5 } from "ag-charts-core";
var RadialGradient = class extends Gradient {
  constructor(colorSpace, stops, bbox) {
    super(colorSpace, stops, bbox);
  }
  createCanvasGradient(ctx, bbox, params) {
    const cx = params?.centerX ?? bbox.x + bbox.width * 0.5;
    const cy = params?.centerY ?? bbox.y + bbox.height * 0.5;
    const innerRadius = params?.innerRadius ?? 0;
    const outerRadius = params?.outerRadius ?? Math.hypot(bbox.width * 0.5, bbox.height * 0.5) / Math.SQRT2;
    return ctx.createRadialGradient(cx, cy, innerRadius, cx, cy, outerRadius);
  }
  createSvgGradient(bbox) {
    const cx = bbox.x + bbox.width * 0.5;
    const cy = bbox.y + bbox.height * 0.5;
    const gradient = createSvgElement5("radialGradient");
    gradient.setAttribute("cx", String(cx));
    gradient.setAttribute("cy", String(cy));
    gradient.setAttribute("r", String(Math.hypot(bbox.width * 0.5, bbox.height * 0.5) / Math.SQRT2));
    gradient.setAttribute("gradientUnits", "userSpaceOnUse");
    return gradient;
  }
};

// packages/ag-charts-community/src/scene/gradient/stops.ts
import { Logger as Logger5 } from "ag-charts-core";

// packages/ag-charts-community/src/util/properties.ts
import { Logger as Logger4, isArray as isArray2, isPlainObject as isPlainObject2 } from "ag-charts-core";
var Property = addFakeTransformToInstanceProperty;
var BaseProperties = class {
  handleUnknownProperties(_unknownKeys, _properties) {
  }
  set(properties) {
    const { className = this.constructor.name } = this.constructor;
    if (properties == null) {
      this.clear();
      return this;
    }
    if (typeof properties !== "object") {
      Logger4.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 array = self[propertyKey].reset(value);
            if (array == null) {
              Logger4.warn(`unable to set [${String(propertyKey)}] - expecting a properties array`);
            } else {
              self[propertyKey] = array;
            }
          } else {
            self[propertyKey].set(value);
          }
        } else if (isPlainObject2(value)) {
          self[propertyKey] = merge(value, self[propertyKey] ?? {});
        } else {
          self[propertyKey] = value;
        }
        keys.delete(propertyKey);
      }
    }
    this.handleUnknownProperties(keys, properties);
    for (const unknownKey of keys) {
      Logger4.warn(`unable to set [${String(unknownKey)}] in ${className} - property is unknown`);
    }
    return this;
  }
  clear() {
    for (const propertyKey of listDecoratedProperties(this)) {
      const currentValue = this[propertyKey];
      if (isProperties(currentValue)) {
        currentValue.clear();
      } else {
        this[propertyKey] = void 0;
      }
    }
    return this;
  }
  toJson() {
    return listDecoratedProperties(this).reduce((object, propertyKey) => {
      const propertyValue = this[propertyKey];
      object[String(propertyKey)] = isProperties(propertyValue) ? propertyValue.toJson() : propertyValue;
      return object;
    }, {});
  }
};
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 (isArray2(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;
}

// packages/ag-charts-community/src/scene/gradient/stops.ts
var StopProperties = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.color = "black";
  }
};
__decorateClass([
  Property
], StopProperties.prototype, "stop", 2);
__decorateClass([
  Property
], StopProperties.prototype, "color", 2);
function stopsAreAscending(fills) {
  let currentStop;
  for (const fill of fills) {
    if (fill?.stop == null)
      continue;
    if (currentStop != null && fill.stop < currentStop) {
      return false;
    }
    currentStop = fill.stop;
  }
  return true;
}
function discreteColorStops(colorStops) {
  return colorStops.flatMap((colorStop, i) => {
    const { stop } = colorStop;
    const nextColor = colorStops.at(i + 1)?.color;
    return nextColor != null ? [colorStop, { stop, color: nextColor }] : [colorStop];
  });
}
function getDefaultColorStops(defaultColorStops, fillMode) {
  const stopOffset = fillMode === "discrete" ? 1 : 0;
  const colorStops = defaultColorStops.map(
    (color, index, { length }) => ({
      stop: (index + stopOffset) / (length - 1 + stopOffset),
      color
    })
  );
  return fillMode === "discrete" ? discreteColorStops(colorStops) : colorStops;
}
function getColorStops(baseFills, defaultColorStops, domain, fillMode = "continuous") {
  const fills = baseFills.map((fill) => typeof fill === "string" ? { color: fill } : fill);
  if (fills.length === 0) {
    return getDefaultColorStops(defaultColorStops, fillMode);
  } else if (!stopsAreAscending(fills)) {
    Logger5.warnOnce(`[fills] must have the stops defined in ascending order`);
    return [];
  }
  const d0 = Math.min(...domain);
  const d1 = Math.max(...domain);
  const isDiscrete = fillMode === "discrete";
  const stops = new Float64Array(fills.length);
  let previousDefinedStopIndex = 0;
  let nextDefinedStopIndex = -1;
  for (let i = 0; i < fills.length; i += 1) {
    const colorStop = fills[i];
    if (i >= nextDefinedStopIndex) {
      nextDefinedStopIndex = fills.length - 1;
      for (let j = i + 1; j < fills.length; j += 1) {
        if (fills[j]?.stop != null) {
          nextDefinedStopIndex = j;
          break;
        }
      }
    }
    let stop = colorStop?.stop;
    if (stop == null) {
      const stop0 = fills[previousDefinedStopIndex]?.stop;
      const stop1 = fills[nextDefinedStopIndex]?.stop;
      const value0 = stop0 ?? d0;
      const value1 = stop1 ?? d1;
      const stopOffset = isDiscrete && stop0 == null ? 1 : 0;
      stop = value0 + (value1 - value0) * (i - previousDefinedStopIndex + stopOffset) / (nextDefinedStopIndex - previousDefinedStopIndex + stopOffset);
    } else {
      previousDefinedStopIndex = i;
    }
    stops[i] = Math.max(0, Math.min(1, (stop - d0) / (d1 - d0)));
  }
  let lastDefinedColor = fills.find((c) => c.color != null)?.color;
  let colorScale;
  const colorStops = fills.map((fill, i) => {
    let color = fill?.color;
    const stop = stops[i];
    if (color != null) {
      lastDefinedColor = color;
    } else if (lastDefinedColor != null) {
      color = lastDefinedColor;
    } else {
      if (colorScale == null) {
        colorScale = new ColorScale();
        colorScale.domain = [0, 1];
        colorScale.range = defaultColorStops;
      }
      color = colorScale.convert(stop);
    }
    return { stop, color };
  });
  return fillMode === "discrete" ? discreteColorStops(colorStops) : colorStops;
}

// packages/ag-charts-community/src/scene/image/image.ts
import { Logger as Logger6, createSvgElement as createSvgElement6 } from "ag-charts-core";
var Image2 = class {
  constructor(imageLoader, imageOptions) {
    this.imageLoader = imageLoader;
    this._cache = void 0;
    this.url = imageOptions.url;
    this.backgroundFill = imageOptions.backgroundFill ?? "black";
    this.backgroundFillOpacity = imageOptions.backgroundFillOpacity ?? 1;
    this.repeat = imageOptions.repeat ?? "no-repeat";
    this.width = imageOptions.width;
    this.height = imageOptions.height;
    this.fit = imageOptions.fit ?? "stretch";
    this.rotation = imageOptions.rotation ?? 0;
  }
  createCanvasImage(ctx, image, width, height) {
    if (!image)
      return null;
    const [renderedWidth, renderedHeight] = this.getSize(image.width, image.height, width, height);
    if (renderedWidth < 1 || renderedHeight < 1) {
      Logger6.warnOnce("Image fill is too small to render, ignoring.");
      return null;
    }
    return ctx.createPattern(image, this.repeat);
  }
  getSize(imageWidth, imageHeight, width, height) {
    const { fit } = this;
    let dw = imageWidth;
    let dh = imageHeight;
    let scale = 1;
    const shapeAspectRatio = width / height;
    const imageAspectRatio = imageWidth / imageHeight;
    if (fit === "stretch" || imageWidth === 0 || imageHeight === 0) {
      dw = width;
      dh = height;
    } else if (fit === "contain") {
      scale = imageAspectRatio > shapeAspectRatio ? width / imageWidth : height / imageHeight;
    } else if (fit === "cover") {
      scale = imageAspectRatio > shapeAspectRatio ? height / imageHeight : width / imageWidth;
    }
    return [Math.max(1, dw * scale), Math.max(1, dh * scale)];
  }
  setImageTransform(pattern, bbox) {
    if (typeof pattern === "string")
      return;
    const { url, rotation, width, height } = this;
    const image = this.imageLoader?.loadImage(url);
    if (!image) {
      return;
    }
    const angle = normalizeAngle360FromDegrees(rotation);
    const cos = Math.cos(angle);
    const sin = Math.sin(angle);
    const [renderedWidth, renderedHeight] = this.getSize(
      image.width,
      image.height,
      width ?? bbox.width,
      height ?? bbox.height
    );
    const widthScale = renderedWidth / image.width;
    const heightScale = renderedHeight / image.height;
    const bboxCenterX = bbox.x + bbox.width / 2;
    const bboxCenterY = bbox.y + bbox.height / 2;
    const rotatedW = cos * renderedWidth - sin * renderedHeight;
    const rotatedH = sin * renderedWidth + cos * renderedHeight;
    const shapeCenterX = rotatedW / 2;
    const shapeCenterY = rotatedH / 2;
    pattern?.setTransform(
      new DOMMatrix([
        cos * widthScale,
        sin * heightScale,
        -sin * widthScale,
        cos * heightScale,
        bboxCenterX - shapeCenterX,
        bboxCenterY - shapeCenterY
      ])
    );
  }
  createPattern(ctx, shapeWidth, shapeHeight, node) {
    const width = this.width ?? shapeWidth;
    const height = this.height ?? shapeHeight;
    const cache = this._cache;
    if (cache != null && cache.ctx === ctx && cache.width === width && cache.height === height) {
      return cache.pattern;
    }
    const image = this.imageLoader?.loadImage(this.url, node);
    const pattern = this.createCanvasImage(ctx, image, width, height);
    if (pattern == null)
      return;
    this._cache = { ctx, pattern, width, height };
    return pattern;
  }
  toSvg(bbox, pixelRatio) {
    const { url, rotation, backgroundFill, backgroundFillOpacity } = this;
    const { x, y, width, height } = bbox;
    const pattern = createSvgElement6("pattern");
    pattern.setAttribute("viewBox", `0 0 ${width} ${height}`);
    pattern.setAttribute("x", String(x));
    pattern.setAttribute("y", String(y));
    pattern.setAttribute("width", String(width));
    pattern.setAttribute("height", String(height));
    pattern.setAttribute("patternUnits", "userSpaceOnUse");
    const rect = createSvgElement6("rect");
    rect.setAttribute("x", "0");
    rect.setAttribute("y", "0");
    rect.setAttribute("width", String(width));
    rect.setAttribute("height", String(height));
    rect.setAttribute("fill", backgroundFill);
    rect.setAttribute("fill-opacity", String(backgroundFillOpacity));
    pattern.appendChild(rect);
    const image = createSvgElement6("image");
    image.setAttribute("href", url);
    image.setAttribute("x", "0");
    image.setAttribute("y", "0");
    image.setAttribute("width", String(width));
    image.setAttribute("height", String(height));
    image.setAttribute("preserveAspectRatio", "none");
    image.setAttribute("transform", `scale(${1 / pixelRatio}) rotate(${rotation}, ${width / 2}, ${height / 2})`);
    pattern.appendChild(image);
    return pattern;
  }
};

// packages/ag-charts-community/src/scene/pattern/pattern.ts
import {
  Logger as Logger8,
  createSvgElement as createSvgElement7
} from "ag-charts-core";

// packages/ag-charts-community/src/util/distance.ts
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));
}

// packages/ag-charts-community/src/util/svg.ts
import { Logger as Logger7 } from "ag-charts-core";
var commandEx = /^[\t\n\f\r ]*([achlmqstvz])[\t\n\f\r ]*/i;
var coordinateEx = /^[+-]?((\d*\.\d+)|(\d+\.)|(\d+))(e[+-]?\d+)?/i;
var commaEx = /[\t\n\f\r ]*,?[\t\n\f\r ]*/;
var flagEx = /^[01]/;
var pathParams = {
  z: [],
  h: [coordinateEx],
  v: [coordinateEx],
  m: [coordinateEx, coordinateEx],
  l: [coordinateEx, coordinateEx],
  t: [coordinateEx, coordinateEx],
  s: [coordinateEx, coordinateEx, coordinateEx, coordinateEx],
  q: [coordinateEx, coordinateEx, coordinateEx, coordinateEx],
  c: [coordinateEx, coordinateEx, coordinateEx, coordinateEx, coordinateEx, coordinateEx],
  a: [coordinateEx, coordinateEx, coordinateEx, flagEx, flagEx, coordinateEx, coordinateEx]
};
function parseSvg(d) {
  if (!d)
    return;
  const segments = [];
  let i = 0;
  let currentCommand;
  while (i < d.length) {
    const commandMatch = commandEx.exec(d.slice(i));
    let command;
    if (commandMatch == null) {
      if (!currentCommand) {
        Logger7.warnOnce(`Invalid SVG path, error at index ${i}: Missing command.`);
        return;
      }
      command = currentCommand;
    } else {
      command = commandMatch[1];
      i += commandMatch[0].length;
    }
    const segment = parseSegment(command, d, i);
    if (!segment)
      return;
    i = segment[0];
    currentCommand = command;
    segments.push(segment[1]);
  }
  return segments;
}
function parseSegment(command, d, index) {
  const params = pathParams[command.toLocaleLowerCase()];
  const pathSeg = { command, params: [] };
  for (const regex of params) {
    const segment = d.slice(index);
    const match = regex.exec(segment);
    if (match != null) {
      pathSeg.params.push(parseFloat(match[0]));
      index += match[0].length;
      const next = commaEx.exec(segment.slice(match[0].length));
      if (next != null) {
        index += next[0].length;
      }
    } else if (pathSeg.params.length === 1) {
      return [index, pathSeg];
    } else {
      Logger7.warnOnce(
        `Invalid SVG path, error at index ${index}: No path segment parameters for command [${command}]`
      );
      return;
    }
  }
  return [index, pathSeg];
}

// packages/ag-charts-community/src/scene/polyRoots.ts
function linearRoot(a, b) {
  const t = -b / a;
  return a !== 0 && t >= 0 && t <= 1 ? [t] : [];
}
function quadraticRoots(a, b, c, delta3 = 1e-6) {
  if (Math.abs(a) < delta3) {
    return linearRoot(b, c);
  }
  const D = b * b - 4 * a * c;
  const roots = [];
  if (Math.abs(D) < delta3) {
    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, delta3 = 1e-6) {
  if (Math.abs(a) < delta3) {
    return quadraticRoots(b, c, d, delta3);
  }
  const A = b / a;
  const B = c / a;
  const C = d / a;
  const Q = (3 * B - A * A) / 9;
  const R = (9 * A * B - 27 * C - 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 (Math.abs(Im) < delta3) {
      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;
}

// packages/ag-charts-community/src/scene/intersection.ts
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 C = 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] + C;
  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:
    //                 |-1  3 -3  1| |P1|
    //   [t^3 t^2 t 1] | 3 -6  3  0| |P2|
    //                 |-3  3  0  0| |P3|
    //                 | 1  0  0  0| |P4|
    -P1 + 3 * P2 - 3 * P3 + P4,
    3 * P1 - 6 * P2 + 3 * P3,
    -3 * P1 + 3 * P2,
    P1
  ];
}

// packages/ag-charts-community/src/scene/util/bezier.ts
import { insertListItemsSorted } from "ag-charts-core";
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 splitBezier2D(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 = 2 * (p0 - 2 * p1 + p2);
  const c = -p0 + 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 bezier2DExtrema(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y) {
  const tx = calculateDerivativeExtrema(cp0x, cp1x, cp2x, cp3x);
  const ty = calculateDerivativeExtrema(cp0y, cp1y, cp2y, cp3y);
  return [...tx, ...ty];
}
function bezierCandidate(points, x, y) {
  const midX = evaluateBezier(points[0].x, points[1].x, points[2].x, points[3].x, 0.5);
  const midY = evaluateBezier(points[0].y, points[1].y, points[2].y, points[3].y, 0.5);
  const distance = Math.hypot(midX - x, midY - y);
  const minDistance = Math.min(
    Math.hypot(points[0].x - x, points[0].y - y),
    Math.hypot(points[1].x - x, points[1].y - y),
    Math.hypot(points[2].x - x, points[2].y - y),
    Math.hypot(points[3].x - x, points[3].y - y)
  );
  return { points, distance, minDistance };
}
function bezier2DDistance(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y, x, y, precision = 1) {
  const points0 = [
    { x: cp0x, y: cp0y },
    { x: cp1x, y: cp1y },
    { x: cp2x, y: cp2y },
    { x: cp3x, y: cp3y }
  ];
  let queue = {
    value: bezierCandidate(points0, x, y),
    next: null
  };
  let bestResult;
  while (queue != null) {
    const { points, distance, minDistance } = queue.value;
    queue = queue.next;
    if (bestResult == null || distance < bestResult.distance) {
      bestResult = { distance, minDistance };
    }
    if (bestResult != null && bestResult.distance - minDistance <= precision) {
      continue;
    }
    const [leftPoints, rightPoints] = splitBezier2D(
      points[0].x,
      points[0].y,
      points[1].x,
      points[1].y,
      points[2].x,
      points[2].y,
      points[3].x,
      points[3].y,
      0.5
    );
    const newCandidates = [bezierCandidate(leftPoints, x, y), bezierCandidate(rightPoints, x, y)].sort(
      bezierCandidateCmp
    );
    queue = insertListItemsSorted(queue, newCandidates, bezierCandidateCmp);
  }
  return bestResult?.distance ?? Infinity;
}
var bezierCandidateCmp = (a, b) => b.minDistance - a.minDistance;

// packages/ag-charts-community/src/scene/extendedPath2D.ts
var ExtendedPath2D = class {
  constructor() {
    // The methods of this class will likely be called many times per animation frame,
    // and any allocation can trigger a GC cycle during animation, so we attempt
    // to minimize the number of allocations.
    this.path2d = new Path2D();
    this.previousCommands = [];
    this.previousParams = [];
    this.previousClosedPath = false;
    this.commands = [];
    this.params = [];
    this.cx = NaN;
    this.cy = NaN;
    this.sx = NaN;
    this.sy = NaN;
    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.sx = x;
    this.sy = y;
    this.cx = x;
    this.cy = y;
    this.path2d.moveTo(x, y);
    this.commands.push(0 /* Move */);
    this.params.push(x, y);
  }
  lineTo(x, y) {
    if (this.openedPath) {
      this.cx = x;
      this.cy = y;
      this.path2d.lineTo(x, y);
      this.commands.push(1 /* Line */);
      this.params.push(x, y);
    } else {
      this.moveTo(x, y);
    }
  }
  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(2 /* Curve */);
    this.params.push(cx1, cy1, cx2, cy2, x, y);
  }
  closePath() {
    if (this.openedPath) {
      this.cx = this.sx;
      this.cy = this.sy;
      this.sx = NaN;
      this.sy = NaN;
      this.path2d.closePath();
      this.commands.push(3 /* ClosePath */);
      this.openedPath = false;
      this.closedPath = true;
    }
  }
  rect(x, y, width, height) {
    this.moveTo(x, y);
    this.lineTo(x + width, y);
    this.lineTo(x + width, y + height);
    this.lineTo(x, y + height);
    this.closePath();
  }
  roundRect(x, y, width, height, radii) {
    radii = Math.min(radii, width / 2, height / 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 + width - radii, y);
    this.arc(x + width - radii, y + radii, radii, 1.5 * Math.PI, 2 * Math.PI);
    this.lineTo(x + width, y + radii);
    this.lineTo(x + width, y + height - radii);
    this.arc(x + width - radii, y + height - radii, radii, 0, Math.PI / 2);
    this.lineTo(x + width - radii, y + height);
    this.lineTo(x + radii, y + height);
    this.arc(x + +radii, y + height - radii, radii, Math.PI / 2, Math.PI);
    this.lineTo(x, y + height - radii);
    this.closePath();
  }
  ellipse(cx, cy, rx, ry, rotation, sAngle, eAngle, counterClockwise = false) {
    const r = rx;
    const scaleY = ry / rx;
    const mxx = Math.cos(rotation);
    const myx = Math.sin(rotation);
    const mxy = -scaleY * myx;
    const myy = scaleY * mxx;
    const x0 = r * Math.cos(sAngle);
    const y0 = r * Math.sin(sAngle);
    const sx = cx + mxx * x0 + mxy * y0;
    const sy = cy + myx * x0 + myy * y0;
    const distanceSquared = (sx - this.cx) ** 2 + (sy - this.cy) ** 2;
    if (!this.openedPath) {
      this.moveTo(sx, sy);
    } else if (distanceSquared > 1e-6) {
      this.lineTo(sx, sy);
    }
    let sweep = counterClockwise ? -normalizeAngle360(sAngle - eAngle) : normalizeAngle360(eAngle - sAngle);
    if (Math.abs(Math.abs(eAngle - sAngle) - 2 * Math.PI) < 1e-6 && sweep < 2 * Math.PI) {
      sweep += 2 * Math.PI * (counterClockwise ? -1 : 1);
    }
    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);
    for (let i = 0; i < arcSections; i += 1) {
      const a0 = sAngle + step * (i + 0);
      const a1 = sAngle + 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);
      const cp1x = rCosStart - h * rSinStart;
      const cp1y = rSinStart + h * rCosStart;
      const cp2x = rCosEnd + h * rSinEnd;
      const cp2y = rSinEnd - h * rCosEnd;
      const cp3x = rCosEnd;
      const cp3y = rSinEnd;
      this.cubicCurveTo(
        cx + mxx * cp1x + mxy * cp1y,
        cy + myx * cp1x + myy * cp1y,
        cx + mxx * cp2x + mxy * cp2y,
        cy + myx * cp2x + myy * cp2y,
        cx + mxx * cp3x + mxy * cp3y,
        cy + myx * cp3x + myy * cp3y
      );
    }
  }
  arc(x, y, r, sAngle, eAngle, counterClockwise) {
    this.ellipse(x, y, r, r, 0, sAngle, eAngle, counterClockwise);
  }
  appendSvg(svg) {
    const parts = parseSvg(svg);
    if (parts == null)
      return false;
    let sx = 0;
    let sy = 0;
    let cx;
    let cy;
    let cpx = 0;
    let cpy = 0;
    for (const { command, params } of parts) {
      cx ?? (cx = params[0]);
      cy ?? (cy = params[1]);
      const relative = command === command.toLowerCase();
      const dx = relative ? cx : 0;
      const dy = relative ? cy : 0;
      switch (command.toLowerCase()) {
        case "m":
          this.moveTo(dx + params[0], dy + params[1]);
          cx = dx + params[0];
          cy = dy + params[1];
          sx = cx;
          sy = cy;
          break;
        case "c":
          this.cubicCurveTo(
            dx + params[0],
            dy + params[1],
            dx + params[2],
            dy + params[3],
            dx + params[4],
            dy + params[5]
          );
          cpx = dx + params[2];
          cpy = dy + params[3];
          cx = dx + params[4];
          cy = dy + params[5];
          break;
        case "s":
          this.cubicCurveTo(
            cx + cx - cpx,
            cy + cy - cpy,
            dx + params[0],
            dy + params[1],
            dx + params[2],
            dy + params[3]
          );
          cpx = dx + params[0];
          cpy = dy + params[1];
          cx = dx + params[2];
          cy = dy + params[3];
          break;
        case "q":
          this.cubicCurveTo(
            (dx + 2 * params[0]) / 3,
            (dy + 2 * params[1]) / 3,
            (2 * params[0] + params[2]) / 3,
            (2 * params[1] + params[3]) / 3,
            params[2],
            params[3]
          );
          cpx = params[0];
          cpy = params[1];
          cx = params[2];
          cy = params[3];
          break;
        case "t":
          this.cubicCurveTo(
            (cx + 2 * (cx + cx - cpx)) / 3,
            (cy + 2 * (cy + cy - cpy)) / 3,
            (2 * (cx + cx - cpx) + params[0]) / 3,
            (2 * (cy + cy - cpy) + params[1]) / 3,
            params[0],
            params[1]
          );
          cpx = cx + cx - cpx;
          cpy = cy + cy - cpy;
          cx = params[0];
          cy = params[1];
          break;
        case "a":
          this.svgEllipse(
            cx,
            cy,
            params[0],
            params[1],
            params[2] * Math.PI / 180,
            params[3],
            params[4],
            dx + params[5],
            dy + params[6]
          );
          cx = dx + params[5];
          cy = dy + params[6];
          break;
        case "h":
          this.lineTo(dx + params[0], cy);
          cx = dx + params[0];
          break;
        case "l":
          this.lineTo(dx + params[0], dy + params[1]);
          cx = dx + params[0];
          cy = dy + params[1];
          break;
        case "v":
          this.lineTo(cx, dy + params[0]);
          cy = dy + params[0];
          break;
        case "z":
          this.closePath();
          cx = sx;
          cy = sy;
          break;
        default:
          throw new Error(`Could not translate command '${command}' with '${params.join(" ")}'`);
      }
    }
    return true;
  }
  svgEllipse(x1, y1, rx, ry, rotation, fA, fS, x2, y2) {
    rx = Math.abs(rx);
    ry = Math.abs(ry);
    const dx = (x1 - x2) / 2;
    const dy = (y1 - y2) / 2;
    const sin = Math.sin(rotation);
    const cos = Math.cos(rotation);
    const rotX = cos * dx + sin * dy;
    const rotY = -sin * dx + cos * dy;
    const normX = rotX / rx;
    const normY = rotY / ry;
    let scale = normX * normX + normY * normY;
    let cx = (x1 + x2) / 2;
    let cy = (y1 + y2) / 2;
    let cpx = 0;
    let cpy = 0;
    if (scale >= 1) {
      scale = Math.sqrt(scale);
      rx *= scale;
      ry *= scale;
    } else {
      scale = Math.sqrt(1 / scale - 1);
      if (fA === fS)
        scale = -scale;
      cpx = scale * rx * normY;
      cpy = -scale * ry * normX;
      cx += cos * cpx - sin * cpy;
      cy += sin * cpx + cos * cpy;
    }
    const sAngle = Math.atan2((rotY - cpy) / ry, (rotX - cpx) / rx);
    const deltaTheta = Math.atan2((-rotY - cpy) / ry, (-rotX - cpx) / rx) - sAngle;
    const eAngle = sAngle + deltaTheta;
    const counterClockwise = !!(1 - fS);
    this.ellipse(cx, cy, rx, ry, rotation, sAngle, eAngle, counterClockwise);
  }
  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 /* Move */:
          intersectionCount += segmentIntersection(sx, sy, px, py, ox, oy, x, y);
          px = params[pi++];
          sx = px;
          py = params[pi++];
          sy = py;
          break;
        case 1 /* Line */:
          intersectionCount += segmentIntersection(px, py, params[pi++], params[pi++], ox, oy, x, y);
          px = params[pi - 2];
          py = params[pi - 1];
          break;
        case 2 /* Curve */:
          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 3 /* ClosePath */:
          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 cx = 0;
    let cy = 0;
    for (let ci = 0, pi = 0; ci < cn; ci++) {
      switch (commands[ci]) {
        case 0 /* Move */:
          cx = sx = params[pi++];
          cy = sy = params[pi++];
          break;
        case 1 /* Line */: {
          const x0 = cx;
          const y0 = cy;
          cx = params[pi++];
          cy = params[pi++];
          best = lineDistanceSquared(x, y, x0, y0, cx, cy, best);
          break;
        }
        case 2 /* Curve */:
          const cp0x = cx;
          const cp0y = cy;
          const cp1x = params[pi++];
          const cp1y = params[pi++];
          const cp2x = params[pi++];
          const cp2y = params[pi++];
          cx = params[pi++];
          cy = params[pi++];
          best = bezier2DDistance(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cx, cy, x, y) ** 2;
          break;
        case 3 /* ClosePath */:
          best = lineDistanceSquared(x, y, cx, cy, sx, sy, best);
          break;
      }
    }
    return best;
  }
  // 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, count) => {
      buffer.push(command);
      for (let i = 0; i < count; i += 2) {
        const { x, y } = transform(params[pi++], params[pi++]);
        buffer.push(x, y);
      }
    };
    let pi = 0;
    for (const command of commands) {
      switch (command) {
        case 0 /* Move */:
          addCommand("M", 2);
          break;
        case 1 /* Line */:
          addCommand("L", 2);
          break;
        case 2 /* Curve */:
          addCommand("C", 6);
          break;
        case 3 /* ClosePath */:
          addCommand("Z", 0);
          break;
      }
    }
    return buffer.join(" ");
  }
  computeBBox() {
    const { commands, params } = this;
    let [top, left, right, bot] = [Infinity, Infinity, -Infinity, -Infinity];
    let [cx, cy] = [NaN, NaN];
    let [sx, sy] = [NaN, NaN];
    const joinPoint = (x, y) => {
      top = Math.min(y, top);
      left = Math.min(x, left);
      right = Math.max(x, right);
      bot = Math.max(y, bot);
      cx = x;
      cy = y;
    };
    let pi = 0;
    for (const command of commands) {
      switch (command) {
        case 0 /* Move */:
          joinPoint(params[pi++], params[pi++]);
          sx = cx;
          sy = cy;
          break;
        case 1 /* Line */:
          joinPoint(params[pi++], params[pi++]);
          break;
        case 2 /* Curve */: {
          const cp0x = cx;
          const cp0y = cy;
          const cp1x = params[pi++];
          const cp1y = params[pi++];
          const cp2x = params[pi++];
          const cp2y = params[pi++];
          const cp3x = params[pi++];
          const cp3y = params[pi++];
          const ts = bezier2DExtrema(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y);
          ts.forEach((t) => {
            const px = evaluateBezier(cp0x, cp1x, cp2x, cp3x, t);
            const py = evaluateBezier(cp0y, cp1y, cp2y, cp3y, t);
            joinPoint(px, py);
          });
          joinPoint(cp3x, cp3y);
          break;
        }
        case 3 /* ClosePath */:
          joinPoint(sx, sy);
          sx = NaN;
          sy = NaN;
          break;
      }
    }
    return new BBox(left, top, right - left, bot - top);
  }
};

// packages/ag-charts-community/src/scene/util/pixel.ts
function align(pixelRatio, start, length) {
  const alignedStart = Math.round(start * pixelRatio) / pixelRatio;
  if (length == null) {
    return alignedStart;
  } else if (length === 0) {
    return 0;
  } else if (length < 1) {
    return Math.ceil(length * pixelRatio) / pixelRatio;
  }
  return Math.round((length + start) * pixelRatio) / pixelRatio - alignedStart;
}
function alignBefore(pixelRatio, start) {
  return Math.floor(start * pixelRatio) / pixelRatio;
}

// packages/ag-charts-community/src/scene/pattern/patterns.ts
function drawPatternUnitPolygon(path, params, moves) {
  const { width, height, padding, strokeWidth } = params;
  const x0 = width / 2;
  const y0 = height / 2;
  const w = Math.max(1, width - padding - strokeWidth / 2);
  const h = Math.max(1, height - padding - strokeWidth / 2);
  let didMove = false;
  for (const [dx, dy] of moves) {
    const x = x0 + (dx - 0.5) * w;
    const y = y0 + (dy - 0.5) * h;
    if (didMove) {
      path.lineTo(x, y);
    } else {
      path.moveTo(x, y);
    }
    didMove = true;
  }
  path.closePath();
}
var PATTERNS = {
  circles(path, { width, strokeWidth, padding }) {
    const c = width / 2;
    const r = Math.max(1, c - padding - strokeWidth / 2);
    path.arc(c, c, r, 0, Math.PI * 2);
  },
  squares(path, { width, height, pixelRatio, padding, strokeWidth }) {
    const offset = padding + strokeWidth / 2;
    path.moveTo(align(pixelRatio, offset), align(pixelRatio, offset));
    path.lineTo(align(pixelRatio, width - offset), align(pixelRatio, offset));
    path.lineTo(align(pixelRatio, width - offset), align(pixelRatio, height - offset));
    path.lineTo(align(pixelRatio, offset), align(pixelRatio, height - offset));
    path.closePath();
  },
  triangles(path, params) {
    drawPatternUnitPolygon(path, params, [
      [0.5, 0],
      [1, 1],
      [0, 1]
    ]);
  },
  diamonds(path, params) {
    drawPatternUnitPolygon(path, params, [
      [0.5, 0],
      [1, 0.5],
      [0.5, 1],
      [0, 0.5]
    ]);
  },
  stars(path, { width, height, padding }) {
    const spikes = 5;
    const outerRadius = Math.max(1, (width - padding) / 2);
    const innerRadius = outerRadius / 2;
    const rotation = Math.PI / 2;
    for (let i = 0; i < spikes * 2; i++) {
      const radius = i % 2 === 0 ? outerRadius : innerRadius;
      const angle = i * Math.PI / spikes - rotation;
      const xCoordinate = width / 2 + Math.cos(angle) * radius;
      const yCoordinate = height / 2 + Math.sin(angle) * radius;
      path.lineTo(xCoordinate, yCoordinate);
    }
    path.closePath();
  },
  hearts(path, { width, height, padding }) {
    const r = Math.max(1, width / 4 - padding / 2);
    const x = width / 2;
    const y = height / 2 + r / 2;
    path.arc(x - r, y - r, r, toRadians(130), toRadians(330));
    path.arc(x + r, y - r, r, toRadians(220), toRadians(50));
    path.lineTo(x, y + r);
    path.closePath();
  },
  crosses(path, params) {
    drawPatternUnitPolygon(path, params, [
      [0.25, 0],
      [0.5, 0.25],
      [0.75, 0],
      [1, 0.25],
      [0.75, 0.5],
      [1, 0.75],
      [0.75, 1],
      [0.5, 0.75],
      [0.25, 1],
      [0, 0.75],
      [0.25, 0.5],
      [0, 0.25]
    ]);
  },
  "vertical-lines"(path, { width, height, pixelRatio, strokeWidth }) {
    const x = align(pixelRatio, width / 2) - strokeWidth % 2 / 2;
    path.moveTo(x, 0);
    path.lineTo(x, height);
  },
  "horizontal-lines"(path, { width, height, pixelRatio, strokeWidth }) {
    const y = align(pixelRatio, height / 2) - strokeWidth % 2 / 2;
    path.moveTo(0, y);
    path.lineTo(width, y);
  },
  "forward-slanted-lines"(path, { width, height, strokeWidth }) {
    const angle = Math.atan2(height, width);
    const insetX = strokeWidth * Math.cos(angle);
    const insetY = strokeWidth * Math.sin(angle);
    path.moveTo(-insetX, insetY);
    path.lineTo(insetX, -insetY);
    path.moveTo(-insetX, height + insetY);
    path.lineTo(width + insetX, -insetY);
    path.moveTo(width - insetX, height + insetY);
    path.lineTo(width + insetX, height - insetY);
  },
  "backward-slanted-lines"(path, { width, height, strokeWidth }) {
    const angle = Math.atan2(height, width);
    const insetX = strokeWidth * Math.cos(angle);
    const insetY = strokeWidth * Math.sin(angle);
    path.moveTo(width - insetX, -insetY);
    path.lineTo(width + insetX, insetY);
    path.moveTo(-insetX, -insetY);
    path.lineTo(width + insetX, height + insetY);
    path.moveTo(-insetX, height - insetY);
    path.lineTo(insetX, height + insetY);
  }
};

// packages/ag-charts-community/src/scene/pattern/pattern.ts
var Pattern = class {
  constructor(patternOptions) {
    this._cache = void 0;
    this.width = Math.max(patternOptions?.width ?? 10, 1);
    this.height = Math.max(patternOptions?.height ?? 10, 1);
    this.fill = patternOptions.fill ?? "none";
    this.fillOpacity = patternOptions.fillOpacity ?? 1;
    this.backgroundFill = patternOptions.backgroundFill ?? "none";
    this.backgroundFillOpacity = patternOptions.backgroundFillOpacity ?? 1;
    this.stroke = patternOptions.stroke ?? "black";
    this.strokeOpacity = patternOptions.strokeOpacity ?? 1;
    this.strokeWidth = patternOptions.strokeWidth ?? 1;
    this.padding = patternOptions.padding ?? 1;
    this.pattern = patternOptions.pattern ?? "forward-slanted-lines";
    this.rotation = patternOptions.rotation ?? 0;
    this.scale = patternOptions.scale ?? 1;
    this.path = patternOptions.path;
  }
  getPath(pixelRatio) {
    const { pattern, width, height, padding, strokeWidth, path: svgPath } = this;
    const path = new ExtendedPath2D();
    let renderPattern = PATTERNS[pattern] != null;
    if (svgPath) {
      renderPattern && (renderPattern = !path.appendSvg(svgPath));
    }
    if (renderPattern) {
      PATTERNS[pattern](path, { width, height, pixelRatio, strokeWidth, padding });
    }
    return path;
  }
  renderStroke(path2d, ctx) {
    const { stroke, strokeWidth, strokeOpacity } = this;
    if (!strokeWidth)
      return;
    ctx.strokeStyle = stroke;
    ctx.lineWidth = strokeWidth;
    ctx.globalAlpha = strokeOpacity;
    ctx.stroke(path2d);
  }
  renderFill(path2d, ctx) {
    const { fill, fillOpacity } = this;
    if (fill === "none") {
      return;
    }
    ctx.fillStyle = fill;
    ctx.globalAlpha = fillOpacity;
    ctx.fill(path2d);
  }
  createCanvasPattern(ctx, pixelRatio) {
    const { width, height, scale, backgroundFill, backgroundFillOpacity } = this;
    if (width * scale < 1 || height * scale < 1) {
      Logger8.warnOnce("Pattern fill is too small to render, ignoring.");
      return null;
    }
    const offscreenPattern = new HdpiOffscreenCanvas({ width, height, pixelRatio: pixelRatio * scale });
    const offscreenPatternCtx = offscreenPattern.context;
    if (backgroundFill !== "none") {
      offscreenPatternCtx.fillStyle = backgroundFill;
      offscreenPatternCtx.globalAlpha = backgroundFillOpacity;
      offscreenPatternCtx.fillRect(0, 0, width, height);
    }
    const path2d = this.getPath(pixelRatio).getPath2D();
    this.renderFill(path2d, offscreenPatternCtx);
    this.renderStroke(path2d, offscreenPatternCtx);
    const pattern = ctx.createPattern(offscreenPattern.canvas, "repeat");
    this.setPatternTransform(pattern, pixelRatio);
    offscreenPattern.destroy();
    return pattern;
  }
  setPatternTransform(pattern, pixelRatio, tx = 0, ty = 0) {
    if (pattern == null)
      return;
    const angle = normalizeAngle360FromDegrees(this.rotation);
    const scale = 1 / pixelRatio;
    const cos = Math.cos(angle) * scale;
    const sin = Math.sin(angle) * scale;
    pattern.setTransform(new DOMMatrix([cos, sin, -sin, cos, tx, ty]));
  }
  createPattern(ctx, pixelRatio) {
    if (this._cache != null && this._cache.ctx === ctx && this._cache.pixelRatio === pixelRatio) {
      return this._cache.pattern;
    }
    const pattern = this.createCanvasPattern(ctx, pixelRatio);
    if (pattern == null)
      return;
    this._cache = { ctx, pattern, pixelRatio };
    return pattern;
  }
  toSvg() {
    const {
      width,
      height,
      fill,
      fillOpacity,
      backgroundFill,
      backgroundFillOpacity,
      stroke,
      strokeWidth,
      strokeOpacity,
      rotation,
      scale
    } = this;
    const pattern = createSvgElement7("pattern");
    pattern.setAttribute("viewBox", `0 0 ${width} ${height}`);
    pattern.setAttribute("width", String(width));
    pattern.setAttribute("height", String(height));
    pattern.setAttribute("patternUnits", "userSpaceOnUse");
    const rect = createSvgElement7("rect");
    rect.setAttribute("x", "0");
    rect.setAttribute("y", "0");
    rect.setAttribute("width", String(width));
    rect.setAttribute("height", String(height));
    rect.setAttribute("fill", backgroundFill);
    rect.setAttribute("fill-opacity", String(backgroundFillOpacity));
    pattern.appendChild(rect);
    const path = createSvgElement7("path");
    path.setAttribute("fill", fill);
    path.setAttribute("fill-opacity", String(fillOpacity));
    path.setAttribute("stroke-opacity", String(strokeOpacity));
    path.setAttribute("stroke", stroke);
    path.setAttribute("stroke-width", String(strokeWidth));
    path.setAttribute("transform", `rotate(${rotation}) scale(${scale})`);
    path.setAttribute("d", this.getPath(1).toSVG());
    pattern.appendChild(path);
    return pattern;
  }
};

// packages/ag-charts-community/src/scene/util/fill.ts
import { isArray as isArray3, isObject as isObject2 } from "ag-charts-core";
function isGradientFill(fill) {
  return isObject2(fill) && fill.type == "gradient";
}
function isPatternFill(fill) {
  return fill !== null && isObject2(fill) && fill.type == "pattern";
}
function isImageFill(fill) {
  return fill !== null && isObject2(fill) && fill.type == "image";
}

// packages/ag-charts-community/src/scene/shape/svgUtils.ts
function setSvgFontAttributes(element, options) {
  const { fontStyle, fontWeight, fontSize, fontFamily } = options;
  if (fontStyle)
    element.setAttribute("font-style", fontStyle);
  if (fontWeight)
    element.setAttribute("font-weight", String(fontWeight));
  if (fontSize != null)
    element.setAttribute("font-size", String(fontSize));
  if (fontFamily)
    element.setAttribute("font-family", fontFamily);
}
function setSvgStrokeAttributes(element, options) {
  const { stroke, strokeWidth, strokeOpacity } = options;
  if (stroke)
    element.setAttribute("stroke", stroke);
  if (strokeWidth != null)
    element.setAttribute("stroke-width", String(strokeWidth));
  if (strokeOpacity != null)
    element.setAttribute("stroke-opacity", String(strokeOpacity));
}
function setSvgLineDashAttributes(element, options) {
  const { lineDash, lineDashOffset } = options;
  if (lineDash?.some((d) => d !== 0)) {
    const lineDashArray = lineDash.length % 2 === 1 ? [...lineDash, ...lineDash] : lineDash;
    element.setAttribute("stroke-dasharray", lineDashArray.join(" "));
    if (lineDashOffset != null)
      element.setAttribute("stroke-dashoffset", String(lineDashOffset));
  }
}

// packages/ag-charts-community/src/scene/shape/shape.ts
var Shape = class extends Node {
  constructor() {
    super(...arguments);
    this.fillOpacity = 1;
    this.strokeOpacity = 1;
    this.fill = "black";
    this.strokeWidth = 0;
    this.lineDashOffset = 0;
    this.opacity = 1;
  }
  getGradient(fill) {
    if (isGradientFill(fill))
      return this.createGradient(fill);
  }
  createGradient(fill) {
    const { colorSpace = "rgb", gradient = "linear", colorStops, rotation = 0, reverse = false } = fill;
    if (colorStops == null)
      return;
    let stops = getColorStops(colorStops, ["black"], [0, 1]);
    if (reverse) {
      stops = stops.map((s) => ({ color: s.color, stop: 1 - s.stop })).reverse();
    }
    switch (gradient) {
      case "linear":
        return new LinearGradient(colorSpace, stops, rotation);
      case "radial":
        return new RadialGradient(colorSpace, stops);
      case "conic":
        return new ConicGradient(colorSpace, stops, rotation);
    }
  }
  getPattern(fill) {
    if (isPatternFill(fill))
      return this.createPattern(fill);
  }
  createPattern(fill) {
    return new Pattern(fill);
  }
  getImage(fill) {
    if (isImageFill(fill))
      return this.createImage(fill);
  }
  createImage(fill) {
    return new Image2(this.imageLoader, fill);
  }
  onFillChange() {
    if (typeof this.fill === "object") {
      if (objectsEqual(this._cachedFill ?? {}, this.fill)) {
        return;
      }
    }
    this.fillGradient = this.getGradient(this.fill);
    this.fillPattern = this.getPattern(this.fill);
    this.fillImage = this.getImage(this.fill);
    this._cachedFill = 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(start, length) {
    return align(this.layerManager?.canvas?.pixelRatio ?? 1, start, length);
  }
  markDirty(property) {
    super.markDirty(property);
    this.cachedDefaultGradientFillBBox = void 0;
  }
  fillStroke(ctx, path) {
    this.renderFill(ctx, path);
    this.renderStroke(ctx, path);
  }
  renderFill(ctx, path) {
    const { fill, fillOpacity, fillImage } = this;
    if (fill != null && fill !== "none" && fillOpacity > 0) {
      const { globalAlpha } = ctx;
      if (fillImage) {
        ctx.globalAlpha = fillImage.backgroundFillOpacity;
        ctx.fillStyle = fillImage.backgroundFill;
        this.executeFill(ctx, path);
        ctx.globalAlpha = globalAlpha;
      }
      this.applyFillAndAlpha(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();
    }
  }
  applyFillAndAlpha(ctx) {
    const { fill, fillGradient, fillPattern, fillImage, fillOpacity = 1, opacity = 1 } = this;
    ctx.globalAlpha *= opacity * fillOpacity;
    if (fillGradient) {
      const { fillBBox = this.getDefaultGradientFillBBox() ?? this.getBBox(), fillParams } = this;
      ctx.fillStyle = fillGradient.createGradient(ctx, fillBBox, fillParams) ?? "black";
    } else if (fillPattern) {
      const { x, y } = this.getBBox();
      const pixelRatio = this.layerManager?.canvas?.pixelRatio ?? 1;
      const pattern = fillPattern.createPattern(ctx, pixelRatio);
      fillPattern.setPatternTransform(pattern, pixelRatio, x, y);
      if (pattern) {
        ctx.fillStyle = pattern;
      } else {
        ctx.fillStyle = fillPattern.fill;
        ctx.globalAlpha *= fillPattern.fillOpacity;
      }
    } else if (fillImage) {
      const bbox = this.getBBox();
      const image = fillImage.createPattern(ctx, bbox.width, bbox.height, this);
      fillImage.setImageTransform(image, bbox);
      ctx.fillStyle = image ?? "transparent";
    } else {
      ctx.fillStyle = typeof fill === "string" ? fill : "black";
    }
  }
  applyStrokeAndAlpha(ctx) {
    const { stroke, strokeOpacity = 1, strokeGradient, opacity = 1 } = this;
    ctx.strokeStyle = strokeGradient?.createGradient(ctx, this.getBBox()) ?? (typeof stroke === "string" ? stroke : void 0) ?? "black";
    ctx.globalAlpha *= opacity * strokeOpacity;
  }
  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) {
    const { stroke, strokeWidth, strokeOpacity, lineDash, lineDashOffset, lineCap, lineJoin, miterLimit } = this;
    if (stroke != null && stroke !== "none" && strokeWidth > 0 && strokeOpacity > 0) {
      const { globalAlpha } = ctx;
      this.applyStrokeAndAlpha(ctx);
      ctx.lineWidth = strokeWidth;
      if (lineDash) {
        ctx.setLineDash(lineDash);
      }
      if (lineDashOffset) {
        ctx.lineDashOffset = lineDashOffset;
      }
      if (lineCap) {
        ctx.lineCap = lineCap;
      }
      if (lineJoin) {
        ctx.lineJoin = lineJoin;
      }
      if (miterLimit != null) {
        ctx.miterLimit = miterLimit;
      }
      this.executeStroke(ctx, path);
      ctx.globalAlpha = globalAlpha;
    }
  }
  executeStroke(ctx, path) {
    if (path) {
      ctx.stroke(path);
    } else {
      ctx.stroke();
    }
  }
  getDefaultGradientFillBBox() {
    this.cachedDefaultGradientFillBBox ?? (this.cachedDefaultGradientFillBBox = Object.freeze(this.computeDefaultGradientFillBBox()));
    return this.cachedDefaultGradientFillBBox;
  }
  computeDefaultGradientFillBBox() {
    return;
  }
  containsPoint(x, y) {
    return this.isPointInPath(x, y);
  }
  applySvgFillAttributes(element, defs) {
    const { fill, fillOpacity } = this;
    if (typeof fill === "string") {
      element.setAttribute("fill", fill);
    } else if (isGradientFill(fill) && this.fillGradient) {
      defs ?? (defs = []);
      const gradient = this.fillGradient.toSvg(this.fillBBox ?? this.getBBox());
      const id = generateUUID();
      gradient.setAttribute("id", id);
      defs.push(gradient);
      element.setAttribute("fill", `url(#${id})`);
    } else if (isPatternFill(fill) && this.fillPattern) {
      defs ?? (defs = []);
      const pattern = this.fillPattern.toSvg();
      const id = generateUUID();
      pattern.setAttribute("id", id);
      defs.push(pattern);
      element.setAttribute("fill", `url(#${id})`);
    } else if (isImageFill(fill) && this.fillImage) {
      defs ?? (defs = []);
      const pixelRatio = this.layerManager?.canvas?.pixelRatio ?? 1;
      const pattern = this.fillImage.toSvg(this.getBBox(), pixelRatio);
      const id = generateUUID();
      pattern.setAttribute("id", id);
      defs.push(pattern);
      element.setAttribute("fill", `url(#${id})`);
    } else {
      element.setAttribute("fill", "none");
    }
    element.setAttribute("fill-opacity", String(fillOpacity));
    return defs;
  }
  applySvgStrokeAttributes(element) {
    const { stroke, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = this;
    setSvgStrokeAttributes(element, { stroke: isString(stroke) ? stroke : void 0, strokeOpacity, strokeWidth });
    setSvgLineDashAttributes(element, { lineDash, lineDashOffset });
  }
};
__decorateClass([
  SceneChangeDetection()
], Shape.prototype, "fillOpacity", 2);
__decorateClass([
  SceneChangeDetection()
], Shape.prototype, "strokeOpacity", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: objectsEqual, changeCb: (s) => s.onFillChange() })
], Shape.prototype, "fill", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: objectsEqual, changeCb: (s) => s.onStrokeChange() })
], Shape.prototype, "stroke", 2);
__decorateClass([
  SceneChangeDetection()
], Shape.prototype, "strokeWidth", 2);
__decorateClass([
  SceneArrayChangeDetection()
], 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) => clamp4(0, v ?? 1, 1) })
], Shape.prototype, "opacity", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: TRIPLE_EQ, checkDirtyOnAssignment: true })
], Shape.prototype, "fillShadow", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: boxesEqual2, changeCb: (s) => s.onFillChange() })
], Shape.prototype, "fillBBox", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: objectsEqual, changeCb: (s) => s.onFillChange() })
], Shape.prototype, "fillParams", 2);

// packages/ag-charts-community/src/scene/transformable.ts
import { createSvgElement as createSvgElement8 } from "ag-charts-core";

// packages/ag-charts-community/src/scene/matrix.ts
import { isNumberEqual } from "ag-charts-core";
var IDENTITY_MATRIX_ELEMENTS = [1, 0, 0, 1, 0, 0];
var Matrix = class _Matrix {
  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 isNumberEqual(e[0], 1) && isNumberEqual(e[1], 0) && isNumberEqual(e[2], 0) && isNumberEqual(e[3], 1) && isNumberEqual(e[4], 0) && isNumberEqual(e[5], 0);
  }
  /**
   * Performs the AxB matrix multiplication and saves the result
   * to `C`, if given, or to `A` otherwise.
   */
  AxB(A, B, C) {
    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];
    C = C ?? A;
    C[0] = a;
    C[1] = b;
    C[2] = c;
    C[3] = d;
    C[4] = e;
    C[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 _Matrix) {
      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 _Matrix(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 _Matrix([d, -b, -c, a, c * f - d * e, b * e - a * f]);
  }
  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 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;
  }
};

// packages/ag-charts-community/src/scene/transformable.ts
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;
    }
    onChangeDetection(property) {
      super.onChangeDetection(property);
      this._dirtyTransform = true;
      if (this.batchLevel > 0) {
        return;
      }
      this.markDirty("transform");
    }
    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) {
      ({ x, y } = this.fromParentPoint(x, y));
      return super.pickNode(x, y);
    }
    pickNodes(x, y, into) {
      ({ x, y } = this.fromParentPoint(x, y));
      return super.pickNodes(x, y, into);
    }
    render(renderCtx) {
      this.computeTransformMatrix();
      const { ctx } = renderCtx;
      const matrix = this[TRANSFORM_MATRIX];
      let performRestore = false;
      try {
        if (!matrix.identity) {
          ctx.save();
          performRestore = true;
          matrix.toContext(ctx);
        }
        super.render(renderCtx);
      } finally {
        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 = createSvgElement8("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 = 0;
      this.rotationCenterY = 0;
      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()
  ], RotatableInternal.prototype, "rotationCenterX", 2);
  __decorateClass([
    SceneChangeDetection()
  ], RotatableInternal.prototype, "rotationCenterY", 2);
  __decorateClass([
    SceneChangeDetection()
  ], 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 = 0;
      this.scalingCenterY = 0;
    }
    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()
  ], ScalableInternal.prototype, "scalingX", 2);
  __decorateClass([
    SceneChangeDetection()
  ], ScalableInternal.prototype, "scalingY", 2);
  __decorateClass([
    SceneChangeDetection()
  ], ScalableInternal.prototype, "scalingCenterX", 2);
  __decorateClass([
    SceneChangeDetection()
  ], 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()
  ], TranslatableInternal.prototype, "translationX", 2);
  __decorateClass([
    SceneChangeDetection()
  ], 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 };
  }
};

// packages/ag-charts-community/src/scene/group.ts
var sharedOffscreenCanvas;
var _Group = class _Group extends Node {
  // optimizeForInfrequentRedraws: true
  constructor(opts) {
    super(opts);
    this.childNodes = /* @__PURE__ */ new Set();
    this.dirty = false;
    this.dirtyZIndex = false;
    this.clipRect = void 0;
    this.opacity = 1;
    this.renderToOffscreenCanvas = false;
    this.optimizeForInfrequentRedraws = false;
    // Used when renderToOffscreenCanvas: true
    this.layer = void 0;
    // optimizeForInfrequentRedraws: false
    this.image = void 0;
    this._lastWidth = NaN;
    this._lastHeight = NaN;
    this._lastDevicePixelRatio = NaN;
    this.isContainerNode = true;
    this.renderToOffscreenCanvas = opts?.renderToOffscreenCanvas === true;
  }
  static is(value) {
    return value instanceof _Group;
  }
  static computeChildrenBBox(nodes, skipInvisible = true) {
    return BBox.merge(Node.extractBBoxes(nodes, skipInvisible));
  }
  static compareChildren(a, b) {
    return compareZIndex(a.zIndex, b.zIndex) || a.serialNumber - b.serialNumber;
  }
  // We consider a group to be boundless, thus any point belongs to it.
  containsPoint(_x, _y) {
    return true;
  }
  computeBBox() {
    return _Group.computeChildrenBBox(this.children());
  }
  computeSafeClippingBBox(pixelRatio) {
    const bbox = this.computeBBox();
    if (bbox?.isFinite() !== true)
      return;
    let strokeWidth = 0;
    const strokeMiterAmount = 4;
    for (const child of this.descendants()) {
      if (child instanceof Shape) {
        strokeWidth = Math.max(strokeWidth, child.strokeWidth);
      }
    }
    const padding = Math.max(
      // Account for anti-aliasing artefacts
      1,
      // Account for strokes (incl. miters) - this may not be the best place to include this
      strokeWidth / 2 * strokeMiterAmount
    );
    const { x: originX, y: originY } = Transformable.toCanvasPoint(this, 0, 0);
    const x = alignBefore(pixelRatio, originX + bbox.x - padding) - originX;
    const y = alignBefore(pixelRatio, originY + bbox.y - padding) - originY;
    const width = Math.ceil(bbox.x + bbox.width - x + padding);
    const height = Math.ceil(bbox.y + bbox.height - y + padding);
    return new BBox(x, y, width, height);
  }
  prepareSharedCanvas(width, height, pixelRatio) {
    if (sharedOffscreenCanvas == null || sharedOffscreenCanvas.pixelRatio !== pixelRatio) {
      sharedOffscreenCanvas = new HdpiOffscreenCanvas({ width, height, pixelRatio });
    } else {
      sharedOffscreenCanvas.resize(width, height, pixelRatio);
    }
    return sharedOffscreenCanvas;
  }
  setScene(scene) {
    super.setScene(scene);
    if (this.layer) {
      this.scene?.layersManager.removeLayer(this.layer);
      this.layer = void 0;
    }
    for (const child of this.children()) {
      child.setScene(scene);
    }
  }
  markDirty(property) {
    this.dirty = true;
    super.markDirty(property);
  }
  markDirtyChildrenOrder() {
    super.markDirtyChildrenOrder();
    this.dirtyZIndex = true;
    this.markDirty();
  }
  /**
   * 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) {
    for (const node of toIterable(nodes)) {
      node.parentNode?.removeChild(node);
      this.childNodes.add(node);
      node.parentNode = this;
      node.setScene(this.scene);
    }
    this.markDirtyChildrenOrder();
    this.markDirty();
  }
  appendChild(node) {
    this.append(node);
    return node;
  }
  removeChild(node) {
    if (!this.childNodes?.delete(node)) {
      throw new Error(
        `AG Charts - internal error, unknown child node ${node.name ?? node.id} in $${this.name ?? this.id}`
      );
    }
    node.parentNode = void 0;
    node.setScene();
    this.markDirtyChildrenOrder();
    this.markDirty();
  }
  clear() {
    for (const child of this.children()) {
      delete child.parentNode;
      child.setScene();
    }
    this.childNodes?.clear();
    this.markDirty();
  }
  /**
   * 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) {
    if (!this.visible || this.pointerEvents === 1 /* None */ || !this.containsPoint(x, y)) {
      return;
    }
    if (this.childNodes != null && this.childNodes.size !== 0) {
      const children = [...this.children()];
      for (let i = children.length - 1; i >= 0; i--) {
        const child = children[i];
        const hit = child.pickNode(x, y);
        if (hit != null) {
          return hit;
        }
      }
    } else if (!this.isContainerNode) {
      return this;
    }
  }
  pickNodes(x, y, into = []) {
    if (!this.visible || this.pointerEvents === 1 /* None */ || !this.containsPoint(x, y)) {
      return into;
    }
    if (!this.isContainerNode) {
      into.push(this);
    }
    for (const child of this.children()) {
      child.pickNodes(x, y, into);
    }
    return into;
  }
  isDirty(renderCtx) {
    const { width, height, devicePixelRatio } = renderCtx;
    const { dirty, layer } = this;
    const layerResized = layer != null && (this._lastWidth !== width || this._lastHeight !== height);
    const pixelRatioChanged = this._lastDevicePixelRatio !== devicePixelRatio;
    this._lastWidth = width;
    this._lastHeight = height;
    this._lastDevicePixelRatio = devicePixelRatio;
    return dirty || layerResized || pixelRatioChanged;
  }
  preRender(renderCtx) {
    let counts;
    if (this.dirty) {
      counts = super.preRender(renderCtx, 0);
      for (const child of this.children()) {
        const childCounts = child.preRender(renderCtx);
        counts.groups += childCounts.groups;
        counts.nonGroups += childCounts.nonGroups;
        counts.complexity += childCounts.complexity;
      }
      counts.groups += 1;
      counts.nonGroups -= 1;
    } else {
      counts = this.childNodeCounts;
    }
    if (this.renderToOffscreenCanvas && !this.optimizeForInfrequentRedraws && 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, renderToOffscreenCanvas } = this;
    const childRenderCtx = { ...renderCtx };
    const dirty = this.isDirty(renderCtx);
    this.dirty = false;
    if (!renderToOffscreenCanvas) {
      this.renderInContext(childRenderCtx);
      super.render(childRenderCtx);
      return;
    }
    const { ctx, stats, devicePixelRatio: pixelRatio } = renderCtx;
    let { image } = this;
    if (dirty) {
      image?.bitmap.close();
      image = void 0;
      const bbox = layer ? void 0 : this.computeSafeClippingBBox(pixelRatio);
      const renderOffscreen = (offscreenCanvas, ...transform) => {
        const offscreenCtx = offscreenCanvas.context;
        childRenderCtx.ctx = offscreenCtx;
        offscreenCanvas.clear();
        offscreenCtx.save();
        try {
          offscreenCtx.setTransform(...transform);
          offscreenCtx.globalAlpha = 1;
          this.renderInContext(childRenderCtx);
        } finally {
          offscreenCtx.restore();
          offscreenCtx.verifyDepthZero?.();
        }
      };
      if (layer) {
        renderOffscreen(layer, ctx.getTransform());
      } else if (bbox) {
        const { x, y, width, height } = bbox;
        const canvas = this.prepareSharedCanvas(width, height, pixelRatio);
        renderOffscreen(canvas, pixelRatio, 0, 0, pixelRatio, -x * pixelRatio, -y * pixelRatio);
        image = { bitmap: canvas.transferToImageBitmap(), x, y, width, height };
      }
      this.image = image;
      if (stats)
        stats.layersRendered++;
    } else if (stats) {
      stats.layersSkipped++;
    }
    const { globalAlpha } = ctx;
    ctx.globalAlpha = globalAlpha * this.opacity;
    if (layer) {
      ctx.save();
      try {
        ctx.resetTransform();
        layer.drawImage(ctx);
      } finally {
        ctx.restore();
      }
    } else if (image) {
      const { bitmap, x, y, width, height } = image;
      ctx.drawImage(bitmap, 0, 0, width * pixelRatio, height * pixelRatio, x, y, width, height);
    }
    ctx.globalAlpha = globalAlpha;
    super.render(childRenderCtx);
  }
  applyClip(ctx, clipRect) {
    const { x, y, width, height } = clipRect;
    ctx.beginPath();
    ctx.rect(x, y, width, height);
    ctx.clip();
  }
  renderInContext(childRenderCtx) {
    const { ctx, stats } = childRenderCtx;
    if (this.dirtyZIndex) {
      this.sortChildren(_Group.compareChildren);
      this.dirtyZIndex = false;
    }
    ctx.save();
    try {
      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) {
          if (stats) {
            stats.nodesSkipped += child.childNodeCounts.nonGroups + child.childNodeCounts.groups;
            stats.opsSkipped += child.childNodeCounts.complexity;
          }
          continue;
        }
        child.isolatedRender(childRenderCtx);
      }
    } finally {
      ctx.restore();
    }
  }
  sortChildren(compareFn) {
    if (!this.childNodes)
      return;
    const sortedChildren = [...this.childNodes].sort(compareFn);
    this.childNodes.clear();
    for (const child of sortedChildren) {
      this.childNodes.add(child);
    }
  }
  *children() {
    yield* this.childNodes;
  }
  *excludeChildren(exclude) {
    for (const child of this.children()) {
      if (exclude.instance && !(child instanceof exclude.instance) || exclude.name && child.name !== exclude.name) {
        yield child;
      }
    }
  }
  *descendants() {
    for (const child of this.children()) {
      yield child;
      if (child instanceof _Group) {
        yield* child.descendants();
      }
    }
  }
  /**
   * 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;
  }
  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) => clamp5(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)) {
};

// packages/ag-charts-community/src/scene/sceneDebug.ts
import { Logger as Logger9, getWindow as getWindow2, isString as isString2, toArray as toArray2 } from "ag-charts-core";
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 */, "scene:stats:verbose" /* SCENE_STATS_VERBOSE */))
    return;
  const {
    layersRendered = 0,
    layersSkipped = 0,
    nodesRendered = 0,
    nodesSkipped = 0,
    opsPerformed = 0,
    opsSkipped = 0
  } = renderCtxStats ?? {};
  const end = performance.now();
  const { start, ...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", start, end)} (${splits})`,
    `${extras}`,
    `Layers: ${detailedStats ? pct(layersRendered, layersSkipped) : layersManager.size}`,
    detailedStats ? `Nodes: ${pct(nodesRendered, nodesSkipped)}` : null,
    detailedStats ? `Ops: ${pct(opsPerformed, opsSkipped)}` : null,
    detailedStats && memUsage ? memUsage : null
  ].filter(isString2);
  const measurer = new SimpleTextMeasurer((t) => ctx.measureText(t));
  const statsSize = new Map(stats.map((t) => [t, measurer.measureLines(t)]));
  const width = Math.max(...Array.from(statsSize.values(), (s) => s.width));
  const height = accumulate(statsSize.values(), (s) => s.height);
  const x = 2 + seriesRect.x;
  ctx.save();
  try {
    ctx.fillStyle = "white";
    ctx.fillRect(x, 0, width, height);
    ctx.fillStyle = "black";
    let y = 0;
    for (const [stat, size] of statsSize.entries()) {
      y += size.height;
      ctx.fillText(stat, x, y);
    }
  } catch (e) {
    Logger9.warnOnce("Error during debug stats rendering", e);
  } finally {
    ctx.restore();
  }
}
function prepareSceneNodeHighlight(ctx) {
  const config = toArray2(getWindow2("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();
  try {
    for (const [name, node] of Object.entries(debugNodes)) {
      const bbox = Transformable.toCanvas(node);
      if (!bbox) {
        Logger9.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);
    }
  } catch (e) {
    Logger9.warnOnce("Error during debug rendering", e);
  } finally {
    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 instanceof Group ? node.dirty : void 0,
    ...Array.from(node instanceof Group ? 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) {
  const nodeDirty = node instanceof Group ? node.dirty : void 0;
  if (!nodeDirty) {
    return { dirtyTree: {}, paths: [] };
  }
  const childrenDirtyTree = Array.from(node instanceof Group ? 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: nodeDirty,
      ...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, start, end) {
  const duration = end != null ? end - start : start;
  return `${name}: ${Math.round(duration * 100) / 100}ms`;
}
function accumulate(iterator, mapper) {
  let sum = 0;
  for (const item of iterator) {
    sum += mapper(item);
  }
  return sum;
}

// packages/ag-charts-community/src/scene/shape/rect.ts
import { boxesEqual as boxesEqual3 } from "ag-charts-core";

// packages/ag-charts-community/src/scene/util/corner.ts
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);
  }
};

// packages/ag-charts-community/src/scene/shape/path.ts
import { createSvgElement as createSvgElement9 } from "ag-charts-core";
var Path = class extends Shape {
  constructor() {
    super(...arguments);
    /**
     * Declare a path to retain for later rendering and hit testing
     * using custom Path2D class. Think of it as a TypeScript version
     * of the native Path2D (with some differences) that works in all browsers.
     */
    this.path = new ExtendedPath2D();
    this._clipX = NaN;
    this._clipY = NaN;
    this.clip = false;
    /**
     * The path only has to be updated when certain attributes change.
     * For example, if transform attributes (such as `translationX`)
     * are changed, we don't have to update the path. The `dirtyPath` flag
     * is how we keep track if the path has to be updated or not.
     */
    this._dirtyPath = true;
    this.lastPixelRatio = NaN;
  }
  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("path");
      }
    }
  }
  get dirtyPath() {
    return this._dirtyPath;
  }
  checkPathDirty() {
    if (this._dirtyPath) {
      return;
    }
    this.dirtyPath = this.path.isDirty() || (this.fillShadow?.isDirty() ?? false) || (this._clipPath?.isDirty() ?? false);
  }
  resetPathDirty() {
    this.path.clear(true);
    this._dirtyPath = false;
  }
  isPathDirty() {
    return this.path.isDirty();
  }
  onChangeDetection(property) {
    if (!this._dirtyPath) {
      this._dirtyPath = true;
      super.onChangeDetection(property);
    }
  }
  computeBBox() {
    this.updatePathIfDirty();
    return this.path.computeBBox();
  }
  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(renderCtx) {
    if (renderCtx.devicePixelRatio !== this.lastPixelRatio) {
      this.dirtyPath = true;
    }
    this.lastPixelRatio = renderCtx.devicePixelRatio;
    this.updatePathIfDirty();
    return super.preRender(renderCtx, this.path.commands.length);
  }
  render(renderCtx) {
    const { ctx } = renderCtx;
    if (this.clip && !isNaN(this._clipX) && !isNaN(this._clipY)) {
      ctx.save();
      try {
        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);
        }
      } finally {
        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 element = createSvgElement9("path");
    element.setAttribute("d", this.svgPathData());
    const defs = this.applySvgFillAttributes(element, []);
    this.applySvgStrokeAttributes(element);
    return {
      elements: [element],
      defs
    };
  }
};
Path.className = "Path";
__decorateClass([
  SceneChangeDetection()
], Path.prototype, "clip", 2);
__decorateClass([
  SceneChangeDetection()
], Path.prototype, "clipX", 1);
__decorateClass([
  SceneChangeDetection()
], Path.prototype, "clipY", 1);

// packages/ag-charts-community/src/scene/shape/rect.ts
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, width, height, 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, width, height);
    } 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, width, height, topLeftCornerRadius);
    return;
  }
  if (width < 0) {
    x += width;
    width = Math.abs(width);
  }
  if (height < 0) {
    y += height;
    height = Math.abs(height);
  }
  if (width <= 0 || height <= 0)
    return;
  if (clipBBox == null) {
    clipBBox = new BBox(x, y, width, height);
  } else {
    const x0 = Math.max(x, clipBBox.x);
    const x1 = Math.min(x + width, clipBBox.x + clipBBox.width);
    const y0 = Math.max(y, clipBBox.y);
    const y1 = Math.min(y + height, clipBBox.y + clipBBox.height);
    clipBBox = new BBox(x0, y0, x1 - x0, y1 - y0);
  }
  const borderScale = Math.max(maxVerticalCornerRadius / height, maxHorizontalCornerRadius / width, 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 + width - 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 + width - 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 + width - bottomRightCornerRadius), 0),
      Math.max(clipBBox.y + clipBBox.height - (y + height - 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 + width - bottomRightCornerRadius;
    const cy = y + height - bottomRightCornerRadius;
    bottomRightCorner = { x0, y0, x1, y1, cx, cy };
  }
  if (drawBottomLeftCorner) {
    const nodes = cornerEdges(
      clipBBox.width,
      clipBBox.height,
      Math.max(clipBBox.y + clipBBox.height - (y + height - 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 + height - 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 = this.strokeWidth;
    this.effectiveStrokeWidth = this.strokeWidth;
    this.hittester = super.isPointInPath.bind(this);
    this.distanceCalculator = super.distanceSquaredTransformedPoint.bind(this);
    /**
     * When the rectangle's width or height is less than a pixel
     * and crisp mode is on, the rectangle will still fit into the pixel,
     * but will be less opaque to make an effect of holding less space.
     */
    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 (w === 0 || h === 0) {
      this.effectiveStrokeWidth = 0;
      this.lastUpdatePathStrokeWidth = 0;
      this.microPixelEffectOpacity = 0;
      return;
    }
    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, height, clipBBox } = this;
    return clipBBox?.clone() ?? new BBox(x, y, width, height);
  }
  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);
  }
  applyFillAndAlpha(ctx) {
    super.applyFillAndAlpha(ctx);
    ctx.globalAlpha *= this.microPixelEffectOpacity;
  }
  applyStrokeAndAlpha(ctx) {
    super.applyStrokeAndAlpha(ctx);
    ctx.globalAlpha *= this.microPixelEffectOpacity;
  }
  renderStroke(ctx) {
    const { stroke, effectiveStrokeWidth } = this;
    if (stroke && effectiveStrokeWidth) {
      const { globalAlpha } = ctx;
      const { lineDash, lineDashOffset, lineCap, lineJoin, borderPath, borderClipPath } = this;
      if (borderClipPath) {
        ctx.clip(borderClipPath.getPath2D());
      }
      this.applyStrokeAndAlpha(ctx);
      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([
  SceneChangeDetection()
], Rect.prototype, "x", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "y", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "width", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "height", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "topLeftCornerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "topRightCornerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "bottomRightCornerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "bottomLeftCornerRadius", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: boxesEqual3 })
], Rect.prototype, "clipBBox", 2);
__decorateClass([
  SceneChangeDetection()
], Rect.prototype, "crisp", 2);

// packages/ag-charts-community/src/scene/shape/text.ts
var externUseGlyphIndependentMeasurements = false;
var _Text = class _Text extends Shape {
  constructor(options) {
    super(options);
    this.x = 0;
    this.y = 0;
    this.lines = [];
    this.text = void 0;
    this.fontSize = _Text.defaultFontSize;
    this.fontFamily = "sans-serif";
    this.textAlign = "start";
    this.textBaseline = "alphabetic";
    this.boxPadding = 0;
    this.trimText = options?.trimText ?? true;
  }
  onTextChange() {
    this.richText?.clear();
    this.textMap?.clear();
    if (isArray4(this.text)) {
      this.lines = [];
      this.richText ?? (this.richText = new Group());
      this.richText.setScene(this.scene);
      this.richText.append(this.text.map(() => new _Text({ trimText: false })));
    } else {
      const lines = this.text?.split("\n") ?? [];
      this.lines = this.trimText ? lines.map((line) => line.trim()) : lines;
    }
  }
  static computeBBox(lines, x, y, opts, useGlyphIndependentMeasurements = true) {
    const {
      font,
      font: { fontSize },
      textAlign,
      textBaseline,
      lineHeight = useGlyphIndependentMeasurements ? TextUtils.getLineHeight(fontSize) : void 0
    } = opts;
    const {
      width,
      alphabeticBaseline,
      offsetLeft: exactOffsetLeft,
      offsetTop: exactOffsetTop,
      height: exactHeight
    } = CachedTextMeasurerPool.measureLines(
      lines,
      useGlyphIndependentMeasurements ? { font, lineHeight, textAlign: "start", textBaseline: "top" } : opts
    );
    const height = lineHeight == null ? exactHeight : lineHeight * lines.length;
    let offsetTop;
    if (lineHeight == null) {
      offsetTop = exactOffsetTop;
    } else if (textBaseline === "alphabetic") {
      const padding = (lineHeight - fontSize) / 2;
      offsetTop = padding - alphabeticBaseline;
    } else {
      offsetTop = TextUtils.getVerticalModifier(textBaseline) * height;
    }
    const offsetLeft = useGlyphIndependentMeasurements ? width * TextUtils.getHorizontalModifier(textAlign) : exactOffsetLeft;
    return new BBox(x - offsetLeft, y - offsetTop, width, height);
  }
  computeBBox(useGlyphIndependentMeasurements = externUseGlyphIndependentMeasurements) {
    this.generateTextMap();
    if (this.textMap?.size) {
      const bbox = BBox.merge(this.textMap.values());
      bbox.x = this.x;
      bbox.y = this.y;
      return bbox;
    }
    const { x, y, lines, textBaseline, textAlign, lineHeight } = this;
    const measuredTextBounds = _Text.computeBBox(
      lines,
      x,
      y,
      { font: this, textBaseline, textAlign, lineHeight },
      useGlyphIndependentMeasurements
    );
    if (this.boxing != null)
      measuredTextBounds.grow(this.boxPadding);
    return measuredTextBounds;
  }
  getBBox(useGlyphIndependentMeasurements = true) {
    if (useGlyphIndependentMeasurements) {
      externUseGlyphIndependentMeasurements = true;
      const bbox = this.computeBBox(true);
      externUseGlyphIndependentMeasurements = false;
      return bbox;
    }
    return super.getBBox();
  }
  getPlainText() {
    return toPlainText(this.text);
  }
  getTextMeasureBBox() {
    return this.computeBBox();
  }
  isPointInPath(x, y) {
    return this.getBBox()?.containsPoint(x, y) ?? false;
  }
  setScene(scene) {
    this.richText?.setScene(scene);
    super.setScene(scene);
  }
  generateTextMap() {
    if (!isArray4(this.text) || this.textMap?.size)
      return;
    this.textMap ?? (this.textMap = /* @__PURE__ */ new Map());
    let index = 0;
    let totalWidth = 0;
    let offsetY = 0;
    const mainStyle = {
      fill: this.fill,
      fontSize: this.fontSize,
      fontFamily: this.fontFamily,
      fontStyle: this.fontStyle,
      fontWeight: this.fontWeight
    };
    for (const textNode of this.richText.children()) {
      const { color, ...textSegment } = this.text[index++];
      textNode.x = 0;
      textNode.y = 0;
      textNode.setProperties(mergeDefaults({ fill: color }, textSegment, mainStyle));
      const textBBox = textNode.getBBox();
      this.textMap.set(textNode, textBBox);
      offsetY = Math.max(
        offsetY,
        textBBox.y + textBBox.height / 2 + (textNode.lineHeight ?? TextUtils.getLineHeight(textNode.fontSize))
      );
      totalWidth += textBBox.x + textBBox.width;
    }
    let offsetX = this.x - totalWidth / 2;
    for (const [textNode, bbox] of this.textMap) {
      textNode.x += offsetX;
      textNode.y += offsetY;
      offsetX += bbox.width;
    }
  }
  render(renderCtx) {
    const { ctx, stats } = renderCtx;
    if (!this.text || !this.layerManager) {
      if (stats)
        stats.nodesSkipped += 1;
      return super.render(renderCtx);
    }
    if (isArray4(this.text)) {
      this.generateTextMap();
      const { width } = this.richText.getBBox();
      let translateX = 0;
      switch (this.textAlign) {
        case "left":
        case "start":
          translateX = width / 2;
          break;
        case "right":
        case "end":
          translateX = width / -2;
      }
      ctx.save();
      ctx.translate(translateX, this.y);
      this.richText.render(renderCtx);
      ctx.restore();
    } else {
      this.renderText(renderCtx);
    }
    if (_Text.debug.check() && !this.textMap?.size) {
      const bbox = this.getBBox(true);
      ctx.strokeStyle = "red";
      ctx.lineWidth = 1;
      ctx.strokeRect(bbox.x, bbox.y, bbox.width, bbox.height);
    }
    super.render(renderCtx);
  }
  markDirty(property) {
    this.textMap?.clear();
    return super.markDirty(property);
  }
  renderText(renderCtx) {
    const { fill, stroke, strokeWidth } = this;
    if (!fill && !(stroke && strokeWidth) || !this.layerManager) {
      return super.render(renderCtx);
    }
    const { ctx } = renderCtx;
    const font = TextUtils.toFontString(this);
    if (ctx.font !== font) {
      ctx.font = font;
    }
    const { fontSize, lineHeight = TextUtils.getLineHeight(fontSize), textAlign, textBaseline } = this;
    ctx.textAlign = textAlign;
    ctx.textBaseline = textBaseline;
    if (this.boxing) {
      const opts = { font: this, textBaseline, textAlign, lineHeight };
      const textBBox = _Text.computeBBox(this.lines, this.x, this.y, opts);
      if (textBBox.width !== 0 && textBBox.height !== 0) {
        const { x, y, width, height } = textBBox.grow(this.boxPadding);
        this.boxing.opacity = this.opacity;
        this.boxing.x = x;
        this.boxing.y = y;
        this.boxing.width = width;
        this.boxing.height = height;
        this.boxing.preRender(renderCtx);
        this.boxing.render(renderCtx);
      }
    }
    this.fillStroke(ctx);
  }
  executeFill(ctx) {
    const { fontSize, lineHeight = TextUtils.getLineHeight(fontSize), textBaseline, lines } = this;
    const lineOriginY = textBaseline === "alphabetic" ? 0 : TextUtils.getVerticalModifier(textBaseline) * lineHeight * (1 - lines.length);
    this.renderLines(lineOriginY, lineHeight, (line, x, y) => ctx.fillText(line, x, y));
  }
  executeStroke(ctx) {
    const { fontSize, lineHeight = TextUtils.getLineHeight(fontSize), textBaseline, lines } = this;
    const lineOriginY = textBaseline === "alphabetic" ? 0 : TextUtils.getVerticalModifier(textBaseline) * lineHeight * (1 - lines.length);
    this.renderLines(lineOriginY, lineHeight, (line, x, y) => ctx.strokeText(line, x, y));
  }
  renderLines(offsetY, lineHeight, renderCallback) {
    const { lines, x, y } = this;
    if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(offsetY) || !Number.isFinite(lineHeight)) {
      return;
    }
    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;
  }
  setBoxing(props) {
    const stroke = props.border?.enabled ? props.border?.stroke : void 0;
    if (props.fill != null || stroke != null) {
      this.boxing ?? (this.boxing = new Rect({ scene: this.scene }));
      this.boxing.fill = props.fill;
      this.boxing.fillOpacity = props.fillOpacity ?? 1;
      this.boxing.cornerRadius = props.cornerRadius ?? 0;
      this.boxing.stroke = stroke;
      this.boxing.strokeWidth = props.border?.strokeWidth ?? 0;
      this.boxing.strokeOpacity = props.border?.strokeOpacity ?? 1;
      this.boxPadding = props.padding ?? 0;
    } else if (this.boxing) {
      this.boxing.destroy();
      this.boxing = void 0;
    }
  }
  getBoxingProperties() {
    const { fill, fillOpacity, cornerRadius, stroke, strokeWidth, strokeOpacity } = this.boxing ?? {};
    return {
      border: { enabled: stroke != null, stroke, strokeWidth, strokeOpacity },
      cornerRadius,
      fill,
      fillOpacity,
      padding: this.boxPadding
    };
  }
  toSVG() {
    if (!this.visible || !this.text)
      return;
    const element = createSvgElement10("text");
    if (isString3(this.text)) {
      this.applySvgFillAttributes(element);
      setSvgFontAttributes(element, this);
      element.setAttribute(
        "text-anchor",
        {
          center: "middle",
          left: "start",
          right: "end",
          start: "start",
          end: "end"
        }[this.textAlign ?? "start"]
      );
      element.setAttribute("alignment-baseline", this.textBaseline);
      element.setAttribute("x", String(this.x));
      element.setAttribute("y", String(this.y));
      element.textContent = this.text;
    } else {
      for (const segment of this.text) {
        const segmentElement = createSvgElement10("tspan");
        setSvgFontAttributes(segmentElement, {
          fontSize: segment.fontSize ?? this.fontSize,
          fontFamily: segment.fontFamily ?? this.fontFamily,
          fontWeight: segment.fontWeight ?? this.fontWeight,
          fontStyle: segment.fontStyle ?? this.fontStyle
        });
        this.applySvgFillAttributes(segmentElement);
        segmentElement.textContent = segment.text;
        element.append(segmentElement);
      }
    }
    return { elements: [element] };
  }
};
_Text.className = "Text";
_Text.debug = Debug.create(true, "scene:text" /* SCENE_TEXT */);
_Text.defaultFontSize = 10;
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "x", 2);
__decorateClass([
  SceneChangeDetection()
], _Text.prototype, "y", 2);
__decorateClass([
  SceneRefChangeDetection({
    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)) {
};

// packages/ag-charts-community/src/util/proxy.ts
import { isArray as isArray5 } from "ag-charts-core";
function ProxyPropertyOnWrite(childName, childProperty) {
  return addTransformToInstanceProperty((target, key, value) => target[childName][childProperty ?? key] = value);
}
function ObserveChanges(observerFn) {
  return addObserverToInstanceProperty(observerFn);
}

// packages/ag-charts-community/src/util/textWrapper.ts
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;
      }
      let i = 0;
      let estimatedWidth = 0;
      let lastSpaceIndex = 0;
      while (i < line.length) {
        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;
            i++;
            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 = 0;
              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;
        }
        i++;
      }
      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, lineMetrics } = measurer.measureLines(lines);
    if (height <= 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 } = lines;
    const lastLine = lines[length - 1];
    const beforeLast = lines[length - 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[length - 2] = beforeLast.slice(0, lastSpaceIndex);
      lines[length - 1] = lastWord + " " + lastLine;
    }
  }
};

// packages/ag-charts-community/src/chart/caption.ts
var Caption = class extends BaseProperties {
  constructor() {
    super(...arguments);
    this.id = createId2(this);
    this.node = new RotatableText({ zIndex: 1 }).setProperties({
      textAlign: "center",
      pointerEvents: 1 /* None */
    });
    this.enabled = false;
    this.textAlign = "center";
    this.fontSize = 10 /* SMALLER */;
    this.fontFamily = "sans-serif";
    this.wrapping = "always";
    this.padding = 0;
    this.layoutStyle = "block";
    this.truncated = false;
  }
  registerInteraction(moduleCtx, where) {
    return moduleCtx.eventsHub.on("layout:complete", () => this.updateA11yText(moduleCtx, where));
  }
  computeTextWrap(containerWidth, containerHeight) {
    const { text, padding, wrapping } = this;
    if (isArray6(text))
      return;
    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 = toPlainText2(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.truncated) {
      const { x, y } = Transformable.toCanvas(this.node);
      const canvasX = event.sourceEvent.offsetX + x;
      const canvasY = event.sourceEvent.offsetY + y;
      moduleCtx.tooltipManager.updateTooltip(this.id, { canvasX, canvasY, showArrow: false }, [
        { type: "structured", title: toPlainText2(this.text) }
      ]);
    }
  }
  handleMouseLeave(moduleCtx, _event) {
    moduleCtx.tooltipManager.removeTooltip(this.id);
  }
};
Caption.SMALL_PADDING = 10;
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node", "visible")
], Caption.prototype, "enabled", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node")
], Caption.prototype, "text", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node")
], Caption.prototype, "textAlign", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontStyle", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontWeight", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontSize", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node")
], Caption.prototype, "fontFamily", 2);
__decorateClass([
  Property,
  ProxyPropertyOnWrite("node", "fill")
], Caption.prototype, "color", 2);
__decorateClass([
  Property
], Caption.prototype, "spacing", 2);
__decorateClass([
  Property
], Caption.prototype, "maxWidth", 2);
__decorateClass([
  Property
], Caption.prototype, "maxHeight", 2);
__decorateClass([
  Property
], Caption.prototype, "wrapping", 2);
__decorateClass([
  Property
], Caption.prototype, "padding", 2);
__decorateClass([
  Property
], Caption.prototype, "layoutStyle", 2);

// packages/ag-charts-community/src/chart/marker/shapes.ts
function drawMarkerUnitPolygon(params, moves) {
  const { path, size } = params;
  const { x: x0, y: y0 } = params;
  path.clear();
  let didMove = false;
  for (const [dx, dy] of moves) {
    const x = x0 + (dx - 0.5) * size;
    const y = y0 + (dy - 0.5) * size;
    if (didMove) {
      path.lineTo(x, y);
    } else {
      path.moveTo(x, y);
    }
    didMove = true;
  }
  path.closePath();
}
var MARKER_SHAPES = {
  circle({ path, x, y, size }) {
    const r = size / 2;
    path.arc(x, y, r, 0, Math.PI * 2);
    path.closePath();
  },
  cross(params) {
    drawMarkerUnitPolygon(params, [
      [0.25, 0],
      [0.5, 0.25],
      [0.75, 0],
      [1, 0.25],
      [0.75, 0.5],
      [1, 0.75],
      [0.75, 1],
      [0.5, 0.75],
      [0.25, 1],
      [0, 0.75],
      [0.25, 0.5],
      [0, 0.25]
    ]);
  },
  diamond(params) {
    drawMarkerUnitPolygon(params, [
      [0.5, 0],
      [1, 0.5],
      [0.5, 1],
      [0, 0.5]
    ]);
  },
  heart({ path, x, y, size }) {
    const r = size / 4;
    y = y + r / 2;
    path.arc(x - r, y - r, r, toRadians(130), toRadians(330));
    path.arc(x + r, y - r, r, toRadians(220), toRadians(50));
    path.lineTo(x, y + r);
    path.closePath();
  },
  pin({ path, x, y, size: s }) {
    const cx = 0.5;
    const cy = 0.5;
    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();
  },
  plus(params) {
    drawMarkerUnitPolygon(params, [
      [1 / 3, 0],
      [2 / 3, 0],
      [2 / 3, 1 / 3],
      [1, 1 / 3],
      [1, 2 / 3],
      [2 / 3, 2 / 3],
      [2 / 3, 1],
      [1 / 3, 1],
      [1 / 3, 2 / 3],
      [0, 2 / 3],
      [0, 1 / 3],
      [1 / 3, 1 / 3]
    ]);
  },
  square({ path, x, y, size, pixelRatio }) {
    const hs = size / 2;
    path.moveTo(align(pixelRatio, x - hs), align(pixelRatio, y - hs));
    path.lineTo(align(pixelRatio, x + hs), align(pixelRatio, y - hs));
    path.lineTo(align(pixelRatio, x + hs), align(pixelRatio, y + hs));
    path.lineTo(align(pixelRatio, x - hs), align(pixelRatio, y + hs));
    path.closePath();
  },
  star({ path, x, y, size }) {
    const spikes = 5;
    const outerRadius = size / 2;
    const innerRadius = outerRadius / 2;
    const rotation = Math.PI / 2;
    for (let i = 0; i < spikes * 2; i++) {
      const radius = i % 2 === 0 ? outerRadius : innerRadius;
      const angle = i * Math.PI / spikes - rotation;
      const xCoordinate = x + Math.cos(angle) * radius;
      const yCoordinate = y + Math.sin(angle) * radius;
      path.lineTo(xCoordinate, yCoordinate);
    }
    path.closePath();
  },
  triangle(params) {
    drawMarkerUnitPolygon(params, [
      [0.5, 0],
      [1, 0.87],
      [0, 0.87]
    ]);
  }
};

// packages/ag-charts-community/src/chart/marker/marker.ts
var InternalMarker = class extends Path {
  constructor() {
    super(...arguments);
    this.shape = "square";
    this.x = 0;
    this.y = 0;
    this.size = 12;
  }
  isPointInPath(x, y) {
    return this.distanceSquared(x, y) <= 0;
  }
  distanceSquared(x, y) {
    const anchor = Marker.anchor(this.shape);
    return Math.max(
      Math.hypot(x - this.x + (anchor.x - 0.5) * this.size, y - this.y + (anchor.y - 0.5) * this.size) - this.size / 2,
      0
    );
  }
  updatePath() {
    const { path, shape, x, y, size } = this;
    const pixelRatio = this.layerManager?.canvas?.pixelRatio ?? 1;
    const anchor = Marker.anchor(shape);
    const drawParams = {
      path,
      x: x - (anchor.x - 0.5) * size,
      y: y - (anchor.y - 0.5) * size,
      size,
      pixelRatio
    };
    path.clear();
    if (typeof shape === "string") {
      MARKER_SHAPES[shape](drawParams);
    } else if (typeof shape === "function") {
      shape(drawParams);
    }
  }
  computeBBox() {
    const { x, y, size } = this;
    const anchor = Marker.anchor(this.shape);
    return new BBox(x - size * anchor.x, y - size * anchor.y, size, size);
  }
  executeFill(ctx, path) {
    if (!path)
      return;
    return super.executeFill(ctx, path);
  }
  executeStroke(ctx, path) {
    if (!path)
      return;
    return super.executeStroke(ctx, path);
  }
};
__decorateClass([
  SceneObjectChangeDetection({ equals: TRIPLE_EQ })
], InternalMarker.prototype, "shape", 2);
__decorateClass([
  SceneChangeDetection()
], InternalMarker.prototype, "x", 2);
__decorateClass([
  SceneChangeDetection()
], InternalMarker.prototype, "y", 2);
__decorateClass([
  SceneChangeDetection({ convertor: Math.abs })
], InternalMarker.prototype, "size", 2);
var Marker = class extends Rotatable(Scalable(Translatable(InternalMarker))) {
  static anchor(shape) {
    if (shape === "pin") {
      return { x: 0.5, y: 1 };
    } else if (typeof shape === "function" && "anchor" in shape) {
      return shape.anchor;
    }
    return { x: 0.5, y: 0.5 };
  }
  constructor(options) {
    super(options);
    if (options?.shape != null) {
      this.shape = options.shape;
    }
  }
};

// packages/ag-charts-community/src/scale/categoryScale.ts
import { clamp as clamp9 } from "ag-charts-core";

// packages/ag-charts-community/src/util/number.ts
import { clamp as clamp6 } from "ag-charts-core";
function findMinMax(array) {
  if (array.length === 0)
    return [];
  const result = [Infinity, -Infinity];
  for (const val of array) {
    if (val < result[0])
      result[0] = val;
    if (val > result[1])
      result[1] = val;
  }
  return result;
}
function previousPowerOf2(value) {
  value = value | 0;
  if (value <= 0)
    return 0;
  if (value === 1)
    return 1;
  return 1 << 31 - Math.clz32(value);
}

// packages/ag-charts-community/src/util/time/duration.ts
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;

// packages/ag-charts-community/src/util/time/encoding.ts
var tzOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset() * durationMinute;
var unitEncoding = {
  millisecond: {
    milliseconds: 1,
    hierarchy: "day",
    encode(date) {
      return date.getTime();
    },
    decode(encoded) {
      return new Date(encoded);
    }
  },
  second: {
    milliseconds: durationSecond,
    hierarchy: "day",
    encode(date, utc) {
      const offset = utc ? 0 : tzOffset;
      return Math.floor((date.getTime() - offset) / durationSecond);
    },
    decode(encoded, utc) {
      const offset = utc ? 0 : tzOffset;
      return new Date(offset + encoded * durationSecond);
    }
  },
  minute: {
    milliseconds: durationMinute,
    hierarchy: "day",
    encode(date, utc) {
      const offset = utc ? 0 : tzOffset;
      return Math.floor((date.getTime() - offset) / durationMinute);
    },
    decode(encoded, utc) {
      const offset = utc ? 0 : tzOffset;
      return new Date(offset + encoded * durationMinute);
    }
  },
  hour: {
    milliseconds: durationHour,
    hierarchy: "day",
    encode(date, utc) {
      const offset = utc ? 0 : tzOffset;
      return Math.floor((date.getTime() - offset) / durationHour);
    },
    decode(encoded, utc) {
      const offset = utc ? 0 : tzOffset;
      return new Date(offset + encoded * durationHour);
    }
  },
  day: {
    milliseconds: durationDay,
    hierarchy: "month",
    encode(date, utc) {
      const tzOffsetMs = utc ? 0 : date.getTimezoneOffset() * durationMinute;
      return Math.floor((date.getTime() - tzOffsetMs) / durationDay);
    },
    decode(encoded, utc) {
      let d;
      if (utc) {
        d = /* @__PURE__ */ new Date(0);
        d.setUTCDate(d.getUTCDate() + encoded);
        d.setUTCHours(0, 0, 0, 0);
      } else {
        d = new Date(1970, 0, 1);
        d.setDate(d.getDate() + encoded);
      }
      return d;
    }
  },
  month: {
    milliseconds: durationMonth,
    hierarchy: "year",
    encode(date, utc) {
      if (utc) {
        return date.getUTCFullYear() * 12 + date.getUTCMonth();
      } else {
        return date.getFullYear() * 12 + date.getMonth();
      }
    },
    decode(encoded, utc) {
      if (utc) {
        const year = Math.floor(encoded / 12);
        const m = encoded - year * 12;
        return new Date(Date.UTC(year, m, 1));
      } else {
        const y = Math.floor(encoded / 12);
        const month = encoded - y * 12;
        return new Date(y, month, 1);
      }
    }
  },
  year: {
    milliseconds: durationYear,
    hierarchy: void 0,
    encode(date, utc) {
      if (utc) {
        return date.getUTCFullYear();
      } else {
        return date.getFullYear();
      }
    },
    decode(encoded, utc) {
      let d;
      if (utc) {
        d = /* @__PURE__ */ new Date();
        d.setUTCFullYear(encoded);
        d.setUTCMonth(0, 1);
        d.setUTCHours(0, 0, 0, 0);
      } else {
        d = new Date(encoded, 0, 1, 0, 0, 0, 0);
      }
      return d;
    }
  }
};

// packages/ag-charts-community/src/util/time/index.ts
function intervalUnit(interval) {
  return typeof interval === "string" ? interval : interval.unit;
}
function intervalStep(interval) {
  return typeof interval === "string" ? 1 : interval.step ?? 1;
}
function intervalMilliseconds(interval) {
  const step = intervalStep(interval);
  return step * unitEncoding[intervalUnit(interval)].milliseconds;
}

// packages/ag-charts-community/src/util/timeFormatDefaults.ts
function dateToNumber(value) {
  return value instanceof Date ? value.getTime() : value;
}

// packages/ag-charts-community/src/scale/bandScale.ts
import { Logger as Logger10, clamp as clamp7 } from "ag-charts-core";
var _BandScale = class _BandScale extends AbstractScale {
  constructor() {
    super(...arguments);
    this.invalid = true;
    this.range = [0, 1];
    this.round = false;
    this._bandwidth = 1;
    this._step = 1;
    this._inset = 1;
    this._rawBandwidth = 1;
    /**
     * The ratio of the range that is reserved for space between bands.
     */
    this._paddingInner = 0;
    /**
     * The ratio of the range that is reserved for space before the first
     * and after the last band.
     */
    this._paddingOuter = 0;
  }
  static is(value) {
    return value instanceof _BandScale;
  }
  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 = clamp7(0, value, 1);
    this._paddingInner = value;
    this._paddingOuter = value;
  }
  get padding() {
    return this._paddingInner;
  }
  set paddingInner(value) {
    this.invalid = true;
    this._paddingInner = clamp7(0, value, 1);
  }
  get paddingInner() {
    return this._paddingInner;
  }
  set paddingOuter(value) {
    this.invalid = true;
    this._paddingOuter = clamp7(0, value, 1);
  }
  get paddingOuter() {
    return this._paddingOuter;
  }
  refresh() {
    if (!this.invalid)
      return;
    this.invalid = false;
    this.update();
    if (this.invalid) {
      Logger10.warnOnce("Expected update to not invalidate scale");
    }
  }
  convert(d, options) {
    this.refresh();
    const i = this.findIndex(d, options?.alignment);
    if (i == null || i < 0 || i >= this.bands.length) {
      return NaN;
    }
    return this.ordinalRange(i);
  }
  invertNearestIndex(position) {
    this.refresh();
    const bandCount = this.bands.length;
    if (bandCount === 0)
      return -1;
    let low = 0;
    let high = bandCount - 1;
    let closestDistance = Infinity;
    let closestIndex = 0;
    while (low <= high) {
      const mid = (high + low) / 2 | 0;
      const p = this.ordinalRange(mid);
      const distance = Math.abs(p - position);
      if (distance === 0)
        return mid;
      if (distance < closestDistance) {
        closestDistance = distance;
        closestIndex = mid;
      }
      if (p < position) {
        low = mid + 1;
      } else {
        high = mid - 1;
      }
    }
    return closestIndex;
  }
  update() {
    const [r0, r1] = this.range;
    let { _paddingInner: paddingInner } = this;
    const { _paddingOuter: paddingOuter, round, bands } = this;
    const bandCount = bands.length;
    if (bandCount === 0)
      return;
    const rangeDistance = r1 - r0;
    let rawStep;
    if (bandCount === 1) {
      paddingInner = 0;
      rawStep = rangeDistance * (1 - paddingOuter * 2);
    } else {
      rawStep = rangeDistance / Math.max(1, bandCount - paddingInner + paddingOuter * 2);
    }
    const step = round ? Math.floor(rawStep) : rawStep;
    let inset = r0 + (rangeDistance - step * (bandCount - paddingInner)) / 2;
    let bandwidth = step * (1 - paddingInner);
    if (round) {
      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, range: range2 } = this;
    const min = Math.min(range2[0], range2[1]);
    const max = Math.max(range2[0], range2[1]);
    return clamp7(min, inset + step * i, max);
  }
};
__decorateClass([
  Invalidating
], _BandScale.prototype, "range", 2);
__decorateClass([
  Invalidating
], _BandScale.prototype, "round", 2);
var BandScale = _BandScale;

// packages/ag-charts-community/src/scale/scaleUtil.ts
import { clamp as clamp8 } from "ag-charts-core";
function filterVisibleTicks(ticks, reversed, visibleRange) {
  if (visibleRange == null || visibleRange[0] === 0 && visibleRange[1] === 1) {
    return { ticks, count: ticks.length, firstTickIndex: 0 };
  }
  const vt0 = clamp8(0, Math.floor(visibleRange[0] * ticks.length), ticks.length);
  const vt1 = clamp8(0, Math.ceil(visibleRange[1] * ticks.length), ticks.length);
  const t0 = reversed ? ticks.length - vt1 : vt0;
  const t1 = reversed ? ticks.length - vt0 : vt1;
  return {
    ticks: ticks.slice(t0, t1),
    count: ticks.length,
    firstTickIndex: t0
  };
}

// packages/ag-charts-community/src/scale/categoryScale.ts
var CategoryScale = class _CategoryScale extends BandScale {
  constructor() {
    super(...arguments);
    this.type = "category";
    this.defaultTickCount = 0;
    /**
     * Maps datum to its index in the {@link domain} array.
     * Used to check for duplicate data (not allowed).
     */
    this.index = /* @__PURE__ */ new Map();
    this.indexInitialized = false;
    /**
     * Contains unique data only.
     */
    this._domain = [];
  }
  static is(value) {
    return value instanceof _CategoryScale;
  }
  set domain(values) {
    if (this._domain === values)
      return;
    this.invalid = true;
    this._domain = values;
    this.index.clear();
    this.indexInitialized = false;
  }
  get domain() {
    return this._domain;
  }
  get bands() {
    return this._domain;
  }
  normalizeDomains(...domains) {
    let normalizedDomain = void 0;
    const seenDomains = /* @__PURE__ */ new Set();
    let animatable = true;
    for (const domain of domains) {
      if (seenDomains.has(domain))
        continue;
      seenDomains.add(domain);
      if (normalizedDomain == null) {
        normalizedDomain = deduplicateCategories(domain);
      } else {
        animatable && (animatable = domainOrderedToNormalizedDomain(domain, normalizedDomain));
        normalizedDomain = deduplicateCategories([...normalizedDomain, ...domain]);
      }
    }
    normalizedDomain ?? (normalizedDomain = []);
    return { domain: normalizedDomain, animatable };
  }
  toDomain(_value) {
    return void 0;
  }
  invert(position, nearest = false) {
    this.refresh();
    const offset = nearest ? this.bandwidth / 2 : 0;
    const index = this.invertNearestIndex(Math.max(0, position - offset));
    const matches = nearest || position === this.ordinalRange(index);
    return matches ? this.domain[index] : void 0;
  }
  ticks(params, domain = this.domain, visibleRange) {
    const { bands } = this;
    let { tickCount } = params;
    if (tickCount === 0) {
      const firstTickIndex2 = bands.length > 1 ? 1 : 0;
      return { ticks: [bands[firstTickIndex2]], count: void 0, firstTickIndex: firstTickIndex2 };
    }
    let step = tickCount != null && tickCount !== 0 ? bands.length / tickCount | 0 : 1;
    step = previousPowerOf2(step);
    if (step <= 1) {
      return filterVisibleTicks(domain, false, visibleRange);
    }
    tickCount = bands.length / step | 0;
    const span = step * tickCount;
    const inset = previousPowerOf2((bands.length - span) / 2 | 0);
    const vt0 = clamp9(0, Math.floor((visibleRange?.[0] ?? 0) * bands.length), bands.length);
    const vt1 = clamp9(0, Math.ceil((visibleRange?.[1] ?? 1) * bands.length), bands.length);
    const i0 = Math.floor((vt0 - inset) / step) * step + inset;
    const i1 = Math.ceil((vt1 - inset) / step) * step + inset;
    const ticks = [];
    for (let i = i0; i < i1; i += step) {
      if (i >= 0 && i < bands.length) {
        ticks.push(bands[i]);
      }
    }
    let firstTickIndex = ticks.length > 0 ? this.findIndex(ticks[0]) : void 0;
    if (firstTickIndex != null) {
      firstTickIndex = Math.floor((firstTickIndex - inset) / step);
    }
    return { ticks, count: void 0, firstTickIndex };
  }
  findIndex(value) {
    const { index, indexInitialized } = this;
    if (!indexInitialized) {
      const { domain } = this;
      for (let i = 0; i < domain.length; i++) {
        index.set(dateToNumber(domain[i]), i);
      }
      this.indexInitialized = true;
    }
    return index.get(dateToNumber(value));
  }
};
function deduplicateCategories(d) {
  let domain;
  const uniqueValues = /* @__PURE__ */ new Set();
  for (const value of d) {
    const key = dateToNumber(value);
    const lastSize = uniqueValues.size;
    uniqueValues.add(key);
    const isUniqueValue = uniqueValues.size !== lastSize;
    if (isUniqueValue) {
      domain?.push(value);
    } else {
      domain ?? (domain = d.slice(0, uniqueValues.size));
    }
  }
  return domain ?? d;
}
function domainOrderedToNormalizedDomain(domain, normalizedDomain) {
  let normalizedIndex = -1;
  for (const value of domain) {
    const normalizedNextIndex = normalizedDomain.indexOf(value);
    if (normalizedNextIndex === -1) {
      normalizedIndex = Infinity;
    } else if (normalizedNextIndex <= normalizedIndex) {
      return false;
    } else {
      normalizedIndex = normalizedNextIndex;
    }
  }
  return true;
}

// packages/ag-charts-community/src/util/ticks.ts
import { Logger as Logger11, clamp as clamp10, countFractionDigits, createNumberFormatter, parseNumberFormat } from "ag-charts-core";
var tInterval = (timeInterval, step) => ({
  duration: intervalMilliseconds(timeInterval) * step,
  timeInterval,
  step
});
var TickIntervals = [
  tInterval({ unit: "second" }, 1),
  tInterval({ unit: "second" }, 5),
  tInterval({ unit: "second" }, 15),
  tInterval({ unit: "second" }, 30),
  tInterval({ unit: "minute" }, 1),
  tInterval({ unit: "minute" }, 5),
  tInterval({ unit: "minute" }, 15),
  tInterval({ unit: "minute" }, 30),
  tInterval({ unit: "hour" }, 1),
  tInterval({ unit: "hour" }, 3),
  tInterval({ unit: "hour" }, 6),
  tInterval({ unit: "hour" }, 12),
  tInterval({ unit: "day" }, 1),
  tInterval({ unit: "day" }, 2),
  tInterval({ unit: "day", step: 7 }, 1),
  tInterval({ unit: "day", step: 7 }, 2),
  tInterval({ unit: "day", step: 7 }, 3),
  tInterval({ unit: "month" }, 1),
  tInterval({ unit: "month" }, 2),
  tInterval({ unit: "month" }, 3),
  tInterval({ unit: "month" }, 4),
  tInterval({ unit: "month" }, 6),
  tInterval({ unit: "year" }, 1)
];
var TickMultipliers = [1, 2, 5, 10];
function isCloseToInteger(n, delta3) {
  return Math.abs(Math.round(n) - n) < delta3;
}
function countTicks(d0, d1, step) {
  const extent = Math.abs(d1 - d0);
  return extent >= step ? Math.abs(d1 - d0) / step + 1 : 1;
}
function createTicks(start, stop, count, minCount, maxCount, visibleRange) {
  if (start === stop)
    return { ticks: [start], count: 1, firstTickIndex: 0 };
  if (count < 2)
    return { ticks: [start, stop], count: 2, firstTickIndex: 0 };
  const step = tickStep(start, stop, count, minCount, maxCount);
  if (!Number.isFinite(step))
    return { ticks: [], count: 0, firstTickIndex: void 0 };
  let d0 = start;
  let d1 = stop;
  if (!isCloseToInteger(d0 / step, 1e-12)) {
    d0 = Math.ceil(d0 / step) * step;
  }
  if (!isCloseToInteger(d1 / step, 1e-12)) {
    d1 = Math.floor(d1 / step) * step;
  }
  if (visibleRange != null) {
    const dr = d1 - d0;
    const vr = stop - start;
    const vd0 = start + vr * visibleRange[0];
    const vd1 = start + vr * visibleRange[1];
    visibleRange = [(vd0 - d0) / dr, (vd1 - d0) / dr];
  }
  const { ticks } = range(d0, d1, step, visibleRange);
  const firstTick = ticks.at(0);
  return {
    ticks,
    count: countTicks(d0, d1, step),
    firstTickIndex: firstTick == null ? void 0 : Math.round((firstTick - d0) / step)
  };
}
var minPrimaryTickRatio = Math.floor(2 * durationWeek / durationMonth * 10) / 10;
function tickStep(start, end, count, minCount = 0, maxCount = Infinity) {
  if (start === end) {
    return clamp10(1, minCount, maxCount);
  } else if (count < 1) {
    return NaN;
  }
  const extent = Math.abs(end - start);
  const step = 10 ** Math.floor(Math.log10(extent / count));
  let m = NaN, minDiff = Infinity, isInBounds = false;
  for (const multiplier of TickMultipliers) {
    const c = Math.ceil(extent / (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 range(start, end, step, visibleRange) {
  if (!Number.isFinite(step) || step <= 0) {
    return { ticks: [], count: 0, firstTickIndex: void 0 };
  } else if (start === end) {
    return { ticks: [start], count: 1, firstTickIndex: 0 };
  }
  const f = 10 ** countFractionDigits(step);
  const d0 = Math.min(start, end);
  const d1 = Math.max(start, end);
  let vd0;
  let vd1;
  if (visibleRange != null && (visibleRange[0] !== 0 || visibleRange[1] !== 1)) {
    const rangeExtent = end - start;
    const adjustedStart = start + rangeExtent * visibleRange[0];
    const adjustedEnd = end - rangeExtent * (1 - visibleRange[1]);
    vd0 = Math.min(adjustedStart, adjustedEnd);
    vd1 = Math.max(adjustedStart, adjustedEnd);
  } else {
    vd0 = d0;
    vd1 = d1;
  }
  vd0 = Math.floor(vd0 * f) / f;
  vd1 = Math.ceil(vd1 * f) / f;
  const ticks = [];
  for (let i = 0; ; i += 1) {
    const p = Math.round((d0 + step * i) * f) / f;
    if (p > d1)
      break;
    if (p >= vd0 && p <= vd1) {
      ticks.push(p);
    }
  }
  const firstTick = ticks.at(0);
  return {
    ticks,
    count: countTicks(d0, d1, step),
    firstTickIndex: firstTick == null ? void 0 : Math.round((firstTick - d0) / step)
  };
}
function isDenseInterval(count, availableRange) {
  if (count >= availableRange) {
    Logger11.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(start, end) {
  const extent = Math.abs(end - start);
  const step = 10 ** Math.floor(Math.log10(extent));
  let minError = Infinity, ticks = [start, end];
  for (const multiplier of TickMultipliers) {
    const m = multiplier * step;
    const d0 = Math.floor(start / m) * m;
    const d1 = Math.ceil(end / m) * m;
    const error = 1 - extent / Math.abs(d1 - d0);
    if (minError > error) {
      minError = error;
      ticks = [d0, d1];
    }
  }
  return ticks;
}

// packages/ag-charts-community/src/scale/continuousScale.ts
var _ContinuousScale = class _ContinuousScale extends AbstractScale {
  constructor(domain = [], range2 = []) {
    super();
    this.domain = domain;
    this.range = range2;
    this.defaultTickCount = _ContinuousScale.defaultTickCount;
    this.defaultClamp = false;
  }
  static is(value) {
    return value instanceof _ContinuousScale;
  }
  normalizeDomains(...domains) {
    return normalizeContinuousDomains(...domains);
  }
  calcBandwidth(smallestInterval = 1, minWidth = 1) {
    const { domain } = this;
    const rangeDistance = this.getPixelRange();
    if (domain.length === 0)
      return rangeDistance;
    const intervals = Math.abs(domain[1].valueOf() - domain[0].valueOf()) / smallestInterval + 1;
    let bands = intervals;
    if (minWidth !== 0) {
      const maxBands = Math.floor(rangeDistance);
      bands = Math.min(bands, maxBands);
    }
    return rangeDistance / Math.max(1, bands);
  }
  convert(value, options) {
    const { domain } = this;
    if (!domain || domain.length < 2 || value == null) {
      return NaN;
    }
    const { range: range2 } = this;
    const clamp11 = options?.clamp ?? this.defaultClamp;
    let d0 = domain[0].valueOf();
    let d1 = domain[1].valueOf();
    let x = value.valueOf();
    if (this.transform) {
      d0 = this.transform(d0);
      d1 = this.transform(d1);
      x = this.transform(x);
    }
    if (clamp11) {
      const [start, stop] = findMinMax([d0, d1]);
      if (x < start) {
        return range2[0];
      } else if (x > stop) {
        return range2[1];
      }
    }
    if (d0 === d1) {
      return (range2[0] + range2[1]) / 2;
    } else if (x === d0) {
      return range2[0];
    } else if (x === d1) {
      return range2[1];
    }
    const r0 = range2[0];
    return r0 + (x - d0) / (d1 - d0) * (range2[1] - r0);
  }
  invert(x, _nearest) {
    const { domain } = this;
    if (domain.length < 2)
      return;
    let d0 = domain[0].valueOf();
    let d1 = domain[1].valueOf();
    if (this.transform) {
      d0 = this.transform(d0);
      d1 = this.transform(d1);
    }
    const { range: range2 } = this;
    const [r0, r1] = range2;
    let d;
    if (r0 === r1) {
      d = this.toDomain((d0 + d1) / 2);
    } else {
      d = this.toDomain(d0 + (x - r0) / (r1 - r0) * (d1 - d0));
    }
    return this.transformInvert ? this.transformInvert(d) : d;
  }
  getPixelRange() {
    const [a, b] = this.range;
    return Math.abs(b - a);
  }
};
_ContinuousScale.defaultTickCount = 5;
var ContinuousScale = _ContinuousScale;
function normalizeContinuousDomains(...domains) {
  let min;
  let minValue = Infinity;
  let max;
  let maxValue = -Infinity;
  for (const domain of domains) {
    for (const d of domain) {
      const value = d.valueOf();
      if (value < minValue) {
        minValue = value;
        min = d;
      }
      if (value > maxValue) {
        maxValue = value;
        max = d;
      }
    }
  }
  if (min != null && max != null) {
    const domain = [min, max];
    return { domain, animatable: true };
  } else {
    return { domain: [], animatable: false };
  }
}

// packages/ag-charts-community/src/scale/linearScale.ts
var LinearScale = class _LinearScale extends ContinuousScale {
  constructor() {
    super([0, 1], [0, 1]);
    this.type = "number";
  }
  static is(value) {
    return value instanceof _LinearScale;
  }
  static getTickStep(start, stop, ticks) {
    const { interval, tickCount = ContinuousScale.defaultTickCount, minTickCount, maxTickCount } = ticks;
    return interval ?? tickStep(start, stop, tickCount, minTickCount, maxTickCount);
  }
  toDomain(d) {
    return d;
  }
  ticks({ interval, tickCount = ContinuousScale.defaultTickCount, minTickCount, maxTickCount }, domain = this.domain, visibleRange) {
    if (!domain || domain.length < 2 || tickCount < 1 || !domain.every(isFinite)) {
      return { ticks: [], count: 0, firstTickIndex: 0 };
    }
    const [d0, d1] = domain;
    if (interval) {
      const step = Math.abs(interval);
      if (!isDenseInterval((d1 - d0) / step, this.getPixelRange())) {
        return range(d0, d1, step, visibleRange);
      }
    }
    return createTicks(d0, d1, tickCount, minTickCount, maxTickCount, visibleRange);
  }
  niceDomain(ticks, domain = this.domain) {
    if (domain.length < 2)
      return [];
    const { tickCount = ContinuousScale.defaultTickCount } = ticks;
    let [start, stop] = domain;
    if (tickCount === 1) {
      [start, stop] = niceTicksDomain(start, stop);
    } else if (tickCount > 1) {
      const roundStart = start > stop ? Math.ceil : Math.floor;
      const roundStop = start > stop ? Math.floor : Math.ceil;
      const maxAttempts = 4;
      for (let i = 0; i < maxAttempts; i++) {
        const prev0 = start;
        const prev1 = stop;
        const step = _LinearScale.getTickStep(start, stop, ticks);
        const [d0, d1] = domain;
        start = roundStart(d0 / step) * step;
        stop = roundStop(d1 / step) * step;
        if (start === prev0 && stop === prev1)
          break;
      }
    }
    return [start, stop];
  }
};

// packages/ag-charts-community/src/scene/scene.ts
import { CleanupRegistry, EventEmitter as EventEmitter2, Logger as Logger12, createId as createId3, downloadUrl } from "ag-charts-core";

// packages/ag-charts-community/src/scene/canvas/hdpiCanvas.ts
import { createElement, getWindow as getWindow3 } from "ag-charts-core";
var HdpiCanvas = class {
  constructor(options) {
    this.enabled = true;
    this.width = 600;
    this.height = 300;
    const { width, height, canvasElement, willReadFrequently = false } = options;
    this.pixelRatio = options.pixelRatio ?? getWindow3("devicePixelRatio") ?? 1;
    this.element = canvasElement ?? createElement("canvas");
    this.element.style.display = "block";
    this.element.style.width = (width ?? this.width) + "px";
    this.element.style.height = (height ?? this.height) + "px";
    this.element.width = Math.round((width ?? this.width) * this.pixelRatio);
    this.element.height = Math.round((height ?? this.height) * this.pixelRatio);
    this.context = this.element.getContext("2d", { willReadFrequently });
    this.onEnabledChange();
    this.resize(width ?? 0, height ?? 0, this.pixelRatio);
    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(width, height, pixelRatio) {
    if (!(width > 0 && height > 0))
      return;
    const { element, context } = this;
    element.width = Math.round(width * pixelRatio);
    element.height = Math.round(height * pixelRatio);
    context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
    element.style.width = width + "px";
    element.style.height = height + "px";
    this.width = width;
    this.height = height;
    this.pixelRatio = pixelRatio;
  }
  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);
  }
  reset() {
    this.context.reset();
    this.context.verifyDepthZero?.();
  }
  onEnabledChange() {
    if (this.element) {
      this.element.style.display = this.enabled ? "" : "none";
    }
  }
};
__decorateClass([
  ObserveChanges((target) => target.onEnabledChange())
], HdpiCanvas.prototype, "enabled", 2);

// packages/ag-charts-community/src/scene/image/imageLoader.ts
import { EventEmitter } from "ag-charts-core";
var ImageLoader = class extends EventEmitter {
  constructor() {
    super(...arguments);
    this.cache = /* @__PURE__ */ new Map();
    this.imageLoadingCount = 0;
  }
  loadImage(uri, affectedNode) {
    const entry = this.cache.get(uri);
    if (entry?.image) {
      return entry.image;
    } else if (entry != null && affectedNode) {
      entry.nodes.add(affectedNode);
      return;
    }
    if (!affectedNode) {
      return;
    }
    const nextEntry = { image: void 0, nodes: /* @__PURE__ */ new Set([affectedNode]) };
    const image = new Image();
    this.imageLoadingCount++;
    image.onload = () => {
      nextEntry.image = image;
      for (const node of nextEntry.nodes) {
        node.markDirty();
      }
      nextEntry.nodes.clear();
      this.imageLoadingCount--;
      this.emit("image-loaded", { uri });
    };
    image.onerror = () => {
      this.imageLoadingCount--;
      nextEntry.nodes.clear();
      this.emit("image-error", { uri });
    };
    image.src = uri;
    this.cache.set(uri, nextEntry);
    return nextEntry.image;
  }
  waitingToLoad() {
    return this.imageLoadingCount > 0;
  }
  destroy() {
    this.cache.forEach((entry) => {
      entry.nodes.clear();
    });
    this.cache.clear();
  }
};

// packages/ag-charts-community/src/scene/layersManager.ts
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(width, height, pixelRatio) {
    this.canvas.resize(width, height, pixelRatio);
    this.layersMap.forEach(({ canvas }) => canvas.resize(width, height, pixelRatio));
  }
  addLayer(opts) {
    const { width, height, pixelRatio } = this.canvas;
    const { name } = opts;
    const canvas = new HdpiOffscreenCanvas({ width, height, 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();
  }
};

// packages/ag-charts-community/src/scene/scene.ts
var Scene = class extends EventEmitter2 {
  constructor(canvasOptions) {
    super();
    this.debug = Debug.create(true, "scene" /* SCENE */);
    this.id = createId3(this);
    this.imageLoader = new ImageLoader();
    this.root = null;
    this.pendingSize = null;
    this.isDirty = false;
    this.cleanup = new CleanupRegistry();
    this.updateDebugFlags();
    this.canvas = new HdpiCanvas(canvasOptions);
    this.layersManager = new LayersManager(this.canvas);
    this.cleanup.register(
      this.imageLoader.on("image-loaded", () => {
        this.emit("scene-changed", {});
      }),
      this.imageLoader.on("image-error", ({ uri }) => {
        Logger12.warnOnce(`Unable to load image ${uri}`);
      })
    );
  }
  waitingForUpdate() {
    return this.imageLoader?.waitingToLoad() ?? false;
  }
  get width() {
    return this.pendingSize?.[0] ?? this.canvas.width;
  }
  get height() {
    return this.pendingSize?.[1] ?? this.canvas.height;
  }
  get pixelRatio() {
    return this.pendingSize?.[2] ?? this.canvas.pixelRatio;
  }
  /** @deprecated v10.2.0 Only used by AG Grid Sparklines */
  setContainer(value) {
    const { element } = this.canvas;
    element.parentElement?.removeChild(element);
    value.appendChild(element);
    return this;
  }
  setRoot(node) {
    if (this.root === node) {
      return this;
    }
    this.isDirty = true;
    this.root?.setScene();
    this.root = node;
    if (node) {
      node.visible = true;
      node.setScene(this);
    }
    return this;
  }
  updateDebugFlags() {
    Debug.inDevelopmentMode(() => Node._debugEnabled = true);
  }
  clearCanvas() {
    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(width, height, pixelRatio) {
    width = Math.round(width);
    height = Math.round(height);
    pixelRatio ?? (pixelRatio = this.pixelRatio);
    if (width > 0 && height > 0 && (width !== this.width || height !== this.height || pixelRatio !== this.pixelRatio)) {
      this.pendingSize = [width, height, pixelRatio];
      this.isDirty = true;
      return true;
    }
    return false;
  }
  render(opts) {
    const { debugSplitTimes = { start: performance.now() }, extraDebugStats, seriesRect } = opts ?? {};
    const {
      canvas,
      canvas: { context: ctx } = {},
      root,
      pendingSize,
      width,
      height,
      pixelRatio: devicePixelRatio
    } = this;
    if (!ctx) {
      return;
    }
    const renderStartTime = performance.now();
    let resized = false;
    if (pendingSize) {
      resized = true;
      this.layersManager.resize(...pendingSize);
      this.pendingSize = null;
    }
    if (root && !root.visible) {
      this.isDirty = false;
      return;
    }
    let rootDirty;
    if (root instanceof Group) {
      rootDirty = root.dirty;
    }
    if (root != null && rootDirty === 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,
      width,
      height,
      devicePixelRatio,
      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 (rootDirty !== false || resized) {
      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(renderCtx);
      }
      if (this.debug.check()) {
        const tree = buildTree(root, "console");
        this.debug("Scene.render() - before", {
          canvasCleared,
          tree
        });
      }
      if (root.visible) {
        try {
          ctx.save();
          root.render(renderCtx);
          ctx.restore();
        } catch (e) {
          this.canvas.reset();
          throw e;
        }
      }
    }
    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, height } = this;
    if (root == null)
      return;
    return Node.toSVG(root, width, height);
  }
  /** 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;
    this.clear();
  }
  destroy() {
    this.strip();
    this.canvas.destroy();
    this.imageLoader.destroy();
    this.cleanup.flush();
    Object.assign(this, { canvas: void 0 });
  }
};
Scene.className = "Scene";

// packages/ag-charts-community/src/scene/shape/arc.ts
import { isNumberEqual as isNumberEqual2 } from "ag-charts-core";
var Arc = class extends Path {
  constructor() {
    super(...arguments);
    this.centerX = 0;
    this.centerY = 0;
    this.radius = 10;
    this.startAngle = 0;
    this.endAngle = Math.PI * 2;
    this.counterClockwise = false;
    this.type = 0 /* Open */;
  }
  get fullPie() {
    return isNumberEqual2(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 /* Chord */) {
      path.closePath();
    } else if (this.type === 2 /* Round */ && !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 /* Open */ && bbox.containsPoint(x, y) && this.path.isPointInPath(x, y);
  }
};
Arc.className = "Arc";
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "centerX", 2);
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "centerY", 2);
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "radius", 2);
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "startAngle", 2);
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "endAngle", 2);
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "counterClockwise", 2);
__decorateClass([
  SceneChangeDetection()
], Arc.prototype, "type", 2);

// packages/ag-charts-community/src/scene/shape/line.ts
import { createSvgElement as createSvgElement11 } from "ag-charts-core";
var Line = class extends Shape {
  constructor(opts = {}) {
    super(opts);
    this.x1 = 0;
    this.y1 = 0;
    this.x2 = 0;
    this.y2 = 0;
    this.fill = void 0;
    this.strokeWidth = 1;
  }
  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 element = createSvgElement11("line");
    element.setAttribute("x1", String(this.x1));
    element.setAttribute("y1", String(this.y1));
    element.setAttribute("x2", String(this.x2));
    element.setAttribute("y2", String(this.y2));
    this.applySvgStrokeAttributes(element);
    return {
      elements: [element]
    };
  }
};
Line.className = "Line";
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "x1", 2);
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "y1", 2);
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "x2", 2);
__decorateClass([
  SceneChangeDetection()
], Line.prototype, "y2", 2);

// packages/ag-charts-community/src/scene/shape/radialColumnShape.ts
import { isNumberEqual as isNumberEqual3 } from "ag-charts-core";
function rotatePoint(x, y, rotation) {
  const radius = Math.sqrt(x ** 2 + y ** 2);
  const angle = Math.atan2(y, x);
  const rotated = angle + 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 = isNumberEqual3(innerRadius, axisInnerRadius);
    const sideRotation = Math.asin(columnWidth / 2 / innerRadius);
    const pointRotation = this.getRotation();
    const rotate = (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 = rotate(left, bottom);
    path.moveTo(bottomLeftPt.x, bottomLeftPt.y);
    const isEmpty = isNumberEqual3(innerRadius, outerRadius);
    const hasSideIntersection = compare(
      axisOuterRadius,
      getTriangleHypotenuse(outerRadius, columnWidth / 2),
      !isRadiusAxisReversed
    );
    if (isEmpty && 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 = rotate(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 (!isNumberEqual3(topIntersectionX, 0)) {
        const topRightBevelPt = rotate(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 = rotate(left, top);
      const topRightPt = rotate(right, top);
      path.lineTo(topLeftPt.x, topLeftPt.y);
      path.lineTo(topRightPt.x, topRightPt.y);
    }
    const bottomRightPt = rotate(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 = rotate(left, bottom);
      path.lineTo(rotatedBottomLeftPt.x, rotatedBottomLeftPt.y);
    }
    path.closePath();
  }
};
RadialColumnShape.className = "RadialColumnShape";
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "isBeveled", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "columnWidth", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "startAngle", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "endAngle", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "outerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "innerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "axisInnerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "axisOuterRadius", 2);
__decorateClass([
  SceneChangeDetection()
], RadialColumnShape.prototype, "isRadiusAxisReversed", 2);
function getRadialColumnWidth(startAngle, endAngle, axisOuterRadius, columnWidthRatio, maxColumnWidthRatio) {
  const rotation = angleBetween(startAngle, endAngle);
  const pad = rotation * (1 - columnWidthRatio) / 2;
  startAngle += pad;
  endAngle -= pad;
  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));
}

// packages/ag-charts-community/src/scene/sectorBox.ts
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
    );
  }
};

// packages/ag-charts-community/src/scene/util/sector.ts
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 angle = Math.atan2(y, x);
  return startAngle < endAngle ? angle <= endAngle && angle >= startAngle : angle <= endAngle && angle >= -Math.PI || angle >= startAngle && angle <= Math.PI;
}
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 start = 0;
  let end = 1;
  for (let i = 0; i < 8; i += 1) {
    const s = (start + end) / 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) {
      start = s;
    } else {
      end = s;
    }
  }
  return start;
}
var delta2 = 1e-6;
function clockwiseAngle(angle, relativeToStartAngle) {
  if (angleBetween(angle, relativeToStartAngle) < delta2) {
    return relativeToStartAngle;
  } else {
    return normalizeAngle360(angle - relativeToStartAngle) + relativeToStartAngle;
  }
}
function clockwiseAngles(startAngle, endAngle, relativeToStartAngle = 0) {
  const fullPie = Math.abs(endAngle - startAngle) >= 2 * Math.PI;
  const sweepAngle = fullPie ? 2 * Math.PI : normalizeAngle360(endAngle - startAngle);
  startAngle = clockwiseAngle(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 ? clockwiseAngle(Math.atan2(p0y - cy, p0x - cx), startAngle) : NaN;
  const a1 = p1DotNormalized > 0 ? clockwiseAngle(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 = clockwiseAngle(theta + deltaTheta, startAngle);
  const a1 = clockwiseAngle(theta - deltaTheta, startAngle);
  if (a0 >= startAngle && a0 <= endAngle) {
    return a0;
  } else if (a1 >= startAngle && a1 <= endAngle) {
    return a1;
  }
}

// packages/ag-charts-community/src/scene/shape/sector.ts
var Arc2 = 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 } = clockwiseAngles(this.startAngle, this.endAngle);
    const { innerRadius, outerRadius } = this.normalizedRadii();
    const clipAngles = clockwiseAngles(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, start, inner) {
    if (r <= 0)
      return;
    const { startAngle, endAngle } = clockwiseAngles(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 angle = start ? startAngle + angleOffset + angleSweep : endAngle - angleOffset - angleSweep;
    const radius = inner ? innerRadius + r : outerRadius - r;
    const cx = radius * Math.cos(angle);
    const cy = radius * Math.sin(angle);
    if (clipSector != null) {
      const delta3 = 1e-6;
      if (!start && !(angle >= startAngle - delta3 && angle <= clipSector.endAngle - delta3))
        return;
      if (start && !(angle >= clipSector.startAngle + delta3 && angle <= endAngle - delta3))
        return;
      if (inner && radius < clipSector.innerRadius - delta3)
        return;
      if (!inner && radius > clipSector.outerRadius + delta3)
        return;
    }
    const arc = new Arc2(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 (start) {
        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 = clockwiseAngle(Math.atan2(y2, x2), startAngle);
        if (start) {
          innerArc?.clipStart(theta2);
        } else {
          outerArc.clipEnd(theta2);
        }
      }
      if (circleClipEnd != null) {
        const { x: x2, y: y2 } = arc.pointAt(circleClipEnd);
        const theta2 = clockwiseAngle(Math.atan2(y2, x2), startAngle);
        if (start) {
          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(start === inner ? arc.a0 : arc.a1);
    const theta = clockwiseAngle(Math.atan2(y, x), startAngle);
    const radialArc = inner ? innerArc : outerArc;
    if (start) {
      radialArc?.clipStart(theta);
    } else {
      radialArc?.clipEnd(theta);
    }
    return arc;
  }
  updatePath() {
    const delta3 = 1e-6;
    const { path, centerX, centerY, concentricEdgeInset, radialEdgeInset } = this;
    let { startOuterCornerRadius, endOuterCornerRadius, startInnerCornerRadius, endInnerCornerRadius } = this;
    const { startAngle, endAngle } = clockwiseAngles(this.startAngle, this.endAngle);
    const { innerRadius, outerRadius } = this.normalizedRadii();
    const clipSector = this.normalizedClipSector();
    const sweepAngle = endAngle - startAngle;
    const fullPie = sweepAngle >= 2 * Math.PI - delta3;
    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 - delta3) {
      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 - delta3) {
      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 Arc2(
      0,
      0,
      outerArcRadius,
      startAngle + outerArcRadiusOffset,
      endAngle - outerArcRadiusOffset
    );
    const innerArcRadius = clipSector?.innerRadius ?? innerRadius;
    const innerArcRadiusOffset = this.getAngleOffset(innerArcRadius);
    const innerArc = hasInnerSweep ? new Arc2(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([
  SceneChangeDetection()
], Sector.prototype, "centerX", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "centerY", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "innerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "outerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "startAngle", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "endAngle", 2);
__decorateClass([
  SceneObjectChangeDetection({ equals: (lhs, rhs) => lhs.equals(rhs) })
], Sector.prototype, "clipSector", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "concentricEdgeInset", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "radialEdgeInset", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "startOuterCornerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "endOuterCornerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "startInnerCornerRadius", 2);
__decorateClass([
  SceneChangeDetection()
], Sector.prototype, "endInnerCornerRadius", 2);
export {
  Arc,
  BBox,
  Caption,
  CategoryScale,
  Group,
  Line,
  LinearScale,
  Marker,
  Path,
  RadialColumnShape,
  Rect,
  Scene,
  Sector,
  Shape,
  TranslatableGroup,
  getRadialColumnWidth,
  toRadians
};