pptx-react-viewer 2.19.6 → 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 +23 -0
  2. package/README.md +1 -1
  3. package/dist/{AiChatPanel-IWC2BJH4.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-2VR6UFFK.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-ATRIORJV.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-E4T6KAJF.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-IWCBDKPX.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-2N2Z7WG2.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-FTUGCQVY.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-3BK53XWF.js → chunk-J56DMNSD.js} +746 -483
  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-RQWZ7J3Z.mjs → chunk-QLELFH7A.mjs} +728 -480
  34. package/dist/chunk-QLELFH7A.mjs.br +0 -0
  35. package/dist/chunk-QLELFH7A.mjs.gz +0 -0
  36. package/dist/{chunk-YEEOYPFO.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-KPNZXUKK.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-667ZAXQN.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-NHN6XKJV.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-VU4RQSTI.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-2VR6UFFK.mjs.br +0 -0
  80. package/dist/AiChatPanel-2VR6UFFK.mjs.gz +0 -0
  81. package/dist/AiChatPanel-IWC2BJH4.js.br +0 -0
  82. package/dist/AiChatPanel-IWC2BJH4.js.gz +0 -0
  83. package/dist/Model3DScene-ATRIORJV.js.br +0 -0
  84. package/dist/Model3DScene-ATRIORJV.js.gz +0 -0
  85. package/dist/Model3DScene-E4T6KAJF.mjs.br +0 -0
  86. package/dist/Model3DScene-E4T6KAJF.mjs.gz +0 -0
  87. package/dist/chunk-2N2Z7WG2.js.br +0 -0
  88. package/dist/chunk-2N2Z7WG2.js.gz +0 -0
  89. package/dist/chunk-3BK53XWF.js.br +0 -0
  90. package/dist/chunk-3BK53XWF.js.gz +0 -0
  91. package/dist/chunk-667ZAXQN.mjs.br +0 -0
  92. package/dist/chunk-667ZAXQN.mjs.gz +0 -0
  93. package/dist/chunk-FTUGCQVY.js.br +0 -0
  94. package/dist/chunk-FTUGCQVY.js.gz +0 -0
  95. package/dist/chunk-IWCBDKPX.mjs.br +0 -0
  96. package/dist/chunk-IWCBDKPX.mjs.gz +0 -0
  97. package/dist/chunk-KPNZXUKK.js.br +0 -0
  98. package/dist/chunk-KPNZXUKK.js.gz +0 -0
  99. package/dist/chunk-MVKRI3CZ.js.br +0 -0
  100. package/dist/chunk-NHN6XKJV.mjs.br +0 -0
  101. package/dist/chunk-NHN6XKJV.mjs.gz +0 -0
  102. package/dist/chunk-RQWZ7J3Z.mjs.br +0 -0
  103. package/dist/chunk-RQWZ7J3Z.mjs.gz +0 -0
  104. package/dist/chunk-SQJBFMEX.mjs.br +0 -0
  105. package/dist/chunk-VU4RQSTI.mjs.br +0 -0
  106. package/dist/chunk-VU4RQSTI.mjs.gz +0 -0
  107. package/dist/chunk-YEEOYPFO.js.br +0 -0
  108. package/dist/chunk-YEEOYPFO.js.gz +0 -0
@@ -20980,9 +20980,9 @@ function applyDrawingColorTransforms(baseColor, colorNode) {
20980
20980
  }
20981
20981
  const tint3 = parseDrawingPercent(getVal("a:tint"));
20982
20982
  if (tint3 !== void 0) {
20983
- r += (255 - r) * tint3;
20984
- g += (255 - g) * tint3;
20985
- b += (255 - b) * tint3;
20983
+ r = 255 - (255 - r) * tint3;
20984
+ g = 255 - (255 - g) * tint3;
20985
+ b = 255 - (255 - b) * tint3;
20986
20986
  }
20987
20987
  const hslKeys = [
20988
20988
  "a:hue",
@@ -27508,7 +27508,7 @@ function guidToKey(guid) {
27508
27508
  }
27509
27509
  const key2 = new Uint8Array(KEY_LENGTH);
27510
27510
  for (let i = 0; i < KEY_LENGTH; i++) {
27511
- key2[i] = parseInt(stripped.substring(i * 2, i * 2 + 2), 16);
27511
+ key2[KEY_LENGTH - 1 - i] = parseInt(stripped.substring(i * 2, i * 2 + 2), 16);
27512
27512
  }
27513
27513
  return key2;
27514
27514
  }
@@ -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
  }
@@ -56172,11 +56172,6 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
56172
56172
  if (requestedSourcePath && this.slideMap.has(requestedSourcePath) && requestedSourcePath.startsWith("ppt/slides/slide")) {
56173
56173
  return requestedSourcePath;
56174
56174
  }
56175
- for (const slidePath of this.slideMap.keys()) {
56176
- if (slidePath.startsWith("ppt/slides/slide")) {
56177
- return slidePath;
56178
- }
56179
- }
56180
56175
  return void 0;
56181
56176
  }
56182
56177
  async loadSlideRelationships(slidePath, relsPath) {
@@ -56216,8 +56211,7 @@ var PptxHandlerRuntime11 = class extends PptxHandlerRuntime10 {
56216
56211
  }
56217
56212
  const cSld = pSld["p:cSld"];
56218
56213
  if (!cSld["p:spTree"]) {
56219
- const emptySlide = this.createEmptySlideXml();
56220
- const emptyTree = emptySlide["p:sld"]?.["p:cSld"]?.["p:spTree"];
56214
+ const emptySlide = this.createEmptySlideXml(), emptyTree = emptySlide["p:sld"]?.["p:cSld"]?.["p:spTree"];
56221
56215
  if (emptyTree) {
56222
56216
  cSld["p:spTree"] = emptyTree;
56223
56217
  }
@@ -59016,13 +59010,32 @@ var PptxHandlerRuntime21 = class extends PptxHandlerRuntime20 {
59016
59010
  const nvPr = xmlPath(raw, "p:nvSpPr", "p:nvPr") ?? xmlPath(raw, "p:nvPicPr", "p:nvPr") ?? xmlPath(raw, "p:nvGraphicFramePr", "p:nvPr");
59017
59011
  return this.readPlaceholderInfoFromNvPr(nvPr);
59018
59012
  }
59013
+ /**
59014
+ * Whether a placeholder element is still an untouched prompt ("Click to
59015
+ * add text") rather than real user content. Only `type: 'text'`
59016
+ * placeholders can be untouched this way: `createEmptyPlaceholderElement`
59017
+ * only ever fabricates that kind, and any other kind (picture, table,
59018
+ * chart, ...) implies the user already put something in it.
59019
+ */
59020
+ isUntouchedPlaceholderPrompt(element) {
59021
+ if (element.type !== "text") {
59022
+ return false;
59023
+ }
59024
+ if (element.text && element.text.trim().length > 0) {
59025
+ return false;
59026
+ }
59027
+ return !element.textSegments?.some((segment) => segment.text.trim().length > 0);
59028
+ }
59019
59029
  // ── Layout placeholder extraction ───────────────────────────────────
59020
59030
  /**
59021
- * Extract all placeholders from a layout's `p:spTree`, returning
59022
- * their placeholder info and their transform (position/size in EMU).
59031
+ * Extract placeholder info + transform (position/size in EMU) for every
59032
+ * placeholder shape in a `p:spTree`. Shared by layout and master
59033
+ * extraction so a layout slot that omits `a:xfrm` (common: only the first
59034
+ * placeholder of a family typically carries one, the rest inherit
59035
+ * position/size from the matching master placeholder) can be resolved
59036
+ * against the same shape of the master.
59023
59037
  */
59024
- extractLayoutPlaceholders(layoutXml) {
59025
- const spTree = xmlPath(layoutXml, "p:sldLayout", "p:cSld", "p:spTree");
59038
+ extractPlaceholderSlotsFromSpTree(spTree) {
59026
59039
  if (!spTree) {
59027
59040
  return [];
59028
59041
  }
@@ -59050,6 +59063,103 @@ var PptxHandlerRuntime21 = class extends PptxHandlerRuntime20 {
59050
59063
  }
59051
59064
  return result;
59052
59065
  }
59066
+ /**
59067
+ * Resolve a layout's slideMaster path from its `.rels` map. Mirrors
59068
+ * `PptxHandlerRuntimeLoadPipeline.findMasterPathForLayout` under a
59069
+ * distinct name: that mixin sits higher in the chain and is not yet
59070
+ * available at this level, and reusing its exact name here would collide
59071
+ * across the mixin chain (TypeScript requires consistent member
59072
+ * visibility for same-named members across the whole prototype chain).
59073
+ */
59074
+ resolveMasterPathForNewLayout(layoutPath) {
59075
+ const layoutRels = this.slideRelsMap.get(layoutPath);
59076
+ if (!layoutRels) {
59077
+ return void 0;
59078
+ }
59079
+ for (const [, target] of layoutRels.entries()) {
59080
+ if (target.includes("slideMaster")) {
59081
+ const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
59082
+ if (target.startsWith("..")) {
59083
+ const segments = (layoutDir + target).split("/");
59084
+ const stack = [];
59085
+ for (const seg of segments) {
59086
+ if (seg === "..") {
59087
+ stack.pop();
59088
+ } else if (seg && seg !== ".") {
59089
+ stack.push(seg);
59090
+ }
59091
+ }
59092
+ return stack.join("/");
59093
+ }
59094
+ return `ppt/${stripParentDirSegments(target)}`;
59095
+ }
59096
+ }
59097
+ return void 0;
59098
+ }
59099
+ /**
59100
+ * Find the master placeholder slot a layout slot inherits its geometry
59101
+ * from when the layout shape itself carries no `a:xfrm`. Prefers an idx
59102
+ * match (the common case: layout and master share idx for ordinary
59103
+ * title/body placeholders); falls back to a type match (with the
59104
+ * ctrTitle->title / subTitle->body aliasing `placeholderMatches` also
59105
+ * applies) since idx is not guaranteed to line up for every family.
59106
+ */
59107
+ findMasterSlotForLayoutSlot(masterSlots, layoutPhInfo) {
59108
+ if (layoutPhInfo.idx !== void 0) {
59109
+ const byIdx = masterSlots.find((slot) => slot.phInfo.idx === layoutPhInfo.idx);
59110
+ if (byIdx) {
59111
+ return byIdx;
59112
+ }
59113
+ }
59114
+ if (!layoutPhInfo.type) {
59115
+ return void 0;
59116
+ }
59117
+ const aliasedType = layoutPhInfo.type === "ctrtitle" ? "title" : layoutPhInfo.type === "subtitle" ? "body" : layoutPhInfo.type;
59118
+ return masterSlots.find(
59119
+ (slot) => slot.phInfo.type === layoutPhInfo.type || slot.phInfo.type === aliasedType
59120
+ );
59121
+ }
59122
+ /**
59123
+ * Extract all placeholders from a layout's `p:spTree`, returning their
59124
+ * placeholder info and transform (position/size in EMU). A slot whose
59125
+ * layout shape has no `a:xfrm` (inheriting position/size from the master
59126
+ * instead) resolves its geometry against the matching master placeholder
59127
+ * rather than reporting an all-zero transform.
59128
+ */
59129
+ extractLayoutPlaceholders(layoutXml, layoutPath) {
59130
+ const spTree = xmlPath(layoutXml, "p:sldLayout", "p:cSld", "p:spTree");
59131
+ const slots = this.extractPlaceholderSlotsFromSpTree(spTree);
59132
+ if (slots.length === 0 || !layoutPath) {
59133
+ return slots;
59134
+ }
59135
+ const needsMasterGeometry = slots.some((slot) => slot.cxEmu <= 0 || slot.cyEmu <= 0);
59136
+ if (!needsMasterGeometry) {
59137
+ return slots;
59138
+ }
59139
+ const masterPath = this.resolveMasterPathForNewLayout(layoutPath);
59140
+ const masterXml = masterPath ? this.masterXmlMap.get(masterPath) : void 0;
59141
+ const masterSpTree = xmlPath(masterXml, "p:sldMaster", "p:cSld", "p:spTree");
59142
+ const masterSlots = this.extractPlaceholderSlotsFromSpTree(masterSpTree);
59143
+ if (masterSlots.length === 0) {
59144
+ return slots;
59145
+ }
59146
+ return slots.map((slot) => {
59147
+ if (slot.cxEmu > 0 && slot.cyEmu > 0) {
59148
+ return slot;
59149
+ }
59150
+ const masterSlot = this.findMasterSlotForLayoutSlot(masterSlots, slot.phInfo);
59151
+ if (!masterSlot || masterSlot.cxEmu <= 0 || masterSlot.cyEmu <= 0) {
59152
+ return slot;
59153
+ }
59154
+ return {
59155
+ ...slot,
59156
+ xEmu: masterSlot.xEmu,
59157
+ yEmu: masterSlot.yEmu,
59158
+ cxEmu: masterSlot.cxEmu,
59159
+ cyEmu: masterSlot.cyEmu
59160
+ };
59161
+ });
59162
+ }
59053
59163
  // ── Core layout switching logic ─────────────────────────────────────
59054
59164
  /**
59055
59165
  * Re-map slide elements to a new layout's placeholders.
@@ -59066,7 +59176,10 @@ var PptxHandlerRuntime21 = class extends PptxHandlerRuntime20 {
59066
59176
  * @returns The updated elements array.
59067
59177
  */
59068
59178
  remapElementsToNewLayout(elements2, newLayoutXml, newLayoutPath) {
59069
- const targets = this.extractLayoutPlaceholders(newLayoutXml).map((slot) => ({ ...slot, matched: false }));
59179
+ const targets = this.extractLayoutPlaceholders(newLayoutXml, newLayoutPath).map((slot) => ({
59180
+ ...slot,
59181
+ matched: false
59182
+ }));
59070
59183
  const resultElements = [];
59071
59184
  for (const element of elements2) {
59072
59185
  const phInfo = this.getElementPlaceholderInfo(element);
@@ -59111,7 +59224,7 @@ var PptxHandlerRuntime21 = class extends PptxHandlerRuntime20 {
59111
59224
  retargetPlaceholder(updatedElement.rawXml, resolvedLayoutPh.phInfo);
59112
59225
  }
59113
59226
  resultElements.push(updatedElement);
59114
- } else {
59227
+ } else if (!this.isUntouchedPlaceholderPrompt(element)) {
59115
59228
  resultElements.push(element);
59116
59229
  }
59117
59230
  }
@@ -68838,6 +68951,7 @@ var PptxHandlerRuntime51 = class _PptxHandlerRuntime18 extends PptxHandlerRuntim
68838
68951
  this.zip.file(relsPath, this.builder.build(relsData));
68839
68952
  }
68840
68953
  };
68954
+ var SPECIAL_PLACEHOLDER_TYPES = /* @__PURE__ */ new Set(["dt", "ftr", "hdr", "sldnum"]);
68841
68955
  var PptxHandlerRuntime52 = class _PptxHandlerRuntime19 extends PptxHandlerRuntime51 {
68842
68956
  /**
68843
68957
  * Parse media data (video/audio path and MIME type) from graphic frame data.
@@ -69066,6 +69180,9 @@ var PptxHandlerRuntime52 = class _PptxHandlerRuntime19 extends PptxHandlerRuntim
69066
69180
  if (source.type && target.type && !typesMatch) {
69067
69181
  return false;
69068
69182
  }
69183
+ if (source.type && SPECIAL_PLACEHOLDER_TYPES.has(source.type) && !target.type || target.type && SPECIAL_PLACEHOLDER_TYPES.has(target.type) && !source.type) {
69184
+ return false;
69185
+ }
69069
69186
  const bothHaveExplicitIdx = source.idx !== void 0 && target.idx !== void 0;
69070
69187
  if (!bothHaveExplicitIdx && source.type && !target.type) {
69071
69188
  return false;
@@ -97145,6 +97262,15 @@ function resolveDataPointMarker(series, pointIndex) {
97145
97262
  fill: point?.spPr?.fillColor ?? series.marker?.spPr?.fillColor
97146
97263
  };
97147
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
+ }
97148
97274
  function schemaLabel(keys, token2, translate) {
97149
97275
  if (token2 === void 0) {
97150
97276
  return "";
@@ -97787,47 +97913,24 @@ function blendToWhite(color2) {
97787
97913
  if (!match) {
97788
97914
  return color2;
97789
97915
  }
97790
- const value = Number.parseInt(match[1], 16);
97791
- const mix = (channel) => Math.round(channel + (255 - channel) * 0.5);
97792
- const r = mix(value >> 16 & 255);
97793
- const g = mix(value >> 8 & 255);
97794
- 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);
97795
97917
  return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, "0").toUpperCase()}`;
97796
97918
  }
97797
97919
  function invertNegativeFill(series, pointIndex, value, baseFill) {
97798
97920
  if (value >= 0) {
97799
97921
  return baseFill;
97800
97922
  }
97801
- const point = series.dataPoints?.find((p) => p.idx === pointIndex);
97802
- const invert = point?.invertIfNegative ?? series.invertIfNegative ?? false;
97923
+ const point = series.dataPoints?.find((p) => p.idx === pointIndex), invert = point?.invertIfNegative ?? series.invertIfNegative ?? false;
97803
97924
  return invert ? blendToWhite(baseFill) : baseFill;
97804
97925
  }
97805
97926
  function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, secondaryIdx, grouping, sourceIndices2) {
97806
- const primitives = [];
97807
- const dataLabels = [];
97808
- const series = chartData.series;
97809
- const palette = chartData.colorPalette;
97810
- const showLabels = chartData.style?.hasDataLabels;
97811
- 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;
97812
97928
  if (grouping === "clustered") {
97813
- const seriesCount = Math.max(series.length, 1);
97814
- const barGroupWidth2 = layout.plotWidth / Math.max(catCount, 1);
97815
- const singleBarWidth = chartData.barGapWidth !== void 0 ? barGroupWidth2 / (seriesCount + Math.max(chartData.barGapWidth, 0) / 100) : barGroupWidth2 * 0.7 / seriesCount;
97816
- const overlap = chartData.barOverlap ?? 0;
97817
- const step = singleBarWidth * (1 - overlap / 100);
97818
- const clusterWidth = singleBarWidth + step * (seriesCount - 1);
97819
- 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;
97820
97930
  for (let displayIndex = 0; displayIndex < catCount; displayIndex++) {
97821
97931
  const sourceIndex = sourceIndices2[displayIndex] ?? displayIndex;
97822
97932
  for (let si = 0; si < series.length; si++) {
97823
- const val2 = series[si].values[sourceIndex] ?? 0;
97824
- const x = layout.plotLeft + barGroupWidth2 * displayIndex + groupOffset + step * si;
97825
- const activeRange = secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange;
97826
- const zeroY = valueToY2(0, activeRange, layout.plotTop, layout.plotBottom);
97827
- const valY = valueToY2(val2, activeRange, layout.plotTop, layout.plotBottom);
97828
- const y = Math.min(zeroY, valY);
97829
- const h = Math.max(Math.abs(zeroY - valY), 1);
97830
- 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);
97831
97934
  primitives.push({
97832
97935
  kind: "rect",
97833
97936
  x,
@@ -97836,7 +97939,13 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97836
97939
  h,
97837
97940
  fill: invertNegativeFill(series[si], sourceIndex, val2, baseFill),
97838
97941
  rx: 1,
97839
- 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
+ )
97840
97949
  });
97841
97950
  if (showLabels) {
97842
97951
  const text2 = buildDataLabelText({
@@ -97865,19 +97974,23 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97865
97974
  const displaySeries2 = series.map((entry2) => ({
97866
97975
  ...entry2,
97867
97976
  values: sourceIndices2.map((sourceIndex) => entry2.values[sourceIndex] ?? 0)
97868
- }));
97869
- const rects = computeStackedBarRects(displaySeries2, catCount, layout, primaryRange, palette);
97977
+ })), rects = computeStackedBarRects(displaySeries2, catCount, layout, primaryRange, palette);
97870
97978
  for (const r of rects) {
97871
- let fill = r.fill;
97872
- let part;
97979
+ let fill = r.fill, part, title;
97873
97980
  if (r.seriesIndex !== void 0 && r.pointIndex !== void 0) {
97874
97981
  const sourcePointIndex = sourceIndices2[r.pointIndex] ?? r.pointIndex;
97875
97982
  fill = resolveDataPointFill(series[r.seriesIndex], sourcePointIndex, r.fill) ?? r.fill;
97876
97983
  const value = series[r.seriesIndex].values[sourcePointIndex] ?? 0;
97877
97984
  fill = invertNegativeFill(series[r.seriesIndex], sourcePointIndex, value, fill);
97878
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
+ );
97879
97992
  }
97880
- 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 });
97881
97994
  }
97882
97995
  if (showLabels) {
97883
97996
  pushClusteredStackedLabels(
@@ -97892,31 +98005,15 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97892
98005
  }
97893
98006
  return { primitives, dataLabels };
97894
98007
  }
97895
- const barGroupWidth = layout.plotWidth / Math.max(catCount, 1);
97896
- const barW = barGroupWidth * 0.6;
97897
- const barOffset = (barGroupWidth - barW) / 2;
97898
- 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) => ({
97899
98009
  ...entry2,
97900
98010
  values: sourceIndices2.map((sourceIndex) => entry2.values[sourceIndex] ?? 0)
97901
- }));
97902
- const totals = categoryTotals(displaySeries, catCount);
98011
+ })), totals = categoryTotals(displaySeries, catCount);
97903
98012
  for (let ci = 0; ci < catCount; ci++) {
97904
- let posRunning = 0;
97905
- let negRunning = 0;
98013
+ let posRunning = 0, negRunning = 0;
97906
98014
  const catTotal = totals[ci] || 1;
97907
98015
  for (let si = 0; si < series.length; si++) {
97908
- const sourceIndex = sourceIndices2[ci] ?? ci;
97909
- const rawVal = series[si].values[sourceIndex] ?? 0;
97910
- const val2 = catTotal > 0 ? rawVal / catTotal * 100 : 0;
97911
- const isNeg = val2 < 0;
97912
- const base = isNeg ? negRunning : posRunning;
97913
- const top = base + val2;
97914
- const x = layout.plotLeft + barGroupWidth * ci + barOffset;
97915
- const baseY = valueToY2(base, primaryRange, layout.plotTop, layout.plotBottom);
97916
- const topY = valueToY2(top, primaryRange, layout.plotTop, layout.plotBottom);
97917
- const y = Math.min(baseY, topY);
97918
- const h = Math.max(Math.abs(baseY - topY), 0.5);
97919
- 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);
97920
98017
  primitives.push({
97921
98018
  kind: "rect",
97922
98019
  x,
@@ -97924,7 +98021,13 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97924
98021
  w: barW,
97925
98022
  h,
97926
98023
  fill: invertNegativeFill(series[si], sourceIndex, rawVal, pctBaseFill),
97927
- 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
+ )
97928
98031
  });
97929
98032
  if (showLabels && Math.abs(val2) > 0) {
97930
98033
  dataLabels.push({
@@ -97948,19 +98051,11 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
97948
98051
  return { primitives, dataLabels };
97949
98052
  }
97950
98053
  function pushClusteredStackedLabels(chartData, series, sourceIndices2, catCount, layout, range, dataLabels) {
97951
- const barGroupWidth = layout.plotWidth / catCount;
97952
- const seriesCount = Math.max(series.length, 1);
97953
- const singleBarWidth = barGroupWidth * 0.7 / seriesCount;
97954
- 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;
97955
98055
  for (let ci = 0; ci < catCount; ci++) {
97956
98056
  const sourceIndex = sourceIndices2[ci] ?? ci;
97957
98057
  for (let si = 0; si < series.length; si++) {
97958
- const val2 = series[si].values[sourceIndex] ?? 0;
97959
- const x = layout.plotLeft + barGroupWidth * ci + groupOffset + singleBarWidth * si + singleBarWidth / 2;
97960
- const zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
97961
- const valY = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
97962
- const labelY = val2 >= 0 ? Math.min(zeroY, valY) - 4 : Math.max(zeroY, valY) + 10;
97963
- 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({
97964
98059
  chartData,
97965
98060
  series: series[si],
97966
98061
  pointIndex: sourceIndex,
@@ -98152,9 +98247,12 @@ function buildMarkerPrimitive(input) {
98152
98247
  return { kind: "circle", cx, cy, r, fill, part };
98153
98248
  }
98154
98249
  }
98155
- function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius2, part, opacity2) {
98156
- const marker = resolveDataPointMarker(series, pointIndex);
98157
- 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({
98158
98256
  symbol: marker.symbol,
98159
98257
  size: marker.size,
98160
98258
  cx,
@@ -98171,34 +98269,180 @@ function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius2, part,
98171
98269
  if (opacity2 !== void 0) {
98172
98270
  m.opacity = opacity2;
98173
98271
  }
98272
+ if (title !== void 0) {
98273
+ m.title = title;
98274
+ }
98174
98275
  out.push(m);
98175
98276
  }
98176
- function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, secondaryIdx, sourceIndices2, xPositions) {
98177
- const primitives = [];
98178
- const dataLabels = [];
98179
- 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";
98180
98293
  for (let si = 0; si < chartData.series.length; si++) {
98181
- 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) => {
98182
98423
  if (series.values.length === 0) {
98183
- continue;
98424
+ return void 0;
98184
98425
  }
98185
- const activeRange = secondaryIdx.has(si) && secondaryRange ? secondaryRange : primaryRange;
98186
- const rawValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0);
98187
- const displayBlanks = sourceIndices2.map((sourceIndex) => series.blanks?.[sourceIndex] ?? false);
98188
- 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(
98189
98427
  rawValues,
98190
98428
  displayBlanks,
98191
98429
  chartData.chartChrome?.dispBlanksAs
98192
98430
  );
98193
- const pts = computeLinePoints(displayValues, catCount, layout, activeRange).map(
98194
- (point, index) => ({
98195
- ...point,
98196
- x: xPositions?.[index] ?? point.x
98197
- })
98198
- );
98199
- const c = seriesColor2(series, si, chartData.colorPalette);
98200
- const seriesPart = { role: "series", seriesIndex: si };
98201
- 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);
98202
98446
  if (allVisible) {
98203
98447
  primitives.push(
98204
98448
  series.smooth ? {
@@ -98236,8 +98480,7 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98236
98480
  if (!visible[displayIndex]) {
98237
98481
  return;
98238
98482
  }
98239
- const idx = sourceIndices2[displayIndex] ?? displayIndex;
98240
- const part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98483
+ const idx = sourceIndices2[displayIndex] ?? displayIndex, part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98241
98484
  pushMarker(
98242
98485
  primitives,
98243
98486
  series,
@@ -98246,19 +98489,45 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98246
98489
  pt.y,
98247
98490
  resolveDataPointFill(series, idx, c) ?? c,
98248
98491
  2.5,
98249
- part
98492
+ part,
98493
+ void 0,
98494
+ buildMarkTooltip(
98495
+ series.name,
98496
+ chartData.categories[idx],
98497
+ series.values[idx] ?? 0,
98498
+ series.numberFormat
98499
+ )
98250
98500
  );
98251
98501
  });
98252
98502
  if (showLabels) {
98253
- displayValues.forEach((val2, displayIndex) => {
98503
+ const labelValues = stackedPlots ? stackedPlots[si].own : displayValues;
98504
+ labelValues.forEach((val2, displayIndex) => {
98254
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
+ }
98255
98524
  const text2 = buildDataLabelText({
98256
98525
  chartData,
98257
98526
  series,
98258
98527
  pointIndex: sourceIndices2[displayIndex] ?? displayIndex,
98259
98528
  value: val2
98260
98529
  });
98261
- if (!pt || !visible[displayIndex] || text2 === void 0) {
98530
+ if (text2 === void 0) {
98262
98531
  return;
98263
98532
  }
98264
98533
  dataLabels.push({
@@ -98275,26 +98544,41 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
98275
98544
  }
98276
98545
  return { primitives, dataLabels };
98277
98546
  }
98278
- function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositions) {
98279
- const primitives = [];
98280
- const dataLabels = [];
98281
- const showLabels = chartData.style?.hasDataLabels;
98282
- 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;
98283
98555
  for (let si = 0; si < chartData.series.length; si++) {
98284
- const series = chartData.series[si];
98285
- if (series.values.length === 0) {
98556
+ const series = chartData.series[si], displayValues = allDisplayValues[si];
98557
+ if (!displayValues) {
98286
98558
  continue;
98287
98559
  }
98288
- const displayValues = sourceIndices2.map((sourceIndex) => series.values[sourceIndex] ?? 0);
98289
- 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) => ({
98290
98561
  ...point,
98291
98562
  x: xPositions?.[index] ?? point.x
98292
- }));
98293
- const c = seriesColor2(series, si, chartData.colorPalette);
98294
- const lineStr = linePointsToSvgString(pts);
98295
- const firstPt = pts[0];
98296
- const lastPt = pts[pts.length - 1];
98297
- 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) {
98298
98582
  primitives.push({
98299
98583
  kind: "polyline",
98300
98584
  points: `${firstPt.x.toFixed(2)},${baselineY.toFixed(2)} ${lineStr} ${lastPt.x.toFixed(2)},${baselineY.toFixed(2)}`,
@@ -98314,8 +98598,7 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98314
98598
  part: { role: "series", seriesIndex: si }
98315
98599
  });
98316
98600
  pts.forEach((pt, displayIndex) => {
98317
- const idx = sourceIndices2[displayIndex] ?? displayIndex;
98318
- const part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98601
+ const idx = sourceIndices2[displayIndex] ?? displayIndex, part = { role: "dataPoint", seriesIndex: si, pointIndex: idx };
98319
98602
  pushMarker(
98320
98603
  primitives,
98321
98604
  series,
@@ -98324,19 +98607,45 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98324
98607
  pt.y,
98325
98608
  resolveDataPointFill(series, idx, c) ?? c,
98326
98609
  2,
98327
- part
98610
+ part,
98611
+ void 0,
98612
+ buildMarkTooltip(
98613
+ series.name,
98614
+ chartData.categories[idx],
98615
+ series.values[idx] ?? 0,
98616
+ series.numberFormat
98617
+ )
98328
98618
  );
98329
98619
  });
98330
98620
  if (showLabels) {
98331
- displayValues.forEach((val2, displayIndex) => {
98621
+ const labelValues = plot ? plot.own : displayValues;
98622
+ labelValues.forEach((val2, displayIndex) => {
98332
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
+ }
98333
98642
  const text2 = buildDataLabelText({
98334
98643
  chartData,
98335
98644
  series,
98336
98645
  pointIndex: sourceIndices2[displayIndex] ?? displayIndex,
98337
98646
  value: val2
98338
98647
  });
98339
- if (!pt || text2 === void 0) {
98648
+ if (text2 === void 0) {
98340
98649
  return;
98341
98650
  }
98342
98651
  dataLabels.push({
@@ -98353,151 +98662,6 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices2, xPositio
98353
98662
  }
98354
98663
  return { primitives, dataLabels };
98355
98664
  }
98356
- function seriesXValues(chartData, series) {
98357
- if (series.xValues && series.xValues.length > 0) {
98358
- return series.xValues;
98359
- }
98360
- const fromCategories = chartData.categories.map(Number);
98361
- return fromCategories.length > 0 ? fromCategories : void 0;
98362
- }
98363
- function scatterDrawsLine(chartData, series) {
98364
- if (series.lineNoFill === true) {
98365
- return false;
98366
- }
98367
- const style = chartData.scatterStyle;
98368
- return style === "line" || style === "lineMarker" || style === "smooth" || style === "smoothMarker";
98369
- }
98370
- function buildScatter(chartData, layout, range) {
98371
- const primitives = [];
98372
- const dataLabels = [];
98373
- const showLabels = chartData.style?.hasDataLabels;
98374
- const allIndices = chartData.series.flatMap((s) => s.values.map((_, i) => i));
98375
- const maxXIndex = Math.max(1, ...allIndices);
98376
- const perSeriesX = chartData.series.map((series) => seriesXValues(chartData, series));
98377
- const xDomain = computeScatterXDomain(perSeriesX);
98378
- const smoothStyle = chartData.scatterStyle === "smooth" || chartData.scatterStyle === "smoothMarker";
98379
- for (let si = 0; si < chartData.series.length; si++) {
98380
- const series = chartData.series[si];
98381
- const c = seriesColor2(series, si, chartData.colorPalette);
98382
- const dots = computeScatterDots(
98383
- series.values,
98384
- maxXIndex,
98385
- layout,
98386
- range,
98387
- perSeriesX[si],
98388
- xDomain
98389
- );
98390
- if (scatterDrawsLine(chartData, series) && dots.length >= 2) {
98391
- const points3 = dots.map((dot) => ({ x: dot.cx, y: dot.cy }));
98392
- const seriesPart = { role: "series", seriesIndex: si };
98393
- primitives.push(
98394
- series.smooth ?? smoothStyle ? {
98395
- kind: "path",
98396
- d: smoothLinePath(points3),
98397
- stroke: c,
98398
- strokeWidth: 2.4,
98399
- fill: "none",
98400
- part: seriesPart
98401
- } : {
98402
- kind: "polyline",
98403
- points: linePointsToSvgString(points3),
98404
- stroke: c,
98405
- strokeWidth: 2.4,
98406
- fill: "none",
98407
- part: seriesPart
98408
- }
98409
- );
98410
- }
98411
- dots.forEach((dot, vi) => {
98412
- const part = { role: "dataPoint", seriesIndex: si, pointIndex: vi };
98413
- pushMarker(
98414
- primitives,
98415
- series,
98416
- vi,
98417
- dot.cx,
98418
- dot.cy,
98419
- resolveDataPointFill(series, vi, c) ?? c,
98420
- 4,
98421
- part,
98422
- 0.85
98423
- );
98424
- });
98425
- if (showLabels) {
98426
- series.values.forEach((val2, vi) => {
98427
- const dot = dots[vi];
98428
- const text2 = buildDataLabelText({ chartData, series, pointIndex: vi, value: val2 });
98429
- if (!dot || text2 === void 0) {
98430
- return;
98431
- }
98432
- dataLabels.push({
98433
- kind: "text",
98434
- x: dot.cx,
98435
- y: dot.cy - 6,
98436
- text: text2,
98437
- fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98438
- fill: "#334155",
98439
- textAnchor: "middle"
98440
- });
98441
- });
98442
- }
98443
- }
98444
- return { primitives, dataLabels };
98445
- }
98446
- function buildBubbles(chartData, layout, range) {
98447
- const primitives = [];
98448
- const dataLabels = [];
98449
- const showLabels = chartData.style?.hasDataLabels;
98450
- const allIndices = chartData.series.flatMap((s) => s.values.map((_, i) => i));
98451
- const maxXIndex = Math.max(1, ...allIndices);
98452
- const perSeriesX = chartData.series.map((series) => seriesXValues(chartData, series));
98453
- const xDomain = computeScatterXDomain(perSeriesX);
98454
- const allSizes = chartData.series.flatMap((series) => series.bubbleSizes ?? []);
98455
- const maxBubble = allSizes.length > 0 ? Math.max(1, ...allSizes.map(Math.abs)) : 1;
98456
- const medianRadius = Math.min(layout.plotWidth, layout.plotHeight) * 0.04;
98457
- for (let si = 0; si < chartData.series.length; si++) {
98458
- const series = chartData.series[si];
98459
- const c = seriesColor2(series, si, chartData.colorPalette);
98460
- const dots = computeScatterDots(
98461
- series.values,
98462
- maxXIndex,
98463
- layout,
98464
- range,
98465
- perSeriesX[si],
98466
- xDomain
98467
- );
98468
- dots.forEach((dot, vi) => {
98469
- const r = computeBubbleRadius(series.bubbleSizes?.[vi], maxBubble, medianRadius);
98470
- primitives.push({
98471
- kind: "circle",
98472
- cx: dot.cx,
98473
- cy: dot.cy,
98474
- r,
98475
- fill: resolveDataPointFill(series, vi, c) ?? c,
98476
- opacity: 0.6,
98477
- part: { role: "dataPoint", seriesIndex: si, pointIndex: vi }
98478
- });
98479
- });
98480
- if (showLabels) {
98481
- series.values.forEach((val2, vi) => {
98482
- const dot = dots[vi];
98483
- const text2 = buildDataLabelText({ chartData, series, pointIndex: vi, value: val2 });
98484
- if (!dot || text2 === void 0) {
98485
- return;
98486
- }
98487
- dataLabels.push({
98488
- kind: "text",
98489
- x: dot.cx,
98490
- y: dot.cy - 10,
98491
- text: text2,
98492
- fontSize: DEFAULT_CHART_DATA_LABEL_PX,
98493
- fill: "#334155",
98494
- textAnchor: "middle"
98495
- });
98496
- });
98497
- }
98498
- }
98499
- return { primitives, dataLabels };
98500
- }
98501
98665
  function categoryX(index, catCount, layout, options) {
98502
98666
  const explicit = options.xPositions?.[index];
98503
98667
  if (explicit !== void 0) {
@@ -99005,10 +99169,7 @@ function valueToX(val2, range, leftX, rightX) {
99005
99169
  const usable = rightX - leftX;
99006
99170
  let ratio;
99007
99171
  if (range.logScale && range.logBase) {
99008
- const base = range.logBase;
99009
- const clampedVal = Math.max(val2, range.min);
99010
- const logVal = Math.log(clampedVal) / Math.log(base);
99011
- 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);
99012
99173
  ratio = (logVal - logMin) / range.span;
99013
99174
  } else {
99014
99175
  ratio = (val2 - range.min) / range.span;
@@ -99016,8 +99177,7 @@ function valueToX(val2, range, leftX, rightX) {
99016
99177
  return range.reverseOrder ? rightX - ratio * usable : leftX + ratio * usable;
99017
99178
  }
99018
99179
  function buildTransposedValueAxis(range, layout) {
99019
- const gridlines = [];
99020
- const axisLabels = [];
99180
+ const gridlines = [], axisLabels = [];
99021
99181
  for (const val2 of axisTickValues(range)) {
99022
99182
  const x = valueToX(val2, range, layout.plotLeft, layout.plotRight);
99023
99183
  gridlines.push({
@@ -99042,8 +99202,7 @@ function buildTransposedValueAxis(range, layout) {
99042
99202
  return { gridlines, axisLabels };
99043
99203
  }
99044
99204
  function buildSideCategoryLabels(categoryLabels, layout) {
99045
- const catCount = Math.max(categoryLabels.length, 1);
99046
- const band = layout.plotHeight / catCount;
99205
+ const catCount = Math.max(categoryLabels.length, 1), band = layout.plotHeight / catCount;
99047
99206
  return categoryLabels.map((label, i) => ({
99048
99207
  kind: "text",
99049
99208
  x: layout.plotLeft - 4,
@@ -99069,16 +99228,7 @@ function barFill(chartData, series, seriesIndex, pointIndex) {
99069
99228
  return resolveDataPointFill(series, pointIndex, paletteColor2(seriesIndex, palette)) ?? seriesColor2(series, seriesIndex, palette);
99070
99229
  }
99071
99230
  function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99072
- const layout = computePlotLayout(element.width, element.height, chartData, true);
99073
- const catCount = Math.max(categoryLabels.length, 1);
99074
- const series = chartData.series;
99075
- const grouping = chartData.grouping ?? "clustered";
99076
- const isStacked = grouping === "stacked" || grouping === "percentStacked";
99077
- const isPercent = grouping === "percentStacked";
99078
- const range = isPercent ? { min: 0, max: 100, span: 100 } : isStacked ? computeStackedValueRange(series, catCount) : computeValueRangeForChart(series, chartData.axes);
99079
- const { gridlines, axisLabels } = buildTransposedValueAxis(range, layout);
99080
- const zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight);
99081
- 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 ? {
99082
99232
  kind: "line",
99083
99233
  x1: zeroX,
99084
99234
  y1: layout.plotTop,
@@ -99086,25 +99236,12 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99086
99236
  y2: layout.plotBottom,
99087
99237
  stroke: ZERO_LINE_COLOR,
99088
99238
  strokeWidth: 1
99089
- } : void 0;
99090
- const primitives = [];
99091
- const dataLabels = [];
99092
- const showLabels = chartData.style?.hasDataLabels;
99093
- const band = layout.plotHeight / catCount;
99239
+ } : void 0, primitives = [], dataLabels = [], showLabels = chartData.style?.hasDataLabels, band = layout.plotHeight / catCount;
99094
99240
  if (!isStacked) {
99095
- const seriesCount = Math.max(series.length, 1);
99096
- const singleBarHeight = chartData.barGapWidth !== void 0 ? band / (seriesCount + Math.max(chartData.barGapWidth, 0) / 100) : band * 0.7 / seriesCount;
99097
- const overlap = chartData.barOverlap ?? 0;
99098
- const step = singleBarHeight * (1 - overlap / 100);
99099
- const clusterHeight = singleBarHeight + step * (seriesCount - 1);
99100
- 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;
99101
99242
  for (let ci = 0; ci < catCount; ci++) {
99102
99243
  for (let si = 0; si < series.length; si++) {
99103
- const val2 = series[si].values[ci] ?? 0;
99104
- const y = layout.plotTop + band * ci + groupOffset + step * si;
99105
- const valX = valueToX(val2, range, layout.plotLeft, layout.plotRight);
99106
- const x = Math.min(zeroX, valX);
99107
- 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);
99108
99245
  primitives.push({
99109
99246
  kind: "rect",
99110
99247
  x,
@@ -99113,7 +99250,13 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99113
99250
  h: singleBarHeight,
99114
99251
  fill: barFill(chartData, series[si], si, ci),
99115
99252
  rx: 1,
99116
- 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
+ )
99117
99260
  });
99118
99261
  if (showLabels) {
99119
99262
  dataLabels.push({
@@ -99130,27 +99273,16 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99130
99273
  }
99131
99274
  }
99132
99275
  } else {
99133
- const totals = isPercent ? categoryTotals2(series, catCount) : [];
99134
- const barH = band * (isPercent ? 0.6 : 0.7);
99135
- const barOffset = (band - barH) / 2;
99276
+ const totals = isPercent ? categoryTotals2(series, catCount) : [], barH = band * (isPercent ? 0.6 : 0.7), barOffset = (band - barH) / 2;
99136
99277
  for (let ci = 0; ci < catCount; ci++) {
99137
- let posRunning = 0;
99138
- let negRunning = 0;
99278
+ let posRunning = 0, negRunning = 0;
99139
99279
  const catTotal = isPercent ? totals[ci] || 1 : 1;
99140
99280
  for (let si = 0; si < series.length; si++) {
99141
- const rawVal = series[si].values[ci] ?? 0;
99142
- const val2 = isPercent ? rawVal / catTotal * 100 : rawVal;
99281
+ const rawVal = series[si].values[ci] ?? 0, val2 = isPercent ? rawVal / catTotal * 100 : rawVal;
99143
99282
  if (val2 === 0) {
99144
99283
  continue;
99145
99284
  }
99146
- const isNeg = val2 < 0;
99147
- const base = isNeg ? negRunning : posRunning;
99148
- const top = base + val2;
99149
- const y = layout.plotTop + band * ci + barOffset;
99150
- const baseX = valueToX(base, range, layout.plotLeft, layout.plotRight);
99151
- const topX = valueToX(top, range, layout.plotLeft, layout.plotRight);
99152
- const x = Math.min(baseX, topX);
99153
- 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);
99154
99286
  primitives.push({
99155
99287
  kind: "rect",
99156
99288
  x,
@@ -99159,7 +99291,13 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99159
99291
  h: barH,
99160
99292
  fill: barFill(chartData, series[si], si, ci),
99161
99293
  rx: 1,
99162
- 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
+ )
99163
99301
  });
99164
99302
  if (showLabels && Math.abs(val2) > 0) {
99165
99303
  dataLabels.push({
@@ -99182,8 +99320,7 @@ function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
99182
99320
  }
99183
99321
  }
99184
99322
  }
99185
- const legendPos = chartData.style?.legendPosition ?? "b";
99186
- const { legend, legendX, legendY, legendAnchor } = buildLegend(
99323
+ const legendPos = chartData.style?.legendPosition ?? "b", { legend, legendX, legendY, legendAnchor } = buildLegend(
99187
99324
  series,
99188
99325
  chartData.colorPalette,
99189
99326
  layout.svgWidth,
@@ -99818,7 +99955,7 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
99818
99955
  const layoutOpts = computeLayoutOptions(chartData.axes, chartData.dataTable, seriesCount);
99819
99956
  const layout = computePlotLayout(element.width, element.height, chartData, true, layoutOpts);
99820
99957
  const catCount = Math.max(categoryLabels.length, 1);
99821
- 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");
99822
99959
  const isPercent = isStacked && chartData.grouping === "percentStacked";
99823
99960
  const { secondary } = splitSeriesByAxis(chartData.series, chartData.axes);
99824
99961
  const secondaryIdx = new Set(secondary.map((e) => e.index));
@@ -99880,7 +100017,8 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
99880
100017
  secondaryRange,
99881
100018
  secondaryIdx,
99882
100019
  sourceIndices2,
99883
- horizontalAxis.xPositions
100020
+ horizontalAxis.xPositions,
100021
+ isStacked ? isPercent ? "percentStacked" : "stacked" : "clustered"
99884
100022
  );
99885
100023
  } else if (kind === "area") {
99886
100024
  plot = buildAreas(
@@ -99889,7 +100027,8 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
99889
100027
  layout,
99890
100028
  primaryRange,
99891
100029
  sourceIndices2,
99892
- horizontalAxis.xPositions
100030
+ horizontalAxis.xPositions,
100031
+ isStacked ? isPercent ? "percentStacked" : "stacked" : "clustered"
99893
100032
  );
99894
100033
  } else if (kind === "scatter") {
99895
100034
  plot = buildScatter(chartData, layout, primaryRange);
@@ -102536,8 +102675,7 @@ function seriesColor2(series, index, colorPalette) {
102536
102675
  return series.color ?? series.marker?.spPr?.fillColor ?? paletteColor2(index, colorPalette);
102537
102676
  }
102538
102677
  function computeValueRange2(series) {
102539
- let dataMin = Number.POSITIVE_INFINITY;
102540
- let dataMax = Number.NEGATIVE_INFINITY;
102678
+ let dataMin = Number.POSITIVE_INFINITY, dataMax = Number.NEGATIVE_INFINITY;
102541
102679
  for (const item of series) {
102542
102680
  for (const value of item.values) {
102543
102681
  if (value < dataMin) {
@@ -102555,11 +102693,9 @@ function computeValueRange2(series) {
102555
102693
  return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
102556
102694
  }
102557
102695
  function computeStackedValueRange(series, catCount) {
102558
- let maxSum = 0;
102559
- let minSum = 0;
102696
+ let maxSum = 0, minSum = 0;
102560
102697
  for (let ci = 0; ci < catCount; ci++) {
102561
- let pos2 = 0;
102562
- let neg = 0;
102698
+ let pos2 = 0, neg = 0;
102563
102699
  for (const s of series) {
102564
102700
  const v = s.values[ci] ?? 0;
102565
102701
  if (v >= 0) {
@@ -102578,10 +102714,7 @@ function valueToY2(val2, range, topY, bottomY) {
102578
102714
  const usable = bottomY - topY;
102579
102715
  let ratio;
102580
102716
  if (range.logScale && range.logBase) {
102581
- const base = range.logBase;
102582
- const clampedVal = Math.max(val2, range.min);
102583
- const logVal = Math.log(clampedVal) / Math.log(base);
102584
- 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);
102585
102718
  ratio = (logVal - logMin) / range.span;
102586
102719
  } else {
102587
102720
  ratio = (val2 - range.min) / range.span;
@@ -102604,23 +102737,20 @@ function formatAxisValue2(val2, formatCode) {
102604
102737
  }
102605
102738
  return val2.toFixed(1);
102606
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
+ }
102607
102744
  function categoryAxisBand(chartData) {
102608
102745
  const axis = chartData.axes?.find(
102609
102746
  (candidate) => candidate.axisType === "catAx" || candidate.axisType === "dateAx"
102610
- );
102611
- const fontPx = axis?.fontSize !== void 0 ? chartFontPx(axis.fontSize) : DEFAULT_CHART_TEXT_PX;
102612
- 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);
102613
102748
  return Math.max(24, offset + fontPx * 1.2);
102614
102749
  }
102615
102750
  function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, options) {
102616
- const svgWidth = Math.max(1, elementWidth);
102617
- const svgHeight = Math.max(1, elementHeight);
102618
- let plotLeft = hasAxes ? 48 : 8;
102619
- let plotTop = 8;
102620
- let plotRight = svgWidth - 8;
102621
- let plotBottom = svgHeight - (hasAxes ? categoryAxisBand(chartData) : 8);
102622
- const style = chartData.style;
102623
- 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";
102624
102754
  if (style?.hasTitle) {
102625
102755
  plotTop += 20;
102626
102756
  }
@@ -102645,8 +102775,7 @@ function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, opti
102645
102775
  const rowCount = options.dataTableRowCount ?? 1;
102646
102776
  plotBottom -= 14 + rowCount * 14;
102647
102777
  }
102648
- const plotWidth = Math.max(plotRight - plotLeft, 1);
102649
- const plotHeight = Math.max(plotBottom - plotTop, 1);
102778
+ const plotWidth = Math.max(plotRight - plotLeft, 1), plotHeight = Math.max(plotBottom - plotTop, 1);
102650
102779
  return {
102651
102780
  svgWidth,
102652
102781
  svgHeight,
@@ -102676,8 +102805,7 @@ function axisTickValues(range) {
102676
102805
  );
102677
102806
  }
102678
102807
  function buildGridlinesAndLabels(range, layout) {
102679
- const gridlines = [];
102680
- const axisLabels = [];
102808
+ const gridlines = [], axisLabels = [];
102681
102809
  for (const val2 of axisTickValues(range)) {
102682
102810
  const y = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
102683
102811
  gridlines.push({
@@ -102737,9 +102865,7 @@ function buildLegend(series, colorPalette, svgWidth, legendPos, svgHeight, plotT
102737
102865
  color: seriesColor2(s, i, colorPalette),
102738
102866
  label: s.name
102739
102867
  }));
102740
- let legendX = svgWidth / 2;
102741
- let legendY = svgHeight - 8;
102742
- let legendAnchor = "middle";
102868
+ let legendX = svgWidth / 2, legendY = svgHeight - 8, legendAnchor = "middle";
102743
102869
  if (legendPos === "r") {
102744
102870
  legendX = svgWidth - 75;
102745
102871
  legendY = plotTop;
@@ -102754,19 +102880,10 @@ function buildLegend(series, colorPalette, svgWidth, legendPos, svgHeight, plotT
102754
102880
  return { legend, legendX, legendY, legendAnchor };
102755
102881
  }
102756
102882
  function computeBarRects(series, catCount, layout, range, colorPalette) {
102757
- const rects = [];
102758
- const seriesCount = Math.max(series.length, 1);
102759
- const barGroupWidth = layout.plotWidth / Math.max(catCount, 1);
102760
- const singleBarWidth = barGroupWidth * 0.7 / seriesCount;
102761
- 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;
102762
102884
  for (let ci = 0; ci < catCount; ci++) {
102763
102885
  for (let si = 0; si < series.length; si++) {
102764
- const val2 = series[si].values[ci] ?? 0;
102765
- const x = layout.plotLeft + barGroupWidth * ci + groupOffset + singleBarWidth * si;
102766
- const zeroY = valueToY2(0, range, layout.plotTop, layout.plotBottom);
102767
- const valY = valueToY2(val2, range, layout.plotTop, layout.plotBottom);
102768
- const y = Math.min(zeroY, valY);
102769
- 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);
102770
102887
  rects.push({
102771
102888
  x,
102772
102889
  y,
@@ -102779,20 +102896,15 @@ function computeBarRects(series, catCount, layout, range, colorPalette) {
102779
102896
  return rects;
102780
102897
  }
102781
102898
  function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
102782
- const rects = [];
102783
- const barW = layout.plotWidth / Math.max(catCount, 1) * 0.7;
102784
- const barOffset = (layout.plotWidth / Math.max(catCount, 1) - barW) / 2;
102785
- 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);
102786
102900
  for (let ci = 0; ci < catCount; ci++) {
102787
- let posTop = zeroY;
102788
- let negBottom = zeroY;
102901
+ let posTop = zeroY, negBottom = zeroY;
102789
102902
  for (let si = 0; si < series.length; si++) {
102790
102903
  const val2 = series[si].values[ci] ?? 0;
102791
102904
  if (val2 === 0) {
102792
102905
  continue;
102793
102906
  }
102794
- const x = layout.plotLeft + layout.plotWidth / Math.max(catCount, 1) * ci + barOffset;
102795
- const h = Math.max(
102907
+ const x = layout.plotLeft + layout.plotWidth / Math.max(catCount, 1) * ci + barOffset, h = Math.max(
102796
102908
  Math.abs(
102797
102909
  valueToY2(val2, range, layout.plotTop, layout.plotBottom) - valueToY2(0, range, layout.plotTop, layout.plotBottom)
102798
102910
  ),
@@ -102830,9 +102942,7 @@ function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
102830
102942
  function computeLinePoints(values, catCount, layout, range) {
102831
102943
  const n = Math.max(catCount, 2);
102832
102944
  return values.map((val2, i) => {
102833
- const nx = n > 1 ? i / (n - 1) : 0;
102834
- const x = layout.plotLeft + layout.plotWidth * nx;
102835
- 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);
102836
102946
  return { x, y };
102837
102947
  });
102838
102948
  }
@@ -102840,49 +102950,30 @@ function linePointsToSvgString(points3) {
102840
102950
  return points3.map((p) => `${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(" ");
102841
102951
  }
102842
102952
  function computePieSlicePath(cx, cy, outerR, innerR, startAngle, endAngle) {
102843
- const largeArc = endAngle - startAngle > Math.PI ? 1 : 0;
102844
- const x1 = cx + outerR * Math.cos(startAngle);
102845
- const y1 = cy + outerR * Math.sin(startAngle);
102846
- const x2 = cx + outerR * Math.cos(endAngle);
102847
- 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);
102848
102954
  let d;
102849
102955
  if (innerR > 0) {
102850
- const ix1 = cx + innerR * Math.cos(startAngle);
102851
- const iy1 = cy + innerR * Math.sin(startAngle);
102852
- const ix2 = cx + innerR * Math.cos(endAngle);
102853
- 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);
102854
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`;
102855
102958
  } else {
102856
102959
  d = `M${cx},${cy} L${x1},${y1} A${outerR},${outerR} 0 ${largeArc} 1 ${x2},${y2} Z`;
102857
102960
  }
102858
- const midAngle = (startAngle + endAngle) / 2;
102859
- const labelR = outerR * 0.7;
102860
- const labelX = cx + labelR * Math.cos(midAngle);
102861
- 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);
102862
102962
  return { d, midAngle, labelX, labelY };
102863
102963
  }
102864
102964
  function computePieLayout(elementWidth, elementHeight, chartData, isDoughnut) {
102865
- const size = Math.min(Math.max(elementWidth, 1), Math.max(elementHeight, 1));
102866
- const titleOffset = chartData.style?.hasTitle ? 20 : 0;
102867
- const legendOffset = chartData.style?.hasLegend ? 20 : 0;
102868
- const cx = size / 2;
102869
- const cy = titleOffset + (size - titleOffset - legendOffset) / 2;
102870
- const outerR = Math.max((size - titleOffset - legendOffset) * 0.42, 0);
102871
- const holeRatio = isDoughnut && chartData.doughnutHoleSize !== void 0 ? Math.min(Math.max(chartData.doughnutHoleSize, 10), 90) / 100 : 0.55;
102872
- 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;
102873
102966
  return { cx, cy, outerR, innerR, size };
102874
102967
  }
102875
102968
  function computePieSlices(values, cx, cy, outerR, innerR, options) {
102876
102969
  const total = values.reduce((s, v) => s + Math.abs(v), 0) || 1;
102877
102970
  let cumAngle = options?.startAngle ?? -Math.PI / 2;
102878
102971
  return values.map((val2, i) => {
102879
- const sliceAngle = Math.abs(val2) / total * Math.PI * 2;
102880
- const startAngle = cumAngle;
102972
+ const sliceAngle = Math.abs(val2) / total * Math.PI * 2, startAngle = cumAngle;
102881
102973
  cumAngle += sliceAngle;
102882
102974
  const explosion = options?.explosions?.[i] ?? 0;
102883
102975
  if (explosion > 0) {
102884
- const mid = (startAngle + cumAngle) / 2;
102885
- const offset = outerR * (explosion / 100);
102976
+ const mid = (startAngle + cumAngle) / 2, offset = outerR * (explosion / 100);
102886
102977
  return computePieSlicePath(
102887
102978
  cx + Math.cos(mid) * offset,
102888
102979
  cy + Math.sin(mid) * offset,
@@ -102911,9 +103002,7 @@ function computeScatterXDomain(seriesXValues2) {
102911
103002
  return { min, span: Math.max(Math.max(...finite2) - min, 1) };
102912
103003
  }
102913
103004
  function computeScatterDots(values, maxXIndex, layout, range, xValues, xDomain) {
102914
- const finiteX = xValues?.slice(0, values.length).filter(Number.isFinite);
102915
- const minX = xDomain ? xDomain.min : finiteX?.length ? Math.min(...finiteX) : 0;
102916
- 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;
102917
103006
  return values.map((val2, i) => ({
102918
103007
  cx: layout.plotLeft + (spanX > 0 ? (Number.isFinite(xValues?.[i]) ? xValues[i] - minX : i) / spanX : 0) * layout.plotWidth,
102919
103008
  cy: valueToY2(val2, range, layout.plotTop, layout.plotBottom)
@@ -102933,8 +103022,7 @@ function radarAngle(index, catCount) {
102933
103022
  function computeRadarPoints(values, maxVal, radius, cx, cy, catCount) {
102934
103023
  const denom = maxVal > 0 ? maxVal : 1;
102935
103024
  return values.slice(0, Math.max(catCount, 1)).map((val2, i) => {
102936
- const angle = radarAngle(i, catCount);
102937
- const r = Math.abs(val2) / denom * radius;
103025
+ const angle = radarAngle(i, catCount), r = Math.abs(val2) / denom * radius;
102938
103026
  return { x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) };
102939
103027
  });
102940
103028
  }
@@ -103001,18 +103089,15 @@ function buildChartViewModel(element) {
103001
103089
  if (element.type !== "chart") {
103002
103090
  return buildFallbackViewModel(element.width, element.height, "Chart");
103003
103091
  }
103004
- const chartEl = element;
103005
- const chartData = chartEl.chartData;
103092
+ const chartEl = element, chartData = chartEl.chartData;
103006
103093
  if (!chartData || chartData.series.length === 0) {
103007
103094
  return buildFallbackViewModel(element.width, element.height, chartData?.title ?? "Chart");
103008
103095
  }
103009
- const chartType = chartData.chartType ?? "bar";
103010
- const kind = resolveChartKind(chartType);
103096
+ const chartType = chartData.chartType ?? "bar", kind = resolveChartKind(chartType);
103011
103097
  if (kind === "unsupported") {
103012
103098
  return buildFallbackViewModel(element.width, element.height, chartData.title ?? chartType);
103013
103099
  }
103014
- const longestLen = chartData.series.reduce((m, s) => Math.max(m, s.values.length), 0);
103015
- 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));
103016
103101
  if (chartType === "ofPie") {
103017
103102
  return withChartAreaFill(
103018
103103
  withUserShapeOverlay(buildOfPieViewModel(element, chartData, categoryLabels), chartData),
@@ -103089,8 +103174,7 @@ function buildFlatViewModel(element, chartData, categoryLabels, kind) {
103089
103174
  return buildCartesianViewModel(element, chartData, categoryLabels, kind);
103090
103175
  }
103091
103176
  function buildFallbackViewModel(width, height, label) {
103092
- const svgWidth = Math.max(width, 1);
103093
- const svgHeight = Math.max(height, 1);
103177
+ const svgWidth = Math.max(width, 1), svgHeight = Math.max(height, 1);
103094
103178
  return {
103095
103179
  svgWidth,
103096
103180
  svgHeight,
@@ -103138,15 +103222,7 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
103138
103222
  element.height,
103139
103223
  chartData,
103140
103224
  isDoughnut
103141
- );
103142
- const svgWidth = Math.max(size, 100);
103143
- const svgHeight = Math.max(size, 60);
103144
- const pieSeries = chartData.series[0];
103145
- const values = pieSeries?.values ?? [];
103146
- const startAngle = -Math.PI / 2 + (chartData.firstSliceAngle ?? 0) * Math.PI / 180;
103147
- const explosions = pieSeries ? values.map((_v, i) => resolveDataPointExplosion(pieSeries, i)) : void 0;
103148
- const slices = computePieSlices(values, cx, cy, outerR, innerR, { startAngle, explosions });
103149
- 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(
103150
103226
  ({ d }, i) => ({
103151
103227
  kind: "path",
103152
103228
  d,
@@ -103155,13 +103231,17 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
103155
103231
  fill: pieSeries ? resolveVaryColorFill(pieSeries, i, paletteColor2(i, chartData.colorPalette)) : paletteColor2(i, chartData.colorPalette),
103156
103232
  stroke: "#ffffff",
103157
103233
  strokeWidth: 1.5,
103158
- 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
+ )
103159
103241
  })
103160
- );
103161
- const dataLabels = [];
103242
+ ), dataLabels = [];
103162
103243
  if (chartData.style?.hasDataLabels) {
103163
- const percentBase = values.reduce((total, entry2) => total + Math.abs(entry2), 0);
103164
- const labelResult = buildPieDataLabels({
103244
+ const percentBase = values.reduce((total, entry2) => total + Math.abs(entry2), 0), labelResult = buildPieDataLabels({
103165
103245
  slices,
103166
103246
  values,
103167
103247
  cx,
@@ -103181,12 +103261,10 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
103181
103261
  dataLabels.push(...labelResult.labels);
103182
103262
  primitives.push(...labelResult.leaderLines);
103183
103263
  }
103184
- const legendPos = chartData.style?.legendPosition ?? "b";
103185
- const legend = categoryLabels.map((label, i) => ({
103264
+ const legendPos = chartData.style?.legendPosition ?? "b", legend = categoryLabels.map((label, i) => ({
103186
103265
  color: pieSeries ? resolveVaryColorFill(pieSeries, i, paletteColor2(i, chartData.colorPalette)) : paletteColor2(i, chartData.colorPalette),
103187
103266
  label
103188
- }));
103189
- const legendX = svgWidth / 2;
103267
+ })), legendX = svgWidth / 2;
103190
103268
  let legendY = svgHeight - 8;
103191
103269
  const legendAnchor = "middle";
103192
103270
  if (legendPos === "t") {
@@ -103216,14 +103294,7 @@ var RADAR_RING_COLOR = "#cbd5e1";
103216
103294
  var RADAR_SPOKE_COLOR = "#94a3b8";
103217
103295
  var RADAR_LABEL_COLOR = "#64748b";
103218
103296
  function buildRadarViewModel(element, chartData, categoryLabels) {
103219
- const layout = computePlotLayout(element.width, element.height, chartData, false);
103220
- const cx = layout.plotLeft + layout.plotWidth / 2;
103221
- const cy = layout.plotTop + layout.plotHeight / 2;
103222
- const radius = Math.max(Math.min(layout.plotWidth, layout.plotHeight) / 2 - 4, 1);
103223
- const catCount = Math.max(categoryLabels.length, 1);
103224
- const maxVal = Math.max(1, ...chartData.series.flatMap((s) => s.values.map((v) => Math.abs(v))));
103225
- const primitives = [];
103226
- 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 = [];
103227
103298
  for (let r = 1; r <= RADAR_RINGS; r++) {
103228
103299
  const rr = radius * r / RADAR_RINGS;
103229
103300
  primitives.push({
@@ -103260,8 +103331,7 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103260
103331
  }
103261
103332
  const dataLabels = [];
103262
103333
  chartData.series.forEach((series, si) => {
103263
- const c = seriesColor2(series, si, chartData.colorPalette);
103264
- 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);
103265
103335
  if (pts.length === 0) {
103266
103336
  return;
103267
103337
  }
@@ -103273,7 +103343,8 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103273
103343
  opacity: 0.2,
103274
103344
  stroke: c,
103275
103345
  strokeWidth: 1.5,
103276
- part: { role: "series", seriesIndex: si }
103346
+ part: { role: "series", seriesIndex: si },
103347
+ title: series.name.length > 0 ? series.name : void 0
103277
103348
  });
103278
103349
  pts.forEach((p, vi) => {
103279
103350
  primitives.push({
@@ -103282,7 +103353,13 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103282
103353
  cy: p.y,
103283
103354
  r: 3,
103284
103355
  fill: c,
103285
- 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
+ )
103286
103363
  });
103287
103364
  });
103288
103365
  if (chartData.style?.hasDataLabels) {
@@ -103303,16 +103380,14 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
103303
103380
  });
103304
103381
  }
103305
103382
  });
103306
- const legendPos = chartData.style?.legendPosition ?? "b";
103307
- const { legend, legendX, legendY, legendAnchor } = buildLegend(
103383
+ const legendPos = chartData.style?.legendPosition ?? "b", { legend, legendX, legendY, legendAnchor } = buildLegend(
103308
103384
  chartData.series,
103309
103385
  chartData.colorPalette,
103310
103386
  layout.svgWidth,
103311
103387
  legendPos,
103312
103388
  layout.svgHeight,
103313
103389
  layout.plotTop
103314
- );
103315
- const title = chartData.style?.hasTitle && chartData.title ? chartData.title : void 0;
103390
+ ), title = chartData.style?.hasTitle && chartData.title ? chartData.title : void 0;
103316
103391
  return {
103317
103392
  svgWidth: layout.svgWidth,
103318
103393
  svgHeight: layout.svgHeight,
@@ -103871,6 +103946,31 @@ var DIRECTIONAL_PRESETS = /* @__PURE__ */ new Set([
103871
103946
  "floatIn",
103872
103947
  "peekIn"
103873
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
+ }
103874
103974
  function animationPresetLabelKey(preset) {
103875
103975
  return `pptx.animation.preset.${preset}`;
103876
103976
  }
@@ -107474,9 +107574,9 @@ function rgbToHex4(r, g, b) {
107474
107574
  function tintColor(hex4, tintFactor) {
107475
107575
  const { r, g, b } = hexToRgb4(hex4);
107476
107576
  return rgbToHex4(
107477
- r + (255 - r) * tintFactor,
107478
- g + (255 - g) * tintFactor,
107479
- b + (255 - b) * tintFactor
107577
+ 255 - (255 - r) * tintFactor,
107578
+ 255 - (255 - g) * tintFactor,
107579
+ 255 - (255 - b) * tintFactor
107480
107580
  );
107481
107581
  }
107482
107582
  function shadeColor(hex4, shadeFactor) {
@@ -107548,12 +107648,10 @@ function applyStyleFill(fill, colorScheme, css, fallback) {
107548
107648
  const fg = normalizeHexColor(
107549
107649
  resolveStyleFillColor(fill.pattern.foreground, colorScheme),
107550
107650
  "#000000"
107551
- );
107552
- const bg = normalizeHexColor(
107651
+ ), bg = normalizeHexColor(
107553
107652
  resolveStyleFillColor(fill.pattern.background, colorScheme),
107554
107653
  "#ffffff"
107555
- );
107556
- const svg = getPatternSvg(fill.pattern.preset, fg, bg);
107654
+ ), svg = getPatternSvg(fill.pattern.preset, fg, bg);
107557
107655
  clearBackground(css);
107558
107656
  if (svg) {
107559
107657
  css.backgroundImage = `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;
@@ -107638,11 +107736,7 @@ var BEVEL_LIGHT_OFFSETS = {
107638
107736
  l: { x: 1, y: 0 }
107639
107737
  };
107640
107738
  function cell3DBevelCss(cell3D) {
107641
- const size = Math.max(cell3D.bevelHeight ?? cell3D.bevelWidth ?? 4, 1);
107642
- const dir = cell3D.lightRigDirection ?? "tl";
107643
- const off = BEVEL_LIGHT_OFFSETS[dir] ?? BEVEL_LIGHT_OFFSETS.tl;
107644
- const highlight = `inset ${off.x * size}px ${off.y * size}px ${size}px rgba(255,255,255,0.55)`;
107645
- const shadow = `inset ${-off.x * size}px ${-off.y * size}px ${size}px rgba(0,0,0,0.4)`;
107739
+ const size = Math.max(cell3D.bevelHeight ?? cell3D.bevelWidth ?? 4, 1), dir = cell3D.lightRigDirection ?? "tl", off = BEVEL_LIGHT_OFFSETS[dir] ?? BEVEL_LIGHT_OFFSETS.tl, highlight = `inset ${off.x * size}px ${off.y * size}px ${size}px rgba(255,255,255,0.55)`, shadow = `inset ${-off.x * size}px ${-off.y * size}px ${size}px rgba(0,0,0,0.4)`;
107646
107740
  return { boxShadow: `${highlight}, ${shadow}` };
107647
107741
  }
107648
107742
  function cellRunStyle(run) {
@@ -108747,6 +108841,23 @@ var TABLE_STYLE_PRESETS = [
108747
108841
  borderColor: "#548235"
108748
108842
  }
108749
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
+ }
108750
108861
  var SEL = "bg-muted border border-border rounded px-2 py-1 text-[11px] w-full";
108751
108862
  var NUM = "flex-1 bg-muted border border-border rounded px-1.5 py-0.5 w-full text-[11px]";
108752
108863
  var LBL = "text-muted-foreground text-[11px]";
@@ -108765,6 +108876,7 @@ var PATTERN_OPTIONS = OOXML_PATTERN_PRESETS.slice(0, 20);
108765
108876
  var MIN_COLUMN_PROPORTION = 0.03;
108766
108877
  var MIN_ROW_HEIGHT = 16;
108767
108878
  var DEFAULT_ROW_HEIGHT = 32;
108879
+ var MIN_COLUMN_WIDTH_FRACTION = 0.05;
108768
108880
  function computeColumnBoundaries(columnWidths) {
108769
108881
  const result = [];
108770
108882
  let cumulative = 0;
@@ -108793,6 +108905,39 @@ function computeResizedColumnWidths(initialWidths, index, deltaProportion) {
108793
108905
  function computeResizedRowHeight(initialRowHeight, deltaY) {
108794
108906
  return Math.round(Math.max(MIN_ROW_HEIGHT, initialRowHeight + deltaY));
108795
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
+ }
108796
108941
  function findSmartArtNodeText(data, nodeId) {
108797
108942
  return data.nodes.find((n) => n.id === nodeId)?.text;
108798
108943
  }
@@ -109167,7 +109312,7 @@ function getImageFitStyle(el) {
109167
109312
  const uncropped = {
109168
109313
  width: "100%",
109169
109314
  height: "100%",
109170
- objectFit: "cover"
109315
+ objectFit: "fill"
109171
109316
  };
109172
109317
  if (!isImageLikeElement(el)) {
109173
109318
  return uncropped;
@@ -111717,6 +111862,8 @@ var translationsEn = {
111717
111862
  "pptx.ribbon.customColour": "Custom colour...",
111718
111863
  "pptx.ribbon.textHighlightColour": "Text highlight colour",
111719
111864
  "pptx.ribbon.highlightColourValue": "Highlight colour {{color}}",
111865
+ "pptx.ribbon.fillColourValue": "Fill colour {{color}}",
111866
+ "pptx.ribbon.outlineColourValue": "Outline colour {{color}}",
111720
111867
  "pptx.ribbon.bulletList": "Bullet list",
111721
111868
  "pptx.ribbon.justify": "Justify",
111722
111869
  "pptx.toolbar.findAndReplace": "Find and replace",
@@ -124724,6 +124871,102 @@ function buildSmartArtA11y(data) {
124724
124871
  nodes
124725
124872
  };
124726
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
+ }
124727
124970
  var THREE_UNAVAILABLE = {
124728
124971
  ok: false,
124729
124972
  resize: () => {
@@ -129162,6 +129405,17 @@ function resolveInkWidth(widths, index, fallback = 3) {
129162
129405
  }
129163
129406
  return widths[index] > 0 ? widths[index] : fallback;
129164
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
+ }
129165
129419
  var COMMENT_MENTION_ATTRIBUTE = "data-pptx-comment-mention";
129166
129420
  var COMMENT_MENTION_CLASS = "pptx-comment-mention";
129167
129421
  var usableMentions = (body, mentions) => (mentions ?? []).filter(
@@ -130610,7 +130864,7 @@ var WEIGHT_SUFFIXES = [
130610
130864
  [/black|heavy/iu, "900"],
130611
130865
  [/bold/iu, "700"]
130612
130866
  ];
130613
- var STYLE_TOKEN = /[-_\s]*(?:thin|hairline|extralight|ultralight|light|regular|normal|book|medium|semibold|demibold|extrabold|ultrabold|black|heavy|bold|italic|oblique)+$/giu;
130867
+ var STYLE_TOKEN = /[-_\s]*(?:thin|hairline|extralight|ultralight|light|regular|normal|book|medium|semibold|demibold|extrabold|ultrabold|black|heavy|bold|italic|oblique)$/giu;
130614
130868
  function deriveCustomFontDescriptor(fileName) {
130615
130869
  const stem = fileName.replace(/\.[^.]+$/u, "");
130616
130870
  const italic = /(?:italic|oblique)(?![a-z])/iu.test(stem);
@@ -132638,8 +132892,7 @@ function sanitizeDownloadFilename(input) {
132638
132892
  return cleaned;
132639
132893
  }
132640
132894
  function downloadBlob(blob, filename) {
132641
- const url = URL.createObjectURL(blob);
132642
- const anchor = document.createElement("a");
132895
+ const url = URL.createObjectURL(blob), anchor = document.createElement("a");
132643
132896
  anchor.href = url;
132644
132897
  anchor.download = filename;
132645
132898
  document.body.appendChild(anchor);
@@ -132664,13 +132917,10 @@ function dataUrlToBlob(dataUrl) {
132664
132917
  if (!match?.groups) {
132665
132918
  return void 0;
132666
132919
  }
132667
- const mime = match.groups.mime || "application/octet-stream";
132668
- const isBase64 = Boolean(match.groups.base64);
132669
- const payload = match.groups.payload ?? "";
132920
+ const mime = match.groups.mime || "application/octet-stream", isBase64 = Boolean(match.groups.base64), payload = match.groups.payload ?? "";
132670
132921
  try {
132671
132922
  if (isBase64) {
132672
- const binary = atob(payload);
132673
- const bytes = new Uint8Array(binary.length);
132923
+ const binary = atob(payload), bytes = new Uint8Array(binary.length);
132674
132924
  for (let i = 0; i < binary.length; i++) {
132675
132925
  bytes[i] = binary.charCodeAt(i);
132676
132926
  }
@@ -132682,9 +132932,7 @@ function dataUrlToBlob(dataUrl) {
132682
132932
  }
132683
132933
  }
132684
132934
  function openUrlInNewTab(url) {
132685
- const blob = url.startsWith("data:") ? dataUrlToBlob(url) : void 0;
132686
- const target = blob ? URL.createObjectURL(blob) : url;
132687
- 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");
132688
132936
  if (opened) {
132689
132937
  try {
132690
132938
  opened.opener = null;
@@ -134395,7 +134643,7 @@ exports.addChartCategory = addChartCategory;
134395
134643
  exports.addChartSeries = addChartSeries;
134396
134644
  exports.addQuickAccessCommand = addQuickAccessCommand;
134397
134645
  exports.addSection = addSection;
134398
- exports.addSmartArtNode = addSmartArtNode;
134646
+ exports.addSiblingAfter = addSiblingAfter;
134399
134647
  exports.addSmartArtNodeAsChild = addSmartArtNodeAsChild;
134400
134648
  exports.addTagToCollections = addTagToCollections;
134401
134649
  exports.alignElements = alignElements;
@@ -134421,6 +134669,7 @@ exports.applyRehearsalTimings = applyRehearsalTimings;
134421
134669
  exports.applyReroutedConnectors = applyReroutedConnectors;
134422
134670
  exports.applyResize = applyResize;
134423
134671
  exports.applyStyleToSelectedSegments = applyStyleToSelectedSegments;
134672
+ exports.applyTableStylePreset = applyTableStylePreset;
134424
134673
  exports.applyThemeOverrideToSlide = applyThemeOverrideToSlide;
134425
134674
  exports.applyThemeToData = applyThemeToData;
134426
134675
  exports.attachPresentationVisibilityPause = attachPresentationVisibilityPause;
@@ -134433,6 +134682,8 @@ exports.bringForward = bringForward;
134433
134682
  exports.bringToFront = bringToFront;
134434
134683
  exports.build3DExtrusionData = build3DExtrusionData;
134435
134684
  exports.buildActiveSessionUsers = buildActiveSessionUsers;
134685
+ exports.buildAnimationTimelineBars = buildAnimationTimelineBars;
134686
+ exports.buildBarActions = buildBarActions;
134436
134687
  exports.buildBroadcastViewerUrl = buildBroadcastViewerUrl;
134437
134688
  exports.buildCacheKey = buildCacheKey;
134438
134689
  exports.buildCalloutLeaderLineSvgPath = buildCalloutLeaderLineSvgPath;
@@ -134483,10 +134734,12 @@ exports.buildTextBuildSpec = buildTextBuildSpec;
134483
134734
  exports.buildThemeColorGrid = buildThemeColorGrid;
134484
134735
  exports.buildThemeColorMap = buildThemeColorMap;
134485
134736
  exports.buildUserFontFaceStyles = buildUserFontFaceStyles;
134737
+ exports.canAddTopLevelNode = canAddTopLevelNode;
134486
134738
  exports.canCommitActionType = canCommitActionType;
134487
134739
  exports.canGoNext = canGoNext;
134488
134740
  exports.canGoPrevious = canGoPrevious;
134489
134741
  exports.canInteractWithElement = canInteractWithElement;
134742
+ exports.canRemoveTopLevelNode = canRemoveTopLevelNode;
134490
134743
  exports.canvasToJpegData = canvasToJpegData;
134491
134744
  exports.cellRunStyle = cellRunStyle;
134492
134745
  exports.cellStyleToCss = cellStyleToCss;
@@ -134501,6 +134754,7 @@ exports.clampSorterZoom = clampSorterZoom;
134501
134754
  exports.clampTransitionNumber = clampTransitionNumber;
134502
134755
  exports.clampUnitInterval = clampUnitInterval2;
134503
134756
  exports.clampZoomScale = clampZoomScale;
134757
+ exports.classifyExtraConnections = classifyExtraConnections;
134504
134758
  exports.clearAllLocalViewerData = clearAllLocalViewerData;
134505
134759
  exports.clearAudienceContent = clearAudienceContent;
134506
134760
  exports.clearLocalAwareness = clearLocalAwareness;
@@ -134520,6 +134774,7 @@ exports.comparePresentation = comparePresentation;
134520
134774
  exports.compileEquationTemplateMathMl = compileEquationTemplateMathMl;
134521
134775
  exports.compileLatexEquation = compileLatexEquation;
134522
134776
  exports.computeAllNotesPages = computeAllNotesPages;
134777
+ exports.computeChartLegendLayout = computeChartLegendLayout;
134523
134778
  exports.computeColumnBoundaries = computeColumnBoundaries;
134524
134779
  exports.computeDrawingViewBox = computeDrawingViewBox;
134525
134780
  exports.computeEntranceAnimationDelay = computeEntranceAnimationDelay;
@@ -134567,9 +134822,10 @@ exports.deleteSection = deleteSection;
134567
134822
  exports.deleteTableColumn = deleteTableColumn;
134568
134823
  exports.deleteTableRow = deleteTableRow;
134569
134824
  exports.deleteTagFromCollections = deleteTagFromCollections;
134570
- exports.demoteSmartArtNode = demoteSmartArtNode;
134825
+ exports.demote = demote;
134571
134826
  exports.deriveSlideFieldContext = deriveSlideFieldContext;
134572
134827
  exports.describeFontEmbedding = describeFontEmbedding;
134828
+ exports.describeSmartArtBounds = describeSmartArtBounds;
134573
134829
  exports.detectOrientation = detectOrientation;
134574
134830
  exports.detectTouchDevice = detectTouchDevice;
134575
134831
  exports.discardAutosaveRecovery = discardAutosaveRecovery;
@@ -134587,6 +134843,8 @@ exports.ensureActionAffordanceStyles = ensureActionAffordanceStyles;
134587
134843
  exports.ensureChartInteractionStyles = ensureChartInteractionStyles;
134588
134844
  exports.erasePresentationInkAt = erasePresentationInkAt;
134589
134845
  exports.escapeHtml2 = escapeHtml22;
134846
+ exports.evenColumnWidths = evenColumnWidths;
134847
+ exports.evenRowHeights = evenRowHeights;
134590
134848
  exports.exportDeckJson = exportDeckJson;
134591
134849
  exports.extraQuickAccessCommands = extraQuickAccessCommands;
134592
134850
  exports.extractPathPoints = extractPathPoints;
@@ -134810,7 +135068,7 @@ exports.printPropertiesFrameSlides = printPropertiesFrameSlides;
134810
135068
  exports.printPropertiesSlidesPerPage = printPropertiesSlidesPerPage;
134811
135069
  exports.probeAutosaveRecovery = probeAutosaveRecovery;
134812
135070
  exports.projectDrawingShapes = projectDrawingShapes;
134813
- exports.promoteSmartArtNode = promoteSmartArtNode;
135071
+ exports.promote = promote;
134814
135072
  exports.publishLiveGeometry = publishLiveGeometry;
134815
135073
  exports.publishLiveInlineText = publishLiveInlineText;
134816
135074
  exports.quickStyleSwatchCss = quickStyleSwatchCss;
@@ -134827,6 +135085,7 @@ exports.rebuildTableStructureInRawXml = rebuildTableStructureInRawXml;
134827
135085
  exports.reconcileSlidesInYDoc = reconcileSlidesInYDoc;
134828
135086
  exports.recordProgressPercent = recordProgressPercent;
134829
135087
  exports.rectToCells = rectToCells;
135088
+ exports.redistributeColumnWidth = redistributeColumnWidth;
134830
135089
  exports.registerCollaborationTeardown = registerCollaborationTeardown;
134831
135090
  exports.registerCustomFont = registerCustomFont;
134832
135091
  exports.registerPersistentAudio = registerPersistentAudio;
@@ -134834,6 +135093,7 @@ exports.remapTextToSegments = remapTextToSegments;
134834
135093
  exports.rememberSessionDeck = rememberSessionDeck;
134835
135094
  exports.removeChartCategory = removeChartCategory;
134836
135095
  exports.removeChartSeries = removeChartSeries;
135096
+ exports.removeEmptyNode = removeEmptyNode;
134837
135097
  exports.removeLastTableElementColumn = removeLastTableElementColumn;
134838
135098
  exports.removeLastTableElementRow = removeLastTableElementRow;
134839
135099
  exports.removeQuickAccessCommand = removeQuickAccessCommand;
@@ -134841,7 +135101,8 @@ exports.removeSmartArtNode = removeSmartArtNode;
134841
135101
  exports.removeTableElementColumn = removeTableElementColumn;
134842
135102
  exports.removeTableElementRow = removeTableElementRow;
134843
135103
  exports.renameSection = renameSection;
134844
- exports.reorderSmartArtNode = reorderSmartArtNode;
135104
+ exports.reorder = reorder2;
135105
+ exports.reorderAnimationTo = reorderAnimationTo;
134845
135106
  exports.replaceMasterViewElements = replaceMasterViewElements;
134846
135107
  exports.rerouteConnectorsForMovedElements = rerouteConnectorsForMovedElements;
134847
135108
  exports.resetPresenterTimer = resetPresenterTimer;
@@ -134935,6 +135196,8 @@ exports.shouldRoomSlidesReplaceLoad = shouldRoomSlidesReplaceLoad;
134935
135196
  exports.shouldShowAutosaveRecoveryPrompt = shouldShowAutosaveRecoveryPrompt;
134936
135197
  exports.shouldUseSvgWarp = shouldUseSvgWarp;
134937
135198
  exports.shouldWriteAutosaveSnapshot = shouldWriteAutosaveSnapshot;
135199
+ exports.siblingCount = siblingCount;
135200
+ exports.siblingIndex = siblingIndex;
134938
135201
  exports.slideProgressPercent = slideProgressPercent;
134939
135202
  exports.slideShowOptionChange = slideShowOptionChange;
134940
135203
  exports.slideSizeFromPreset = slideSizeFromPreset;