ooxml-core 1.17.0 → 1.19.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 (137) hide show
  1. package/dist/{PptxHandler-K7GMS2ST.mjs → PptxHandler-5GBBVJCR.mjs} +2 -2
  2. package/dist/{PptxHandler-L3JPWOBN.mjs → PptxHandler-H43MAMTO.mjs} +1 -1
  3. package/dist/{PptxHandler-U6EFO73T.cjs → PptxHandler-ZHPGBSAF.cjs} +2 -2
  4. package/dist/{PresentationBuilder-XC3F3OPY.mjs → PresentationBuilder-7ZSUKCX5.mjs} +1 -1
  5. package/dist/{PresentationBuilder-OK526SZ4.mjs → PresentationBuilder-IJW42L3R.mjs} +2 -2
  6. package/dist/{PresentationBuilder-LUR6LGHU.cjs → PresentationBuilder-O4H4MMWB.cjs} +4 -4
  7. package/dist/automation/index.cjs +5198 -3235
  8. package/dist/automation/index.mjs +5198 -3235
  9. package/dist/chart/axis-range-auto.d.ts +10 -0
  10. package/dist/chart/axis-range-auto.d.ts.map +1 -0
  11. package/dist/chart/axis-range-types.d.ts +27 -0
  12. package/dist/chart/axis-range-types.d.ts.map +1 -0
  13. package/dist/chart/axis-range.d.ts +37 -0
  14. package/dist/chart/axis-range.d.ts.map +1 -0
  15. package/dist/chart/axis-ticks.d.ts +8 -0
  16. package/dist/chart/axis-ticks.d.ts.map +1 -0
  17. package/dist/chart/data-label-text.d.ts +70 -0
  18. package/dist/chart/data-label-text.d.ts.map +1 -0
  19. package/dist/chart/formatting-nodes.d.ts +6 -0
  20. package/dist/chart/formatting-nodes.d.ts.map +1 -1
  21. package/dist/chart/index.cjs +1536 -571
  22. package/dist/chart/index.d.ts +7 -0
  23. package/dist/chart/index.d.ts.map +1 -1
  24. package/dist/chart/index.mjs +1512 -572
  25. package/dist/chart/line-dash.d.ts +2 -0
  26. package/dist/chart/line-dash.d.ts.map +1 -0
  27. package/dist/chart/marker-shape.d.ts +70 -0
  28. package/dist/chart/marker-shape.d.ts.map +1 -0
  29. package/dist/chart/read-formatting.d.ts.map +1 -1
  30. package/dist/chart/render/chart-svg-axes.d.ts +9 -0
  31. package/dist/chart/render/chart-svg-axes.d.ts.map +1 -0
  32. package/dist/chart/render/chart-svg-bars.d.ts.map +1 -1
  33. package/dist/chart/render/chart-svg-cartesian.d.ts.map +1 -1
  34. package/dist/chart/render/chart-svg-labels.d.ts +42 -0
  35. package/dist/chart/render/chart-svg-labels.d.ts.map +1 -0
  36. package/dist/chart/render/chart-svg-markers.d.ts +6 -0
  37. package/dist/chart/render/chart-svg-markers.d.ts.map +1 -0
  38. package/dist/chart/render/chart-svg-radial.d.ts.map +1 -1
  39. package/dist/chart/render/chart-svg-xy.d.ts.map +1 -1
  40. package/dist/chart/render/chart-view-axes.d.ts +30 -0
  41. package/dist/chart/render/chart-view-axes.d.ts.map +1 -0
  42. package/dist/chart/render/chart-view-labels.d.ts +16 -0
  43. package/dist/chart/render/chart-view-labels.d.ts.map +1 -0
  44. package/dist/chart/render/chart-view-markers.d.ts +27 -0
  45. package/dist/chart/render/chart-view-markers.d.ts.map +1 -0
  46. package/dist/chart/render/chart-view-series.d.ts.map +1 -1
  47. package/dist/chart/render/chart-view.d.ts +7 -1
  48. package/dist/chart/render/chart-view.d.ts.map +1 -1
  49. package/dist/chart/render/index.d.ts +2 -0
  50. package/dist/chart/render/index.d.ts.map +1 -1
  51. package/dist/chart/render/summary-from-space.d.ts +2 -2
  52. package/dist/chart/render/summary-from-space.d.ts.map +1 -1
  53. package/dist/chart/render/summary-labels.d.ts +9 -0
  54. package/dist/chart/render/summary-labels.d.ts.map +1 -0
  55. package/dist/chart/render/summary.d.ts +29 -1
  56. package/dist/chart/render/summary.d.ts.map +1 -1
  57. package/dist/{chunk-IM5LFEA2.mjs → chunk-3XFPCZKB.mjs} +1 -1
  58. package/dist/{chunk-YS43OMM3.mjs → chunk-75GLSRZE.mjs} +4 -4
  59. package/dist/{chunk-A7S2NYAU.mjs → chunk-BIVNVDAH.mjs} +1 -1
  60. package/dist/{chunk-UFGJNXRG.mjs → chunk-QBJRB6WW.mjs} +1 -1
  61. package/dist/{chunk-HLZIALC5.mjs → chunk-RUZEMWDI.mjs} +1 -1
  62. package/dist/docx/embedded.cjs +15 -0
  63. package/dist/docx/embedded.mjs +15 -0
  64. package/dist/docx/index.cjs +1825 -693
  65. package/dist/docx/index.mjs +1825 -693
  66. package/dist/docx/layout/index.cjs +1684 -567
  67. package/dist/docx/layout/index.mjs +1684 -567
  68. package/dist/docx/load/index.cjs +15 -0
  69. package/dist/docx/load/index.mjs +15 -0
  70. package/dist/docx/ui/index.cjs +1696 -579
  71. package/dist/docx/ui/index.mjs +1696 -579
  72. package/dist/index.cjs +1623 -658
  73. package/dist/index.mjs +1623 -658
  74. package/dist/pptx/automation/index.cjs +61 -0
  75. package/dist/pptx/automation/index.mjs +5 -5
  76. package/dist/pptx/cli/index.cjs +61 -0
  77. package/dist/pptx/cli/index.mjs +4 -4
  78. package/dist/pptx/converter/index.mjs +2 -2
  79. package/dist/pptx/editor/render/slide-operations.cjs +1 -1
  80. package/dist/pptx/editor/render/slide-operations.mjs +1 -1
  81. package/dist/pptx/index.cjs +61 -0
  82. package/dist/pptx/index.mjs +5 -5
  83. package/dist/teams/index.cjs +212 -50
  84. package/dist/teams/index.mjs +212 -50
  85. package/dist/visio/edit-chart-object-commands.d.ts +36 -0
  86. package/dist/visio/edit-chart-object-commands.d.ts.map +1 -0
  87. package/dist/visio/edit-chart-object.d.ts +7 -0
  88. package/dist/visio/edit-chart-object.d.ts.map +1 -0
  89. package/dist/visio/edit-commands.d.ts +2 -1
  90. package/dist/visio/edit-commands.d.ts.map +1 -1
  91. package/dist/visio/edit-foreign-frame.d.ts +8 -0
  92. package/dist/visio/edit-foreign-frame.d.ts.map +1 -0
  93. package/dist/visio/edit-metadata-commands.d.ts +7 -0
  94. package/dist/visio/edit-metadata-commands.d.ts.map +1 -1
  95. package/dist/visio/edit-picture.d.ts +8 -0
  96. package/dist/visio/edit-picture.d.ts.map +1 -1
  97. package/dist/visio/edit.d.ts.map +1 -1
  98. package/dist/visio/emf-bitmap.d.ts +8 -0
  99. package/dist/visio/emf-bitmap.d.ts.map +1 -0
  100. package/dist/visio/index.cjs +17505 -6279
  101. package/dist/visio/index.d.ts +2 -0
  102. package/dist/visio/index.d.ts.map +1 -1
  103. package/dist/visio/index.mjs +17503 -6280
  104. package/dist/visio/model.d.ts +18 -0
  105. package/dist/visio/model.d.ts.map +1 -1
  106. package/dist/visio/prepare-embedded.d.ts +10 -0
  107. package/dist/visio/prepare-embedded.d.ts.map +1 -0
  108. package/dist/visio/prepare-images.d.ts.map +1 -1
  109. package/dist/visio/shapes.d.ts.map +1 -1
  110. package/dist/visio/sheet.d.ts +2 -1
  111. package/dist/visio/sheet.d.ts.map +1 -1
  112. package/dist/visio/ui/edit-commands.d.ts.map +1 -1
  113. package/dist/visio/ui/index.cjs +33580 -22875
  114. package/dist/visio/ui/index.mjs +33578 -22875
  115. package/dist/visio/ui/insert.d.ts +11 -0
  116. package/dist/visio/ui/insert.d.ts.map +1 -1
  117. package/dist/xlsx/edit/chart-colors.d.ts.map +1 -1
  118. package/dist/xlsx/index.cjs +1965 -817
  119. package/dist/xlsx/index.mjs +1965 -817
  120. package/dist/xlsx/load/index.cjs +190 -51
  121. package/dist/xlsx/load/index.mjs +190 -51
  122. package/dist/xlsx/model.d.ts +5 -0
  123. package/dist/xlsx/model.d.ts.map +1 -1
  124. package/dist/xlsx/read/chart.d.ts.map +1 -1
  125. package/dist/xlsx/read/load.d.ts.map +1 -1
  126. package/dist/xlsx/read/workbook-part.d.ts +2 -0
  127. package/dist/xlsx/read/workbook-part.d.ts.map +1 -1
  128. package/dist/xlsx/ui/dialogs/grid-chart.d.ts +22 -1
  129. package/dist/xlsx/ui/dialogs/grid-chart.d.ts.map +1 -1
  130. package/dist/xlsx/ui/index.cjs +17482 -4364
  131. package/dist/xlsx/ui/index.mjs +17472 -4362
  132. package/dist/xlsx/write/workbook-part.d.ts.map +1 -1
  133. package/package.json +1 -1
  134. package/dist/visio/edit-foreign-bitmap.d.ts +0 -7
  135. package/dist/visio/edit-foreign-bitmap.d.ts.map +0 -1
  136. /package/dist/{chunk-KU3SMBFU.mjs → chunk-H6TNNXJK.mjs} +0 -0
  137. /package/dist/{chunk-UWWS6VVJ.cjs → chunk-MHMVD23Y.cjs} +0 -0
@@ -526,6 +526,52 @@ function formatChartNumber(value, formatCode) {
526
526
  return formatChartNumberWithColor(value, formatCode)?.text;
527
527
  }
528
528
 
529
+ // chart/data-label-text.ts
530
+ var DATA_LABEL_SEPARATOR = ", ";
531
+ var DATA_LABEL_CATEGORY_PERCENT_SEPARATOR = "\n";
532
+ var FLAG_KEYS = [
533
+ "showValue",
534
+ "showCategory",
535
+ "showSeriesName",
536
+ "showPercent",
537
+ "showBubbleSize"
538
+ ];
539
+ function resolveDataLabelFlags(levels) {
540
+ const { point, series, chart } = levels;
541
+ const picked = {};
542
+ for (const key of FLAG_KEYS) picked[key] = point?.[key] ?? series?.[key] ?? chart?.[key];
543
+ const anyDeclared = FLAG_KEYS.some((key) => picked[key] !== void 0);
544
+ return {
545
+ showValue: anyDeclared ? picked.showValue === true : levels.siblingOwnsLabels !== true,
546
+ showCategory: picked.showCategory === true,
547
+ showSeriesName: picked.showSeriesName === true,
548
+ showPercent: picked.showPercent === true,
549
+ showBubbleSize: picked.showBubbleSize === true,
550
+ separator: point?.separator ?? series?.separator ?? chart?.separator ?? (picked.showCategory === true && picked.showPercent === true ? DATA_LABEL_CATEGORY_PERCENT_SEPARATOR : DATA_LABEL_SEPARATOR)
551
+ };
552
+ }
553
+ function composeDataLabelText(input) {
554
+ const { flags, value, numberFormat: numberFormat2 } = input;
555
+ const parts = [];
556
+ let valueColor;
557
+ if (flags.showSeriesName && input.seriesName) parts.push(input.seriesName);
558
+ if (flags.showCategory && input.category) parts.push(input.category);
559
+ if (flags.showValue) {
560
+ const formatted = formatChartNumberWithColor(value, numberFormat2);
561
+ parts.push(formatted?.text ?? (input.formatValue ?? String)(value, numberFormat2));
562
+ valueColor = formatted?.color;
563
+ }
564
+ if (flags.showPercent) {
565
+ const base = input.percentBase;
566
+ parts.push(base > 0 ? `${Math.round(Math.abs(value) / base * 100)}%` : "0%");
567
+ }
568
+ if (flags.showBubbleSize && input.bubbleSize !== void 0)
569
+ parts.push((input.formatBubbleSize ?? String)(input.bubbleSize));
570
+ const text3 = parts.join(flags.separator);
571
+ if (text3.length === 0) return void 0;
572
+ return { text: text3, color: parts.length === 1 && flags.showValue ? valueColor : void 0 };
573
+ }
574
+
529
575
  // chart/auto-title.ts
530
576
  var CHART_AUTO_TITLE = "Chart Title";
531
577
  var CHARTEX_ONLY_TYPES = /* @__PURE__ */ new Set([
@@ -562,12 +608,12 @@ function formatCompactAxisValue(value, formatCode) {
562
608
  }
563
609
 
564
610
  // chart/bubble-radius.ts
565
- function computeBubbleRadius(sizeVal, maxBubble, medianRadius, options) {
566
- const scale = (options?.bubbleScale ?? 100) / 100;
611
+ function computeBubbleRadius(sizeVal, maxBubble, medianRadius, options2) {
612
+ const scale = (options2?.bubbleScale ?? 100) / 100;
567
613
  if (sizeVal === void 0) return medianRadius * scale;
568
614
  const denom = maxBubble > 0 ? maxBubble : 1;
569
615
  const magnitude = Math.abs(sizeVal);
570
- const ratio = (options?.sizeRepresents ?? "w") === "area" ? Math.sqrt(magnitude) / Math.sqrt(denom) : magnitude / denom;
616
+ const ratio = (options2?.sizeRepresents ?? "w") === "area" ? Math.sqrt(magnitude) / Math.sqrt(denom) : magnitude / denom;
571
617
  return medianRadius * scale * 0.5 + ratio * medianRadius * scale * 1.5;
572
618
  }
573
619
  function maxBubbleSize(sizes) {
@@ -673,10 +719,10 @@ function squarify(nodes, box) {
673
719
 
674
720
  // chart/hierarchy.ts
675
721
  function normalizeLevels(levels, pointCount) {
676
- return levels.map((level) => {
722
+ return levels.map((level2) => {
677
723
  let previous = "";
678
724
  return Array.from({ length: pointCount }, (_, index) => {
679
- const label = level[index]?.trim() ?? "";
725
+ const label = level2[index]?.trim() ?? "";
680
726
  if (label) previous = label;
681
727
  return label || previous;
682
728
  });
@@ -834,12 +880,12 @@ function computeSunburstArcs(series, cx2, cy, maxR) {
834
880
  });
835
881
  return out;
836
882
  }
837
- function hierarchyKey(levels, level, index) {
838
- return levels.slice(level).map((labels) => labels[index] ?? "").join("\0");
883
+ function hierarchyKey(levels, level2, index) {
884
+ return levels.slice(level2).map((labels) => labels[index] ?? "").join("\0");
839
885
  }
840
886
  function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR) {
841
- const levels = categoryLevels2.filter((level) => level.length > 0);
842
- const leafCount = Math.max(values.length, ...levels.map((level) => level.length), 0);
887
+ const levels = categoryLevels2.filter((level2) => level2.length > 0);
888
+ const leafCount = Math.max(values.length, ...levels.map((level2) => level2.length), 0);
843
889
  if (levels.length === 0 || leafCount === 0) return [];
844
890
  const rawWeights = Array.from({ length: leafCount }, (_, index) => Math.abs(values[index] ?? 0));
845
891
  const weights = rawWeights.some((value) => value !== 0) ? rawWeights : rawWeights.map(() => 1);
@@ -850,15 +896,15 @@ function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR)
850
896
  const rootLabels = levels[levels.length - 1] ?? [];
851
897
  const rootColors = /* @__PURE__ */ new Map();
852
898
  const out = [];
853
- for (let level = levels.length - 1; level >= 0; level--) {
854
- const ringIndex = levels.length - 1 - level;
899
+ for (let level2 = levels.length - 1; level2 >= 0; level2--) {
900
+ const ringIndex = levels.length - 1 - level2;
855
901
  const innerRadius = ringWidth * (ringIndex + 0.5);
856
902
  const outerRadius = ringWidth * (ringIndex + 1.5);
857
903
  let start = 0;
858
904
  while (start < leafCount) {
859
- const key = hierarchyKey(levels, level, start);
905
+ const key = hierarchyKey(levels, level2, start);
860
906
  let end = start + 1;
861
- while (end < leafCount && hierarchyKey(levels, level, end) === key) end++;
907
+ while (end < leafCount && hierarchyKey(levels, level2, end) === key) end++;
862
908
  const startAngle = -Math.PI / 2 + (prefix[start] ?? 0) / total * Math.PI * 2;
863
909
  const endAngle = -Math.PI / 2 + (prefix[end] ?? 0) / total * Math.PI * 2;
864
910
  const rootLabel = rootLabels[start] ?? "";
@@ -868,8 +914,8 @@ function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR)
868
914
  colorIndex: rootColors.get(rootLabel) ?? start,
869
915
  opacity: Math.max(0.1, 0.9 - ringIndex * 0.1),
870
916
  level: ringIndex,
871
- label: levels[level]?.[start] ?? "",
872
- ...level === 0 && end === start + 1 ? { pointIndex: start } : {},
917
+ label: levels[level2]?.[start] ?? "",
918
+ ...level2 === 0 && end === start + 1 ? { pointIndex: start } : {},
873
919
  ...arcLabelPlacement(cx2, cy, (innerRadius + outerRadius) / 2, startAngle, endAngle)
874
920
  });
875
921
  start = end;
@@ -968,14 +1014,14 @@ function scottBinCount(values, min, max) {
968
1014
  const width = 3.49 * sd * values.length ** (-1 / 3);
969
1015
  return Math.max(1, Math.ceil((max - min) / width));
970
1016
  }
971
- function computeHistogramBins(values, options, format = String) {
972
- const closed = options.intervalClosed ?? "l";
1017
+ function computeHistogramBins(values, options2, format = String) {
1018
+ const closed = options2.intervalClosed ?? "l";
973
1019
  const finite = values.map((value, sourceIndex) => ({ value, sourceIndex })).filter((item) => Number.isFinite(item.value));
974
1020
  if (finite.length === 0) {
975
1021
  return [];
976
1022
  }
977
- const underflow = typeof options.underflow === "number" ? options.underflow : void 0;
978
- const overflow = typeof options.overflow === "number" ? options.overflow : void 0;
1023
+ const underflow = typeof options2.underflow === "number" ? options2.underflow : void 0;
1024
+ const overflow = typeof options2.overflow === "number" ? options2.overflow : void 0;
979
1025
  const under = underflow === void 0 ? [] : finite.filter(
980
1026
  (item) => closed === "r" ? item.value <= underflow : item.value < underflow
981
1027
  );
@@ -992,8 +1038,8 @@ function computeHistogramBins(values, options, format = String) {
992
1038
  if (regular.length > 0) {
993
1039
  const min = Math.min(...regular.map((item) => item.value));
994
1040
  const max = Math.max(...regular.map((item) => item.value));
995
- const requestedSize = options.binSize && options.binSize > 0 ? options.binSize : void 0;
996
- const requestedCount = options.binCount && options.binCount > 0 ? options.binCount : void 0;
1041
+ const requestedSize = options2.binSize && options2.binSize > 0 ? options2.binSize : void 0;
1042
+ const requestedCount = options2.binCount && options2.binCount > 0 ? options2.binCount : void 0;
997
1043
  const start = requestedSize ? Math.floor(min / requestedSize) * requestedSize : min;
998
1044
  const count = requestedSize ? Math.max(
999
1045
  closed === "l" ? Math.floor((max - start) / requestedSize) + 1 : Math.ceil((max - start) / requestedSize),
@@ -1044,9 +1090,9 @@ function aggregateByCategory(values, rawCategories) {
1044
1090
  }
1045
1091
 
1046
1092
  // chart/waterfall.ts
1047
- function buildWaterfallSteps(values, options) {
1093
+ function buildWaterfallSteps(values, options2) {
1048
1094
  const subtotalIndices = new Set(
1049
- options?.subtotalIndices ?? (values.length > 0 ? [values.length - 1] : [])
1095
+ options2?.subtotalIndices ?? (values.length > 0 ? [values.length - 1] : [])
1050
1096
  );
1051
1097
  const steps = [];
1052
1098
  let runningTotal = 0;
@@ -1122,13 +1168,13 @@ var noFit = () => ({
1122
1168
  rSquared: 0,
1123
1169
  coefficients: []
1124
1170
  });
1125
- function fitModel(options, xVals, yVals) {
1171
+ function fitModel(options2, xVals, yVals) {
1126
1172
  const xs = [...xVals];
1127
1173
  const ys = [...yVals];
1128
- switch (options.kind) {
1174
+ switch (options2.kind) {
1129
1175
  case "linear": {
1130
1176
  const reg = computeLinearRegression(xs, ys);
1131
- const fixed = options.intercept;
1177
+ const fixed = options2.intercept;
1132
1178
  const slope = fixed !== void 0 ? ys.reduce((s, y, i) => s + (y - fixed) * xs[i], 0) / xs.reduce((s, x) => s + x * x, 0) : reg.slope;
1133
1179
  const b = fixed ?? reg.intercept;
1134
1180
  return {
@@ -1178,7 +1224,7 @@ function fitModel(options, xVals, yVals) {
1178
1224
  };
1179
1225
  }
1180
1226
  case "polynomial": {
1181
- const order = Math.min(options.order ?? 2, 6);
1227
+ const order = Math.min(options2.order ?? 2, 6);
1182
1228
  const coeffs = fitPolynomial(xs, ys, order);
1183
1229
  const evaluate = (x) => coeffs.reduce((s, c2, i) => s + c2 * x ** i, 0);
1184
1230
  return {
@@ -1192,11 +1238,11 @@ function fitModel(options, xVals, yVals) {
1192
1238
  return void 0;
1193
1239
  }
1194
1240
  }
1195
- function fitChartTrendline(options, xVals, yVals) {
1241
+ function fitChartTrendline(options2, xVals, yVals) {
1196
1242
  const count = yVals.length;
1197
1243
  if (count < 2) return noFit();
1198
- if (options.kind === "movingAvg") {
1199
- const period = options.period ?? 2;
1244
+ if (options2.kind === "movingAvg") {
1245
+ const period = options2.period ?? 2;
1200
1246
  const points2 = [];
1201
1247
  for (let i = period - 1; i < count; i++) {
1202
1248
  let sum = 0;
@@ -1205,10 +1251,10 @@ function fitChartTrendline(options, xVals, yVals) {
1205
1251
  }
1206
1252
  return { points: points2, equation: `${period}-period moving average`, rSquared: 0, coefficients: [] };
1207
1253
  }
1208
- const model = fitModel(options, xVals, yVals);
1254
+ const model = fitModel(options2, xVals, yVals);
1209
1255
  if (!model) return noFit();
1210
- const startX = Math.min(...xVals) - (options.backward ?? 0);
1211
- const endX = Math.max(...xVals) + (options.forward ?? 0);
1256
+ const startX = Math.min(...xVals) - (options2.backward ?? 0);
1257
+ const endX = Math.max(...xVals) + (options2.forward ?? 0);
1212
1258
  const steps = Math.max(Math.ceil((endX - startX) * 4), 20);
1213
1259
  const points = [];
1214
1260
  for (let step = 0; step <= steps; step++) {
@@ -1231,18 +1277,18 @@ function chartSampleVariance(values) {
1231
1277
  const mean = values.reduce((sum, value) => sum + value, 0) / count;
1232
1278
  return values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / Math.max(count - 1, 1);
1233
1279
  }
1234
- function chartErrorBarAmount(options, values, displayIndex, sourceIndex, side) {
1235
- switch (options.valueType) {
1280
+ function chartErrorBarAmount(options2, values, displayIndex, sourceIndex, side) {
1281
+ switch (options2.valueType) {
1236
1282
  case "fixedVal":
1237
- return options.value ?? 0;
1283
+ return options2.value ?? 0;
1238
1284
  case "percentage":
1239
- return Math.abs(values[displayIndex] ?? 0) * ((options.value ?? 0) / 100);
1285
+ return Math.abs(values[displayIndex] ?? 0) * ((options2.value ?? 0) / 100);
1240
1286
  case "stdDev":
1241
- return Math.sqrt(chartSampleVariance(values)) * (options.value ?? 1);
1287
+ return Math.sqrt(chartSampleVariance(values)) * (options2.value ?? 1);
1242
1288
  case "stdErr":
1243
1289
  return Math.sqrt(chartSampleVariance(values) / Math.max(values.length, 1));
1244
1290
  case "cust":
1245
- return side === "plus" ? options.customPlus?.[sourceIndex] ?? 0 : options.customMinus?.[sourceIndex] ?? 0;
1291
+ return side === "plus" ? options2.customPlus?.[sourceIndex] ?? 0 : options2.customMinus?.[sourceIndex] ?? 0;
1246
1292
  }
1247
1293
  }
1248
1294
 
@@ -1447,8 +1493,8 @@ function rgbToHsl(r, g, b) {
1447
1493
  }
1448
1494
  return { h, s: clampUnitInterval(s), l: clampUnitInterval(l) };
1449
1495
  }
1450
- function hslToRgb(h, s, l, roundChannel = Math.round, options) {
1451
- const sC = options?.clampSaturation === false ? s : clampUnitInterval(s);
1496
+ function hslToRgb(h, s, l, roundChannel = Math.round, options2) {
1497
+ const sC = options2?.clampSaturation === false ? s : clampUnitInterval(s);
1452
1498
  const lC = clampUnitInterval(l);
1453
1499
  const hN = (h % 360 + 360) % 360;
1454
1500
  const c2 = (1 - Math.abs(2 * lC - 1)) * sC;
@@ -1853,17 +1899,17 @@ function checkXmlLimits(xml, label, limits = {}) {
1853
1899
  throw new Error(`${label} XML exceeds the nesting depth limit of ${maxDepth}`);
1854
1900
  }
1855
1901
  }
1856
- function parseXml(xml, options = {}) {
1857
- const label = options.label ?? "OOXML";
1902
+ function parseXml(xml, options2 = {}) {
1903
+ const label = options2.label ?? "OOXML";
1858
1904
  if (/<!DOCTYPE|<!ENTITY/i.test(xml))
1859
1905
  throw new Error(`${label} XML with DTD or entity declarations is not supported`);
1860
- checkXmlLimits(xml, label, options.limits);
1906
+ checkXmlLimits(xml, label, options2.limits);
1861
1907
  let parseError = "";
1862
1908
  let parsed;
1863
1909
  try {
1864
1910
  parsed = new DOMParser({
1865
- onError: (level, message) => {
1866
- if (level !== "warning") parseError = message;
1911
+ onError: (level2, message) => {
1912
+ if (level2 !== "warning") parseError = message;
1867
1913
  }
1868
1914
  }).parseFromString(xml, "application/xml");
1869
1915
  } catch (error) {
@@ -2053,13 +2099,13 @@ var APPLIED = /* @__PURE__ */ new Set([
2053
2099
  "lumMod",
2054
2100
  "lumOff"
2055
2101
  ]);
2056
- function resolveDrawingColor(color, theme, options) {
2102
+ function resolveDrawingColor(color, theme, options2) {
2057
2103
  const base = baseHex(color, theme);
2058
2104
  const rgb = base ? hexToRgbChannels(base) : null;
2059
2105
  if (!rgb) return void 0;
2060
- if (options?.transformOrder === "document") {
2106
+ if (options2?.transformOrder === "document") {
2061
2107
  const value = orderedColorTransforms(rgb, color.transforms);
2062
- const round = options.hslRounding === "halfDown" ? (channel) => Math.ceil(channel - 0.5) : Math.round;
2108
+ const round = options2.hslRounding === "halfDown" ? (channel) => Math.ceil(channel - 0.5) : Math.round;
2063
2109
  return {
2064
2110
  hex: `#${toHex(round(value.r))}${toHex(round(value.g))}${toHex(round(value.b))}`,
2065
2111
  alpha: value.alpha,
@@ -2110,7 +2156,7 @@ function resolveDrawingColor(color, theme, options) {
2110
2156
  if (lumMod !== void 0) hsl.l = clampUnitInterval(hsl.l * lumMod);
2111
2157
  const lumOff = parseDrawingFraction(find("lumOff"));
2112
2158
  if (lumOff !== void 0) hsl.l = clampUnitInterval(hsl.l + lumOff);
2113
- const round = options?.hslRounding === "halfDown" ? (value) => Math.ceil(value - 0.5) : Math.round;
2159
+ const round = options2?.hslRounding === "halfDown" ? (value) => Math.ceil(value - 0.5) : Math.round;
2114
2160
  ({ r, g, b } = hslToRgb(hsl.h, hsl.s, hsl.l, round));
2115
2161
  }
2116
2162
  let alpha = parseDrawingPercent(find("alpha")) ?? 1;
@@ -2499,6 +2545,19 @@ function readChartStyle(xml) {
2499
2545
  }
2500
2546
 
2501
2547
  // chart/formatting-nodes.ts
2548
+ function chartDataLabelNode(root) {
2549
+ const plot = first(first(root, "chart", NS.c), "plotArea", NS.c);
2550
+ const groups = plot ? elements(plot).filter((node) => node.localName.endsWith("Chart")) : [];
2551
+ const candidates = groups.flatMap((group2) => [
2552
+ ...children(group2, "ser", NS.c).map((ser) => first(ser, "dLbls", NS.c)),
2553
+ first(group2, "dLbls", NS.c)
2554
+ ]);
2555
+ return candidates.find(
2556
+ (node) => node !== void 0 && (first(node, "txPr", NS.c) !== void 0 || elements(node).some(
2557
+ (child2) => child2.localName.startsWith("show") && child2.getAttribute("val") === "1"
2558
+ ))
2559
+ );
2560
+ }
2502
2561
  function chartFormattingNodes(root) {
2503
2562
  const chart = first(root, "chart", NS.c);
2504
2563
  const plot = first(chart, "plotArea", NS.c);
@@ -2673,6 +2732,8 @@ function readChartFormatting(root) {
2673
2732
  const entries = Object.fromEntries(
2674
2733
  Object.entries(nodes).flatMap(([name, node]) => node ? [[name, entry2(node)]] : [])
2675
2734
  );
2735
+ const labels = chartDataLabelNode(root);
2736
+ if (labels) entries["dataLabel"] = entry2(labels);
2676
2737
  const builtInStyle = readBuiltInChartStyle(root);
2677
2738
  const textBody = c(root, "txPr");
2678
2739
  const textDefaults = textBody ? {
@@ -3041,7 +3102,7 @@ function resolveInnerRect(fillToRect, focalPoint) {
3041
3102
  function lerpEdge(inner, outer, t) {
3042
3103
  return inner + (outer - inner) * t;
3043
3104
  }
3044
- function buildRectPathGradientSvg(stops, focalPoint, fillToRect, options) {
3105
+ function buildRectPathGradientSvg(stops, focalPoint, fillToRect, options2) {
3045
3106
  if (stops.length === 0) {
3046
3107
  return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"/>';
3047
3108
  }
@@ -3050,7 +3111,7 @@ function buildRectPathGradientSvg(stops, focalPoint, fillToRect, options) {
3050
3111
  const rects = [];
3051
3112
  const alphaRects = [];
3052
3113
  const masked = sorted.some((stop) => (stop.opacity ?? 1) < 1);
3053
- const bands = options?.bands;
3114
+ const bands = options2?.bands;
3054
3115
  if (!Number.isInteger(bands) || bands < 1) throw new RangeError("Invalid gradient band count");
3055
3116
  for (let i = bands; i >= 0; i -= 1) {
3056
3117
  const t = i / bands;
@@ -3173,12 +3234,12 @@ function chartGradientMarkup(def) {
3173
3234
 
3174
3235
  // chart/bar-cluster-geometry.ts
3175
3236
  var DEFAULT_BAR_GAP_WIDTH = 150;
3176
- function assertBarClusterOptions(options) {
3237
+ function assertBarClusterOptions(options2) {
3177
3238
  for (const [field, min, max] of [
3178
3239
  ["barGapWidth", 0, 500],
3179
3240
  ["barOverlap", -100, 100]
3180
3241
  ]) {
3181
- const value = options[field];
3242
+ const value = options2[field];
3182
3243
  if (value !== void 0 && (!Number.isInteger(value) || value < min || value > max))
3183
3244
  throw new RangeError(`${field} must be an integer from ${min} to ${max}`);
3184
3245
  }
@@ -4431,7 +4492,7 @@ function dataSourceInner(source) {
4431
4492
  case "multiLvlStrRef": {
4432
4493
  const levels = source.levels ? elementXml(
4433
4494
  "multiLvlStrCache",
4434
- valXml("ptCount", source.levelPointCount) + source.levels.map((level) => elementXml("lvl", cachePoints(level))).join("")
4495
+ valXml("ptCount", source.levelPointCount) + source.levels.map((level2) => elementXml("lvl", cachePoints(level2))).join("")
4435
4496
  ) : "";
4436
4497
  return `<c:multiLvlStrRef>${formula}${levels}</c:multiLvlStrRef>`;
4437
4498
  }
@@ -4464,8 +4525,8 @@ function titleXml(context, title) {
4464
4525
  chartTextXml(context, tx, false) + layoutXml(context, title.layout) + valXml("overlay", title.overlay) + shapePropertiesXml(context, title.spPr) + textBodyXml(context, title.txPr) + raw(context, title.extLst)
4465
4526
  );
4466
4527
  }
4467
- function labelOptionsXml(context, options) {
4468
- return numberFormatXml(options.numberFormat) + shapePropertiesXml(context, options.spPr) + textBodyXml(context, options.txPr) + valXml("dLblPos", options.position) + valXml("showLegendKey", options.showLegendKey) + valXml("showVal", options.showValue) + valXml("showCatName", options.showCategoryName) + valXml("showSerName", options.showSeriesName) + valXml("showPercent", options.showPercent) + valXml("showBubbleSize", options.showBubbleSize) + (options.separator === void 0 ? "" : textElement("separator", options.separator));
4528
+ function labelOptionsXml(context, options2) {
4529
+ return numberFormatXml(options2.numberFormat) + shapePropertiesXml(context, options2.spPr) + textBodyXml(context, options2.txPr) + valXml("dLblPos", options2.position) + valXml("showLegendKey", options2.showLegendKey) + valXml("showVal", options2.showValue) + valXml("showCatName", options2.showCategoryName) + valXml("showSerName", options2.showSeriesName) + valXml("showPercent", options2.showPercent) + valXml("showBubbleSize", options2.showBubbleSize) + (options2.separator === void 0 ? "" : textElement("separator", options2.separator));
4469
4530
  }
4470
4531
  function labelXml(context, label) {
4471
4532
  return elementXml(
@@ -4635,7 +4696,7 @@ function styleXml(context, space) {
4635
4696
  );
4636
4697
  }
4637
4698
  var relationship = (local, id, content = "") => id === void 0 ? "" : elementXml(local, content, ` r:id="${escapeAttribute(id)}"`);
4638
- function writeChartSpace(space, options = {}) {
4699
+ function writeChartSpace(space, options2 = {}) {
4639
4700
  const bindings = new Map(CHART_ROOT_BINDINGS);
4640
4701
  for (const { prefix, uri } of space.namespaceDeclarations ?? [])
4641
4702
  if (!bindings.has(prefix) && /^[A-Za-z_][\w.-]*$/.test(prefix)) bindings.set(prefix, uri);
@@ -4650,10 +4711,204 @@ function writeChartSpace(space, options = {}) {
4650
4711
  space.externalDataRelId,
4651
4712
  valXml("autoUpdate", space.externalDataAutoUpdate)
4652
4713
  ) + raw(context, space.printSettings) + relationship("userShapes", space.userShapesRelId) + raw(context, space.extLst);
4653
- const breakAfter = options.declarationBreak ?? "\r\n";
4714
+ const breakAfter = options2.declarationBreak ?? "\r\n";
4654
4715
  return `${DECLARATION2}${breakAfter}<c:chartSpace${declarations}>${body}</c:chartSpace>`;
4655
4716
  }
4656
4717
 
4718
+ // chart/marker-shape.ts
4719
+ var CHART_PX_PER_PT = 4 / 3;
4720
+ var DEFAULT_MARKER_OUTLINE_PT = 0.75;
4721
+ function markerOutline(marker) {
4722
+ if (!marker.stroke) {
4723
+ return {};
4724
+ }
4725
+ return {
4726
+ stroke: marker.stroke,
4727
+ strokeWidth: (marker.strokeWidth ?? DEFAULT_MARKER_OUTLINE_PT) * CHART_PX_PER_PT
4728
+ };
4729
+ }
4730
+ var AUTOMATIC_MARKER_CYCLE = [
4731
+ "diamond",
4732
+ "square",
4733
+ "triangle",
4734
+ "x",
4735
+ "star",
4736
+ "circle",
4737
+ "plus",
4738
+ "dot",
4739
+ "dash"
4740
+ ];
4741
+ function automaticMarkerSymbol(seriesIdx) {
4742
+ const length = AUTOMATIC_MARKER_CYCLE.length;
4743
+ const normalized = (Math.trunc(seriesIdx) % length + length) % length;
4744
+ return AUTOMATIC_MARKER_CYCLE[Number.isFinite(normalized) ? normalized : 0];
4745
+ }
4746
+ function markerRadius(size, defaultRadius) {
4747
+ if (size === void 0 || !Number.isFinite(size) || size <= 0) {
4748
+ return defaultRadius;
4749
+ }
4750
+ return size / 2;
4751
+ }
4752
+ function polygonPoints(vertices) {
4753
+ return vertices.map(([x, y]) => `${x.toFixed(2)},${y.toFixed(2)}`).join(" ");
4754
+ }
4755
+ function starVertices(cx2, cy, r) {
4756
+ const inner = r * 0.5;
4757
+ const out = [];
4758
+ for (let i = 0; i < 10; i++) {
4759
+ const radius = i % 2 === 0 ? r : inner;
4760
+ const angle = -Math.PI / 2 + Math.PI * i / 5;
4761
+ out.push([cx2 + radius * Math.cos(angle), cy + radius * Math.sin(angle)]);
4762
+ }
4763
+ return out;
4764
+ }
4765
+ function rectPolygon(x, y, w, h) {
4766
+ return polygonPoints([
4767
+ [x, y],
4768
+ [x + w, y],
4769
+ [x + w, y + h],
4770
+ [x, y + h]
4771
+ ]);
4772
+ }
4773
+ function buildMarkerPrimitive(input) {
4774
+ const { symbol, cx: cx2, cy, fill } = input;
4775
+ const part = input.part === void 0 ? {} : { part: input.part };
4776
+ if (symbol === "none") {
4777
+ return null;
4778
+ }
4779
+ const r = markerRadius(input.size, input.defaultRadius);
4780
+ const outline = input.stroke ? {
4781
+ stroke: input.stroke,
4782
+ strokeWidth: input.strokeWidth ?? DEFAULT_MARKER_OUTLINE_PT * CHART_PX_PER_PT
4783
+ } : void 0;
4784
+ const polygonStroke = outline ?? { stroke: fill, strokeWidth: 0 };
4785
+ const lineStroke = input.stroke ?? fill;
4786
+ switch (symbol) {
4787
+ case "square":
4788
+ case "dash": {
4789
+ const h = symbol === "dash" ? r * 0.64 : r * 2;
4790
+ const y = cy - h / 2;
4791
+ if (outline) {
4792
+ return {
4793
+ kind: "polygon",
4794
+ points: rectPolygon(cx2 - r, y, r * 2, h),
4795
+ fill,
4796
+ ...outline,
4797
+ ...part
4798
+ };
4799
+ }
4800
+ return { kind: "rect", x: cx2 - r, y, w: r * 2, h, fill, ...part };
4801
+ }
4802
+ case "diamond":
4803
+ return {
4804
+ kind: "polygon",
4805
+ points: polygonPoints([
4806
+ [cx2, cy - r],
4807
+ [cx2 + r, cy],
4808
+ [cx2, cy + r],
4809
+ [cx2 - r, cy]
4810
+ ]),
4811
+ fill,
4812
+ ...polygonStroke,
4813
+ ...part
4814
+ };
4815
+ case "triangle":
4816
+ return {
4817
+ kind: "polygon",
4818
+ points: polygonPoints([
4819
+ [cx2, cy - r],
4820
+ [cx2 + r * 0.9, cy + r * 0.75],
4821
+ [cx2 - r * 0.9, cy + r * 0.75]
4822
+ ]),
4823
+ fill,
4824
+ ...polygonStroke,
4825
+ ...part
4826
+ };
4827
+ case "star":
4828
+ return {
4829
+ kind: "polygon",
4830
+ points: polygonPoints(starVertices(cx2, cy, r)),
4831
+ fill,
4832
+ ...polygonStroke,
4833
+ ...part
4834
+ };
4835
+ case "plus":
4836
+ return {
4837
+ kind: "path",
4838
+ d: `M${(cx2 - r).toFixed(2)},${cy.toFixed(2)} L${(cx2 + r).toFixed(2)},${cy.toFixed(2)} M${cx2.toFixed(2)},${(cy - r).toFixed(2)} L${cx2.toFixed(2)},${(cy + r).toFixed(2)}`,
4839
+ fill: "none",
4840
+ stroke: lineStroke,
4841
+ strokeWidth: Math.max(1, r * 0.4),
4842
+ ...part
4843
+ };
4844
+ case "x":
4845
+ return {
4846
+ kind: "path",
4847
+ d: `M${(cx2 - r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx2 + r).toFixed(2)},${(cy + r).toFixed(2)} M${(cx2 + r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx2 - r).toFixed(2)},${(cy + r).toFixed(2)}`,
4848
+ fill: "none",
4849
+ stroke: lineStroke,
4850
+ strokeWidth: Math.max(1, r * 0.4),
4851
+ ...part
4852
+ };
4853
+ case "dot":
4854
+ return { kind: "circle", cx: cx2, cy, r: Math.max(r * 0.6, 1), fill, ...part, ...outline };
4855
+ default:
4856
+ return { kind: "circle", cx: cx2, cy, r, fill, ...part, ...outline };
4857
+ }
4858
+ }
4859
+
4860
+ // chart/render/chart-view-markers.ts
4861
+ function summaryMarkers(source, group2, seriesPosition) {
4862
+ if (!["line", "scatter", "radar"].includes(group2.kind)) return {};
4863
+ const enabled = group2.kind === "line" ? group2.marker === true : group2.kind === "radar" ? group2.radarStyle === "marker" : !["line", "smooth", "none"].includes(group2.scatterStyle ?? "marker");
4864
+ const symbol = source.marker?.symbol;
4865
+ const marker = {
4866
+ ...source.marker,
4867
+ symbol: symbol && symbol !== "auto" ? symbol : source.marker || enabled ? automaticMarkerSymbol(source.index ?? seriesPosition) : "none"
4868
+ };
4869
+ const pointMarkers = {};
4870
+ for (const point of source.dataPoints) {
4871
+ if (point.index === void 0 || !point.marker) continue;
4872
+ const override = point.marker;
4873
+ pointMarkers[point.index] = {
4874
+ ...marker,
4875
+ ...override,
4876
+ ...override.symbol === "auto" || !source.marker && override.symbol === void 0 ? { symbol: automaticMarkerSymbol(source.index ?? seriesPosition) } : {},
4877
+ ...marker.spPr || override.spPr ? {
4878
+ spPr: {
4879
+ ...marker.spPr,
4880
+ ...override.spPr,
4881
+ ...marker.spPr?.line || override.spPr?.line ? { line: { ...marker.spPr?.line, ...override.spPr?.line } } : {}
4882
+ }
4883
+ } : {}
4884
+ };
4885
+ }
4886
+ return { marker, ...Object.keys(pointMarkers).length ? { pointMarkers } : {} };
4887
+ }
4888
+ function seriesMarkerViews(source, drawingColor) {
4889
+ const fillColor = (fill) => fill?.kind === "none" ? "none" : fill?.kind === "solid" ? drawingColor(fill.color) : void 0;
4890
+ const resolve = (marker) => {
4891
+ const fill = fillColor(marker.spPr?.fill);
4892
+ const stroke = fillColor(marker.spPr?.line?.fill);
4893
+ const width = marker.spPr?.line?.widthEmu;
4894
+ return {
4895
+ ...marker.symbol !== void 0 ? { symbol: marker.symbol } : {},
4896
+ ...marker.size !== void 0 ? { size: marker.size } : {},
4897
+ ...fill !== void 0 ? { fill } : {},
4898
+ ...stroke !== void 0 ? { stroke } : {},
4899
+ ...width !== void 0 ? { strokeWidth: width / 9525 } : {}
4900
+ };
4901
+ };
4902
+ return {
4903
+ ...source.marker ? { marker: resolve(source.marker) } : {},
4904
+ ...source.pointMarkers ? {
4905
+ pointMarkers: Object.fromEntries(
4906
+ Object.entries(source.pointMarkers).map(([i, marker]) => [i, resolve(marker)])
4907
+ )
4908
+ } : {}
4909
+ };
4910
+ }
4911
+
4657
4912
  // chart/render/summary-analysis.ts
4658
4913
  function summaryTrendline(source) {
4659
4914
  const kind = chartTrendlineKind(source.trendlineType);
@@ -4694,6 +4949,41 @@ function summaryAnalysis(series) {
4694
4949
  };
4695
4950
  }
4696
4951
 
4952
+ // chart/render/summary-labels.ts
4953
+ function level(options2, custom) {
4954
+ const out = {};
4955
+ if (options2.deleted !== void 0) out.deleted = options2.deleted;
4956
+ if (options2.showValue !== void 0) out.showValue = options2.showValue;
4957
+ if (options2.showCategoryName !== void 0) out.showCategory = options2.showCategoryName;
4958
+ if (options2.showSeriesName !== void 0) out.showSeriesName = options2.showSeriesName;
4959
+ if (options2.showPercent !== void 0) out.showPercent = options2.showPercent;
4960
+ if (options2.showBubbleSize !== void 0) out.showBubbleSize = options2.showBubbleSize;
4961
+ if (options2.separator !== void 0) out.separator = options2.separator;
4962
+ if (options2.position) out.position = options2.position;
4963
+ if (options2.numberFormat?.formatCode) out.numberFormat = options2.numberFormat.formatCode;
4964
+ if (custom?.text !== void 0) out.text = custom.text;
4965
+ return out;
4966
+ }
4967
+ function shows(levels, point) {
4968
+ const flags = resolveDataLabelFlags({ ...levels, ...point ? { point } : {} });
4969
+ return point?.text !== void 0 || Object.values(flags).some((value) => value === true);
4970
+ }
4971
+ function summaryDataLabels(series, group2) {
4972
+ const own = series.dataLabels;
4973
+ if (!own && !group2) return void 0;
4974
+ const out = {};
4975
+ if (group2) out.chart = level(group2);
4976
+ if (own) out.series = level(own);
4977
+ const points = {};
4978
+ for (const labels of [group2, own])
4979
+ for (const label of labels?.labels ?? [])
4980
+ if (label.index !== void 0)
4981
+ points[label.index] = { ...points[label.index], ...level(label, label.tx) };
4982
+ if (Object.keys(points).length) out.points = points;
4983
+ if (!shows(out) && !Object.values(points).some((point) => shows(out, point))) return void 0;
4984
+ return out;
4985
+ }
4986
+
4697
4987
  // chart/render/summary-from-space.ts
4698
4988
  var solidColor = (fill) => fill?.kind === "solid" ? fill.color : void 0;
4699
4989
  var isSolidFill = (fill) => fill?.kind === "solid" || fill?.kind === "unsupported" && fill.element === "solidFill";
@@ -4711,7 +5001,7 @@ var GROUP_TYPES = {
4711
5001
  surface: "surface"
4712
5002
  };
4713
5003
  var GROUPINGS = /* @__PURE__ */ new Set(["clustered", "stacked", "percentStacked", "standard"]);
4714
- function chartSummarySeries(source, chartType) {
5004
+ function chartSummarySeries(source, chartType, groupLabels) {
4715
5005
  const categories = source.categories ?? source.xValues;
4716
5006
  const values = source.values ?? source.yValues;
4717
5007
  const numeric = (v) => typeof v === "number" ? v : v === "" ? null : Number.isFinite(Number(v)) ? Number(v) : null;
@@ -4719,6 +5009,7 @@ function chartSummarySeries(source, chartType) {
4719
5009
  categories: chartSourceValues(categories),
4720
5010
  values: chartSourceValues(values).map(numeric)
4721
5011
  };
5012
+ if (values?.cache?.formatCode !== void 0) out.numberFormat = values.cache.formatCode;
4722
5013
  if (source.bubbleSizes) {
4723
5014
  out.bubbleSizes = chartSourceValues(source.bubbleSizes).map(numeric);
4724
5015
  if (source.bubbleSizes.formula) out.bubbleSizesRef = source.bubbleSizes.formula;
@@ -4747,6 +5038,8 @@ function chartSummarySeries(source, chartType) {
4747
5038
  }
4748
5039
  if (Object.keys(points).length) out.pointColors = points;
4749
5040
  if (Object.keys(pointFills).length) out.pointFills = pointFills;
5041
+ const dataLabels = summaryDataLabels(source, groupLabels);
5042
+ if (dataLabels) out.dataLabels = dataLabels;
4750
5043
  Object.assign(out, summaryAnalysis(source));
4751
5044
  return out;
4752
5045
  }
@@ -4774,7 +5067,10 @@ function extraGroups(chartSpace, firstType) {
4774
5067
  const type = group2.kind === "bar" ? "column" : group2.kind;
4775
5068
  const entry3 = {
4776
5069
  chartType: type,
4777
- series: group2.series.map((source) => chartSummarySeries(source, type)),
5070
+ series: group2.series.map((source, index) => ({
5071
+ ...chartSummarySeries(source, type, group2.dataLabels),
5072
+ ...summaryMarkers(source, group2, index)
5073
+ })),
4778
5074
  secondary: valueAxisId(chartSpace, group2.axisIds) !== primary
4779
5075
  };
4780
5076
  if (group2.grouping && GROUPINGS.has(group2.grouping))
@@ -4792,11 +5088,16 @@ function chartSummaryFromSpace(chartSpace, extras = {}) {
4792
5088
  const group2 = chartSpace.plotArea.groups[0];
4793
5089
  let chartType = group2 ? GROUP_TYPES[group2.kind] : "column";
4794
5090
  if (chartType === "bar" && group2?.barDirection !== "bar") chartType = "column";
4795
- const series = (group2?.series ?? []).map((source) => chartSummarySeries(source, chartType));
5091
+ const series = (group2?.series ?? []).map((source, index) => ({
5092
+ ...chartSummarySeries(source, chartType, group2?.dataLabels),
5093
+ ...group2 ? summaryMarkers(source, group2, index) : {}
5094
+ }));
4796
5095
  const summary = {
4797
5096
  chartType,
4798
5097
  series,
4799
- showLegend: chartSpace.legend !== void 0
5098
+ showLegend: chartSpace.legend !== void 0,
5099
+ axes: chartSpace.plotArea.axes,
5100
+ axisIds: group2?.axisIds ?? []
4800
5101
  };
4801
5102
  const combined = extraGroups(chartSpace, chartType);
4802
5103
  if (combined.length) summary.extraGroups = combined;
@@ -4858,9 +5159,9 @@ function dimension(data, kind, type) {
4858
5159
  const out = { points: [] };
4859
5160
  const formula = text(cx(element, "f"));
4860
5161
  if (formula) out.formula = formula;
4861
- const level = cx(element, "lvl");
4862
- const count = Number(level?.getAttribute("ptCount") ?? 0);
4863
- for (const point of level ? children(level, "pt", NS.cx) : []) {
5162
+ const level2 = cx(element, "lvl");
5163
+ const count = Number(level2?.getAttribute("ptCount") ?? 0);
5164
+ for (const point of level2 ? children(level2, "pt", NS.cx) : []) {
4864
5165
  const index = Number(point.getAttribute("idx") ?? out.points.length);
4865
5166
  if (Number.isInteger(index) && index >= 0) out.points[index] = text(point);
4866
5167
  }
@@ -4869,10 +5170,10 @@ function dimension(data, kind, type) {
4869
5170
  }
4870
5171
  function categoryLevels(data) {
4871
5172
  const element = data ? children(data, "strDim", NS.cx).find((d) => (d.getAttribute("type") ?? "") === "cat") : void 0;
4872
- return (element ? children(element, "lvl", NS.cx) : []).map((level) => {
5173
+ return (element ? children(element, "lvl", NS.cx) : []).map((level2) => {
4873
5174
  const points = [];
4874
- const count = Number(level.getAttribute("ptCount") ?? 0);
4875
- for (const point of children(level, "pt", NS.cx)) {
5175
+ const count = Number(level2.getAttribute("ptCount") ?? 0);
5176
+ for (const point of children(level2, "pt", NS.cx)) {
4876
5177
  const index = Number(point.getAttribute("idx") ?? points.length);
4877
5178
  if (Number.isInteger(index) && index >= 0) points[index] = text(point);
4878
5179
  }
@@ -5043,135 +5344,553 @@ function chartBarSpacing(chart) {
5043
5344
  };
5044
5345
  }
5045
5346
 
5046
- // chart/render/chart-svg-bars.ts
5047
- function barLayout(model, frame) {
5048
- const count = Math.max(1, model.series.length);
5049
- const geometry = clusteredBarGeometry(frame.bandSize, count, chartBarSpacing(model));
5050
- const barSize = geometry.singleBarWidth;
5051
- const offset = (si) => model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
5052
- return { barSize, offset };
5053
- }
5054
- function bars(model, frame, out, values) {
5055
- const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
5056
- const { barSize, offset: barOffset } = barLayout(model, frame);
5057
- const base = frame.value(0);
5058
- const pos = new Array(model.categories.length).fill(0);
5059
- const neg = new Array(model.categories.length).fill(0);
5060
- model.series.forEach((s, si) => {
5061
- values[si]?.forEach((v, i) => {
5062
- if (v === null || i >= model.categories.length) return;
5063
- let from = 0;
5064
- let to = v;
5065
- if (stacked) {
5066
- const acc = v >= 0 ? pos : neg;
5067
- from = acc[i] ?? 0;
5068
- to = from + v;
5069
- acc[i] = to;
5070
- }
5071
- const a2 = stacked ? frame.value(from) : base;
5072
- const b = frame.value(to);
5073
- const offset = barOffset(si);
5074
- const center = frame.band(i);
5075
- const width = model.horizontal ? Math.abs(b - a2) : barSize;
5076
- const height = model.horizontal ? barSize : Math.abs(b - a2);
5077
- let color = s.pointColors?.[i] ?? s.color;
5078
- const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
5079
- if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
5080
- const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
5081
- if (baseId) {
5082
- const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
5083
- const def = buildChartGradientDef(id, gradient, {
5084
- width: Number(n(width)),
5085
- height: Number(n(height)),
5086
- shape: "rect"
5087
- });
5088
- out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
5089
- color = `url(#${id})`;
5090
- }
5091
- }
5092
- out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
5093
- if (model.horizontal)
5094
- out.push(
5095
- rect(Math.min(a2, b), center + offset, Math.abs(b - a2), barSize, color, s.shadowFilter)
5096
- );
5097
- else
5098
- out.push(
5099
- rect(center + offset, Math.min(a2, b), barSize, Math.abs(b - a2), color, s.shadowFilter)
5100
- );
5101
- out.push("</g>");
5102
- });
5103
- });
5347
+ // drawingml/drawing-color-css.ts
5348
+ function drawingColorCss(value) {
5349
+ if (!value || value.alpha === 1) return value?.hex;
5350
+ const channels = [1, 3, 5].map(
5351
+ (offset) => Number.parseInt(value.hex.slice(offset, offset + 2), 16)
5352
+ );
5353
+ return `rgba(${channels.join(",")},${value.alpha})`;
5104
5354
  }
5105
5355
 
5106
- // chart/render/chart-svg-analysis.ts
5107
- var DASHES = {
5108
- dot: [1, 3],
5109
- dash: [4, 3],
5110
- lgDash: [8, 3],
5111
- dashDot: [4, 3, 1, 3],
5112
- lgDashDot: [8, 3, 1, 3],
5113
- lgDashDotDot: [8, 3, 1, 3, 1, 3],
5114
- sysDash: [3, 1],
5115
- sysDot: [1, 1],
5116
- sysDashDot: [3, 1, 1, 1],
5117
- sysDashDotDot: [3, 1, 1, 1, 1, 1]
5118
- };
5119
- var CAP = 4;
5120
- function strokeAttributes(stroke) {
5121
- const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
5122
- const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
5123
- return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
5124
- }
5125
- var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
5126
- function trendlines(series, si, xs, ys, plane, out) {
5127
- for (const trendline of series.trendlines ?? []) {
5128
- const fit2 = fitChartTrendline(trendline.fit, xs, ys);
5129
- if (fit2.points.length < 2) continue;
5130
- const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
5131
- out.push(
5132
- `<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
5133
- );
5134
- }
5356
+ // units/constants.ts
5357
+ var EMU_PER_PIXEL = 9525;
5358
+ var EMU_PER_POINT = 12700;
5359
+
5360
+ // chart/render/theme-palette.ts
5361
+ var THEME_SLOTS = [
5362
+ "lt1",
5363
+ "dk1",
5364
+ "lt2",
5365
+ "dk2",
5366
+ "accent1",
5367
+ "accent2",
5368
+ "accent3",
5369
+ "accent4",
5370
+ "accent5",
5371
+ "accent6",
5372
+ "hlink",
5373
+ "folHlink"
5374
+ ];
5375
+ var DEFAULT_THEME_COLORS = [
5376
+ "FFFFFF",
5377
+ "000000",
5378
+ "E7E6E6",
5379
+ "44546A",
5380
+ "4472C4",
5381
+ "ED7D31",
5382
+ "A5A5A5",
5383
+ "FFC000",
5384
+ "5B9BD5",
5385
+ "70AD47",
5386
+ "0563C1",
5387
+ "954F72"
5388
+ ];
5389
+ function themeColor(theme, index) {
5390
+ const hex = theme.colors[index] ?? DEFAULT_THEME_COLORS[index];
5391
+ return hex && parseArgbHex(hex) ? hex.replace(/^#/, "") : void 0;
5135
5392
  }
5136
- function errorBar(bars2, at, values, plane, out) {
5137
- const stroke = strokeAttributes(bars2.stroke);
5138
- for (const side of ["plus", "minus"]) {
5139
- if (bars2.barType !== side && bars2.barType !== "both") continue;
5140
- const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
5141
- const sign = side === "plus" ? 1 : -1;
5142
- const [x1, y1] = plane(at.x, at.y);
5143
- const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
5144
- out.push(segment(x1, y1, x2, y2, stroke));
5145
- if (!bars2.endCap) continue;
5146
- if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
5147
- else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
5148
- }
5393
+
5394
+ // chart/render/chart-colors.ts
5395
+ function chartColorScheme(theme) {
5396
+ const slots = Object.fromEntries(
5397
+ THEME_SLOTS.map((slot, index) => [slot, `#${themeColor(theme, index) ?? "000000"}`])
5398
+ );
5399
+ return {
5400
+ ...slots,
5401
+ bg1: slots.lt1,
5402
+ tx1: slots.dk1,
5403
+ bg2: slots.lt2,
5404
+ tx2: slots.dk2
5405
+ };
5149
5406
  }
5150
- function plottedPoints(series, xOf) {
5151
- return series.values.flatMap((y, index) => {
5152
- const x = xOf(index);
5153
- return y === null || x === null ? [] : [{ x, y, index }];
5154
- });
5407
+ function modulateLuminance(hex, lumMod, lumOff = 0) {
5408
+ const rgb = parseArgbHex(hex);
5409
+ if (!rgb) return "#000000";
5410
+ if (lumMod === 1 && lumOff === 0) return rgbToUpperHex(rgb);
5411
+ const hsl = rgbToHsl(...rgb);
5412
+ const l = Math.max(0, Math.min(1, hsl.l * lumMod + lumOff));
5413
+ const out = hslToRgb(hsl.h, hsl.s, l);
5414
+ return rgbToUpperHex([out.r, out.g, out.b]);
5155
5415
  }
5156
- function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
5157
- const points = plottedPoints(series, xOf);
5158
- const xs = points.map((p) => p.x);
5159
- const ys = points.map((p) => p.y);
5160
- trendlines(series, si, xs, ys, plane, out);
5161
- for (const bars2 of series.errorBars ?? []) {
5162
- if (categoryAxis && bars2.direction === "x") continue;
5163
- const values = bars2.direction === "x" ? xs : ys;
5164
- points.forEach(
5165
- (p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
5166
- );
5167
- }
5416
+ function autoSeriesColor(theme, index) {
5417
+ const i = Math.max(0, Math.floor(index));
5418
+ return chartPaletteSeriesColor(findChartColorPalette(10), i, i + 1, chartColorScheme(theme));
5168
5419
  }
5169
- function categoryAnalysis(model, frame, out) {
5170
- if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
5171
- const plane = (x, y) => model.horizontal ? [frame.value(y), frame.band(x - 1)] : [frame.band(x - 1), frame.value(y)];
5172
- const barred = model.type === "bar" || model.type === "column";
5173
- const layout = barred ? barLayout(model, frame) : void 0;
5174
- model.series.forEach((series, si) => {
5420
+
5421
+ // drawingml/drawing-shadow.ts
5422
+ function resolveDrawingShadow(effects, theme) {
5423
+ const node = first(effects, "outerShdw", NS.a);
5424
+ if (!node) return void 0;
5425
+ const value = (key, fallback) => Number(node.getAttribute(key) ?? fallback);
5426
+ if (value("sx", 1e5) !== 1e5 || value("sy", 1e5) !== 1e5 || value("kx", 0) !== 0 || value("ky", 0) !== 0)
5427
+ return void 0;
5428
+ const color = parseDrawingColorIn(node);
5429
+ const resolved = color && resolveDrawingColor(color, theme, { transformOrder: "document" });
5430
+ const blur = value("blurRad", 0) / EMU_PER_PIXEL;
5431
+ const distance = value("dist", 0) / EMU_PER_PIXEL;
5432
+ const angle = value("dir", 0) / 6e4 * Math.PI / 180;
5433
+ if (!resolved || ![blur, distance, angle].every(Number.isFinite) || blur < 0 || distance < 0)
5434
+ return void 0;
5435
+ return {
5436
+ color: resolved.hex,
5437
+ opacity: resolved.alpha,
5438
+ blur,
5439
+ dx: Math.cos(angle) * distance,
5440
+ dy: Math.sin(angle) * distance
5441
+ };
5442
+ }
5443
+ function resolveDrawingShadowXml(xml, theme) {
5444
+ return xml ? resolveDrawingShadow(parseXml(xml).documentElement, theme) : void 0;
5445
+ }
5446
+ function svgDropShadowElement(s, format) {
5447
+ const num = format.number;
5448
+ return `<feDropShadow dx="${num(s.dx)}" dy="${num(s.dy)}" stdDeviation="${num(s.blur / 2)}" flood-color="${format.color(s.color, "#000000")}" flood-opacity="${num(s.opacity)}" result="shadow"/>`;
5449
+ }
5450
+
5451
+ // chart/text-inheritance.ts
5452
+ var TEXT_KEYS = [
5453
+ "fontSize",
5454
+ "bold",
5455
+ "italic",
5456
+ "underline",
5457
+ "typeface",
5458
+ "textColor",
5459
+ "fontRef"
5460
+ ];
5461
+ var TEXT_PARTS = [
5462
+ "title",
5463
+ "axisTitle",
5464
+ "categoryAxis",
5465
+ "valueAxis",
5466
+ "legend",
5467
+ "dataLabel"
5468
+ ];
5469
+ function inheritChartText(part, entry3, builtIn, root) {
5470
+ if (!root || !TEXT_PARTS.includes(part)) return entry3;
5471
+ const out = { ...entry3 };
5472
+ for (const key of TEXT_KEYS) {
5473
+ delete out[key];
5474
+ const value = root[key] ?? builtIn?.[key];
5475
+ if (value !== void 0) Object.assign(out, { [key]: value });
5476
+ }
5477
+ if (part === "title" && root.fontSize !== void 0) out.fontSize = root.fontSize * 1.2;
5478
+ if (root.textEffectsXml !== void 0) out.textEffectsXml = root.textEffectsXml;
5479
+ return out;
5480
+ }
5481
+
5482
+ // chart/render/chart-appearance.ts
5483
+ var chartPointsToPixels = (points) => points * EMU_PER_POINT / EMU_PER_PIXEL;
5484
+ function typeface(entry3, theme) {
5485
+ const name = entry3.typeface;
5486
+ if (name?.startsWith("+mj-")) return theme.majorFont;
5487
+ if (name?.startsWith("+mn-")) return theme.minorFont;
5488
+ return name ?? (entry3.fontRef?.index === "major" ? theme.majorFont : entry3.fontRef?.index === "minor" ? theme.minorFont : void 0);
5489
+ }
5490
+ function chartAppearance(chart, theme) {
5491
+ const defaults = builtInChartTextStyle(effectiveBuiltInChartStyle(chart.formatting));
5492
+ const entries = {};
5493
+ for (const part of CHART_STYLE_PARTS) {
5494
+ const base = chart.styleDefinition?.entries[part];
5495
+ const direct = chart.formatting?.entries[part];
5496
+ if (!defaults[part] && !base && !direct) continue;
5497
+ const entry3 = {
5498
+ ...inheritChartText(
5499
+ part,
5500
+ { ...defaults[part], ...base, sourceXml: base?.sourceXml ?? "" },
5501
+ defaults[part],
5502
+ chart.formatting?.textDefaults
5503
+ ),
5504
+ ...direct,
5505
+ sourceXml: direct?.sourceXml ?? base?.sourceXml ?? ""
5506
+ };
5507
+ if (base?.line || direct?.line) entry3.line = { ...base?.line, ...direct?.line };
5508
+ entries[part] = entry3;
5509
+ }
5510
+ const scheme = chartColorScheme(theme);
5511
+ const resolve = (color) => resolveDrawingColor(
5512
+ color,
5513
+ { scheme: (name) => scheme[name] },
5514
+ { hslRounding: "halfDown", transformOrder: "document" }
5515
+ );
5516
+ const out = resolveChartStyleDefinition(
5517
+ { entries},
5518
+ (color) => drawingColorCss(resolve(color))
5519
+ ) ?? {};
5520
+ for (const part of CHART_STYLE_PARTS) {
5521
+ const entry3 = entries[part];
5522
+ if (!entry3) continue;
5523
+ const family = typeface(entry3, theme);
5524
+ const shadow = resolveDrawingShadowXml(entry3.textEffectsXml, {
5525
+ scheme: (name) => scheme[name]
5526
+ });
5527
+ if (shadow) (out[part] ??= {}).textShadow = shadow;
5528
+ if (family) (out[part] ??= {}).typeface = family;
5529
+ if (entry3.axisVisible !== void 0) (out[part] ??= {}).axisVisible = entry3.axisVisible;
5530
+ if (entry3.labelsVisible !== void 0) (out[part] ??= {}).labelsVisible = entry3.labelsVisible;
5531
+ if (entry3.line?.widthEmu === 0) (out[part] ??= {}).lineWidth = 0;
5532
+ if (entry3.fill?.kind === "gradient") {
5533
+ (out[part] ??= {}).gradient = resolveChartGradient(entry3.fill, resolve);
5534
+ }
5535
+ }
5536
+ return out;
5537
+ }
5538
+
5539
+ // text/css-font-family.ts
5540
+ var FALLBACKS = {
5541
+ calibri: '"Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
5542
+ "calibri light": '"Calibri Light", "Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
5543
+ cambria: '"Cambria", "Caladea", Georgia, serif',
5544
+ arial: 'Arial, "Liberation Sans", Helvetica, sans-serif',
5545
+ "times new roman": '"Times New Roman", "Liberation Serif", Times, serif',
5546
+ "courier new": '"Courier New", "Liberation Mono", monospace',
5547
+ aptos: '"Aptos", "Calibri", "Carlito", "Segoe UI", sans-serif'
5548
+ };
5549
+ function cssFontFamily(name) {
5550
+ const known = FALLBACKS[name.toLowerCase()];
5551
+ if (known) return known;
5552
+ const quoted = `"${name.replace(/["\\]/g, "")}"`;
5553
+ return `${quoted}, "Calibri", "Carlito", "Segoe UI", sans-serif`;
5554
+ }
5555
+
5556
+ // chart/render/chart-svg-appearance.ts
5557
+ var nextPaintId = 0;
5558
+ function chartGradientPaint(model, width = 1024, height = 768) {
5559
+ const prefix = `xlsx-chart-${++nextPaintId}`;
5560
+ const appearance = { ...model.appearance };
5561
+ const defs = [];
5562
+ const shadowPaint = (shadow, suffix) => {
5563
+ const id = `${prefix}-${suffix}`;
5564
+ const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
5565
+ defs.push(
5566
+ `<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
5567
+ );
5568
+ return `url(#${id})`;
5569
+ };
5570
+ for (const [part, entry3] of Object.entries(appearance)) {
5571
+ if (entry3?.textShadow)
5572
+ appearance[part] = {
5573
+ ...entry3,
5574
+ textShadowFilter: shadowPaint(entry3.textShadow, `${part}-text-shadow`)
5575
+ };
5576
+ }
5577
+ const paint2 = (gradient, suffix, bounds) => {
5578
+ const def = buildChartGradientDef(`${prefix}-${suffix}`, gradient, bounds);
5579
+ defs.push(chartGradientMarkup(def));
5580
+ return `url(#${def.id})`;
5581
+ };
5582
+ for (const part of ["chartArea", "plotArea"]) {
5583
+ const entry3 = appearance[part];
5584
+ if (!entry3?.gradient) continue;
5585
+ if (part === "plotArea" && ["circle", "shape"].includes(entry3.gradient.path ?? "")) continue;
5586
+ appearance[part] = {
5587
+ ...entry3,
5588
+ fillColor: paint2(entry3.gradient, part, { width, height, shape: "rect" })
5589
+ };
5590
+ }
5591
+ const series = model.series.map((source, index) => {
5592
+ const view = { ...source };
5593
+ if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
5594
+ const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
5595
+ if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
5596
+ if (source.pointGradients) {
5597
+ view.pointColors = [...source.pointColors ?? []];
5598
+ for (const [key, gradient] of Object.entries(source.pointGradients))
5599
+ view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
5600
+ }
5601
+ return view;
5602
+ });
5603
+ return defs.length ? { model: { ...model, appearance, series }, defs: `<defs>${defs.join("")}</defs>` } : { model, defs: "" };
5604
+ }
5605
+ function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
5606
+ const entry3 = model.appearance?.[part];
5607
+ return {
5608
+ size: entry3?.fontSize === void 0 ? fallbackSize : chartPointsToPixels(entry3.fontSize),
5609
+ ...entry3?.color === void 0 ? {} : { fill: entry3.color },
5610
+ ...entry3?.bold === void 0 ? {} : { weight: entry3.bold ? "bold" : "normal" },
5611
+ ...entry3?.italic === void 0 ? {} : { italic: entry3.italic },
5612
+ ...entry3?.underline === void 0 ? {} : { underline: entry3.underline },
5613
+ ...entry3?.typeface === void 0 ? {} : { family: cssFontFamily(entry3.typeface) },
5614
+ ...entry3?.textShadowFilter === void 0 ? {} : { filter: entry3.textShadowFilter }
5615
+ };
5616
+ }
5617
+ function chartStroke(model, part) {
5618
+ const entry3 = model.appearance?.[part];
5619
+ return {
5620
+ color: entry3?.axisVisible === false ? "none" : entry3?.lineColor ?? (part.startsWith("gridline") ? GRID_COLOR : AXIS_COLOR),
5621
+ width: entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth)
5622
+ };
5623
+ }
5624
+ function chartAreaRect(model, part, area) {
5625
+ if (area.w <= 0 || area.h <= 0) return "";
5626
+ const entry3 = model.appearance?.[part];
5627
+ let fill = entry3?.fillColor ?? (part === "chartArea" ? "#FFFFFF" : "none");
5628
+ let defs = "";
5629
+ if (part !== "chartArea" && entry3?.gradient && (part !== "plotArea" || ["circle", "shape"].includes(entry3.gradient.path ?? ""))) {
5630
+ const def = buildChartGradientDef(`xlsx-chart-${++nextPaintId}-${part}`, entry3.gradient, {
5631
+ width: area.w,
5632
+ height: area.h,
5633
+ shape: "rect"
5634
+ });
5635
+ defs = `<defs>${chartGradientMarkup(def)}</defs>`;
5636
+ fill = `url(#${def.id})`;
5637
+ }
5638
+ const stroke = entry3?.lineColor ?? "none";
5639
+ if (fill === "none" && stroke === "none") return "";
5640
+ const width = entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth);
5641
+ return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
5642
+ }
5643
+
5644
+ // chart/render/chart-svg-labels.ts
5645
+ var GAP = 3;
5646
+ var LINE = 1.2;
5647
+ var NAMED_COLORS = /^(black|blue|cyan|green|magenta|red|white|yellow)$/iu;
5648
+ function measure(model, label) {
5649
+ const attrs = chartTextAttributes(model, "dataLabel", 10);
5650
+ const size = attrs.size ?? 10;
5651
+ const lines = label.text.split("\n");
5652
+ return {
5653
+ lines,
5654
+ size,
5655
+ w: Math.max(...lines.map((l) => textWidth(l, size))),
5656
+ h: lines.length * size * LINE,
5657
+ attrs
5658
+ };
5659
+ }
5660
+ function draw(m, label, x, y, anchor, out) {
5661
+ const fill = label.color && NAMED_COLORS.test(label.color) ? label.color.toLowerCase() : void 0;
5662
+ m.lines.forEach((line2, k) => {
5663
+ const lineY = y - m.h / 2 + (k + 0.5) * m.size * LINE + m.size * 0.35;
5664
+ out.push(text2(x, lineY, line2, { ...m.attrs, ...fill ? { fill } : {}, anchor }));
5665
+ });
5666
+ }
5667
+ function barLabels(model, marks, out) {
5668
+ const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
5669
+ for (const mark of marks) {
5670
+ const label = mark.series.labels?.[mark.index];
5671
+ if (!label) continue;
5672
+ const m = measure(model, label);
5673
+ let position = label.position ?? (stacked ? "ctr" : "outEnd");
5674
+ if (stacked && position === "outEnd") position = "ctr";
5675
+ const cx2 = mark.x + mark.w / 2;
5676
+ const cy = mark.y + mark.h / 2;
5677
+ if (model.horizontal) {
5678
+ const end = mark.negative ? mark.x : mark.x + mark.w;
5679
+ const base = mark.negative ? mark.x + mark.w : mark.x;
5680
+ const dir2 = mark.negative ? -1 : 1;
5681
+ const side = (at, outward) => [
5682
+ at + (outward ? dir2 : -dir2) * GAP,
5683
+ (outward ? dir2 : -dir2) > 0 ? "start" : "end"
5684
+ ];
5685
+ const [x, anchor] = position === "ctr" ? [cx2, "middle"] : position === "inEnd" ? side(end, false) : position === "inBase" ? side(base, true) : side(end, true);
5686
+ draw(m, label, x, cy, anchor, out);
5687
+ continue;
5688
+ }
5689
+ const top = mark.negative ? mark.y + mark.h : mark.y;
5690
+ const bottom = mark.negative ? mark.y : mark.y + mark.h;
5691
+ const dir = mark.negative ? 1 : -1;
5692
+ const y = position === "ctr" ? cy : position === "inEnd" ? top - dir * (GAP + m.h / 2) : position === "inBase" ? bottom + dir * (GAP + m.h / 2) : top + dir * (GAP + m.h / 2);
5693
+ draw(m, label, cx2, y, "middle", out);
5694
+ }
5695
+ }
5696
+ function pointLabels(model, marks, out) {
5697
+ for (const mark of marks) {
5698
+ const label = mark.series.labels?.[mark.index];
5699
+ if (!label) continue;
5700
+ const m = measure(model, label);
5701
+ const reach = mark.radius + GAP;
5702
+ switch (model.type === "area" ? "ctr" : label.position ?? "r") {
5703
+ case "ctr":
5704
+ draw(m, label, mark.x, mark.y, "middle", out);
5705
+ break;
5706
+ case "t":
5707
+ draw(m, label, mark.x, mark.y - reach - m.h / 2, "middle", out);
5708
+ break;
5709
+ case "b":
5710
+ draw(m, label, mark.x, mark.y + reach + m.h / 2, "middle", out);
5711
+ break;
5712
+ case "l":
5713
+ draw(m, label, mark.x - reach, mark.y, "end", out);
5714
+ break;
5715
+ default:
5716
+ draw(m, label, mark.x + reach, mark.y, "start", out);
5717
+ }
5718
+ }
5719
+ }
5720
+ function sliceLabels(model, marks, out) {
5721
+ for (const mark of marks) {
5722
+ const label = mark.series.labels?.[mark.index];
5723
+ if (!label) continue;
5724
+ const m = measure(model, label);
5725
+ const mid = (mark.start + mark.end) / 2;
5726
+ const ux = Math.sin(mid);
5727
+ const uy = -Math.cos(mid);
5728
+ const place = (radius) => [
5729
+ mark.cx + radius * ux,
5730
+ mark.cy + radius * uy
5731
+ ];
5732
+ const position = model.type === "doughnut" ? "ctr" : label.position ?? "bestFit";
5733
+ let x;
5734
+ let y;
5735
+ if (position === "ctr") [x, y] = place(mark.inner + (mark.outer - mark.inner) / 2);
5736
+ else if (position === "inEnd") {
5737
+ const extent = Math.abs(ux) * m.w / 2 + Math.abs(uy) * m.h / 2;
5738
+ [x, y] = place(Math.max(0, mark.outer - GAP - extent));
5739
+ } else if (position === "outEnd") {
5740
+ const extent = Math.abs(ux) * m.w / 2 + Math.abs(uy) * m.h / 2;
5741
+ [x, y] = place(mark.outer + GAP + extent);
5742
+ } else {
5743
+ const placed = placeBestFitLabel(
5744
+ {
5745
+ cx: mark.cx,
5746
+ cy: mark.cy,
5747
+ outerR: mark.outer,
5748
+ startAngle: mark.start - Math.PI / 2,
5749
+ endAngle: mark.end - Math.PI / 2
5750
+ },
5751
+ m.w,
5752
+ m.h
5753
+ );
5754
+ x = placed.x;
5755
+ y = placed.y;
5756
+ }
5757
+ draw(m, label, x, y, "middle", out);
5758
+ }
5759
+ }
5760
+ function hasOutsideLabels(model) {
5761
+ return model.series.some(
5762
+ (s) => s.labels?.some(
5763
+ (l) => l !== void 0 && ["bestFit", "outEnd"].includes(l.position ?? "bestFit")
5764
+ )
5765
+ );
5766
+ }
5767
+
5768
+ // chart/render/chart-svg-bars.ts
5769
+ function barLayout(model, frame) {
5770
+ const count = Math.max(1, model.series.length);
5771
+ const geometry = clusteredBarGeometry(frame.bandSize, count, chartBarSpacing(model));
5772
+ const barSize = geometry.singleBarWidth;
5773
+ const offset = (si) => model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
5774
+ return { barSize, offset };
5775
+ }
5776
+ function bars(model, frame, out, values) {
5777
+ const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
5778
+ const { barSize, offset: barOffset } = barLayout(model, frame);
5779
+ const base = frame.value(0);
5780
+ const pos = new Array(model.categories.length).fill(0);
5781
+ const neg = new Array(model.categories.length).fill(0);
5782
+ const marks = [];
5783
+ model.series.forEach((s, si) => {
5784
+ values[si]?.forEach((v, i) => {
5785
+ if (v === null || i >= model.categories.length) return;
5786
+ let from = 0;
5787
+ let to = v;
5788
+ if (stacked) {
5789
+ const acc = v >= 0 ? pos : neg;
5790
+ from = acc[i] ?? 0;
5791
+ to = from + v;
5792
+ acc[i] = to;
5793
+ }
5794
+ const a2 = stacked ? frame.value(from) : base;
5795
+ const b = frame.value(to);
5796
+ const offset = barOffset(si);
5797
+ const center = frame.band(i);
5798
+ const width = model.horizontal ? Math.abs(b - a2) : barSize;
5799
+ const height = model.horizontal ? barSize : Math.abs(b - a2);
5800
+ let color = s.pointColors?.[i] ?? s.color;
5801
+ const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
5802
+ if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
5803
+ const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
5804
+ if (baseId) {
5805
+ const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
5806
+ const def = buildChartGradientDef(id, gradient, {
5807
+ width: Number(n(width)),
5808
+ height: Number(n(height)),
5809
+ shape: "rect"
5810
+ });
5811
+ out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
5812
+ color = `url(#${id})`;
5813
+ }
5814
+ }
5815
+ out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
5816
+ const box = model.horizontal ? { x: Math.min(a2, b), y: center + offset, w: Math.abs(b - a2), h: barSize } : { x: center + offset, y: Math.min(a2, b), w: barSize, h: Math.abs(b - a2) };
5817
+ out.push(rect(box.x, box.y, box.w, box.h, color, s.shadowFilter));
5818
+ out.push("</g>");
5819
+ marks.push({ series: s, index: i, ...box, negative: v < 0 });
5820
+ });
5821
+ });
5822
+ barLabels(model, marks, out);
5823
+ }
5824
+
5825
+ // chart/render/chart-svg-analysis.ts
5826
+ var DASHES = {
5827
+ dot: [1, 3],
5828
+ dash: [4, 3],
5829
+ lgDash: [8, 3],
5830
+ dashDot: [4, 3, 1, 3],
5831
+ lgDashDot: [8, 3, 1, 3],
5832
+ lgDashDotDot: [8, 3, 1, 3, 1, 3],
5833
+ sysDash: [3, 1],
5834
+ sysDot: [1, 1],
5835
+ sysDashDot: [3, 1, 1, 1],
5836
+ sysDashDotDot: [3, 1, 1, 1, 1, 1]
5837
+ };
5838
+ var CAP = 4;
5839
+ function strokeAttributes(stroke) {
5840
+ const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
5841
+ const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
5842
+ return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
5843
+ }
5844
+ var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
5845
+ function trendlines(series, si, xs, ys, plane, out) {
5846
+ for (const trendline of series.trendlines ?? []) {
5847
+ const fit2 = fitChartTrendline(trendline.fit, xs, ys);
5848
+ if (fit2.points.length < 2) continue;
5849
+ const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
5850
+ out.push(
5851
+ `<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
5852
+ );
5853
+ }
5854
+ }
5855
+ function errorBar(bars2, at, values, plane, out) {
5856
+ const stroke = strokeAttributes(bars2.stroke);
5857
+ for (const side of ["plus", "minus"]) {
5858
+ if (bars2.barType !== side && bars2.barType !== "both") continue;
5859
+ const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
5860
+ const sign = side === "plus" ? 1 : -1;
5861
+ const [x1, y1] = plane(at.x, at.y);
5862
+ const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
5863
+ out.push(segment(x1, y1, x2, y2, stroke));
5864
+ if (!bars2.endCap) continue;
5865
+ if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
5866
+ else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
5867
+ }
5868
+ }
5869
+ function plottedPoints(series, xOf) {
5870
+ return series.values.flatMap((y, index) => {
5871
+ const x = xOf(index);
5872
+ return y === null || x === null ? [] : [{ x, y, index }];
5873
+ });
5874
+ }
5875
+ function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
5876
+ const points = plottedPoints(series, xOf);
5877
+ const xs = points.map((p) => p.x);
5878
+ const ys = points.map((p) => p.y);
5879
+ trendlines(series, si, xs, ys, plane, out);
5880
+ for (const bars2 of series.errorBars ?? []) {
5881
+ if (categoryAxis && bars2.direction === "x") continue;
5882
+ const values = bars2.direction === "x" ? xs : ys;
5883
+ points.forEach(
5884
+ (p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
5885
+ );
5886
+ }
5887
+ }
5888
+ function categoryAnalysis(model, frame, out) {
5889
+ if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
5890
+ const plane = (x, y) => model.horizontal ? [frame.value(y), frame.band(x - 1)] : [frame.band(x - 1), frame.value(y)];
5891
+ const barred = model.type === "bar" || model.type === "column";
5892
+ const layout = barred ? barLayout(model, frame) : void 0;
5893
+ model.series.forEach((series, si) => {
5175
5894
  if (!series.trendlines && !series.errorBars) return;
5176
5895
  const shift = layout ? layout.offset(si) + layout.barSize / 2 : 0;
5177
5896
  const barPlane = (x, y) => {
@@ -5189,6 +5908,60 @@ function scatterAnalysis(model, px, py, out) {
5189
5908
  });
5190
5909
  }
5191
5910
 
5911
+ // chart/render/chart-svg-markers.ts
5912
+ function chartMarkerRadius(series, index, defaultRadius = 3) {
5913
+ const marker = { ...series.marker, ...series.pointMarkers?.[index] };
5914
+ if (marker.symbol === "none") return 0;
5915
+ const radius = markerRadius(marker.size, defaultRadius);
5916
+ return marker.symbol === "dot" ? Math.max(radius * 0.6, 1) : radius;
5917
+ }
5918
+ function chartSeriesMarkerSvg(series, index, cx2, cy, defaultRadius = 3) {
5919
+ const marker = { ...series.marker, ...series.pointMarkers?.[index] };
5920
+ const primitive = buildMarkerPrimitive({
5921
+ ...marker,
5922
+ symbol: marker.symbol,
5923
+ size: marker.size,
5924
+ cx: cx2,
5925
+ cy,
5926
+ fill: marker.fill ?? series.pointColors?.[index] ?? series.color,
5927
+ defaultRadius
5928
+ });
5929
+ if (!primitive) return "";
5930
+ let geometry;
5931
+ switch (primitive.kind) {
5932
+ case "circle":
5933
+ geometry = `cx="${n(primitive.cx)}" cy="${n(primitive.cy)}" r="${n(primitive.r)}"`;
5934
+ break;
5935
+ case "rect":
5936
+ geometry = `x="${n(primitive.x)}" y="${n(primitive.y)}" width="${n(primitive.w)}" height="${n(primitive.h)}"`;
5937
+ break;
5938
+ case "path":
5939
+ geometry = `d="${esc(primitive.d)}"`;
5940
+ break;
5941
+ case "polygon":
5942
+ geometry = `points="${esc(primitive.points)}"`;
5943
+ break;
5944
+ }
5945
+ const outline = primitive.stroke ? ` stroke="${esc(primitive.stroke)}" stroke-width="${n(primitive.strokeWidth ?? 1)}"` : "";
5946
+ const filter = series.shadowFilter ? ` filter="${esc(series.shadowFilter)}"` : "";
5947
+ return `<${primitive.kind} ${geometry} fill="${esc(primitive.fill)}"${outline}${filter}/>`;
5948
+ }
5949
+
5950
+ // chart/line-dash.ts
5951
+ function chartLineDashArray(style, width) {
5952
+ if (!style || style === "solid") {
5953
+ return void 0;
5954
+ }
5955
+ const unit = Math.max(width, 1);
5956
+ if (style === "dot" || style === "sysDot") {
5957
+ return `${unit} ${unit * 2}`;
5958
+ }
5959
+ if (style === "lgDash") {
5960
+ return `${unit * 6} ${unit * 3}`;
5961
+ }
5962
+ return `${unit * 3} ${unit * 2}`;
5963
+ }
5964
+
5192
5965
  // chart/render/chart-scale.ts
5193
5966
  var clean = (n2) => Number(n2.toPrecision(12));
5194
5967
  function* units(raw2) {
@@ -5199,14 +5972,14 @@ function* units(raw2) {
5199
5972
  exp++;
5200
5973
  }
5201
5974
  }
5202
- function niceScale(dataMin, dataMax, options = {}) {
5203
- const maxIntervals = Math.max(1, options.maxIntervals ?? 10);
5975
+ function niceScale(dataMin, dataMax, options2 = {}) {
5976
+ const maxIntervals = Math.max(1, options2.maxIntervals ?? 10);
5204
5977
  let lo = Number.isFinite(dataMin) ? dataMin : 0;
5205
5978
  let hi = Number.isFinite(dataMax) ? dataMax : 0;
5206
5979
  if (lo > hi) [lo, hi] = [hi, lo];
5207
5980
  if (lo === hi) {
5208
5981
  if (lo === 0) hi = 1;
5209
- else if (options.noZero) {
5982
+ else if (options2.noZero) {
5210
5983
  const pad = Math.abs(lo) * 0.1 || 1;
5211
5984
  lo -= pad;
5212
5985
  hi += pad;
@@ -5215,7 +5988,7 @@ function niceScale(dataMin, dataMax, options = {}) {
5215
5988
  }
5216
5989
  let fixedLo = false;
5217
5990
  let fixedHi = false;
5218
- if (!options.noZero) {
5991
+ if (!options2.noZero) {
5219
5992
  if (lo >= 0 && hi - lo >= hi / 6) {
5220
5993
  lo = 0;
5221
5994
  fixedLo = true;
@@ -5255,196 +6028,327 @@ function formatAxisValue(value, percent = false) {
5255
6028
  return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
5256
6029
  }
5257
6030
 
5258
- // drawingml/drawing-color-css.ts
5259
- function drawingColorCss(value) {
5260
- if (!value || value.alpha === 1) return value?.hex;
5261
- const channels = [1, 3, 5].map(
5262
- (offset) => Number.parseInt(value.hex.slice(offset, offset + 2), 16)
6031
+ // chart/render/chart-svg-axes.ts
6032
+ function axisTickText(value, axis, percent = false) {
6033
+ return formatChartNumber(value, axis?.source.numberFormat?.formatCode) ?? formatAxisValue(value, percent);
6034
+ }
6035
+ function axisLine(model, axis, part, x1, y1, x2, y2) {
6036
+ if (axis?.source.deleted) return "";
6037
+ return styledAxisLine(x1, y1, x2, y2, axis?.line, chartStroke(model, part));
6038
+ }
6039
+ function styledAxisLine(x1, y1, x2, y2, paint2, fallback) {
6040
+ const color = paint2?.color ?? fallback.color;
6041
+ const width = paint2?.width ?? fallback.width;
6042
+ if (color === "none" || width === 0) return "";
6043
+ const dash = chartLineDashArray(paint2?.dash, width);
6044
+ return line(x1, y1, x2, y2, esc(color), width).replace(
6045
+ "/>",
6046
+ dash ? ` stroke-dasharray="${dash}"/>` : "/>"
5263
6047
  );
5264
- return `rgba(${channels.join(",")},${value.alpha})`;
6048
+ }
6049
+ function axisGridlines(model, axis, ticks, position, plot, vertical) {
6050
+ const draw2 = (values, paint2, minor2) => {
6051
+ const fallback = chartStroke(model, minor2 ? "gridlineMinor" : "gridlineMajor");
6052
+ return values.map((value) => {
6053
+ const p = position(value);
6054
+ return vertical ? styledAxisLine(p, plot.y, p, plot.y + plot.h, paint2, fallback) : styledAxisLine(plot.x, p, plot.x + plot.w, p, paint2, fallback);
6055
+ }).join("");
6056
+ };
6057
+ const major = !axis || axis.source.majorGridlines ? draw2(ticks, axis?.majorGrid, false) : "";
6058
+ const minor = axis?.source.minorGridlines ? draw2(axis.minorTicks, axis.minorGrid, true) : "";
6059
+ return major + minor;
5265
6060
  }
5266
6061
 
5267
- // units/constants.ts
5268
- var EMU_PER_PIXEL = 9525;
5269
- var EMU_PER_POINT = 12700;
6062
+ // chart/axis-range-auto.ts
6063
+ function computeAxisValueRange(series, plotHeightPx) {
6064
+ let dataMin = Number.POSITIVE_INFINITY, dataMax = Number.NEGATIVE_INFINITY;
6065
+ for (const item of series) {
6066
+ for (const value of item.values) {
6067
+ if (value !== null && Number.isFinite(value) && value < dataMin) {
6068
+ dataMin = value;
6069
+ }
6070
+ if (value !== null && Number.isFinite(value) && value > dataMax) {
6071
+ dataMax = value;
6072
+ }
6073
+ }
6074
+ }
6075
+ if (dataMin === Number.POSITIVE_INFINITY) {
6076
+ return { min: 0, max: 1, span: 1 };
6077
+ }
6078
+ const { min, max, majorUnit } = niceValueAxisBounds(
6079
+ dataMin,
6080
+ dataMax,
6081
+ plotHeightPx !== void 0 ? axisTargetIntervals(plotHeightPx) : void 0
6082
+ );
6083
+ return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
6084
+ }
6085
+ function computeAxisStackedValueRange(series, catCount, plotHeightPx) {
6086
+ let maxSum = 0, minSum = 0;
6087
+ for (let ci = 0; ci < catCount; ci++) {
6088
+ let pos = 0, neg = 0;
6089
+ for (const s of series) {
6090
+ const v = s.values[ci] ?? 0;
6091
+ if (v >= 0) {
6092
+ pos += v;
6093
+ } else {
6094
+ neg += v;
6095
+ }
6096
+ }
6097
+ maxSum = Math.max(maxSum, pos);
6098
+ minSum = Math.min(minSum, neg);
6099
+ }
6100
+ const { min, max, majorUnit } = niceValueAxisBounds(
6101
+ Math.min(minSum, 0),
6102
+ Math.max(maxSum, 0),
6103
+ plotHeightPx !== void 0 ? axisTargetIntervals(plotHeightPx) : void 0
6104
+ );
6105
+ return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
6106
+ }
5270
6107
 
5271
- // drawingml/drawing-shadow.ts
5272
- function resolveDrawingShadow(effects, theme) {
5273
- const node = first(effects, "outerShdw", NS.a);
5274
- if (!node) return void 0;
5275
- const value = (key, fallback) => Number(node.getAttribute(key) ?? fallback);
5276
- if (value("sx", 1e5) !== 1e5 || value("sy", 1e5) !== 1e5 || value("kx", 0) !== 0 || value("ky", 0) !== 0)
5277
- return void 0;
5278
- const color = parseDrawingColorIn(node);
5279
- const resolved = color && resolveDrawingColor(color, theme, { transformOrder: "document" });
5280
- const blur = value("blurRad", 0) / EMU_PER_PIXEL;
5281
- const distance = value("dist", 0) / EMU_PER_PIXEL;
5282
- const angle = value("dir", 0) / 6e4 * Math.PI / 180;
5283
- if (!resolved || ![blur, distance, angle].every(Number.isFinite) || blur < 0 || distance < 0)
5284
- return void 0;
6108
+ // chart/axis-range.ts
6109
+ function computeLogValueRange(series, logBase) {
6110
+ const allValues = series.flatMap((item) => item.values).filter((value) => value !== null && Number.isFinite(value) && value > 0);
6111
+ if (allValues.length === 0) {
6112
+ return { min: 1, max: logBase, span: 1, logScale: true, logBase };
6113
+ }
6114
+ const dataMin = Math.min(...allValues);
6115
+ const dataMax = Math.max(...allValues);
6116
+ const logMin = Math.floor(Math.log(dataMin) / Math.log(logBase));
6117
+ const logMax = Math.ceil(Math.log(dataMax) / Math.log(logBase));
6118
+ const min = logBase ** logMin;
6119
+ const max = logBase ** Math.max(logMax, logMin + 1);
5285
6120
  return {
5286
- color: resolved.hex,
5287
- opacity: resolved.alpha,
5288
- blur,
5289
- dx: Math.cos(angle) * distance,
5290
- dy: Math.sin(angle) * distance
6121
+ min,
6122
+ max,
6123
+ span: Math.max(Math.log(max) / Math.log(logBase) - Math.log(min) / Math.log(logBase), 1),
6124
+ logScale: true,
6125
+ logBase
5291
6126
  };
5292
6127
  }
5293
- function resolveDrawingShadowXml(xml, theme) {
5294
- return xml ? resolveDrawingShadow(parseXml(xml).documentElement, theme) : void 0;
6128
+ function computeValueRangeForAxis(series, axis, plotHeightPx) {
6129
+ const requestedLogBase = axis?.logBase ?? 10;
6130
+ const logBase = axis?.logScale && Number.isFinite(requestedLogBase) && requestedLogBase > 1 ? requestedLogBase : axis?.logScale ? 10 : void 0;
6131
+ const automatic = logBase ? computeLogValueRange(series, logBase) : computeAxisValueRange(series, plotHeightPx);
6132
+ return withAxisBounds(automatic, axis, logBase);
5295
6133
  }
5296
- function svgDropShadowElement(s, format) {
5297
- const num = format.number;
5298
- return `<feDropShadow dx="${num(s.dx)}" dy="${num(s.dy)}" stdDeviation="${num(s.blur / 2)}" flood-color="${format.color(s.color, "#000000")}" flood-opacity="${num(s.opacity)}" result="shadow"/>`;
6134
+ function computeStackedValueRangeForAxis(series, catCount, axis, isPercent, plotSizePx) {
6135
+ if (isPercent) {
6136
+ return {
6137
+ ...percentStackedRange(series, catCount, plotSizePx),
6138
+ ...axis?.orientation === "maxMin" ? { reverseOrder: true } : {}
6139
+ };
6140
+ }
6141
+ return withAxisBounds(computeAxisStackedValueRange(series, catCount, plotSizePx), axis);
5299
6142
  }
5300
-
5301
- // chart/render/theme-palette.ts
5302
- var THEME_SLOTS = [
5303
- "lt1",
5304
- "dk1",
5305
- "lt2",
5306
- "dk2",
5307
- "accent1",
5308
- "accent2",
5309
- "accent3",
5310
- "accent4",
5311
- "accent5",
5312
- "accent6",
5313
- "hlink",
5314
- "folHlink"
5315
- ];
5316
- var DEFAULT_THEME_COLORS = [
5317
- "FFFFFF",
5318
- "000000",
5319
- "E7E6E6",
5320
- "44546A",
5321
- "4472C4",
5322
- "ED7D31",
5323
- "A5A5A5",
5324
- "FFC000",
5325
- "5B9BD5",
5326
- "70AD47",
5327
- "0563C1",
5328
- "954F72"
5329
- ];
5330
- function themeColor(theme, index) {
5331
- const hex = theme.colors[index] ?? DEFAULT_THEME_COLORS[index];
5332
- return hex && parseArgbHex(hex) ? hex.replace(/^#/, "") : void 0;
6143
+ function percentStackedRange(series, catCount, plotSizePx) {
6144
+ const shares = series.map((entry3) => ({
6145
+ ...entry3,
6146
+ values: Array.from({ length: catCount }, (_, ci) => {
6147
+ const total = series.reduce((sum, s) => sum + Math.abs(s.values[ci] ?? 0), 0);
6148
+ return total > 0 ? (entry3.values[ci] ?? 0) / total * 100 : 0;
6149
+ })
6150
+ }));
6151
+ const automatic = computeAxisStackedValueRange(shares, catCount, plotSizePx);
6152
+ if (automatic.min >= 0) {
6153
+ return { min: 0, max: 100, span: 100 };
6154
+ }
6155
+ const min = Math.max(automatic.min, -100);
6156
+ const unit = automatic.majorUnit;
6157
+ return {
6158
+ min,
6159
+ max: 100,
6160
+ span: 100 - min,
6161
+ ...unit !== void 0 && 100 % unit === 0 && min % unit === 0 ? { majorUnit: unit } : {}
6162
+ };
5333
6163
  }
5334
-
5335
- // chart/render/chart-colors.ts
5336
- function chartColorScheme(theme) {
5337
- const slots = Object.fromEntries(
5338
- THEME_SLOTS.map((slot, index) => [slot, `#${themeColor(theme, index) ?? "000000"}`])
5339
- );
6164
+ function withAxisBounds(automatic, axis, logBase) {
6165
+ const validMin = typeof axis?.min === "number" && Number.isFinite(axis.min) && (!logBase || axis.min > 0) ? axis.min : void 0;
6166
+ const validMax = typeof axis?.max === "number" && Number.isFinite(axis.max) && (!logBase || axis.max > 0) ? axis.max : void 0;
6167
+ const min = validMin ?? automatic.min;
6168
+ let max = validMax ?? automatic.max;
6169
+ const majorUnit = validMin === void 0 && validMax === void 0 ? automatic.majorUnit : void 0;
6170
+ if (max <= min) {
6171
+ max = logBase ? min * logBase : min + 1;
6172
+ }
6173
+ const span = logBase ? Math.log(max) / Math.log(logBase) - Math.log(min) / Math.log(logBase) : max - min;
5340
6174
  return {
5341
- ...slots,
5342
- bg1: slots.lt1,
5343
- tx1: slots.dk1,
5344
- bg2: slots.lt2,
5345
- tx2: slots.dk2
6175
+ min,
6176
+ max,
6177
+ span: Math.max(span, Number.EPSILON),
6178
+ ...majorUnit !== void 0 ? { majorUnit } : {},
6179
+ ...logBase ? { logScale: true, logBase } : {},
6180
+ ...axis?.orientation === "maxMin" ? { reverseOrder: true } : {}
5346
6181
  };
5347
6182
  }
5348
- function modulateLuminance(hex, lumMod, lumOff = 0) {
5349
- const rgb = parseArgbHex(hex);
5350
- if (!rgb) return "#000000";
5351
- if (lumMod === 1 && lumOff === 0) return rgbToUpperHex(rgb);
5352
- const hsl = rgbToHsl(...rgb);
5353
- const l = Math.max(0, Math.min(1, hsl.l * lumMod + lumOff));
5354
- const out = hslToRgb(hsl.h, hsl.s, l);
5355
- return rgbToUpperHex([out.r, out.g, out.b]);
6183
+ function valueToYLog(val, range, topY, bottomY) {
6184
+ const base = range.logBase ?? 10;
6185
+ const logValue = Math.log(Math.max(val, range.min)) / Math.log(base);
6186
+ const logMin = Math.log(range.min) / Math.log(base);
6187
+ const ratio = (logValue - logMin) / range.span;
6188
+ return range.reverseOrder ? topY + ratio * (bottomY - topY) : bottomY - ratio * (bottomY - topY);
6189
+ }
6190
+ function findLogAxis(axes) {
6191
+ return axes?.find((axis) => axis.axisType === "valAx" && axis.logScale);
6192
+ }
6193
+ function computeValueRangeForChart(series, axes, plotHeightPx) {
6194
+ const primaryAxis = axes?.find((axis) => axis.axisType === "valAx" && axis.axPos === "l") ?? axes?.find((axis) => axis.axisType === "valAx" && axis.axPos !== "r");
6195
+ return computeValueRangeForAxis(series, primaryAxis, plotHeightPx);
6196
+ }
6197
+
6198
+ // chart/axis-ticks.ts
6199
+ var LOG_EXPONENT_TOLERANCE = 1e-12;
6200
+ function generateLogTicks(range) {
6201
+ if (!range.logScale || !range.logBase) {
6202
+ return [];
6203
+ }
6204
+ const base = range.logBase;
6205
+ const logMin = Math.log(range.min) / Math.log(base);
6206
+ const logMax = Math.log(range.max) / Math.log(base);
6207
+ const firstExponent = Math.ceil(logMin - LOG_EXPONENT_TOLERANCE);
6208
+ const lastExponent = Math.floor(logMax + LOG_EXPONENT_TOLERANCE);
6209
+ if (lastExponent < firstExponent) {
6210
+ return range.min === range.max ? [range.min] : [range.min, range.max];
6211
+ }
6212
+ return Array.from(
6213
+ { length: lastExponent - firstExponent + 1 },
6214
+ (_unused, index) => base ** (firstExponent + index)
6215
+ );
6216
+ }
6217
+ function generateIntervalTicks(range, unit) {
6218
+ if (!Number.isFinite(unit) || unit <= 0 || range.logScale) {
6219
+ return [];
6220
+ }
6221
+ const tolerance = Math.max(1, Math.abs(range.min), Math.abs(range.max)) * 1e-12;
6222
+ const first2 = Math.ceil((range.min - tolerance) / unit);
6223
+ const last = Math.floor((range.max + tolerance) / unit);
6224
+ const count = Math.min(Math.max(last - first2 + 1, 0), 2e3);
6225
+ return Array.from({ length: count }, (_, index) => (first2 + index) * unit);
5356
6226
  }
5357
- function autoSeriesColor(theme, index) {
5358
- const i = Math.max(0, Math.floor(index));
5359
- return chartPaletteSeriesColor(findChartColorPalette(10), i, i + 1, chartColorScheme(theme));
6227
+ function generateAxisTicks(range, axis, defaultIntervals) {
6228
+ if (range.logScale && range.logBase) {
6229
+ return generateLogTicks(range);
6230
+ }
6231
+ const explicit = generateIntervalTicks(range, axis?.majorUnit ?? 0);
6232
+ if (explicit.length > 0) {
6233
+ return explicit;
6234
+ }
6235
+ const automatic = generateIntervalTicks(range, range.majorUnit ?? 0);
6236
+ if (automatic.length > 0) {
6237
+ return automatic;
6238
+ }
6239
+ return Array.from(
6240
+ { length: defaultIntervals + 1 },
6241
+ (_, index) => range.min + range.span / defaultIntervals * index
6242
+ );
5360
6243
  }
5361
-
5362
- // chart/text-inheritance.ts
5363
- var TEXT_KEYS = [
5364
- "fontSize",
5365
- "bold",
5366
- "italic",
5367
- "underline",
5368
- "typeface",
5369
- "textColor",
5370
- "fontRef"
5371
- ];
5372
- var TEXT_PARTS = [
5373
- "title",
5374
- "axisTitle",
5375
- "categoryAxis",
5376
- "valueAxis",
5377
- "legend",
5378
- "dataLabel"
5379
- ];
5380
- function inheritChartText(part, entry3, builtIn, root) {
5381
- if (!root || !TEXT_PARTS.includes(part)) return entry3;
5382
- const out = { ...entry3 };
5383
- for (const key of TEXT_KEYS) {
5384
- delete out[key];
5385
- const value = root[key] ?? builtIn?.[key];
5386
- if (value !== void 0) Object.assign(out, { [key]: value });
6244
+ function generateMinorAxisTicks(range, axis) {
6245
+ const minor = generateIntervalTicks(range, axis?.minorUnit ?? 0);
6246
+ if (minor.length === 0) {
6247
+ return [];
5387
6248
  }
5388
- if (part === "title" && root.fontSize !== void 0) out.fontSize = root.fontSize * 1.2;
5389
- if (root.textEffectsXml !== void 0) out.textEffectsXml = root.textEffectsXml;
5390
- return out;
6249
+ const majorUnit = axis?.majorUnit;
6250
+ if (!majorUnit || !Number.isFinite(majorUnit) || majorUnit <= 0) {
6251
+ return minor;
6252
+ }
6253
+ const tolerance = Math.max(1, Math.abs(range.min), Math.abs(range.max)) * 1e-10;
6254
+ return minor.filter(
6255
+ (value) => Math.abs(value / majorUnit - Math.round(value / majorUnit)) > tolerance
6256
+ );
5391
6257
  }
5392
6258
 
5393
- // chart/render/chart-appearance.ts
5394
- var chartPointsToPixels = (points) => points * EMU_PER_POINT / EMU_PER_PIXEL;
5395
- function typeface(entry3, theme) {
5396
- const name = entry3.typeface;
5397
- if (name?.startsWith("+mj-")) return theme.majorFont;
5398
- if (name?.startsWith("+mn-")) return theme.minorFont;
5399
- return name ?? (entry3.fontRef?.index === "major" ? theme.majorFont : entry3.fontRef?.index === "minor" ? theme.minorFont : void 0);
6259
+ // chart/render/chart-view-axes.ts
6260
+ function chartAxisRatio(value, scale, axis) {
6261
+ const range = axis?.range;
6262
+ const ratio = range?.logScale ? Math.log(Math.max(value, range.min) / range.min) / Math.log(range.max / range.min) : (value - scale.min) / (scale.max - scale.min || 1);
6263
+ return range?.reverseOrder ? 1 - ratio : ratio;
5400
6264
  }
5401
- function chartAppearance(chart, theme) {
5402
- const defaults = builtInChartTextStyle(effectiveBuiltInChartStyle(chart.formatting));
5403
- const entries = {};
5404
- for (const part of CHART_STYLE_PARTS) {
5405
- const base = chart.styleDefinition?.entries[part];
5406
- const direct = chart.formatting?.entries[part];
5407
- if (!defaults[part] && !base && !direct) continue;
5408
- const entry3 = {
5409
- ...inheritChartText(
5410
- part,
5411
- { ...defaults[part], ...base, sourceXml: base?.sourceXml ?? "" },
5412
- defaults[part],
5413
- chart.formatting?.textDefaults
5414
- ),
5415
- ...direct,
5416
- sourceXml: direct?.sourceXml ?? base?.sourceXml ?? ""
5417
- };
5418
- if (base?.line || direct?.line) entry3.line = { ...base?.line, ...direct?.line };
5419
- entries[part] = entry3;
5420
- }
5421
- const scheme = chartColorScheme(theme);
5422
- const resolve = (color) => resolveDrawingColor(
5423
- color,
5424
- { scheme: (name) => scheme[name] },
5425
- { hslRounding: "halfDown", transformOrder: "document" }
6265
+ function chartAxisLabels(axis) {
6266
+ return axis?.source.deleted !== true && axis?.source.tickLabelPosition !== "none";
6267
+ }
6268
+ function options(axis) {
6269
+ return {
6270
+ ...axis.scaling,
6271
+ ...axis.scaling.logBase === void 0 ? {} : { logScale: true },
6272
+ ...axis.majorUnit === void 0 ? {} : { majorUnit: axis.majorUnit },
6273
+ ...axis.minorUnit === void 0 ? {} : { minorUnit: axis.minorUnit }
6274
+ };
6275
+ }
6276
+ function applyChartAxes(model, chart, color) {
6277
+ if (!chart.axes?.length) return;
6278
+ const axes = chart.axes;
6279
+ const linked = axes.filter((axis) => axis.id !== void 0 && chart.axisIds?.includes(axis.id));
6280
+ const candidates = linked.length ? linked : axes;
6281
+ const xy = model.type === "scatter" || model.type === "bubble";
6282
+ const value = candidates.find((axis) => axis.kind === "val" && !["b", "t"].includes(axis.position ?? "")) ?? candidates.find((axis) => axis.kind === "val");
6283
+ const category = candidates.find(
6284
+ (axis) => xy ? axis.kind === "val" && axis !== value : axis.kind === "cat" || axis.kind === "date"
5426
6285
  );
5427
- const out = resolveChartStyleDefinition(
5428
- { entries},
5429
- (color) => drawingColorCss(resolve(color))
5430
- ) ?? {};
5431
- for (const part of CHART_STYLE_PARTS) {
5432
- const entry3 = entries[part];
5433
- if (!entry3) continue;
5434
- const family = typeface(entry3, theme);
5435
- const shadow = resolveDrawingShadowXml(entry3.textEffectsXml, {
5436
- scheme: (name) => scheme[name]
5437
- });
5438
- if (shadow) (out[part] ??= {}).textShadow = shadow;
5439
- if (family) (out[part] ??= {}).typeface = family;
5440
- if (entry3.axisVisible !== void 0) (out[part] ??= {}).axisVisible = entry3.axisVisible;
5441
- if (entry3.labelsVisible !== void 0) (out[part] ??= {}).labelsVisible = entry3.labelsVisible;
5442
- if (entry3.line?.widthEmu === 0) (out[part] ??= {}).lineWidth = 0;
5443
- if (entry3.fill?.kind === "gradient") {
5444
- (out[part] ??= {}).gradient = resolveChartGradient(entry3.fill, resolve);
6286
+ const secondary = axes.find((axis) => axis.kind === "val" && axis !== value && axis !== category);
6287
+ const paint2 = (shape) => {
6288
+ const ln = shape?.line;
6289
+ const fill = ln?.fill;
6290
+ const resolved = fill?.kind === "none" ? "none" : color(fill?.kind === "solid" ? fill.color : void 0);
6291
+ return {
6292
+ ...resolved === void 0 ? {} : { color: resolved },
6293
+ ...ln?.widthEmu === void 0 ? {} : { width: ln.widthEmu / EMU_PER_PIXEL },
6294
+ ...ln?.dash === void 0 ? {} : { dash: ln.dash }
6295
+ };
6296
+ };
6297
+ const bind = (axis, scale, values) => {
6298
+ const opts = options(axis);
6299
+ const automatic = opts.logScale ? computeLogValueRange(
6300
+ [{ values: values ?? [] }],
6301
+ opts.logBase && Number.isFinite(opts.logBase) && opts.logBase > 1 ? opts.logBase : 10
6302
+ ) : {
6303
+ min: scale?.min ?? 0,
6304
+ max: scale?.max ?? 1,
6305
+ span: (scale?.max ?? 1) - (scale?.min ?? 0),
6306
+ ...scale ? { majorUnit: scale.majorUnit } : {}
6307
+ };
6308
+ const logBase = automatic.logBase;
6309
+ const range = withAxisBounds(automatic, opts, logBase);
6310
+ if (scale) {
6311
+ scale.min = range.min;
6312
+ scale.max = range.max;
6313
+ scale.ticks = generateAxisTicks(range, opts, 5);
5445
6314
  }
5446
- }
5447
- return out;
6315
+ return {
6316
+ source: axis,
6317
+ range,
6318
+ minorTicks: generateMinorAxisTicks(range, opts),
6319
+ line: paint2(axis.spPr),
6320
+ majorGrid: paint2(axis.majorGridlinesSpPr),
6321
+ minorGrid: paint2(axis.minorGridlinesSpPr)
6322
+ };
6323
+ };
6324
+ const out = {};
6325
+ if (value)
6326
+ out.value = bind(
6327
+ value,
6328
+ model.valueAxis,
6329
+ [
6330
+ ...model.series,
6331
+ ...model.extraGroups?.filter((g) => !g.secondary).flatMap((g) => g.series) ?? []
6332
+ ].flatMap((s) => s.values)
6333
+ );
6334
+ if (category)
6335
+ out.category = bind(
6336
+ category,
6337
+ model.xAxis ?? {
6338
+ min: 0,
6339
+ max: Math.max(1, model.categories.length - 1),
6340
+ majorUnit: 1,
6341
+ ticks: []
6342
+ },
6343
+ model.series.flatMap((s) => s.xValues ?? [])
6344
+ );
6345
+ if (secondary)
6346
+ out.secondary = bind(
6347
+ secondary,
6348
+ model.secondaryAxis,
6349
+ model.extraGroups?.filter((g) => g.secondary).flatMap((g) => g.series.flatMap((s) => s.values))
6350
+ );
6351
+ model.axes = out;
5448
6352
  }
5449
6353
 
5450
6354
  // chart/render/chart-view-analysis.ts
@@ -5496,15 +6400,15 @@ function seriesName(series, index, evaluateRef) {
5496
6400
  const fromRef = resolveRef(series.nameRef, evaluateRef)?.map(toText).filter((t) => t !== "").join(" ");
5497
6401
  return fromRef || series.name || `Series${index + 1}`;
5498
6402
  }
5499
- function seriesContext(chart, theme, options) {
6403
+ function seriesContext(chart, theme, options2) {
5500
6404
  const scheme = chartColorScheme(theme);
5501
6405
  const resolver = { scheme: (name) => scheme[name] };
5502
6406
  return {
5503
6407
  theme,
5504
6408
  scheme,
5505
6409
  palette: chart.colorPalette === void 0 ? void 0 : findChartColorPalette(chart.colorPalette),
5506
- evaluateRef: options.evaluateRef ?? (() => []),
5507
- seriesColor: options.seriesColor,
6410
+ evaluateRef: options2.evaluateRef ?? (() => []),
6411
+ seriesColor: options2.seriesColor,
5508
6412
  drawingColor: (color) => color && drawingColorCss(resolveDrawingColor(color, resolver, { transformOrder: "document" })),
5509
6413
  gradient: (fill) => fill?.kind === "gradient" ? resolveChartGradient(
5510
6414
  fill,
@@ -5530,7 +6434,11 @@ function seriesView(ctx, s, index, total, categoriesOf) {
5530
6434
  })
5531
6435
  );
5532
6436
  if (Object.keys(points).length) view.pointGradients = points;
5533
- Object.assign(view, analysisView(s, color, ctx.drawingColor));
6437
+ Object.assign(
6438
+ view,
6439
+ analysisView(s, color, ctx.drawingColor),
6440
+ seriesMarkerViews(s, ctx.drawingColor)
6441
+ );
5534
6442
  return view;
5535
6443
  }
5536
6444
 
@@ -5703,6 +6611,64 @@ function chartTitleText(chart, theme) {
5703
6611
  };
5704
6612
  }
5705
6613
 
6614
+ // chart/render/chart-view-labels.ts
6615
+ function labelsOf(source, view, categories, numberFormat2) {
6616
+ const { chart, series, points } = source;
6617
+ if ((series?.deleted ?? chart?.deleted) === true) return void 0;
6618
+ const percentBase = view.values.reduce(
6619
+ (sum, v) => sum + (v === null ? 0 : Math.abs(v)),
6620
+ 0
6621
+ );
6622
+ const out = [];
6623
+ let any = false;
6624
+ view.values.forEach((value, i) => {
6625
+ const point = points?.[i];
6626
+ if (value === null || point?.deleted === true) return;
6627
+ const position = point?.position ?? series?.position ?? chart?.position;
6628
+ const x = view.xValues?.[i];
6629
+ const category = x === void 0 || x === null ? categories[i] : formatAxisValue(x);
6630
+ let built;
6631
+ if (point?.text !== void 0) built = { text: point.text };
6632
+ else {
6633
+ const flags = resolveDataLabelFlags({
6634
+ ...point ? { point } : {},
6635
+ ...series ? { series } : {},
6636
+ ...chart ? { chart } : {}
6637
+ });
6638
+ built = composeDataLabelText({
6639
+ flags,
6640
+ seriesName: view.name,
6641
+ category,
6642
+ value,
6643
+ numberFormat: point?.numberFormat ?? series?.numberFormat ?? chart?.numberFormat ?? numberFormat2,
6644
+ percentBase,
6645
+ bubbleSize: view.sizes?.[i] ?? void 0,
6646
+ formatValue: (v) => formatAxisValue(v),
6647
+ formatBubbleSize: (size) => formatAxisValue(size)
6648
+ });
6649
+ }
6650
+ if (!built) return;
6651
+ any = true;
6652
+ out[i] = {
6653
+ text: built.text,
6654
+ ...position ? { position } : {},
6655
+ ...built.color ? { color: built.color } : {}
6656
+ };
6657
+ });
6658
+ return any ? out : void 0;
6659
+ }
6660
+ function applyDataLabels(model, sources, extra) {
6661
+ const apply = (source, view) => {
6662
+ if (!source?.dataLabels) return;
6663
+ const labels = labelsOf(source.dataLabels, view, model.categories, source.numberFormat);
6664
+ if (labels) view.labels = labels;
6665
+ };
6666
+ model.series.forEach((view, i) => apply(sources[i], view));
6667
+ model.extraGroups?.forEach(
6668
+ (group2, g) => group2.series.forEach((view, i) => apply(extra[g]?.series[i], view))
6669
+ );
6670
+ }
6671
+
5706
6672
  // chart/render/chart-view-ex.ts
5707
6673
  function groupsAxis(groups, categories) {
5708
6674
  let min = Infinity;
@@ -5772,11 +6738,11 @@ function histogramView(chart, model) {
5772
6738
  const first2 = model.series[0];
5773
6739
  if (!first2) return;
5774
6740
  const raw2 = first2.values.map((v) => v ?? Number.NaN);
5775
- const options = chart.histogram ?? {};
5776
- const bins = options.aggregateByCategory ? aggregateByCategory(
6741
+ const options2 = chart.histogram ?? {};
6742
+ const bins = options2.aggregateByCategory ? aggregateByCategory(
5777
6743
  first2.values.map((v) => v ?? 0),
5778
6744
  model.categories
5779
- ) : computeHistogramBins(raw2, options, formatAxisValue);
6745
+ ) : computeHistogramBins(raw2, options2, formatAxisValue);
5780
6746
  model.categories = bins.map((bin) => bin.label);
5781
6747
  first2.values = bins.map((bin) => bin.value);
5782
6748
  model.barGapWidth = 0;
@@ -5800,11 +6766,11 @@ var SUPPORTED = /* @__PURE__ */ new Set([
5800
6766
  "treemap",
5801
6767
  "sunburst"
5802
6768
  ]);
5803
- function chartSummaryView(chart, theme, options = {}) {
6769
+ function chartSummaryView(chart, theme, options2 = {}) {
5804
6770
  const type = chart.chartType;
5805
6771
  const radial = type === "pie" || type === "doughnut";
5806
6772
  const byPoint = radial || type === "treemap" || type === "sunburst";
5807
- const ctx = seriesContext(chart, theme, options);
6773
+ const ctx = seriesContext(chart, theme, options2);
5808
6774
  const { palette, scheme, drawingColor } = ctx;
5809
6775
  const grouping = chart.grouping ?? (type === "bar" || type === "column" ? "clustered" : "standard");
5810
6776
  const rawCategories = [];
@@ -5888,128 +6854,23 @@ function chartSummaryView(chart, theme, options = {}) {
5888
6854
  chartExtraView(chart, model, ctx, total, collect);
5889
6855
  if (type === "waterfall") waterfallView(chart, model, ctx);
5890
6856
  else if (!byPoint) model.valueAxis = valueAxis(model);
6857
+ applyDataLabels(model, chart.series, extra);
5891
6858
  chartExtraAxes(model);
6859
+ applyChartAxes(model, chart, ctx.drawingColor);
5892
6860
  return model;
5893
6861
  }
5894
6862
 
5895
- // text/css-font-family.ts
5896
- var FALLBACKS = {
5897
- calibri: '"Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
5898
- "calibri light": '"Calibri Light", "Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
5899
- cambria: '"Cambria", "Caladea", Georgia, serif',
5900
- arial: 'Arial, "Liberation Sans", Helvetica, sans-serif',
5901
- "times new roman": '"Times New Roman", "Liberation Serif", Times, serif',
5902
- "courier new": '"Courier New", "Liberation Mono", monospace',
5903
- aptos: '"Aptos", "Calibri", "Carlito", "Segoe UI", sans-serif'
5904
- };
5905
- function cssFontFamily(name) {
5906
- const known = FALLBACKS[name.toLowerCase()];
5907
- if (known) return known;
5908
- const quoted = `"${name.replace(/["\\]/g, "")}"`;
5909
- return `${quoted}, "Calibri", "Carlito", "Segoe UI", sans-serif`;
5910
- }
5911
-
5912
- // chart/render/chart-svg-appearance.ts
5913
- var nextPaintId = 0;
5914
- function chartGradientPaint(model, width = 1024, height = 768) {
5915
- const prefix = `xlsx-chart-${++nextPaintId}`;
5916
- const appearance = { ...model.appearance };
5917
- const defs = [];
5918
- const shadowPaint = (shadow, suffix) => {
5919
- const id = `${prefix}-${suffix}`;
5920
- const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
5921
- defs.push(
5922
- `<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
5923
- );
5924
- return `url(#${id})`;
5925
- };
5926
- for (const [part, entry3] of Object.entries(appearance)) {
5927
- if (entry3?.textShadow)
5928
- appearance[part] = {
5929
- ...entry3,
5930
- textShadowFilter: shadowPaint(entry3.textShadow, `${part}-text-shadow`)
5931
- };
5932
- }
5933
- const paint2 = (gradient, suffix, bounds) => {
5934
- const def = buildChartGradientDef(`${prefix}-${suffix}`, gradient, bounds);
5935
- defs.push(chartGradientMarkup(def));
5936
- return `url(#${def.id})`;
5937
- };
5938
- for (const part of ["chartArea", "plotArea"]) {
5939
- const entry3 = appearance[part];
5940
- if (!entry3?.gradient) continue;
5941
- if (part === "plotArea" && ["circle", "shape"].includes(entry3.gradient.path ?? "")) continue;
5942
- appearance[part] = {
5943
- ...entry3,
5944
- fillColor: paint2(entry3.gradient, part, { width, height, shape: "rect" })
5945
- };
5946
- }
5947
- const series = model.series.map((source, index) => {
5948
- const view = { ...source };
5949
- if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
5950
- const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
5951
- if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
5952
- if (source.pointGradients) {
5953
- view.pointColors = [...source.pointColors ?? []];
5954
- for (const [key, gradient] of Object.entries(source.pointGradients))
5955
- view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
5956
- }
5957
- return view;
5958
- });
5959
- return defs.length ? { model: { ...model, appearance, series }, defs: `<defs>${defs.join("")}</defs>` } : { model, defs: "" };
5960
- }
5961
- function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
5962
- const entry3 = model.appearance?.[part];
5963
- return {
5964
- size: entry3?.fontSize === void 0 ? fallbackSize : chartPointsToPixels(entry3.fontSize),
5965
- ...entry3?.color === void 0 ? {} : { fill: entry3.color },
5966
- ...entry3?.bold === void 0 ? {} : { weight: entry3.bold ? "bold" : "normal" },
5967
- ...entry3?.italic === void 0 ? {} : { italic: entry3.italic },
5968
- ...entry3?.underline === void 0 ? {} : { underline: entry3.underline },
5969
- ...entry3?.typeface === void 0 ? {} : { family: cssFontFamily(entry3.typeface) },
5970
- ...entry3?.textShadowFilter === void 0 ? {} : { filter: entry3.textShadowFilter }
5971
- };
5972
- }
5973
- function chartStroke(model, part) {
5974
- const entry3 = model.appearance?.[part];
5975
- return {
5976
- color: entry3?.axisVisible === false ? "none" : entry3?.lineColor ?? (part === "gridlineMajor" ? GRID_COLOR : AXIS_COLOR),
5977
- width: entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth)
5978
- };
5979
- }
5980
- function chartAreaRect(model, part, area) {
5981
- if (area.w <= 0 || area.h <= 0) return "";
5982
- const entry3 = model.appearance?.[part];
5983
- let fill = entry3?.fillColor ?? (part === "chartArea" ? "#FFFFFF" : "none");
5984
- let defs = "";
5985
- if (part !== "chartArea" && entry3?.gradient && (part !== "plotArea" || ["circle", "shape"].includes(entry3.gradient.path ?? ""))) {
5986
- const def = buildChartGradientDef(`xlsx-chart-${++nextPaintId}-${part}`, entry3.gradient, {
5987
- width: area.w,
5988
- height: area.h,
5989
- shape: "rect"
5990
- });
5991
- defs = `<defs>${chartGradientMarkup(def)}</defs>`;
5992
- fill = `url(#${def.id})`;
5993
- }
5994
- const stroke = entry3?.lineColor ?? "none";
5995
- if (fill === "none" && stroke === "none") return "";
5996
- const width = entry3?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry3.lineWidth);
5997
- return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
5998
- }
5999
-
6000
6863
  // chart/render/chart-svg-cartesian.ts
6001
6864
  function cartesianAxes(model, area, out) {
6002
6865
  const scale = model.valueAxis;
6003
6866
  if (!scale) return void 0;
6004
- const labels = scale.ticks.map((t) => formatAxisValue(t, scale.percent));
6867
+ const labels = scale.ticks.map((t) => axisTickText(t, model.axes?.value, scale.percent));
6005
6868
  const valueAttrs = chartTextAttributes(model, "valueAxis");
6006
6869
  const categoryAttrs = chartTextAttributes(model, "categoryAxis");
6007
6870
  const valueSize = valueAttrs.size ?? 10;
6008
6871
  const categorySize = categoryAttrs.size ?? 10;
6009
- const grid = chartStroke(model, "gridlineMajor");
6010
- const axis = chartStroke(model, "categoryAxis");
6011
- const valueLabels = model.appearance?.valueAxis?.labelsVisible !== false;
6012
- const categoryLabels = model.appearance?.categoryAxis?.labelsVisible !== false;
6872
+ const valueLabels = chartAxisLabels(model.axes?.value) && model.appearance?.valueAxis?.labelsVisible !== false;
6873
+ const categoryLabels = chartAxisLabels(model.axes?.category) && model.appearance?.categoryAxis?.labelsVisible !== false;
6013
6874
  const labelW = valueLabels ? Math.max(...labels.map((l) => textWidth(l, valueSize)), 8) + 6 : 4;
6014
6875
  const horizontal = model.horizontal;
6015
6876
  const cats = Math.max(1, model.categories.length);
@@ -6018,7 +6879,7 @@ function cartesianAxes(model, area, out) {
6018
6879
  Math.max(...model.categories.map((c2) => textWidth(c2, categorySize)), 8) + 6
6019
6880
  );
6020
6881
  const second = horizontal ? void 0 : model.secondaryAxis;
6021
- const secondLabels = second?.ticks.map((t) => formatAxisValue(t, second.percent)) ?? [];
6882
+ const secondLabels = second?.ticks.map((t) => axisTickText(t, model.axes?.secondary, second.percent)) ?? [];
6022
6883
  const secondW = second ? valueLabels ? Math.max(...secondLabels.map((l) => textWidth(l, valueSize)), 8) + 8 : 4 : 0;
6023
6884
  const plot = horizontal ? {
6024
6885
  x: area.x + catW,
@@ -6031,29 +6892,47 @@ function cartesianAxes(model, area, out) {
6031
6892
  w: Math.max(1, area.w - labelW - 4 - secondW),
6032
6893
  h: Math.max(1, area.h - Math.max(20, categorySize * 1.5))
6033
6894
  };
6034
- const span = scale.max - scale.min || 1;
6035
- const value = horizontal ? (v) => plot.x + (v - scale.min) / span * plot.w : (v) => plot.y + plot.h - (v - scale.min) / span * plot.h;
6895
+ const value = horizontal ? (v) => plot.x + chartAxisRatio(v, scale, model.axes?.value) * plot.w : (v) => plot.y + plot.h - chartAxisRatio(v, scale, model.axes?.value) * plot.h;
6036
6896
  const bandSize = (horizontal ? plot.h : plot.w) / cats;
6037
- const band = horizontal ? (i) => plot.y + plot.h - bandSize * (i + 0.5) : (i) => plot.x + bandSize * (i + 0.5);
6897
+ const index = (i) => model.axes?.category?.range.reverseOrder ? cats - 1 - i : i;
6898
+ const band = horizontal ? (i) => plot.y + plot.h - bandSize * (index(i) + 0.5) : (i) => plot.x + bandSize * (index(i) + 0.5);
6038
6899
  out.push(chartAreaRect(model, "plotArea", plot));
6900
+ out.push(axisGridlines(model, model.axes?.value, scale.ticks, value, plot, horizontal));
6901
+ if (model.axes?.category?.source.majorGridlines || model.axes?.category?.source.minorGridlines)
6902
+ out.push(
6903
+ axisGridlines(
6904
+ model,
6905
+ model.axes.category,
6906
+ model.categories.map((_, i) => i),
6907
+ band,
6908
+ plot,
6909
+ !horizontal
6910
+ )
6911
+ );
6039
6912
  scale.ticks.forEach((t, i) => {
6040
6913
  const p = value(t);
6041
6914
  const label = labels[i] ?? "";
6042
6915
  if (horizontal) {
6043
- out.push(line(p, plot.y, p, plot.y + plot.h, grid.color, grid.width));
6044
6916
  if (valueLabels)
6045
6917
  out.push(
6046
6918
  text2(p, plot.y + plot.h + valueSize + 2, label, { anchor: "middle", ...valueAttrs })
6047
6919
  );
6048
6920
  } else {
6049
- out.push(line(plot.x, p, plot.x + plot.w, p, grid.color, grid.width));
6050
6921
  if (valueLabels)
6051
6922
  out.push(text2(plot.x - 4, p + valueSize * 0.3, label, { anchor: "end", ...valueAttrs }));
6052
6923
  }
6053
6924
  });
6054
- const zero = value(Math.min(Math.max(0, scale.min), scale.max));
6055
- if (horizontal) out.push(line(zero, plot.y, zero, plot.y + plot.h, axis.color, axis.width));
6056
- else out.push(line(plot.x, zero, plot.x + plot.w, zero, axis.color, axis.width));
6925
+ const source = model.axes?.value?.source;
6926
+ const crossing = source?.crosses === "max" ? scale.max : source?.crosses === "min" ? scale.min : source?.crossesAt ?? 0;
6927
+ const zero = value(Math.min(Math.max(crossing, scale.min), scale.max));
6928
+ if (horizontal)
6929
+ out.push(
6930
+ axisLine(model, model.axes?.category, "categoryAxis", zero, plot.y, zero, plot.y + plot.h)
6931
+ );
6932
+ else
6933
+ out.push(
6934
+ axisLine(model, model.axes?.category, "categoryAxis", plot.x, zero, plot.x + plot.w, zero)
6935
+ );
6057
6936
  const step = Math.max(
6058
6937
  1,
6059
6938
  Math.ceil(cats / Math.max(1, Math.floor((horizontal ? plot.h : plot.w) / 14)))
@@ -6078,20 +6957,23 @@ function cartesianAxes(model, area, out) {
6078
6957
  });
6079
6958
  const frame = { plot, value, band, bandSize };
6080
6959
  if (second) {
6081
- const secondSpan = second.max - second.min || 1;
6082
- frame.secondary = (v) => plot.y + plot.h - (v - second.min) / secondSpan * plot.h;
6083
- const secondAxis = chartStroke(model, "valueAxis");
6960
+ frame.secondary = (v) => plot.y + plot.h - chartAxisRatio(v, second, model.axes?.secondary) * plot.h;
6084
6961
  out.push(
6085
- line(
6962
+ axisLine(
6963
+ model,
6964
+ model.axes?.secondary,
6965
+ "valueAxis",
6086
6966
  plot.x + plot.w,
6087
6967
  plot.y,
6088
6968
  plot.x + plot.w,
6089
- plot.y + plot.h,
6090
- secondAxis.color,
6091
- secondAxis.width
6969
+ plot.y + plot.h
6092
6970
  )
6093
6971
  );
6094
- if (valueLabels)
6972
+ if (model.axes?.secondary?.source.majorGridlines || model.axes?.secondary?.source.minorGridlines)
6973
+ out.push(
6974
+ axisGridlines(model, model.axes.secondary, second.ticks, frame.secondary, plot, false)
6975
+ );
6976
+ if (chartAxisLabels(model.axes?.secondary))
6095
6977
  second.ticks.forEach(
6096
6978
  (t, i) => out.push(
6097
6979
  text2(plot.x + plot.w + 4, frame.secondary(t) + valueSize * 0.3, secondLabels[i] ?? "", {
@@ -6115,6 +6997,7 @@ function linesAndAreas(model, frame, out) {
6115
6997
  const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
6116
6998
  const acc = new Array(model.categories.length).fill(0);
6117
6999
  const area = model.type === "area";
7000
+ const marks = [];
6118
7001
  const layers = [];
6119
7002
  model.series.forEach((s, si) => {
6120
7003
  const points = [];
@@ -6129,16 +7012,24 @@ function linesAndAreas(model, frame, out) {
6129
7012
  const top = below + (v ?? 0);
6130
7013
  if (stacked) acc[i] = top;
6131
7014
  points.push([frame.band(i), frame.value(top)]);
7015
+ marks.push({
7016
+ series: s,
7017
+ index: i,
7018
+ x: frame.band(i),
7019
+ y: frame.value(top),
7020
+ radius: area ? 0 : chartMarkerRadius(s, i, 2.5)
7021
+ });
6132
7022
  lower.push([frame.band(i), frame.value(below)]);
6133
7023
  });
6134
7024
  layers.push({
7025
+ series: s,
6135
7026
  points,
6136
7027
  lower,
6137
7028
  color: s.color,
6138
7029
  filter: s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""
6139
7030
  });
6140
7031
  });
6141
- for (const { points, lower, color, filter } of area ? [...layers].reverse() : layers) {
7032
+ for (const { points, lower, color, filter, series } of area ? [...layers].reverse() : layers) {
6142
7033
  if (area) {
6143
7034
  const poly = [...points, ...[...lower].reverse()].map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
6144
7035
  out.push(`<polygon points="${poly}" fill="${color}" fill-opacity="0.85"${filter}/>`);
@@ -6157,10 +7048,11 @@ function linesAndAreas(model, frame, out) {
6157
7048
  else segment2.push(`${n(x)},${n(y)}`);
6158
7049
  }
6159
7050
  flush();
6160
- for (const [x, y] of points)
6161
- if (!Number.isNaN(x))
6162
- out.push(`<circle cx="${n(x)}" cy="${n(y)}" r="2.5" fill="${color}"${filter}/>`);
7051
+ points.forEach(([x, y], index) => {
7052
+ if (!Number.isNaN(x)) out.push(chartSeriesMarkerSvg(series, index, x, y, 2.5));
7053
+ });
6163
7054
  }
7055
+ pointLabels(model, marks, out);
6164
7056
  }
6165
7057
 
6166
7058
  // chart/render/chart-svg-xy.ts
@@ -6168,16 +7060,14 @@ function scatter(model, area, out) {
6168
7060
  const ys = model.valueAxis;
6169
7061
  const xs = model.xAxis;
6170
7062
  if (!ys || !xs) return;
6171
- const yLabels = ys.ticks.map((t) => formatAxisValue(t));
7063
+ const yLabels = ys.ticks.map((t) => axisTickText(t, model.axes?.value));
6172
7064
  const valueAttrs = chartTextAttributes(model, "valueAxis");
6173
7065
  const categoryAttrs = chartTextAttributes(model, "categoryAxis");
6174
7066
  const valueSize = valueAttrs.size ?? 10;
6175
7067
  const categorySize = categoryAttrs.size ?? 10;
6176
- const grid = chartStroke(model, "gridlineMajor");
6177
7068
  const xAxis = chartStroke(model, "categoryAxis");
6178
- const yAxis = chartStroke(model, "valueAxis");
6179
- const valueLabels = model.appearance?.valueAxis?.labelsVisible !== false;
6180
- const categoryLabels = model.appearance?.categoryAxis?.labelsVisible !== false;
7069
+ const valueLabels = chartAxisLabels(model.axes?.value) && model.appearance?.valueAxis?.labelsVisible !== false;
7070
+ const categoryLabels = chartAxisLabels(model.axes?.category) && model.appearance?.categoryAxis?.labelsVisible !== false;
6181
7071
  const labelW = valueLabels ? Math.max(...yLabels.map((l) => textWidth(l, valueSize)), 8) + 6 : 4;
6182
7072
  const plot = {
6183
7073
  x: area.x + labelW,
@@ -6197,17 +7087,24 @@ function scatter(model, area, out) {
6197
7087
  s.values.forEach((_, i) => {
6198
7088
  reach = Math.max(reach, radiusOf(s.sizes?.[i] ?? void 0) ?? 0);
6199
7089
  });
6200
- const widen = (s, length) => {
7090
+ const widen = (s, length, axis) => {
7091
+ if (axis?.range.logScale) return s;
6201
7092
  const pad = reach * (s.max - s.min || 1) / Math.max(1, length - 2 * reach);
6202
- return { ...s, min: s.min - pad, max: s.max + pad };
7093
+ return {
7094
+ ...s,
7095
+ min: axis?.source.scaling.min === void 0 ? s.min - pad : s.min,
7096
+ max: axis?.source.scaling.max === void 0 ? s.max + pad : s.max
7097
+ };
6203
7098
  };
6204
- const xView = widen(xs, plot.w);
6205
- const yView = widen(ys, plot.h);
6206
- const px = (v) => plot.x + (v - xView.min) / (xView.max - xView.min || 1) * plot.w;
6207
- const py = (v) => plot.y + plot.h - (v - yView.min) / (yView.max - yView.min || 1) * plot.h;
7099
+ const xView = widen(xs, plot.w, model.axes?.category);
7100
+ const yView = widen(ys, plot.h, model.axes?.value);
7101
+ const px = (v) => plot.x + chartAxisRatio(v, xView, model.axes?.category) * plot.w;
7102
+ const py = (v) => plot.y + plot.h - chartAxisRatio(v, yView, model.axes?.value) * plot.h;
6208
7103
  out.push(chartAreaRect(model, "plotArea", plot));
7104
+ out.push(axisGridlines(model, model.axes?.value, ys.ticks, py, plot, false));
7105
+ if (model.axes?.category)
7106
+ out.push(axisGridlines(model, model.axes.category, xs.ticks, px, plot, true));
6209
7107
  ys.ticks.forEach((t, i) => {
6210
- out.push(line(plot.x, py(t), plot.x + plot.w, py(t), grid.color, grid.width));
6211
7108
  if (valueLabels)
6212
7109
  out.push(
6213
7110
  text2(plot.x - 4, py(t) + valueSize * 0.3, yLabels[i] ?? "", {
@@ -6217,19 +7114,31 @@ function scatter(model, area, out) {
6217
7114
  );
6218
7115
  });
6219
7116
  for (const t of xs.ticks) {
6220
- out.push(line(px(t), plot.y + plot.h, px(t), plot.y + plot.h + 3, xAxis.color, xAxis.width));
7117
+ if (!model.axes?.category?.source.deleted)
7118
+ out.push(line(px(t), plot.y + plot.h, px(t), plot.y + plot.h + 3, xAxis.color, xAxis.width));
6221
7119
  if (categoryLabels)
6222
7120
  out.push(
6223
- text2(px(t), plot.y + plot.h + categorySize + 3, formatAxisValue(t), {
7121
+ text2(px(t), plot.y + plot.h + categorySize + 3, axisTickText(t, model.axes?.category), {
6224
7122
  anchor: "middle",
6225
7123
  ...categoryAttrs
6226
7124
  })
6227
7125
  );
6228
7126
  }
6229
7127
  out.push(
6230
- line(plot.x, plot.y + plot.h, plot.x + plot.w, plot.y + plot.h, xAxis.color, xAxis.width)
7128
+ axisLine(
7129
+ model,
7130
+ model.axes?.category,
7131
+ "categoryAxis",
7132
+ plot.x,
7133
+ plot.y + plot.h,
7134
+ plot.x + plot.w,
7135
+ plot.y + plot.h
7136
+ )
7137
+ );
7138
+ out.push(
7139
+ axisLine(model, model.axes?.value, "valueAxis", plot.x, plot.y, plot.x, plot.y + plot.h)
6231
7140
  );
6232
- out.push(line(plot.x, plot.y, plot.x, plot.y + plot.h, yAxis.color, yAxis.width));
7141
+ const marks = [];
6233
7142
  for (const [si, s] of model.series.entries())
6234
7143
  s.values.forEach((v, i) => {
6235
7144
  const x = s.xValues?.[i] ?? null;
@@ -6237,15 +7146,18 @@ function scatter(model, area, out) {
6237
7146
  const filter = s.shadowFilter ? ` filter="${s.shadowFilter}"` : "";
6238
7147
  const fill = s.pointColors?.[i] ?? s.color;
6239
7148
  if (!bubble) {
6240
- out.push(`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="3" fill="${fill}"${filter}/>`);
7149
+ out.push(chartSeriesMarkerSvg(s, i, px(x), py(v)));
7150
+ marks.push({ series: s, index: i, x: px(x), y: py(v), radius: chartMarkerRadius(s, i) });
6241
7151
  return;
6242
7152
  }
6243
7153
  const r = radiusOf(s.sizes?.[i] ?? void 0);
6244
7154
  if (r === void 0) return;
7155
+ marks.push({ series: s, index: i, x: px(x), y: py(v), radius: r });
6245
7156
  out.push(
6246
7157
  `<circle cx="${n(px(x))}" cy="${n(py(v))}" r="${n(r)}" fill="${fill}" fill-opacity="0.6" data-chart-series="${si}" data-chart-point="${i}"${filter}/>`
6247
7158
  );
6248
7159
  });
7160
+ pointLabels(model, marks, out);
6249
7161
  scatterAnalysis(model, px, py, out);
6250
7162
  }
6251
7163
 
@@ -6410,7 +7322,9 @@ function pieSvg(model, area) {
6410
7322
  const out = [chartAreaRect(model, "plotArea", area)];
6411
7323
  const cx2 = area.x + area.w / 2;
6412
7324
  const cy = area.y + area.h / 2;
6413
- const radius = Math.max(1, Math.min(area.w, area.h) / 2 - 4);
7325
+ const margin = hasOutsideLabels(model) ? Math.min(area.w, area.h) * 0.12 : 0;
7326
+ const radius = Math.max(1, Math.min(area.w, area.h) / 2 - 4 - margin);
7327
+ const slices = [];
6414
7328
  const rings = model.type === "doughnut" ? model.series : model.series.slice(0, 1);
6415
7329
  const hole = model.type === "doughnut" ? radius * 0.5 : 0;
6416
7330
  const ringSize = (radius - hole) / Math.max(1, rings.length);
@@ -6427,9 +7341,20 @@ function pieSvg(model, area) {
6427
7341
  out.push(
6428
7342
  `<path d="${slicePath(cx2, cy, outer, inner, angle, angle + sweep)}" fill="${color}" stroke="#FFFFFF" stroke-width="1"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
6429
7343
  );
7344
+ slices.push({
7345
+ series: s,
7346
+ index: i,
7347
+ cx: cx2,
7348
+ cy,
7349
+ outer,
7350
+ inner,
7351
+ start: angle,
7352
+ end: angle + sweep
7353
+ });
6430
7354
  angle += sweep;
6431
7355
  });
6432
7356
  });
7357
+ sliceLabels(model, slices, out);
6433
7358
  return out.join("");
6434
7359
  }
6435
7360
  function radarSvg(model, area) {
@@ -6442,32 +7367,37 @@ function radarSvg(model, area) {
6442
7367
  const valueSize = valueAttrs.size ?? 9;
6443
7368
  const categorySize = categoryAttrs.size ?? 10;
6444
7369
  const grid = chartStroke(model, "gridlineMajor");
6445
- const axis = chartStroke(model, "categoryAxis");
6446
7370
  const cx2 = area.x + area.w / 2;
6447
7371
  const cy = area.y + area.h / 2 + 4;
6448
7372
  const radius = Math.max(1, Math.min(area.w, area.h) / 2 - Math.max(18, categorySize * 1.8));
6449
7373
  const angle = (i) => i / count * Math.PI * 2;
6450
- const r = (v) => (v - scale.min) / (scale.max - scale.min || 1) * radius;
7374
+ const r = (v) => chartAxisRatio(v, scale, model.axes?.value) * radius;
6451
7375
  const labelEvery = Math.max(
6452
7376
  1,
6453
7377
  Math.ceil(12 / Math.max(1, radius / Math.max(1, scale.ticks.length - 1)))
6454
7378
  );
6455
7379
  for (const [k, t] of scale.ticks.entries()) {
6456
7380
  const ring = Array.from({ length: count }, (_, i) => polar(cx2, cy, r(t), angle(i))).map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
6457
- out.push(
6458
- `<polygon points="${ring}" fill="none" stroke="${grid.color}" stroke-width="${n(grid.width)}"/>`
6459
- );
6460
- if (model.appearance?.valueAxis?.labelsVisible !== false && k % labelEvery === 0)
7381
+ if (!model.axes?.value || model.axes.value.source.majorGridlines)
7382
+ out.push(
7383
+ `<polygon points="${ring}" fill="none" stroke="${grid.color}" stroke-width="${n(grid.width)}"/>`
7384
+ );
7385
+ if (chartAxisLabels(model.axes?.value) && model.appearance?.valueAxis?.labelsVisible !== false && k % labelEvery === 0)
6461
7386
  out.push(
6462
- text2(cx2 + 3, cy - r(t) + valueSize * 0.3, formatAxisValue(t, scale.percent), valueAttrs)
7387
+ text2(
7388
+ cx2 + 3,
7389
+ cy - r(t) + valueSize * 0.3,
7390
+ axisTickText(t, model.axes?.value, scale.percent),
7391
+ valueAttrs
7392
+ )
6463
7393
  );
6464
7394
  }
6465
7395
  model.categories.forEach((c2, i) => {
6466
7396
  const [x, y] = polar(cx2, cy, radius, angle(i));
6467
- out.push(line(cx2, cy, x, y, axis.color, axis.width));
7397
+ out.push(axisLine(model, model.axes?.category, "categoryAxis", cx2, cy, x, y));
6468
7398
  const [lx, ly] = polar(cx2, cy, radius + 10, angle(i));
6469
7399
  const anchor = Math.abs(lx - cx2) < 2 ? "middle" : lx > cx2 ? "start" : "end";
6470
- if (model.appearance?.categoryAxis?.labelsVisible !== false)
7400
+ if (chartAxisLabels(model.axes?.category) && model.appearance?.categoryAxis?.labelsVisible !== false)
6471
7401
  out.push(
6472
7402
  text2(lx, ly + categorySize * 0.3, fit(c2, area.w / 4, categorySize), {
6473
7403
  anchor,
@@ -6475,12 +7405,22 @@ function radarSvg(model, area) {
6475
7405
  })
6476
7406
  );
6477
7407
  });
7408
+ const marks = [];
6478
7409
  for (const s of model.series) {
6479
- const points = s.values.slice(0, count).map((v, i) => polar(cx2, cy, r(v ?? scale.min), angle(i))).map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
7410
+ const vertices = s.values.slice(0, count).map((v, i) => polar(cx2, cy, r(v ?? scale.min), angle(i)));
7411
+ vertices.forEach(([x, y], i) => {
7412
+ if (s.values[i] === null) return;
7413
+ const markerSeries = s;
7414
+ if (markerSeries.marker || markerSeries.pointMarkers)
7415
+ out.push(chartSeriesMarkerSvg(s, i, x, y));
7416
+ marks.push({ series: s, index: i, x, y, radius: chartMarkerRadius(s, i) });
7417
+ });
7418
+ const points = vertices.map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
6480
7419
  out.push(
6481
7420
  `<polygon points="${points}" fill="none" stroke="${s.color}" stroke-width="2"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
6482
7421
  );
6483
7422
  }
7423
+ pointLabels(model, marks, out);
6484
7424
  return out.join("");
6485
7425
  }
6486
7426
 
@@ -6571,33 +7511,33 @@ var CHART_FONT_FAMILY = "Calibri, Carlito, Arial, sans-serif";
6571
7511
  function cssFont(attrs) {
6572
7512
  return `${attrs.italic ? "italic" : "normal"} ${attrs.weight ?? "normal"} ${attrs.size ?? 10}px ${attrs.family ?? CHART_FONT_FAMILY}`;
6573
7513
  }
6574
- function chartFontMetrics(attrs, options) {
6575
- const metrics = options.measureFont?.(cssFont(attrs));
7514
+ function chartFontMetrics(attrs, options2) {
7515
+ const metrics = options2.measureFont?.(cssFont(attrs));
6576
7516
  return metrics && Number.isFinite(metrics.ascent) && Number.isFinite(metrics.descent) && metrics.ascent >= 0 && metrics.descent >= 0 && metrics.ascent + metrics.descent > 0 ? metrics : void 0;
6577
7517
  }
6578
- function chartTextWidth(content, attrs, options) {
6579
- const width = options.measureText?.(content, cssFont(attrs));
7518
+ function chartTextWidth(content, attrs, options2) {
7519
+ const width = options2.measureText?.(content, cssFont(attrs));
6580
7520
  return width !== void 0 && Number.isFinite(width) && width >= 0 ? width : textWidth(content, attrs.size);
6581
7521
  }
6582
- function fitChartText(content, maxWidth, attrs, options) {
6583
- if (!options.measureText) return fit(content, maxWidth, attrs.size);
6584
- if (chartTextWidth(content, attrs, options) <= maxWidth) return content;
7522
+ function fitChartText(content, maxWidth, attrs, options2) {
7523
+ if (!options2.measureText) return fit(content, maxWidth, attrs.size);
7524
+ if (chartTextWidth(content, attrs, options2) <= maxWidth) return content;
6585
7525
  const points = [...content];
6586
7526
  let low = 0;
6587
7527
  let high = points.length;
6588
7528
  while (low < high) {
6589
7529
  const mid = Math.ceil((low + high) / 2);
6590
- if (chartTextWidth(`${points.slice(0, mid).join("")}\u2026`, attrs, options) <= maxWidth) low = mid;
7530
+ if (chartTextWidth(`${points.slice(0, mid).join("")}\u2026`, attrs, options2) <= maxWidth) low = mid;
6591
7531
  else high = mid - 1;
6592
7532
  }
6593
7533
  return `${points.slice(0, low).join("")}\u2026`;
6594
7534
  }
6595
7535
 
6596
7536
  // chart/render/chart-svg-legend.ts
6597
- function chartLegendSvg(model, area, frame, options) {
7537
+ function chartLegendSvg(model, area, frame, options2) {
6598
7538
  const automatic = [];
6599
7539
  const bounds = {};
6600
- const reserved = automaticLegend(model, area, automatic, options, bounds);
7540
+ const reserved = automaticLegend(model, area, automatic, options2, bounds);
6601
7541
  const plot = model.legendOverlay ? area : reserved;
6602
7542
  const box = bounds.box;
6603
7543
  if (!box) return { plot, markup: "", foreground: false };
@@ -6611,11 +7551,11 @@ function chartLegendSvg(model, area, frame, options) {
6611
7551
  const entries = legendEntries(model);
6612
7552
  const attrs = chartTextAttributes(model, "legend");
6613
7553
  const size = attrs.size ?? 10;
6614
- const font = chartFontMetrics(attrs, options);
7554
+ const font = chartFontMetrics(attrs, options2);
6615
7555
  const keySize = size / 2;
6616
7556
  const keyGap = size / 4;
6617
7557
  const widths = entries.map(
6618
- (entry3) => chartTextWidth(entry3.label, attrs, options) + keySize + keyGap
7558
+ (entry3) => chartTextWidth(entry3.label, attrs, options2) + keySize + keyGap
6619
7559
  );
6620
7560
  const horizontal = manual.width > manual.height && widths.reduce((sum, width) => sum + width, 0) + size <= manual.width;
6621
7561
  const rowWidth = horizontal ? manual.width / entries.length : manual.width;
@@ -6630,8 +7570,8 @@ function chartLegendSvg(model, area, frame, options) {
6630
7570
  ];
6631
7571
  const baselineOffset = font ? (font.ascent - font.descent) / 2 : size * 0.35;
6632
7572
  entries.forEach((entry3, i) => {
6633
- const available = horizontal ? chartTextWidth(entry3.label, attrs, options) : Math.max(0, rowWidth - size / 2 - keySize - keyGap);
6634
- const label = fitChartText(entry3.label, available, attrs, options);
7573
+ const available = horizontal ? chartTextWidth(entry3.label, attrs, options2) : Math.max(0, rowWidth - size / 2 - keySize - keyGap);
7574
+ const label = fitChartText(entry3.label, available, attrs, options2);
6635
7575
  const contentWidth = Math.min(
6636
7576
  horizontal ? widths[i] ?? 0 : Math.max(...widths),
6637
7577
  rowWidth - size / 2
@@ -6674,7 +7614,7 @@ function legendEntries(model) {
6674
7614
  color: s.color
6675
7615
  }));
6676
7616
  }
6677
- function automaticLegend(model, area, out, options, bounds) {
7617
+ function automaticLegend(model, area, out, options2, bounds) {
6678
7618
  const entries = legendEntries(model);
6679
7619
  if (!model.showLegend || entries.length === 0) return area;
6680
7620
  const pos = model.legendPosition;
@@ -6683,7 +7623,7 @@ function automaticLegend(model, area, out, options, bounds) {
6683
7623
  const rowH = Math.max(16, size * 1.4);
6684
7624
  if (pos === "t" || pos === "b") {
6685
7625
  const widths = entries.map(
6686
- (e) => Math.min(chartTextWidth(e.label, attrs, options) + 20, area.w / 2)
7626
+ (e) => Math.min(chartTextWidth(e.label, attrs, options2) + 20, area.w / 2)
6687
7627
  );
6688
7628
  const total = widths.reduce((a2, b) => a2 + b, 0);
6689
7629
  let x2 = area.x + Math.max(0, (area.w - total) / 2);
@@ -6700,14 +7640,14 @@ function automaticLegend(model, area, out, options, bounds) {
6700
7640
  entries.forEach((e, i) => {
6701
7641
  const w = widths[i] ?? 0;
6702
7642
  out.push(rect(x2, y, 8, 8, e.color));
6703
- out.push(text2(x2 + 12, y + 8, fitChartText(e.label, w - 16, attrs, options), attrs));
7643
+ out.push(text2(x2 + 12, y + 8, fitChartText(e.label, w - 16, attrs, options2), attrs));
6704
7644
  x2 += w;
6705
7645
  });
6706
7646
  return pos === "t" ? { x: area.x, y: area.y + rowH + 4, w: area.w, h: area.h - rowH - 4 } : { x: area.x, y: area.y, w: area.w, h: area.h - rowH - 4 };
6707
7647
  }
6708
7648
  const width = Math.min(
6709
7649
  area.w * 0.35,
6710
- Math.max(...entries.map((e) => chartTextWidth(e.label, attrs, options))) + 22
7650
+ Math.max(...entries.map((e) => chartTextWidth(e.label, attrs, options2))) + 22
6711
7651
  );
6712
7652
  const height = entries.length * rowH;
6713
7653
  const x = pos === "l" ? area.x + 4 : area.x + area.w - width;
@@ -6725,14 +7665,14 @@ function automaticLegend(model, area, out, options, bounds) {
6725
7665
  const y = y0 + i * rowH;
6726
7666
  if (y + rowH > area.y + area.h + 2) return;
6727
7667
  out.push(rect(x, y + 3, 8, 8, e.color));
6728
- out.push(text2(x + 12, y + 11, fitChartText(e.label, width - 16, attrs, options), attrs));
7668
+ out.push(text2(x + 12, y + 11, fitChartText(e.label, width - 16, attrs, options2), attrs));
6729
7669
  });
6730
7670
  return pos === "l" ? { x: area.x + width + 8, y: area.y, w: area.w - width - 8, h: area.h } : { x: area.x, y: area.y, w: area.w - width - 8, h: area.h };
6731
7671
  }
6732
7672
 
6733
7673
  // text/wrap-styled-runs.ts
6734
7674
  var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
6735
- function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
7675
+ function wrapStyledRuns(runs, maxWidth, measure2, options2 = {}) {
6736
7676
  const groups = [];
6737
7677
  for (const [source, run2] of runs.entries()) {
6738
7678
  for (const token of run2.text.split(/(\r\n|[\r\n]|[ \t]+)/u).filter(Boolean)) {
@@ -6755,7 +7695,7 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
6755
7695
  return result2;
6756
7696
  };
6757
7697
  const width = (pieces) => pieces.reduce((sum, piece) => {
6758
- const advance = measure(piece.text, piece.run);
7698
+ const advance = measure2(piece.text, piece.run);
6759
7699
  return sum + (Number.isFinite(advance) && advance >= 0 ? advance : 0);
6760
7700
  }, 0);
6761
7701
  const result = [];
@@ -6780,7 +7720,7 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
6780
7720
  if (line2.length && width(merged(line2, [...separator, ...group2.pieces])) > maxWidth) flush();
6781
7721
  else line2 = merged(line2, separator);
6782
7722
  spaces = [];
6783
- if (options.breakWords && wordWidth > maxWidth) {
7723
+ if (options2.breakWords && wordWidth > maxWidth) {
6784
7724
  for (const piece of group2.pieces) {
6785
7725
  for (const { segment: segment2 } of graphemes.segment(piece.text)) {
6786
7726
  const next = { ...piece, text: segment2 };
@@ -6798,11 +7738,11 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
6798
7738
  function spacing2(value, naturalHeight, fallback) {
6799
7739
  return value ? value.unit === "points" ? chartPointsToPixels(value.value) : naturalHeight * value.value : fallback;
6800
7740
  }
6801
- function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
7741
+ function chartRichTitleSvg(model, width, options2 = {}, frameHeight = 400) {
6802
7742
  if (!model.title) return void 0;
6803
7743
  const base = chartTextAttributes(model, "title", 14);
6804
7744
  const capacity = Math.max(1, width * 0.8 - 8);
6805
- if (!model.titleText && !hasManualLayoutFields(model.titleLayout) && !model.titleOverlay && !model.title.includes("\n") && chartTextWidth(model.title, base, options) <= capacity)
7745
+ if (!model.titleText && !hasManualLayoutFields(model.titleLayout) && !model.titleOverlay && !model.title.includes("\n") && chartTextWidth(model.title, base, options2) <= capacity)
6806
7746
  return void 0;
6807
7747
  const paragraphs = model.titleText?.paragraphs ?? [
6808
7748
  {
@@ -6838,7 +7778,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
6838
7778
  "title",
6839
7779
  base.size
6840
7780
  ),
6841
- options
7781
+ options2
6842
7782
  ),
6843
7783
  { breakWords: true }
6844
7784
  );
@@ -6862,10 +7802,10 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
6862
7802
  return {
6863
7803
  ...line2,
6864
7804
  runs,
6865
- width: runs.reduce((sum, run2) => sum + chartTextWidth(run2.text, run2.attrs, options), 0),
7805
+ width: runs.reduce((sum, run2) => sum + chartTextWidth(run2.text, run2.attrs, options2), 0),
6866
7806
  size: runs.length ? Math.max(...runs.map((run2) => run2.attrs.size ?? 14)) : base.size ?? 14,
6867
7807
  fontMetrics: (runs.length ? runs.map((run2) => run2.attrs) : [base]).map(
6868
- (attrs) => chartFontMetrics(attrs, options)
7808
+ (attrs) => chartFontMetrics(attrs, options2)
6869
7809
  )
6870
7810
  };
6871
7811
  });
@@ -6903,7 +7843,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
6903
7843
  anchor: "start"
6904
7844
  }).replace("<text ", '<tspan data-chart-title-run="true" ').replace("</text>", "</tspan>")
6905
7845
  );
6906
- x += chartTextWidth(run2.text, run2.attrs, options);
7846
+ x += chartTextWidth(run2.text, run2.attrs, options2);
6907
7847
  }
6908
7848
  }
6909
7849
  const parent = text2(0, 0, "", { ...base, underline: false }).replace(
@@ -6929,7 +7869,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
6929
7869
  }
6930
7870
 
6931
7871
  // chart/render/chart-svg.ts
6932
- function renderChartSvg(model, width, height, options = {}) {
7872
+ function renderChartSvg(model, width, height, options2 = {}) {
6933
7873
  const paint2 = chartGradientPaint(model, Math.max(1, width), Math.max(1, height));
6934
7874
  model = paint2.model;
6935
7875
  const w = Math.max(1, width);
@@ -6943,7 +7883,7 @@ function renderChartSvg(model, width, height, options = {}) {
6943
7883
  if (paint2.defs) out.push(paint2.defs);
6944
7884
  out.push(chartAreaRect(model, "chartArea", { x: 0, y: 0, w, h }));
6945
7885
  let area = { x: 8, y: 8, w: w - 16, h: h - 16 };
6946
- const richTitle = chartRichTitleSvg(model, w, options, h);
7886
+ const richTitle = chartRichTitleSvg(model, w, options2, h);
6947
7887
  if (richTitle) {
6948
7888
  if (model.titleLayout || model.titleOverlay) foregroundTitle = richTitle.markup;
6949
7889
  else out.push(richTitle.markup);
@@ -6952,9 +7892,9 @@ function renderChartSvg(model, width, height, options = {}) {
6952
7892
  } else if (model.title) {
6953
7893
  const attrs = chartTextAttributes(model, "title", 14);
6954
7894
  const size = attrs.size ?? 14;
6955
- const label = fitChartText(model.title, w - 16, attrs, options);
6956
- const titleWidth = Math.min(w - 16, chartTextWidth(label, attrs, options) + 8);
6957
- const font = chartFontMetrics(attrs, options);
7895
+ const label = fitChartText(model.title, w - 16, attrs, options2);
7896
+ const titleWidth = Math.min(w - 16, chartTextWidth(label, attrs, options2) + 8);
7897
+ const font = chartFontMetrics(attrs, options2);
6958
7898
  const titleHeight = Math.max(24, font ? font.ascent + font.descent + 4 : size * 1.4 + 4);
6959
7899
  out.push(
6960
7900
  chartAreaRect(model, "title", {
@@ -6982,7 +7922,7 @@ function renderChartSvg(model, width, height, options = {}) {
6982
7922
  out.push("</svg>");
6983
7923
  return out.join("");
6984
7924
  }
6985
- const legend = chartLegendSvg(model, area, { width: w, height: h }, options);
7925
+ const legend = chartLegendSvg(model, area, { width: w, height: h }, options2);
6986
7926
  area = legend.plot;
6987
7927
  if (!legend.foreground) out.push(legend.markup);
6988
7928
  if (area.w > 4 && area.h > 4) {
@@ -7029,8 +7969,8 @@ function chartSpaceKind(space) {
7029
7969
  const type = chartSummaryFromSpace(space).chartType;
7030
7970
  return { type, drawn: DRAWN_CHART_TYPES.has(type) };
7031
7971
  }
7032
- function renderChartSpaceSvg(space, options) {
7033
- const { width, height, theme, fonts, formatting, colorPalette, styleDefinition, ...svg } = options;
7972
+ function renderChartSpaceSvg(space, options2) {
7973
+ const { width, height, theme, fonts, formatting, colorPalette, styleDefinition, ...svg } = options2;
7034
7974
  const summary = chartSummaryFromSpace(space, {
7035
7975
  ...formatting ? { formatting } : {},
7036
7976
  ...colorPalette !== void 0 ? { colorPalette } : {},
@@ -7039,10 +7979,10 @@ function renderChartSpaceSvg(space, options) {
7039
7979
  const view = chartSummaryView(summary, chartThemePalette(theme, fonts));
7040
7980
  return renderChartSvg(view, width, height, svg);
7041
7981
  }
7042
- function renderChartSummarySvg(summary, options) {
7043
- const { width, height, theme, fonts, ...svg } = options;
7982
+ function renderChartSummarySvg(summary, options2) {
7983
+ const { width, height, theme, fonts, ...svg } = options2;
7044
7984
  const view = chartSummaryView(summary, chartThemePalette(theme, fonts));
7045
7985
  return renderChartSvg(view, width, height, svg);
7046
7986
  }
7047
7987
 
7048
- export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, CHART_AUTO_TITLE, CHART_COLOR_PALETTES, CHART_COLOR_STYLE_CONTENT_TYPE, CHART_COLOR_STYLE_NS, CHART_COLOR_STYLE_REL, CHART_ERROR_BAR_DIRECTIONS, CHART_ERROR_BAR_TYPES, CHART_ERROR_VALUE_TYPES, CHART_GROUP_ELEMENTS, CHART_STYLE_PARTS, DEFAULT_BAR_GAP_WIDTH, DEFAULT_CHART_PALETTE, DEFAULT_THEME_COLORS, DRAWN_CHART_TYPES, LABEL_COLLISION_GAP, STOCK_DEFAULT_DOWN_FILL, STOCK_DEFAULT_UP_FILL, STOCK_DEFAULT_WICK_COLOR, STOCK_TICK_WIDTH, THEME_SLOTS, aggregate, aggregateByCategory, assertBarClusterOptions, autoSeriesColor, axisTargetIntervals, buildChartGradientDef, buildHierarchyRoots, buildWaterfallSteps, builtInChartStyleXml, builtInChartTextStyle, categoryTotals, chartCacheValues, chartColorScheme, chartColorStyleId, chartColorStyleXml, chartErrorBarAmount, chartExSummary, chartGradientMarkup, chartPaletteColors, chartPaletteSeriesColor, chartPaletteSeriesColorChoice, chartSampleVariance, chartSourceValues, chartSpaceKind, chartSummaryFromSpace, chartSummarySeries, chartSummaryView, chartThemePalette, chartTrendlineKind, chartTrendlineType, clusteredBarGeometry, computeBoxStats, computeBubbleRadius, computeHierarchicalSunburstArcs, computeHistogramBins, computeLinearRegression, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, computeSunburstArcs, computeWaterfallRange, effectiveBuiltInChartStyle, findChartColorPalette, fitChartTrendline, fitPolynomial, formatChartNumber, formatChartNumberWithColor, formatCompactAxisValue, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, getChartStylePalette, groupRowsByCategory, hasManualLayoutFields, hierarchyBranchLabels, impliesAutoTitle, isChartexOnlyType, layoutTreemap, maxBubbleSize, medianBubbleRadius, modulateLuminance, niceAxisStep, niceValueAxisBounds, normalizeLevels, nudgeOutsideLabels, parseChartSpace, placeBestFitLabel, radarAngle, radarRingPoints, readBuiltInChartStyle, readChartFormatting, readChartManualLayoutValues, readChartStyle, readDisplayNaAsBlank, removeGradientStop, renderChartSpaceSvg, renderChartSummarySvg, renderChartSvg, resolveAutoTitleText, resolveBlankDisplay, resolveChartGradient, resolveChartStyleDefinition, resolveManualLayoutRect, scottBinCount, shade, sortGradientStops, squarify, stockCandle, stockSlots, sunburstArcPath, themeColor, tint, updateGradientStop, visibleRuns, withChartGradientDirection, withinLinearTransform, writeChartAxisFormatting, writeChartFillFormatting, writeChartLayoutFormatting, writeChartSpace };
7988
+ export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, CHART_AUTO_TITLE, CHART_COLOR_PALETTES, CHART_COLOR_STYLE_CONTENT_TYPE, CHART_COLOR_STYLE_NS, CHART_COLOR_STYLE_REL, CHART_ERROR_BAR_DIRECTIONS, CHART_ERROR_BAR_TYPES, CHART_ERROR_VALUE_TYPES, CHART_GROUP_ELEMENTS, CHART_STYLE_PARTS, DATA_LABEL_CATEGORY_PERCENT_SEPARATOR, DATA_LABEL_SEPARATOR, DEFAULT_BAR_GAP_WIDTH, DEFAULT_CHART_PALETTE, DEFAULT_THEME_COLORS, DRAWN_CHART_TYPES, LABEL_COLLISION_GAP, STOCK_DEFAULT_DOWN_FILL, STOCK_DEFAULT_UP_FILL, STOCK_DEFAULT_WICK_COLOR, STOCK_TICK_WIDTH, THEME_SLOTS, aggregate, aggregateByCategory, assertBarClusterOptions, autoSeriesColor, automaticMarkerSymbol, axisTargetIntervals, buildChartGradientDef, buildHierarchyRoots, buildMarkerPrimitive, buildWaterfallSteps, builtInChartStyleXml, builtInChartTextStyle, categoryTotals, chartCacheValues, chartColorScheme, chartColorStyleId, chartColorStyleXml, chartErrorBarAmount, chartExSummary, chartGradientMarkup, chartLineDashArray, chartMarkerRadius, chartPaletteColors, chartPaletteSeriesColor, chartPaletteSeriesColorChoice, chartSampleVariance, chartSeriesMarkerSvg, chartSourceValues, chartSpaceKind, chartSummaryFromSpace, chartSummarySeries, chartSummaryView, chartThemePalette, chartTrendlineKind, chartTrendlineType, clusteredBarGeometry, composeDataLabelText, computeAxisStackedValueRange, computeAxisValueRange, computeBoxStats, computeBubbleRadius, computeHierarchicalSunburstArcs, computeHistogramBins, computeLinearRegression, computeLogValueRange, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, computeStackedValueRangeForAxis, computeSunburstArcs, computeValueRangeForAxis, computeValueRangeForChart, computeWaterfallRange, effectiveBuiltInChartStyle, findChartColorPalette, findLogAxis, fitChartTrendline, fitPolynomial, formatChartNumber, formatChartNumberWithColor, formatCompactAxisValue, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, generateAxisTicks, generateLogTicks, generateMinorAxisTicks, getChartStylePalette, groupRowsByCategory, hasManualLayoutFields, hierarchyBranchLabels, impliesAutoTitle, isChartexOnlyType, layoutTreemap, markerOutline, markerRadius, maxBubbleSize, medianBubbleRadius, modulateLuminance, niceAxisStep, niceValueAxisBounds, normalizeLevels, nudgeOutsideLabels, parseChartSpace, placeBestFitLabel, radarAngle, radarRingPoints, readBuiltInChartStyle, readChartFormatting, readChartManualLayoutValues, readChartStyle, readDisplayNaAsBlank, removeGradientStop, renderChartSpaceSvg, renderChartSummarySvg, renderChartSvg, resolveAutoTitleText, resolveBlankDisplay, resolveChartGradient, resolveChartStyleDefinition, resolveDataLabelFlags, resolveManualLayoutRect, scottBinCount, seriesMarkerViews, shade, sortGradientStops, squarify, stockCandle, stockSlots, summaryMarkers, sunburstArcPath, themeColor, tint, updateGradientStop, valueToYLog, visibleRuns, withAxisBounds, withChartGradientDirection, withinLinearTransform, writeChartAxisFormatting, writeChartFillFormatting, writeChartLayoutFormatting, writeChartSpace };