apexcharts 6.2.0 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/apexcharts.common.js +2 -2
  2. package/dist/apexcharts.esm.js +1379 -212
  3. package/dist/apexcharts.js +1379 -212
  4. package/dist/apexcharts.min.js +2 -2
  5. package/dist/apexcharts.ssr.common.js +2 -2
  6. package/dist/apexcharts.ssr.esm.js +1379 -212
  7. package/dist/area.common.js +2 -2
  8. package/dist/area.esm.js +4 -4
  9. package/dist/bar.common.js +2 -2
  10. package/dist/bar.esm.js +208 -109
  11. package/dist/boxPlot.common.js +2 -2
  12. package/dist/boxPlot.esm.js +208 -109
  13. package/dist/bubble.common.js +2 -2
  14. package/dist/bubble.esm.js +4 -4
  15. package/dist/candlestick.common.js +2 -2
  16. package/dist/candlestick.esm.js +208 -109
  17. package/dist/column.common.js +2 -2
  18. package/dist/column.esm.js +208 -109
  19. package/dist/core.common.js +2 -2
  20. package/dist/core.esm.js +949 -137
  21. package/dist/donut.common.js +1 -1
  22. package/dist/donut.esm.js +1 -1
  23. package/dist/features/all.common.js +2 -2
  24. package/dist/features/all.esm.js +314 -28
  25. package/dist/features/annotations.common.js +1 -1
  26. package/dist/features/annotations.esm.js +1 -1
  27. package/dist/features/context-menu.common.js +1 -1
  28. package/dist/features/context-menu.esm.js +1 -1
  29. package/dist/features/drilldown.common.js +1 -1
  30. package/dist/features/drilldown.esm.js +1 -1
  31. package/dist/features/exports.common.js +1 -1
  32. package/dist/features/exports.esm.js +1 -1
  33. package/dist/features/facet.common.js +1 -1
  34. package/dist/features/facet.esm.js +1 -1
  35. package/dist/features/history.common.js +1 -1
  36. package/dist/features/history.esm.js +1 -1
  37. package/dist/features/ink.common.js +1 -1
  38. package/dist/features/ink.esm.js +1 -1
  39. package/dist/features/keyboard.common.js +1 -1
  40. package/dist/features/keyboard.esm.js +1 -1
  41. package/dist/features/legend.common.js +1 -1
  42. package/dist/features/legend.esm.js +1 -1
  43. package/dist/features/link.common.js +1 -1
  44. package/dist/features/link.esm.js +1 -1
  45. package/dist/features/marks.common.js +1 -1
  46. package/dist/features/marks.esm.js +1 -1
  47. package/dist/features/measure.common.js +1 -1
  48. package/dist/features/measure.esm.js +1 -1
  49. package/dist/features/morph.common.js +1 -1
  50. package/dist/features/morph.esm.js +1 -1
  51. package/dist/features/perspectives.common.js +1 -1
  52. package/dist/features/perspectives.esm.js +1 -1
  53. package/dist/features/renderer-canvas.common.js +2 -2
  54. package/dist/features/renderer-canvas.esm.js +294 -7
  55. package/dist/features/storyboard.common.js +1 -1
  56. package/dist/features/storyboard.esm.js +1 -1
  57. package/dist/features/toolbar.common.js +2 -2
  58. package/dist/features/toolbar.esm.js +19 -20
  59. package/dist/features/weave.common.js +1 -1
  60. package/dist/features/weave.esm.js +1 -1
  61. package/dist/heatmap.common.js +2 -2
  62. package/dist/heatmap.esm.js +79 -41
  63. package/dist/line.common.js +2 -2
  64. package/dist/line.esm.js +4 -4
  65. package/dist/pie.common.js +1 -1
  66. package/dist/pie.esm.js +1 -1
  67. package/dist/polarArea.common.js +1 -1
  68. package/dist/polarArea.esm.js +1 -1
  69. package/dist/radar.common.js +1 -1
  70. package/dist/radar.esm.js +1 -1
  71. package/dist/radialBar.common.js +1 -1
  72. package/dist/radialBar.esm.js +1 -1
  73. package/dist/rangeArea.common.js +2 -2
  74. package/dist/rangeArea.esm.js +4 -4
  75. package/dist/rangeBar.common.js +2 -2
  76. package/dist/rangeBar.esm.js +208 -109
  77. package/dist/scatter.common.js +2 -2
  78. package/dist/scatter.esm.js +4 -4
  79. package/dist/treemap.common.js +1 -1
  80. package/dist/treemap.esm.js +1 -1
  81. package/dist/violin.common.js +2 -2
  82. package/dist/violin.esm.js +208 -109
  83. package/package.json +1 -1
  84. package/src/apexcharts.js +307 -33
  85. package/src/charts/Bar.js +38 -6
  86. package/src/charts/HeatMap.js +126 -55
  87. package/src/charts/Line.js +7 -5
  88. package/src/charts/common/bar/DataLabels.js +16 -0
  89. package/src/modules/Core.js +19 -0
  90. package/src/modules/Crosshairs.js +24 -5
  91. package/src/modules/Data.js +212 -16
  92. package/src/modules/Filters.js +34 -6
  93. package/src/modules/Graphics.js +4 -4
  94. package/src/modules/Range.js +160 -32
  95. package/src/modules/Series.js +25 -0
  96. package/src/modules/ZoomPanSelection.js +16 -11
  97. package/src/modules/animations/AxisTransition.js +57 -15
  98. package/src/modules/animations/DataLabelTransition.js +235 -0
  99. package/src/modules/animations/LengthTransition.js +15 -2
  100. package/src/modules/axes/YAxis.js +21 -1
  101. package/src/modules/helpers/UpdateHelpers.js +16 -5
  102. package/src/modules/settings/Defaults.js +12 -1
  103. package/src/modules/settings/Globals.js +50 -1
  104. package/src/modules/settings/Options.js +16 -0
  105. package/src/modules/tooltip/AxesTooltip.js +7 -1
  106. package/src/modules/tooltip/Intersect.js +145 -32
  107. package/src/modules/tooltip/Labels.js +9 -0
  108. package/src/modules/tooltip/Tooltip.js +28 -7
  109. package/src/modules/tooltip/Utils.js +5 -1
  110. package/src/renderers/Renderer.js +8 -2
  111. package/src/renderers/canvas/CanvasCompositor.js +100 -1
  112. package/src/renderers/canvas/CanvasGraphics.js +184 -0
  113. package/src/renderers/canvas/CanvasRenderer.js +62 -6
  114. package/src/types/internal.d.ts +31 -0
  115. package/types/apexcharts.d.ts +30 -0
@@ -51,7 +51,7 @@ var __async = (__this, __arguments, generator) => {
51
51
  });
52
52
  };
53
53
  /*!
54
- * ApexCharts v6.2.0
54
+ * ApexCharts v6.4.0
55
55
  * (c) 2018-2026 ApexCharts
56
56
  */
57
57
  class Environment {
@@ -2815,7 +2815,14 @@ class Defaults {
2815
2815
  heatmap() {
2816
2816
  return {
2817
2817
  chart: {
2818
- stacked: false
2818
+ stacked: false,
2819
+ // A heatmap is a fixed grid: zooming/panning only distorts the cells
2820
+ // and (on a datetime axis) collapses the month labels to repeats, so
2821
+ // it is off by default, mirroring treemap. Users can opt back in with
2822
+ // chart.zoom.enabled: true.
2823
+ zoom: {
2824
+ enabled: false
2825
+ }
2819
2826
  },
2820
2827
  fill: {
2821
2828
  opacity: 1
@@ -2829,7 +2836,11 @@ class Defaults {
2829
2836
  colors: ["#fff"]
2830
2837
  },
2831
2838
  tooltip: {
2832
- followCursor: true,
2839
+ // Anchor the tooltip above the hovered cell with a downward arrow
2840
+ // (flipping below near the top edge), the same treatment horizontal
2841
+ // bars get, rather than trailing the cursor. Opt back into the old
2842
+ // behavior with tooltip.followCursor: true.
2843
+ followCursor: false,
2833
2844
  marker: {
2834
2845
  show: false
2835
2846
  },
@@ -4510,6 +4521,20 @@ class Options {
4510
4521
  blur: 1,
4511
4522
  color: "#000",
4512
4523
  opacity: 0.8
4524
+ },
4525
+ // Ride data labels to their new position on a data-change update
4526
+ // (e.g. a bar chart race), instead of snapping. Off by default so
4527
+ // existing charts are unchanged. Speed/easing follow
4528
+ // chart.animations.dynamicAnimation. Bar/column only.
4529
+ animate: {
4530
+ enabled: false
4531
+ },
4532
+ // Count the numeric value up/down from its previous value on update,
4533
+ // like countUp.js. Off by default. The dataLabels.formatter runs each
4534
+ // frame, so number formatting (decimals, separators, prefixes) is
4535
+ // preserved. Bar/column only.
4536
+ countUp: {
4537
+ enabled: false
4513
4538
  }
4514
4539
  },
4515
4540
  fill: {
@@ -4701,13 +4726,15 @@ class Options {
4701
4726
  states: {
4702
4727
  hover: {
4703
4728
  filter: {
4704
- type: "lighten"
4729
+ type: "lighten",
4730
+ value: 0.15
4705
4731
  }
4706
4732
  },
4707
4733
  active: {
4708
4734
  allowMultipleDataPointsSelection: false,
4709
4735
  filter: {
4710
- type: "darken"
4736
+ type: "darken",
4737
+ value: 0.35
4711
4738
  }
4712
4739
  }
4713
4740
  },
@@ -5761,14 +5788,54 @@ class Globals {
5761
5788
  globals
5762
5789
  );
5763
5790
  }
5791
+ /**
5792
+ * Lazy initial-series snapshot. Capturing `initialSeries` used to deep-clone
5793
+ * the entire series on every parse and every update: the single largest CPU
5794
+ * bucket at 50k+ points (profiled at ~23ms per 50k update). The setter now
5795
+ * stores a cheap per-series shallow copy (series OBJECTS copied, data arrays
5796
+ * shared) and the deep snapshot materializes only when something actually
5797
+ * reads it (resetSeries, toolbar reset-home, tooltip same-length check).
5798
+ *
5799
+ * Why sharing the data arrays is safe: internal "mutations" of a series'
5800
+ * data are property REPLACEMENTS (`series[i].data = []` on legend collapse),
5801
+ * which cannot reach the captured copies because each series object was
5802
+ * copied at capture time. The one in-place mutator (appendData's push loop)
5803
+ * re-captures immediately after mutating, so the pending snapshot never
5804
+ * spans the mutation.
5805
+ *
5806
+ * @param {Record<string, any>} globals
5807
+ */
5808
+ defineLazyInitialSeries(globals) {
5809
+ let src = [];
5810
+ let snap = null;
5811
+ Object.defineProperty(globals, "initialSeries", {
5812
+ configurable: true,
5813
+ enumerable: true,
5814
+ get() {
5815
+ if (snap === null) {
5816
+ snap = Utils$1.clone(src);
5817
+ }
5818
+ return snap;
5819
+ },
5820
+ set(value) {
5821
+ src = Array.isArray(value) ? value.map(
5822
+ (s) => s && typeof s === "object" && !Array.isArray(s) ? __spreadValues({}, s) : s
5823
+ ) : value;
5824
+ snap = null;
5825
+ globals._initialSeriesPeek = src;
5826
+ }
5827
+ });
5828
+ globals._initialSeriesPeek = src;
5829
+ }
5764
5830
  /**
5765
5831
  * @param {Record<string, any>} config
5766
5832
  */
5767
5833
  init(config) {
5768
5834
  const globals = this.globalVars(config);
5769
5835
  this.initGlobalVars(globals);
5836
+ this.defineLazyInitialSeries(globals);
5770
5837
  globals.initialConfig = Utils$1.extend({}, config);
5771
- globals.initialSeries = Utils$1.clone(config.series);
5838
+ globals.initialSeries = config.series;
5772
5839
  globals.lastXAxis = Utils$1.clone(
5773
5840
  /** @type {NonNullable<typeof globals.initialConfig>} */
5774
5841
  globals.initialConfig.xaxis
@@ -8147,6 +8214,7 @@ class Animations {
8147
8214
  });
8148
8215
  }
8149
8216
  }
8217
+ const DEFAULT_INTENSITY = { lighten: 0.15, darken: 0.35 };
8150
8218
  class Filters {
8151
8219
  /**
8152
8220
  * @param {import('../types/internal').ChartStateW} w
@@ -8172,8 +8240,9 @@ class Filters {
8172
8240
  * @param {any} el
8173
8241
  * @param {number} i
8174
8242
  * @param {string} filterType
8243
+ * @param {number} [intensity] Blend strength (0 to 1). Defaults per type.
8175
8244
  */
8176
- applyFilter(el, i, filterType) {
8245
+ applyFilter(el, i, filterType, intensity) {
8177
8246
  var _a, _b, _c;
8178
8247
  const w = this.w;
8179
8248
  if (el.unfilter) {
@@ -8184,15 +8253,21 @@ class Filters {
8184
8253
  return;
8185
8254
  }
8186
8255
  const shadowAttr = w.config.chart.dropShadow;
8187
- const brightnessFactor = filterType === "lighten" ? 2 : 0.3;
8256
+ const fallback = filterType === "lighten" ? DEFAULT_INTENSITY.lighten : DEFAULT_INTENSITY.darken;
8257
+ const t = Math.max(
8258
+ 0,
8259
+ Math.min(1, typeof intensity === "number" ? intensity : fallback)
8260
+ );
8261
+ const diag = 1 - t;
8262
+ const offset = filterType === "lighten" ? t : 0;
8188
8263
  if (el.filterWith) {
8189
8264
  el.filterWith((add) => {
8190
8265
  add.colorMatrix({
8191
8266
  type: "matrix",
8192
8267
  values: `
8193
- ${brightnessFactor} 0 0 0 0
8194
- 0 ${brightnessFactor} 0 0 0
8195
- 0 0 ${brightnessFactor} 0 0
8268
+ ${diag} 0 0 0 ${offset}
8269
+ 0 ${diag} 0 0 ${offset}
8270
+ 0 0 ${diag} 0 ${offset}
8196
8271
  0 0 0 1 0
8197
8272
  `,
8198
8273
  in: "SourceGraphic",
@@ -8291,7 +8366,7 @@ class Filters {
8291
8366
  el.node.setAttribute("selected", true);
8292
8367
  const activeFilter = w.config.states.active.filter;
8293
8368
  if (activeFilter !== "none") {
8294
- this.applyFilter(el, realIndex, activeFilter.type);
8369
+ this.applyFilter(el, realIndex, activeFilter.type, activeFilter.value);
8295
8370
  }
8296
8371
  }
8297
8372
  }
@@ -9130,7 +9205,7 @@ class Graphics {
9130
9205
  if (w.config.states.hover.filter.type !== "none") {
9131
9206
  if (!w.interact.isTouchDevice) {
9132
9207
  const hoverFilter = w.config.states.hover.filter;
9133
- filters.applyFilter(path, i, hoverFilter.type);
9208
+ filters.applyFilter(path, i, hoverFilter.type, hoverFilter.value);
9134
9209
  }
9135
9210
  }
9136
9211
  }
@@ -9215,12 +9290,12 @@ class Graphics {
9215
9290
  if (selected === "true") {
9216
9291
  const activeFilter = w.config.states.active.filter;
9217
9292
  if (activeFilter !== "none") {
9218
- filters.applyFilter(path, i, activeFilter.type);
9293
+ filters.applyFilter(path, i, activeFilter.type, activeFilter.value);
9219
9294
  } else {
9220
9295
  if (w.config.states.hover.filter !== "none") {
9221
9296
  if (!w.interact.isTouchDevice) {
9222
9297
  const hoverFilter = w.config.states.hover.filter;
9223
- filters.applyFilter(path, i, hoverFilter.type);
9298
+ filters.applyFilter(path, i, hoverFilter.type, hoverFilter.value);
9224
9299
  }
9225
9300
  }
9226
9301
  }
@@ -9228,7 +9303,7 @@ class Graphics {
9228
9303
  if (w.config.states.active.filter.type !== "none") {
9229
9304
  if (w.config.states.hover.filter.type !== "none" && !w.interact.isTouchDevice) {
9230
9305
  const hoverFilter = w.config.states.hover.filter;
9231
- filters.applyFilter(path, i, hoverFilter.type);
9306
+ filters.applyFilter(path, i, hoverFilter.type, hoverFilter.value);
9232
9307
  } else {
9233
9308
  filters.getDefaultFilter(path, i);
9234
9309
  }
@@ -9867,12 +9942,13 @@ function computeMarkCount(w) {
9867
9942
  const markerSize = w.config.markers && w.config.markers.size;
9868
9943
  const markersOn = Array.isArray(markerSize) ? markerSize.some((s) => s > 0) : (markerSize || 0) > 0;
9869
9944
  const labelsOn = !!(w.config.dataLabels && w.config.dataLabels.enabled);
9945
+ const isHeatmap = type === "heatmap";
9870
9946
  let total = 0;
9871
9947
  let maxLen = 0;
9872
9948
  series.forEach((s) => {
9873
9949
  const n = Array.isArray(s.data) ? s.data.length : 0;
9874
9950
  if (n > maxLen) maxLen = n;
9875
- if (scatterish || markersOn) total += n;
9951
+ if (scatterish || markersOn || isHeatmap) total += n;
9876
9952
  if (labelsOn) total += n;
9877
9953
  });
9878
9954
  const LARGE_D = 5e4;
@@ -12724,7 +12800,7 @@ class Range {
12724
12800
  * @param {number | null} [endingSeriesIndex]
12725
12801
  */
12726
12802
  getMinYMaxY(startingSeriesIndex, lowestY = Number.MAX_VALUE, highestY = -Number.MAX_VALUE, endingSeriesIndex = null) {
12727
- var _a, _b, _c, _d, _e, _f, _g, _h;
12803
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
12728
12804
  const cnf = this.w.config;
12729
12805
  const gl = this.w.globals;
12730
12806
  let maxY = -Number.MAX_VALUE;
@@ -12788,14 +12864,68 @@ class Range {
12788
12864
  }
12789
12865
  }
12790
12866
  }
12867
+ const plainNumeric = seriesMin === series && seriesMax === series && cnf.chart.type !== "boxPlot" && seriesType !== "candlestick" && seriesType !== "boxPlot" && seriesType !== "violin" && seriesType !== "rangeArea" && seriesType !== "rangeBar" && !(this.w.seriesData.seriesGoals[i] && this.w.seriesData.seriesGoals[i].length);
12868
+ if (plainNumeric) {
12869
+ const arr = series[i];
12870
+ const jEnd = Math.min(lastXIndex, arr.length - 1);
12871
+ const pe = (_b = this.w.seriesData._parsedExtrema) == null ? void 0 : _b[i];
12872
+ if (pe && pe.ref === arr && pe.len === arr.length && firstXIndex === 0 && jEnd === arr.length - 1) {
12873
+ if (pe.maxY > maxY) maxY = pe.maxY;
12874
+ if (pe.lowestY < lowestY) lowestY = pe.lowestY;
12875
+ if (pe.negMinY < 0 && pe.negMinY < minY) minY = pe.negMinY;
12876
+ if (pe.yDec > gl.yValueDecimal) gl.yValueDecimal = pe.yDec;
12877
+ if (pe.hasNulls) gl.hasNullValues = true;
12878
+ } else {
12879
+ let yDec = gl.yValueDecimal;
12880
+ let hasNulls = false;
12881
+ for (let j = firstXIndex; j <= jEnd; j++) {
12882
+ const val = arr[j];
12883
+ if (val !== null && typeof val === "number" && val === val && val !== Infinity && val !== -Infinity) {
12884
+ if (val > maxY) maxY = val;
12885
+ if (val < lowestY) lowestY = val;
12886
+ if (minY > val && val < 0) minY = val;
12887
+ if (!Number.isInteger(val)) {
12888
+ const av = val < 0 ? -val : val;
12889
+ if (av >= 1e-6 && av < 1e21) {
12890
+ const str = "" + val;
12891
+ const dot = str.indexOf(".");
12892
+ const dec = dot === -1 ? 0 : str.length - dot - 1;
12893
+ if (dec > yDec) yDec = dec;
12894
+ } else {
12895
+ const nv = Utils$1.noExponents(val);
12896
+ if (Utils$1.isFloat(nv)) {
12897
+ yDec = Math.max(yDec, nv.toString().split(".")[1].length);
12898
+ }
12899
+ }
12900
+ }
12901
+ } else {
12902
+ hasNulls = true;
12903
+ }
12904
+ }
12905
+ gl.yValueDecimal = yDec;
12906
+ if (hasNulls) gl.hasNullValues = true;
12907
+ }
12908
+ highestY = maxY;
12909
+ if (seriesType === "bar" || seriesType === "column") {
12910
+ if (minY < 0 && maxY < 0) {
12911
+ maxY = 0;
12912
+ highestY = Math.max(highestY, 0);
12913
+ }
12914
+ if (minY === Number.MIN_VALUE) {
12915
+ minY = 0;
12916
+ lowestY = Math.min(lowestY, 0);
12917
+ }
12918
+ }
12919
+ continue;
12920
+ }
12791
12921
  for (let j = firstXIndex; j <= lastXIndex && j < this.w.seriesData.series[i].length; j++) {
12792
12922
  let val = series[i][j];
12793
12923
  if (val !== null && Utils$1.isNumber(val)) {
12794
- if (typeof ((_b = seriesMax[i]) == null ? void 0 : _b[j]) !== "undefined") {
12924
+ if (typeof ((_c = seriesMax[i]) == null ? void 0 : _c[j]) !== "undefined") {
12795
12925
  maxY = Math.max(maxY, seriesMax[i][j]);
12796
12926
  lowestY = Math.min(lowestY, seriesMax[i][j]);
12797
12927
  }
12798
- if (typeof ((_c = seriesMin[i]) == null ? void 0 : _c[j]) !== "undefined") {
12928
+ if (typeof ((_d = seriesMin[i]) == null ? void 0 : _d[j]) !== "undefined") {
12799
12929
  lowestY = Math.min(lowestY, seriesMin[i][j]);
12800
12930
  highestY = Math.max(highestY, seriesMin[i][j]);
12801
12931
  }
@@ -12824,7 +12954,7 @@ class Range {
12824
12954
  break;
12825
12955
  case "violin":
12826
12956
  {
12827
- if (typeof ((_d = this.w.violinData.seriesViolinMax[i]) == null ? void 0 : _d[j]) !== "undefined") {
12957
+ if (typeof ((_e = this.w.violinData.seriesViolinMax[i]) == null ? void 0 : _e[j]) !== "undefined") {
12828
12958
  maxY = Math.max(maxY, this.w.violinData.seriesViolinMax[i][j]);
12829
12959
  lowestY = Math.min(
12830
12960
  lowestY,
@@ -12847,7 +12977,7 @@ class Range {
12847
12977
  );
12848
12978
  }
12849
12979
  if (this.w.config.chart.type === "boxPlot" || seriesType === "boxPlot") {
12850
- const boxPts = (_f = (_e = this.w.candleData.seriesBoxPoints) == null ? void 0 : _e[i]) == null ? void 0 : _f[j];
12980
+ const boxPts = (_g = (_f = this.w.candleData.seriesBoxPoints) == null ? void 0 : _f[i]) == null ? void 0 : _g[j];
12851
12981
  if (boxPts) {
12852
12982
  for (let p = 0; p < boxPts.length; p++) {
12853
12983
  const pv = boxPts[p];
@@ -12866,7 +12996,7 @@ class Range {
12866
12996
  val.toString().split(".")[1].length
12867
12997
  );
12868
12998
  }
12869
- if (minY > ((_g = seriesMin[i]) == null ? void 0 : _g[j]) && ((_h = seriesMin[i]) == null ? void 0 : _h[j]) < 0) {
12999
+ if (minY > ((_h = seriesMin[i]) == null ? void 0 : _h[j]) && ((_i = seriesMin[i]) == null ? void 0 : _i[j]) < 0) {
12870
13000
  minY = seriesMin[i][j];
12871
13001
  }
12872
13002
  } else {
@@ -13020,38 +13150,33 @@ class Range {
13020
13150
  const cnf = this.w.config;
13021
13151
  const isXNumeric = cnf.xaxis.type === "numeric" || cnf.xaxis.type === "datetime" || cnf.xaxis.type === "category" && !this.w.axisFlags.noLabelsProvided || this.w.axisFlags.noLabelsProvided || this.w.axisFlags.isXNumeric;
13022
13152
  const getInitialMinXMaxX = () => {
13153
+ var _a;
13154
+ let minX = gl.minX;
13155
+ let maxX = gl.maxX;
13023
13156
  for (let i = 0; i < this.w.seriesData.series.length; i++) {
13024
- if (this.w.labelData.labels[i]) {
13025
- for (let j = 0; j < this.w.labelData.labels[i].length; j++) {
13026
- if (this.w.labelData.labels[i][j] !== null && Utils$1.isNumber(this.w.labelData.labels[i][j])) {
13027
- gl.maxX = Math.max(
13028
- gl.maxX,
13029
- /** @type {number} */
13030
- /** @type {any} */
13031
- this.w.labelData.labels[i][j]
13032
- );
13033
- gl.initialMaxX = Math.max(
13034
- gl.maxX,
13035
- /** @type {number} */
13036
- /** @type {any} */
13037
- this.w.labelData.labels[i][j]
13038
- );
13039
- gl.minX = Math.min(
13040
- gl.minX,
13041
- /** @type {number} */
13042
- /** @type {any} */
13043
- this.w.labelData.labels[i][j]
13044
- );
13045
- gl.initialMinX = Math.min(
13046
- gl.minX,
13047
- /** @type {number} */
13048
- /** @type {any} */
13049
- this.w.labelData.labels[i][j]
13050
- );
13051
- }
13157
+ const lbls = (
13158
+ /** @type {any} */
13159
+ this.w.labelData.labels[i]
13160
+ );
13161
+ if (!lbls) continue;
13162
+ const pe = (_a = this.w.seriesData._parsedExtrema) == null ? void 0 : _a[i];
13163
+ if (pe && pe.xNumeric && pe.xref === lbls && pe.len === lbls.length) {
13164
+ if (pe.maxX > maxX) maxX = pe.maxX;
13165
+ if (pe.minX < minX) minX = pe.minX;
13166
+ continue;
13167
+ }
13168
+ for (let j = 0; j < lbls.length; j++) {
13169
+ const v = lbls[j];
13170
+ if (v !== null && typeof v === "number" && v === v) {
13171
+ if (v > maxX) maxX = v;
13172
+ if (v < minX) minX = v;
13052
13173
  }
13053
13174
  }
13054
13175
  }
13176
+ gl.maxX = maxX;
13177
+ gl.initialMaxX = maxX;
13178
+ gl.minX = minX;
13179
+ gl.initialMinX = minX;
13055
13180
  };
13056
13181
  if (this.w.axisFlags.isXNumeric) {
13057
13182
  getInitialMinXMaxX();
@@ -13193,13 +13318,40 @@ class Range {
13193
13318
  _getMinXDiff() {
13194
13319
  const gl = this.w.globals;
13195
13320
  if (this.w.axisFlags.isXNumeric) {
13196
- this.w.seriesData.seriesX.forEach((sX) => {
13321
+ this.w.seriesData.seriesX.forEach((sX, si) => {
13322
+ var _a;
13197
13323
  if (sX.length) {
13198
13324
  if (sX.length === 1) {
13199
13325
  sX.push(
13200
13326
  this.w.seriesData.seriesX[gl.maxValsInArrayIndex][this.w.seriesData.seriesX[gl.maxValsInArrayIndex].length - 1]
13201
13327
  );
13202
13328
  }
13329
+ const pe = (_a = this.w.seriesData._parsedExtrema) == null ? void 0 : _a[si];
13330
+ if (pe && pe.xNumeric && pe.xSorted && pe.xref === sX && pe.len === sX.length) {
13331
+ if (pe.minXDiff < gl.minXDiff) gl.minXDiff = pe.minXDiff;
13332
+ if (gl.dataPoints === 1 || gl.minXDiff === Number.MAX_VALUE) {
13333
+ gl.minXDiff = 0.5;
13334
+ }
13335
+ return;
13336
+ }
13337
+ let presorted = true;
13338
+ let minDiff = gl.minXDiff;
13339
+ for (let j = 1; j < sX.length; j++) {
13340
+ const d = sX[j] - sX[j - 1];
13341
+ if (d > 0) {
13342
+ if (d < minDiff) minDiff = d;
13343
+ } else if (d < 0) {
13344
+ presorted = false;
13345
+ break;
13346
+ }
13347
+ }
13348
+ if (presorted) {
13349
+ gl.minXDiff = minDiff;
13350
+ if (gl.dataPoints === 1 || gl.minXDiff === Number.MAX_VALUE) {
13351
+ gl.minXDiff = 0.5;
13352
+ }
13353
+ return;
13354
+ }
13203
13355
  const seriesX = sX.slice();
13204
13356
  seriesX.sort((a, b) => a - b);
13205
13357
  seriesX.forEach((s, j) => {
@@ -13358,6 +13510,13 @@ class YAxis {
13358
13510
  realIndex,
13359
13511
  w.globals.yAxisScale[realIndex].result.slice()
13360
13512
  );
13513
+ let labelStep = 1;
13514
+ if (w.config.chart.type === "heatmap" && !w.config.yaxis[realIndex].labels.formatter) {
13515
+ const fs = parseInt(yaxisFontSize, 10) || 11;
13516
+ const maxLabels = Math.max(1, Math.floor(w.layout.gridHeight / (fs * 1.4)));
13517
+ const count = tickAmount + 1;
13518
+ if (count > maxLabels) labelStep = Math.ceil(count / maxLabels);
13519
+ }
13361
13520
  if (w.config.yaxis[realIndex].labels.show) {
13362
13521
  let lY = w.layout.translateY + w.config.yaxis[realIndex].labels.offsetY;
13363
13522
  if (w.globals.isBarHorizontal) lY = 0;
@@ -13365,7 +13524,8 @@ class YAxis {
13365
13524
  lY += parseInt(yaxisFontSize, 10) / 3;
13366
13525
  let firstLabel = null;
13367
13526
  for (let i = tickAmount; i >= 0; i--) {
13368
- const val = lbFormatter(labels[i], i, w);
13527
+ const thinned = labelStep > 1 && i % labelStep !== 0;
13528
+ const val = thinned ? "" : lbFormatter(labels[i], i, w);
13369
13529
  let xPad = w.config.yaxis[realIndex].labels.padding;
13370
13530
  if (w.config.yaxis[realIndex].opposite && w.config.yaxis.length !== 0)
13371
13531
  xPad *= -1;
@@ -13976,6 +14136,7 @@ class Crosshairs {
13976
14136
  }
13977
14137
  drawXCrosshairs() {
13978
14138
  const w = this.w;
14139
+ w.dom.elGraphical.node.querySelectorAll(":scope > .apexcharts-xcrosshairs").forEach((el) => el.remove());
13979
14140
  const graphics = new Graphics(this.w);
13980
14141
  const filters = new Filters(this.w);
13981
14142
  const crosshairGradient = w.config.xaxis.crosshairs.fill.gradient;
@@ -14007,10 +14168,7 @@ class Crosshairs {
14007
14168
  []
14008
14169
  );
14009
14170
  }
14010
- let xcrosshairs = graphics.drawRect();
14011
- if (w.config.xaxis.crosshairs.width === 1) {
14012
- xcrosshairs = graphics.drawLine(0, 0, 0, 0);
14013
- }
14171
+ let xcrosshairs = w.config.xaxis.crosshairs.width === 1 ? graphics.drawLine(0, 0, 0, 0) : graphics.drawRect();
14014
14172
  let gridHeight = w.layout.gridHeight;
14015
14173
  if (!Utils$1.isNumber(gridHeight) || gridHeight < 0) {
14016
14174
  gridHeight = 0;
@@ -14047,6 +14205,9 @@ class Crosshairs {
14047
14205
  }
14048
14206
  drawYCrosshairs() {
14049
14207
  const w = this.w;
14208
+ w.dom.elGraphical.node.querySelectorAll(
14209
+ ":scope > .apexcharts-ycrosshairs, :scope > .apexcharts-ycrosshairs-hidden"
14210
+ ).forEach((el) => el.remove());
14050
14211
  const graphics = new Graphics(this.w);
14051
14212
  const crosshair = (
14052
14213
  /** @type {any[]} */
@@ -14599,7 +14760,7 @@ function uniquifyKeys(keys) {
14599
14760
  return count === 0 ? k : `${k}#${count}`;
14600
14761
  });
14601
14762
  }
14602
- function seriesJoin(w, realIndex, includeIdentity = false) {
14763
+ function seriesJoin(w, realIndex, includeIdentity = false, allowReorder = false) {
14603
14764
  var _a, _b;
14604
14765
  if (!lengthTransitionEnabled(w)) return null;
14605
14766
  const frame = w.globals.prevStreamFrame;
@@ -14613,7 +14774,7 @@ function seriesJoin(w, realIndex, includeIdentity = false) {
14613
14774
  );
14614
14775
  const newKeys = uniquifyKeys(newY.map((_, j) => datumKey(w, realIndex, j)));
14615
14776
  const join = joinKeys(oldKeys, newKeys);
14616
- if (!join.ordered) return null;
14777
+ if (!join.ordered && !allowReorder) return null;
14617
14778
  if (!join.changed && !includeIdentity) return null;
14618
14779
  return { join, oldKeys, newKeys };
14619
14780
  }
@@ -14922,7 +15083,7 @@ function captureAxisChrome(w) {
14922
15083
  gl.prevChromeFrame = null;
14923
15084
  }
14924
15085
  }
14925
- function fadeIn(w, node, duration, ease) {
15086
+ function fadeIn$1(w, node, duration, ease) {
14926
15087
  const style = (
14927
15088
  /** @type {any} */
14928
15089
  node.style
@@ -15019,34 +15180,59 @@ function transitionAxis(w, {
15019
15180
  const spanHi = Math.max(...spanPs);
15020
15181
  const margin = Math.max(40, (spanHi - spanLo) * 0.25);
15021
15182
  const clamp = (p) => Math.max(spanLo - margin, Math.min(spanHi + margin, p));
15183
+ const tweenPairedLine = (line, old) => {
15184
+ if (!line) return;
15185
+ const lineTo = parseFloat(line.getAttribute(lineAttrs[0]) || "");
15186
+ const lineFrom = oldLines[old.i];
15187
+ if (isFinite(lineTo) && isFinite(lineFrom)) {
15188
+ tweenPos(w, line, lineAttrs, lineFrom, lineTo, duration, ease);
15189
+ }
15190
+ };
15022
15191
  newLabels.forEach((label, i) => {
15023
15192
  const to = parseFloat(label.getAttribute(posAttr) || "");
15024
15193
  const old = oldByText.get(label.textContent || "");
15025
15194
  const line = newLinesAligned ? newLines[i] : null;
15026
15195
  if (old) matchedOld.add(old.i);
15027
- if (!old || !isFinite(old.pos) || old.transform || label.getAttribute("transform")) {
15196
+ const labelTransform = label.getAttribute("transform");
15197
+ if (!old || !isFinite(old.pos)) {
15028
15198
  if (!old) {
15029
- if (project && isFinite(to) && !label.getAttribute("transform")) {
15199
+ if (project && isFinite(to) && !labelTransform) {
15030
15200
  const from = isFinite(project.toOld(to)) ? clamp(project.toOld(to)) : NaN;
15031
15201
  if (isFinite(from) && Math.abs(from - to) > 0.5) {
15032
15202
  tweenPos(w, label, [posAttr], from, to, duration, ease);
15033
15203
  if (line) tweenPos(w, line, lineAttrs, from, to, duration, ease);
15034
15204
  }
15035
15205
  }
15036
- fadeIn(w, label, duration, ease);
15037
- if (line) fadeIn(w, line, duration, ease);
15206
+ fadeIn$1(w, label, duration, ease);
15207
+ if (line) fadeIn$1(w, line, duration, ease);
15038
15208
  }
15039
15209
  return;
15040
15210
  }
15041
15211
  if (!isFinite(to) || Math.abs(old.pos - to) < 0.5) return;
15042
- tweenPos(w, label, [posAttr], old.pos, to, duration, ease);
15043
- if (line) {
15044
- const lineTo = parseFloat(line.getAttribute(lineAttrs[0]) || "");
15045
- const lineFrom = oldLines[old.i];
15046
- if (isFinite(lineTo) && isFinite(lineFrom)) {
15047
- tweenPos(w, line, lineAttrs, lineFrom, lineTo, duration, ease);
15212
+ if (labelTransform || old.transform) {
15213
+ const delta = old.pos - to;
15214
+ if (isFinite(delta)) {
15215
+ const base = labelTransform || "";
15216
+ rafTween(
15217
+ w,
15218
+ duration,
15219
+ ease,
15220
+ (eased) => {
15221
+ const v = delta * (1 - eased);
15222
+ const t = posAttr === "x" ? `translate(${v} 0)` : `translate(0 ${v})`;
15223
+ label.setAttribute("transform", `${t} ${base}`.trim());
15224
+ },
15225
+ () => {
15226
+ if (base) label.setAttribute("transform", base);
15227
+ else label.removeAttribute("transform");
15228
+ }
15229
+ );
15048
15230
  }
15231
+ tweenPairedLine(line, old);
15232
+ return;
15049
15233
  }
15234
+ tweenPos(w, label, [posAttr], old.pos, to, duration, ease);
15235
+ tweenPairedLine(line, old);
15050
15236
  });
15051
15237
  if (!project || !newLabels.length) return;
15052
15238
  let ghosts = 0;
@@ -15085,7 +15271,7 @@ function applyAxisTransition(w) {
15085
15271
  if (!chrome || !gl.axisCharts || !Environment.isBrowser()) return;
15086
15272
  if (!lengthTransitionEnabled(w)) return;
15087
15273
  const anyMotion = (w.seriesData.series || []).some(
15088
- (_, i) => seriesJoin(w, i, true) !== null
15274
+ (_, i) => seriesJoin(w, i, true, true) !== null
15089
15275
  );
15090
15276
  if (!anyMotion) return;
15091
15277
  const root = w.dom.baseEl;
@@ -15129,6 +15315,158 @@ function applyAxisTransition(w) {
15129
15315
  } catch (_) {
15130
15316
  }
15131
15317
  }
15318
+ const DL_GROUP_SEL = ".apexcharts-data-labels[data\\:dlKey]";
15319
+ const DL_TEXT_SEL = ".apexcharts-datalabel";
15320
+ function dataLabelMotionEnabled(w) {
15321
+ var _a, _b;
15322
+ const dl = w.config.dataLabels;
15323
+ return !!(((_a = dl == null ? void 0 : dl.animate) == null ? void 0 : _a.enabled) || ((_b = dl == null ? void 0 : dl.countUp) == null ? void 0 : _b.enabled));
15324
+ }
15325
+ function decimalsOf(n) {
15326
+ if (!isFinite(n)) return 0;
15327
+ const s = String(n);
15328
+ const dot = s.indexOf(".");
15329
+ return dot === -1 ? 0 : Math.min(6, s.length - dot - 1);
15330
+ }
15331
+ function writeLabel(textEl, s) {
15332
+ const tspan = textEl.querySelector("tspan");
15333
+ if (tspan) tspan.textContent = s;
15334
+ else textEl.textContent = s;
15335
+ }
15336
+ function captureDataLabels(w) {
15337
+ const gl = w.globals;
15338
+ gl.prevDataLabels = null;
15339
+ if (!gl.axisCharts || !Environment.isBrowser()) return;
15340
+ if (!dataLabelMotionEnabled(w)) return;
15341
+ const root = w.dom.baseEl;
15342
+ if (!Utils$1.elementExists(root)) return;
15343
+ try {
15344
+ const map = /* @__PURE__ */ new Map();
15345
+ root.querySelectorAll(DL_GROUP_SEL).forEach((group) => {
15346
+ const key = group.getAttribute("data:dlKey");
15347
+ if (!key) return;
15348
+ const textEl = group.querySelector(DL_TEXT_SEL);
15349
+ if (!textEl) return;
15350
+ map.set(key, {
15351
+ cx: parseFloat(textEl.getAttribute("cx") || ""),
15352
+ cy: parseFloat(textEl.getAttribute("cy") || ""),
15353
+ val: parseFloat(group.getAttribute("data:dlVal") || "")
15354
+ });
15355
+ });
15356
+ gl.prevDataLabels = map.size ? map : null;
15357
+ } catch (_) {
15358
+ gl.prevDataLabels = null;
15359
+ }
15360
+ }
15361
+ function fadeIn(w, node, duration, ease) {
15362
+ const style = (
15363
+ /** @type {any} */
15364
+ node.style
15365
+ );
15366
+ style.opacity = "0";
15367
+ rafTween(
15368
+ w,
15369
+ duration,
15370
+ ease,
15371
+ (eased) => {
15372
+ style.opacity = String(eased);
15373
+ },
15374
+ () => {
15375
+ style.opacity = "";
15376
+ }
15377
+ );
15378
+ }
15379
+ function applyDataLabelTransition(w) {
15380
+ var _a, _b;
15381
+ const gl = w.globals;
15382
+ const prev = gl.prevDataLabels;
15383
+ gl.prevDataLabels = null;
15384
+ if (!prev || !gl.axisCharts || !Environment.isBrowser()) return;
15385
+ if (!dataLabelMotionEnabled(w)) return;
15386
+ if (!lengthTransitionEnabled(w)) return;
15387
+ const root = w.dom.baseEl;
15388
+ if (!Utils$1.elementExists(root)) return;
15389
+ const dl = w.config.dataLabels;
15390
+ const ride = !!((_a = dl.animate) == null ? void 0 : _a.enabled);
15391
+ const countUp = !!((_b = dl.countUp) == null ? void 0 : _b.enabled);
15392
+ const formatter = dl.formatter;
15393
+ const duration = Math.max(1, w.config.chart.animations.dynamicAnimation.speed || 1);
15394
+ const ease = morphEasing(w);
15395
+ try {
15396
+ root.querySelectorAll(DL_GROUP_SEL).forEach((group) => {
15397
+ const key = group.getAttribute("data:dlKey");
15398
+ if (!key) return;
15399
+ const textEl = group.querySelector(DL_TEXT_SEL);
15400
+ if (!textEl) return;
15401
+ const old = prev.get(key);
15402
+ if (ride) {
15403
+ if (old && isFinite(old.cx) && isFinite(old.cy)) {
15404
+ const newCx = parseFloat(textEl.getAttribute("cx") || "");
15405
+ const newCy = parseFloat(textEl.getAttribute("cy") || "");
15406
+ const dx = old.cx - newCx;
15407
+ const dy = old.cy - newCy;
15408
+ if (isFinite(dx) && isFinite(dy) && Math.abs(dx) + Math.abs(dy) > 0.5) {
15409
+ const base = group.getAttribute("transform") || "";
15410
+ rafTween(
15411
+ w,
15412
+ duration,
15413
+ ease,
15414
+ (eased) => {
15415
+ const t = 1 - eased;
15416
+ group.setAttribute(
15417
+ "transform",
15418
+ `translate(${dx * t} ${dy * t}) ${base}`.trim()
15419
+ );
15420
+ },
15421
+ () => {
15422
+ group.setAttribute("transform", base);
15423
+ }
15424
+ );
15425
+ }
15426
+ } else if (!old) {
15427
+ fadeIn(w, group, duration, ease);
15428
+ }
15429
+ }
15430
+ if (countUp && old && isFinite(old.val)) {
15431
+ const newVal = parseFloat(group.getAttribute("data:dlVal") || "");
15432
+ if (isFinite(newVal) && Math.abs(newVal - old.val) > 1e-9) {
15433
+ const from = old.val;
15434
+ const dec = Math.max(decimalsOf(from), decimalsOf(newVal));
15435
+ const realIndex = parseInt(key, 10);
15436
+ const j = parseInt(group.getAttribute("data:dlJ") || "", 10);
15437
+ const format = (v) => {
15438
+ const rounded = Number(v.toFixed(dec));
15439
+ let out = rounded;
15440
+ if (typeof formatter === "function") {
15441
+ try {
15442
+ out = formatter(rounded, __spreadProps(__spreadValues({}, w), {
15443
+ seriesIndex: realIndex,
15444
+ dataPointIndex: isFinite(j) ? j : 0,
15445
+ w
15446
+ }));
15447
+ } catch (_) {
15448
+ out = rounded;
15449
+ }
15450
+ }
15451
+ return String(out);
15452
+ };
15453
+ rafTween(
15454
+ w,
15455
+ duration,
15456
+ ease,
15457
+ (eased) => {
15458
+ writeLabel(textEl, format(from + (newVal - from) * eased));
15459
+ },
15460
+ () => {
15461
+ writeLabel(textEl, format(newVal));
15462
+ }
15463
+ );
15464
+ }
15465
+ }
15466
+ });
15467
+ } catch (_) {
15468
+ }
15469
+ }
15132
15470
  class Series {
15133
15471
  /**
15134
15472
  * @param {import('../types/internal').ChartStateW} w
@@ -15237,6 +15575,24 @@ class Series {
15237
15575
  (_a = this._toggleDataSeries) == null ? void 0 : _a.call(this, isSeriesHidden.realIndex, false);
15238
15576
  }
15239
15577
  }
15578
+ /**
15579
+ * Cheap pre-update reset for the data-replacement paths (updateSeries /
15580
+ * appendSeries). Clears the same bookkeeping resetSeries() clears (series
15581
+ * cache, previous paths, collapsed-series state) WITHOUT restoring
15582
+ * config.series from the initialSeries snapshot: the caller is about to
15583
+ * replace the series anyway (parseData assigns config.series = newSeries),
15584
+ * so materializing and cloning the snapshot per update is pure waste (two
15585
+ * O(n) deep clones per streaming tick at 50k points).
15586
+ */
15587
+ prepareDataUpdate() {
15588
+ const w = this.w;
15589
+ this.clearSeriesCache();
15590
+ w.globals.previousPaths = [];
15591
+ w.globals.collapsedSeries = [];
15592
+ w.globals.ancillaryCollapsedSeries = [];
15593
+ w.globals.collapsedSeriesIndices = [];
15594
+ w.globals.ancillaryCollapsedSeriesIndices = [];
15595
+ }
15240
15596
  resetSeries(shouldUpdateChart = true, shouldResetZoom = true, shouldResetCollapsed = true) {
15241
15597
  var _a, _b;
15242
15598
  const w = this.w;
@@ -15484,6 +15840,7 @@ class Series {
15484
15840
  const w = this.w;
15485
15841
  captureStreamFrame(w);
15486
15842
  captureAxisChrome(w);
15843
+ captureDataLabels(w);
15487
15844
  if (!w.globals.axisCharts) {
15488
15845
  w.globals.previousPaths = w.seriesData.series;
15489
15846
  return;
@@ -17738,6 +18095,24 @@ class Core {
17738
18095
  }
17739
18096
  }
17740
18097
  if (canvasMode) {
18098
+ const rr = (
18099
+ /** @type {any} */
18100
+ ctx.renderer
18101
+ );
18102
+ if (rr && rr._repaintHostInPlace) {
18103
+ rr._repaintHostInPlace = false;
18104
+ const wrapNode = this.w.dom.elGraphical.node.querySelector(
18105
+ ".apexcharts-canvas-series-wrap"
18106
+ );
18107
+ if (wrapNode && rr.canRepaintInPlace && rr.canRepaintInPlace()) {
18108
+ rr.repaintInPlace();
18109
+ const groups = Array.isArray(elGraph) ? elGraph : [elGraph];
18110
+ groups.forEach((g) => {
18111
+ if (g && g.node) wrapNode.appendChild(g.node);
18112
+ });
18113
+ return [];
18114
+ }
18115
+ }
17741
18116
  const host = ctx.renderer.present();
17742
18117
  if (host) {
17743
18118
  const wrap = new Graphics(w).group({
@@ -18135,6 +18510,108 @@ class Data {
18135
18510
  const firstDataPoint = this.getFirstDataPoint();
18136
18511
  return firstDataPoint && Array.isArray(firstDataPoint);
18137
18512
  }
18513
+ /**
18514
+ * Typed single pass for the dominant [[x, y], ...] shape: scalar numeric or
18515
+ * null y, no z, no OHLC tuples. One monomorphic loop fills preallocated
18516
+ * x/y arrays and fuses the y-extrema scan that Range.getMinYMaxY would
18517
+ * otherwise repeat over every value (the extrema entry is ref+length
18518
+ * guarded, so any later reshaping of the series array simply falls back to
18519
+ * the scan). Returns false untouched on any non-conforming point so the
18520
+ * general loop below handles mixed/exotic data with unchanged output.
18521
+ * @param {any[]} data
18522
+ * @param {number} i
18523
+ * @returns {boolean}
18524
+ */
18525
+ _fast2DArrayParse(data, i) {
18526
+ var _a, _b;
18527
+ const n = data.length;
18528
+ if (n === 0) return false;
18529
+ const ys = new Array(n);
18530
+ const xs = new Array(n);
18531
+ let maxY = -Number.MAX_VALUE;
18532
+ let lowestY = Number.MAX_VALUE;
18533
+ let negMinY = Infinity;
18534
+ let hasNulls = false;
18535
+ let yDec = 0;
18536
+ let xNumeric = true;
18537
+ let minX = Infinity;
18538
+ let maxX = -Infinity;
18539
+ let xSorted = true;
18540
+ let minXDiff = Infinity;
18541
+ let prevX = NaN;
18542
+ for (let j = 0; j < n; j++) {
18543
+ const point = data[j];
18544
+ if (!Array.isArray(point) || point.length > 2) return false;
18545
+ const x = point[0];
18546
+ const y = point[1];
18547
+ if (xNumeric) {
18548
+ if (typeof x === "number") {
18549
+ if (x === x) {
18550
+ if (x < minX) minX = x;
18551
+ if (x > maxX) maxX = x;
18552
+ }
18553
+ const d = x - prevX;
18554
+ if (d > 0) {
18555
+ if (d < minXDiff) minXDiff = d;
18556
+ } else if (d < 0) {
18557
+ xSorted = false;
18558
+ }
18559
+ prevX = x;
18560
+ } else {
18561
+ xNumeric = false;
18562
+ }
18563
+ }
18564
+ if (typeof y === "number") {
18565
+ if (y === y && y !== Infinity && y !== -Infinity) {
18566
+ if (y > maxY) maxY = y;
18567
+ if (y < lowestY) lowestY = y;
18568
+ if (y < 0 && y < negMinY) negMinY = y;
18569
+ if (!Number.isInteger(y)) {
18570
+ const av = y < 0 ? -y : y;
18571
+ if (av >= 1e-6 && av < 1e21) {
18572
+ const str = "" + y;
18573
+ const dot = str.indexOf(".");
18574
+ const dec = dot === -1 ? 0 : str.length - dot - 1;
18575
+ if (dec > yDec) yDec = dec;
18576
+ } else {
18577
+ const nv = Utils$1.noExponents(y);
18578
+ if (Utils$1.isFloat(nv)) {
18579
+ yDec = Math.max(yDec, nv.toString().split(".")[1].length);
18580
+ }
18581
+ }
18582
+ }
18583
+ } else {
18584
+ hasNulls = true;
18585
+ }
18586
+ } else if (y === null) {
18587
+ hasNulls = true;
18588
+ } else {
18589
+ return false;
18590
+ }
18591
+ ys[j] = y;
18592
+ xs[j] = x;
18593
+ }
18594
+ this.twoDSeries = ys;
18595
+ this.twoDSeriesX = xs;
18596
+ this.w.axisFlags.dataFormatXNumeric = true;
18597
+ const extrema = (_b = (_a = this.w.seriesData)._parsedExtrema) != null ? _b : _a._parsedExtrema = [];
18598
+ extrema[i] = {
18599
+ ref: ys,
18600
+ len: n,
18601
+ maxY,
18602
+ lowestY,
18603
+ negMinY,
18604
+ hasNulls,
18605
+ yDec,
18606
+ xref: xs,
18607
+ xNumeric,
18608
+ minX,
18609
+ maxX,
18610
+ xSorted,
18611
+ minXDiff
18612
+ };
18613
+ return true;
18614
+ }
18138
18615
  /**
18139
18616
  * @param {any[]} ser
18140
18617
  * @param {number} i
@@ -18144,6 +18621,9 @@ class Data {
18144
18621
  const data = ser[i].data;
18145
18622
  const isBoxPlot = cnf.chart.type === "boxPlot" || /** @type {any} */
18146
18623
  cnf.series[i].type === "boxPlot";
18624
+ if (!isBoxPlot && cnf.xaxis.type !== "datetime" && this._fast2DArrayParse(data, i)) {
18625
+ return;
18626
+ }
18147
18627
  for (let j = 0; j < data.length; j++) {
18148
18628
  const point = data[j];
18149
18629
  const x = point[0];
@@ -18540,6 +19020,7 @@ class Data {
18540
19020
  const cnf = this.w.config;
18541
19021
  const gl = this.w.globals;
18542
19022
  const dt = new DateTime(this.w);
19023
+ this.w.seriesData._parsedExtrema = [];
18543
19024
  const xlabels = cnf.labels.length > 0 ? cnf.labels.slice() : cnf.xaxis.categories.slice();
18544
19025
  this.w.axisFlags.isRangeBar = cnf.chart.type === "rangeBar" && gl.isBarHorizontal;
18545
19026
  this.w.labelData.hasXaxisGroups = cnf.xaxis.type === "category" && cnf.xaxis.group.groups.length > 0;
@@ -18929,7 +19410,11 @@ class Data {
18929
19410
  if (this.w.axisFlags.dataWasParsed) {
18930
19411
  return series;
18931
19412
  }
18932
- if (!globalParsing && !series.some((s) => s.parsing)) {
19413
+ const hasGlobalParsing = !!(globalParsing && (globalParsing.x || globalParsing.y || globalParsing.z));
19414
+ const hasSeriesParsing = series.some(
19415
+ (s) => s.parsing && (s.parsing.x || s.parsing.y || s.parsing.z)
19416
+ );
19417
+ if (!hasGlobalParsing && !hasSeriesParsing) {
18933
19418
  return series;
18934
19419
  }
18935
19420
  const processedSeries = series.map((serie, index) => {
@@ -19196,7 +19681,7 @@ class Data {
19196
19681
  * @param {any[]} ser
19197
19682
  */
19198
19683
  parseData(ser) {
19199
- var _a, _b, _c, _d, _e, _f;
19684
+ var _a, _b, _c, _d, _e, _f, _g;
19200
19685
  const w = this.w;
19201
19686
  const cnf = w.config;
19202
19687
  const gl = w.globals;
@@ -19222,8 +19707,11 @@ class Data {
19222
19707
  gl.dataReducerRawMaxX = rawMaxX;
19223
19708
  }
19224
19709
  }
19225
- cnf.series = ser;
19226
19710
  if (gl.dataReducerRawSeries && ((_f = cnf.chart.dataReducer) == null ? void 0 : _f.enabled)) {
19711
+ ser = ser.map((s) => __spreadValues({}, s));
19712
+ }
19713
+ cnf.series = ser;
19714
+ if (gl.dataReducerRawSeries && ((_g = cnf.chart.dataReducer) == null ? void 0 : _g.enabled)) {
19227
19715
  const stash = gl.dataReducerRawSeries;
19228
19716
  gl.initialSeries = ser.map((s, i) => {
19229
19717
  var _a2, _b2, _c2;
@@ -19232,7 +19720,7 @@ class Data {
19232
19720
  });
19233
19721
  });
19234
19722
  } else {
19235
- gl.initialSeries = Utils$1.clone(ser);
19723
+ gl.initialSeries = ser;
19236
19724
  }
19237
19725
  this.excludeCollapsedSeriesInYAxis();
19238
19726
  this.fallbackToCategory = false;
@@ -19252,10 +19740,23 @@ class Data {
19252
19740
  }
19253
19741
  this.coreUtils.getSeriesTotals();
19254
19742
  if (gl.axisCharts) {
19255
- this.w.seriesData.stackedSeriesTotals = this.coreUtils.getStackedSeriesTotals();
19256
- this.w.seriesData.stackedSeriesTotalsByGroups = this.coreUtils.getStackedSeriesTotalsByGroups();
19743
+ Data._defineLazyResult(
19744
+ this.w.seriesData,
19745
+ "stackedSeriesTotals",
19746
+ () => this.coreUtils.getStackedSeriesTotals()
19747
+ );
19748
+ Data._defineLazyResult(
19749
+ this.w.seriesData,
19750
+ "stackedSeriesTotalsByGroups",
19751
+ () => this.coreUtils.getStackedSeriesTotalsByGroups()
19752
+ );
19753
+ Data._defineLazyResult(gl, "seriesPercent", () => {
19754
+ this.coreUtils.getPercentSeries();
19755
+ return gl.seriesPercent;
19756
+ });
19757
+ } else {
19758
+ this.coreUtils.getPercentSeries();
19257
19759
  }
19258
- this.coreUtils.getPercentSeries();
19259
19760
  if (!this.w.axisFlags.dataFormatXNumeric && (!this.w.axisFlags.isXNumeric || cnf.xaxis.type === "numeric" && cnf.labels.length === 0 && cnf.xaxis.categories.length === 0)) {
19260
19761
  this.handleExternalLabelsData(ser);
19261
19762
  }
@@ -19268,6 +19769,12 @@ class Data {
19268
19769
  }
19269
19770
  return {
19270
19771
  // w.seriesData (future slice)
19772
+ // initialSeries/originalSeries and the stacked totals are deliberately
19773
+ // ABSENT: they already live as lazy accessors on gl / w.seriesData, so
19774
+ // a snapshot field would either force their materialization (a deep
19775
+ // clone plus three O(n) passes per parse that most charts never need)
19776
+ // or, as a delegating getter, recurse into itself when a writer copies
19777
+ // it back onto the object it delegates to.
19271
19778
  seriesData: {
19272
19779
  series: this.w.seriesData.series,
19273
19780
  seriesNames: this.w.seriesData.seriesNames,
@@ -19275,10 +19782,6 @@ class Data {
19275
19782
  seriesZ: this.w.seriesData.seriesZ,
19276
19783
  seriesColors: this.w.seriesData.seriesColors,
19277
19784
  seriesGoals: this.w.seriesData.seriesGoals,
19278
- initialSeries: gl.initialSeries,
19279
- originalSeries: gl.originalSeries,
19280
- stackedSeriesTotals: this.w.seriesData.stackedSeriesTotals,
19281
- stackedSeriesTotalsByGroups: this.w.seriesData.stackedSeriesTotalsByGroups,
19282
19785
  noLabelsProvided: this.w.axisFlags.noLabelsProvided
19283
19786
  },
19284
19787
  // w.rangeData (future slice)
@@ -19327,6 +19830,40 @@ class Data {
19327
19830
  * @param {number|null|undefined} xmax
19328
19831
  * @returns {any[]} Sliced array (new array, never the input reference).
19329
19832
  */
19833
+ /**
19834
+ * Define `key` on `obj` as a lazily computed property: `compute` runs on
19835
+ * first read after this call and its result is cached; assigning to the
19836
+ * property stores the assigned value directly (so code that writes the
19837
+ * field, like getPercentSeries, keeps working). Re-calling resets the cache
19838
+ * (used once per parse).
19839
+ * @param {any} obj
19840
+ * @param {string} key
19841
+ * @param {() => any} compute
19842
+ */
19843
+ static _defineLazyResult(obj, key, compute) {
19844
+ let has = false;
19845
+ let value;
19846
+ Object.defineProperty(obj, key, {
19847
+ configurable: true,
19848
+ enumerable: true,
19849
+ get() {
19850
+ if (!has) {
19851
+ has = true;
19852
+ value = compute();
19853
+ }
19854
+ return value;
19855
+ },
19856
+ set(v) {
19857
+ has = true;
19858
+ value = v;
19859
+ }
19860
+ });
19861
+ }
19862
+ /**
19863
+ * @param {any[]} data
19864
+ * @param {any} xmin
19865
+ * @param {any} xmax
19866
+ */
19330
19867
  static sliceByXRange(data, xmin, xmax) {
19331
19868
  const len = data.length;
19332
19869
  if (len === 0) return data;
@@ -19550,7 +20087,7 @@ class UpdateHelpers {
19550
20087
  if (!redraw) {
19551
20088
  w.globals.resized = true;
19552
20089
  w.globals.dataChanged = true;
19553
- if (animate) {
20090
+ if (animate && w.config.chart.animations.enabled) {
19554
20091
  ch.series.getPreviousPaths();
19555
20092
  }
19556
20093
  }
@@ -19596,7 +20133,7 @@ class UpdateHelpers {
19596
20133
  w.globals.lastXAxis = options2.xaxis ? Utils$1.clone(options2.xaxis) : [];
19597
20134
  w.globals.lastYAxis = options2.yaxis ? Utils$1.clone(options2.yaxis) : [];
19598
20135
  w.globals.initialConfig = Utils$1.extend({}, w.config);
19599
- w.globals.initialSeries = Utils$1.clone(w.config.series);
20136
+ w.globals.initialSeries = w.config.series;
19600
20137
  if (options2.series) {
19601
20138
  for (let i = 0; i < w.globals.collapsedSeriesIndices.length; i++) {
19602
20139
  const series = w.config.series[w.globals.collapsedSeriesIndices[i]];
@@ -19641,7 +20178,7 @@ class UpdateHelpers {
19641
20178
  xMax: w.globals.maxX
19642
20179
  });
19643
20180
  PerformanceCache.invalidateSelectors(w);
19644
- if (animate) {
20181
+ if (animate && w.config.chart.animations.enabled) {
19645
20182
  this.ctx.series.getPreviousPaths();
19646
20183
  }
19647
20184
  const prevSeriesCount = w.config.series.length;
@@ -19661,15 +20198,16 @@ class UpdateHelpers {
19661
20198
  this.ctx._writeParsedAxisFlags(parsedState.axisFlags);
19662
20199
  if (overwriteInitialSeries) {
19663
20200
  if (w.globals.initialConfig) {
19664
- w.globals.initialConfig.series = Utils$1.clone(w.config.series);
20201
+ w.globals.initialConfig.series = w.config.series;
19665
20202
  }
19666
- w.globals.initialSeries = Utils$1.clone(w.config.series);
20203
+ w.globals.initialSeries = w.config.series;
19667
20204
  }
19668
20205
  if (this._canUseFastPath(newSeries, prevSeriesCount, prevDataLengths, w)) {
19669
20206
  return this.ctx.fastUpdate(animate, prevAxisScaleSig).then(() => {
19670
20207
  resolve(this.ctx);
19671
20208
  });
19672
20209
  }
20210
+ if (this.ctx._updateStats) this.ctx._updateStats.full++;
19673
20211
  return this.ctx.update().then(() => {
19674
20212
  resolve(this.ctx);
19675
20213
  });
@@ -20192,11 +20730,11 @@ class Utils2 {
20192
20730
  return false;
20193
20731
  }
20194
20732
  isInitialSeriesSameLen() {
20195
- var _a, _b, _c;
20733
+ var _a, _b, _c, _d;
20196
20734
  let sameLen = true;
20197
20735
  const initialSeries = (
20198
20736
  /** @type {any[]} */
20199
- ((_a = this.w.globals.initialSeries) == null ? void 0 : _a.filter(
20737
+ ((_b = (_a = this.w.globals._initialSeriesPeek) != null ? _a : this.w.globals.initialSeries) == null ? void 0 : _b.filter(
20200
20738
  /**
20201
20739
  * @param {Record<string, any>} s
20202
20740
  * @param {number} i
@@ -20208,7 +20746,7 @@ class Utils2 {
20208
20746
  )) || []
20209
20747
  );
20210
20748
  for (let i = 0; i < initialSeries.length - 1; i++) {
20211
- if (!((_b = initialSeries[i]) == null ? void 0 : _b.data) || !((_c = initialSeries[i + 1]) == null ? void 0 : _c.data)) return true;
20749
+ if (!((_c = initialSeries[i]) == null ? void 0 : _c.data) || !((_d = initialSeries[i + 1]) == null ? void 0 : _d.data)) return true;
20212
20750
  if (initialSeries[i].data.length !== initialSeries[i + 1].data.length) {
20213
20751
  sameLen = false;
20214
20752
  break;
@@ -20814,12 +21352,14 @@ class Labels {
20814
21352
  w
20815
21353
  });
20816
21354
  if (tooltipEl) {
21355
+ const arrowEl = tooltipEl.querySelector(".apexcharts-tooltip-arrow");
20817
21356
  if (typeof customTooltip === "string" || typeof customTooltip === "number") {
20818
21357
  tooltipEl.innerHTML = String(customTooltip);
20819
21358
  } else if (customTooltip instanceof Element || typeof customTooltip.nodeName === "string") {
20820
21359
  tooltipEl.innerHTML = "";
20821
21360
  tooltipEl.appendChild(customTooltip.cloneNode(true));
20822
21361
  }
21362
+ if (arrowEl) tooltipEl.appendChild(arrowEl);
20823
21363
  }
20824
21364
  }
20825
21365
  }
@@ -21672,33 +22212,107 @@ class Intersect {
21672
22212
  var _a, _b;
21673
22213
  const ttCtx = this.ttCtx;
21674
22214
  const w = this.w;
21675
- if (e.target.classList.contains(`apexcharts-${type}-rect`)) {
21676
- const i = this.getAttr(e, "i");
21677
- const j = this.getAttr(e, "j");
21678
- const cx = this.getAttr(e, "cx");
21679
- const cy = this.getAttr(e, "cy");
21680
- const width = this.getAttr(e, "width");
21681
- const height = this.getAttr(e, "height");
21682
- ttCtx.tooltipLabels.drawSeriesTexts({
21683
- ttItems: opt.ttItems,
21684
- i,
21685
- j,
21686
- shared: false,
21687
- e
21688
- });
21689
- w.interact.capturedSeriesIndex = i;
21690
- w.interact.capturedDataPointIndex = j;
21691
- x = cx + ttCtx.tooltipRect.ttWidth / 2 + width;
21692
- y = cy + ttCtx.tooltipRect.ttHeight / 2 - height / 2;
21693
- ttCtx.tooltipPosition.moveXCrosshairs(cx + width / 2);
21694
- if (x > w.layout.gridWidth / 2) {
21695
- x = cx - ttCtx.tooltipRect.ttWidth / 2 + width;
21696
- }
21697
- if (ttCtx.w.config.tooltip.followCursor) {
21698
- const seriesBound = w.dom.elWrap.getBoundingClientRect();
21699
- x = ((_a = w.interact.clientX) != null ? _a : 0) - seriesBound.left - (x > w.layout.gridWidth / 2 ? ttCtx.tooltipRect.ttWidth : 0);
21700
- y = ((_b = w.interact.clientY) != null ? _b : 0) - seriesBound.top - (y > w.layout.gridHeight / 2 ? ttCtx.tooltipRect.ttHeight : 0);
22215
+ const renderer = w.globals.activeRenderer;
22216
+ const canvasCells = type === "heatmap" && renderer && renderer.kind === "canvas" && typeof renderer.hitTest === "function";
22217
+ let i, j, cx, cy, width, height;
22218
+ if (canvasCells) {
22219
+ const seriesBound = opt.elGrid.getBoundingClientRect();
22220
+ const clientX = e.type === "touchmove" ? e.touches[0].clientX : e.clientX;
22221
+ const clientY = e.type === "touchmove" ? e.touches[0].clientY : e.clientY;
22222
+ const hit = renderer.hitTest(
22223
+ clientX - seriesBound.left,
22224
+ clientY - seriesBound.top
22225
+ );
22226
+ if (!hit) {
22227
+ return { x, y, noHit: true };
22228
+ }
22229
+ i = hit.seriesIndex;
22230
+ j = hit.dataPointIndex;
22231
+ cx = hit.x;
22232
+ cy = hit.y;
22233
+ width = hit.width;
22234
+ height = hit.height;
22235
+ } else if (e.target.classList.contains(`apexcharts-${type}-rect`)) {
22236
+ i = this.getAttr(e, "i");
22237
+ j = this.getAttr(e, "j");
22238
+ cx = this.getAttr(e, "cx");
22239
+ cy = this.getAttr(e, "cy");
22240
+ width = this.getAttr(e, "width");
22241
+ height = this.getAttr(e, "height");
22242
+ } else {
22243
+ return { x, y };
22244
+ }
22245
+ ttCtx.tooltipLabels.drawSeriesTexts({
22246
+ ttItems: opt.ttItems,
22247
+ i,
22248
+ j,
22249
+ shared: false,
22250
+ e
22251
+ });
22252
+ w.interact.capturedSeriesIndex = i;
22253
+ w.interact.capturedDataPointIndex = j;
22254
+ ttCtx.tooltipPosition.moveXCrosshairs(cx + width / 2);
22255
+ const tooltipEl = ttCtx.getElTooltip();
22256
+ if (type === "heatmap" && w.config.tooltip.arrow && !w.config.tooltip.followCursor && tooltipEl) {
22257
+ const elGridRect = opt.elGrid.getBoundingClientRect();
22258
+ const elWrapRect = w.dom.elWrap.getBoundingClientRect();
22259
+ const gridOffsetXInElWrap = elGridRect.left - elWrapRect.left;
22260
+ let clLeft, clTop, clRight, clBottom;
22261
+ if (canvasCells) {
22262
+ clLeft = cx;
22263
+ clTop = cy;
22264
+ clRight = cx + width;
22265
+ clBottom = cy + height;
22266
+ } else {
22267
+ const r = e.target.getBoundingClientRect();
22268
+ clLeft = r.left - elGridRect.left;
22269
+ clTop = r.top - elGridRect.top;
22270
+ clRight = r.right - elGridRect.left;
22271
+ clBottom = r.bottom - elGridRect.top;
22272
+ }
22273
+ const ttW = ttCtx.tooltipRect.ttWidth || 0;
22274
+ const ttH = ttCtx.tooltipRect.ttHeight || 0;
22275
+ const ARROW_TIP_OVERHANG = 7;
22276
+ const cellCenterXInElWrap = (clLeft + clRight) / 2 + gridOffsetXInElWrap;
22277
+ const cellTopInElWrap = clTop + w.layout.translateY;
22278
+ const cellBottomInElWrap = clBottom + w.layout.translateY;
22279
+ const gridTop = w.layout.translateY;
22280
+ const gridBottom = w.layout.translateY + w.layout.gridHeight;
22281
+ const gridLeft = gridOffsetXInElWrap;
22282
+ const gridRight = gridOffsetXInElWrap + w.layout.gridWidth;
22283
+ let placement = "top";
22284
+ let finalY = cellTopInElWrap - ttH - ARROW_TIP_OVERHANG;
22285
+ if (finalY < gridTop) {
22286
+ const belowTop = cellBottomInElWrap + ARROW_TIP_OVERHANG;
22287
+ if (belowTop + ttH <= gridBottom) {
22288
+ placement = "bottom";
22289
+ finalY = belowTop;
22290
+ } else {
22291
+ finalY = gridTop;
22292
+ }
21701
22293
  }
22294
+ let finalX = cellCenterXInElWrap - ttW / 2;
22295
+ if (finalX < gridLeft) finalX = gridLeft;
22296
+ if (finalX + ttW > gridRight) finalX = gridRight - ttW;
22297
+ const arrowX = Math.max(10, Math.min(ttW - 10, cellCenterXInElWrap - finalX));
22298
+ ttCtx.tooltipPosition.applyTooltipPosition(tooltipEl, {
22299
+ x: finalX,
22300
+ y: finalY,
22301
+ placement,
22302
+ arrowY: null,
22303
+ arrowX
22304
+ });
22305
+ return { x: finalX, y: finalY, positioned: true };
22306
+ }
22307
+ x = cx + ttCtx.tooltipRect.ttWidth / 2 + width;
22308
+ y = cy + ttCtx.tooltipRect.ttHeight / 2 - height / 2;
22309
+ if (x > w.layout.gridWidth / 2) {
22310
+ x = cx - ttCtx.tooltipRect.ttWidth / 2 + width;
22311
+ }
22312
+ if (ttCtx.w.config.tooltip.followCursor) {
22313
+ const seriesBound = w.dom.elWrap.getBoundingClientRect();
22314
+ x = ((_a = w.interact.clientX) != null ? _a : 0) - seriesBound.left - (x > w.layout.gridWidth / 2 ? ttCtx.tooltipRect.ttWidth : 0);
22315
+ y = ((_b = w.interact.clientY) != null ? _b : 0) - seriesBound.top - (y > w.layout.gridHeight / 2 ? ttCtx.tooltipRect.ttHeight : 0);
21702
22316
  }
21703
22317
  return {
21704
22318
  x,
@@ -22072,7 +22686,7 @@ class AxesTooltip {
22072
22686
  const tooltipCssClass = isRight ? `apexcharts-yaxistooltip apexcharts-yaxistooltip-${i} apexcharts-yaxistooltip-right` : `apexcharts-yaxistooltip apexcharts-yaxistooltip-${i} apexcharts-yaxistooltip-left`;
22073
22687
  const renderTo = w.dom.elWrap;
22074
22688
  const yaxisTooltip = w.dom.baseEl.querySelector(
22075
- `.apexcharts-yaxistooltip apexcharts-yaxistooltip-${i}`
22689
+ `.apexcharts-yaxistooltip.apexcharts-yaxistooltip-${i}`
22076
22690
  );
22077
22691
  if (yaxisTooltip === null) {
22078
22692
  ttCtx.yaxisTooltip = BrowserAPIs.createElementNS(
@@ -22337,7 +22951,7 @@ class Tooltip {
22337
22951
  this.tConfig.style.background
22338
22952
  );
22339
22953
  }
22340
- const isSharedMulti = this.tConfig.shared && w.config.series.length > 1 && !w.globals.isBarHorizontal;
22954
+ const isSharedMulti = this.tConfig.shared && w.config.series.length > 1 && !w.globals.isBarHorizontal && w.config.chart.type !== "heatmap";
22341
22955
  const shouldDrawArrow = this.tConfig.arrow && !this.tConfig.followCursor && !this.tConfig.fixed.enabled && !isSharedMulti && !this.tConfig.fillSeriesColor && w.globals.axisCharts;
22342
22956
  if (shouldDrawArrow) {
22343
22957
  const arrowEl = BrowserAPIs.createElementNS(
@@ -22514,6 +23128,8 @@ class Tooltip {
22514
23128
  this.addPathsEventListeners([hoverArea], seriesHoverParams);
22515
23129
  } else if (commonBar && !w.globals.comboCharts || chartWithmarkers && this.showOnIntersect) {
22516
23130
  this.addDatapointEventsListeners(seriesHoverParams);
23131
+ } else if (type === "heatmap" && w.globals.activeRenderer && w.globals.activeRenderer.kind === "canvas") {
23132
+ this.addPathsEventListeners([hoverArea], seriesHoverParams);
22517
23133
  } else if (!w.globals.axisCharts || type === "heatmap" || type === "treemap") {
22518
23134
  const seriesAll = w.dom.baseEl.querySelectorAll(".apexcharts-series");
22519
23135
  this.addPathsEventListeners(seriesAll, seriesHoverParams);
@@ -22763,10 +23379,16 @@ class Tooltip {
22763
23379
  y,
22764
23380
  type: w.config.chart.type
22765
23381
  });
23382
+ if (markerXY.noHit) {
23383
+ this.handleMouseOut(opt);
23384
+ return;
23385
+ }
22766
23386
  x = markerXY.x;
22767
23387
  y = markerXY.y;
22768
- tooltipEl.style.left = x + "px";
22769
- tooltipEl.style.top = y + "px";
23388
+ if (!markerXY.positioned) {
23389
+ tooltipEl.style.left = x + "px";
23390
+ tooltipEl.style.top = y + "px";
23391
+ }
22770
23392
  } else {
22771
23393
  if (this.tooltipUtil.hasBars()) {
22772
23394
  this.intersect.handleBarTooltip({
@@ -24782,6 +25404,8 @@ const _ApexCharts = class _ApexCharts {
24782
25404
  /** @type {any} */
24783
25405
  __publicField(this, "_keyboardNavigation");
24784
25406
  /** @type {any} */
25407
+ __publicField(this, "_zoomPanSelection");
25408
+ /** @type {any} */
24785
25409
  __publicField(this, "windowResizeHandler");
24786
25410
  /** @type {any} */
24787
25411
  __publicField(this, "parentResizeHandler");
@@ -24823,6 +25447,7 @@ const _ApexCharts = class _ApexCharts {
24823
25447
  const initCtx = new InitCtxVariables(this);
24824
25448
  initCtx.initModules();
24825
25449
  this.lastUpdateOptions = null;
25450
+ this._updateStats = { fast: 0, fastWithAxes: 0, full: 0 };
24826
25451
  this.create = this.create.bind(this);
24827
25452
  if (Environment.isBrowser()) {
24828
25453
  this.windowResizeHandler = this._windowResizeHandler.bind(this);
@@ -25203,7 +25828,7 @@ const _ApexCharts = class _ApexCharts {
25203
25828
  if (Utils$1.shallowEqual(this.lastUpdateOptions, options2)) {
25204
25829
  return Promise.resolve(this);
25205
25830
  }
25206
- if (options2.series && this.lastUpdateOptions.series) {
25831
+ if (options2.series && this.lastUpdateOptions.series && !_ApexCharts._optionsTooBigToCompare(options2)) {
25207
25832
  if (JSON.stringify(this.lastUpdateOptions.series) === JSON.stringify(options2.series)) {
25208
25833
  const optionsWithoutSeries = __spreadValues({}, options2);
25209
25834
  const lastWithoutSeries = __spreadValues({}, this.lastUpdateOptions);
@@ -25257,7 +25882,7 @@ const _ApexCharts = class _ApexCharts {
25257
25882
  */
25258
25883
  updateSeries(newSeries = [], animate = true, overwriteInitialSeries = true) {
25259
25884
  this.data.resetParsingFlags();
25260
- this.series.resetSeries(false);
25885
+ this.series.prepareDataUpdate();
25261
25886
  this.updateHelpers.revertDefaultAxisMinMax();
25262
25887
  return this.updateHelpers._updateSeries(
25263
25888
  newSeries,
@@ -25280,7 +25905,7 @@ const _ApexCharts = class _ApexCharts {
25280
25905
  /** @type {any} */
25281
25906
  newSerie
25282
25907
  );
25283
- this.series.resetSeries(false);
25908
+ this.series.prepareDataUpdate();
25284
25909
  this.updateHelpers.revertDefaultAxisMinMax();
25285
25910
  return this.updateHelpers._updateSeries(
25286
25911
  newSeries,
@@ -25300,7 +25925,9 @@ const _ApexCharts = class _ApexCharts {
25300
25925
  const me = this;
25301
25926
  me.data.resetParsingFlags();
25302
25927
  me.w.globals.dataChanged = true;
25303
- me.series.getPreviousPaths();
25928
+ if (me.w.config.chart.animations.enabled) {
25929
+ me.series.getPreviousPaths();
25930
+ }
25304
25931
  const newSeries = me.w.config.series.slice();
25305
25932
  for (let i = 0; i < newSeries.length; i++) {
25306
25933
  if (newData[i] !== null && typeof newData[i] !== "undefined") {
@@ -25320,19 +25947,37 @@ const _ApexCharts = class _ApexCharts {
25320
25947
  trimStreamingSeries(newSeries, me.w);
25321
25948
  me.w.config.series = newSeries;
25322
25949
  if (overwriteInitialSeries) {
25323
- me.w.globals.initialSeries = Utils$1.clone(me.w.config.series);
25950
+ me.w.globals.initialSeries = me.w.config.series;
25324
25951
  }
25325
25952
  return this.update();
25326
25953
  }
25954
+ /**
25955
+ * True when an options object carries enough series data that a
25956
+ * JSON.stringify equality check (and the Utils.clone needed to store it for
25957
+ * later comparison) would cost more than the re-render it tries to avoid.
25958
+ * @param {any} options
25959
+ * @returns {boolean}
25960
+ */
25961
+ static _optionsTooBigToCompare(options2) {
25962
+ const series = options2 && options2.series;
25963
+ if (!Array.isArray(series)) return false;
25964
+ let points = 0;
25965
+ for (let i = 0; i < series.length; i++) {
25966
+ const d = series[i] && series[i].data;
25967
+ points += Array.isArray(d) ? d.length : 1;
25968
+ if (points > 1e3) return true;
25969
+ }
25970
+ return false;
25971
+ }
25327
25972
  /**
25328
25973
  * @param {object} [options]
25329
25974
  */
25330
25975
  update(options2) {
25331
25976
  return new Promise((resolve, reject) => {
25332
- if (this.lastUpdateOptions && JSON.stringify(this.lastUpdateOptions) === JSON.stringify(options2)) {
25977
+ if (options2 && this.lastUpdateOptions && !_ApexCharts._optionsTooBigToCompare(options2) && JSON.stringify(this.lastUpdateOptions) === JSON.stringify(options2)) {
25333
25978
  return resolve(this);
25334
25979
  }
25335
- this.lastUpdateOptions = Utils$1.clone(options2);
25980
+ this.lastUpdateOptions = options2 && !_ApexCharts._optionsTooBigToCompare(options2) ? Utils$1.clone(options2) : null;
25336
25981
  new Destroy(this.ctx).clear({ isUpdating: true });
25337
25982
  const graphData = this.create(this.w.config.series, options2 != null ? options2 : {});
25338
25983
  if (!graphData) return resolve(this);
@@ -25340,6 +25985,7 @@ const _ApexCharts = class _ApexCharts {
25340
25985
  var _a;
25341
25986
  (_a = this.morphTypeChange) == null ? void 0 : _a.applyChromeFade();
25342
25987
  applyAxisTransition(this.w);
25988
+ applyDataLabelTransition(this.w);
25343
25989
  if (typeof this.w.config.chart.events.updated === "function") {
25344
25990
  this.w.config.chart.events.updated(this, this.w);
25345
25991
  }
@@ -25351,6 +25997,140 @@ const _ApexCharts = class _ApexCharts {
25351
25997
  });
25352
25998
  });
25353
25999
  }
26000
+ /**
26001
+ * Redraws the scale-dependent chrome (grid lines, x-axis, y-axes) IN PLACE
26002
+ * within the frozen layout after a data-only update changed the axis
26003
+ * domain. The rebuilt groups replace the old nodes positionally, so z-order
26004
+ * (grid back/front) is preserved without re-running mount. Legend,
26005
+ * annotations containers, toolbar, defs/masks, and the plot geometry are
26006
+ * untouched.
26007
+ *
26008
+ * Returns false when the refresh cannot faithfully reproduce the chart and
26009
+ * the caller must fall back to a full render:
26010
+ * - horizontal bar charts (inversed axes draw through a different path)
26011
+ * - charts with annotations or ink notes (their positions are scale-bound
26012
+ * and are laid out by the full render)
26013
+ * - the new y labels no longer fit the width reserved at layout time
26014
+ *
26015
+ * @param {any} _xyRatios
26016
+ * @returns {boolean} true when the chrome was refreshed in place
26017
+ */
26018
+ _fastAxisChromeRefresh(_xyRatios) {
26019
+ const w = this.w;
26020
+ const gl = w.globals;
26021
+ this._fastAxisBailReason = "";
26022
+ try {
26023
+ if (gl.isBarHorizontal) {
26024
+ this._fastAxisBailReason = "barHorizontal";
26025
+ return false;
26026
+ }
26027
+ if (w.config.chart.sparkline.enabled) return true;
26028
+ const a = w.config.annotations;
26029
+ if (a && (a.yaxis && a.yaxis.length || a.xaxis && a.xaxis.length || a.points && a.points.length || a.texts && a.texts.length || a.images && a.images.length)) {
26030
+ this._fastAxisBailReason = "annotations";
26031
+ return false;
26032
+ }
26033
+ if (w.config.chart.ink && w.config.chart.ink.enabled) {
26034
+ this._fastAxisBailReason = "ink";
26035
+ return false;
26036
+ }
26037
+ const dim = this.dimensions;
26038
+ if (!dim || !dim.dimYAxis) {
26039
+ this._fastAxisBailReason = "noDimensions";
26040
+ return false;
26041
+ }
26042
+ const prevYLabelsCoords = w.layout.yLabelsCoords;
26043
+ const prevYTitleCoords = w.layout.yTitleCoords;
26044
+ const yaxisLabelCoords = dim.dimYAxis.getyAxisLabelsCoords();
26045
+ const yTitleCoords = dim.dimYAxis.getyAxisTitleCoords();
26046
+ w.layout.yLabelsCoords = [];
26047
+ w.layout.yTitleCoords = [];
26048
+ w.config.yaxis.map((_yaxe, index) => {
26049
+ w.layout.yLabelsCoords.push({
26050
+ width: yaxisLabelCoords[index].width,
26051
+ index
26052
+ });
26053
+ w.layout.yTitleCoords.push(
26054
+ /** @type {any} */
26055
+ { width: yTitleCoords[index].width, index }
26056
+ );
26057
+ });
26058
+ const newYAxisWidth = dim.dimYAxis.getTotalYAxisWidth();
26059
+ if (newYAxisWidth > dim.yAxisWidth + 2) {
26060
+ w.layout.yLabelsCoords = prevYLabelsCoords;
26061
+ w.layout.yTitleCoords = prevYTitleCoords;
26062
+ this._fastAxisBailReason = `labelWidth ${newYAxisWidth} > ${dim.yAxisWidth}`;
26063
+ return false;
26064
+ }
26065
+ const innerEl = w.dom.elGraphical.node;
26066
+ const oldGrid = innerEl.querySelector(".apexcharts-grid");
26067
+ const oldGridBorders = innerEl.querySelector(".apexcharts-grid-borders");
26068
+ if (!oldGrid) {
26069
+ this._fastAxisBailReason = "missingGridNode";
26070
+ return false;
26071
+ }
26072
+ const gridParent = oldGrid.parentNode;
26073
+ const gridNext = oldGridBorders ? oldGridBorders.nextSibling : oldGrid.nextSibling;
26074
+ oldGrid.remove();
26075
+ if (oldGridBorders) oldGridBorders.remove();
26076
+ innerEl.querySelectorAll(".apexcharts-xaxis-tick").forEach((t) => t.remove());
26077
+ this.grid = new Grid(w, this);
26078
+ const elgrid = this.grid.drawGrid();
26079
+ if (elgrid && elgrid.el) {
26080
+ gridParent.insertBefore(elgrid.el.node, gridNext);
26081
+ if (elgrid.elGridBorders && elgrid.elGridBorders.node) {
26082
+ gridParent.insertBefore(elgrid.elGridBorders.node, gridNext);
26083
+ }
26084
+ }
26085
+ const xAxis = new XAxis(this.w, this.ctx, elgrid);
26086
+ const oldXaxis = innerEl.querySelector(".apexcharts-xaxis");
26087
+ if (oldXaxis) {
26088
+ const xParent = oldXaxis.parentNode;
26089
+ const xNext = oldXaxis.nextSibling;
26090
+ oldXaxis.remove();
26091
+ const elXaxis = xAxis.drawXaxis();
26092
+ xParent.insertBefore(elXaxis.node, xNext);
26093
+ }
26094
+ const yAxis = new YAxis(
26095
+ this.w,
26096
+ { theme: this.theme, timeScale: this.timeScale },
26097
+ elgrid
26098
+ );
26099
+ for (let index = 0; index < w.config.yaxis.length; index++) {
26100
+ if (gl.ignoreYAxisIndexes.indexOf(index) !== -1) continue;
26101
+ const oldY = w.dom.baseEl.querySelector(
26102
+ `.apexcharts-yaxis[rel='${index}']`
26103
+ );
26104
+ if (!oldY) {
26105
+ this._fastAxisBailReason = "missingYAxisNode";
26106
+ return false;
26107
+ }
26108
+ const yParent = oldY.parentNode;
26109
+ if (!yParent) {
26110
+ this._fastAxisBailReason = "missingYAxisParent";
26111
+ return false;
26112
+ }
26113
+ const yNext = oldY.nextSibling;
26114
+ oldY.remove();
26115
+ const elYaxis = yAxis.drawYaxis(index);
26116
+ yParent.insertBefore(elYaxis.node, yNext);
26117
+ }
26118
+ if (elgrid !== null) {
26119
+ xAxis.xAxisLabelCorrections();
26120
+ yAxis.setYAxisTextAlignments();
26121
+ w.config.yaxis.map((yaxe, index) => {
26122
+ if (gl.ignoreYAxisIndexes.indexOf(index) === -1) {
26123
+ yAxis.yAxisTitleRotate(index, yaxe.opposite);
26124
+ }
26125
+ });
26126
+ }
26127
+ return true;
26128
+ } catch (e) {
26129
+ this._fastAxisBailReason = "error: " + (e && /** @type {any} */
26130
+ e.message);
26131
+ return false;
26132
+ }
26133
+ }
25354
26134
  /**
25355
26135
  * Fast update path for data-only series changes.
25356
26136
  *
@@ -25408,18 +26188,32 @@ const _ApexCharts = class _ApexCharts {
25408
26188
  }
25409
26189
  }
25410
26190
  const xyRatios = this.core.xySettings();
26191
+ if (this._zoomPanSelection) this._zoomPanSelection.xyRatios = xyRatios;
25411
26192
  const newAxisScaleSig = JSON.stringify({
25412
26193
  y: (gl.yAxisScale || []).map((s) => s ? s.result : null),
25413
26194
  xMin: gl.minX,
25414
26195
  xMax: gl.maxX
25415
26196
  });
25416
- if (gl.axisCharts && prevAxisScaleSig != null && newAxisScaleSig !== prevAxisScaleSig) {
26197
+ const scaleChanged = gl.axisCharts && prevAxisScaleSig != null && newAxisScaleSig !== prevAxisScaleSig;
26198
+ if (scaleChanged && !this._fastAxisChromeRefresh(xyRatios)) {
26199
+ this._updateStats.full++;
25417
26200
  return this.update().then(() => resolve(this)).catch(reject);
25418
26201
  }
26202
+ if (scaleChanged) {
26203
+ this._updateStats.fastWithAxes++;
26204
+ } else {
26205
+ this._updateStats.fast++;
26206
+ }
25419
26207
  (_a = this.weave) == null ? void 0 : _a.dispatch("afterScales", { pass: "fast", xyRatios });
26208
+ const rr = (
26209
+ /** @type {any} */
26210
+ this.ctx.renderer
26211
+ );
26212
+ const reuseCanvasHost = !!(rr && rr.kind === "canvas" && rr.canRepaintInPlace && rr.canRepaintInPlace());
26213
+ if (reuseCanvasHost) rr._repaintHostInPlace = true;
25420
26214
  const innerEl = w.dom.elGraphical.node;
25421
26215
  const toRemove = innerEl.querySelectorAll(
25422
- ".apexcharts-canvas-series-wrap, .apexcharts-series, .apexcharts-datalabels, .apexcharts-datalabels-background"
26216
+ (reuseCanvasHost ? "" : ".apexcharts-canvas-series-wrap, ") + ".apexcharts-plot-series, .apexcharts-series, .apexcharts-datalabels, .apexcharts-datalabels-background"
25423
26217
  );
25424
26218
  toRemove.forEach(
25425
26219
  (el) => {
@@ -25429,11 +26223,13 @@ const _ApexCharts = class _ApexCharts {
25429
26223
  );
25430
26224
  const elGraph = this.core.plotChartType(w.config.series, xyRatios);
25431
26225
  const gridEl = innerEl.querySelector(".apexcharts-grid");
26226
+ const xaxisEl = innerEl.querySelector(".apexcharts-xaxis");
25432
26227
  const graphs = Array.isArray(elGraph) ? elGraph : [elGraph];
25433
- if (gridEl && w.config.grid.position === "front") {
26228
+ const anchor = gridEl && w.config.grid.position === "front" ? gridEl : xaxisEl;
26229
+ if (anchor) {
25434
26230
  graphs.forEach((g) => {
25435
26231
  const node = g && g.node ? g.node : g;
25436
- if (node) innerEl.insertBefore(node, gridEl);
26232
+ if (node) innerEl.insertBefore(node, anchor);
25437
26233
  });
25438
26234
  } else {
25439
26235
  graphs.forEach((g) => {
@@ -26193,41 +26989,57 @@ const _ApexCharts = class _ApexCharts {
26193
26989
  return this.ctx.drilldown.drillToRoot();
26194
26990
  }
26195
26991
  // ─── Slice write-back stubs ─────────────────────────────────────────────────
26992
+ /**
26993
+ * Copy own DATA properties of a parse-state slice onto a live w.* slice.
26994
+ * Never Object.assign here: several w.* fields (and, historically, snapshot
26995
+ * fields) are lazy accessors, and [[Get]]-ing an accessor while copying
26996
+ * forces its deferred computation (a deep initialSeries clone plus O(n)
26997
+ * stacked-totals passes on every render/update) and can replace the live
26998
+ * accessor with a materialized value for the life of the instance.
26999
+ * @param {any} target
27000
+ * @param {any} slice
27001
+ */
27002
+ static _writeDataProps(target, slice) {
27003
+ for (const key of Object.keys(slice)) {
27004
+ const d = Object.getOwnPropertyDescriptor(slice, key);
27005
+ if (d && "value" in d) target[key] = d.value;
27006
+ }
27007
+ }
26196
27008
  /**
26197
27009
  * @param {Partial<import('./types/internal').SeriesData>} slice
26198
27010
  */
26199
27011
  _writeParsedSeriesData(slice) {
26200
- Object.assign(this.w.seriesData, slice);
27012
+ _ApexCharts._writeDataProps(this.w.seriesData, slice);
26201
27013
  }
26202
27014
  /**
26203
27015
  * @param {Partial<import('./types/internal').RangeData>} slice
26204
27016
  */
26205
27017
  _writeParsedRangeData(slice) {
26206
- Object.assign(this.w.rangeData, slice);
27018
+ _ApexCharts._writeDataProps(this.w.rangeData, slice);
26207
27019
  }
26208
27020
  /**
26209
27021
  * @param {Partial<import('./types/internal').CandleData>} slice
26210
27022
  */
26211
27023
  _writeParsedCandleData(slice) {
26212
- Object.assign(this.w.candleData, slice);
27024
+ _ApexCharts._writeDataProps(this.w.candleData, slice);
26213
27025
  }
26214
27026
  /**
26215
27027
  * @param {Partial<import('./types/internal').LabelData>} slice
26216
27028
  */
26217
27029
  _writeParsedLabelData(slice) {
26218
- Object.assign(this.w.labelData, slice);
27030
+ _ApexCharts._writeDataProps(this.w.labelData, slice);
26219
27031
  }
26220
27032
  /**
26221
27033
  * @param {Partial<import('./types/internal').AxisFlags>} slice
26222
27034
  */
26223
27035
  _writeParsedAxisFlags(slice) {
26224
- Object.assign(this.w.axisFlags, slice);
27036
+ _ApexCharts._writeDataProps(this.w.axisFlags, slice);
26225
27037
  }
26226
27038
  /**
26227
27039
  * @param {Partial<import('./types/internal').LayoutCoords>} slice
26228
27040
  */
26229
27041
  _writeLayoutCoords(slice) {
26230
- Object.assign(this.w.layout, slice);
27042
+ _ApexCharts._writeDataProps(this.w.layout, slice);
26231
27043
  }
26232
27044
  _parentResizeCallback() {
26233
27045
  if (this.w.globals.animationEnded && this.w.config.chart.redrawOnParentResize) {
@@ -28765,7 +29577,6 @@ class ZoomPanSelection extends Toolbar {
28765
29577
  this.xyRatios = xyRatios;
28766
29578
  this.zoomRect = this.graphics.drawRect(0, 0, 0, 0);
28767
29579
  this.selectionRect = this.graphics.drawRect(0, 0, 0, 0);
28768
- this.gridRect = w.dom.baseEl.querySelector(".apexcharts-grid");
28769
29580
  this.constraints = new Box(0, 0, w.layout.gridWidth, w.layout.gridHeight);
28770
29581
  this.zoomRect.node.classList.add("apexcharts-zoom-rect");
28771
29582
  this.selectionRect.node.classList.add("apexcharts-selection-rect");
@@ -28829,14 +29640,12 @@ class ZoomPanSelection extends Toolbar {
28829
29640
  }
28830
29641
  this.selectionRect = null;
28831
29642
  this.zoomRect = null;
28832
- this.gridRect = null;
28833
29643
  }
28834
29644
  /**
28835
29645
  * @param {import('../types/internal').XYRatios} xyRatios
28836
29646
  * @param {any} e
28837
29647
  */
28838
29648
  svgMouseEvents(xyRatios, e) {
28839
- var _a;
28840
29649
  const w = this.w;
28841
29650
  const toolbar = this.ctx.toolbar;
28842
29651
  if (w.interact.momentum && w.interact.momentum.busy) return;
@@ -28867,7 +29676,7 @@ class ZoomPanSelection extends Toolbar {
28867
29676
  this.clientX = e.type === "touchmove" || e.type === "touchstart" ? e.touches[0].clientX : e.type === "touchend" ? e.changedTouches[0].clientX : e.clientX;
28868
29677
  this.clientY = e.type === "touchmove" || e.type === "touchstart" ? e.touches[0].clientY : e.type === "touchend" ? e.changedTouches[0].clientY : e.clientY;
28869
29678
  if (e.type === "mousedown" && e.which === 1 || e.type === "touchstart") {
28870
- const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
29679
+ const gridRectDim = this._gridRect();
28871
29680
  if (!gridRectDim) return;
28872
29681
  this.startX = this.clientX - gridRectDim.left - w.globals.barPadForNumericAxis;
28873
29682
  this.startY = this.clientY - gridRectDim.top;
@@ -28882,7 +29691,7 @@ class ZoomPanSelection extends Toolbar {
28882
29691
  this.panDragging({
28883
29692
  context: this,
28884
29693
  zoomtype,
28885
- xyRatios
29694
+ xyRatios: this.xyRatios
28886
29695
  });
28887
29696
  }
28888
29697
  } else {
@@ -28901,9 +29710,8 @@ class ZoomPanSelection extends Toolbar {
28901
29710
  }
28902
29711
  /** @param {{ zoomtype?: any, isResized?: any }} opts */
28903
29712
  handleMouseUp({ zoomtype, isResized }) {
28904
- var _a;
28905
29713
  const w = this.w;
28906
- const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
29714
+ const gridRectDim = this._gridRect();
28907
29715
  if (gridRectDim && (this.w.interact.mousedown || isResized)) {
28908
29716
  this.endX = this.clientX - gridRectDim.left - w.globals.barPadForNumericAxis;
28909
29717
  this.endY = this.clientY - gridRectDim.top;
@@ -28945,11 +29753,11 @@ class ZoomPanSelection extends Toolbar {
28945
29753
  * @param {any} e
28946
29754
  */
28947
29755
  executeMouseWheelZoom(e) {
28948
- var _a, _b, _c;
29756
+ var _a, _b;
28949
29757
  const w = this.w;
28950
29758
  this.minX = w.axisFlags.isRangeBar ? w.globals.minY : w.globals.minX;
28951
29759
  this.maxX = w.axisFlags.isRangeBar ? w.globals.maxY : w.globals.maxX;
28952
- const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
29760
+ const gridRectDim = this._gridRect();
28953
29761
  if (!gridRectDim) return;
28954
29762
  const mouseX = (e.clientX - gridRectDim.left) / gridRectDim.width;
28955
29763
  const currentMinX = this.minX;
@@ -28970,8 +29778,8 @@ class ZoomPanSelection extends Toolbar {
28970
29778
  newMaxX = currentMaxX + zoomRange / 2;
28971
29779
  }
28972
29780
  if (!w.axisFlags.isRangeBar) {
28973
- const clampMin = (_b = w.globals.dataReducerRawMinX) != null ? _b : w.globals.initialMinX;
28974
- const clampMax = (_c = w.globals.dataReducerRawMaxX) != null ? _c : w.globals.initialMaxX;
29781
+ const clampMin = (_a = w.globals.dataReducerRawMinX) != null ? _a : w.globals.initialMinX;
29782
+ const clampMax = (_b = w.globals.dataReducerRawMaxX) != null ? _b : w.globals.initialMaxX;
28975
29783
  newMinX = Math.max(newMinX, clampMin);
28976
29784
  newMaxX = Math.min(newMaxX, clampMax);
28977
29785
  const minXDiff = w.globals.minXDiff > 0 && isFinite(w.globals.minXDiff) ? w.globals.minXDiff : 0;
@@ -29108,10 +29916,9 @@ class ZoomPanSelection extends Toolbar {
29108
29916
  }
29109
29917
  }
29110
29918
  selectionDrawing({ context, zoomtype }) {
29111
- var _a;
29112
29919
  const w = this.w;
29113
29920
  const me = context;
29114
- const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
29921
+ const gridRectDim = this._gridRect();
29115
29922
  if (!gridRectDim) return;
29116
29923
  const startX = me.startX - 1;
29117
29924
  const startY = me.startY;
@@ -29217,8 +30024,8 @@ class ZoomPanSelection extends Toolbar {
29217
30024
  if ((typeof w.config.chart.events.selection === "function" || linkActive) && w.interact.selectionEnabled) {
29218
30025
  clearTimeout((_a = this.w.globals.selectionResizeTimer) != null ? _a : void 0);
29219
30026
  this.w.globals.selectionResizeTimer = window.setTimeout(() => {
29220
- var _a2, _b;
29221
- const gridRectDim = (_a2 = this.gridRect) == null ? void 0 : _a2.getBoundingClientRect();
30027
+ var _a2;
30028
+ const gridRectDim = this._gridRect();
29222
30029
  if (!gridRectDim) return;
29223
30030
  const selectionRect = selRect.node.getBoundingClientRect();
29224
30031
  let minX, maxX, minY, maxY;
@@ -29252,7 +30059,7 @@ class ZoomPanSelection extends Toolbar {
29252
30059
  if (w.config.chart.brush.enabled && w.config.chart.events.brushScrolled !== void 0) {
29253
30060
  w.config.chart.events.brushScrolled(this.ctx, xyAxis);
29254
30061
  }
29255
- (_b = this.ctx.linkedViews) == null ? void 0 : _b.onSourceSelection(xyAxis.xaxis);
30062
+ (_a2 = this.ctx.linkedViews) == null ? void 0 : _a2.onSourceSelection(xyAxis.xaxis);
29256
30063
  }, timerInterval);
29257
30064
  }
29258
30065
  }
@@ -29264,7 +30071,8 @@ class ZoomPanSelection extends Toolbar {
29264
30071
  const xyRatios = this.xyRatios;
29265
30072
  const toolbar = this.ctx.toolbar;
29266
30073
  const selRect = w.interact.zoomEnabled ? me.zoomRect.node.getBoundingClientRect() : me.selectionRect.node.getBoundingClientRect();
29267
- const gridRectDim = me.gridRect.getBoundingClientRect();
30074
+ const gridRectDim = me._gridRect();
30075
+ if (!gridRectDim) return;
29268
30076
  const localStartX = selRect.left - gridRectDim.left - w.globals.barPadForNumericAxis;
29269
30077
  const localEndX = selRect.right - gridRectDim.left - w.globals.barPadForNumericAxis;
29270
30078
  const localStartY = selRect.top - gridRectDim.top;
@@ -29522,8 +30330,11 @@ class ZoomPanSelection extends Toolbar {
29522
30330
  const w = this.w;
29523
30331
  return w.axisFlags.isRangeBar ? { min: w.globals.minY, max: w.globals.maxY } : { min: w.globals.minX, max: w.globals.maxX };
29524
30332
  }
29525
- /** Live grid rect from the current DOM (this.gridRect goes stale/null after
29526
- * the re-render a gesture frame triggers). */
30333
+ /** Live grid rect from the current DOM. Never cache the grid node on the
30334
+ * instance: a full render replaces this whole instance, but the fast update
30335
+ * path (fastUpdate/_fastAxisChromeRefresh) keeps the instance while swapping
30336
+ * the grid node, and a cached node would go stale (detached nodes report an
30337
+ * all-zero bounding rect, silently corrupting selection geometry). */
29527
30338
  _gridRect() {
29528
30339
  const baseEl = this.w.dom.baseEl;
29529
30340
  const grid = baseEl && baseEl.querySelector(".apexcharts-grid");
@@ -34429,6 +35240,30 @@ class CanvasMarkerRef {
34429
35240
  return NOOP_RUNNER;
34430
35241
  }
34431
35242
  }
35243
+ const SHARED_RECT_REF = {
35244
+ __isCanvasMark: true,
35245
+ node: SHARED_MARKER_NODE,
35246
+ /** @returns {any} */
35247
+ attr() {
35248
+ return SHARED_RECT_REF;
35249
+ },
35250
+ add() {
35251
+ return SHARED_RECT_REF;
35252
+ },
35253
+ addTo() {
35254
+ return SHARED_RECT_REF;
35255
+ },
35256
+ remove() {
35257
+ return SHARED_RECT_REF;
35258
+ },
35259
+ /** @returns {any} */
35260
+ css() {
35261
+ return SHARED_RECT_REF;
35262
+ },
35263
+ animate() {
35264
+ return NOOP_RUNNER;
35265
+ }
35266
+ };
34432
35267
  class CanvasMark {
34433
35268
  /** @param {any} cmd */
34434
35269
  constructor(cmd) {
@@ -34556,6 +35391,16 @@ class CanvasGraphics {
34556
35391
  this._msi = new Int32Array(16);
34557
35392
  this._mn = 0;
34558
35393
  this._mcap = 16;
35394
+ this._crx = new Float64Array(16);
35395
+ this._cry = new Float64Array(16);
35396
+ this._crw = new Float64Array(16);
35397
+ this._crh = new Float64Array(16);
35398
+ this._crstyle = new Int32Array(16);
35399
+ this._crsi = new Int32Array(16);
35400
+ this._crdi = new Int32Array(16);
35401
+ this._crn = 0;
35402
+ this._crcap = 16;
35403
+ this._cellRadius = 0;
34559
35404
  this._styles = [];
34560
35405
  this._styleMap = /* @__PURE__ */ new Map();
34561
35406
  this._lf = NEVER;
@@ -34568,6 +35413,12 @@ class CanvasGraphics {
34568
35413
  this._lofFill = NEVER;
34569
35414
  this._lofBase = -1;
34570
35415
  this._lofId = -1;
35416
+ this._rlf = NEVER;
35417
+ this._rls = NEVER;
35418
+ this._rlsw = NEVER;
35419
+ this._rlfo = NEVER;
35420
+ this._rlso = NEVER;
35421
+ this._rlid = -1;
34571
35422
  }
34572
35423
  _resetStyleCache() {
34573
35424
  this._lf = NEVER;
@@ -34580,6 +35431,12 @@ class CanvasGraphics {
34580
35431
  this._lofFill = NEVER;
34581
35432
  this._lofBase = -1;
34582
35433
  this._lofId = -1;
35434
+ this._rlf = NEVER;
35435
+ this._rls = NEVER;
35436
+ this._rlsw = NEVER;
35437
+ this._rlfo = NEVER;
35438
+ this._rlso = NEVER;
35439
+ this._rlid = -1;
34583
35440
  }
34584
35441
  /** Start a fresh scene (columnar marker store + object-command list). */
34585
35442
  reset() {
@@ -34596,6 +35453,46 @@ class CanvasGraphics {
34596
35453
  }
34597
35454
  cap = Math.ceil(cap * 1.15) + 16;
34598
35455
  if (cap > this._mcap) this._allocMarkers(cap);
35456
+ this._crn = 0;
35457
+ this._cellRadius = 0;
35458
+ if (cap > this._crcap) this._allocRects(cap);
35459
+ }
35460
+ /** @param {number} cap */
35461
+ _allocRects(cap) {
35462
+ this._crcap = cap;
35463
+ this._crx = new Float64Array(cap);
35464
+ this._cry = new Float64Array(cap);
35465
+ this._crw = new Float64Array(cap);
35466
+ this._crh = new Float64Array(cap);
35467
+ this._crstyle = new Int32Array(cap);
35468
+ this._crsi = new Int32Array(cap);
35469
+ this._crdi = new Int32Array(cap);
35470
+ }
35471
+ /** Grow the rect columns (rare: capacity estimate was low). */
35472
+ _growRects() {
35473
+ const cap = this._crcap * 2;
35474
+ const nx = new Float64Array(cap);
35475
+ nx.set(this._crx);
35476
+ this._crx = nx;
35477
+ const ny = new Float64Array(cap);
35478
+ ny.set(this._cry);
35479
+ this._cry = ny;
35480
+ const nw = new Float64Array(cap);
35481
+ nw.set(this._crw);
35482
+ this._crw = nw;
35483
+ const nh = new Float64Array(cap);
35484
+ nh.set(this._crh);
35485
+ this._crh = nh;
35486
+ const nst = new Int32Array(cap);
35487
+ nst.set(this._crstyle);
35488
+ this._crstyle = nst;
35489
+ const nsi = new Int32Array(cap);
35490
+ nsi.set(this._crsi);
35491
+ this._crsi = nsi;
35492
+ const ndi = new Int32Array(cap);
35493
+ ndi.set(this._crdi);
35494
+ this._crdi = ndi;
35495
+ this._crcap = cap;
34599
35496
  }
34600
35497
  /** @param {number} cap */
34601
35498
  _allocMarkers(cap) {
@@ -34705,6 +35602,65 @@ class CanvasGraphics {
34705
35602
  shapeName(id) {
34706
35603
  return SHAPE_NAME[id] || "circle";
34707
35604
  }
35605
+ // ── columnar rect cell (heatmap): parallel unboxed arrays, no per-cell object ──
35606
+ /**
35607
+ * Record a heatmap-style cell (a filled, optionally stroked rect). Geometry
35608
+ * and style are captured up front into the columns; the returned handle is a
35609
+ * shared no-op (the emit site sets nothing back on it in canvas mode).
35610
+ * @param {number} x @param {number} y @param {number} w @param {number} h
35611
+ * @param {any} opts {fill, fillOpacity, stroke, strokeWidth, radius, seriesIndex, dataPointIndex}
35612
+ * @returns {any}
35613
+ */
35614
+ drawRectCell(x, y, w, h, opts = {}) {
35615
+ const styleId = this._rectStyleId(opts);
35616
+ if (this._crn >= this._crcap) this._growRects();
35617
+ const i = this._crn++;
35618
+ this._crx[i] = x || 0;
35619
+ this._cry[i] = y || 0;
35620
+ this._crw[i] = w > 0 ? w : 0;
35621
+ this._crh[i] = h > 0 ? h : 0;
35622
+ this._crstyle[i] = styleId;
35623
+ this._crsi[i] = opts.seriesIndex == null ? -1 : opts.seriesIndex;
35624
+ this._crdi[i] = opts.dataPointIndex == null ? -1 : opts.dataPointIndex;
35625
+ if (opts.radius) this._cellRadius = opts.radius;
35626
+ return SHARED_RECT_REF;
35627
+ }
35628
+ /**
35629
+ * Resolve (and dedupe) a rect-cell style → shared-palette id. A last-style
35630
+ * cache keeps the Map/string work off the path for runs of same-style cells.
35631
+ * @param {any} opts
35632
+ * @returns {number}
35633
+ */
35634
+ _rectStyleId(opts) {
35635
+ const fill = opts.fill;
35636
+ const stroke = opts.stroke;
35637
+ const sw = opts.strokeWidth;
35638
+ const fo = opts.fillOpacity;
35639
+ const so = opts.strokeOpacity;
35640
+ if (fill === this._rlf && stroke === this._rls && sw === this._rlsw && fo === this._rlfo && so === this._rlso) {
35641
+ return this._rlid;
35642
+ }
35643
+ const id = this._internStyle(fill, stroke, sw, 0, fo, so);
35644
+ this._rlf = fill;
35645
+ this._rls = stroke;
35646
+ this._rlsw = sw;
35647
+ this._rlfo = fo;
35648
+ this._rlso = so;
35649
+ this._rlid = id;
35650
+ return id;
35651
+ }
35652
+ /** @returns {number} number of recorded rect cells */
35653
+ rectCount() {
35654
+ return this._crn;
35655
+ }
35656
+ /** @param {number} i @returns {any} the style object for a rect cell */
35657
+ rectStyle(i) {
35658
+ return this._styles[this._crstyle[i]];
35659
+ }
35660
+ /** @param {number} i @returns {number} series (realIndex) of a cell, -1 if none */
35661
+ rectSeries(i) {
35662
+ return this._crsi[i];
35663
+ }
34708
35664
  /**
34709
35665
  * @param {string} tag
34710
35666
  * @param {number} z
@@ -35020,9 +35976,97 @@ class CanvasCompositor {
35020
35976
  this._paintOne(ctx, c);
35021
35977
  }
35022
35978
  }
35979
+ this._paintRects(ctx, shim2);
35023
35980
  this._paintMarkers(ctx, shim2);
35024
35981
  this._alpha = 1;
35025
35982
  }
35983
+ /**
35984
+ * Paint the columnar rect cells (heatmap) as STYLE BATCHES: one fill/stroke
35985
+ * state application per run of consecutive same-style cells, then a fast
35986
+ * fillRect (or a roundRect path when the shared corner radius is non-zero)
35987
+ * per cell. Clipped to the plot rect so cells never bleed into the canvas
35988
+ * margin (mirrors the SVG gridRectMask). Per-cell globalAlpha carries the
35989
+ * hover/legend dim multiplier when a dim spec is active.
35990
+ * @param {any} ctx
35991
+ * @param {any} shim
35992
+ */
35993
+ _paintRects(ctx, shim2) {
35994
+ const n = shim2.rectCount ? shim2.rectCount() : 0;
35995
+ if (!n) return;
35996
+ const rx = shim2._crx;
35997
+ const ry = shim2._cry;
35998
+ const rw = shim2._crw;
35999
+ const rh = shim2._crh;
36000
+ const rstyle = shim2._crstyle;
36001
+ const radius = shim2._cellRadius || 0;
36002
+ const cx = (
36003
+ /** @type {any} */
36004
+ ctx
36005
+ );
36006
+ const useRound = radius > 0 && typeof cx.roundRect === "function";
36007
+ const dimming = !!this._dim;
36008
+ const gw = Math.max(0, this.w.layout.gridWidth || 0);
36009
+ const gh = Math.max(0, this.w.layout.gridHeight || 0);
36010
+ ctx.save();
36011
+ ctx.beginPath();
36012
+ ctx.rect(0, 0, gw, gh);
36013
+ ctx.clip();
36014
+ let i = 0;
36015
+ while (i < n) {
36016
+ const styleId = rstyle[i];
36017
+ const style = shim2.rectStyle(i);
36018
+ if (!style) {
36019
+ i++;
36020
+ continue;
36021
+ }
36022
+ const fill = style.fill;
36023
+ const doFill = fill && fill !== "none" && !(typeof fill === "string" && fill.indexOf("url(") === 0);
36024
+ const stroke = style.stroke;
36025
+ const sw = style.strokeWidth == null ? 0 : Number(style.strokeWidth);
36026
+ const doStroke = stroke && stroke !== "none" && sw > 0 && !(typeof stroke === "string" && stroke.indexOf("url(") === 0);
36027
+ if (doFill) ctx.fillStyle = fill;
36028
+ if (doStroke) {
36029
+ ctx.strokeStyle = stroke;
36030
+ ctx.lineWidth = sw;
36031
+ ctx.setLineDash([]);
36032
+ }
36033
+ const baseFillA = style.fillOpacity == null ? 1 : Number(style.fillOpacity);
36034
+ const baseStrokeA = style.strokeOpacity == null ? 1 : Number(style.strokeOpacity);
36035
+ let j = i;
36036
+ while (j < n && rstyle[j] === styleId) {
36037
+ const w = rw[j];
36038
+ const h = rh[j];
36039
+ if (w > 0 && h > 0) {
36040
+ const f = dimming ? this._seriesAlpha(shim2.rectSeries(j)) : 1;
36041
+ if (useRound) {
36042
+ ctx.beginPath();
36043
+ cx.roundRect(rx[j], ry[j], w, h, radius);
36044
+ if (doFill) {
36045
+ ctx.globalAlpha = baseFillA * f;
36046
+ ctx.fill();
36047
+ }
36048
+ if (doStroke) {
36049
+ ctx.globalAlpha = baseStrokeA * f;
36050
+ ctx.stroke();
36051
+ }
36052
+ } else {
36053
+ if (doFill) {
36054
+ ctx.globalAlpha = baseFillA * f;
36055
+ ctx.fillRect(rx[j], ry[j], w, h);
36056
+ }
36057
+ if (doStroke) {
36058
+ ctx.globalAlpha = baseStrokeA * f;
36059
+ ctx.strokeRect(rx[j], ry[j], w, h);
36060
+ }
36061
+ }
36062
+ }
36063
+ j++;
36064
+ }
36065
+ i = j;
36066
+ }
36067
+ ctx.globalAlpha = 1;
36068
+ ctx.restore();
36069
+ }
35026
36070
  /**
35027
36071
  * Reusable unit Path2D for a (shape, size): the shape's geometry built at the
35028
36072
  * origin once, then translated per marker via setTransform. Returns null when
@@ -35336,6 +36380,20 @@ class CanvasRenderer {
35336
36380
  clear() {
35337
36381
  this._compositor.clear();
35338
36382
  }
36383
+ /**
36384
+ * Whether the existing <canvas> host can be repainted in place (it exists
36385
+ * and is still mounted). Used by the data-only fast update path to skip
36386
+ * recreating the foreignObject + backing store on every tick.
36387
+ * @returns {boolean}
36388
+ */
36389
+ canRepaintInPlace() {
36390
+ const host = this._compositor.getHost();
36391
+ return !!(host && host.node && host.node.isConnected);
36392
+ }
36393
+ /** Repaint the freshly recorded display list into the EXISTING canvas. */
36394
+ repaintInPlace() {
36395
+ this._compositor.paint(this._g.displayList(), this._g);
36396
+ }
35339
36397
  // ── emit primitives (delegate to the display-list shim) ──
35340
36398
  /** @param {any} attrs */
35341
36399
  group(attrs) {
@@ -35359,6 +36417,16 @@ class CanvasRenderer {
35359
36417
  this._g.drawRect(...args)
35360
36418
  );
35361
36419
  }
36420
+ /**
36421
+ * Columnar heatmap-cell rect (dense same-shape rects): recorded into typed
36422
+ * arrays, painted as style batches. Distinct from drawRect (object command)
36423
+ * so 100k cells don't allocate 100k retained commands.
36424
+ * @param {number} x @param {number} y @param {number} w @param {number} h
36425
+ * @param {any} opts
36426
+ */
36427
+ drawRectCell(x, y, w, h, opts) {
36428
+ return this._g.drawRectCell(x, y, w, h, opts);
36429
+ }
35362
36430
  /**
35363
36431
  * @param {number} r
35364
36432
  * @param {any} attrs
@@ -35388,14 +36456,44 @@ class CanvasRenderer {
35388
36456
  return feature === "solidFill" || feature === "dashArray";
35389
36457
  }
35390
36458
  // ── interaction ──
35391
- // Shared tooltip/zoom/click resolve via coordinate lookup (pointsArray), so
35392
- // there is no per-mark hit surface to query; hitTest stays a no-op unless a
35393
- // future per-point feature needs it.
35394
- /**
35395
- * @param {number} _px
35396
- * @param {number} _py
35397
- */
35398
- hitTest(_px, _py) {
36459
+ // Line/area/bar/scatter tooltips resolve via coordinate lookup (pointsArray),
36460
+ // so those need no per-mark query. Heatmap cells, however, are hovered by
36461
+ // point (the SVG path hit-tests the <rect> under the cursor); with cells on
36462
+ // canvas there is no node, so hitTest resolves the columnar rect store.
36463
+ /**
36464
+ * Find the cell under a plot-local point (0,0 = plot origin, the same space
36465
+ * as the recorded cell geometry). Reverse scan so a later-painted cell wins
36466
+ * when cells overlap (continuous-x edges). A linear scan stays well under a
36467
+ * frame even at 100k cells (~100k integer compares). Returns the cell's
36468
+ * series/dataPoint index plus its geometry for tooltip positioning, or null
36469
+ * when the point is off every cell.
36470
+ * @param {number} px
36471
+ * @param {number} py
36472
+ * @returns {({seriesIndex:number,dataPointIndex:number,x:number,y:number,width:number,height:number})|null}
36473
+ */
36474
+ hitTest(px, py) {
36475
+ const g = this._g;
36476
+ const n = g.rectCount ? g.rectCount() : 0;
36477
+ if (!n) return null;
36478
+ const rx = g._crx;
36479
+ const ry = g._cry;
36480
+ const rw = g._crw;
36481
+ const rh = g._crh;
36482
+ for (let k = n - 1; k >= 0; k--) {
36483
+ const w = rw[k];
36484
+ const h = rh[k];
36485
+ if (w <= 0 || h <= 0) continue;
36486
+ if (px >= rx[k] && px < rx[k] + w && py >= ry[k] && py < ry[k] + h) {
36487
+ return {
36488
+ seriesIndex: g._crsi[k],
36489
+ dataPointIndex: g._crdi[k],
36490
+ x: rx[k],
36491
+ y: ry[k],
36492
+ width: w,
36493
+ height: h
36494
+ };
36495
+ }
36496
+ }
35399
36497
  return null;
35400
36498
  }
35401
36499
  /**
@@ -39256,6 +40354,7 @@ class BarDataLabels {
39256
40354
  barWidth,
39257
40355
  dataLabelsConfig
39258
40356
  }) {
40357
+ var _a, _b;
39259
40358
  const w = this.w;
39260
40359
  let rotate = "rotate(0)";
39261
40360
  if (w.config.plotOptions.bar.dataLabels.orientation === "vertical")
@@ -39270,6 +40369,17 @@ class BarDataLabels {
39270
40369
  class: "apexcharts-data-labels",
39271
40370
  transform: rotate
39272
40371
  });
40372
+ const dlCfg = w.config.dataLabels;
40373
+ if (((_a = dlCfg.animate) == null ? void 0 : _a.enabled) || ((_b = dlCfg.countUp) == null ? void 0 : _b.enabled)) {
40374
+ elDataLabelsWrap.node.setAttribute(
40375
+ "data:dlKey",
40376
+ `${i}::${datumKey(w, i, j)}`
40377
+ );
40378
+ elDataLabelsWrap.node.setAttribute("data:dlJ", String(j));
40379
+ if (typeof val === "number" && isFinite(val)) {
40380
+ elDataLabelsWrap.node.setAttribute("data:dlVal", String(val));
40381
+ }
40382
+ }
39273
40383
  let text = "";
39274
40384
  if (typeof val !== "undefined") {
39275
40385
  text = formatter(val, __spreadProps(__spreadValues({}, w), {
@@ -40227,6 +41337,7 @@ class Bar {
40227
41337
  this.pathArr = [];
40228
41338
  this._prevKeyed = null;
40229
41339
  this._ltCache = null;
41340
+ this._layoutShiftCache = null;
40230
41341
  this.series = [];
40231
41342
  this.elSeries = null;
40232
41343
  this.visibleI = 0;
@@ -40255,7 +41366,7 @@ class Bar {
40255
41366
  * @return {Element} element which is supplied to parent chart draw method for appending
40256
41367
  **/
40257
41368
  draw(series, seriesIndex) {
40258
- var _a, _b;
41369
+ var _a, _b, _c;
40259
41370
  const w = this.w;
40260
41371
  const graphics = new Graphics(this.w);
40261
41372
  const coreUtils = new CoreUtils(this.w);
@@ -40329,8 +41440,10 @@ class Bar {
40329
41440
  el: elDataLabelsWrap.node,
40330
41441
  // On a layout-changing update the labels must stay hidden through the
40331
41442
  // reflow morph (the updateOptions flow otherwise reveals them at
40332
- // frame 0, where they float over sliding bars).
40333
- holdUntilComplete: this.isLengthTransition(realIndex)
41443
+ // frame 0, where they float over sliding bars). When dataLabels.animate
41444
+ // is on the labels instead RIDE the morph (see DataLabelTransition), so
41445
+ // keep them visible: holding would hide the very motion we want to show.
41446
+ holdUntilComplete: !((_a = w.config.dataLabels.animate) == null ? void 0 : _a.enabled) && this.isLengthTransition(realIndex)
40334
41447
  });
40335
41448
  elDataLabelsWrap.node.classList.add("apexcharts-element-hidden");
40336
41449
  const elGoalsMarkers = graphics.group({
@@ -40383,9 +41496,9 @@ class Bar {
40383
41496
  j,
40384
41497
  realIndex
40385
41498
  );
40386
- if (this.isFunnel && !this.isPyramid && this.barOptions.isFunnel3d && ((_a = w.config.plotOptions.funnel) == null ? void 0 : _a.shape) !== "trapezoid" && this.pathArr.length && j > 0) {
41499
+ if (this.isFunnel && !this.isPyramid && this.barOptions.isFunnel3d && ((_b = w.config.plotOptions.funnel) == null ? void 0 : _b.shape) !== "trapezoid" && this.pathArr.length && j > 0) {
40387
41500
  const barShadow = this.barHelpers.drawBarShadow({
40388
- color: typeof pathFill.color === "string" && ((_b = pathFill.color) == null ? void 0 : _b.indexOf("url")) === -1 ? pathFill.color : Utils$1.hexToRgba(w.globals.colors[i]),
41501
+ color: typeof pathFill.color === "string" && ((_c = pathFill.color) == null ? void 0 : _c.indexOf("url")) === -1 ? pathFill.color : Utils$1.hexToRgba(w.globals.colors[i]),
40389
41502
  prevPaths: this.pathArr[this.pathArr.length - 1],
40390
41503
  currPaths: paths,
40391
41504
  realIndex,
@@ -40557,7 +41670,7 @@ class Bar {
40557
41670
  }
40558
41671
  const animCfg = w.config.chart.animations;
40559
41672
  const gradCfg = animCfg.animateGradually;
40560
- const staggerEnabled = gradCfg && gradCfg.enabled !== false && !(w.globals.dataChanged && this.isLengthTransition(realIndex));
41673
+ const staggerEnabled = gradCfg && gradCfg.enabled !== false && !(w.globals.dataChanged && this.isLayoutShift(realIndex));
40561
41674
  let delay = 0;
40562
41675
  if (staggerEnabled) {
40563
41676
  const totalBars = w.globals.dataPoints || 1;
@@ -40971,6 +42084,26 @@ class Bar {
40971
42084
  this._ltCache[realIndex] = result;
40972
42085
  return result;
40973
42086
  }
42087
+ /**
42088
+ * Whether this update moves survivors to new slots: a length change
42089
+ * (enter/exit, via isLengthTransition) OR a pure reorder (a "bar chart race"
42090
+ * swap, same datum set in a new order). Used to drop the per-bar stagger so
42091
+ * all bars slide on one shared clock, staying locked to the axis/data labels.
42092
+ * Broader than isLengthTransition, which is deliberately enter/exit-only
42093
+ * (exit ghosts / baseline enters must not fire on a plain reorder).
42094
+ * @param {number} realIndex
42095
+ */
42096
+ isLayoutShift(realIndex) {
42097
+ if (this.isLengthTransition(realIndex)) return true;
42098
+ if (!this._layoutShiftCache) this._layoutShiftCache = {};
42099
+ if (this._layoutShiftCache[realIndex] !== void 0) {
42100
+ return this._layoutShiftCache[realIndex];
42101
+ }
42102
+ const sj = seriesJoin(this.w, realIndex, true, true);
42103
+ const result = !!(sj && sj.join.changed);
42104
+ this._layoutShiftCache[realIndex] = result;
42105
+ return result;
42106
+ }
40974
42107
  /**
40975
42108
  * Resolve `pathFrom` for a bar on data update, joining old and new datums
40976
42109
  * by KEY (category label / x value) so survivors keep their identity across
@@ -42832,14 +43965,24 @@ class HeatMap {
42832
43965
  * @param {any[]} series
42833
43966
  */
42834
43967
  draw(series) {
43968
+ var _a, _b;
42835
43969
  const w = this.w;
42836
43970
  const graphics = new Graphics(this.w, this.ctx);
43971
+ const emit = seriesEmitter(this.ctx, graphics);
43972
+ const useCanvas = emit !== graphics && typeof emit.drawRectCell === "function";
42837
43973
  const ret = graphics.group({
42838
43974
  class: "apexcharts-heatmap"
42839
43975
  });
42840
43976
  ret.attr("clip-path", `url(#gridRectMask${w.globals.cuid})`);
42841
43977
  const xDivision = w.layout.gridWidth / w.globals.dataPoints;
42842
43978
  const yDivision = w.layout.gridHeight / w.seriesData.series.length;
43979
+ const isContinuousX = (w.config.xaxis.type === "numeric" || w.config.xaxis.type === "datetime") && w.axisFlags.isXNumeric && this.xRatio > 0;
43980
+ let binPx = xDivision;
43981
+ if (isContinuousX) {
43982
+ const diff = w.globals.minXDiff;
43983
+ binPx = Number.isFinite(diff) && diff > 0 ? diff / this.xRatio : xDivision;
43984
+ }
43985
+ const cellFillOpacity = Array.isArray(w.config.fill.opacity) ? (_a = w.config.fill.opacity[0]) != null ? _a : 1 : (_b = w.config.fill.opacity) != null ? _b : 1;
42843
43986
  let y1 = 0;
42844
43987
  let rev = false;
42845
43988
  this.negRange = this.helpers.checkColorRange();
@@ -42856,7 +43999,9 @@ class HeatMap {
42856
43999
  "data:realIndex": i
42857
44000
  });
42858
44001
  Series.addCollapsedClassToSeries(this.w, elSeries, i);
42859
- graphics.setupEventDelegation(elSeries, ".apexcharts-heatmap-rect");
44002
+ if (!useCanvas) {
44003
+ graphics.setupEventDelegation(elSeries, ".apexcharts-heatmap-rect");
44004
+ }
42860
44005
  if (w.config.chart.dropShadow.enabled) {
42861
44006
  const shadow = w.config.chart.dropShadow;
42862
44007
  const filters = new Filters(this.w);
@@ -42866,13 +44011,22 @@ class HeatMap {
42866
44011
  const shadeIntensity = w.config.plotOptions.heatmap.shadeIntensity;
42867
44012
  let j = 0;
42868
44013
  for (let dIndex = 0; dIndex < w.globals.dataPoints; dIndex++) {
42869
- if (w.seriesData.seriesX.length && !w.globals.allSeriesHasEqualX) {
44014
+ if (!isContinuousX && w.seriesData.seriesX.length && !w.globals.allSeriesHasEqualX) {
42870
44015
  if (w.globals.minX + w.globals.minXDiff * dIndex < w.seriesData.seriesX[i][j]) {
42871
44016
  x1 = x1 + xDivision;
42872
44017
  continue;
42873
44018
  }
42874
44019
  }
42875
44020
  if (j >= heatSeries[i].length) break;
44021
+ const cellW = isContinuousX ? binPx : xDivision;
44022
+ if (isContinuousX) {
44023
+ const xVal = w.seriesData.seriesX[i] ? w.seriesData.seriesX[i][j] : null;
44024
+ if (xVal == null || xVal !== xVal) {
44025
+ j++;
44026
+ continue;
44027
+ }
44028
+ x1 = (xVal - w.globals.minX) / this.xRatio - binPx / 2;
44029
+ }
42876
44030
  const heatColor = this.helpers.getShadeColor(
42877
44031
  w.config.chart.type,
42878
44032
  i,
@@ -42891,47 +44045,60 @@ class HeatMap {
42891
44045
  w.globals.hasNegs ? heatColorProps.percent < 0 ? 1 - (1 + heatColorProps.percent / 100) : shadeIntensity + heatColorProps.percent / 100 : heatColorProps.percent / 100
42892
44046
  ),
42893
44047
  patternID: Utils$1.randomId(),
42894
- width: w.config.fill.image.width ? w.config.fill.image.width : xDivision,
44048
+ width: w.config.fill.image.width ? w.config.fill.image.width : cellW,
42895
44049
  height: w.config.fill.image.height ? w.config.fill.image.height : yDivision
42896
44050
  });
42897
44051
  }
42898
44052
  const radius = this.rectRadius;
42899
- const rect = graphics.drawRect(x1, y1, xDivision, yDivision, radius);
42900
- rect.attr({
42901
- cx: x1,
42902
- cy: y1
42903
- });
42904
- rect.node.classList.add("apexcharts-heatmap-rect");
42905
- elSeries.add(rect);
42906
- rect.attr({
42907
- fill: color,
42908
- i,
42909
- index: i,
42910
- j,
42911
- val: series[i][j],
42912
- "stroke-width": this.strokeWidth,
42913
- stroke: w.config.plotOptions.heatmap.useFillColorAsStroke ? color : w.globals.stroke.colors[0],
42914
- color
42915
- });
42916
- if (w.config.chart.animations.enabled && !w.globals.dataChanged) {
42917
- let speed = 1;
42918
- if (!w.globals.resized) {
42919
- speed = w.config.chart.animations.speed;
42920
- }
42921
- this.animateHeatMap(rect, x1, y1, xDivision, yDivision, speed, i, j);
42922
- }
42923
- if (w.globals.dataChanged) {
42924
- let speed = 1;
42925
- if (this.dynamicAnim.enabled && w.globals.shouldAnimate) {
42926
- speed = this.dynamicAnim.speed;
42927
- let colorFrom = w.globals.previousPaths[i] && w.globals.previousPaths[i][j] && w.globals.previousPaths[i][j].color;
42928
- if (!colorFrom) colorFrom = "rgba(255, 255, 255, 0)";
42929
- this.animateHeatColor(
42930
- rect,
42931
- Utils$1.isColorHex(colorFrom) ? colorFrom : Utils$1.rgb2hex(colorFrom),
42932
- Utils$1.isColorHex(color) ? color : Utils$1.rgb2hex(color),
42933
- speed
42934
- );
44053
+ const stroke = w.config.plotOptions.heatmap.useFillColorAsStroke ? color : w.globals.stroke.colors[0];
44054
+ if (useCanvas) {
44055
+ emit.drawRectCell(x1, y1, cellW, yDivision, {
44056
+ fill: color,
44057
+ fillOpacity: cellFillOpacity,
44058
+ stroke,
44059
+ strokeWidth: this.strokeWidth,
44060
+ radius,
44061
+ seriesIndex: i,
44062
+ dataPointIndex: j
44063
+ });
44064
+ } else {
44065
+ const rect = graphics.drawRect(x1, y1, cellW, yDivision, radius);
44066
+ rect.attr({
44067
+ cx: x1,
44068
+ cy: y1
44069
+ });
44070
+ rect.node.classList.add("apexcharts-heatmap-rect");
44071
+ elSeries.add(rect);
44072
+ rect.attr({
44073
+ fill: color,
44074
+ i,
44075
+ index: i,
44076
+ j,
44077
+ val: series[i][j],
44078
+ "stroke-width": this.strokeWidth,
44079
+ stroke,
44080
+ color
44081
+ });
44082
+ if (w.config.chart.animations.enabled && !w.globals.dataChanged) {
44083
+ let speed = 1;
44084
+ if (!w.globals.resized) {
44085
+ speed = w.config.chart.animations.speed;
44086
+ }
44087
+ this.animateHeatMap(rect, x1, y1, cellW, yDivision, speed, i, j);
44088
+ }
44089
+ if (w.globals.dataChanged) {
44090
+ let speed = 1;
44091
+ if (this.dynamicAnim.enabled && w.globals.shouldAnimate) {
44092
+ speed = this.dynamicAnim.speed;
44093
+ let colorFrom = w.globals.previousPaths[i] && w.globals.previousPaths[i][j] && w.globals.previousPaths[i][j].color;
44094
+ if (!colorFrom) colorFrom = "rgba(255, 255, 255, 0)";
44095
+ this.animateHeatColor(
44096
+ rect,
44097
+ Utils$1.isColorHex(colorFrom) ? colorFrom : Utils$1.rgb2hex(colorFrom),
44098
+ Utils$1.isColorHex(color) ? color : Utils$1.rgb2hex(color),
44099
+ speed
44100
+ );
44101
+ }
42935
44102
  }
42936
44103
  }
42937
44104
  const formatter = w.config.dataLabels.formatter;
@@ -42943,7 +44110,7 @@ class HeatMap {
42943
44110
  });
42944
44111
  const dataLabels = this.helpers.calculateDataLabels({
42945
44112
  text: formattedText,
42946
- x: x1 + xDivision / 2,
44113
+ x: x1 + cellW / 2,
42947
44114
  y: y1 + yDivision / 2,
42948
44115
  i,
42949
44116
  j,
@@ -42953,7 +44120,7 @@ class HeatMap {
42953
44120
  if (dataLabels !== null) {
42954
44121
  elSeries.add(dataLabels);
42955
44122
  }
42956
- x1 = x1 + xDivision;
44123
+ if (!isContinuousX) x1 = x1 + xDivision;
42957
44124
  j++;
42958
44125
  }
42959
44126
  y1 = y1 + yDivision;
@@ -43949,7 +45116,7 @@ class Line {
43949
45116
  let { pathFromLine, pathFromArea } = pathsFrom;
43950
45117
  const r = this.ctx && this.ctx.renderer;
43951
45118
  const canvasMode = !!(r && r.kind && r.kind !== "svg");
43952
- const buildStrings = !canvasMode || w.globals.dataChanged;
45119
+ const buildStrings = !canvasMode || w.globals.dataChanged && !!w.globals.prevStreamFrame;
43953
45120
  const nxs = canvasMode ? new Float64Array(n) : null;
43954
45121
  const nys = canvasMode ? new Float64Array(n) : null;
43955
45122
  if (nxs && nys) {