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