pptx-react-viewer 2.19.7 → 2.20.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 (108) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +1 -1
  3. package/dist/{AiChatPanel-MAC2Z5SK.js → AiChatPanel-KOKEVIOQ.js} +24 -24
  4. package/dist/AiChatPanel-KOKEVIOQ.js.br +0 -0
  5. package/dist/AiChatPanel-KOKEVIOQ.js.gz +0 -0
  6. package/dist/{AiChatPanel-WVO66CKC.mjs → AiChatPanel-S5UYFWT2.mjs} +4 -4
  7. package/dist/AiChatPanel-S5UYFWT2.mjs.br +0 -0
  8. package/dist/AiChatPanel-S5UYFWT2.mjs.gz +0 -0
  9. package/dist/{Model3DScene-CU4WGIMH.js → Model3DScene-T5372GIJ.js} +2 -2
  10. package/dist/Model3DScene-T5372GIJ.js.br +0 -0
  11. package/dist/Model3DScene-T5372GIJ.js.gz +0 -0
  12. package/dist/{Model3DScene-PTCZUGIT.mjs → Model3DScene-T6QOOVLN.mjs} +1 -1
  13. package/dist/Model3DScene-T6QOOVLN.mjs.br +0 -0
  14. package/dist/Model3DScene-T6QOOVLN.mjs.gz +0 -0
  15. package/dist/{chunk-DZHCLAH3.mjs → chunk-2T7J57AC.mjs} +1 -1
  16. package/dist/chunk-2T7J57AC.mjs.br +0 -0
  17. package/dist/chunk-2T7J57AC.mjs.gz +0 -0
  18. package/dist/{chunk-MVKRI3CZ.js → chunk-6CPUGAK7.js} +2 -0
  19. package/dist/chunk-6CPUGAK7.js.br +0 -0
  20. package/dist/{chunk-MVKRI3CZ.js.gz → chunk-6CPUGAK7.js.gz} +0 -0
  21. package/dist/{chunk-JENKEQZP.js → chunk-AFAAKYYB.js} +1093 -1254
  22. package/dist/chunk-AFAAKYYB.js.br +0 -0
  23. package/dist/chunk-AFAAKYYB.js.gz +0 -0
  24. package/dist/{chunk-V5PW4QCE.js → chunk-BW3ZS73U.js} +178 -172
  25. package/dist/chunk-BW3ZS73U.js.br +0 -0
  26. package/dist/chunk-BW3ZS73U.js.gz +0 -0
  27. package/dist/{chunk-GUGHIQ4P.js → chunk-J56DMNSD.js} +604 -452
  28. package/dist/chunk-J56DMNSD.js.br +0 -0
  29. package/dist/chunk-J56DMNSD.js.gz +0 -0
  30. package/dist/{chunk-SQJBFMEX.mjs → chunk-MZOZNBRO.mjs} +2 -0
  31. package/dist/chunk-MZOZNBRO.mjs.br +0 -0
  32. package/dist/{chunk-SQJBFMEX.mjs.gz → chunk-MZOZNBRO.mjs.gz} +0 -0
  33. package/dist/{chunk-ZPNLWBED.mjs → chunk-QLELFH7A.mjs} +586 -449
  34. package/dist/chunk-QLELFH7A.mjs.br +0 -0
  35. package/dist/chunk-QLELFH7A.mjs.gz +0 -0
  36. package/dist/{chunk-XDF76VFA.js → chunk-SAKMXLW2.js} +382 -379
  37. package/dist/chunk-SAKMXLW2.js.br +0 -0
  38. package/dist/chunk-SAKMXLW2.js.gz +0 -0
  39. package/dist/{chunk-EVM5OFAD.js → chunk-T7OUKBWK.js} +3 -3
  40. package/dist/chunk-T7OUKBWK.js.br +0 -0
  41. package/dist/chunk-T7OUKBWK.js.gz +0 -0
  42. package/dist/{chunk-QZV7XDQG.mjs → chunk-U2UIJRSW.mjs} +25 -19
  43. package/dist/chunk-U2UIJRSW.mjs.br +0 -0
  44. package/dist/chunk-U2UIJRSW.mjs.gz +0 -0
  45. package/dist/{chunk-5BG5BANR.mjs → chunk-XWCN4TGE.mjs} +67 -228
  46. package/dist/chunk-XWCN4TGE.mjs.br +0 -0
  47. package/dist/chunk-XWCN4TGE.mjs.gz +0 -0
  48. package/dist/{chunk-LP3Y4NXE.mjs → chunk-YMNURZ22.mjs} +6 -3
  49. package/dist/chunk-YMNURZ22.mjs.br +0 -0
  50. package/dist/chunk-YMNURZ22.mjs.gz +0 -0
  51. package/dist/i18n.js +4 -4
  52. package/dist/i18n.js.br +0 -0
  53. package/dist/i18n.js.gz +0 -0
  54. package/dist/i18n.mjs +1 -1
  55. package/dist/i18n.mjs.br +0 -0
  56. package/dist/i18n.mjs.gz +0 -0
  57. package/dist/index.js +47 -47
  58. package/dist/index.js.br +0 -0
  59. package/dist/index.js.gz +0 -0
  60. package/dist/index.mjs +6 -6
  61. package/dist/index.mjs.br +0 -0
  62. package/dist/index.mjs.gz +0 -0
  63. package/dist/internals.js +79 -79
  64. package/dist/internals.js.br +0 -0
  65. package/dist/internals.js.gz +0 -0
  66. package/dist/internals.mjs +4 -4
  67. package/dist/internals.mjs.br +0 -0
  68. package/dist/internals.mjs.gz +0 -0
  69. package/dist/pptx-viewer.css +1 -1
  70. package/dist/pptx-viewer.css.br +0 -0
  71. package/dist/pptx-viewer.css.gz +0 -0
  72. package/dist/viewer/index.js +27 -27
  73. package/dist/viewer/index.js.br +0 -0
  74. package/dist/viewer/index.js.gz +0 -0
  75. package/dist/viewer/index.mjs +6 -6
  76. package/dist/viewer/index.mjs.br +0 -0
  77. package/dist/viewer/index.mjs.gz +0 -0
  78. package/package.json +1 -1
  79. package/dist/AiChatPanel-MAC2Z5SK.js.br +0 -0
  80. package/dist/AiChatPanel-MAC2Z5SK.js.gz +0 -0
  81. package/dist/AiChatPanel-WVO66CKC.mjs.br +0 -0
  82. package/dist/AiChatPanel-WVO66CKC.mjs.gz +0 -0
  83. package/dist/Model3DScene-CU4WGIMH.js.br +0 -0
  84. package/dist/Model3DScene-CU4WGIMH.js.gz +0 -0
  85. package/dist/Model3DScene-PTCZUGIT.mjs.br +0 -0
  86. package/dist/Model3DScene-PTCZUGIT.mjs.gz +0 -0
  87. package/dist/chunk-5BG5BANR.mjs.br +0 -0
  88. package/dist/chunk-5BG5BANR.mjs.gz +0 -0
  89. package/dist/chunk-DZHCLAH3.mjs.br +0 -0
  90. package/dist/chunk-DZHCLAH3.mjs.gz +0 -0
  91. package/dist/chunk-EVM5OFAD.js.br +0 -0
  92. package/dist/chunk-EVM5OFAD.js.gz +0 -0
  93. package/dist/chunk-GUGHIQ4P.js.br +0 -0
  94. package/dist/chunk-GUGHIQ4P.js.gz +0 -0
  95. package/dist/chunk-JENKEQZP.js.br +0 -0
  96. package/dist/chunk-JENKEQZP.js.gz +0 -0
  97. package/dist/chunk-LP3Y4NXE.mjs.br +0 -0
  98. package/dist/chunk-LP3Y4NXE.mjs.gz +0 -0
  99. package/dist/chunk-MVKRI3CZ.js.br +0 -0
  100. package/dist/chunk-QZV7XDQG.mjs.br +0 -0
  101. package/dist/chunk-QZV7XDQG.mjs.gz +0 -0
  102. package/dist/chunk-SQJBFMEX.mjs.br +0 -0
  103. package/dist/chunk-V5PW4QCE.js.br +0 -0
  104. package/dist/chunk-V5PW4QCE.js.gz +0 -0
  105. package/dist/chunk-XDF76VFA.js.br +0 -0
  106. package/dist/chunk-XDF76VFA.js.gz +0 -0
  107. package/dist/chunk-ZPNLWBED.mjs.br +0 -0
  108. package/dist/chunk-ZPNLWBED.mjs.gz +0 -0
@@ -27589,9 +27589,9 @@ function addSmartArtNode(data, text2, afterNodeId) {
27589
27589
  };
27590
27590
  const nodes = [...data.nodes];
27591
27591
  if (afterNodeId) {
27592
- const siblingIndex = nodes.findIndex((n) => n.id === afterNodeId);
27593
- if (siblingIndex >= 0) {
27594
- nodes.splice(siblingIndex + 1, 0, newNode);
27592
+ const siblingIndex2 = nodes.findIndex((n) => n.id === afterNodeId);
27593
+ if (siblingIndex2 >= 0) {
27594
+ nodes.splice(siblingIndex2 + 1, 0, newNode);
27595
27595
  } else {
27596
27596
  nodes.push(newNode);
27597
27597
  }
@@ -97262,6 +97262,15 @@ function resolveDataPointMarker(series, pointIndex) {
97262
97262
  fill: point?.spPr?.fillColor ?? series.marker?.spPr?.fillColor
97263
97263
  };
97264
97264
  }
97265
+ var LEGEND_ITEM_WIDTH = 80;
97266
+ var LEGEND_ITEM_HEIGHT = 14;
97267
+ function computeChartLegendLayout(vm) {
97268
+ const vertical = vm.legendAnchor === "start";
97269
+ return vm.legend.map((entry2, i) => {
97270
+ const x = vertical ? vm.legendX : vm.legendX - vm.legend.length * LEGEND_ITEM_WIDTH / 2 + i * LEGEND_ITEM_WIDTH, y = vertical ? vm.legendY + i * LEGEND_ITEM_HEIGHT : vm.legendY;
97271
+ return { x, y, color: entry2.color, label: entry2.label };
97272
+ });
97273
+ }
97265
97274
  function schemaLabel(keys, token2, translate) {
97266
97275
  if (token2 === void 0) {
97267
97276
  return "";
@@ -97904,47 +97913,24 @@ function blendToWhite(color2) {
97904
97913
  if (!match) {
97905
97914
  return color2;
97906
97915
  }
97907
- const value = Number.parseInt(match[1], 16);
97908
- const mix = (channel) => Math.round(channel + (255 - channel) * 0.5);
97909
- const r = mix(value >> 16 & 255);
97910
- const g = mix(value >> 8 & 255);
97911
- const b = mix(value & 255);
97916
+ const value = Number.parseInt(match[1], 16), mix = (channel) => Math.round(channel + (255 - channel) * 0.5), r = mix(value >> 16 & 255), g = mix(value >> 8 & 255), b = mix(value & 255);
97912
97917
  return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, "0").toUpperCase()}`;
97913
97918
  }
97914
97919
  function invertNegativeFill(series, pointIndex, value, baseFill) {
97915
97920
  if (value >= 0) {
97916
97921
  return baseFill;
97917
97922
  }
97918
- const point = series.dataPoints?.find((p) => p.idx === pointIndex);
97919
- const invert = point?.invertIfNegative ?? series.invertIfNegative ?? false;
97923
+ const point = series.dataPoints?.find((p) => p.idx === pointIndex), invert = point?.invertIfNegative ?? series.invertIfNegative ?? false;
97920
97924
  return invert ? blendToWhite(baseFill) : baseFill;
97921
97925
  }
97922
97926
  function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, secondaryIdx, grouping, sourceIndices2) {
97923
- const primitives = [];
97924
- const dataLabels = [];
97925
- const series = chartData.series;
97926
- const palette = chartData.colorPalette;
97927
- const showLabels = chartData.style?.hasDataLabels;
97928
- const varyColorsSingle = chartData.varyColors === true && series.length === 1;
97927
+ const primitives = [], dataLabels = [], series = chartData.series, palette = chartData.colorPalette, showLabels = chartData.style?.hasDataLabels, varyColorsSingle = chartData.varyColors === true && series.length === 1;
97929
97928
  if (grouping === "clustered") {
97930
- const seriesCount = Math.max(series.length, 1);
97931
- const barGroupWidth2 = layout.plotWidth / Math.max(catCount, 1);
97932
- const singleBarWidth = chartData.barGapWidth !== void 0 ? barGroupWidth2 / (seriesCount + Math.max(chartData.barGapWidth, 0) / 100) : barGroupWidth2 * 0.7 / seriesCount;
97933
- const overlap = chartData.barOverlap ?? 0;
97934
- const step = singleBarWidth * (1 - overlap / 100);
97935
- const clusterWidth = singleBarWidth + step * (seriesCount - 1);
97936
- const groupOffset = (barGroupWidth2 - clusterWidth) / 2;
97929
+ const seriesCount = Math.max(series.length, 1), barGroupWidth2 = layout.plotWidth / Math.max(catCount, 1), singleBarWidth = chartData.barGapWidth !== void 0 ? barGroupWidth2 / (seriesCount + Math.max(chartData.barGapWidth, 0) / 100) : barGroupWidth2 * 0.7 / seriesCount, overlap = chartData.barOverlap ?? 0, step = singleBarWidth * (1 - overlap / 100), clusterWidth = singleBarWidth + step * (seriesCount - 1), groupOffset = (barGroupWidth2 - clusterWidth) / 2;
97937
97930
  for (let displayIndex = 0; displayIndex < catCount; displayIndex++) {
97938
97931
  const sourceIndex = sourceIndices2[displayIndex] ?? displayIndex;
97939
97932
  for (let si = 0; si < series.length; si++) {
97940
- const val2 = series[si].values[sourceIndex] ?? 0;
97941
- const x = layout.plotLeft + barGroupWidth2 * displayIndex + groupOffset + step * si;
97942
- const activeRange = secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange;
97943
- const zeroY = valueToY2(0, activeRange, layout.plotTop, layout.plotBottom);
97944
- const valY = valueToY2(val2, activeRange, layout.plotTop, layout.plotBottom);
97945
- const y = Math.min(zeroY, valY);
97946
- const h = Math.max(Math.abs(zeroY - valY), 1);
97947
- const baseFill = varyColorsSingle ? resolveVaryColorFill(series[si], sourceIndex, paletteColor2(sourceIndex, palette)) : resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor2(series[si], si, palette);
97933
+ const val2 = series[si].values[sourceIndex] ?? 0, x = layout.plotLeft + barGroupWidth2 * displayIndex + groupOffset + step * si, activeRange = secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange, zeroY = valueToY2(0, activeRange, layout.plotTop, layout.plotBottom), valY = valueToY2(val2, activeRange, layout.plotTop, layout.plotBottom), y = Math.min(zeroY, valY), h = Math.max(Math.abs(zeroY - valY), 1), baseFill = varyColorsSingle ? resolveVaryColorFill(series[si], sourceIndex, paletteColor2(sourceIndex, palette)) : resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor2(series[si], si, palette);
97948
97934
  primitives.push({
97949
97935
  kind: "rect",
97950
97936
  x,
@@ -97953,7 +97939,13 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97953
97939
  h,
97954
97940
  fill: invertNegativeFill(series[si], sourceIndex, val2, baseFill),
97955
97941
  rx: 1,
97956
- part: { role: "dataPoint", seriesIndex: si, pointIndex: sourceIndex }
97942
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: sourceIndex },
97943
+ title: buildMarkTooltip(
97944
+ series[si].name,
97945
+ chartData.categories[sourceIndex],
97946
+ val2,
97947
+ series[si].numberFormat
97948
+ )
97957
97949
  });
97958
97950
  if (showLabels) {
97959
97951
  const text2 = buildDataLabelText({
@@ -97982,19 +97974,23 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97982
97974
  const displaySeries2 = series.map((entry2) => ({
97983
97975
  ...entry2,
97984
97976
  values: sourceIndices2.map((sourceIndex) => entry2.values[sourceIndex] ?? 0)
97985
- }));
97986
- const rects = computeStackedBarRects(displaySeries2, catCount, layout, primaryRange, palette);
97977
+ })), rects = computeStackedBarRects(displaySeries2, catCount, layout, primaryRange, palette);
97987
97978
  for (const r of rects) {
97988
- let fill = r.fill;
97989
- let part;
97979
+ let fill = r.fill, part, title;
97990
97980
  if (r.seriesIndex !== void 0 && r.pointIndex !== void 0) {
97991
97981
  const sourcePointIndex = sourceIndices2[r.pointIndex] ?? r.pointIndex;
97992
97982
  fill = resolveDataPointFill(series[r.seriesIndex], sourcePointIndex, r.fill) ?? r.fill;
97993
97983
  const value = series[r.seriesIndex].values[sourcePointIndex] ?? 0;
97994
97984
  fill = invertNegativeFill(series[r.seriesIndex], sourcePointIndex, value, fill);
97995
97985
  part = { role: "dataPoint", seriesIndex: r.seriesIndex, pointIndex: sourcePointIndex };
97986
+ title = buildMarkTooltip(
97987
+ series[r.seriesIndex].name,
97988
+ chartData.categories[sourcePointIndex],
97989
+ value,
97990
+ series[r.seriesIndex].numberFormat
97991
+ );
97996
97992
  }
97997
- primitives.push({ kind: "rect", x: r.x, y: r.y, w: r.w, h: r.h, fill, rx: 1, part });
97993
+ primitives.push({ kind: "rect", x: r.x, y: r.y, w: r.w, h: r.h, fill, rx: 1, part, title });
97998
97994
  }
97999
97995
  if (showLabels) {
98000
97996
  pushClusteredStackedLabels(
@@ -98009,31 +98005,15 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
98009
98005
  }
98010
98006
  return { primitives, dataLabels };
98011
98007
  }
98012
- const barGroupWidth = layout.plotWidth / Math.max(catCount, 1);
98013
- const barW = barGroupWidth * 0.6;
98014
- const barOffset = (barGroupWidth - barW) / 2;
98015
- const displaySeries = series.map((entry2) => ({
98008
+ const barGroupWidth = layout.plotWidth / Math.max(catCount, 1), barW = barGroupWidth * 0.6, barOffset = (barGroupWidth - barW) / 2, displaySeries = series.map((entry2) => ({
98016
98009
  ...entry2,
98017
98010
  values: sourceIndices2.map((sourceIndex) => entry2.values[sourceIndex] ?? 0)
98018
- }));
98019
- const totals = categoryTotals(displaySeries, catCount);
98011
+ })), totals = categoryTotals(displaySeries, catCount);
98020
98012
  for (let ci = 0; ci < catCount; ci++) {
98021
- let posRunning = 0;
98022
- let negRunning = 0;
98013
+ let posRunning = 0, negRunning = 0;
98023
98014
  const catTotal = totals[ci] || 1;
98024
98015
  for (let si = 0; si < series.length; si++) {
98025
- const sourceIndex = sourceIndices2[ci] ?? ci;
98026
- const rawVal = series[si].values[sourceIndex] ?? 0;
98027
- const val2 = catTotal > 0 ? rawVal / catTotal * 100 : 0;
98028
- const isNeg = val2 < 0;
98029
- const base = isNeg ? negRunning : posRunning;
98030
- const top = base + val2;
98031
- const x = layout.plotLeft + barGroupWidth * ci + barOffset;
98032
- const baseY = valueToY2(base, primaryRange, layout.plotTop, layout.plotBottom);
98033
- const topY = valueToY2(top, primaryRange, layout.plotTop, layout.plotBottom);
98034
- const y = Math.min(baseY, topY);
98035
- const h = Math.max(Math.abs(baseY - topY), 0.5);
98036
- const pctBaseFill = resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor2(series[si], si, palette);
98016
+ const sourceIndex = sourceIndices2[ci] ?? ci, rawVal = series[si].values[sourceIndex] ?? 0, val2 = catTotal > 0 ? rawVal / catTotal * 100 : 0, isNeg = val2 < 0, base = isNeg ? negRunning : posRunning, top = base + val2, x = layout.plotLeft + barGroupWidth * ci + barOffset, baseY = valueToY2(base, primaryRange, layout.plotTop, layout.plotBottom), topY = valueToY2(top, primaryRange, layout.plotTop, layout.plotBottom), y = Math.min(baseY, topY), h = Math.max(Math.abs(baseY - topY), 0.5), pctBaseFill = resolveDataPointFill(series[si], sourceIndex, paletteColor2(si, palette)) ?? seriesColor2(series[si], si, palette);
98037
98017
  primitives.push({
98038
98018
  kind: "rect",
98039
98019
  x,
@@ -98041,7 +98021,13 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
98041
98021
  w: barW,
98042
98022
  h,
98043
98023
  fill: invertNegativeFill(series[si], sourceIndex, rawVal, pctBaseFill),
98044
- part: { role: "dataPoint", seriesIndex: si, pointIndex: sourceIndex }
98024
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: sourceIndex },
98025
+ title: buildMarkTooltip(
98026
+ series[si].name,
98027
+ chartData.categories[sourceIndex],
98028
+ rawVal,
98029
+ series[si].numberFormat
98030
+ )
98045
98031
  });
98046
98032
  if (showLabels && Math.abs(val2) > 0) {
98047
98033
  dataLabels.push({
@@ -98065,19 +98051,11 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
98065
98051
  return { primitives, dataLabels };
98066
98052
  }
98067
98053
  function pushClusteredStackedLabels(chartData, series, sourceIndices2, catCount, layout, range, dataLabels) {
98068
- const barGroupWidth = layout.plotWidth / catCount;
98069
- const seriesCount = Math.max(series.length, 1);
98070
- const singleBarWidth = barGroupWidth * 0.7 / seriesCount;
98071
- const groupOffset = (barGroupWidth - singleBarWidth * seriesCount) / 2;
98054
+ const barGroupWidth = layout.plotWidth / catCount, seriesCount = Math.max(series.length, 1), singleBarWidth = barGroupWidth * 0.7 / seriesCount, groupOffset = (barGroupWidth - singleBarWidth * seriesCount) / 2;
98072
98055
  for (let ci = 0; ci < catCount; ci++) {
98073
98056
  const sourceIndex = sourceIndices2[ci] ?? ci;
98074
98057
  for (let si = 0; si < series.length; si++) {
98075
- const val2 = series[si].values[sourceIndex] ?? 0;
98076
- const x = layout.plotLeft + barGroupWidth * ci + groupOffset + singleBarWidth * si + singleBarWidth / 2;
98077
- const zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
98078
- const valY = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
98079
- const labelY = val2 >= 0 ? Math.min(zeroY, valY) - 4 : Math.max(zeroY, valY) + 10;
98080
- const text2 = buildDataLabelText({
98058
+ const val2 = series[si].values[sourceIndex] ?? 0, x = layout.plotLeft + barGroupWidth * ci + groupOffset + singleBarWidth * si + singleBarWidth / 2, zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom), valY = valueToY2(val2, range, layout.plotTop, layout.plotBottom), labelY = val2 >= 0 ? Math.min(zeroY, valY) - 4 : Math.max(zeroY, valY) + 10, text2 = buildDataLabelText({
98081
98059
  chartData,
98082
98060
  series: series[si],
98083
98061
  pointIndex: sourceIndex,
@@ -98269,9 +98247,12 @@ function buildMarkerPrimitive(input) {
98269
98247
  return { kind: "circle", cx, cy, r, fill, part };
98270
98248
  }
98271
98249
  }
98272
- function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius2, part, opacity2) {
98273
- const marker = resolveDataPointMarker(series, pointIndex);
98274
- const m = buildMarkerPrimitive({
98250
+ function xyMarkTooltip(seriesName, xVal, yVal, numberFormat) {
98251
+ const y = formatAxisValue2(yVal, numberFormat), coords = xVal !== void 0 ? `(${formatAxisValue2(xVal)}, ${y})` : y;
98252
+ return seriesName.length > 0 ? `${seriesName}: ${coords}` : coords;
98253
+ }
98254
+ function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius2, part, opacity2, title) {
98255
+ const marker = resolveDataPointMarker(series, pointIndex), m = buildMarkerPrimitive({
98275
98256
  symbol: marker.symbol,
98276
98257
  size: marker.size,
98277
98258
  cx,
@@ -98288,34 +98269,180 @@ function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius2, part,
98288
98269
  if (opacity2 !== void 0) {
98289
98270
  m.opacity = opacity2;
98290
98271
  }
98272
+ if (title !== void 0) {
98273
+ m.title = title;
98274
+ }
98291
98275
  out.push(m);
98292
98276
  }
98293
- function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, secondaryIdx, sourceIndices2, xPositions) {
98294
- const primitives = [];
98295
- const dataLabels = [];
98296
- const showLabels = chartData.style?.hasDataLabels;
98277
+ function seriesXValues(chartData, series) {
98278
+ if (series.xValues && series.xValues.length > 0) {
98279
+ return series.xValues;
98280
+ }
98281
+ const fromCategories = chartData.categories.map(Number);
98282
+ return fromCategories.length > 0 ? fromCategories : void 0;
98283
+ }
98284
+ function scatterDrawsLine(chartData, series) {
98285
+ if (series.lineNoFill === true) {
98286
+ return false;
98287
+ }
98288
+ const style = chartData.scatterStyle;
98289
+ return style === "line" || style === "lineMarker" || style === "smooth" || style === "smoothMarker";
98290
+ }
98291
+ function buildScatter(chartData, layout, range) {
98292
+ const primitives = [], dataLabels = [], showLabels = chartData.style?.hasDataLabels, allIndices = chartData.series.flatMap((s) => s.values.map((_, i) => i)), maxXIndex = Math.max(1, ...allIndices), perSeriesX = chartData.series.map((series) => seriesXValues(chartData, series)), xDomain = computeScatterXDomain(perSeriesX), smoothStyle = chartData.scatterStyle === "smooth" || chartData.scatterStyle === "smoothMarker";
98297
98293
  for (let si = 0; si < chartData.series.length; si++) {
98298
- const series = chartData.series[si];
98294
+ const series = chartData.series[si], c = seriesColor2(series, si, chartData.colorPalette), dots = computeScatterDots(series.values, maxXIndex, layout, range, perSeriesX[si], xDomain);
98295
+ if (scatterDrawsLine(chartData, series) && dots.length >= 2) {
98296
+ const points3 = dots.map((dot) => ({ x: dot.cx, y: dot.cy })), seriesPart = { role: "series", seriesIndex: si };
98297
+ primitives.push(
98298
+ series.smooth ?? smoothStyle ? {
98299
+ kind: "path",
98300
+ d: smoothLinePath(points3),
98301
+ stroke: c,
98302
+ strokeWidth: 2.4,
98303
+ fill: "none",
98304
+ part: seriesPart
98305
+ } : {
98306
+ kind: "polyline",
98307
+ points: linePointsToSvgString(points3),
98308
+ stroke: c,
98309
+ strokeWidth: 2.4,
98310
+ fill: "none",
98311
+ part: seriesPart
98312
+ }
98313
+ );
98314
+ }
98315
+ dots.forEach((dot, vi) => {
98316
+ const part = { role: "dataPoint", seriesIndex: si, pointIndex: vi };
98317
+ pushMarker(
98318
+ primitives,
98319
+ series,
98320
+ vi,
98321
+ dot.cx,
98322
+ dot.cy,
98323
+ resolveDataPointFill(series, vi, c) ?? c,
98324
+ 4,
98325
+ part,
98326
+ 0.85,
98327
+ xyMarkTooltip(
98328
+ series.name,
98329
+ perSeriesX[si]?.[vi],
98330
+ series.values[vi] ?? 0,
98331
+ series.numberFormat
98332
+ )
98333
+ );
98334
+ });
98335
+ if (showLabels) {
98336
+ series.values.forEach((val2, vi) => {
98337
+ const dot = dots[vi], text2 = buildDataLabelText({ chartData, series, pointIndex: vi, value: val2 });
98338
+ if (!dot || text2 === void 0) {
98339
+ return;
98340
+ }
98341
+ dataLabels.push({
98342
+ kind: "text",
98343
+ x: dot.cx,
98344
+ y: dot.cy - 6,
98345
+ text: text2,
98346
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98347
+ fill: "#334155",
98348
+ textAnchor: "middle"
98349
+ });
98350
+ });
98351
+ }
98352
+ }
98353
+ return { primitives, dataLabels };
98354
+ }
98355
+ function buildBubbles(chartData, layout, range) {
98356
+ const primitives = [], dataLabels = [], showLabels = chartData.style?.hasDataLabels, allIndices = chartData.series.flatMap((s) => s.values.map((_, i) => i)), maxXIndex = Math.max(1, ...allIndices), perSeriesX = chartData.series.map((series) => seriesXValues(chartData, series)), xDomain = computeScatterXDomain(perSeriesX), allSizes = chartData.series.flatMap((series) => series.bubbleSizes ?? []), maxBubble = allSizes.length > 0 ? Math.max(1, ...allSizes.map(Math.abs)) : 1, medianRadius = Math.min(layout.plotWidth, layout.plotHeight) * 0.04;
98357
+ for (let si = 0; si < chartData.series.length; si++) {
98358
+ const series = chartData.series[si], c = seriesColor2(series, si, chartData.colorPalette), dots = computeScatterDots(series.values, maxXIndex, layout, range, perSeriesX[si], xDomain);
98359
+ dots.forEach((dot, vi) => {
98360
+ const r = computeBubbleRadius(series.bubbleSizes?.[vi], maxBubble, medianRadius), size = series.bubbleSizes?.[vi], label = size !== void 0 ? `${xyMarkTooltip(series.name, perSeriesX[si]?.[vi], series.values[vi] ?? 0, series.numberFormat)}, size ${formatAxisValue2(size)}` : xyMarkTooltip(
98361
+ series.name,
98362
+ perSeriesX[si]?.[vi],
98363
+ series.values[vi] ?? 0,
98364
+ series.numberFormat
98365
+ );
98366
+ primitives.push({
98367
+ kind: "circle",
98368
+ cx: dot.cx,
98369
+ cy: dot.cy,
98370
+ r,
98371
+ fill: resolveDataPointFill(series, vi, c) ?? c,
98372
+ opacity: 0.6,
98373
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: vi },
98374
+ title: label
98375
+ });
98376
+ });
98377
+ if (showLabels) {
98378
+ series.values.forEach((val2, vi) => {
98379
+ const dot = dots[vi], text2 = buildDataLabelText({ chartData, series, pointIndex: vi, value: val2 });
98380
+ if (!dot || text2 === void 0) {
98381
+ return;
98382
+ }
98383
+ dataLabels.push({
98384
+ kind: "text",
98385
+ x: dot.cx,
98386
+ y: dot.cy - 10,
98387
+ text: text2,
98388
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98389
+ fill: "#334155",
98390
+ textAnchor: "middle"
98391
+ });
98392
+ });
98393
+ }
98394
+ }
98395
+ return { primitives, dataLabels };
98396
+ }
98397
+ function categoryAbsTotals(seriesValues, catCount) {
98398
+ return Array.from(
98399
+ { length: catCount },
98400
+ (_, ci) => seriesValues.reduce((sum, values) => sum + Math.abs(values[ci] ?? 0), 0)
98401
+ );
98402
+ }
98403
+ function computeStackedSeriesPlots(seriesValues, catCount, percent3) {
98404
+ const totals = percent3 ? categoryAbsTotals(seriesValues, catCount) : void 0, posRunning = new Array(catCount).fill(0), negRunning = new Array(catCount).fill(0);
98405
+ return seriesValues.map((values) => {
98406
+ const cumulative = [], base = [], own = [];
98407
+ for (let ci = 0; ci < catCount; ci++) {
98408
+ const raw = values[ci] ?? 0, total = totals?.[ci] ?? 0, val2 = percent3 ? total > 0 ? raw / total * 100 : 0 : raw, isNeg = val2 < 0, from = isNeg ? negRunning[ci] : posRunning[ci], to = from + val2;
98409
+ base.push(from);
98410
+ cumulative.push(to);
98411
+ own.push(val2);
98412
+ if (isNeg) {
98413
+ negRunning[ci] = to;
98414
+ } else {
98415
+ posRunning[ci] = to;
98416
+ }
98417
+ }
98418
+ return { cumulative, base, own };
98419
+ });
98420
+ }
98421
+ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, secondaryIdx, sourceIndices2, xPositions, stacking = "clustered") {
98422
+ const primitives = [], dataLabels = [], showLabels = chartData.style?.hasDataLabels, isStackedMode = stacking !== "clustered", isPercent = stacking === "percentStacked", resolved = chartData.series.map((series) => {
98299
98423
  if (series.values.length === 0) {
98300
- continue;
98424
+ return void 0;
98301
98425
  }
98302
- const activeRange = secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange;
98303
- const rawValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0);
98304
- const displayBlanks = sourceIndices2.map((sourceIndex) => series.blanks?.[sourceIndex] ?? false);
98305
- const { values: displayValues, visible } = resolveBlankDisplay(
98426
+ const rawValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0), displayBlanks = sourceIndices2.map((sourceIndex) => series.blanks?.[sourceIndex] ?? false), { values: displayValues, visible } = resolveBlankDisplay(
98306
98427
  rawValues,
98307
98428
  displayBlanks,
98308
98429
  chartData.chartChrome?.dispBlanksAs
98309
98430
  );
98310
- const pts = computeLinePoints(displayValues, catCount, layout, activeRange).map(
98311
- (point, index) => ({
98312
- ...point,
98313
- x: xPositions?.[index] ?? point.x
98314
- })
98315
- );
98316
- const c = seriesColor2(series, si, chartData.colorPalette);
98317
- const seriesPart = { role: "series", seriesIndex: si };
98318
- const allVisible = visible.every(Boolean);
98431
+ return { displayValues, visible };
98432
+ }), stackedPlots = isStackedMode ? computeStackedSeriesPlots(
98433
+ resolved.map((entry2) => entry2?.displayValues ?? []),
98434
+ catCount,
98435
+ isPercent
98436
+ ) : void 0;
98437
+ for (let si = 0; si < chartData.series.length; si++) {
98438
+ const series = chartData.series[si], entry2 = resolved[si];
98439
+ if (!entry2) {
98440
+ continue;
98441
+ }
98442
+ const { displayValues, visible } = entry2, activeRange = isStackedMode ? primaryRange : secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange, plotValues = stackedPlots ? stackedPlots[si].cumulative : displayValues, pts = computeLinePoints(plotValues, catCount, layout, activeRange).map((point, index) => ({
98443
+ ...point,
98444
+ x: xPositions?.[index] ?? point.x
98445
+ })), c = seriesColor2(series, si, chartData.colorPalette), seriesPart = { role: "series", seriesIndex: si }, allVisible = visible.every(Boolean);
98319
98446
  if (allVisible) {
98320
98447
  primitives.push(
98321
98448
  series.smooth ? {
@@ -98353,8 +98480,7 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98353
98480
  if (!visible[displayIndex]) {
98354
98481
  return;
98355
98482
  }
98356
- const idx = sourceIndices2[displayIndex] ?? displayIndex;
98357
- const part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98483
+ const idx = sourceIndices2[displayIndex] ?? displayIndex, part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98358
98484
  pushMarker(
98359
98485
  primitives,
98360
98486
  series,
@@ -98363,19 +98489,45 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98363
98489
  pt.y,
98364
98490
  resolveDataPointFill(series, idx, c) ?? c,
98365
98491
  2.5,
98366
- part
98492
+ part,
98493
+ void 0,
98494
+ buildMarkTooltip(
98495
+ series.name,
98496
+ chartData.categories[idx],
98497
+ series.values[idx] ?? 0,
98498
+ series.numberFormat
98499
+ )
98367
98500
  );
98368
98501
  });
98369
98502
  if (showLabels) {
98370
- displayValues.forEach((val2, displayIndex) => {
98503
+ const labelValues = stackedPlots ? stackedPlots[si].own : displayValues;
98504
+ labelValues.forEach((val2, displayIndex) => {
98371
98505
  const pt = pts[displayIndex];
98506
+ if (!pt || !visible[displayIndex]) {
98507
+ return;
98508
+ }
98509
+ if (isPercent) {
98510
+ if (val2 === 0) {
98511
+ return;
98512
+ }
98513
+ dataLabels.push({
98514
+ kind: "text",
98515
+ x: pt.x,
98516
+ y: pt.y - 7,
98517
+ text: `${Math.round(val2)}%`,
98518
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98519
+ fill: "#334155",
98520
+ textAnchor: "middle"
98521
+ });
98522
+ return;
98523
+ }
98372
98524
  const text2 = buildDataLabelText({
98373
98525
  chartData,
98374
98526
  series,
98375
98527
  pointIndex: sourceIndices2[displayIndex] ?? displayIndex,
98376
98528
  value: val2
98377
98529
  });
98378
- if (!pt || !visible[displayIndex] || text2 === void 0) {
98530
+ if (text2 === void 0) {
98379
98531
  return;
98380
98532
  }
98381
98533
  dataLabels.push({
@@ -98392,26 +98544,41 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98392
98544
  }
98393
98545
  return { primitives, dataLabels };
98394
98546
  }
98395
- function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositions) {
98396
- const primitives = [];
98397
- const dataLabels = [];
98398
- const showLabels = chartData.style?.hasDataLabels;
98399
- const baselineY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
98547
+ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositions, stacking = "clustered") {
98548
+ const primitives = [], dataLabels = [], showLabels = chartData.style?.hasDataLabels, isStackedMode = stacking !== "clustered", isPercent = stacking === "percentStacked", baselineY = valueToY2(0, range, layout.plotTop, layout.plotBottom), allDisplayValues = chartData.series.map(
98549
+ (series) => series.values.length === 0 ? void 0 : sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0)
98550
+ ), stackedPlots = isStackedMode ? computeStackedSeriesPlots(
98551
+ allDisplayValues.map((values) => values ?? []),
98552
+ catCount,
98553
+ isPercent
98554
+ ) : void 0;
98400
98555
  for (let si = 0; si < chartData.series.length; si++) {
98401
- const series = chartData.series[si];
98402
- if (series.values.length === 0) {
98556
+ const series = chartData.series[si], displayValues = allDisplayValues[si];
98557
+ if (!displayValues) {
98403
98558
  continue;
98404
98559
  }
98405
- const displayValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0);
98406
- const pts = computeLinePoints(displayValues, catCount, layout, range).map((point, index) => ({
98560
+ const plot = stackedPlots?.[si], topValues = plot ? plot.cumulative : displayValues, pts = computeLinePoints(topValues, catCount, layout, range).map((point, index) => ({
98407
98561
  ...point,
98408
98562
  x: xPositions?.[index] ?? point.x
98409
- }));
98410
- const c = seriesColor2(series, si, chartData.colorPalette);
98411
- const lineStr = linePointsToSvgString(pts);
98412
- const firstPt = pts[0];
98413
- const lastPt = pts[pts.length - 1];
98414
- if (firstPt && lastPt) {
98563
+ })), c = seriesColor2(series, si, chartData.colorPalette), lineStr = linePointsToSvgString(pts), firstPt = pts[0], lastPt = pts[pts.length - 1];
98564
+ if (plot) {
98565
+ const baseStr = linePointsToSvgString(
98566
+ [
98567
+ ...computeLinePoints(plot.base, catCount, layout, range).map((point, index) => ({
98568
+ ...point,
98569
+ x: xPositions?.[index] ?? point.x
98570
+ }))
98571
+ ].reverse()
98572
+ );
98573
+ primitives.push({
98574
+ kind: "polyline",
98575
+ points: `${lineStr} ${baseStr}`,
98576
+ stroke: "none",
98577
+ strokeWidth: 0,
98578
+ fill: c,
98579
+ part: { role: "series", seriesIndex: si }
98580
+ });
98581
+ } else if (firstPt && lastPt) {
98415
98582
  primitives.push({
98416
98583
  kind: "polyline",
98417
98584
  points: `${firstPt.x.toFixed(2)},${baselineY.toFixed(2)} ${lineStr} ${lastPt.x.toFixed(2)},${baselineY.toFixed(2)}`,
@@ -98431,8 +98598,7 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98431
98598
  part: { role: "series", seriesIndex: si }
98432
98599
  });
98433
98600
  pts.forEach((pt, displayIndex) => {
98434
- const idx = sourceIndices2[displayIndex] ?? displayIndex;
98435
- const part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98601
+ const idx = sourceIndices2[displayIndex] ?? displayIndex, part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98436
98602
  pushMarker(
98437
98603
  primitives,
98438
98604
  series,
@@ -98441,19 +98607,45 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98441
98607
  pt.y,
98442
98608
  resolveDataPointFill(series, idx, c) ?? c,
98443
98609
  2,
98444
- part
98610
+ part,
98611
+ void 0,
98612
+ buildMarkTooltip(
98613
+ series.name,
98614
+ chartData.categories[idx],
98615
+ series.values[idx] ?? 0,
98616
+ series.numberFormat
98617
+ )
98445
98618
  );
98446
98619
  });
98447
98620
  if (showLabels) {
98448
- displayValues.forEach((val2, displayIndex) => {
98621
+ const labelValues = plot ? plot.own : displayValues;
98622
+ labelValues.forEach((val2, displayIndex) => {
98449
98623
  const pt = pts[displayIndex];
98624
+ if (!pt) {
98625
+ return;
98626
+ }
98627
+ if (isPercent) {
98628
+ if (val2 === 0) {
98629
+ return;
98630
+ }
98631
+ dataLabels.push({
98632
+ kind: "text",
98633
+ x: pt.x,
98634
+ y: pt.y - 6,
98635
+ text: `${Math.round(val2)}%`,
98636
+ fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98637
+ fill: "#334155",
98638
+ textAnchor: "middle"
98639
+ });
98640
+ return;
98641
+ }
98450
98642
  const text2 = buildDataLabelText({
98451
98643
  chartData,
98452
98644
  series,
98453
98645
  pointIndex: sourceIndices2[displayIndex] ?? displayIndex,
98454
98646
  value: val2
98455
98647
  });
98456
- if (!pt || text2 === void 0) {
98648
+ if (text2 === void 0) {
98457
98649
  return;
98458
98650
  }
98459
98651
  dataLabels.push({
@@ -98470,151 +98662,6 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98470
98662
  }
98471
98663
  return { primitives, dataLabels };
98472
98664
  }
98473
- function seriesXValues(chartData, series) {
98474
- if (series.xValues && series.xValues.length > 0) {
98475
- return series.xValues;
98476
- }
98477
- const fromCategories = chartData.categories.map(Number);
98478
- return fromCategories.length > 0 ? fromCategories : void 0;
98479
- }
98480
- function scatterDrawsLine(chartData, series) {
98481
- if (series.lineNoFill === true) {
98482
- return false;
98483
- }
98484
- const style = chartData.scatterStyle;
98485
- return style === "line" || style === "lineMarker" || style === "smooth" || style === "smoothMarker";
98486
- }
98487
- function buildScatter(chartData, layout, range) {
98488
- const primitives = [];
98489
- const dataLabels = [];
98490
- const showLabels = chartData.style?.hasDataLabels;
98491
- const allIndices = chartData.series.flatMap((s) => s.values.map((_, i) => i));
98492
- const maxXIndex = Math.max(1, ...allIndices);
98493
- const perSeriesX = chartData.series.map((series) => seriesXValues(chartData, series));
98494
- const xDomain = computeScatterXDomain(perSeriesX);
98495
- const smoothStyle = chartData.scatterStyle === "smooth" || chartData.scatterStyle === "smoothMarker";
98496
- for (let si = 0; si < chartData.series.length; si++) {
98497
- const series = chartData.series[si];
98498
- const c = seriesColor2(series, si, chartData.colorPalette);
98499
- const dots = computeScatterDots(
98500
- series.values,
98501
- maxXIndex,
98502
- layout,
98503
- range,
98504
- perSeriesX[si],
98505
- xDomain
98506
- );
98507
- if (scatterDrawsLine(chartData, series) && dots.length >= 2) {
98508
- const points3 = dots.map((dot) => ({ x: dot.cx, y: dot.cy }));
98509
- const seriesPart = { role: "series", seriesIndex: si };
98510
- primitives.push(
98511
- series.smooth ?? smoothStyle ? {
98512
- kind: "path",
98513
- d: smoothLinePath(points3),
98514
- stroke: c,
98515
- strokeWidth: 2.4,
98516
- fill: "none",
98517
- part: seriesPart
98518
- } : {
98519
- kind: "polyline",
98520
- points: linePointsToSvgString(points3),
98521
- stroke: c,
98522
- strokeWidth: 2.4,
98523
- fill: "none",
98524
- part: seriesPart
98525
- }
98526
- );
98527
- }
98528
- dots.forEach((dot, vi) => {
98529
- const part = { role: "dataPoint", seriesIndex: si, pointIndex: vi };
98530
- pushMarker(
98531
- primitives,
98532
- series,
98533
- vi,
98534
- dot.cx,
98535
- dot.cy,
98536
- resolveDataPointFill(series, vi, c) ?? c,
98537
- 4,
98538
- part,
98539
- 0.85
98540
- );
98541
- });
98542
- if (showLabels) {
98543
- series.values.forEach((val2, vi) => {
98544
- const dot = dots[vi];
98545
- const text2 = buildDataLabelText({ chartData, series, pointIndex: vi, value: val2 });
98546
- if (!dot || text2 === void 0) {
98547
- return;
98548
- }
98549
- dataLabels.push({
98550
- kind: "text",
98551
- x: dot.cx,
98552
- y: dot.cy - 6,
98553
- text: text2,
98554
- fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98555
- fill: "#334155",
98556
- textAnchor: "middle"
98557
- });
98558
- });
98559
- }
98560
- }
98561
- return { primitives, dataLabels };
98562
- }
98563
- function buildBubbles(chartData, layout, range) {
98564
- const primitives = [];
98565
- const dataLabels = [];
98566
- const showLabels = chartData.style?.hasDataLabels;
98567
- const allIndices = chartData.series.flatMap((s) => s.values.map((_, i) => i));
98568
- const maxXIndex = Math.max(1, ...allIndices);
98569
- const perSeriesX = chartData.series.map((series) => seriesXValues(chartData, series));
98570
- const xDomain = computeScatterXDomain(perSeriesX);
98571
- const allSizes = chartData.series.flatMap((series) => series.bubbleSizes ?? []);
98572
- const maxBubble = allSizes.length > 0 ? Math.max(1, ...allSizes.map(Math.abs)) : 1;
98573
- const medianRadius = Math.min(layout.plotWidth, layout.plotHeight) * 0.04;
98574
- for (let si = 0; si < chartData.series.length; si++) {
98575
- const series = chartData.series[si];
98576
- const c = seriesColor2(series, si, chartData.colorPalette);
98577
- const dots = computeScatterDots(
98578
- series.values,
98579
- maxXIndex,
98580
- layout,
98581
- range,
98582
- perSeriesX[si],
98583
- xDomain
98584
- );
98585
- dots.forEach((dot, vi) => {
98586
- const r = computeBubbleRadius(series.bubbleSizes?.[vi], maxBubble, medianRadius);
98587
- primitives.push({
98588
- kind: "circle",
98589
- cx: dot.cx,
98590
- cy: dot.cy,
98591
- r,
98592
- fill: resolveDataPointFill(series, vi, c) ?? c,
98593
- opacity: 0.6,
98594
- part: { role: "dataPoint", seriesIndex: si, pointIndex: vi }
98595
- });
98596
- });
98597
- if (showLabels) {
98598
- series.values.forEach((val2, vi) => {
98599
- const dot = dots[vi];
98600
- const text2 = buildDataLabelText({ chartData, series, pointIndex: vi, value: val2 });
98601
- if (!dot || text2 === void 0) {
98602
- return;
98603
- }
98604
- dataLabels.push({
98605
- kind: "text",
98606
- x: dot.cx,
98607
- y: dot.cy - 10,
98608
- text: text2,
98609
- fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98610
- fill: "#334155",
98611
- textAnchor: "middle"
98612
- });
98613
- });
98614
- }
98615
- }
98616
- return { primitives, dataLabels };
98617
- }
98618
98665
  function categoryX(index, catCount, layout, options) {
98619
98666
  const explicit = options.xPositions?.[index];
98620
98667
  if (explicit !== void 0) {
@@ -99122,10 +99169,7 @@ function valueToX(val2, range, leftX, rightX) {
99122
99169
  const usable = rightX - leftX;
99123
99170
  let ratio;
99124
99171
  if (range.logScale && range.logBase) {
99125
- const base = range.logBase;
99126
- const clampedVal = Math.max(val2, range.min);
99127
- const logVal = Math.log(clampedVal) / Math.log(base);
99128
- const logMin = Math.log(range.min) / Math.log(base);
99172
+ const base = range.logBase, clampedVal = Math.max(val2, range.min), logVal = Math.log(clampedVal) / Math.log(base), logMin = Math.log(range.min) / Math.log(base);
99129
99173
  ratio = (logVal - logMin) / range.span;
99130
99174
  } else {
99131
99175
  ratio = (val2 - range.min) / range.span;
@@ -99133,8 +99177,7 @@ function valueToX(val2, range, leftX, rightX) {
99133
99177
  return range.reverseOrder ? rightX - ratio * usable : leftX + ratio * usable;
99134
99178
  }
99135
99179
  function buildTransposedValueAxis(range, layout) {
99136
- const gridlines = [];
99137
- const axisLabels = [];
99180
+ const gridlines = [], axisLabels = [];
99138
99181
  for (const val2 of axisTickValues(range)) {
99139
99182
  const x = valueToX(val2, range, layout.plotLeft, layout.plotRight);
99140
99183
  gridlines.push({
@@ -99159,8 +99202,7 @@ function buildTransposedValueAxis(range, layout) {
99159
99202
  return { gridlines, axisLabels };
99160
99203
  }
99161
99204
  function buildSideCategoryLabels(categoryLabels, layout) {
99162
- const catCount = Math.max(categoryLabels.length, 1);
99163
- const band = layout.plotHeight / catCount;
99205
+ const catCount = Math.max(categoryLabels.length, 1), band = layout.plotHeight / catCount;
99164
99206
  return categoryLabels.map((label, i) => ({
99165
99207
  kind: "text",
99166
99208
  x: layout.plotLeft - 4,
@@ -99186,16 +99228,7 @@ function barFill(chartData, series, seriesIndex, pointIndex) {
99186
99228
  return resolveDataPointFill(series, pointIndex, paletteColor2(seriesIndex, palette)) ?? seriesColor2(series, seriesIndex, palette);
99187
99229
  }
99188
99230
  function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99189
- const layout = computePlotLayout(element.width, element.height, chartData, true);
99190
- const catCount = Math.max(categoryLabels.length, 1);
99191
- const series = chartData.series;
99192
- const grouping = chartData.grouping ?? "clustered";
99193
- const isStacked = grouping === "stacked" || grouping === "percentStacked";
99194
- const isPercent = grouping === "percentStacked";
99195
- const range = isPercent ? { min: 0, max: 100, span: 100 } : isStacked ? computeStackedValueRange(series, catCount) : computeValueRangeForChart(series, chartData.axes);
99196
- const { gridlines, axisLabels } = buildTransposedValueAxis(range, layout);
99197
- const zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight);
99198
- const zeroLine = range.min < 0 && range.max > 0 ? {
99231
+ const layout = computePlotLayout(element.width, element.height, chartData, true), catCount = Math.max(categoryLabels.length, 1), series = chartData.series, grouping = chartData.grouping ?? "clustered", isStacked = grouping === "stacked" || grouping === "percentStacked", isPercent = grouping === "percentStacked", range = isPercent ? { min: 0, max: 100, span: 100 } : isStacked ? computeStackedValueRange(series, catCount) : computeValueRangeForChart(series, chartData.axes), { gridlines, axisLabels } = buildTransposedValueAxis(range, layout), zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight), zeroLine = range.min < 0 && range.max > 0 ? {
99199
99232
  kind: "line",
99200
99233
  x1: zeroX,
99201
99234
  y1: layout.plotTop,
@@ -99203,25 +99236,12 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99203
99236
  y2: layout.plotBottom,
99204
99237
  stroke: ZERO_LINE_COLOR,
99205
99238
  strokeWidth: 1
99206
- } : void 0;
99207
- const primitives = [];
99208
- const dataLabels = [];
99209
- const showLabels = chartData.style?.hasDataLabels;
99210
- const band = layout.plotHeight / catCount;
99239
+ } : void 0, primitives = [], dataLabels = [], showLabels = chartData.style?.hasDataLabels, band = layout.plotHeight / catCount;
99211
99240
  if (!isStacked) {
99212
- const seriesCount = Math.max(series.length, 1);
99213
- const singleBarHeight = chartData.barGapWidth !== void 0 ? band / (seriesCount + Math.max(chartData.barGapWidth, 0) / 100) : band * 0.7 / seriesCount;
99214
- const overlap = chartData.barOverlap ?? 0;
99215
- const step = singleBarHeight * (1 - overlap / 100);
99216
- const clusterHeight = singleBarHeight + step * (seriesCount - 1);
99217
- const groupOffset = (band - clusterHeight) / 2;
99241
+ const seriesCount = Math.max(series.length, 1), singleBarHeight = chartData.barGapWidth !== void 0 ? band / (seriesCount + Math.max(chartData.barGapWidth, 0) / 100) : band * 0.7 / seriesCount, overlap = chartData.barOverlap ?? 0, step = singleBarHeight * (1 - overlap / 100), clusterHeight = singleBarHeight + step * (seriesCount - 1), groupOffset = (band - clusterHeight) / 2;
99218
99242
  for (let ci = 0; ci < catCount; ci++) {
99219
99243
  for (let si = 0; si < series.length; si++) {
99220
- const val2 = series[si].values[ci] ?? 0;
99221
- const y = layout.plotTop + band * ci + groupOffset + step * si;
99222
- const valX = valueToX(val2, range, layout.plotLeft, layout.plotRight);
99223
- const x = Math.min(zeroX, valX);
99224
- const w = Math.max(Math.abs(valX - zeroX), 1);
99244
+ const val2 = series[si].values[ci] ?? 0, y = layout.plotTop + band * ci + groupOffset + step * si, valX = valueToX(val2, range, layout.plotLeft, layout.plotRight), x = Math.min(zeroX, valX), w = Math.max(Math.abs(valX - zeroX), 1);
99225
99245
  primitives.push({
99226
99246
  kind: "rect",
99227
99247
  x,
@@ -99230,7 +99250,13 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99230
99250
  h: singleBarHeight,
99231
99251
  fill: barFill(chartData, series[si], si, ci),
99232
99252
  rx: 1,
99233
- part: { role: "dataPoint", seriesIndex: si, pointIndex: ci }
99253
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: ci },
99254
+ title: buildMarkTooltip(
99255
+ series[si].name,
99256
+ categoryLabels[ci],
99257
+ val2,
99258
+ series[si].numberFormat
99259
+ )
99234
99260
  });
99235
99261
  if (showLabels) {
99236
99262
  dataLabels.push({
@@ -99247,27 +99273,16 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99247
99273
  }
99248
99274
  }
99249
99275
  } else {
99250
- const totals = isPercent ? categoryTotals2(series, catCount) : [];
99251
- const barH = band * (isPercent ? 0.6 : 0.7);
99252
- const barOffset = (band - barH) / 2;
99276
+ const totals = isPercent ? categoryTotals2(series, catCount) : [], barH = band * (isPercent ? 0.6 : 0.7), barOffset = (band - barH) / 2;
99253
99277
  for (let ci = 0; ci < catCount; ci++) {
99254
- let posRunning = 0;
99255
- let negRunning = 0;
99278
+ let posRunning = 0, negRunning = 0;
99256
99279
  const catTotal = isPercent ? totals[ci] || 1 : 1;
99257
99280
  for (let si = 0; si < series.length; si++) {
99258
- const rawVal = series[si].values[ci] ?? 0;
99259
- const val2 = isPercent ? rawVal / catTotal * 100 : rawVal;
99281
+ const rawVal = series[si].values[ci] ?? 0, val2 = isPercent ? rawVal / catTotal * 100 : rawVal;
99260
99282
  if (val2 === 0) {
99261
99283
  continue;
99262
99284
  }
99263
- const isNeg = val2 < 0;
99264
- const base = isNeg ? negRunning : posRunning;
99265
- const top = base + val2;
99266
- const y = layout.plotTop + band * ci + barOffset;
99267
- const baseX = valueToX(base, range, layout.plotLeft, layout.plotRight);
99268
- const topX = valueToX(top, range, layout.plotLeft, layout.plotRight);
99269
- const x = Math.min(baseX, topX);
99270
- const w = Math.max(Math.abs(topX - baseX), 0.5);
99285
+ const isNeg = val2 < 0, base = isNeg ? negRunning : posRunning, top = base + val2, y = layout.plotTop + band * ci + barOffset, baseX = valueToX(base, range, layout.plotLeft, layout.plotRight), topX = valueToX(top, range, layout.plotLeft, layout.plotRight), x = Math.min(baseX, topX), w = Math.max(Math.abs(topX - baseX), 0.5);
99271
99286
  primitives.push({
99272
99287
  kind: "rect",
99273
99288
  x,
@@ -99276,7 +99291,13 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99276
99291
  h: barH,
99277
99292
  fill: barFill(chartData, series[si], si, ci),
99278
99293
  rx: 1,
99279
- part: { role: "dataPoint", seriesIndex: si, pointIndex: ci }
99294
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: ci },
99295
+ title: buildMarkTooltip(
99296
+ series[si].name,
99297
+ categoryLabels[ci],
99298
+ rawVal,
99299
+ series[si].numberFormat
99300
+ )
99280
99301
  });
99281
99302
  if (showLabels && Math.abs(val2) > 0) {
99282
99303
  dataLabels.push({
@@ -99299,8 +99320,7 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99299
99320
  }
99300
99321
  }
99301
99322
  }
99302
- const legendPos = chartData.style?.legendPosition ?? "b";
99303
- const { legend, legendX, legendY, legendAnchor } = buildLegend(
99323
+ const legendPos = chartData.style?.legendPosition ?? "b", { legend, legendX, legendY, legendAnchor } = buildLegend(
99304
99324
  series,
99305
99325
  chartData.colorPalette,
99306
99326
  layout.svgWidth,
@@ -99935,7 +99955,7 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
99935
99955
  const layoutOpts = computeLayoutOptions(chartData.axes, chartData.dataTable, seriesCount);
99936
99956
  const layout = computePlotLayout(element.width, element.height, chartData, true, layoutOpts);
99937
99957
  const catCount = Math.max(categoryLabels.length, 1);
99938
- const isStacked = kind === "bar" && (chartData.grouping === "stacked" || chartData.grouping === "percentStacked");
99958
+ const isStacked = (kind === "bar" || kind === "line" || kind === "area") && (chartData.grouping === "stacked" || chartData.grouping === "percentStacked");
99939
99959
  const isPercent = isStacked && chartData.grouping === "percentStacked";
99940
99960
  const { secondary } = splitSeriesByAxis(chartData.series, chartData.axes);
99941
99961
  const secondaryIdx = new Set(secondary.map((e) => e.index));
@@ -99997,7 +100017,8 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
99997
100017
  secondaryRange,
99998
100018
  secondaryIdx,
99999
100019
  sourceIndices2,
100000
- horizontalAxis.xPositions
100020
+ horizontalAxis.xPositions,
100021
+ isStacked ? isPercent ? "percentStacked" : "stacked" : "clustered"
100001
100022
  );
100002
100023
  } else if (kind === "area") {
100003
100024
  plot = buildAreas(
@@ -100006,7 +100027,8 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
100006
100027
  layout,
100007
100028
  primaryRange,
100008
100029
  sourceIndices2,
100009
- horizontalAxis.xPositions
100030
+ horizontalAxis.xPositions,
100031
+ isStacked ? isPercent ? "percentStacked" : "stacked" : "clustered"
100010
100032
  );
100011
100033
  } else if (kind === "scatter") {
100012
100034
  plot = buildScatter(chartData, layout, primaryRange);
@@ -102653,8 +102675,7 @@ function seriesColor2(series, index, colorPalette) {
102653
102675
  return series.color ?? series.marker?.spPr?.fillColor ?? paletteColor2(index, colorPalette);
102654
102676
  }
102655
102677
  function computeValueRange2(series) {
102656
- let dataMin = Number.POSITIVE_INFINITY;
102657
- let dataMax = Number.NEGATIVE_INFINITY;
102678
+ let dataMin = Number.POSITIVE_INFINITY, dataMax = Number.NEGATIVE_INFINITY;
102658
102679
  for (const item of series) {
102659
102680
  for (const value of item.values) {
102660
102681
  if (value < dataMin) {
@@ -102672,11 +102693,9 @@ function computeValueRange2(series) {
102672
102693
  return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
102673
102694
  }
102674
102695
  function computeStackedValueRange(series, catCount) {
102675
- let maxSum = 0;
102676
- let minSum = 0;
102696
+ let maxSum = 0, minSum = 0;
102677
102697
  for (let ci = 0; ci < catCount; ci++) {
102678
- let pos2 = 0;
102679
- let neg = 0;
102698
+ let pos2 = 0, neg = 0;
102680
102699
  for (const s of series) {
102681
102700
  const v = s.values[ci] ?? 0;
102682
102701
  if (v >= 0) {
@@ -102695,10 +102714,7 @@ function valueToY2(val2, range, topY, bottomY) {
102695
102714
  const usable = bottomY - topY;
102696
102715
  let ratio;
102697
102716
  if (range.logScale && range.logBase) {
102698
- const base = range.logBase;
102699
- const clampedVal = Math.max(val2, range.min);
102700
- const logVal = Math.log(clampedVal) / Math.log(base);
102701
- const logMin = Math.log(range.min) / Math.log(base);
102717
+ const base = range.logBase, clampedVal = Math.max(val2, range.min), logVal = Math.log(clampedVal) / Math.log(base), logMin = Math.log(range.min) / Math.log(base);
102702
102718
  ratio = (logVal - logMin) / range.span;
102703
102719
  } else {
102704
102720
  ratio = (val2 - range.min) / range.span;
@@ -102721,23 +102737,20 @@ function formatAxisValue2(val2, formatCode) {
102721
102737
  }
102722
102738
  return val2.toFixed(1);
102723
102739
  }
102740
+ function buildMarkTooltip(seriesName, categoryLabel, value, numberFormat) {
102741
+ const label = [seriesName, categoryLabel].filter((part) => Boolean(part && part.length > 0)).join(", "), formatted = formatAxisValue2(value, numberFormat);
102742
+ return label.length > 0 ? `${label}: ${formatted}` : formatted;
102743
+ }
102724
102744
  function categoryAxisBand(chartData) {
102725
102745
  const axis = chartData.axes?.find(
102726
102746
  (candidate) => candidate.axisType === "catAx" || candidate.axisType === "dateAx"
102727
- );
102728
- const fontPx = axis?.fontSize !== void 0 ? chartFontPx(axis.fontSize) : DEFAULT_CHART_TEXT_PX;
102729
- const offset = 4 + 8 * ((axis?.labelOffset ?? 100) / 100);
102747
+ ), fontPx = axis?.fontSize !== void 0 ? chartFontPx(axis.fontSize) : DEFAULT_CHART_TEXT_PX, offset = 4 + 8 * ((axis?.labelOffset ?? 100) / 100);
102730
102748
  return Math.max(24, offset + fontPx * 1.2);
102731
102749
  }
102732
102750
  function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, options) {
102733
- const svgWidth = Math.max(1, elementWidth);
102734
- const svgHeight = Math.max(1, elementHeight);
102735
- let plotLeft = hasAxes ? 48 : 8;
102736
- let plotTop = 8;
102737
- let plotRight = svgWidth - 8;
102738
- let plotBottom = svgHeight - (hasAxes ? categoryAxisBand(chartData) : 8);
102739
- const style = chartData.style;
102740
- const legendPos = style?.legendPosition ?? "b";
102751
+ const svgWidth = Math.max(1, elementWidth), svgHeight = Math.max(1, elementHeight);
102752
+ let plotLeft = hasAxes ? 48 : 8, plotTop = 8, plotRight = svgWidth - 8, plotBottom = svgHeight - (hasAxes ? categoryAxisBand(chartData) : 8);
102753
+ const style = chartData.style, legendPos = style?.legendPosition ?? "b";
102741
102754
  if (style?.hasTitle) {
102742
102755
  plotTop += 20;
102743
102756
  }
@@ -102762,8 +102775,7 @@ function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, opti
102762
102775
  const rowCount = options.dataTableRowCount ?? 1;
102763
102776
  plotBottom -= 14 + rowCount * 14;
102764
102777
  }
102765
- const plotWidth = Math.max(plotRight - plotLeft, 1);
102766
- const plotHeight = Math.max(plotBottom - plotTop, 1);
102778
+ const plotWidth = Math.max(plotRight - plotLeft, 1), plotHeight = Math.max(plotBottom - plotTop, 1);
102767
102779
  return {
102768
102780
  svgWidth,
102769
102781
  svgHeight,
@@ -102793,8 +102805,7 @@ function axisTickValues(range) {
102793
102805
  );
102794
102806
  }
102795
102807
  function buildGridlinesAndLabels(range, layout) {
102796
- const gridlines = [];
102797
- const axisLabels = [];
102808
+ const gridlines = [], axisLabels = [];
102798
102809
  for (const val2 of axisTickValues(range)) {
102799
102810
  const y = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
102800
102811
  gridlines.push({
@@ -102854,9 +102865,7 @@ function buildLegend(series, colorPalette, svgWidth, legendPos, svgHeight, plotT
102854
102865
  color: seriesColor2(s, i, colorPalette),
102855
102866
  label: s.name
102856
102867
  }));
102857
- let legendX = svgWidth / 2;
102858
- let legendY = svgHeight - 8;
102859
- let legendAnchor = "middle";
102868
+ let legendX = svgWidth / 2, legendY = svgHeight - 8, legendAnchor = "middle";
102860
102869
  if (legendPos === "r") {
102861
102870
  legendX = svgWidth - 75;
102862
102871
  legendY = plotTop;
@@ -102871,19 +102880,10 @@ function buildLegend(series, colorPalette, svgWidth, legendPos, svgHeight, plotT
102871
102880
  return { legend, legendX, legendY, legendAnchor };
102872
102881
  }
102873
102882
  function computeBarRects(series, catCount, layout, range, colorPalette) {
102874
- const rects = [];
102875
- const seriesCount = Math.max(series.length, 1);
102876
- const barGroupWidth = layout.plotWidth / Math.max(catCount, 1);
102877
- const singleBarWidth = barGroupWidth * 0.7 / seriesCount;
102878
- const groupOffset = (barGroupWidth - singleBarWidth * seriesCount) / 2;
102883
+ const rects = [], seriesCount = Math.max(series.length, 1), barGroupWidth = layout.plotWidth / Math.max(catCount, 1), singleBarWidth = barGroupWidth * 0.7 / seriesCount, groupOffset = (barGroupWidth - singleBarWidth * seriesCount) / 2;
102879
102884
  for (let ci = 0; ci < catCount; ci++) {
102880
102885
  for (let si = 0; si < series.length; si++) {
102881
- const val2 = series[si].values[ci] ?? 0;
102882
- const x = layout.plotLeft + barGroupWidth * ci + groupOffset + singleBarWidth * si;
102883
- const zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
102884
- const valY = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
102885
- const y = Math.min(zeroY, valY);
102886
- const h = Math.max(Math.abs(zeroY - valY), 1);
102886
+ const val2 = series[si].values[ci] ?? 0, x = layout.plotLeft + barGroupWidth * ci + groupOffset + singleBarWidth * si, zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom), valY = valueToY2(val2, range, layout.plotTop, layout.plotBottom), y = Math.min(zeroY, valY), h = Math.max(Math.abs(zeroY - valY), 1);
102887
102887
  rects.push({
102888
102888
  x,
102889
102889
  y,
@@ -102896,20 +102896,15 @@ function computeBarRects(series, catCount, layout, range, colorPalette) {
102896
102896
  return rects;
102897
102897
  }
102898
102898
  function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
102899
- const rects = [];
102900
- const barW = layout.plotWidth / Math.max(catCount, 1) * 0.7;
102901
- const barOffset = (layout.plotWidth / Math.max(catCount, 1) - barW) / 2;
102902
- const zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
102899
+ const rects = [], barW = layout.plotWidth / Math.max(catCount, 1) * 0.7, barOffset = (layout.plotWidth / Math.max(catCount, 1) - barW) / 2, zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
102903
102900
  for (let ci = 0; ci < catCount; ci++) {
102904
- let posTop = zeroY;
102905
- let negBottom = zeroY;
102901
+ let posTop = zeroY, negBottom = zeroY;
102906
102902
  for (let si = 0; si < series.length; si++) {
102907
102903
  const val2 = series[si].values[ci] ?? 0;
102908
102904
  if (val2 === 0) {
102909
102905
  continue;
102910
102906
  }
102911
- const x = layout.plotLeft + layout.plotWidth / Math.max(catCount, 1) * ci + barOffset;
102912
- const h = Math.max(
102907
+ const x = layout.plotLeft + layout.plotWidth / Math.max(catCount, 1) * ci + barOffset, h = Math.max(
102913
102908
  Math.abs(
102914
102909
  valueToY2(val2, range, layout.plotTop, layout.plotBottom) - valueToY2(0, range, layout.plotTop, layout.plotBottom)
102915
102910
  ),
@@ -102947,9 +102942,7 @@ function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
102947
102942
  function computeLinePoints(values, catCount, layout, range) {
102948
102943
  const n = Math.max(catCount, 2);
102949
102944
  return values.map((val2, i) => {
102950
- const nx = n > 1 ? i / (n - 1) : 0;
102951
- const x = layout.plotLeft + layout.plotWidth * nx;
102952
- const y = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
102945
+ const nx = n > 1 ? i / (n - 1) : 0, x = layout.plotLeft + layout.plotWidth * nx, y = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
102953
102946
  return { x, y };
102954
102947
  });
102955
102948
  }
@@ -102957,49 +102950,30 @@ function linePointsToSvgString(points3) {
102957
102950
  return points3.map((p) => `${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(" ");
102958
102951
  }
102959
102952
  function computePieSlicePath(cx, cy, outerR, innerR, startAngle, endAngle) {
102960
- const largeArc = endAngle - startAngle > Math.PI ? 1 : 0;
102961
- const x1 = cx + outerR * Math.cos(startAngle);
102962
- const y1 = cy + outerR * Math.sin(startAngle);
102963
- const x2 = cx + outerR * Math.cos(endAngle);
102964
- const y2 = cy + outerR * Math.sin(endAngle);
102953
+ const largeArc = endAngle - startAngle > Math.PI ? 1 : 0, x1 = cx + outerR * Math.cos(startAngle), y1 = cy + outerR * Math.sin(startAngle), x2 = cx + outerR * Math.cos(endAngle), y2 = cy + outerR * Math.sin(endAngle);
102965
102954
  let d;
102966
102955
  if (innerR > 0) {
102967
- const ix1 = cx + innerR * Math.cos(startAngle);
102968
- const iy1 = cy + innerR * Math.sin(startAngle);
102969
- const ix2 = cx + innerR * Math.cos(endAngle);
102970
- const iy2 = cy + innerR * Math.sin(endAngle);
102956
+ const ix1 = cx + innerR * Math.cos(startAngle), iy1 = cy + innerR * Math.sin(startAngle), ix2 = cx + innerR * Math.cos(endAngle), iy2 = cy + innerR * Math.sin(endAngle);
102971
102957
  d = `M${x1},${y1} A${outerR},${outerR} 0 ${largeArc} 1 ${x2},${y2} L${ix2},${iy2} A${innerR},${innerR} 0 ${largeArc} 0 ${ix1},${iy1} Z`;
102972
102958
  } else {
102973
102959
  d = `M${cx},${cy} L${x1},${y1} A${outerR},${outerR} 0 ${largeArc} 1 ${x2},${y2} Z`;
102974
102960
  }
102975
- const midAngle = (startAngle + endAngle) / 2;
102976
- const labelR = outerR * 0.7;
102977
- const labelX = cx + labelR * Math.cos(midAngle);
102978
- const labelY = cy + labelR * Math.sin(midAngle);
102961
+ const midAngle = (startAngle + endAngle) / 2, labelR = outerR * 0.7, labelX = cx + labelR * Math.cos(midAngle), labelY = cy + labelR * Math.sin(midAngle);
102979
102962
  return { d, midAngle, labelX, labelY };
102980
102963
  }
102981
102964
  function computePieLayout(elementWidth, elementHeight, chartData, isDoughnut) {
102982
- const size = Math.min(Math.max(elementWidth, 1), Math.max(elementHeight, 1));
102983
- const titleOffset = chartData.style?.hasTitle ? 20 : 0;
102984
- const legendOffset = chartData.style?.hasLegend ? 20 : 0;
102985
- const cx = size / 2;
102986
- const cy = titleOffset + (size - titleOffset - legendOffset) / 2;
102987
- const outerR = Math.max((size - titleOffset - legendOffset) * 0.42, 0);
102988
- const holeRatio = isDoughnut && chartData.doughnutHoleSize !== void 0 ? Math.min(Math.max(chartData.doughnutHoleSize, 10), 90) / 100 : 0.55;
102989
- const innerR = isDoughnut ? outerR * holeRatio : 0;
102965
+ const size = Math.min(Math.max(elementWidth, 1), Math.max(elementHeight, 1)), titleOffset = chartData.style?.hasTitle ? 20 : 0, legendOffset = chartData.style?.hasLegend ? 20 : 0, cx = size / 2, cy = titleOffset + (size - titleOffset - legendOffset) / 2, outerR = Math.max((size - titleOffset - legendOffset) * 0.42, 0), holeRatio = isDoughnut && chartData.doughnutHoleSize !== void 0 ? Math.min(Math.max(chartData.doughnutHoleSize, 10), 90) / 100 : 0.55, innerR = isDoughnut ? outerR * holeRatio : 0;
102990
102966
  return { cx, cy, outerR, innerR, size };
102991
102967
  }
102992
102968
  function computePieSlices(values, cx, cy, outerR, innerR, options) {
102993
102969
  const total = values.reduce((s, v) => s + Math.abs(v), 0) || 1;
102994
102970
  let cumAngle = options?.startAngle ?? -Math.PI / 2;
102995
102971
  return values.map((val2, i) => {
102996
- const sliceAngle = Math.abs(val2) / total * Math.PI * 2;
102997
- const startAngle = cumAngle;
102972
+ const sliceAngle = Math.abs(val2) / total * Math.PI * 2, startAngle = cumAngle;
102998
102973
  cumAngle += sliceAngle;
102999
102974
  const explosion = options?.explosions?.[i] ?? 0;
103000
102975
  if (explosion > 0) {
103001
- const mid = (startAngle + cumAngle) / 2;
103002
- const offset = outerR * (explosion / 100);
102976
+ const mid = (startAngle + cumAngle) / 2, offset = outerR * (explosion / 100);
103003
102977
  return computePieSlicePath(
103004
102978
  cx + Math.cos(mid) * offset,
103005
102979
  cy + Math.sin(mid) * offset,
@@ -103028,9 +103002,7 @@ function computeScatterXDomain(seriesXValues2) {
103028
103002
  return { min, span: Math.max(Math.max(...finite2) - min, 1) };
103029
103003
  }
103030
103004
  function computeScatterDots(values, maxXIndex, layout, range, xValues, xDomain) {
103031
- const finiteX = xValues?.slice(0, values.length).filter(Number.isFinite);
103032
- const minX = xDomain ? xDomain.min : finiteX?.length ? Math.min(...finiteX) : 0;
103033
- const spanX = xDomain ? xDomain.span : finiteX?.length ? Math.max(Math.max(...finiteX) - minX, 1) : maxXIndex;
103005
+ const finiteX = xValues?.slice(0, values.length).filter(Number.isFinite), minX = xDomain ? xDomain.min : finiteX?.length ? Math.min(...finiteX) : 0, spanX = xDomain ? xDomain.span : finiteX?.length ? Math.max(Math.max(...finiteX) - minX, 1) : maxXIndex;
103034
103006
  return values.map((val2, i) => ({
103035
103007
  cx: layout.plotLeft + (spanX > 0 ? (Number.isFinite(xValues?.[i]) ? xValues[i] - minX : i) / spanX : 0) * layout.plotWidth,
103036
103008
  cy: valueToY2(val2, range, layout.plotTop, layout.plotBottom)
@@ -103050,8 +103022,7 @@ function radarAngle(index, catCount) {
103050
103022
  function computeRadarPoints(values, maxVal, radius, cx, cy, catCount) {
103051
103023
  const denom = maxVal > 0 ? maxVal : 1;
103052
103024
  return values.slice(0, Math.max(catCount, 1)).map((val2, i) => {
103053
- const angle = radarAngle(i, catCount);
103054
- const r = Math.abs(val2) / denom * radius;
103025
+ const angle = radarAngle(i, catCount), r = Math.abs(val2) / denom * radius;
103055
103026
  return { x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) };
103056
103027
  });
103057
103028
  }
@@ -103118,18 +103089,15 @@ function buildChartViewModel(element) {
103118
103089
  if (element.type !== "chart") {
103119
103090
  return buildFallbackViewModel(element.width, element.height, "Chart");
103120
103091
  }
103121
- const chartEl = element;
103122
- const chartData = chartEl.chartData;
103092
+ const chartEl = element, chartData = chartEl.chartData;
103123
103093
  if (!chartData || chartData.series.length === 0) {
103124
103094
  return buildFallbackViewModel(element.width, element.height, chartData?.title ?? "Chart");
103125
103095
  }
103126
- const chartType = chartData.chartType ?? "bar";
103127
- const kind = resolveChartKind(chartType);
103096
+ const chartType = chartData.chartType ?? "bar", kind = resolveChartKind(chartType);
103128
103097
  if (kind === "unsupported") {
103129
103098
  return buildFallbackViewModel(element.width, element.height, chartData.title ?? chartType);
103130
103099
  }
103131
- const longestLen = chartData.series.reduce((m, s) => Math.max(m, s.values.length), 0);
103132
- const categoryLabels = chartData.categories.length > 0 ? chartData.categories : Array.from({ length: longestLen }, (_, i) => String(i + 1));
103100
+ const longestLen = chartData.series.reduce((m, s) => Math.max(m, s.values.length), 0), categoryLabels = chartData.categories.length > 0 ? chartData.categories : Array.from({ length: longestLen }, (_, i) => String(i + 1));
103133
103101
  if (chartType === "ofPie") {
103134
103102
  return withChartAreaFill(
103135
103103
  withUserShapeOverlay(buildOfPieViewModel(element, chartData, categoryLabels), chartData),
@@ -103206,8 +103174,7 @@ function buildFlatViewModel(element, chartData, categoryLabels, kind) {
103206
103174
  return buildCartesianViewModel(element, chartData, categoryLabels, kind);
103207
103175
  }
103208
103176
  function buildFallbackViewModel(width, height, label) {
103209
- const svgWidth = Math.max(width, 1);
103210
- const svgHeight = Math.max(height, 1);
103177
+ const svgWidth = Math.max(width, 1), svgHeight = Math.max(height, 1);
103211
103178
  return {
103212
103179
  svgWidth,
103213
103180
  svgHeight,
@@ -103255,15 +103222,7 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
103255
103222
  element.height,
103256
103223
  chartData,
103257
103224
  isDoughnut
103258
- );
103259
- const svgWidth = Math.max(size, 100);
103260
- const svgHeight = Math.max(size, 60);
103261
- const pieSeries = chartData.series[0];
103262
- const values = pieSeries?.values ?? [];
103263
- const startAngle = -Math.PI / 2 + (chartData.firstSliceAngle ?? 0) * Math.PI / 180;
103264
- const explosions = pieSeries ? values.map((_v, i) => resolveDataPointExplosion(pieSeries, i)) : void 0;
103265
- const slices = computePieSlices(values, cx, cy, outerR, innerR, { startAngle, explosions });
103266
- const primitives = slices.map(
103225
+ ), svgWidth = Math.max(size, 100), svgHeight = Math.max(size, 60), pieSeries = chartData.series[0], values = pieSeries?.values ?? [], startAngle = -Math.PI / 2 + (chartData.firstSliceAngle ?? 0) * Math.PI / 180, explosions = pieSeries ? values.map((_v, i) => resolveDataPointExplosion(pieSeries, i)) : void 0, slices = computePieSlices(values, cx, cy, outerR, innerR, { startAngle, explosions }), primitives = slices.map(
103267
103226
  ({ d }, i) => ({
103268
103227
  kind: "path",
103269
103228
  d,
@@ -103272,13 +103231,17 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
103272
103231
  fill: pieSeries ? resolveVaryColorFill(pieSeries, i, paletteColor2(i, chartData.colorPalette)) : paletteColor2(i, chartData.colorPalette),
103273
103232
  stroke: "#ffffff",
103274
103233
  strokeWidth: 1.5,
103275
- part: { role: "dataPoint", seriesIndex: 0, pointIndex: i }
103234
+ part: { role: "dataPoint", seriesIndex: 0, pointIndex: i },
103235
+ title: buildMarkTooltip(
103236
+ pieSeries?.name,
103237
+ categoryLabels[i],
103238
+ values[i] ?? 0,
103239
+ pieSeries?.numberFormat
103240
+ )
103276
103241
  })
103277
- );
103278
- const dataLabels = [];
103242
+ ), dataLabels = [];
103279
103243
  if (chartData.style?.hasDataLabels) {
103280
- const percentBase = values.reduce((total, entry2) => total + Math.abs(entry2), 0);
103281
- const labelResult = buildPieDataLabels({
103244
+ const percentBase = values.reduce((total, entry2) => total + Math.abs(entry2), 0), labelResult = buildPieDataLabels({
103282
103245
  slices,
103283
103246
  values,
103284
103247
  cx,
@@ -103298,12 +103261,10 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
103298
103261
  dataLabels.push(...labelResult.labels);
103299
103262
  primitives.push(...labelResult.leaderLines);
103300
103263
  }
103301
- const legendPos = chartData.style?.legendPosition ?? "b";
103302
- const legend = categoryLabels.map((label, i) => ({
103264
+ const legendPos = chartData.style?.legendPosition ?? "b", legend = categoryLabels.map((label, i) => ({
103303
103265
  color: pieSeries ? resolveVaryColorFill(pieSeries, i, paletteColor2(i, chartData.colorPalette)) : paletteColor2(i, chartData.colorPalette),
103304
103266
  label
103305
- }));
103306
- const legendX = svgWidth / 2;
103267
+ })), legendX = svgWidth / 2;
103307
103268
  let legendY = svgHeight - 8;
103308
103269
  const legendAnchor = "middle";
103309
103270
  if (legendPos === "t") {
@@ -103333,14 +103294,7 @@ var RADAR_RING_COLOR = "#cbd5e1";
103333
103294
  var RADAR_SPOKE_COLOR = "#94a3b8";
103334
103295
  var RADAR_LABEL_COLOR = "#64748b";
103335
103296
  function buildRadarViewModel(element, chartData, categoryLabels) {
103336
- const layout = computePlotLayout(element.width, element.height, chartData, false);
103337
- const cx = layout.plotLeft + layout.plotWidth / 2;
103338
- const cy = layout.plotTop + layout.plotHeight / 2;
103339
- const radius = Math.max(Math.min(layout.plotWidth, layout.plotHeight) / 2 - 4, 1);
103340
- const catCount = Math.max(categoryLabels.length, 1);
103341
- const maxVal = Math.max(1, ...chartData.series.flatMap((s) => s.values.map((v) => Math.abs(v))));
103342
- const primitives = [];
103343
- const perimeterLabels = [];
103297
+ const layout = computePlotLayout(element.width, element.height, chartData, false), cx = layout.plotLeft + layout.plotWidth / 2, cy = layout.plotTop + layout.plotHeight / 2, radius = Math.max(Math.min(layout.plotWidth, layout.plotHeight) / 2 - 4, 1), catCount = Math.max(categoryLabels.length, 1), maxVal = Math.max(1, ...chartData.series.flatMap((s) => s.values.map((v) => Math.abs(v)))), primitives = [], perimeterLabels = [];
103344
103298
  for (let r = 1; r <= RADAR_RINGS; r++) {
103345
103299
  const rr = radius * r / RADAR_RINGS;
103346
103300
  primitives.push({
@@ -103377,8 +103331,7 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103377
103331
  }
103378
103332
  const dataLabels = [];
103379
103333
  chartData.series.forEach((series, si) => {
103380
- const c = seriesColor2(series, si, chartData.colorPalette);
103381
- const pts = computeRadarPoints(series.values, maxVal, radius, cx, cy, catCount);
103334
+ const c = seriesColor2(series, si, chartData.colorPalette), pts = computeRadarPoints(series.values, maxVal, radius, cx, cy, catCount);
103382
103335
  if (pts.length === 0) {
103383
103336
  return;
103384
103337
  }
@@ -103390,7 +103343,8 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103390
103343
  opacity: 0.2,
103391
103344
  stroke: c,
103392
103345
  strokeWidth: 1.5,
103393
- part: { role: "series", seriesIndex: si }
103346
+ part: { role: "series", seriesIndex: si },
103347
+ title: series.name.length > 0 ? series.name : void 0
103394
103348
  });
103395
103349
  pts.forEach((p, vi) => {
103396
103350
  primitives.push({
@@ -103399,7 +103353,13 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103399
103353
  cy: p.y,
103400
103354
  r: 3,
103401
103355
  fill: c,
103402
- part: { role: "dataPoint", seriesIndex: si, pointIndex: vi }
103356
+ part: { role: "dataPoint", seriesIndex: si, pointIndex: vi },
103357
+ title: buildMarkTooltip(
103358
+ series.name,
103359
+ categoryLabels[vi],
103360
+ series.values[vi] ?? 0,
103361
+ series.numberFormat
103362
+ )
103403
103363
  });
103404
103364
  });
103405
103365
  if (chartData.style?.hasDataLabels) {
@@ -103420,16 +103380,14 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103420
103380
  });
103421
103381
  }
103422
103382
  });
103423
- const legendPos = chartData.style?.legendPosition ?? "b";
103424
- const { legend, legendX, legendY, legendAnchor } = buildLegend(
103383
+ const legendPos = chartData.style?.legendPosition ?? "b", { legend, legendX, legendY, legendAnchor } = buildLegend(
103425
103384
  chartData.series,
103426
103385
  chartData.colorPalette,
103427
103386
  layout.svgWidth,
103428
103387
  legendPos,
103429
103388
  layout.svgHeight,
103430
103389
  layout.plotTop
103431
- );
103432
- const title = chartData.style?.hasTitle && chartData.title ? chartData.title : void 0;
103390
+ ), title = chartData.style?.hasTitle && chartData.title ? chartData.title : void 0;
103433
103391
  return {
103434
103392
  svgWidth: layout.svgWidth,
103435
103393
  svgHeight: layout.svgHeight,
@@ -103988,6 +103946,31 @@ var DIRECTIONAL_PRESETS = /* @__PURE__ */ new Set([
103988
103946
  "floatIn",
103989
103947
  "peekIn"
103990
103948
  ]);
103949
+ function reorderAnimationTo(animations, source, targetIndex) {
103950
+ const sorted = [...animations].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
103951
+ const sourceIndex = typeof source === "number" ? source : sorted.findIndex((a) => a.elementId === source.elementId);
103952
+ if (sourceIndex < 0 || sourceIndex >= sorted.length || targetIndex < 0 || targetIndex >= sorted.length || sourceIndex === targetIndex) {
103953
+ return reindexOrder(sorted);
103954
+ }
103955
+ const [moved] = sorted.splice(sourceIndex, 1);
103956
+ sorted.splice(targetIndex, 0, moved);
103957
+ return reindexOrder(sorted);
103958
+ }
103959
+ function buildAnimationTimelineBars(animations) {
103960
+ const sorted = [...animations].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
103961
+ const total = Math.max(
103962
+ 1,
103963
+ ...sorted.map((animation) => (animation.delayMs ?? 0) + (animation.durationMs ?? 500))
103964
+ );
103965
+ return sorted.map((animation) => ({
103966
+ elementId: animation.elementId,
103967
+ leftPercent: (animation.delayMs ?? 0) / total * 100,
103968
+ widthPercent: (animation.durationMs ?? 500) / total * 100
103969
+ }));
103970
+ }
103971
+ function reindexOrder(anims) {
103972
+ return anims.map((a, i) => ({ ...a, order: i }));
103973
+ }
103991
103974
  function animationPresetLabelKey(preset) {
103992
103975
  return `pptx.animation.preset.${preset}`;
103993
103976
  }
@@ -108858,6 +108841,23 @@ var TABLE_STYLE_PRESETS = [
108858
108841
  borderColor: "#548235"
108859
108842
  }
108860
108843
  ];
108844
+ function applyTableStylePreset(td, preset) {
108845
+ return td.rows.map((row, ri) => ({
108846
+ ...row,
108847
+ cells: row.cells.map((cell) => {
108848
+ const isHeader = ri === 0 && Boolean(td.firstRowHeader);
108849
+ const isBand = Boolean(td.bandedRows) && (ri - (td.firstRowHeader ? 1 : 0)) % 2 === 0;
108850
+ const style = {
108851
+ ...cell.style,
108852
+ backgroundColor: isHeader ? preset.headerBg : isBand ? preset.bandBg : void 0,
108853
+ color: isHeader ? preset.headerFg : cell.style?.color,
108854
+ bold: isHeader ? true : cell.style?.bold,
108855
+ borderColor: preset.borderColor
108856
+ };
108857
+ return { ...cell, style };
108858
+ })
108859
+ }));
108860
+ }
108861
108861
  var SEL = "bg-muted border border-border rounded px-2 py-1 text-[11px] w-full";
108862
108862
  var NUM = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full text-[11px]";
108863
108863
  var LBL = "text-muted-foreground text-[11px]";
@@ -108876,6 +108876,7 @@ var PATTERN_OPTIONS = OOXML_PATTERN_PRESETS.slice(0, 20);
108876
108876
  var MIN_COLUMN_PROPORTION = 0.03;
108877
108877
  var MIN_ROW_HEIGHT = 16;
108878
108878
  var DEFAULT_ROW_HEIGHT = 32;
108879
+ var MIN_COLUMN_WIDTH_FRACTION = 0.05;
108879
108880
  function computeColumnBoundaries(columnWidths) {
108880
108881
  const result = [];
108881
108882
  let cumulative = 0;
@@ -108904,6 +108905,39 @@ function computeResizedColumnWidths(initialWidths, index, deltaProportion) {
108904
108905
  function computeResizedRowHeight(initialRowHeight, deltaY) {
108905
108906
  return Math.round(Math.max(MIN_ROW_HEIGHT, initialRowHeight + deltaY));
108906
108907
  }
108908
+ function redistributeColumnWidth(widths, index, newFraction) {
108909
+ const oldFraction = widths[index];
108910
+ if (oldFraction === void 0) {
108911
+ return widths;
108912
+ }
108913
+ const diff = newFraction - oldFraction;
108914
+ const next = [...widths];
108915
+ next[index] = newFraction;
108916
+ const othersTotal = 1 - oldFraction;
108917
+ if (othersTotal > 0) {
108918
+ for (let j = 0; j < next.length; j++) {
108919
+ if (j !== index) {
108920
+ next[j] = Math.max(MIN_COLUMN_WIDTH_FRACTION, widths[j] - diff * (widths[j] / othersTotal));
108921
+ }
108922
+ }
108923
+ }
108924
+ const sum = next.reduce((a, b) => a + b, 0);
108925
+ return sum > 0 ? next.map((w) => w / sum) : next;
108926
+ }
108927
+ function evenColumnWidths(count) {
108928
+ if (count <= 0) {
108929
+ return [];
108930
+ }
108931
+ return Array.from({ length: count }, () => 1 / count);
108932
+ }
108933
+ function evenRowHeights(rows) {
108934
+ const count = rows.length;
108935
+ if (count === 0) {
108936
+ return rows;
108937
+ }
108938
+ const avg = Math.round(rows.reduce((s, r) => s + (r.height ?? DEFAULT_ROW_HEIGHT), 0) / count);
108939
+ return rows.map((r) => ({ ...r, height: avg }));
108940
+ }
108907
108941
  function findSmartArtNodeText(data, nodeId) {
108908
108942
  return data.nodes.find((n) => n.id === nodeId)?.text;
108909
108943
  }
@@ -111828,6 +111862,8 @@ var translationsEn = {
111828
111862
  "pptx.ribbon.customColour": "Custom colour...",
111829
111863
  "pptx.ribbon.textHighlightColour": "Text highlight colour",
111830
111864
  "pptx.ribbon.highlightColourValue": "Highlight colour {{color}}",
111865
+ "pptx.ribbon.fillColourValue": "Fill colour {{color}}",
111866
+ "pptx.ribbon.outlineColourValue": "Outline colour {{color}}",
111831
111867
  "pptx.ribbon.bulletList": "Bullet list",
111832
111868
  "pptx.ribbon.justify": "Justify",
111833
111869
  "pptx.toolbar.findAndReplace": "Find and replace",
@@ -124835,6 +124871,102 @@ function buildSmartArtA11y(data) {
124835
124871
  nodes
124836
124872
  };
124837
124873
  }
124874
+ var LAYOUT_BOUNDS = {
124875
+ // A Venn diagram is typically drawn with 2-3 overlapping sets; beyond a
124876
+ // handful of circles it becomes unreadable.
124877
+ venn: { min: 2, max: 3 },
124878
+ // A 2x2 matrix has exactly four quadrants.
124879
+ matrix: { min: 4, max: 4 },
124880
+ // Pyramids and funnels need at least two tiers to convey a hierarchy.
124881
+ pyramid: { min: 2, max: 5 },
124882
+ funnel: { min: 2, max: 5 },
124883
+ // A target is a small set of concentric rings.
124884
+ target: { min: 2, max: 5 },
124885
+ // Gears mesh in small clusters.
124886
+ gear: { min: 2, max: 3 },
124887
+ // Cycles need at least three steps to read as a loop.
124888
+ cycle: { min: 3 }
124889
+ // Relationship / process / list / hierarchy / timeline are flexible but
124890
+ // still need at least one node to exist.
124891
+ };
124892
+ var DEFAULT_BOUNDS = { min: 1 };
124893
+ function getSmartArtNodeBounds(layout) {
124894
+ if (!layout) {
124895
+ return DEFAULT_BOUNDS;
124896
+ }
124897
+ return LAYOUT_BOUNDS[layout] ?? DEFAULT_BOUNDS;
124898
+ }
124899
+ function canAddTopLevelNode(layout, topLevelCount) {
124900
+ const { max } = getSmartArtNodeBounds(layout);
124901
+ return max === void 0 || topLevelCount < max;
124902
+ }
124903
+ function canRemoveTopLevelNode(layout, topLevelCount) {
124904
+ const { min } = getSmartArtNodeBounds(layout);
124905
+ return topLevelCount > min;
124906
+ }
124907
+ function describeSmartArtBounds(layout) {
124908
+ const { min, max } = getSmartArtNodeBounds(layout);
124909
+ if (min <= 1 && max === void 0) {
124910
+ return void 0;
124911
+ }
124912
+ if (max === void 0) {
124913
+ return `Works best with at least ${min} items.`;
124914
+ }
124915
+ if (min === max) {
124916
+ return `This layout uses exactly ${max} items.`;
124917
+ }
124918
+ return `Works best with ${min} to ${max} items.`;
124919
+ }
124920
+ function addSiblingAfter(data, nodeId) {
124921
+ const next = addSmartArtNode(data, "", nodeId);
124922
+ if (next === data) {
124923
+ return void 0;
124924
+ }
124925
+ const idx = next.nodes.findIndex((n) => n.id === nodeId), inserted = idx >= 0 ? next.nodes[idx + 1] : void 0;
124926
+ return { data: next, focusNodeId: inserted?.id };
124927
+ }
124928
+ function removeEmptyNode(data, nodeId) {
124929
+ if (data.nodes.length <= 1) {
124930
+ return void 0;
124931
+ }
124932
+ const removedIndex = data.nodes.findIndex((n) => n.id === nodeId), next = removeSmartArtNode(data, nodeId);
124933
+ if (next === data) {
124934
+ return void 0;
124935
+ }
124936
+ const focusNode = next.nodes[Math.max(0, removedIndex - 1)];
124937
+ return { data: next, focusNodeId: focusNode?.id };
124938
+ }
124939
+ function demote(data, nodeId) {
124940
+ const next = demoteSmartArtNode(data, nodeId);
124941
+ return next === data ? void 0 : next;
124942
+ }
124943
+ function promote(data, nodeId) {
124944
+ const next = promoteSmartArtNode(data, nodeId);
124945
+ return next === data ? void 0 : next;
124946
+ }
124947
+ function reorder2(data, nodeId, direction) {
124948
+ const next = reorderSmartArtNode(data, nodeId, direction);
124949
+ return next === data ? void 0 : next;
124950
+ }
124951
+ function siblingIndex(data, nodeId) {
124952
+ const node = data.nodes.find((n) => n.id === nodeId);
124953
+ if (!node) {
124954
+ return -1;
124955
+ }
124956
+ const siblings = data.nodes.filter((n) => n.parentId === node.parentId);
124957
+ return siblings.findIndex((n) => n.id === nodeId);
124958
+ }
124959
+ function siblingCount(data, nodeId) {
124960
+ const node = data.nodes.find((n) => n.id === nodeId);
124961
+ if (!node) {
124962
+ return 0;
124963
+ }
124964
+ return data.nodes.filter((n) => n.parentId === node.parentId).length;
124965
+ }
124966
+ var TREE_CONNECTION_TYPES = /* @__PURE__ */ new Set(["parOf", "presParOf", void 0]);
124967
+ function classifyExtraConnections(data) {
124968
+ return (data.connections ?? []).filter((c) => !TREE_CONNECTION_TYPES.has(c.type));
124969
+ }
124838
124970
  var THREE_UNAVAILABLE = {
124839
124971
  ok: false,
124840
124972
  resize: () => {
@@ -129273,6 +129405,17 @@ function resolveInkWidth(widths, index, fallback = 3) {
129273
129405
  }
129274
129406
  return widths[index] > 0 ? widths[index] : fallback;
129275
129407
  }
129408
+ function buildBarActions(opts) {
129409
+ const { slideCount } = opts;
129410
+ const noSlides = slideCount === 0;
129411
+ return [
129412
+ { key: "slides", label: "Slides", disabled: noSlides },
129413
+ { key: "insert", label: "Insert", disabled: noSlides },
129414
+ { key: "inspector", label: "Format", disabled: noSlides },
129415
+ { key: "comments", label: "Comments", disabled: noSlides },
129416
+ { key: "notes", label: "Notes", disabled: noSlides }
129417
+ ];
129418
+ }
129276
129419
  var COMMENT_MENTION_ATTRIBUTE = "data-pptx-comment-mention";
129277
129420
  var COMMENT_MENTION_CLASS = "pptx-comment-mention";
129278
129421
  var usableMentions = (body, mentions) => (mentions ?? []).filter(
@@ -132749,8 +132892,7 @@ function sanitizeDownloadFilename(input) {
132749
132892
  return cleaned;
132750
132893
  }
132751
132894
  function downloadBlob(blob, filename) {
132752
- const url = URL.createObjectURL(blob);
132753
- const anchor = document.createElement("a");
132895
+ const url = URL.createObjectURL(blob), anchor = document.createElement("a");
132754
132896
  anchor.href = url;
132755
132897
  anchor.download = filename;
132756
132898
  document.body.appendChild(anchor);
@@ -132775,13 +132917,10 @@ function dataUrlToBlob(dataUrl) {
132775
132917
  if (!match?.groups) {
132776
132918
  return void 0;
132777
132919
  }
132778
- const mime = match.groups.mime || "application/octet-stream";
132779
- const isBase64 = Boolean(match.groups.base64);
132780
- const payload = match.groups.payload ?? "";
132920
+ const mime = match.groups.mime || "application/octet-stream", isBase64 = Boolean(match.groups.base64), payload = match.groups.payload ?? "";
132781
132921
  try {
132782
132922
  if (isBase64) {
132783
- const binary = atob(payload);
132784
- const bytes = new Uint8Array(binary.length);
132923
+ const binary = atob(payload), bytes = new Uint8Array(binary.length);
132785
132924
  for (let i = 0; i < binary.length; i++) {
132786
132925
  bytes[i] = binary.charCodeAt(i);
132787
132926
  }
@@ -132793,9 +132932,7 @@ function dataUrlToBlob(dataUrl) {
132793
132932
  }
132794
132933
  }
132795
132934
  function openUrlInNewTab(url) {
132796
- const blob = url.startsWith("data:") ? dataUrlToBlob(url) : void 0;
132797
- const target = blob ? URL.createObjectURL(blob) : url;
132798
- const opened = window.open(target, "_blank");
132935
+ const blob = url.startsWith("data:") ? dataUrlToBlob(url) : void 0, target = blob ? URL.createObjectURL(blob) : url, opened = window.open(target, "_blank");
132799
132936
  if (opened) {
132800
132937
  try {
132801
132938
  opened.opener = null;
@@ -134506,7 +134643,7 @@ exports.addChartCategory = addChartCategory;
134506
134643
  exports.addChartSeries = addChartSeries;
134507
134644
  exports.addQuickAccessCommand = addQuickAccessCommand;
134508
134645
  exports.addSection = addSection;
134509
- exports.addSmartArtNode = addSmartArtNode;
134646
+ exports.addSiblingAfter = addSiblingAfter;
134510
134647
  exports.addSmartArtNodeAsChild = addSmartArtNodeAsChild;
134511
134648
  exports.addTagToCollections = addTagToCollections;
134512
134649
  exports.alignElements = alignElements;
@@ -134532,6 +134669,7 @@ exports.applyRehearsalTimings = applyRehearsalTimings;
134532
134669
  exports.applyReroutedConnectors = applyReroutedConnectors;
134533
134670
  exports.applyResize = applyResize;
134534
134671
  exports.applyStyleToSelectedSegments = applyStyleToSelectedSegments;
134672
+ exports.applyTableStylePreset = applyTableStylePreset;
134535
134673
  exports.applyThemeOverrideToSlide = applyThemeOverrideToSlide;
134536
134674
  exports.applyThemeToData = applyThemeToData;
134537
134675
  exports.attachPresentationVisibilityPause = attachPresentationVisibilityPause;
@@ -134544,6 +134682,8 @@ exports.bringForward = bringForward;
134544
134682
  exports.bringToFront = bringToFront;
134545
134683
  exports.build3DExtrusionData = build3DExtrusionData;
134546
134684
  exports.buildActiveSessionUsers = buildActiveSessionUsers;
134685
+ exports.buildAnimationTimelineBars = buildAnimationTimelineBars;
134686
+ exports.buildBarActions = buildBarActions;
134547
134687
  exports.buildBroadcastViewerUrl = buildBroadcastViewerUrl;
134548
134688
  exports.buildCacheKey = buildCacheKey;
134549
134689
  exports.buildCalloutLeaderLineSvgPath = buildCalloutLeaderLineSvgPath;
@@ -134594,10 +134734,12 @@ exports.buildTextBuildSpec = buildTextBuildSpec;
134594
134734
  exports.buildThemeColorGrid = buildThemeColorGrid;
134595
134735
  exports.buildThemeColorMap = buildThemeColorMap;
134596
134736
  exports.buildUserFontFaceStyles = buildUserFontFaceStyles;
134737
+ exports.canAddTopLevelNode = canAddTopLevelNode;
134597
134738
  exports.canCommitActionType = canCommitActionType;
134598
134739
  exports.canGoNext = canGoNext;
134599
134740
  exports.canGoPrevious = canGoPrevious;
134600
134741
  exports.canInteractWithElement = canInteractWithElement;
134742
+ exports.canRemoveTopLevelNode = canRemoveTopLevelNode;
134601
134743
  exports.canvasToJpegData = canvasToJpegData;
134602
134744
  exports.cellRunStyle = cellRunStyle;
134603
134745
  exports.cellStyleToCss = cellStyleToCss;
@@ -134612,6 +134754,7 @@ exports.clampSorterZoom = clampSorterZoom;
134612
134754
  exports.clampTransitionNumber = clampTransitionNumber;
134613
134755
  exports.clampUnitInterval = clampUnitInterval2;
134614
134756
  exports.clampZoomScale = clampZoomScale;
134757
+ exports.classifyExtraConnections = classifyExtraConnections;
134615
134758
  exports.clearAllLocalViewerData = clearAllLocalViewerData;
134616
134759
  exports.clearAudienceContent = clearAudienceContent;
134617
134760
  exports.clearLocalAwareness = clearLocalAwareness;
@@ -134631,6 +134774,7 @@ exports.comparePresentation = comparePresentation;
134631
134774
  exports.compileEquationTemplateMathMl = compileEquationTemplateMathMl;
134632
134775
  exports.compileLatexEquation = compileLatexEquation;
134633
134776
  exports.computeAllNotesPages = computeAllNotesPages;
134777
+ exports.computeChartLegendLayout = computeChartLegendLayout;
134634
134778
  exports.computeColumnBoundaries = computeColumnBoundaries;
134635
134779
  exports.computeDrawingViewBox = computeDrawingViewBox;
134636
134780
  exports.computeEntranceAnimationDelay = computeEntranceAnimationDelay;
@@ -134678,9 +134822,10 @@ exports.deleteSection = deleteSection;
134678
134822
  exports.deleteTableColumn = deleteTableColumn;
134679
134823
  exports.deleteTableRow = deleteTableRow;
134680
134824
  exports.deleteTagFromCollections = deleteTagFromCollections;
134681
- exports.demoteSmartArtNode = demoteSmartArtNode;
134825
+ exports.demote = demote;
134682
134826
  exports.deriveSlideFieldContext = deriveSlideFieldContext;
134683
134827
  exports.describeFontEmbedding = describeFontEmbedding;
134828
+ exports.describeSmartArtBounds = describeSmartArtBounds;
134684
134829
  exports.detectOrientation = detectOrientation;
134685
134830
  exports.detectTouchDevice = detectTouchDevice;
134686
134831
  exports.discardAutosaveRecovery = discardAutosaveRecovery;
@@ -134698,6 +134843,8 @@ exports.ensureActionAffordanceStyles = ensureActionAffordanceStyles;
134698
134843
  exports.ensureChartInteractionStyles = ensureChartInteractionStyles;
134699
134844
  exports.erasePresentationInkAt = erasePresentationInkAt;
134700
134845
  exports.escapeHtml2 = escapeHtml22;
134846
+ exports.evenColumnWidths = evenColumnWidths;
134847
+ exports.evenRowHeights = evenRowHeights;
134701
134848
  exports.exportDeckJson = exportDeckJson;
134702
134849
  exports.extraQuickAccessCommands = extraQuickAccessCommands;
134703
134850
  exports.extractPathPoints = extractPathPoints;
@@ -134921,7 +135068,7 @@ exports.printPropertiesFrameSlides = printPropertiesFrameSlides;
134921
135068
  exports.printPropertiesSlidesPerPage = printPropertiesSlidesPerPage;
134922
135069
  exports.probeAutosaveRecovery = probeAutosaveRecovery;
134923
135070
  exports.projectDrawingShapes = projectDrawingShapes;
134924
- exports.promoteSmartArtNode = promoteSmartArtNode;
135071
+ exports.promote = promote;
134925
135072
  exports.publishLiveGeometry = publishLiveGeometry;
134926
135073
  exports.publishLiveInlineText = publishLiveInlineText;
134927
135074
  exports.quickStyleSwatchCss = quickStyleSwatchCss;
@@ -134938,6 +135085,7 @@ exports.rebuildTableStructureInRawXml = rebuildTableStructureInRawXml;
134938
135085
  exports.reconcileSlidesInYDoc = reconcileSlidesInYDoc;
134939
135086
  exports.recordProgressPercent = recordProgressPercent;
134940
135087
  exports.rectToCells = rectToCells;
135088
+ exports.redistributeColumnWidth = redistributeColumnWidth;
134941
135089
  exports.registerCollaborationTeardown = registerCollaborationTeardown;
134942
135090
  exports.registerCustomFont = registerCustomFont;
134943
135091
  exports.registerPersistentAudio = registerPersistentAudio;
@@ -134945,6 +135093,7 @@ exports.remapTextToSegments = remapTextToSegments;
134945
135093
  exports.rememberSessionDeck = rememberSessionDeck;
134946
135094
  exports.removeChartCategory = removeChartCategory;
134947
135095
  exports.removeChartSeries = removeChartSeries;
135096
+ exports.removeEmptyNode = removeEmptyNode;
134948
135097
  exports.removeLastTableElementColumn = removeLastTableElementColumn;
134949
135098
  exports.removeLastTableElementRow = removeLastTableElementRow;
134950
135099
  exports.removeQuickAccessCommand = removeQuickAccessCommand;
@@ -134952,7 +135101,8 @@ exports.removeSmartArtNode = removeSmartArtNode;
134952
135101
  exports.removeTableElementColumn = removeTableElementColumn;
134953
135102
  exports.removeTableElementRow = removeTableElementRow;
134954
135103
  exports.renameSection = renameSection;
134955
- exports.reorderSmartArtNode = reorderSmartArtNode;
135104
+ exports.reorder = reorder2;
135105
+ exports.reorderAnimationTo = reorderAnimationTo;
134956
135106
  exports.replaceMasterViewElements = replaceMasterViewElements;
134957
135107
  exports.rerouteConnectorsForMovedElements = rerouteConnectorsForMovedElements;
134958
135108
  exports.resetPresenterTimer = resetPresenterTimer;
@@ -135046,6 +135196,8 @@ exports.shouldRoomSlidesReplaceLoad = shouldRoomSlidesReplaceLoad;
135046
135196
  exports.shouldShowAutosaveRecoveryPrompt = shouldShowAutosaveRecoveryPrompt;
135047
135197
  exports.shouldUseSvgWarp = shouldUseSvgWarp;
135048
135198
  exports.shouldWriteAutosaveSnapshot = shouldWriteAutosaveSnapshot;
135199
+ exports.siblingCount = siblingCount;
135200
+ exports.siblingIndex = siblingIndex;
135049
135201
  exports.slideProgressPercent = slideProgressPercent;
135050
135202
  exports.slideShowOptionChange = slideShowOptionChange;
135051
135203
  exports.slideSizeFromPreset = slideSizeFromPreset;