pptx-react-viewer 2.18.0 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +701 -0
  2. package/dist/{AiChatPanel-UN5DHPZY.js → AiChatPanel-2GBJETOY.js} +24 -24
  3. package/dist/AiChatPanel-2GBJETOY.js.br +0 -0
  4. package/dist/AiChatPanel-2GBJETOY.js.gz +0 -0
  5. package/dist/{AiChatPanel-SSSBERWJ.mjs → AiChatPanel-FZUKTQPQ.mjs} +4 -4
  6. package/dist/AiChatPanel-FZUKTQPQ.mjs.br +0 -0
  7. package/dist/AiChatPanel-FZUKTQPQ.mjs.gz +0 -0
  8. package/dist/{Model3DScene-4RPYKC2I.js → Model3DScene-JHTI2AQ6.js} +2 -2
  9. package/dist/Model3DScene-JHTI2AQ6.js.br +0 -0
  10. package/dist/Model3DScene-JHTI2AQ6.js.gz +0 -0
  11. package/dist/{Model3DScene-LYEESYAI.mjs → Model3DScene-WRRQSYAZ.mjs} +1 -1
  12. package/dist/Model3DScene-WRRQSYAZ.mjs.br +0 -0
  13. package/dist/Model3DScene-WRRQSYAZ.mjs.gz +0 -0
  14. package/dist/{PowerPointViewer-Cf4YHjdF.d.ts → PowerPointViewer-DVFkeluD.d.ts} +2 -2
  15. package/dist/PowerPointViewer-DVFkeluD.d.ts.map +1 -0
  16. package/dist/{audience-content-store-CyS0oP6t.d.ts → audience-content-store-ChVOSdBh.d.ts} +2 -2
  17. package/dist/{audience-content-store-CyS0oP6t.d.ts.map → audience-content-store-ChVOSdBh.d.ts.map} +1 -1
  18. package/dist/{chunk-WVDM36ZM.js → chunk-7ARD2J6Y.js} +1096 -1033
  19. package/dist/chunk-7ARD2J6Y.js.br +0 -0
  20. package/dist/chunk-7ARD2J6Y.js.gz +0 -0
  21. package/dist/{chunk-QUB5OSKY.mjs → chunk-BO373PYH.mjs} +70 -115
  22. package/dist/chunk-BO373PYH.mjs.br +0 -0
  23. package/dist/chunk-BO373PYH.mjs.gz +0 -0
  24. package/dist/{chunk-ASKYZ5ZY.js → chunk-IRLOXBO7.js} +439 -484
  25. package/dist/chunk-IRLOXBO7.js.br +0 -0
  26. package/dist/chunk-IRLOXBO7.js.gz +0 -0
  27. package/dist/{chunk-RTUGI4HQ.js → chunk-MVKRI3CZ.js} +9 -0
  28. package/dist/chunk-MVKRI3CZ.js.br +0 -0
  29. package/dist/chunk-MVKRI3CZ.js.gz +0 -0
  30. package/dist/{chunk-BZOL6FXF.mjs → chunk-MWEBCWVD.mjs} +16 -2270
  31. package/dist/chunk-MWEBCWVD.mjs.br +0 -0
  32. package/dist/chunk-MWEBCWVD.mjs.gz +0 -0
  33. package/dist/{chunk-ICZDMFF2.js → chunk-NFFV3RDS.js} +1219 -1101
  34. package/dist/chunk-NFFV3RDS.js.br +0 -0
  35. package/dist/chunk-NFFV3RDS.js.gz +0 -0
  36. package/dist/{chunk-4LWGAVAP.js → chunk-OVPJT4EQ.js} +162 -2416
  37. package/dist/chunk-OVPJT4EQ.js.br +0 -0
  38. package/dist/chunk-OVPJT4EQ.js.gz +0 -0
  39. package/dist/{chunk-MAVLV56S.js → chunk-RPJ2BIQ7.js} +3 -3
  40. package/dist/chunk-RPJ2BIQ7.js.br +0 -0
  41. package/dist/chunk-RPJ2BIQ7.js.gz +0 -0
  42. package/dist/{chunk-SNL6LBRX.mjs → chunk-SQJBFMEX.mjs} +9 -0
  43. package/dist/chunk-SQJBFMEX.mjs.br +0 -0
  44. package/dist/chunk-SQJBFMEX.mjs.gz +0 -0
  45. package/dist/{chunk-GODW6RNR.mjs → chunk-XF3EOHY2.mjs} +1087 -1017
  46. package/dist/chunk-XF3EOHY2.mjs.br +0 -0
  47. package/dist/chunk-XF3EOHY2.mjs.gz +0 -0
  48. package/dist/{chunk-O7FTUUXP.mjs → chunk-YWJBD7KV.mjs} +210 -92
  49. package/dist/chunk-YWJBD7KV.mjs.br +0 -0
  50. package/dist/chunk-YWJBD7KV.mjs.gz +0 -0
  51. package/dist/{chunk-7XF6S4AM.mjs → chunk-ZMEYXAC6.mjs} +1 -1
  52. package/dist/chunk-ZMEYXAC6.mjs.br +0 -0
  53. package/dist/{chunk-7XF6S4AM.mjs.gz → chunk-ZMEYXAC6.mjs.gz} +0 -0
  54. package/dist/i18n.js +4 -4
  55. package/dist/i18n.js.br +0 -0
  56. package/dist/i18n.js.gz +0 -0
  57. package/dist/i18n.mjs +1 -1
  58. package/dist/i18n.mjs.br +0 -0
  59. package/dist/i18n.mjs.gz +0 -0
  60. package/dist/index.d.ts +38 -1
  61. package/dist/index.js +47 -47
  62. package/dist/index.js.br +0 -0
  63. package/dist/index.js.gz +0 -0
  64. package/dist/index.mjs +6 -6
  65. package/dist/index.mjs.br +0 -0
  66. package/dist/index.mjs.gz +0 -0
  67. package/dist/internals.d.ts +102 -15
  68. package/dist/internals.d.ts.map +1 -1
  69. package/dist/internals.js +79 -79
  70. package/dist/internals.js.br +0 -0
  71. package/dist/internals.js.gz +0 -0
  72. package/dist/internals.mjs +4 -4
  73. package/dist/internals.mjs.br +0 -0
  74. package/dist/internals.mjs.gz +0 -0
  75. package/dist/{types-C_CTI-QE.d.ts → types-TCH6icpi.d.ts} +23 -1
  76. package/dist/{types-C_CTI-QE.d.ts.map → types-TCH6icpi.d.ts.map} +1 -1
  77. package/dist/{useViewerBuildingBlocks-DItilDbP.d.ts → useViewerBuildingBlocks-BKb0qs1j.d.ts} +20 -4
  78. package/dist/{useViewerBuildingBlocks-DItilDbP.d.ts.map → useViewerBuildingBlocks-BKb0qs1j.d.ts.map} +1 -1
  79. package/dist/viewer/index.d.ts +38 -1
  80. package/dist/viewer/index.js +27 -27
  81. package/dist/viewer/index.js.br +0 -0
  82. package/dist/viewer/index.js.gz +0 -0
  83. package/dist/viewer/index.mjs +6 -6
  84. package/dist/viewer/index.mjs.br +0 -0
  85. package/dist/viewer/index.mjs.gz +0 -0
  86. package/package.json +1 -1
  87. package/dist/AiChatPanel-SSSBERWJ.mjs.br +0 -0
  88. package/dist/AiChatPanel-SSSBERWJ.mjs.gz +0 -0
  89. package/dist/AiChatPanel-UN5DHPZY.js.br +0 -0
  90. package/dist/AiChatPanel-UN5DHPZY.js.gz +0 -0
  91. package/dist/Model3DScene-4RPYKC2I.js.br +0 -0
  92. package/dist/Model3DScene-4RPYKC2I.js.gz +0 -0
  93. package/dist/Model3DScene-LYEESYAI.mjs.br +0 -0
  94. package/dist/Model3DScene-LYEESYAI.mjs.gz +0 -0
  95. package/dist/PowerPointViewer-Cf4YHjdF.d.ts.map +0 -1
  96. package/dist/SurfaceChart3DScene-ACPKCWLJ.js +0 -78
  97. package/dist/SurfaceChart3DScene-ACPKCWLJ.js.br +0 -0
  98. package/dist/SurfaceChart3DScene-ACPKCWLJ.js.gz +0 -0
  99. package/dist/SurfaceChart3DScene-JR62SOYO.mjs +0 -76
  100. package/dist/SurfaceChart3DScene-JR62SOYO.mjs.br +0 -0
  101. package/dist/SurfaceChart3DScene-JR62SOYO.mjs.gz +0 -0
  102. package/dist/chunk-4LWGAVAP.js.br +0 -0
  103. package/dist/chunk-4LWGAVAP.js.gz +0 -0
  104. package/dist/chunk-7XF6S4AM.mjs.br +0 -0
  105. package/dist/chunk-ASKYZ5ZY.js.br +0 -0
  106. package/dist/chunk-ASKYZ5ZY.js.gz +0 -0
  107. package/dist/chunk-BZOL6FXF.mjs.br +0 -0
  108. package/dist/chunk-BZOL6FXF.mjs.gz +0 -0
  109. package/dist/chunk-GODW6RNR.mjs.br +0 -0
  110. package/dist/chunk-GODW6RNR.mjs.gz +0 -0
  111. package/dist/chunk-ICZDMFF2.js.br +0 -0
  112. package/dist/chunk-ICZDMFF2.js.gz +0 -0
  113. package/dist/chunk-MAVLV56S.js.br +0 -0
  114. package/dist/chunk-MAVLV56S.js.gz +0 -0
  115. package/dist/chunk-O7FTUUXP.mjs.br +0 -0
  116. package/dist/chunk-O7FTUUXP.mjs.gz +0 -0
  117. package/dist/chunk-QUB5OSKY.mjs.br +0 -0
  118. package/dist/chunk-QUB5OSKY.mjs.gz +0 -0
  119. package/dist/chunk-RTUGI4HQ.js.br +0 -0
  120. package/dist/chunk-RTUGI4HQ.js.gz +0 -0
  121. package/dist/chunk-SNL6LBRX.mjs.br +0 -0
  122. package/dist/chunk-SNL6LBRX.mjs.gz +0 -0
  123. package/dist/chunk-WVDM36ZM.js.br +0 -0
  124. package/dist/chunk-WVDM36ZM.js.gz +0 -0
@@ -1,8 +1,8 @@
1
- import { translationsEn } from './chunk-SNL6LBRX.mjs';
2
- import { SHAPE_PRESET_DEFS, computeValueRangeForChart, VIEWER_SHORTCUT_REFERENCE, getAnimationInitialStyle, cloneHistorySnapshot, hasShapeProperties, getImageFitStyle, isImageLikeElement, getImageTilingStyle, runMediaCommand, findMediaElementByElementId, mediaPlaybackAttributes, buildTextBlockStyle, hasTextProperties, toCssWritingMode, toCssTextOrientation, toCssVerticalDirection, buildTextBodyLayoutStyle, buildTextBody3DSceneStyle, buildParagraphs, colorWithOpacity, normalizeHexColor, build3DExtrusionData, getComputedFillStyle, getComputedEffectStyle, getComputedStrokeStyle, isStrokeOnlyPresetElement, resolveShapeGeometry, normalizeStrokeDashType, getSvgStrokeDasharray, buildSvgGradientDef, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, svgLineCap, getCompoundLineOffsets, getCompoundLineWidths, computeSelectionRect, DEFAULT_FONT_FAMILY, cellStyleToCss, rectToCells, isCellInRect, tableContainerCss, buildChartViewModel, buildNotesPdfBytes, buildSlidesPdfBytes, buildPreviewAnimation, buildMotionPathPreview, getRoundRectRadiusPx2, getResolvedShapeClipPath, mediaFallbackVisual, registerPersistentAudio, resolveAutoFitFontScale, getSubstituteFontFamily, parsePanoseString, hasDistinctScriptFonts, pieceLetterSpacing, resolveMetricTrackingPx, TEXT_BUILD_ID_SEP, buildTextBuildSpec, textBuildSpanStyle, apply3dEffects, clampUnitInterval, customGeometryPathsToSvgSubpaths, svgGradientFillRef, computeColumnBoundaries, getTableCellBandStyle, parseDrawingColor, parseDrawingColorOpacity, getCellDiagonalBorders, cellRunStyle, getChartStylePalette, chartAreaFill, computeLayout, valueToY, formatAxisValue, computeLayoutOptions, splitSeriesByAxis, computeValueRange, getSecondaryValueAxis, seriesColor, paletteColor, resolveRegionCode, normalizeValue, sequentialColorScale, mediaFallbackIcon, mediaFallbackLabelKey, MEDIA_CHROME_ATTRIBUTE, convertOmmlToMathMl, sanitizeMathMl, tableCellCss, computeResizedColumnWidths, computeResizedRowHeight, DEFAULT_ROW_HEIGHT, ooxmlGradientAngleToCssDegrees, generateLogTicks, formatAxisValueWithUnits, getDisplayUnitLabel, splitRunForMetrics, hexToRgbChannels, chartPartToAttrs, segmentByScript, resolveFontForScript } from './chunk-GODW6RNR.mjs';
1
+ import { translationsEn } from './chunk-SQJBFMEX.mjs';
2
+ import { SHAPE_PRESET_DEFS, VIEWER_SHORTCUT_REFERENCE, getAnimationInitialStyle, cloneHistorySnapshot, hasShapeProperties, getImageFitStyle, isImageLikeElement, getImageTilingStyle, runMediaCommand, findMediaElementByElementId, mediaPlaybackAttributes, buildTextBlockStyle, hasTextProperties, toCssWritingMode, toCssTextOrientation, toCssVerticalDirection, buildTextBodyLayoutStyle, buildTextBody3DSceneStyle, buildParagraphs, colorWithOpacity, normalizeHexColor, build3DExtrusionData, getComputedFillStyle, getComputedEffectStyle, getComputedStrokeStyle, isStrokeOnlyPresetElement, resolveShapeGeometry, normalizeStrokeDashType, getSvgStrokeDasharray, buildSvgGradientDef, isCalloutShape, getCalloutLeaderLineGeometry, buildCalloutLeaderLineSvgPath, getCalloutViewBoxBounds, svgLineCap, getCompoundLineOffsets, getCompoundLineWidths, computeSelectionRect, DEFAULT_FONT_FAMILY, cellStyleToCss, rectToCells, isCellInRect, tableContainerCss, buildChartViewModel, resolveChartKind, chartPreserveAspectRatio, buildNotesPdfBytes, buildSlidesPdfBytes, buildPreviewAnimation, buildMotionPathPreview, getRoundRectRadiusPx2, getResolvedShapeClipPath, mediaFallbackVisual, registerPersistentAudio, resolveAutoFitFontScale, getSubstituteFontFamily, parsePanoseString, hasDistinctScriptFonts, pieceLetterSpacing, resolveMetricTrackingPx, TEXT_BUILD_ID_SEP, buildTextBuildSpec, textBuildSpanStyle, apply3dEffects, clampUnitInterval, customGeometryPathsToSvgSubpaths, svgGradientFillRef, computeColumnBoundaries, getTableCellBandStyle, parseDrawingColor, parseDrawingColorOpacity, getCellDiagonalBorders, cellRunStyle, getChartStylePalette, mediaFallbackIcon, mediaFallbackLabelKey, MEDIA_CHROME_ATTRIBUTE, convertOmmlToMathMl, sanitizeMathMl, tableCellCss, computeResizedColumnWidths, computeResizedRowHeight, DEFAULT_ROW_HEIGHT, ooxmlGradientAngleToCssDegrees, chartPartToAttrs, splitRunForMetrics, hexToRgbChannels, segmentByScript, resolveFontForScript } from './chunk-XF3EOHY2.mjs';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
- import React6, { useState, useEffect, useMemo, Suspense, useRef, useCallback, useLayoutEffect } from 'react';
5
+ import React6, { useRef, useState, useEffect, useCallback, useMemo, useLayoutEffect } from 'react';
6
6
  import { LuTriangle, LuPlus, LuMoveRight, LuMinus, LuDiamond, LuDatabase, LuCircle, LuSquare } from 'react-icons/lu';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import { useTranslation } from 'react-i18next';
@@ -3636,7 +3636,8 @@ function renderPrimitive(prim, key) {
3636
3636
  stroke: p.stroke ?? "none",
3637
3637
  strokeWidth: p.strokeWidth ?? 0,
3638
3638
  fillOpacity: p.opacity ?? 1,
3639
- ...partAttrs(p.part)
3639
+ ...partAttrs(p.part),
3640
+ children: p.title !== void 0 ? /* @__PURE__ */ jsx("title", { children: p.title }) : null
3640
3641
  },
3641
3642
  key
3642
3643
  );
@@ -3822,2277 +3823,22 @@ function renderChartViewModel(elementId, vm, preserveAspectRatio = "none") {
3822
3823
  }
3823
3824
  );
3824
3825
  }
3825
-
3826
- // src/viewer/utils/chart-area-line.tsx
3827
- function renderAreaChart(element, _chartData, _categoryLabels) {
3828
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
3829
- }
3830
- function renderLineChart(element, _chartData, _categoryLabels) {
3831
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
3832
- }
3833
- function renderBoxWhiskerChart(element, _chartData, _categoryLabels) {
3834
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
3835
- }
3836
- function renderHistogramChart(element, _chartData, _categoryLabels) {
3837
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
3838
- }
3839
- function renderDefaultBarChart(element, _chartData, _categoryLabels) {
3840
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
3841
- }
3842
- var WORLD_REGIONS = [
3843
- // North America
3844
- {
3845
- code: "US",
3846
- name: "United States",
3847
- path: "M130,160 L250,155 265,170 270,190 260,210 230,215 200,220 170,215 145,205 130,195Z M280,175 L295,165 310,170 310,185 295,195 280,190Z",
3848
- labelXY: [200, 190]
3849
- },
3850
- {
3851
- code: "CA",
3852
- name: "Canada",
3853
- path: "M120,90 L280,85 290,100 295,130 280,150 250,155 200,155 160,155 130,155 115,140 110,115Z",
3854
- labelXY: [200, 125]
3855
- },
3856
- {
3857
- code: "MX",
3858
- name: "Mexico",
3859
- path: "M145,215 L200,220 210,235 200,255 185,265 165,260 150,245 140,230Z",
3860
- labelXY: [175, 240]
3861
- },
3862
- // South America
3863
- {
3864
- code: "BR",
3865
- name: "Brazil",
3866
- path: "M270,300 L310,280 335,290 340,320 330,355 310,370 285,365 265,345 260,320Z",
3867
- labelXY: [300, 330]
3868
- },
3869
- {
3870
- code: "AR",
3871
- name: "Argentina",
3872
- path: "M260,370 L280,365 290,380 285,410 275,435 260,445 250,425 248,395Z",
3873
- labelXY: [268, 410]
3874
- },
3875
- // Europe
3876
- {
3877
- code: "GB",
3878
- name: "United Kingdom",
3879
- path: "M440,120 L448,110 455,115 455,135 448,142 440,138Z",
3880
- labelXY: [448, 128]
3881
- },
3882
- {
3883
- code: "FR",
3884
- name: "France",
3885
- path: "M450,145 L470,140 480,150 478,168 465,175 450,170 445,158Z",
3886
- labelXY: [463, 158]
3887
- },
3888
- {
3889
- code: "DE",
3890
- name: "Germany",
3891
- path: "M478,125 L498,120 505,130 502,148 490,152 478,148 475,138Z",
3892
- labelXY: [490, 138]
3893
- },
3894
- {
3895
- code: "IT",
3896
- name: "Italy",
3897
- path: "M490,155 L498,152 505,162 500,180 492,190 488,178 486,165Z",
3898
- labelXY: [495, 172]
3899
- },
3900
- {
3901
- code: "ES",
3902
- name: "Spain",
3903
- path: "M432,168 L460,165 465,175 460,188 442,192 430,185 428,175Z",
3904
- labelXY: [448, 180]
3905
- },
3906
- // Russia spans Europe/Asia
3907
- {
3908
- code: "RU",
3909
- name: "Russia",
3910
- path: "M510,60 L780,50 830,70 840,100 820,120 750,115 700,105 650,100 580,105 530,110 510,100 505,80Z",
3911
- labelXY: [670, 85]
3912
- },
3913
- {
3914
- code: "TR",
3915
- name: "Turkey",
3916
- path: "M530,165 L570,160 585,170 580,182 555,185 530,180Z",
3917
- labelXY: [558, 175]
3918
- },
3919
- // Africa
3920
- {
3921
- code: "EG",
3922
- name: "Egypt",
3923
- path: "M530,200 L555,195 565,205 560,225 545,230 530,222Z",
3924
- labelXY: [548, 215]
3925
- },
3926
- {
3927
- code: "NG",
3928
- name: "Nigeria",
3929
- path: "M475,275 L500,270 510,280 505,298 490,302 475,295Z",
3930
- labelXY: [492, 288]
3931
- },
3932
- {
3933
- code: "ZA",
3934
- name: "South Africa",
3935
- path: "M520,380 L545,370 560,380 555,400 540,410 520,405 515,392Z",
3936
- labelXY: [538, 392]
3937
- },
3938
- // Middle East
3939
- {
3940
- code: "SA",
3941
- name: "Saudi Arabia",
3942
- path: "M565,220 L600,210 615,225 610,250 590,258 570,250 560,238Z",
3943
- labelXY: [590, 238]
3944
- },
3945
- // Asia
3946
- {
3947
- code: "IN",
3948
- name: "India",
3949
- path: "M640,210 L665,195 685,210 688,240 678,268 660,278 645,265 635,240Z",
3950
- labelXY: [662, 240]
3951
- },
3952
- {
3953
- code: "CN",
3954
- name: "China",
3955
- path: "M700,120 L775,115 800,130 805,160 790,180 760,185 730,180 710,168 695,150 690,135Z",
3956
- labelXY: [750, 155]
3957
- },
3958
- {
3959
- code: "JP",
3960
- name: "Japan",
3961
- path: "M835,145 L845,135 852,140 850,158 842,165 835,160Z",
3962
- labelXY: [843, 152]
3963
- },
3964
- {
3965
- code: "KR",
3966
- name: "South Korea",
3967
- path: "M815,158 L825,152 830,160 827,170 818,172 813,165Z",
3968
- labelXY: [822, 163]
3969
- },
3970
- {
3971
- code: "ID",
3972
- name: "Indonesia",
3973
- path: "M740,295 L780,288 810,292 830,298 825,310 790,312 755,308 740,305Z",
3974
- labelXY: [785, 302]
3975
- },
3976
- // Oceania
3977
- {
3978
- code: "AU",
3979
- name: "Australia",
3980
- path: "M790,350 L850,340 880,355 885,385 870,405 840,410 810,400 790,380Z",
3981
- labelXY: [838, 378]
3982
- }
3983
- ];
3984
- function renderMapChart(element, chartData, categoryLabels) {
3985
- const svgWidth = element.width;
3986
- const svgHeight = element.height;
3987
- const categories = categoryLabels.length > 0 ? categoryLabels : chartData.categories;
3988
- const series = chartData.series;
3989
- const values = series.length > 0 ? series[0].values : [];
3990
- const finiteVals = values.filter((v) => Number.isFinite(v));
3991
- const minVal = finiteVals.length > 0 ? Math.min(...finiteVals) : 0;
3992
- const maxVal = finiteVals.length > 0 ? Math.max(...finiteVals) : 1;
3993
- const regionValueMap = /* @__PURE__ */ new Map();
3994
- const unmatchedRows = [];
3995
- categories.forEach((cat, i) => {
3996
- const value = values[i] ?? 0;
3997
- const code = resolveRegionCode(cat);
3998
- if (code) {
3999
- regionValueMap.set(code, { value, label: cat });
4000
- } else {
4001
- unmatchedRows.push({ label: cat, value });
4002
- }
4003
- });
4004
- const legendHeight = 30;
4005
- const fallbackRowH = 14;
4006
- const fallbackTableH = unmatchedRows.length > 0 ? Math.min(unmatchedRows.length + 1, 6) * fallbackRowH + 8 : 0;
4007
- const titleH = chartData.title ? 22 : 0;
4008
- const mapAreaH = Math.max(svgHeight - titleH - legendHeight - fallbackTableH - 8, 80);
4009
- const mapScale = Math.min((svgWidth - 20) / 1e3, mapAreaH / 500);
4010
- const mapOffsetX = (svgWidth - 1e3 * mapScale) / 2;
4011
- const mapOffsetY = titleH + 4;
4012
- const elements = [];
4013
- if (chartData.title) {
4014
- elements.push(
4015
- /* @__PURE__ */ jsx(
4016
- "text",
4017
- {
4018
- x: svgWidth / 2,
4019
- y: 16,
4020
- textAnchor: "middle",
4021
- fontSize: 12,
4022
- fontWeight: 700,
4023
- fill: "#334155",
4024
- children: chartData.title
4025
- },
4026
- `${element.id}-map-title`
4027
- )
4028
- );
3826
+ function renderChartElement(element) {
3827
+ if (element.type !== "chart") {
3828
+ return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: translationsEn["pptx.chart.heading"] });
4029
3829
  }
4030
- WORLD_REGIONS.forEach((region) => {
4031
- const entry = regionValueMap.get(region.code);
4032
- let fill = "#e2e8f0";
4033
- let dataLabel = null;
4034
- if (entry) {
4035
- const t = normalizeValue(entry.value, minVal, maxVal);
4036
- fill = sequentialColorScale(t);
4037
- dataLabel = /* @__PURE__ */ jsx(
4038
- "text",
4039
- {
4040
- x: region.labelXY[0] * mapScale + mapOffsetX,
4041
- y: region.labelXY[1] * mapScale + mapOffsetY + 4,
4042
- textAnchor: "middle",
4043
- fontSize: Math.max(6, 7 * mapScale),
4044
- fontWeight: 600,
4045
- fill: "#1e293b",
4046
- style: { pointerEvents: "none" },
4047
- children: formatAxisValue(entry.value)
4048
- },
4049
- `${element.id}-map-dl-${region.code}`
4050
- );
4051
- }
4052
- elements.push(
4053
- /* @__PURE__ */ jsxs("g", { children: [
4054
- /* @__PURE__ */ jsx(
4055
- "path",
4056
- {
4057
- d: region.path,
4058
- fill,
4059
- stroke: "#94a3b8",
4060
- strokeWidth: 0.5 / mapScale,
4061
- transform: `translate(${mapOffsetX},${mapOffsetY}) scale(${mapScale})`,
4062
- opacity: 0.9,
4063
- children: /* @__PURE__ */ jsxs("title", { children: [
4064
- region.name,
4065
- entry ? `: ${formatAxisValue(entry.value)}` : ""
4066
- ] })
4067
- }
4068
- ),
4069
- dataLabel
4070
- ] }, `${element.id}-map-g-${region.code}`)
4071
- );
4072
- });
4073
- const legendY = mapOffsetY + mapAreaH + 4;
4074
- const barW = Math.min(svgWidth * 0.4, 160);
4075
- const barX = (svgWidth - barW) / 2;
4076
- const gradId = `${element.id}-map-choropleth-grad`;
4077
- elements.push(
4078
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradId, x1: "0", y1: "0", x2: "1", y2: "0", children: [
4079
- /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#dbeafe" }),
4080
- /* @__PURE__ */ jsx("stop", { offset: "50%", stopColor: "#3b82f6" }),
4081
- /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#1e3a5f" })
4082
- ] }) }, `${element.id}-map-defs`),
4083
- /* @__PURE__ */ jsx(
4084
- "rect",
4085
- {
4086
- x: barX,
4087
- y: legendY,
4088
- width: barW,
4089
- height: 8,
4090
- rx: 4,
4091
- fill: `url(#${gradId})`
4092
- },
4093
- `${element.id}-map-legend-bar`
4094
- ),
4095
- /* @__PURE__ */ jsx(
4096
- "text",
4097
- {
4098
- x: barX,
4099
- y: legendY + 18,
4100
- fontSize: 7,
4101
- fill: "#64748b",
4102
- textAnchor: "middle",
4103
- children: formatAxisValue(minVal)
4104
- },
4105
- `${element.id}-map-legend-min`
4106
- ),
4107
- /* @__PURE__ */ jsx(
4108
- "text",
4109
- {
4110
- x: barX + barW,
4111
- y: legendY + 18,
4112
- fontSize: 7,
4113
- fill: "#64748b",
4114
- textAnchor: "middle",
4115
- children: formatAxisValue(maxVal)
4116
- },
4117
- `${element.id}-map-legend-max`
4118
- )
4119
- );
4120
- if (unmatchedRows.length > 0) {
4121
- const tableY = legendY + 26;
4122
- const fontSize = Math.min(8, fallbackRowH * 0.7);
4123
- const colW = Math.min((svgWidth - 20) / 2, 120);
4124
- const tableX = (svgWidth - colW * 2) / 2;
4125
- elements.push(
4126
- /* @__PURE__ */ jsx(
4127
- "text",
4128
- {
4129
- x: svgWidth / 2,
4130
- y: tableY,
4131
- textAnchor: "middle",
4132
- fontSize: 7,
4133
- fill: "#94a3b8",
4134
- children: translationsEn["pptx.chart.additionalRegionsFallback"]
4135
- },
4136
- `${element.id}-map-ft-hdr`
4137
- )
4138
- );
4139
- const maxRows = Math.min(unmatchedRows.length, 5);
4140
- for (let i = 0; i < maxRows; i++) {
4141
- const row = unmatchedRows[i];
4142
- const y = tableY + fallbackRowH * (i + 1);
4143
- if (y + fallbackRowH > svgHeight) {
4144
- break;
4145
- }
4146
- if (i % 2 === 0) {
4147
- elements.push(
4148
- /* @__PURE__ */ jsx(
4149
- "rect",
4150
- {
4151
- x: tableX,
4152
- y: y - fallbackRowH + 4,
4153
- width: colW * 2,
4154
- height: fallbackRowH,
4155
- fill: "#f1f5f9",
4156
- rx: 2
4157
- },
4158
- `${element.id}-map-ft-bg-${i}`
4159
- )
4160
- );
4161
- }
4162
- elements.push(
4163
- /* @__PURE__ */ jsx(
4164
- "text",
4165
- {
4166
- x: tableX + 4,
4167
- y,
4168
- fontSize,
4169
- fill: "#334155",
4170
- children: row.label
4171
- },
4172
- `${element.id}-map-ft-lbl-${i}`
4173
- ),
4174
- /* @__PURE__ */ jsx(
4175
- "text",
4176
- {
4177
- x: tableX + colW + 4,
4178
- y,
4179
- fontSize,
4180
- fill: "#475569",
4181
- children: formatAxisValue(row.value)
4182
- },
4183
- `${element.id}-map-ft-val-${i}`
4184
- )
4185
- );
4186
- }
4187
- if (unmatchedRows.length > 5) {
4188
- const moreY = tableY + fallbackRowH * 6;
4189
- elements.push(
4190
- /* @__PURE__ */ jsxs(
4191
- "text",
4192
- {
4193
- x: svgWidth / 2,
4194
- y: moreY,
4195
- textAnchor: "middle",
4196
- fontSize: 6,
4197
- fill: "#94a3b8",
4198
- children: [
4199
- "+",
4200
- unmatchedRows.length - 5,
4201
- " more regions"
4202
- ]
4203
- },
4204
- `${element.id}-map-ft-more`
4205
- )
4206
- );
4207
- }
3830
+ const chartData = element.chartData;
3831
+ if (!chartData || chartData.series.length === 0) {
3832
+ return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: translationsEn["pptx.chart.heading"] });
4208
3833
  }
4209
- return /* @__PURE__ */ jsxs(
4210
- "svg",
4211
- {
4212
- className: "w-full h-full pointer-events-none",
4213
- viewBox: `0 0 ${svgWidth} ${svgHeight}`,
4214
- preserveAspectRatio: "xMidYMid meet",
4215
- role: "img",
4216
- "aria-label": `Geographic map chart${chartData.title ? `: ${chartData.title}` : ""}`,
4217
- children: [
4218
- /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: svgWidth, height: svgHeight, fill: "#f8fafc", rx: 4 }),
4219
- elements
4220
- ]
4221
- }
3834
+ const kind = resolveChartKind(chartData.chartType ?? "bar");
3835
+ return renderChartViewModel(
3836
+ element.id,
3837
+ buildReactChartViewModel(element),
3838
+ chartPreserveAspectRatio(kind)
4222
3839
  );
4223
3840
  }
4224
3841
 
4225
- // src/viewer/utils/chart-pie.tsx
4226
- function renderPieChart(element, _chartData, _categoryLabels) {
4227
- const vm = buildReactChartViewModel(element);
4228
- return renderChartViewModel(element.id, vm, "xMidYMid meet");
4229
- }
4230
-
4231
- // src/viewer/utils/chart-radar.tsx
4232
- function renderRadarChart(element, _chartData, _categoryLabels) {
4233
- const vm = buildReactChartViewModel(element);
4234
- return renderChartViewModel(element.id, vm, "xMidYMid meet");
4235
- }
4236
-
4237
- // src/viewer/utils/chart-scatter-bubble.tsx
4238
- function renderScatterChart(element, _chartData, _categoryLabels) {
4239
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
4240
- }
4241
- function renderBubbleChart(element, _chartData, _categoryLabels) {
4242
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
4243
- }
4244
-
4245
- // src/viewer/utils/chart-stacked-bar.tsx
4246
- function renderStackedBarChart(element, _chartData, _categoryLabels) {
4247
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
4248
- }
4249
-
4250
- // src/viewer/utils/chart-overlay-utils.ts
4251
- function sColor(series, idx) {
4252
- return seriesColor(series, idx);
4253
- }
4254
- function valToY(val, range, topY, bottomY) {
4255
- const usable = bottomY - topY;
4256
- return bottomY - (val - range.min) / range.span * usable;
4257
- }
4258
- function xToPixel(xVal, catCount, layout, mode) {
4259
- {
4260
- const slotWidth = layout.plotWidth / Math.max(catCount, 1);
4261
- return layout.plotLeft + slotWidth * xVal + slotWidth / 2;
4262
- }
4263
- }
4264
- function computeLinearRegression(xVals, yVals) {
4265
- const n = xVals.length;
4266
- if (n < 2) {
4267
- return { slope: 0, intercept: 0, rSquared: 0 };
4268
- }
4269
- let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;
4270
- for (let i = 0; i < n; i++) {
4271
- sumX += xVals[i];
4272
- sumY += yVals[i];
4273
- sumXY += xVals[i] * yVals[i];
4274
- sumXX += xVals[i] * xVals[i];
4275
- }
4276
- const denom = n * sumXX - sumX * sumX;
4277
- if (Math.abs(denom) < 1e-12) {
4278
- return { slope: 0, intercept: sumY / n, rSquared: 0 };
4279
- }
4280
- const slope = (n * sumXY - sumX * sumY) / denom;
4281
- const intercept = (sumY - slope * sumX) / n;
4282
- const ssRes = yVals.reduce((s, y, i) => s + (y - (slope * xVals[i] + intercept)) ** 2, 0);
4283
- const meanY = sumY / n;
4284
- const ssTot = yVals.reduce((s, y) => s + (y - meanY) ** 2, 0);
4285
- const rSquared = ssTot > 0 ? 1 - ssRes / ssTot : 0;
4286
- return { slope, intercept, rSquared };
4287
- }
4288
- function fitPolynomial(xVals, yVals, order) {
4289
- const n = xVals.length;
4290
- const m = order + 1;
4291
- const matrix = Array.from({ length: m }, () => Array(m + 1).fill(0));
4292
- for (let i = 0; i < m; i++) {
4293
- for (let j = 0; j < m; j++) {
4294
- let sum2 = 0;
4295
- for (let k = 0; k < n; k++) {
4296
- sum2 += xVals[k] ** (i + j);
4297
- }
4298
- matrix[i][j] = sum2;
4299
- }
4300
- let sum = 0;
4301
- for (let k = 0; k < n; k++) {
4302
- sum += yVals[k] * xVals[k] ** i;
4303
- }
4304
- matrix[i][m] = sum;
4305
- }
4306
- for (let i = 0; i < m; i++) {
4307
- let maxRow = i;
4308
- for (let k = i + 1; k < m; k++) {
4309
- if (Math.abs(matrix[k][i]) > Math.abs(matrix[maxRow][i])) {
4310
- maxRow = k;
4311
- }
4312
- }
4313
- [matrix[i], matrix[maxRow]] = [matrix[maxRow], matrix[i]];
4314
- const pivot = matrix[i][i];
4315
- if (Math.abs(pivot) < 1e-12) {
4316
- continue;
4317
- }
4318
- for (let j = i; j <= m; j++) {
4319
- matrix[i][j] /= pivot;
4320
- }
4321
- for (let k = 0; k < m; k++) {
4322
- if (k === i) {
4323
- continue;
4324
- }
4325
- const factor = matrix[k][i];
4326
- for (let j = i; j <= m; j++) {
4327
- matrix[k][j] -= factor * matrix[i][j];
4328
- }
4329
- }
4330
- }
4331
- return matrix.map((row) => row[m]);
4332
- }
4333
- function computeRSquared(xVals, yVals, evalFn) {
4334
- const n = xVals.length;
4335
- const meanY = yVals.reduce((s, y) => s + y, 0) / n;
4336
- let ssRes = 0, ssTot = 0;
4337
- for (let i = 0; i < n; i++) {
4338
- ssRes += (yVals[i] - evalFn(xVals[i])) ** 2;
4339
- ssTot += (yVals[i] - meanY) ** 2;
4340
- }
4341
- return ssTot > 0 ? 1 - ssRes / ssTot : 0;
4342
- }
4343
- function computeTrendlinePoints(trendline, values, catCount, layout, range, mode) {
4344
- const n = values.length;
4345
- if (n < 2) {
4346
- return { points: [], equation: "", rSquared: 0 };
4347
- }
4348
- const xVals = values.map((_v, i) => i);
4349
- const yVals = values;
4350
- const forward = trendline.forward ?? 0;
4351
- const backward = trendline.backward ?? 0;
4352
- const startX = -backward;
4353
- const endX = n - 1 + forward;
4354
- const steps = Math.max(Math.ceil((endX - startX) * 4), 20);
4355
- let evalFn;
4356
- let equation = "";
4357
- let rSquared = 0;
4358
- switch (trendline.trendlineType) {
4359
- case "linear": {
4360
- const reg = computeLinearRegression(xVals, yVals);
4361
- const slope = trendline.intercept !== void 0 ? yVals.reduce((s, y, i) => s + (y - trendline.intercept) * xVals[i], 0) / xVals.reduce((s, x) => s + x * x, 0) : reg.slope;
4362
- const b = trendline.intercept ?? reg.intercept;
4363
- evalFn = (x) => slope * x + b;
4364
- equation = `y = ${slope.toFixed(2)}x + ${b.toFixed(2)}`;
4365
- rSquared = reg.rSquared;
4366
- break;
4367
- }
4368
- case "exponential": {
4369
- const logY = yVals.filter((y) => y > 0).map((y) => Math.log(y));
4370
- const filteredX = xVals.filter((_x, i) => yVals[i] > 0);
4371
- if (logY.length < 2) {
4372
- return { points: [], equation: "", rSquared: 0 };
4373
- }
4374
- const reg = computeLinearRegression(filteredX, logY);
4375
- const a = Math.exp(reg.intercept);
4376
- const b = reg.slope;
4377
- evalFn = (x) => a * Math.exp(b * x);
4378
- equation = `y = ${a.toFixed(2)}e^(${b.toFixed(2)}x)`;
4379
- rSquared = reg.rSquared;
4380
- break;
4381
- }
4382
- case "logarithmic": {
4383
- const lnX = xVals.filter((x) => x > 0).map((x) => Math.log(x));
4384
- const filteredY = yVals.filter((_y, i) => xVals[i] > 0);
4385
- if (lnX.length < 2) {
4386
- return { points: [], equation: "", rSquared: 0 };
4387
- }
4388
- const reg = computeLinearRegression(lnX, filteredY);
4389
- evalFn = (x) => x > 0 ? reg.slope * Math.log(x) + reg.intercept : 0;
4390
- equation = `y = ${reg.slope.toFixed(2)}ln(x) + ${reg.intercept.toFixed(2)}`;
4391
- rSquared = reg.rSquared;
4392
- break;
4393
- }
4394
- case "power": {
4395
- const logX = xVals.filter((x, i) => x > 0 && yVals[i] > 0).map((x) => Math.log(x));
4396
- const logY = yVals.filter((y, i) => y > 0 && xVals[i] > 0).map((y) => Math.log(y));
4397
- if (logX.length < 2) {
4398
- return { points: [], equation: "", rSquared: 0 };
4399
- }
4400
- const reg = computeLinearRegression(logX, logY);
4401
- const a = Math.exp(reg.intercept);
4402
- evalFn = (x) => x > 0 ? a * x ** reg.slope : 0;
4403
- equation = `y = ${a.toFixed(2)}x^${reg.slope.toFixed(2)}`;
4404
- rSquared = reg.rSquared;
4405
- break;
4406
- }
4407
- case "polynomial": {
4408
- const order = Math.min(trendline.order ?? 2, 6);
4409
- const coeffs = fitPolynomial(xVals, yVals, order);
4410
- evalFn = (x) => coeffs.reduce((s, c, i) => s + c * x ** i, 0);
4411
- equation = coeffs.map((c, i) => `${c.toFixed(2)}x^${i}`).join(" + ");
4412
- rSquared = computeRSquared(xVals, yVals, evalFn);
4413
- break;
4414
- }
4415
- case "movingAvg": {
4416
- const period = trendline.period ?? 2;
4417
- const maPoints = [];
4418
- for (let i = period - 1; i < n; i++) {
4419
- let sum = 0;
4420
- for (let j = i - period + 1; j <= i; j++) {
4421
- sum += yVals[j];
4422
- }
4423
- const avgVal = sum / period;
4424
- const px = xToPixel(i, catCount, layout);
4425
- const py = valToY(avgVal, range, layout.plotTop, layout.plotBottom);
4426
- maPoints.push({ x: px, y: py });
4427
- }
4428
- return {
4429
- points: maPoints,
4430
- equation: `${period}-period moving average`,
4431
- rSquared: 0
4432
- };
4433
- }
4434
- default:
4435
- return { points: [], equation: "", rSquared: 0 };
4436
- }
4437
- const points = [];
4438
- for (let step = 0; step <= steps; step++) {
4439
- const xVal = startX + (endX - startX) * step / steps;
4440
- const yVal = evalFn(xVal);
4441
- if (!Number.isFinite(yVal)) {
4442
- continue;
4443
- }
4444
- const px = xToPixel(xVal, catCount, layout);
4445
- const py = valToY(yVal, range, layout.plotTop, layout.plotBottom);
4446
- points.push({ x: px, y: py });
4447
- }
4448
- return { points, equation, rSquared };
4449
- }
4450
- function renderTrendlines(elementId, chartData, layout, range, mode) {
4451
- const catCount = Math.max(chartData.categories.length, 1);
4452
- const nodes = [];
4453
- chartData.series.forEach((series, si) => {
4454
- if (!series.trendlines || series.trendlines.length === 0) {
4455
- return;
4456
- }
4457
- series.trendlines.forEach((tl, ti) => {
4458
- const { points, equation, rSquared } = computeTrendlinePoints(
4459
- tl,
4460
- series.values,
4461
- catCount,
4462
- layout,
4463
- range);
4464
- if (points.length < 2) {
4465
- return;
4466
- }
4467
- const pathD = points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
4468
- const strokeColor = tl.color || sColor(series, si);
4469
- nodes.push(
4470
- /* @__PURE__ */ jsx(
4471
- "path",
4472
- {
4473
- d: pathD,
4474
- fill: "none",
4475
- stroke: strokeColor,
4476
- strokeWidth: 1.5,
4477
- strokeDasharray: "6 3",
4478
- opacity: 0.8
4479
- },
4480
- `${elementId}-tl-${si}-${ti}`
4481
- )
4482
- );
4483
- const textParts = [];
4484
- if (tl.displayEq && equation) {
4485
- textParts.push(equation);
4486
- }
4487
- if (tl.displayRSq) {
4488
- textParts.push(`R\xB2 = ${rSquared.toFixed(4)}`);
4489
- }
4490
- if (textParts.length > 0) {
4491
- const lastPt = points[points.length - 1];
4492
- nodes.push(
4493
- /* @__PURE__ */ jsx(
4494
- "text",
4495
- {
4496
- x: lastPt.x,
4497
- y: lastPt.y - 6,
4498
- textAnchor: "end",
4499
- fontSize: 7,
4500
- fill: strokeColor,
4501
- children: textParts.join(" ")
4502
- },
4503
- `${elementId}-tl-txt-${si}-${ti}`
4504
- )
4505
- );
4506
- }
4507
- });
4508
- });
4509
- if (nodes.length === 0) {
4510
- return null;
4511
- }
4512
- return /* @__PURE__ */ jsx("g", { children: nodes }, `${elementId}-trendlines`);
4513
- }
4514
- function computeErrorValue(errBars, values, pointIndex, direction) {
4515
- switch (errBars.valType) {
4516
- case "fixedVal":
4517
- return errBars.val ?? 0;
4518
- case "percentage":
4519
- return Math.abs(values[pointIndex]) * ((errBars.val ?? 0) / 100);
4520
- case "stdDev": {
4521
- const n = values.length;
4522
- const mean = values.reduce((s, v) => s + v, 0) / n;
4523
- const variance = values.reduce((s, v) => s + (v - mean) ** 2, 0) / n;
4524
- const stdDev = Math.sqrt(variance);
4525
- return stdDev * (errBars.val ?? 1);
4526
- }
4527
- case "stdErr": {
4528
- const n2 = values.length;
4529
- const mean2 = values.reduce((s, v) => s + v, 0) / n2;
4530
- const variance2 = values.reduce((s, v) => s + (v - mean2) ** 2, 0) / n2;
4531
- return Math.sqrt(variance2 / n2);
4532
- }
4533
- case "cust": {
4534
- if (direction === "plus") {
4535
- return errBars.customPlus?.[pointIndex] ?? 0;
4536
- }
4537
- return errBars.customMinus?.[pointIndex] ?? 0;
4538
- }
4539
- default:
4540
- return 0;
4541
- }
4542
- }
4543
- function renderErrorBars(elementId, chartData, layout, range, mode) {
4544
- const catCount = Math.max(chartData.categories.length, 1);
4545
- const nodes = [];
4546
- const capW = 4;
4547
- chartData.series.forEach((series, si) => {
4548
- if (!series.errBars || series.errBars.length === 0) {
4549
- return;
4550
- }
4551
- series.errBars.forEach((eb) => {
4552
- if (eb.direction !== "y") {
4553
- return;
4554
- }
4555
- series.values.forEach((val, vi) => {
4556
- const cx = xToPixel(vi, catCount, layout);
4557
- const baseY = valToY(val, range, layout.plotTop, layout.plotBottom);
4558
- if (eb.barType === "plus" || eb.barType === "both") {
4559
- const plusErr = computeErrorValue(eb, series.values, vi, "plus");
4560
- const topY = valToY(val + plusErr, range, layout.plotTop, layout.plotBottom);
4561
- nodes.push(
4562
- /* @__PURE__ */ jsx(
4563
- "line",
4564
- {
4565
- x1: cx,
4566
- y1: baseY,
4567
- x2: cx,
4568
- y2: topY,
4569
- stroke: "#334155",
4570
- strokeWidth: 1
4571
- },
4572
- `${elementId}-eb-p-${si}-${vi}`
4573
- ),
4574
- /* @__PURE__ */ jsx(
4575
- "line",
4576
- {
4577
- x1: cx - capW,
4578
- y1: topY,
4579
- x2: cx + capW,
4580
- y2: topY,
4581
- stroke: "#334155",
4582
- strokeWidth: 1
4583
- },
4584
- `${elementId}-eb-pc-${si}-${vi}`
4585
- )
4586
- );
4587
- }
4588
- if (eb.barType === "minus" || eb.barType === "both") {
4589
- const minusErr = computeErrorValue(eb, series.values, vi, "minus");
4590
- const botY = valToY(val - minusErr, range, layout.plotTop, layout.plotBottom);
4591
- nodes.push(
4592
- /* @__PURE__ */ jsx(
4593
- "line",
4594
- {
4595
- x1: cx,
4596
- y1: baseY,
4597
- x2: cx,
4598
- y2: botY,
4599
- stroke: "#334155",
4600
- strokeWidth: 1
4601
- },
4602
- `${elementId}-eb-m-${si}-${vi}`
4603
- ),
4604
- /* @__PURE__ */ jsx(
4605
- "line",
4606
- {
4607
- x1: cx - capW,
4608
- y1: botY,
4609
- x2: cx + capW,
4610
- y2: botY,
4611
- stroke: "#334155",
4612
- strokeWidth: 1
4613
- },
4614
- `${elementId}-eb-mc-${si}-${vi}`
4615
- )
4616
- );
4617
- }
4618
- });
4619
- });
4620
- });
4621
- if (nodes.length === 0) {
4622
- return null;
4623
- }
4624
- return /* @__PURE__ */ jsx("g", { children: nodes }, `${elementId}-errorbars`);
4625
- }
4626
- function renderDropLines(elementId, chartData, layout, range, mode) {
4627
- if (!chartData.dropLines) {
4628
- return null;
4629
- }
4630
- const catCount = Math.max(chartData.categories.length, 1);
4631
- const style = chartData.dropLines;
4632
- const baselineY = valToY(range.min, range, layout.plotTop, layout.plotBottom);
4633
- const nodes = [];
4634
- chartData.series.forEach((series, si) => {
4635
- series.values.forEach((val, vi) => {
4636
- const cx = xToPixel(vi, catCount, layout);
4637
- const dataY = valToY(val, range, layout.plotTop, layout.plotBottom);
4638
- nodes.push(
4639
- /* @__PURE__ */ jsx(
4640
- "line",
4641
- {
4642
- x1: cx,
4643
- y1: dataY,
4644
- x2: cx,
4645
- y2: baselineY,
4646
- stroke: style.color || "#94a3b8",
4647
- strokeWidth: style.width ?? 0.8,
4648
- strokeDasharray: style.dashStyle === "dash" ? "4 3" : void 0
4649
- },
4650
- `${elementId}-dl-${si}-${vi}`
4651
- )
4652
- );
4653
- });
4654
- });
4655
- if (nodes.length === 0) {
4656
- return null;
4657
- }
4658
- return /* @__PURE__ */ jsx("g", { children: nodes }, `${elementId}-droplines`);
4659
- }
4660
- function renderUpDownBars(elementId, chartData, layout, range, mode) {
4661
- if (!chartData.upDownBars || chartData.series.length < 2) {
4662
- return null;
4663
- }
4664
- const catCount = Math.max(chartData.categories.length, 1);
4665
- const bars = chartData.upDownBars;
4666
- const first = chartData.series[0];
4667
- const last = chartData.series[chartData.series.length - 1];
4668
- const slot = layout.plotWidth / catCount;
4669
- const gapWidth = bars.gapWidth ?? 150;
4670
- const barW = Math.max(slot / (1 + Math.max(gapWidth, 0) / 100), 1);
4671
- const upFill = bars.upBars?.fillColor ?? "#e2e8f0";
4672
- const downFill = bars.downBars?.fillColor ?? "#334155";
4673
- const nodes = [];
4674
- for (let vi = 0; vi < catCount; vi++) {
4675
- const firstVal = first.values[vi];
4676
- const lastVal = last.values[vi];
4677
- if (firstVal === void 0 || lastVal === void 0) {
4678
- continue;
4679
- }
4680
- const firstY = valToY(firstVal, range, layout.plotTop, layout.plotBottom);
4681
- const lastY = valToY(lastVal, range, layout.plotTop, layout.plotBottom);
4682
- const cx = xToPixel(vi, catCount, layout);
4683
- nodes.push(
4684
- /* @__PURE__ */ jsx(
4685
- "rect",
4686
- {
4687
- x: cx - barW / 2,
4688
- y: Math.min(firstY, lastY),
4689
- width: barW,
4690
- height: Math.max(Math.abs(firstY - lastY), 1),
4691
- fill: lastVal >= firstVal ? upFill : downFill,
4692
- stroke: "#64748b",
4693
- strokeWidth: 0.5
4694
- },
4695
- `${elementId}-udb-${vi}`
4696
- )
4697
- );
4698
- }
4699
- if (nodes.length === 0) {
4700
- return null;
4701
- }
4702
- return /* @__PURE__ */ jsx("g", { children: nodes }, `${elementId}-updownbars`);
4703
- }
4704
- function renderHiLowLines(elementId, chartData, layout, range, mode) {
4705
- if (!chartData.hiLowLines) {
4706
- return null;
4707
- }
4708
- if (chartData.series.length < 2) {
4709
- return null;
4710
- }
4711
- const catCount = Math.max(chartData.categories.length, 1);
4712
- const style = chartData.hiLowLines;
4713
- const nodes = [];
4714
- for (let vi = 0; vi < catCount; vi++) {
4715
- let highVal = -Infinity;
4716
- let lowVal = Infinity;
4717
- for (const series of chartData.series) {
4718
- const v = series.values[vi];
4719
- if (v !== void 0) {
4720
- highVal = Math.max(highVal, v);
4721
- lowVal = Math.min(lowVal, v);
4722
- }
4723
- }
4724
- if (!Number.isFinite(highVal) || !Number.isFinite(lowVal)) {
4725
- continue;
4726
- }
4727
- const cx = xToPixel(vi, catCount, layout);
4728
- const highY = valToY(highVal, range, layout.plotTop, layout.plotBottom);
4729
- const lowY = valToY(lowVal, range, layout.plotTop, layout.plotBottom);
4730
- nodes.push(
4731
- /* @__PURE__ */ jsx(
4732
- "line",
4733
- {
4734
- x1: cx,
4735
- y1: highY,
4736
- x2: cx,
4737
- y2: lowY,
4738
- stroke: style.color || "#334155",
4739
- strokeWidth: style.width ?? 1,
4740
- strokeDasharray: style.dashStyle === "dash" ? "4 3" : void 0
4741
- },
4742
- `${elementId}-hl-${vi}`
4743
- )
4744
- );
4745
- }
4746
- if (nodes.length === 0) {
4747
- return null;
4748
- }
4749
- return /* @__PURE__ */ jsx("g", { children: nodes }, `${elementId}-hilowlines`);
4750
- }
4751
- function renderTitle(id, style, title, svgWidth) {
4752
- if (!style?.hasTitle) {
4753
- return null;
4754
- }
4755
- return /* @__PURE__ */ jsx(
4756
- "text",
4757
- {
4758
- x: svgWidth / 2,
4759
- y: 16,
4760
- textAnchor: "middle",
4761
- fontSize: 12,
4762
- fontWeight: 600,
4763
- fill: "#1e293b",
4764
- children: title || "Chart"
4765
- },
4766
- `${id}-title`
4767
- );
4768
- }
4769
- function renderLegend(id, style, series, layout, colorPalette) {
4770
- if (!style?.hasLegend || series.length === 0) {
4771
- return null;
4772
- }
4773
- const pos = style.legendPosition || "b";
4774
- if (pos === "b" || pos === "t") {
4775
- const y = pos === "b" ? layout.svgHeight - 10 : layout.plotTop - 14;
4776
- const items = [];
4777
- const charWidth = 6;
4778
- const gap = 24;
4779
- const totalWidth = series.reduce((w, s) => w + (s.name?.length ?? 4) * charWidth + gap, 0);
4780
- let cx = (layout.svgWidth - totalWidth) / 2;
4781
- series.forEach((s, i) => {
4782
- items.push(
4783
- /* @__PURE__ */ jsx(
4784
- "rect",
4785
- {
4786
- x: cx,
4787
- y: y - 5,
4788
- width: 10,
4789
- height: 10,
4790
- rx: 2,
4791
- fill: seriesColor(s, i, style?.styleId, colorPalette)
4792
- },
4793
- `${id}-leg-r-${i}`
4794
- )
4795
- );
4796
- items.push(
4797
- /* @__PURE__ */ jsx("text", { x: cx + 14, y: y + 4, fontSize: 9, fill: "#475569", children: s.name || `Series ${i + 1}` }, `${id}-leg-t-${i}`)
4798
- );
4799
- cx += (s.name?.length ?? 4) * charWidth + gap;
4800
- });
4801
- return /* @__PURE__ */ jsx("g", { children: items }, `${id}-legend`);
4802
- }
4803
- const x = pos === "r" ? layout.plotRight + 8 : 4;
4804
- return /* @__PURE__ */ jsx("g", { children: series.map((s, i) => {
4805
- const cy = layout.plotTop + i * 16;
4806
- return /* @__PURE__ */ jsxs("g", { children: [
4807
- /* @__PURE__ */ jsx(
4808
- "rect",
4809
- {
4810
- x,
4811
- y: cy,
4812
- width: 10,
4813
- height: 10,
4814
- rx: 2,
4815
- fill: seriesColor(s, i, style?.styleId, colorPalette)
4816
- }
4817
- ),
4818
- /* @__PURE__ */ jsx("text", { x: x + 14, y: cy + 8, fontSize: 9, fill: "#475569", children: s.name || `Series ${i + 1}` })
4819
- ] }, `${id}-leg-${i}`);
4820
- }) }, `${id}-legend`);
4821
- }
4822
- function renderGridlines(id, style, range, layout) {
4823
- if (!style?.hasGridlines) {
4824
- return null;
4825
- }
4826
- const lines = [];
4827
- if (range.logScale && range.logBase) {
4828
- const ticks = generateLogTicks(range);
4829
- ticks.forEach((tickVal, i) => {
4830
- const y = valueToY(tickVal, range, layout.plotTop, layout.plotBottom);
4831
- lines.push(
4832
- /* @__PURE__ */ jsx(
4833
- "line",
4834
- {
4835
- x1: layout.plotLeft,
4836
- y1: y,
4837
- x2: layout.plotRight,
4838
- y2: y,
4839
- stroke: "#cbd5e1",
4840
- strokeWidth: 0.7,
4841
- strokeDasharray: "4 3"
4842
- },
4843
- `${id}-grid-log-${i}`
4844
- )
4845
- );
4846
- });
4847
- } else {
4848
- const steps = 4;
4849
- for (let i = 0; i <= steps; i++) {
4850
- const val = range.min + range.span * i / steps;
4851
- const y = valueToY(val, range, layout.plotTop, layout.plotBottom);
4852
- lines.push(
4853
- /* @__PURE__ */ jsx(
4854
- "line",
4855
- {
4856
- x1: layout.plotLeft,
4857
- y1: y,
4858
- x2: layout.plotRight,
4859
- y2: y,
4860
- stroke: "#cbd5e1",
4861
- strokeWidth: 0.7,
4862
- strokeDasharray: "4 3"
4863
- },
4864
- `${id}-grid-${i}`
4865
- )
4866
- );
4867
- }
4868
- }
4869
- return /* @__PURE__ */ jsx("g", { children: lines }, `${id}-gridlines`);
4870
- }
4871
- function renderValueAxis(id, range, layout, axisFormatting) {
4872
- const labels = [];
4873
- const hasDisplayUnits = Boolean(axisFormatting?.displayUnits);
4874
- if (range.logScale && range.logBase) {
4875
- const ticks = generateLogTicks(range);
4876
- ticks.forEach((tickVal, i) => {
4877
- const y = valueToY(tickVal, range, layout.plotTop, layout.plotBottom);
4878
- labels.push(
4879
- /* @__PURE__ */ jsx(
4880
- "text",
4881
- {
4882
- x: layout.plotLeft - 4,
4883
- y: y + 3,
4884
- textAnchor: "end",
4885
- fontSize: 8,
4886
- fill: "#64748b",
4887
- children: hasDisplayUnits ? formatAxisValueWithUnits(tickVal, axisFormatting) : formatAxisValue(tickVal)
4888
- },
4889
- `${id}-vaxis-log-${i}`
4890
- )
4891
- );
4892
- });
4893
- } else {
4894
- const steps = 4;
4895
- for (let i = 0; i <= steps; i++) {
4896
- const val = range.min + range.span * i / steps;
4897
- const y = valueToY(val, range, layout.plotTop, layout.plotBottom);
4898
- labels.push(
4899
- /* @__PURE__ */ jsx(
4900
- "text",
4901
- {
4902
- x: layout.plotLeft - 4,
4903
- y: y + 3,
4904
- textAnchor: "end",
4905
- fontSize: 8,
4906
- fill: "#64748b",
4907
- children: hasDisplayUnits ? formatAxisValueWithUnits(val, axisFormatting) : formatAxisValue(val)
4908
- },
4909
- `${id}-vaxis-${i}`
4910
- )
4911
- );
4912
- }
4913
- }
4914
- if (hasDisplayUnits) {
4915
- const unitLabel = getDisplayUnitLabel(
4916
- axisFormatting.displayUnits,
4917
- axisFormatting.displayUnitsLabel
4918
- );
4919
- if (unitLabel) {
4920
- const midY = (layout.plotTop + layout.plotBottom) / 2;
4921
- labels.push(
4922
- /* @__PURE__ */ jsx(
4923
- "text",
4924
- {
4925
- x: layout.plotLeft - 36,
4926
- y: midY,
4927
- textAnchor: "middle",
4928
- fontSize: 9,
4929
- fill: "#64748b",
4930
- transform: `rotate(-90, ${layout.plotLeft - 36}, ${midY})`,
4931
- children: unitLabel
4932
- },
4933
- `${id}-vaxis-dispunit`
4934
- )
4935
- );
4936
- }
4937
- }
4938
- return /* @__PURE__ */ jsx("g", { children: labels }, `${id}-vaxis`);
4939
- }
4940
- function renderCategoryAxis(id, categories, layout) {
4941
- const count = categories.length;
4942
- if (count === 0) {
4943
- return null;
4944
- }
4945
- return /* @__PURE__ */ jsx("g", { children: categories.map((cat, i) => {
4946
- const slotWidth = layout.plotWidth / count;
4947
- const x = layout.plotLeft + slotWidth * i + slotWidth / 2;
4948
- return /* @__PURE__ */ jsx(
4949
- "text",
4950
- {
4951
- x,
4952
- y: layout.plotBottom + 14,
4953
- textAnchor: "middle",
4954
- fontSize: 8,
4955
- fill: "#64748b",
4956
- children: cat
4957
- },
4958
- `${id}-caxis-${i}`
4959
- );
4960
- }) }, `${id}-caxis`);
4961
- }
4962
- function renderCategoryAxisForLine(id, categories, layout) {
4963
- const count = categories.length;
4964
- if (count === 0) {
4965
- return null;
4966
- }
4967
- return /* @__PURE__ */ jsx("g", { children: categories.map((cat, i) => {
4968
- const x = count > 1 ? layout.plotLeft + layout.plotWidth * i / (count - 1) : layout.plotLeft + layout.plotWidth / 2;
4969
- return /* @__PURE__ */ jsx(
4970
- "text",
4971
- {
4972
- x,
4973
- y: layout.plotBottom + 14,
4974
- textAnchor: "middle",
4975
- fontSize: 8,
4976
- fill: "#64748b",
4977
- children: cat
4978
- },
4979
- `${id}-caxis-${i}`
4980
- );
4981
- }) }, `${id}-caxis`);
4982
- }
4983
- function renderZeroLine(id, range, layout) {
4984
- if (range.logScale) {
4985
- return null;
4986
- }
4987
- if (range.min >= 0) {
4988
- return null;
4989
- }
4990
- const y = valueToY(0, range, layout.plotTop, layout.plotBottom);
4991
- return /* @__PURE__ */ jsx(
4992
- "line",
4993
- {
4994
- x1: layout.plotLeft,
4995
- y1: y,
4996
- x2: layout.plotRight,
4997
- y2: y,
4998
- stroke: "#334155",
4999
- strokeWidth: 1
5000
- },
5001
- `${id}-zero`
5002
- );
5003
- }
5004
- function renderSecondaryValueAxis(id, range, layout, axisFormatting) {
5005
- const steps = 4;
5006
- const labels = [];
5007
- const fontSize = axisFormatting?.fontSize ?? 8;
5008
- const fontColor = axisFormatting?.fontColor ?? "#64748b";
5009
- const fontFamily = axisFormatting?.fontFamily;
5010
- const fontWeight = axisFormatting?.fontBold ? 700 : void 0;
5011
- const hasDisplayUnits = Boolean(axisFormatting?.displayUnits);
5012
- for (let i = 0; i <= steps; i++) {
5013
- const val = range.min + range.span * i / steps;
5014
- const y = valueToY(val, range, layout.plotTop, layout.plotBottom);
5015
- labels.push(
5016
- /* @__PURE__ */ jsx(
5017
- "text",
5018
- {
5019
- x: layout.plotRight + 4,
5020
- y: y + 3,
5021
- textAnchor: "start",
5022
- fontSize,
5023
- fontFamily,
5024
- fontWeight,
5025
- fill: fontColor,
5026
- children: hasDisplayUnits ? formatAxisValueWithUnits(val, axisFormatting) : formatAxisValue(val)
5027
- },
5028
- `${id}-sec-vaxis-${i}`
5029
- )
5030
- );
5031
- }
5032
- if (axisFormatting?.titleText) {
5033
- labels.push(
5034
- /* @__PURE__ */ jsx(
5035
- "text",
5036
- {
5037
- x: layout.plotRight + 36,
5038
- y: (layout.plotTop + layout.plotBottom) / 2,
5039
- textAnchor: "middle",
5040
- fontSize: 9,
5041
- fill: fontColor,
5042
- transform: `rotate(-90, ${layout.plotRight + 36}, ${(layout.plotTop + layout.plotBottom) / 2})`,
5043
- children: axisFormatting.titleText
5044
- },
5045
- `${id}-sec-vaxis-title`
5046
- )
5047
- );
5048
- }
5049
- if (hasDisplayUnits) {
5050
- const unitLabel = getDisplayUnitLabel(
5051
- axisFormatting.displayUnits,
5052
- axisFormatting.displayUnitsLabel
5053
- );
5054
- if (unitLabel) {
5055
- const labelX = layout.plotRight + (axisFormatting?.titleText ? 52 : 36);
5056
- const midY = (layout.plotTop + layout.plotBottom) / 2;
5057
- labels.push(
5058
- /* @__PURE__ */ jsx(
5059
- "text",
5060
- {
5061
- x: labelX,
5062
- y: midY,
5063
- textAnchor: "middle",
5064
- fontSize: 9,
5065
- fill: fontColor,
5066
- transform: `rotate(-90, ${labelX}, ${midY})`,
5067
- children: unitLabel
5068
- },
5069
- `${id}-sec-vaxis-dispunit`
5070
- )
5071
- );
5072
- }
5073
- }
5074
- return /* @__PURE__ */ jsx("g", { children: labels }, `${id}-sec-vaxis`);
5075
- }
5076
- function renderSecondaryAxisTicks(id, range, layout) {
5077
- const steps = 4;
5078
- const ticks = [];
5079
- for (let i = 0; i <= steps; i++) {
5080
- const val = range.min + range.span * i / steps;
5081
- const y = valueToY(val, range, layout.plotTop, layout.plotBottom);
5082
- ticks.push(
5083
- /* @__PURE__ */ jsx(
5084
- "line",
5085
- {
5086
- x1: layout.plotRight,
5087
- y1: y,
5088
- x2: layout.plotRight + 4,
5089
- y2: y,
5090
- stroke: "#94a3b8",
5091
- strokeWidth: 0.7
5092
- },
5093
- `${id}-sec-tick-${i}`
5094
- )
5095
- );
5096
- }
5097
- return /* @__PURE__ */ jsx("g", { children: ticks }, `${id}-sec-ticks`);
5098
- }
5099
- function renderSecondaryGridlines(id, range, layout, axisFormatting) {
5100
- if (!axisFormatting?.minorGridlinesSpPr && !axisFormatting?.majorGridlinesSpPr) {
5101
- return null;
5102
- }
5103
- const steps = 4;
5104
- const lines = [];
5105
- const gridColor = axisFormatting.majorGridlinesSpPr?.strokeColor ?? "#e2e8f0";
5106
- for (let i = 0; i <= steps; i++) {
5107
- const val = range.min + range.span * i / steps;
5108
- const y = valueToY(val, range, layout.plotTop, layout.plotBottom);
5109
- lines.push(
5110
- /* @__PURE__ */ jsx(
5111
- "line",
5112
- {
5113
- x1: layout.plotLeft,
5114
- y1: y,
5115
- x2: layout.plotRight,
5116
- y2: y,
5117
- stroke: gridColor,
5118
- strokeWidth: 0.5,
5119
- strokeDasharray: "2 3",
5120
- opacity: 0.5
5121
- },
5122
- `${id}-sec-grid-${i}`
5123
- )
5124
- );
5125
- }
5126
- return /* @__PURE__ */ jsx("g", { children: lines }, `${id}-sec-gridlines`);
5127
- }
5128
- function renderChrome(id, chartData, layout, range, categories, options, secondaryOptions) {
5129
- const style = chartData.style;
5130
- const chrome = [];
5131
- const primaryValueAxis = chartData.axes?.find((a) => a.axisType === "valAx" && a.axPos !== "r") ?? chartData.axes?.find((a) => a.axisType === "valAx");
5132
- chrome.push(renderTitle(id, style, chartData.title, layout.svgWidth));
5133
- chrome.push(renderGridlines(id, style, range, layout));
5134
- chrome.push(renderValueAxis(id, range, layout, primaryValueAxis));
5135
- chrome.push(renderZeroLine(id, range, layout));
5136
- if (options.categoryAxisStyle === "bar") {
5137
- chrome.push(renderCategoryAxis(id, categories, layout));
5138
- } else {
5139
- chrome.push(renderCategoryAxisForLine(id, categories, layout));
5140
- }
5141
- chrome.push(renderLegend(id, style, chartData.series, layout, chartData.colorPalette));
5142
- if (secondaryOptions?.secondaryRange) {
5143
- chrome.push(
5144
- renderSecondaryValueAxis(
5145
- id,
5146
- secondaryOptions.secondaryRange,
5147
- layout,
5148
- secondaryOptions.secondaryAxisFormatting
5149
- )
5150
- );
5151
- chrome.push(renderSecondaryAxisTicks(id, secondaryOptions.secondaryRange, layout));
5152
- chrome.push(
5153
- renderSecondaryGridlines(
5154
- id,
5155
- secondaryOptions.secondaryRange,
5156
- layout,
5157
- secondaryOptions.secondaryAxisFormatting
5158
- )
5159
- );
5160
- }
5161
- return chrome;
5162
- }
5163
- function renderOverlays(id, chartData, layout, range, mode) {
5164
- const overlayLayout = layout;
5165
- const overlayRange = range;
5166
- const nodes = [];
5167
- nodes.push(renderUpDownBars(id, chartData, overlayLayout, overlayRange));
5168
- nodes.push(renderDropLines(id, chartData, overlayLayout, overlayRange));
5169
- nodes.push(renderHiLowLines(id, chartData, overlayLayout, overlayRange));
5170
- nodes.push(renderTrendlines(id, chartData, overlayLayout, overlayRange));
5171
- nodes.push(renderErrorBars(id, chartData, overlayLayout, overlayRange));
5172
- return nodes;
5173
- }
5174
- function formatValue(val) {
5175
- if (Math.abs(val) >= 1e6) {
5176
- return `${(val / 1e6).toFixed(1)}M`;
5177
- }
5178
- if (Math.abs(val) >= 1e3) {
5179
- return `${(val / 1e3).toFixed(1)}K`;
5180
- }
5181
- if (Number.isInteger(val)) {
5182
- return String(val);
5183
- }
5184
- return val.toFixed(1);
5185
- }
5186
- function renderChartDataTable(elementId, chartData, svgWidth) {
5187
- const table = chartData.dataTable;
5188
- if (!table) {
5189
- return null;
5190
- }
5191
- const categories = chartData.categories;
5192
- const series = chartData.series;
5193
- if (categories.length === 0 && series.length === 0) {
5194
- return null;
5195
- }
5196
- const borderColor = "#cbd5e1";
5197
- const showH = table.showHorzBorder !== false;
5198
- const showV = table.showVertBorder !== false;
5199
- const showO = table.showOutline !== false;
5200
- const showK = table.showKeys !== false;
5201
- const borderStyle = `1px solid ${borderColor}`;
5202
- return /* @__PURE__ */ jsx(
5203
- "div",
5204
- {
5205
- style: {
5206
- width: svgWidth,
5207
- overflow: "hidden",
5208
- fontSize: 8,
5209
- lineHeight: "14px",
5210
- color: "#334155",
5211
- pointerEvents: "none"
5212
- },
5213
- children: /* @__PURE__ */ jsxs(
5214
- "table",
5215
- {
5216
- style: {
5217
- width: "100%",
5218
- borderCollapse: "collapse",
5219
- border: showO ? borderStyle : "none"
5220
- },
5221
- children: [
5222
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
5223
- showK && /* @__PURE__ */ jsx(
5224
- "th",
5225
- {
5226
- "aria-label": translationsEn["pptx.chart.rowLabelsAria"],
5227
- style: {
5228
- padding: "1px 4px",
5229
- fontWeight: 400,
5230
- borderBottom: showH ? borderStyle : "none",
5231
- borderRight: showV ? borderStyle : "none",
5232
- textAlign: "left"
5233
- }
5234
- }
5235
- ),
5236
- categories.map((cat, ci) => /* @__PURE__ */ jsx(
5237
- "th",
5238
- {
5239
- style: {
5240
- padding: "1px 4px",
5241
- fontWeight: 600,
5242
- borderBottom: showH ? borderStyle : "none",
5243
- borderRight: showV && ci < categories.length - 1 ? borderStyle : "none",
5244
- textAlign: "center"
5245
- },
5246
- children: cat
5247
- },
5248
- `${elementId}-dtable-h-${ci}`
5249
- ))
5250
- ] }) }),
5251
- /* @__PURE__ */ jsx("tbody", { children: series.map((s, si) => /* @__PURE__ */ jsxs("tr", { children: [
5252
- showK && /* @__PURE__ */ jsxs(
5253
- "td",
5254
- {
5255
- style: {
5256
- padding: "1px 4px",
5257
- borderBottom: showH && si < series.length - 1 ? borderStyle : "none",
5258
- borderRight: showV ? borderStyle : "none",
5259
- whiteSpace: "nowrap"
5260
- },
5261
- children: [
5262
- /* @__PURE__ */ jsx(
5263
- "span",
5264
- {
5265
- style: {
5266
- display: "inline-block",
5267
- width: 8,
5268
- height: 8,
5269
- borderRadius: 2,
5270
- backgroundColor: seriesColor(
5271
- s,
5272
- si,
5273
- chartData.style?.styleId,
5274
- chartData.colorPalette
5275
- ),
5276
- marginRight: 4,
5277
- verticalAlign: "middle"
5278
- }
5279
- }
5280
- ),
5281
- s.name
5282
- ]
5283
- }
5284
- ),
5285
- categories.map((_cat, ci) => /* @__PURE__ */ jsx(
5286
- "td",
5287
- {
5288
- style: {
5289
- padding: "1px 4px",
5290
- textAlign: "center",
5291
- borderBottom: showH && si < series.length - 1 ? borderStyle : "none",
5292
- borderRight: showV && ci < categories.length - 1 ? borderStyle : "none"
5293
- },
5294
- children: s.values[ci] !== void 0 ? formatValue(s.values[ci]) : ""
5295
- },
5296
- `${elementId}-dtable-c-${si}-${ci}`
5297
- ))
5298
- ] }, `${elementId}-dtable-r-${si}`)) })
5299
- ]
5300
- }
5301
- )
5302
- },
5303
- `${elementId}-dtable`
5304
- );
5305
- }
5306
- function renderStockChart(element, chartData, categoryLabels) {
5307
- const style = chartData.style;
5308
- const areaFill = chartAreaFill(chartData);
5309
- const legendPos = style?.legendPosition || "b";
5310
- const range = computeValueRangeForChart(chartData.series, chartData.axes);
5311
- const layout = computeLayout(element.width, element.height, style, true, legendPos);
5312
- const catCount = Math.max(categoryLabels.length, 1);
5313
- const barGroupWidth = layout.plotWidth / catCount;
5314
- const candleWidth = barGroupWidth * 0.5;
5315
- const hasFour = chartData.series.length >= 4;
5316
- const openSeries = hasFour ? chartData.series[0] : void 0;
5317
- const highSeries = chartData.series[hasFour ? 1 : 0];
5318
- const lowSeries = chartData.series[hasFour ? 2 : 1];
5319
- const closeSeries = chartData.series[hasFour ? 3 : 2];
5320
- if (!highSeries || !lowSeries || !closeSeries) {
5321
- return null;
5322
- }
5323
- const elements = [];
5324
- const dlElements = [];
5325
- for (let ci = 0; ci < catCount; ci++) {
5326
- const high = highSeries.values[ci] ?? 0;
5327
- const low = lowSeries.values[ci] ?? 0;
5328
- const open = openSeries?.values[ci] ?? low;
5329
- const close = closeSeries.values[ci] ?? high;
5330
- const isUp = close >= open;
5331
- const cx = layout.plotLeft + barGroupWidth * ci + barGroupWidth / 2;
5332
- const highY = valueToY(high, range, layout.plotTop, layout.plotBottom);
5333
- const lowY = valueToY(low, range, layout.plotTop, layout.plotBottom);
5334
- const openY = valueToY(open, range, layout.plotTop, layout.plotBottom);
5335
- const closeY = valueToY(close, range, layout.plotTop, layout.plotBottom);
5336
- elements.push(
5337
- /* @__PURE__ */ jsx(
5338
- "line",
5339
- {
5340
- x1: cx,
5341
- y1: highY,
5342
- x2: cx,
5343
- y2: lowY,
5344
- stroke: "#334155",
5345
- strokeWidth: 1
5346
- },
5347
- `${element.id}-stock-wick-${ci}`
5348
- )
5349
- );
5350
- const bodyTop = Math.min(openY, closeY);
5351
- const bodyHeight = Math.max(Math.abs(openY - closeY), 1);
5352
- elements.push(
5353
- /* @__PURE__ */ jsx(
5354
- "rect",
5355
- {
5356
- x: cx - candleWidth / 2,
5357
- y: bodyTop,
5358
- width: candleWidth,
5359
- height: bodyHeight,
5360
- fill: isUp ? "#22c55e" : "#ef4444",
5361
- stroke: isUp ? "#16a34a" : "#dc2626",
5362
- strokeWidth: 0.5,
5363
- rx: 1
5364
- },
5365
- `${element.id}-stock-body-${ci}`
5366
- )
5367
- );
5368
- if (style?.hasDataLabels) {
5369
- dlElements.push(
5370
- /* @__PURE__ */ jsx(
5371
- "text",
5372
- {
5373
- x: cx,
5374
- y: highY - 4,
5375
- textAnchor: "middle",
5376
- fontSize: 7,
5377
- fill: "#334155",
5378
- children: formatAxisValue(close)
5379
- },
5380
- `${element.id}-stock-dl-${ci}`
5381
- )
5382
- );
5383
- }
5384
- }
5385
- return /* @__PURE__ */ jsxs(Fragment, { children: [
5386
- /* @__PURE__ */ jsxs(
5387
- "svg",
5388
- {
5389
- className: "w-full h-full pointer-events-none",
5390
- viewBox: `0 0 ${layout.svgWidth} ${layout.svgHeight}`,
5391
- preserveAspectRatio: "none",
5392
- children: [
5393
- areaFill && /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: layout.svgWidth, height: layout.svgHeight, fill: areaFill }),
5394
- renderChrome(element.id, chartData, layout, range, categoryLabels, {
5395
- categoryAxisStyle: "bar"
5396
- }),
5397
- elements,
5398
- dlElements,
5399
- renderOverlays(element.id, chartData, layout, range)
5400
- ]
5401
- }
5402
- ),
5403
- renderChartDataTable(element.id, chartData, layout.svgWidth)
5404
- ] });
5405
- }
5406
-
5407
- // src/viewer/utils/chart-sunburst-funnel.tsx
5408
- function renderSunburstChart(element, _chartData, _categoryLabels) {
5409
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
5410
- }
5411
- function renderFunnelChart(element, _chartData, _categoryLabels) {
5412
- return renderChartViewModel(element.id, buildReactChartViewModel(element));
5413
- }
5414
- function FailedToLoad() {
5415
- return null;
5416
- }
5417
- var LazySurfaceChart3DScene = React6.lazy(
5418
- async () => {
5419
- try {
5420
- return await import('./SurfaceChart3DScene-JR62SOYO.mjs');
5421
- } catch {
5422
- return { default: FailedToLoad };
5423
- }
5424
- }
5425
- );
5426
- var SurfaceChart3DErrorBoundary = class extends React6.Component {
5427
- constructor(props) {
5428
- super(props);
5429
- this.state = { hasError: false };
5430
- }
5431
- static getDerivedStateFromError() {
5432
- return { hasError: true };
5433
- }
5434
- render() {
5435
- if (this.state.hasError) {
5436
- return this.props.fallback;
5437
- }
5438
- return this.props.children;
5439
- }
5440
- };
5441
- function buildSurfaceData(chartData, categoryLabels) {
5442
- const rows = chartData.series.length;
5443
- const cols = Math.max(categoryLabels.length, 1);
5444
- const range = computeValueRangeForChart(chartData.series, chartData.axes);
5445
- const heightMap = new Float32Array(rows * cols);
5446
- const colorMap = new Float32Array(rows * cols * 3);
5447
- for (let r = 0; r < rows; r++) {
5448
- const series = chartData.series[r];
5449
- for (let c = 0; c < cols; c++) {
5450
- const val = series?.values[c] ?? 0;
5451
- const t = range.span > 0 ? (val - range.min) / range.span : 0;
5452
- const idx = r * cols + c;
5453
- heightMap[idx] = t;
5454
- const { r: cr, g: cg, b: cb } = surfaceColor(t);
5455
- colorMap[idx * 3] = cr / 255;
5456
- colorMap[idx * 3 + 1] = cg / 255;
5457
- colorMap[idx * 3 + 2] = cb / 255;
5458
- }
5459
- }
5460
- return { heightMap, colorMap, rows, cols };
5461
- }
5462
- function LoadingPlaceholder({ width, height }) {
5463
- const { t } = useTranslation();
5464
- return /* @__PURE__ */ jsx(
5465
- "div",
5466
- {
5467
- style: {
5468
- width,
5469
- height,
5470
- display: "flex",
5471
- alignItems: "center",
5472
- justifyContent: "center",
5473
- background: "#f8fafc",
5474
- border: "1px dashed #cbd5e1",
5475
- borderRadius: 4,
5476
- fontSize: 11,
5477
- color: "#94a3b8"
5478
- },
5479
- children: t("pptx.chart.loading3dSurface")
5480
- }
5481
- );
5482
- }
5483
- var SurfaceChart3D = React6.memo(
5484
- ({ element, chartData, categoryLabels, fallback }) => {
5485
- const [threeAvailable, setThreeAvailable] = useState(null);
5486
- useEffect(() => {
5487
- let cancelled = false;
5488
- import('./three.module-AC7ESV4W.mjs').then(() => {
5489
- if (!cancelled) {
5490
- setThreeAvailable(true);
5491
- }
5492
- return void 0;
5493
- }).catch(() => {
5494
- if (!cancelled) {
5495
- setThreeAvailable(false);
5496
- }
5497
- });
5498
- return () => {
5499
- cancelled = true;
5500
- };
5501
- }, []);
5502
- const surfaceData = useMemo(
5503
- () => buildSurfaceData(chartData, categoryLabels),
5504
- [chartData, categoryLabels]
5505
- );
5506
- const seriesNames = useMemo(() => chartData.series.map((s) => s.name), [chartData.series]);
5507
- if (threeAvailable === null) {
5508
- return /* @__PURE__ */ jsx(LoadingPlaceholder, { width: element.width, height: element.height });
5509
- }
5510
- if (!threeAvailable) {
5511
- return fallback;
5512
- }
5513
- return /* @__PURE__ */ jsx(SurfaceChart3DErrorBoundary, { fallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingPlaceholder, { width: element.width, height: element.height }), children: /* @__PURE__ */ jsx(
5514
- LazySurfaceChart3DScene,
5515
- {
5516
- cols: surfaceData.cols,
5517
- rows: surfaceData.rows,
5518
- heightMap: surfaceData.heightMap,
5519
- colorMap: surfaceData.colorMap,
5520
- wireframe: true,
5521
- categoryLabels,
5522
- seriesNames,
5523
- title: chartData.title,
5524
- width: element.width,
5525
- height: element.height
5526
- }
5527
- ) }) });
5528
- }
5529
- );
5530
- SurfaceChart3D.displayName = "SurfaceChart3D";
5531
- var ISO_COS30 = Math.cos(Math.PI / 6);
5532
- var ISO_SIN30 = Math.sin(Math.PI / 6);
5533
- function isoProject(x, y, z) {
5534
- return {
5535
- screenX: (x - y) * ISO_COS30,
5536
- screenY: (x + y) * ISO_SIN30 - z
5537
- };
5538
- }
5539
- function surfaceColor(t) {
5540
- return {
5541
- r: Math.round(30 + 200 * t),
5542
- g: Math.round(80 + 100 * (1 - Math.abs(t - 0.5) * 2)),
5543
- b: Math.round(200 * (1 - t) + 30)
5544
- };
5545
- }
5546
- function isoCellVertices(col, row, cellSize, zScale, getValue) {
5547
- const corners = [
5548
- [col, row],
5549
- [col + 1, row],
5550
- [col + 1, row + 1],
5551
- [col, row + 1]
5552
- ];
5553
- return corners.map(([c, r]) => {
5554
- const val = getValue(r, c);
5555
- return isoProject(c * cellSize, r * cellSize, val * zScale);
5556
- });
5557
- }
5558
- function darkenRgb(r, g, b, factor) {
5559
- return `rgb(${Math.round(r * factor)},${Math.round(g * factor)},${Math.round(b * factor)})`;
5560
- }
5561
- function renderIsometricSurfaceChart(element, chartData, categoryLabels) {
5562
- const style = chartData.style;
5563
- const areaFill = chartAreaFill(chartData);
5564
- const legendPos = style?.legendPosition || "b";
5565
- const layout = computeLayout(element.width, element.height, style, false, legendPos);
5566
- const range = computeValueRangeForChart(chartData.series, chartData.axes);
5567
- const catCount = Math.max(categoryLabels.length, 1);
5568
- const seriesCount = chartData.series.length;
5569
- const cols = catCount - 1;
5570
- const rows = seriesCount - 1;
5571
- const gridSpan = cols + rows;
5572
- const baseHeightBudget = layout.plotHeight * 0.65;
5573
- const widthBudget = layout.plotWidth * 0.9;
5574
- const cellByWidth = widthBudget / (gridSpan * ISO_COS30);
5575
- const cellByHeight = baseHeightBudget / (gridSpan * ISO_SIN30);
5576
- const cellSize = Math.min(cellByWidth, cellByHeight);
5577
- const zHeadroom = layout.plotHeight * 0.3;
5578
- const zScale = range.span > 0 ? zHeadroom : 0;
5579
- const normValue = (r, c) => {
5580
- const ri = Math.min(r, seriesCount - 1);
5581
- const ci = Math.min(c, catCount - 1);
5582
- const val = chartData.series[ri]?.values[ci] ?? 0;
5583
- return range.span > 0 ? (val - range.min) / range.span : 0;
5584
- };
5585
- const allProjected = [];
5586
- for (let r = 0; r <= rows; r++) {
5587
- for (let c = 0; c <= cols; c++) {
5588
- const nv = normValue(r, c);
5589
- allProjected.push(isoProject(c * cellSize, r * cellSize, nv * zScale));
5590
- }
5591
- }
5592
- const minSX = Math.min(...allProjected.map((p) => p.screenX));
5593
- const maxSX = Math.max(...allProjected.map((p) => p.screenX));
5594
- const minSY = Math.min(...allProjected.map((p) => p.screenY));
5595
- const maxSY = Math.max(...allProjected.map((p) => p.screenY));
5596
- const projW = maxSX - minSX;
5597
- const projH = maxSY - minSY;
5598
- const offsetX = layout.plotLeft + layout.plotWidth / 2 - (minSX + projW / 2);
5599
- const offsetY = layout.plotTop + layout.plotHeight / 2 - (minSY + projH / 2);
5600
- const cellEntries = [];
5601
- for (let r = 0; r < rows; r++) {
5602
- for (let c = 0; c < cols; c++) {
5603
- cellEntries.push({ row: r, col: c, depth: r + c });
5604
- }
5605
- }
5606
- cellEntries.sort((a, b) => a.depth - b.depth);
5607
- const polygons = [];
5608
- for (const { row, col } of cellEntries) {
5609
- const verts = isoCellVertices(col, row, cellSize, zScale, normValue);
5610
- const avgT = (normValue(row, col) + normValue(row, col + 1) + normValue(row + 1, col + 1) + normValue(row + 1, col)) / 4;
5611
- const { r, g, b } = surfaceColor(avgT);
5612
- const points = verts.map((v) => `${(v.screenX + offsetX).toFixed(2)},${(v.screenY + offsetY).toFixed(2)}`).join(" ");
5613
- polygons.push(
5614
- /* @__PURE__ */ jsx(
5615
- "polygon",
5616
- {
5617
- points,
5618
- fill: `rgb(${r},${g},${b})`,
5619
- opacity: 0.9
5620
- },
5621
- `${element.id}-iso-${row}-${col}`
5622
- )
5623
- );
5624
- polygons.push(
5625
- /* @__PURE__ */ jsx(
5626
- "polygon",
5627
- {
5628
- points,
5629
- fill: "none",
5630
- stroke: darkenRgb(r, g, b, 0.6),
5631
- strokeWidth: 0.5,
5632
- opacity: 0.7
5633
- },
5634
- `${element.id}-iso-edge-${row}-${col}`
5635
- )
5636
- );
5637
- }
5638
- return /* @__PURE__ */ jsxs(
5639
- "svg",
5640
- {
5641
- className: "w-full h-full pointer-events-none",
5642
- viewBox: `0 0 ${layout.svgWidth} ${layout.svgHeight}`,
5643
- preserveAspectRatio: "xMidYMid meet",
5644
- children: [
5645
- areaFill && /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: layout.svgWidth, height: layout.svgHeight, fill: areaFill }),
5646
- renderTitle(element.id, style, chartData.title, layout.svgWidth),
5647
- renderLegend(element.id, style, chartData.series, layout),
5648
- polygons
5649
- ]
5650
- }
5651
- );
5652
- }
5653
- function renderFlatSurfaceChart(element, chartData, categoryLabels) {
5654
- const style = chartData.style;
5655
- const areaFill = chartAreaFill(chartData);
5656
- const legendPos = style?.legendPosition || "b";
5657
- const layout = computeLayout(element.width, element.height, style, true, legendPos);
5658
- const range = computeValueRangeForChart(chartData.series, chartData.axes);
5659
- const catCount = Math.max(categoryLabels.length, 1);
5660
- const seriesCount = chartData.series.length;
5661
- const cellW = layout.plotWidth / Math.max(catCount - 1, 1);
5662
- const cellH = layout.plotHeight / Math.max(seriesCount - 1, 1);
5663
- const cells = [];
5664
- for (let si = 0; si < seriesCount; si++) {
5665
- for (let ci = 0; ci < catCount; ci++) {
5666
- const val = chartData.series[si].values[ci] ?? 0;
5667
- const t = range.span > 0 ? (val - range.min) / range.span : 0;
5668
- const { r, g, b } = surfaceColor(t);
5669
- cells.push(
5670
- /* @__PURE__ */ jsx(
5671
- "rect",
5672
- {
5673
- x: layout.plotLeft + ci * cellW,
5674
- y: layout.plotTop + si * cellH,
5675
- width: cellW + 0.5,
5676
- height: cellH + 0.5,
5677
- fill: `rgb(${r},${g},${b})`,
5678
- opacity: 0.85
5679
- },
5680
- `${element.id}-surf-${si}-${ci}`
5681
- )
5682
- );
5683
- }
5684
- }
5685
- return /* @__PURE__ */ jsxs(
5686
- "svg",
5687
- {
5688
- className: "w-full h-full pointer-events-none",
5689
- viewBox: `0 0 ${layout.svgWidth} ${layout.svgHeight}`,
5690
- preserveAspectRatio: "none",
5691
- children: [
5692
- areaFill && /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: layout.svgWidth, height: layout.svgHeight, fill: areaFill }),
5693
- renderChrome(element.id, chartData, layout, range, categoryLabels, {
5694
- categoryAxisStyle: "bar"
5695
- }),
5696
- cells
5697
- ]
5698
- }
5699
- );
5700
- }
5701
- function renderSurfaceChart(element, chartData, categoryLabels) {
5702
- const catCount = Math.max(categoryLabels.length, 1);
5703
- const seriesCount = chartData.series.length;
5704
- if (seriesCount >= 2 && catCount >= 2) {
5705
- const svgFallback = renderIsometricSurfaceChart(element, chartData, categoryLabels);
5706
- return /* @__PURE__ */ jsx(
5707
- SurfaceChart3D,
5708
- {
5709
- element,
5710
- chartData,
5711
- categoryLabels,
5712
- fallback: svgFallback
5713
- }
5714
- );
5715
- }
5716
- return renderFlatSurfaceChart(element, chartData, categoryLabels);
5717
- }
5718
- function renderTreemapChart(element, chartData, categoryLabels) {
5719
- const style = chartData.style;
5720
- const areaFill = chartAreaFill(chartData);
5721
- const legendPos = style?.legendPosition || "b";
5722
- const layout = computeLayout(element.width, element.height, style, false, legendPos);
5723
- const allValues = chartData.series.flatMap((s) => s.values);
5724
- const totalAbs = allValues.reduce((sum, v) => sum + Math.abs(v), 0) || 1;
5725
- const rects = [];
5726
- let curX = layout.plotLeft;
5727
- let curY = layout.plotTop;
5728
- let remainW = layout.plotWidth;
5729
- let remainH = layout.plotHeight;
5730
- const remaining = allValues.map((v, i) => ({ value: Math.abs(v), index: i })).sort((a, b) => b.value - a.value);
5731
- let remainTotal = totalAbs;
5732
- remaining.forEach((item) => {
5733
- const fraction = remainTotal > 0 ? item.value / remainTotal : 0;
5734
- const useWidth = remainW >= remainH;
5735
- const w = useWidth ? remainW * fraction : remainW;
5736
- const h = useWidth ? remainH : remainH * fraction;
5737
- rects.push(
5738
- /* @__PURE__ */ jsx(
5739
- "rect",
5740
- {
5741
- x: curX,
5742
- y: curY,
5743
- width: Math.max(w - 1, 1),
5744
- height: Math.max(h - 1, 1),
5745
- fill: paletteColor(item.index, chartData.style?.styleId, chartData.colorPalette),
5746
- rx: 2,
5747
- opacity: 0.85
5748
- },
5749
- `${element.id}-tm-${item.index}`
5750
- )
5751
- );
5752
- const label2 = categoryLabels[item.index] ?? `${item.index + 1}`;
5753
- if (w > 30 && h > 14) {
5754
- rects.push(
5755
- /* @__PURE__ */ jsx(
5756
- "text",
5757
- {
5758
- x: curX + Math.max(w - 1, 1) / 2,
5759
- y: curY + Math.max(h - 1, 1) / 2 + 4,
5760
- textAnchor: "middle",
5761
- fontSize: Math.min(10, h * 0.3),
5762
- fill: "#fff",
5763
- fontWeight: 600,
5764
- children: label2
5765
- },
5766
- `${element.id}-tm-lbl-${item.index}`
5767
- )
5768
- );
5769
- }
5770
- if (useWidth) {
5771
- curX += w;
5772
- remainW -= w;
5773
- } else {
5774
- curY += h;
5775
- remainH -= h;
5776
- }
5777
- remainTotal -= item.value;
5778
- });
5779
- return /* @__PURE__ */ jsxs(
5780
- "svg",
5781
- {
5782
- className: "w-full h-full pointer-events-none",
5783
- viewBox: `0 0 ${layout.svgWidth} ${layout.svgHeight}`,
5784
- preserveAspectRatio: "none",
5785
- children: [
5786
- areaFill && /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: layout.svgWidth, height: layout.svgHeight, fill: areaFill }),
5787
- renderTitle(element.id, style, chartData.title, layout.svgWidth),
5788
- renderLegend(element.id, style, chartData.series, layout),
5789
- rects
5790
- ]
5791
- }
5792
- );
5793
- }
5794
- function renderWaterfallChart(element, chartData, categoryLabels) {
5795
- const style = chartData.style;
5796
- const areaFill = chartAreaFill(chartData);
5797
- const legendPos = style?.legendPosition || "b";
5798
- const values = chartData.series[0]?.values ?? [];
5799
- const range = computeValueRangeForChart(chartData.series, chartData.axes);
5800
- const layout = computeLayout(element.width, element.height, style, true, legendPos);
5801
- const catCount = Math.max(categoryLabels.length, values.length, 1);
5802
- const barWidth = layout.plotWidth / catCount * 0.6;
5803
- const gap = layout.plotWidth / catCount * 0.2;
5804
- let runningTotal = 0;
5805
- const bars = [];
5806
- const dataLabels = [];
5807
- values.forEach((val, i) => {
5808
- const isLast = i === values.length - 1;
5809
- const startVal = isLast ? 0 : runningTotal;
5810
- const endVal = isLast ? runningTotal + val : runningTotal + val;
5811
- const barStartY = valueToY(startVal, range, layout.plotTop, layout.plotBottom);
5812
- const barEndY = valueToY(endVal, range, layout.plotTop, layout.plotBottom);
5813
- const x = layout.plotLeft + layout.plotWidth / catCount * i + gap;
5814
- const y = Math.min(barStartY, barEndY);
5815
- const h = Math.max(Math.abs(barEndY - barStartY), 1);
5816
- const barColor = isLast ? "#6366f1" : val >= 0 ? "#22c55e" : "#ef4444";
5817
- bars.push(
5818
- /* @__PURE__ */ jsx(
5819
- "rect",
5820
- {
5821
- x,
5822
- y,
5823
- width: barWidth,
5824
- height: h,
5825
- fill: barColor,
5826
- rx: 1
5827
- },
5828
- `${element.id}-wf-bar-${i}`
5829
- )
5830
- );
5831
- if (style?.hasDataLabels) {
5832
- dataLabels.push(
5833
- /* @__PURE__ */ jsx(
5834
- "text",
5835
- {
5836
- x: x + barWidth / 2,
5837
- y: y - 4,
5838
- textAnchor: "middle",
5839
- fontSize: 7,
5840
- fill: "#334155",
5841
- children: formatAxisValue(isLast ? endVal : val)
5842
- },
5843
- `${element.id}-wf-dl-${i}`
5844
- )
5845
- );
5846
- }
5847
- if (!isLast && i < values.length - 1) {
5848
- const nextX = layout.plotLeft + layout.plotWidth / catCount * (i + 1) + gap;
5849
- bars.push(
5850
- /* @__PURE__ */ jsx(
5851
- "line",
5852
- {
5853
- x1: x + barWidth,
5854
- y1: barEndY,
5855
- x2: nextX,
5856
- y2: barEndY,
5857
- stroke: "#94a3b8",
5858
- strokeWidth: 0.8,
5859
- strokeDasharray: "3 2"
5860
- },
5861
- `${element.id}-wf-conn-${i}`
5862
- )
5863
- );
5864
- }
5865
- if (!isLast) {
5866
- runningTotal += val;
5867
- }
5868
- });
5869
- return /* @__PURE__ */ jsxs(
5870
- "svg",
5871
- {
5872
- className: "w-full h-full pointer-events-none",
5873
- viewBox: `0 0 ${layout.svgWidth} ${layout.svgHeight}`,
5874
- preserveAspectRatio: "none",
5875
- children: [
5876
- areaFill && /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: layout.svgWidth, height: layout.svgHeight, fill: areaFill }),
5877
- renderChrome(element.id, chartData, layout, range, categoryLabels, {
5878
- categoryAxisStyle: "bar"
5879
- }),
5880
- bars,
5881
- dataLabels
5882
- ]
5883
- }
5884
- );
5885
- }
5886
- function renderComboChart(element, chartData, categoryLabels) {
5887
- const style = chartData.style;
5888
- const areaFill = chartAreaFill(chartData);
5889
- const legendPos = style?.legendPosition || "b";
5890
- const layoutOpts = computeLayoutOptions(
5891
- chartData.axes,
5892
- chartData.dataTable,
5893
- chartData.series.length
5894
- );
5895
- const layout = computeLayout(element.width, element.height, style, true, legendPos, layoutOpts);
5896
- const { primary, secondary } = splitSeriesByAxis(chartData.series, chartData.axes);
5897
- const primarySeries = primary.length > 0 ? primary.map((e) => e.series) : chartData.series;
5898
- const secondarySeries = secondary.map((e) => e.series);
5899
- const range = computeValueRangeForChart(primarySeries, chartData.axes);
5900
- const secondaryRange = secondarySeries.length > 0 ? computeValueRange(secondarySeries) : void 0;
5901
- const secondaryAxisFmt = getSecondaryValueAxis(chartData.axes);
5902
- const catCount = Math.max(categoryLabels.length, 1);
5903
- const barSeriesCount = 1;
5904
- const barGroupWidth = layout.plotWidth / catCount;
5905
- const barWidth = barGroupWidth * 0.5;
5906
- const barOffset = (barGroupWidth - barWidth) / 2;
5907
- const barSeries = chartData.series[0];
5908
- const lineSeries = chartData.series.slice(1);
5909
- const barElements = [];
5910
- const lineElements = [];
5911
- const dlElements = [];
5912
- if (barSeries) {
5913
- const isBarSecondary = secondary.some((e) => e.index === 0);
5914
- const barRange = isBarSecondary && secondaryRange ? secondaryRange : range;
5915
- barSeries.values.forEach((val, vi) => {
5916
- const x = layout.plotLeft + barGroupWidth * vi + barOffset;
5917
- const zeroY = valueToY(0, barRange, layout.plotTop, layout.plotBottom);
5918
- const valY = valueToY(val, barRange, layout.plotTop, layout.plotBottom);
5919
- const y = Math.min(zeroY, valY);
5920
- const h = Math.max(Math.abs(zeroY - valY), 1);
5921
- barElements.push(
5922
- /* @__PURE__ */ jsx(
5923
- "rect",
5924
- {
5925
- x,
5926
- y,
5927
- width: barWidth,
5928
- height: h,
5929
- fill: seriesColor(barSeries, 0, chartData.style?.styleId, chartData.colorPalette),
5930
- rx: 1
5931
- },
5932
- `${element.id}-combo-bar-${vi}`
5933
- )
5934
- );
5935
- if (style?.hasDataLabels) {
5936
- dlElements.push(
5937
- /* @__PURE__ */ jsx(
5938
- "text",
5939
- {
5940
- x: x + barWidth / 2,
5941
- y: val >= 0 ? y - 4 : y + h + 10,
5942
- textAnchor: "middle",
5943
- fontSize: 7,
5944
- fill: "#334155",
5945
- children: formatAxisValue(val)
5946
- },
5947
- `${element.id}-combo-bar-dl-${vi}`
5948
- )
5949
- );
5950
- }
5951
- });
5952
- }
5953
- lineSeries.forEach((series, si) => {
5954
- if (series.values.length === 0) {
5955
- return;
5956
- }
5957
- const seriesIdx = si + barSeriesCount;
5958
- const isSecondary = secondary.some((e) => e.index === seriesIdx);
5959
- const activeRange = isSecondary && secondaryRange ? secondaryRange : range;
5960
- const points = series.values.map((val, vi) => {
5961
- const x = layout.plotLeft + barGroupWidth * vi + barGroupWidth / 2;
5962
- const y = valueToY(val, activeRange, layout.plotTop, layout.plotBottom);
5963
- return { x, y, val };
5964
- });
5965
- const c = seriesColor(series, seriesIdx, chartData.style?.styleId, chartData.colorPalette);
5966
- lineElements.push(
5967
- /* @__PURE__ */ jsx(
5968
- "polyline",
5969
- {
5970
- fill: "none",
5971
- stroke: c,
5972
- strokeWidth: 2.4,
5973
- points: points.map((p) => `${p.x},${p.y}`).join(" ")
5974
- },
5975
- `${element.id}-combo-line-${si}`
5976
- )
5977
- );
5978
- points.forEach((p, vi) => {
5979
- lineElements.push(
5980
- /* @__PURE__ */ jsx("circle", { cx: p.x, cy: p.y, r: 2.5, fill: c }, `${element.id}-combo-dot-${si}-${vi}`)
5981
- );
5982
- if (style?.hasDataLabels) {
5983
- dlElements.push(
5984
- /* @__PURE__ */ jsx(
5985
- "text",
5986
- {
5987
- x: p.x,
5988
- y: p.y - 7,
5989
- textAnchor: "middle",
5990
- fontSize: 7,
5991
- fill: "#334155",
5992
- children: formatAxisValue(p.val)
5993
- },
5994
- `${element.id}-combo-line-dl-${si}-${vi}`
5995
- )
5996
- );
5997
- }
5998
- });
5999
- });
6000
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6001
- /* @__PURE__ */ jsxs(
6002
- "svg",
6003
- {
6004
- className: "w-full h-full pointer-events-none",
6005
- viewBox: `0 0 ${layout.svgWidth} ${layout.svgHeight}`,
6006
- preserveAspectRatio: "none",
6007
- children: [
6008
- areaFill && /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: layout.svgWidth, height: layout.svgHeight, fill: areaFill }),
6009
- renderChrome(
6010
- element.id,
6011
- chartData,
6012
- layout,
6013
- range,
6014
- categoryLabels,
6015
- { categoryAxisStyle: "bar" },
6016
- secondaryRange ? { secondaryRange, secondaryAxisFormatting: secondaryAxisFmt } : void 0
6017
- ),
6018
- barElements,
6019
- lineElements,
6020
- dlElements,
6021
- renderOverlays(element.id, chartData, layout, range)
6022
- ]
6023
- }
6024
- ),
6025
- renderChartDataTable(element.id, chartData, layout.svgWidth)
6026
- ] });
6027
- }
6028
- function renderChartElement(element) {
6029
- if (element.type !== "chart") {
6030
- return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: translationsEn["pptx.chart.heading"] });
6031
- }
6032
- const chartData = element.chartData;
6033
- if (!chartData || chartData.series.length === 0) {
6034
- return /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[11px] text-white/80 pointer-events-none", children: translationsEn["pptx.chart.heading"] });
6035
- }
6036
- const longestSeriesLength = chartData.series.reduce(
6037
- (maxLength, series) => Math.max(maxLength, series.values.length),
6038
- 0
6039
- );
6040
- const categoryLabels = chartData.categories.length > 0 ? chartData.categories : Array.from({ length: longestSeriesLength }, (_, index) => String(index + 1));
6041
- const chartType = chartData.chartType ?? "bar";
6042
- if (chartType === "pie" || chartType === "doughnut" || chartType === "pie3D" || chartType === "ofPie") {
6043
- return renderPieChart(element);
6044
- }
6045
- if (chartType === "scatter") {
6046
- return renderScatterChart(element);
6047
- }
6048
- if (chartType === "bubble") {
6049
- return renderBubbleChart(element);
6050
- }
6051
- if (chartType === "radar") {
6052
- return renderRadarChart(element);
6053
- }
6054
- if (chartType === "stock") {
6055
- return renderStockChart(element, chartData, categoryLabels);
6056
- }
6057
- if (chartType === "area" || chartType === "area3D") {
6058
- return renderAreaChart(element);
6059
- }
6060
- if (chartType === "line" || chartType === "line3D") {
6061
- return renderLineChart(element);
6062
- }
6063
- if (chartType === "waterfall") {
6064
- return renderWaterfallChart(element, chartData, categoryLabels);
6065
- }
6066
- if (chartType === "combo") {
6067
- return renderComboChart(element, chartData, categoryLabels);
6068
- }
6069
- if (chartType === "bar" && (chartData.grouping === "stacked" || chartData.grouping === "percentStacked")) {
6070
- return renderStackedBarChart(element);
6071
- }
6072
- if (chartType === "surface") {
6073
- return renderSurfaceChart(element, chartData, categoryLabels);
6074
- }
6075
- if (chartType === "treemap") {
6076
- return renderTreemapChart(element, chartData, categoryLabels);
6077
- }
6078
- if (chartType === "sunburst") {
6079
- return renderSunburstChart(element);
6080
- }
6081
- if (chartType === "funnel") {
6082
- return renderFunnelChart(element);
6083
- }
6084
- if (chartType === "boxWhisker") {
6085
- return renderBoxWhiskerChart(element);
6086
- }
6087
- if (chartType === "histogram") {
6088
- return renderHistogramChart(element);
6089
- }
6090
- if (chartType === "regionMap") {
6091
- return renderMapChart(element, chartData, categoryLabels);
6092
- }
6093
- return renderDefaultBarChart(element);
6094
- }
6095
-
6096
3842
  // src/viewer/utils/pdf-builder-notes-builder.ts
6097
3843
  function buildNotesPdf(pages) {
6098
3844
  const images = pages.map((page) => {