pace-chart-lib 1.0.1 → 1.0.3

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 (131) hide show
  1. package/dist/{components → Components}/Charts/ChartsWithAxis/ChartsWithAxisFunctions.d.ts +76 -38
  2. package/dist/{components → Components}/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.types.d.ts +4 -2
  3. package/dist/{components → Components}/Charts/Core/CommonFunctions.d.ts +3 -1
  4. package/dist/{components → Components}/Charts/Core/DefaultProperties.types.d.ts +2 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/pace-chart-lib.es.js +54619 -0
  7. package/dist/pace-chart-lib.umd.js +54622 -0
  8. package/dist/vite.svg +1 -0
  9. package/package.json +1 -1
  10. package/dist/Services/ErrorLog.js +0 -3
  11. package/dist/components/Charts/ChartsWithAxis/AreaFamily/AreaChart.js +0 -496
  12. package/dist/components/Charts/ChartsWithAxis/AreaFamily/LineChart.d.ts +0 -4
  13. package/dist/components/Charts/ChartsWithAxis/AreaFamily/LineChart.js +0 -491
  14. package/dist/components/Charts/ChartsWithAxis/AreaFamily/NormalizedStackAreaChart.js +0 -517
  15. package/dist/components/Charts/ChartsWithAxis/AreaFamily/NormalizedStackLineChart.d.ts +0 -4
  16. package/dist/components/Charts/ChartsWithAxis/AreaFamily/NormalizedStackLineChart.js +0 -553
  17. package/dist/components/Charts/ChartsWithAxis/AreaFamily/StackAreaChart.js +0 -517
  18. package/dist/components/Charts/ChartsWithAxis/AreaFamily/StackLineChart.d.ts +0 -4
  19. package/dist/components/Charts/ChartsWithAxis/AreaFamily/StackLineChart.js +0 -553
  20. package/dist/components/Charts/ChartsWithAxis/BarFamily/BarChart.d.ts +0 -12
  21. package/dist/components/Charts/ChartsWithAxis/BarFamily/BarChart.js +0 -9
  22. package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisFunctions.js +0 -4909
  23. package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisTypes.type.d.ts +0 -0
  24. package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisTypes.type.js +0 -0
  25. package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisTypes.types.js +0 -49
  26. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnChart copy.d.ts +0 -4
  27. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnChart copy.js +0 -486
  28. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnChart.js +0 -497
  29. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnHistogramChart.js +0 -418
  30. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/CustomColumnChart.js +0 -1013
  31. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/LayeredColumnChart.js +0 -478
  32. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/LineChart.d.ts +0 -4
  33. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/LineChart.js +0 -451
  34. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/NormalizedStackColumnChart.js +0 -533
  35. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/NormalizedStackLineChart.js +0 -512
  36. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/StackColumnChart.js +0 -530
  37. package/dist/components/Charts/ChartsWithAxis/ColumnFamily/StackLineChart.js +0 -512
  38. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/BarChart.d.ts +0 -12
  39. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/BarChart.js +0 -9
  40. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalBarChart.js +0 -497
  41. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalHistogramChart.js +0 -497
  42. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredColumnChart.d.ts +0 -4
  43. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredColumnChart.js +0 -479
  44. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredHorizontalBarChart.js +0 -478
  45. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/NormalizedStackHorizontalBarChart.js +0 -473
  46. package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/StackHorizontalBarChart.js +0 -465
  47. package/dist/components/Charts/ChartsWithAxis/LineFamily/100%StackLineChart.d.ts +0 -0
  48. package/dist/components/Charts/ChartsWithAxis/LineFamily/100%StackLineChart.js +0 -0
  49. package/dist/components/Charts/ChartsWithAxis/LineFamily/LineChart.js +0 -451
  50. package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalisedStackLineChart.d.ts +0 -4
  51. package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalisedStackLineChart.js +0 -554
  52. package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalizedStackLineChart.d.ts +0 -4
  53. package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalizedStackLineChart.js +0 -510
  54. package/dist/components/Charts/ChartsWithAxis/LineFamily/StackLineChart.d.ts +0 -4
  55. package/dist/components/Charts/ChartsWithAxis/LineFamily/StackLineChart.js +0 -507
  56. package/dist/components/Charts/ChartsWithAxis/MiscellaneousChartFamily/TornadoChart.js +0 -393
  57. package/dist/components/Charts/ChartsWithAxis/MiscellaneousChartFamily/WaterfallChart.js +0 -606
  58. package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxis.types.d.ts +0 -0
  59. package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxis.types.js +0 -0
  60. package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisFunctions.js +0 -815
  61. package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.type.d.ts +0 -0
  62. package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.type.js +0 -0
  63. package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.types.js +0 -32
  64. package/dist/components/Charts/ChartsWithoutAxis/Maps/Cordinates.js +0 -15021
  65. package/dist/components/Charts/ChartsWithoutAxis/Maps/Maps.js +0 -391
  66. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/BubbleChart.js +0 -367
  67. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/OrganizationChart.js +0 -570
  68. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/ProgressChart.js +0 -212
  69. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/PyramidChart.js +0 -401
  70. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/RadialBarChart.js +0 -313
  71. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/SankeyChart.js +0 -719
  72. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/ScatterChart.js +0 -807
  73. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/Speedometer.js +0 -514
  74. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/VennChart.js +0 -282
  75. package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/WordCloud.js +0 -207
  76. package/dist/components/Charts/ChartsWithoutAxis/PieFamily/DonutChart.js +0 -476
  77. package/dist/components/Charts/ChartsWithoutAxis/PieFamily/PieChart.js +0 -420
  78. package/dist/components/Charts/ChartsWithoutAxis/PieFamily/PieFamilyCommonFunctions.js +0 -106
  79. package/dist/components/Charts/ChartsWithoutAxis/PieFamily/PieofPieChart.js +0 -507
  80. package/dist/components/Charts/ChartsWithoutAxis/PieFamily/TreemapChart.js +0 -246
  81. package/dist/components/Charts/Core/Common.type.d.ts +0 -0
  82. package/dist/components/Charts/Core/Common.type.js +0 -0
  83. package/dist/components/Charts/Core/Common.types.js +0 -133
  84. package/dist/components/Charts/Core/CommonFunctions.js +0 -1782
  85. package/dist/components/Charts/Core/DefaultChartDataProperties.js +0 -64
  86. package/dist/components/Charts/Core/DefaultProperties.d.ts +0 -0
  87. package/dist/components/Charts/Core/DefaultProperties.js +0 -0
  88. package/dist/components/Charts/Core/DefaultProperties.type.d.ts +0 -586
  89. package/dist/components/Charts/Core/DefaultProperties.type.js +0 -585
  90. package/dist/components/Charts/Core/DefaultProperties.types.js +0 -592
  91. package/dist/index.js +0 -40
  92. /package/dist/{components → Components}/Charts/ChartsWithAxis/AreaFamily/AreaChart.d.ts +0 -0
  93. /package/dist/{components → Components}/Charts/ChartsWithAxis/AreaFamily/NormalizedStackAreaChart.d.ts +0 -0
  94. /package/dist/{components → Components}/Charts/ChartsWithAxis/AreaFamily/StackAreaChart.d.ts +0 -0
  95. /package/dist/{components → Components}/Charts/ChartsWithAxis/ChartsWithAxisTypes.types.d.ts +0 -0
  96. /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/ColumnChart.d.ts +0 -0
  97. /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/ColumnHistogramChart.d.ts +0 -0
  98. /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/CustomColumnChart.d.ts +0 -0
  99. /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/LayeredColumnChart.d.ts +0 -0
  100. /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/NormalizedStackColumnChart.d.ts +0 -0
  101. /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/StackColumnChart.d.ts +0 -0
  102. /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalBarChart.d.ts +0 -0
  103. /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalHistogramChart.d.ts +0 -0
  104. /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredHorizontalBarChart.d.ts +0 -0
  105. /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/NormalizedStackHorizontalBarChart.d.ts +0 -0
  106. /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/StackHorizontalBarChart.d.ts +0 -0
  107. /package/dist/{components → Components}/Charts/ChartsWithAxis/LineFamily/LineChart.d.ts +0 -0
  108. /package/dist/{components/Charts/ChartsWithAxis/ColumnFamily → Components/Charts/ChartsWithAxis/LineFamily}/NormalizedStackLineChart.d.ts +0 -0
  109. /package/dist/{components/Charts/ChartsWithAxis/ColumnFamily → Components/Charts/ChartsWithAxis/LineFamily}/StackLineChart.d.ts +0 -0
  110. /package/dist/{components → Components}/Charts/ChartsWithAxis/MiscellaneousChartFamily/TornadoChart.d.ts +0 -0
  111. /package/dist/{components → Components}/Charts/ChartsWithAxis/MiscellaneousChartFamily/WaterfallChart.d.ts +0 -0
  112. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/ChartsWithoutAxisFunctions.d.ts +0 -0
  113. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/Maps/Cordinates.d.ts +0 -0
  114. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/Maps/Maps.d.ts +0 -0
  115. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/BubbleChart.d.ts +0 -0
  116. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/OrganizationChart.d.ts +0 -0
  117. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/ProgressChart.d.ts +0 -0
  118. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/PyramidChart.d.ts +0 -0
  119. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/RadialBarChart.d.ts +0 -0
  120. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/SankeyChart.d.ts +0 -0
  121. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/ScatterChart.d.ts +0 -0
  122. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/Speedometer.d.ts +0 -0
  123. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/VennChart.d.ts +0 -0
  124. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/WordCloud.d.ts +0 -0
  125. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/DonutChart.d.ts +0 -0
  126. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/PieChart.d.ts +0 -0
  127. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/PieFamilyCommonFunctions.d.ts +0 -0
  128. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/PieofPieChart.d.ts +0 -0
  129. /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/TreemapChart.d.ts +0 -0
  130. /package/dist/{components → Components}/Charts/Core/Common.types.d.ts +0 -0
  131. /package/dist/{components → Components}/Charts/Core/DefaultChartDataProperties.d.ts +0 -0
@@ -1,1782 +0,0 @@
1
- import * as d3 from "d3";
2
- import { calculateWidthHeightDynamically, getNumberWithFormat } from "../ChartsWithAxis/ChartsWithAxisFunctions";
3
- import { actualChartTypes } from "../ChartsWithAxis/ChartsWithAxisTypes.types";
4
- import { colorThemeTypes, fontStyleOptions, horizontalLegendAllignment, legendColorMode, staticLegendShape, staticLegendPosition, staticTotalAlignment, staticTotalPosition, verticalLegendAllignment } from "./Common.types";
5
- import { defaultChartFormatOptions } from "./DefaultProperties.types";
6
- import { logError } from "../../../Services/ErrorLog";
7
- const fileName = "CommonFunctions.ts";
8
- import { chartProperties } from "./DefaultChartDataProperties";
9
- const chartsWithDataTableArray = [
10
- actualChartTypes.bar,
11
- actualChartTypes.stackColumn,
12
- actualChartTypes.stackColumn100,
13
- actualChartTypes.line,
14
- actualChartTypes.stackLine,
15
- actualChartTypes.stackLine100,
16
- actualChartTypes.area,
17
- actualChartTypes.stackArea,
18
- actualChartTypes.stackArea100,
19
- ];
20
- const chartsWithoutPlotArea = [
21
- actualChartTypes.pie,
22
- actualChartTypes.pieOfPie,
23
- actualChartTypes.sunburst,
24
- actualChartTypes.pyramidChart,
25
- actualChartTypes.organizationalChart,
26
- actualChartTypes.vennDiagramChart,
27
- actualChartTypes.progressChart,
28
- actualChartTypes.maps,
29
- actualChartTypes.wordCloud,
30
- actualChartTypes.sankey,
31
- actualChartTypes.speedometerChart,
32
- actualChartTypes.radialBarChart,
33
- ];
34
- export const svgID = "scaling-svg-";
35
- export function getRandomColor() {
36
- try {
37
- let letters = "0123456789ABCDEF";
38
- let color = "#";
39
- for (let i = 0; i < 6; i++) {
40
- color += letters[Math.floor(Math.random() * 16)];
41
- }
42
- return { color };
43
- }
44
- catch (error) {
45
- logError(fileName, "getRandomColor", error);
46
- }
47
- }
48
- /**
49
- * Draws chart legends in the specified position with optional scroll behavior,
50
- * using layout and format options defined in the configuration.
51
- *
52
- * @param {number} height - The total height of the chart container.
53
- * @param {any} svg - The SVG element where the chart and legends are rendered.
54
- * @param {number[]} maxLegendDimensions - Array with the maximum dimensions [width, height] of the legends.
55
- * @param {number} chartTitleHeight - Height occupied by the chart title (used to offset legends).
56
- * @param {number} width - The total width of the chart container.
57
- * @param {number} legendMargin - Margin to be applied around the legend area.
58
- * @param {TDefaultChartFormatOptionsType} formatOptions - Formatting options for the chart including legend settings.
59
- * @param {TSeries[]} seriesData - Array of data series to be represented in the legend.
60
- * @param {string} chartId - A unique identifier for the chart, used to bind legend elements.
61
- * @param {string} legendShape - A shape for chart legends.
62
- *
63
- * @return {void} - This function does not return anything. It updates the SVG by rendering legends.
64
- */
65
- export function drawLegends(height, svg, maxLegendDimensions, chartTitleHeight, width, legendMargin, formatOptions, seriesData, chartId, legendShape) {
66
- try {
67
- let position = formatOptions.legends.legendPosition;
68
- let horizontalLegendAlignment = formatOptions.legends.legendAlignmentTopBottom;
69
- let verticalLegendAlignment = formatOptions.legends.legendAlignment;
70
- if (formatOptions.legends.legendVisibility) {
71
- switch (position) {
72
- case staticLegendPosition.none:
73
- break;
74
- case staticLegendPosition.right:
75
- let heightRight = !formatOptions.plotArea.fitChart
76
- ? height - chartTitleHeight - 20
77
- : height - chartTitleHeight - 10;
78
- legendsWithScroll(svg, seriesData, width - maxLegendDimensions[0] - 30, chartTitleHeight + 5, legendMargin + 25, heightRight, position, verticalLegendAlignment, legendShape, formatOptions, chartId);
79
- break;
80
- case staticLegendPosition.top:
81
- legendsWithScroll(svg, seriesData, 7, chartTitleHeight + 5, width - 10, 30, position, horizontalLegendAlignment, legendShape, formatOptions, chartId);
82
- break;
83
- case staticLegendPosition.left:
84
- let heightLeft = !formatOptions.plotArea.fitChart
85
- ? height - chartTitleHeight - 20
86
- : height - chartTitleHeight - 10;
87
- legendsWithScroll(svg, seriesData, 7, chartTitleHeight + 5, legendMargin + 25, heightLeft, position, verticalLegendAlignment, legendShape, formatOptions, chartId);
88
- break;
89
- case staticLegendPosition.bottom:
90
- legendsWithScroll(svg, seriesData, 7, height - 25, width - 10, 30, position, horizontalLegendAlignment, legendShape, formatOptions, chartId);
91
- break;
92
- }
93
- }
94
- }
95
- catch (error) {
96
- logError(fileName, "drawLegends", error);
97
- }
98
- }
99
- ;
100
- /**
101
- * @param {string[]} list - Array of legend strings.
102
- * @param {TDefaultChartFormatOptionsType} formatOptions - Chart formatting options including legend font size and family.
103
- * @return {{width: number, height: number}} - The calculated width and height of the longest legend text.
104
- */
105
- export function calculateMaxLegendWidth(list, formatOptions) {
106
- try {
107
- let maxLength = 0;
108
- let maxLegend = list[0];
109
- list.forEach(legend => {
110
- //legend.includes("-") ? legend.split("-")[1] :
111
- let splitedLegend = legend.includes("~$~") ? legend.split("~$~")[1] : legend.includes("-") ? legend.slice(legend.indexOf("-") + 1) : legend;
112
- let splitedLegendLength = splitedLegend.length;
113
- if (maxLength < splitedLegendLength) {
114
- maxLength = splitedLegendLength;
115
- maxLegend = splitedLegend;
116
- }
117
- });
118
- return calculateWidthHeightDynamically(maxLegend, formatOptions.legends.legendFontSize, formatOptions.legends.legendFontFamily);
119
- }
120
- catch (error) {
121
- logError(fileName, "calculateMaxLegendWidth", error);
122
- }
123
- }
124
- /**
125
- * Renders markers for line or area chart series on the provided D3 selection.
126
- * Binds marker shapes, sizes, colors, and handles visibility and interaction (tooltips).
127
- *
128
- * @param {d3.Selection<SVGGElement, unknown, null, undefined>} lines - The D3 selection (SVG group) where marker groups will be appended.
129
- * @param {TSeries[]} chartData - The data array representing chart series, each with data points and properties.
130
- * @param {string} type - The chart type (e.g., "CombiLine", "Area", "StackArea") affecting marker rendering logic.
131
- * @param {Function} xScale - D3 scale function for x-axis, used to position markers horizontally.
132
- * @param {Function} yScale - D3 scale function for y-axis, used to position markers vertically.
133
- * @param {Function} yScaleRight - D3 scale function for secodary y-axis, used to position markers vertically.
134
- * @param {Function} tooltipHandle - (Not used in current snippet but assumed) Function to manage tooltip display.
135
- * @param {TDefaultChartFormatOptionsType} formatOptions - Configuration object for chart formatting and visibility settings.
136
- * @param {TChartJSON} chartJSON - Object containing chart metadata, formatting info, and dimension mappings.
137
- * @param {number} secondaryCustomYaxisMaxValue - Maximum value for secondary Y axis scale, used for visibility logic.
138
- * @param {number} secondaryCustomYaxisMinValue - Minimum value for secondary Y axis scale, used for visibility logic.
139
- * @param {number} customYaxisMinValue - Minimum value for primary Y axis scale, used for visibility logic.
140
- * @param {number} customYaxisMaxValue - Maximum value for primary Y axis scale, used for visibility logic.
141
- * @param {boolean} isNormalizedChart - 100% chart type validation.
142
- *
143
- * @returns {void} This function does not return a value; it appends and updates SVG marker elements in the DOM.
144
- */
145
- export function lineMarkers(lines, chartData, type, xScale, yScale, yScaleRight, tooltipHandle, formatOptions, chartJSON, secondaryCustomYaxisMaxValue, secondaryCustomYaxisMinValue, customYaxisMinValue, customYaxisMaxValue, isNormalizedChart) {
146
- try {
147
- let hideZeroValues = formatOptions.plotArea.hideZeroValues;
148
- formatOptions.plotArea.plotAreaHideLineAndMarkers === undefined ? formatOptions.plotArea.plotAreaHideLineAndMarkers = true : null;
149
- chartData.forEach((d) => d.data.forEach((j) => {
150
- j["markerShape"] = (type === "CombiLine" && !formatOptions.plotArea.plotAreaHideLineAndMarkers) ? "None" : d.properties.markerShape ? d.properties.markerShape : "Circle";
151
- j["currentMeasure"] = d.properties.currentMeasure;
152
- }));
153
- chartData.forEach((d) => d.data.forEach((j) => (j["markerColor"] = d.properties.markerColor ? d.properties.markerColor : "Blue")));
154
- chartData.forEach((d) => d.data.forEach((j) => (j["markerSize"] =
155
- d.properties.markerShape != "None" && d.properties.markerSize && d.properties.markerShape != "None" ? type === "Area" ? formatOptions.plotArea.plotAreaHideLineAndMarkers ? d.properties.markerSize : 0 : d.properties.markerSize : 0)));
156
- function Markershapes(Shape) {
157
- return Shape == "Square"
158
- ? d3.symbolSquare
159
- : Shape == "Circle"
160
- ? d3.symbolCircle
161
- : Shape == "Cross"
162
- ? d3.symbolCross
163
- : Shape == "Triangle"
164
- ? d3.symbolTriangle
165
- : Shape == "Star"
166
- ? d3.symbolStar
167
- : Shape == "Diamond"
168
- ? d3.symbolDiamond
169
- : Shape == "Wye"
170
- ? d3.symbolWye
171
- : d3.symbolCircle;
172
- }
173
- // JOIN: bind parent marker groups
174
- let markerGroups = lines.selectAll(".parentGroup")
175
- .data(chartData, d => d.legend);
176
- // EXIT old groups
177
- // markerGroups.exit().remove();
178
- // ENTER new groups
179
- let markerGroupsEnter = markerGroups.enter()
180
- .append("g")
181
- .attr("class", "parentGroup")
182
- .attr("hoverId", d => {
183
- if (Array.isArray(d.legend) && d.legend.length > 0) {
184
- return d.legend.includes("~$~")
185
- ? d.legend.split("~$~")[1].replace(/ /g, "-")
186
- : d.legend.replace(/ /g, "-");
187
- }
188
- else {
189
- return d.legend.replace(/ /g, "-");
190
- }
191
- });
192
- // MERGE all groups
193
- let mergedMarkerGroups = markerGroupsEnter.merge(markerGroups);
194
- // FOR EACH group: bind marker data and render path elements
195
- mergedMarkerGroups.each(function (groupData) {
196
- const group = d3.select(this);
197
- // JOIN markers to path elements
198
- let markers = group.selectAll("path")
199
- .data(groupData.data);
200
- // EXIT old paths
201
- // markers.exit().remove();
202
- // ENTER new paths
203
- let markersEnter = markers.enter()
204
- .append("path")
205
- .attr("fill", d => d.markerColor);
206
- // ENTER + UPDATE merged paths
207
- markersEnter.merge(markers)
208
- .attr("d", d => {
209
- return d3.symbol()
210
- .type(Markershapes(d.markerShape))
211
- .size(d.markerSize * 50)();
212
- })
213
- .attr("visibility", d => {
214
- const hideByX = !xScale(d.dimension) && xScale(d.dimension) !== 0;
215
- const visible = formatOptions.marker.markerVisibility
216
- ? checkVisibleConditions(chartData, d, type, hideZeroValues, secondaryCustomYaxisMaxValue, secondaryCustomYaxisMinValue, customYaxisMinValue, customYaxisMaxValue)
217
- ? "hidden"
218
- : ([actualChartTypes.stackLine100, "CombiLine"].includes(type) ? "visible"
219
- : ([actualChartTypes.stackArea, actualChartTypes.area, "CombiArea", "CombiStackArea"].includes(type)
220
- ? (formatOptions.plotArea.plotAreaHideLineAndMarkers ? "visible" : "hidden")
221
- : "visible"))
222
- : (type === "CombiLine" ? "visible"
223
- : (["Area", "CombiArea"].includes(type)
224
- ? (formatOptions.plotArea.plotAreaHideLineAndMarkers ? "visible" : "hidden")
225
- : "hidden"));
226
- return hideByX ? "hidden" : visible;
227
- })
228
- .attr("transform", d => {
229
- let requiredYScale = d.axis == "Primary" ? yScale : yScaleRight;
230
- const x = xScale(d.dimension);
231
- const y = [actualChartTypes.stackArea100, actualChartTypes.stackArea, actualChartTypes.stackLine, actualChartTypes.stackLine100, "CombiStackArea"].includes(type)
232
- ? (d[1] > 0 ? requiredYScale(d[1]) : requiredYScale(d[0]))
233
- : requiredYScale(d.value);
234
- return `translate(${x},${y})`;
235
- })
236
- .on("mousemove", (event, d) => {
237
- showTooltipOnMouseMove([
238
- {
239
- key: formatOptions.xAxisTitle.xAxisTitleText,
240
- value: chartJSON.formattedDimensionListMap.get(Array.isArray(d.dimension) ? d.dimension[0] : d.dimension)
241
- },
242
- {
243
- key: formatOptions.yAxisTitle.yAxisTitleText || d.value,
244
- value: getNumberWithFormat(
245
- // (["combiStackArea", "StackArea", "StackLine"].includes(type) ? (d as TDataPoint).value : ["100StackLine"].includes(type) ? d[1] - d[0] : (d as TDataPoint).value),
246
- ([actualChartTypes.stackLine100, actualChartTypes.stackArea100, ""].includes(type) ? d[1] - d[0] : d.value), formatOptions.toolTip.toolTipDisplayUnits, formatOptions.toolTip.toolTipNumberFormat, formatOptions.toolTip.toolTipDecimalPrecision)
247
- },
248
- {
249
- key: "Legend",
250
- value: d.legend.includes("~$~") ? d.legend.split("~$~")[1] : d.legend
251
- },
252
- {
253
- key: "Calculated Tooltip",
254
- value: d.tooltip
255
- }
256
- ], formatOptions, event);
257
- })
258
- .on("mouseout", () => {
259
- hideTooltipOnMouseOut();
260
- });
261
- });
262
- }
263
- catch (error) {
264
- logError(fileName, "lineMarkers", error);
265
- }
266
- }
267
- /**
268
- * Determines whether a data point should be hidden based on visibility rules, axis scales, and zero value hiding.
269
- *
270
- * @param {TSeries[]} chartData - Array of chart series data, used to check axis property of the first series.
271
- * @param {any} d - Data point to check visibility for; expected to have properties like Measure, [0], and [1].
272
- * @param {string} type - Chart type string (e.g., "StackArea"), influences visibility logic for stacked charts.
273
- * @param {boolean} hideZeroValues - Flag indicating whether zero values should be hidden.
274
- * @param {number} secondaryCustomYaxisMaxValue - Maximum allowed value on secondary Y axis.
275
- * @param {number} secondaryCustomYaxisMinValue - Minimum allowed value on secondary Y axis.
276
- * @param {number} customYaxisMinValue - Minimum allowed value on primary Y axis.
277
- * @param {number} customYaxisMaxValue - Maximum allowed value on primary Y axis.
278
- *
279
- * @returns {boolean} True if the data point should be hidden based on the conditions; false otherwise.
280
- */
281
- const checkVisibleConditions = (chartData, d, type, hideZeroValues, secondaryCustomYaxisMaxValue, secondaryCustomYaxisMinValue, customYaxisMinValue, customYaxisMaxValue) => {
282
- try {
283
- if (chartData[0].properties.axis && chartData[0].properties.axis === "Secondary") {
284
- return (hideZeroValues && d.Measure == 0) || d.Measure > secondaryCustomYaxisMaxValue || d.Measure < secondaryCustomYaxisMinValue;
285
- }
286
- else if (type.includes("Stack")) {
287
- return (d.Measure > 0) ? ((hideZeroValues && d[1] == 0) || d[1] < customYaxisMinValue || d[1] > customYaxisMaxValue) : ((hideZeroValues && d[0] == 0) || d[0] < customYaxisMinValue || d[0] > customYaxisMaxValue);
288
- }
289
- else
290
- return (hideZeroValues && d.Measure == 0) || d.Measure < customYaxisMinValue || d.Measure > customYaxisMaxValue;
291
- }
292
- catch (error) {
293
- logError(fileName, "checkVisibleConditions", error);
294
- }
295
- };
296
- /**
297
- * Attaches hover interactions to the area chart elements to show markers and tooltips
298
- * when the user moves the mouse over the chart.
299
- *
300
- * @param {TDefaultChartFormatOptionsType} formatOptions - Configuration options for chart appearance and tooltip formatting.
301
- * @param {any} areas - D3 selection representing the area paths of the chart.
302
- * @param {any} focus - D3 selection representing the group or element used for showing the focus marker and tooltip.
303
- * @param {string[]} filteredDimension - Array of dimension values representing the x-axis categories.
304
- * @param {any[]} lineData - Array of data series objects containing values, marker properties, and metadata.
305
- * @param {any} xScale - D3 scale function for the x-axis.
306
- * @param {any} yScaleLeft - D3 scale function for the left y-axis.
307
- * @param {string} chartType - The type of area chart (e.g., "stackArea", "stackArea100").
308
- *
309
- * @return {void} This function modifies the chart's behavior by adding interactivity but does not return a value.
310
- */
311
- export function onHoverMarkerForAreaChartFamily(formatOptions, areas, focus, filteredDimension, lineData, xScale, yScaleLeft, chartType) {
312
- try {
313
- if (!formatOptions.plotArea.plotAreaHideLineAndMarkers) {
314
- areas
315
- .on("mouseover", function () {
316
- focus.style("display", null);
317
- })
318
- .on("mousemove", mousemove)
319
- .on("mouseout", function () {
320
- focus.style("display", "none");
321
- hideTooltipOnMouseOut();
322
- //
323
- });
324
- }
325
- // .on("mousemove", mouseout)
326
- let demList = filteredDimension;
327
- function mousemove(event) {
328
- try {
329
- let m = d3.pointer(event), lowDiff = 1e99, legendIndex, dimensionIndex = null;
330
- for (let i = 0; i < demList.length; i++) {
331
- let diff = Math.abs(m[0] - xScale(demList[i]));
332
- if (diff < lowDiff) {
333
- lowDiff = diff;
334
- dimensionIndex = i;
335
- }
336
- }
337
- let mindiff = 1e99;
338
- for (let k = 0; k < lineData.length; k++) {
339
- let diff1 = Math.abs(m[1] - yScaleLeft(lineData[k].data[dimensionIndex].value));
340
- if (diff1 < mindiff) {
341
- mindiff = diff1;
342
- legendIndex = k;
343
- }
344
- }
345
- focus
346
- .attr("transform", getCoordinates(lineData[legendIndex], dimensionIndex, xScale, yScaleLeft))
347
- .append("circle")
348
- .attr("r", lineData[legendIndex].properties.markerSize * 2.5)
349
- .attr("id", "tooltip")
350
- // .attr("id", lineData[0].AxisDataList[dimensionIndex].Dimension)
351
- .attr("fill", lineData[legendIndex].properties.markerColor)
352
- .text(showTooltipOnMouseMove([
353
- { key: formatOptions.xAxisTitle.xAxisTitleText, value: lineData[legendIndex].data[dimensionIndex].dimension },
354
- {
355
- key: lineData[legendIndex].properties.currentMeasure ? lineData[legendIndex].properties.currentMeasure : this.basestyle.YAxisTitle.YAxisTitleText,
356
- value: getNumberWithFormat((chartType === actualChartTypes.stackArea100) ? (legendIndex === 0 ? lineData[legendIndex].data[dimensionIndex].value : lineData[legendIndex].data[dimensionIndex].value - lineData[legendIndex - 1].data[dimensionIndex].value) : lineData[legendIndex].data[dimensionIndex].value, formatOptions.toolTip.toolTipDisplayUnits, formatOptions.toolTip.toolTipNumberFormat, formatOptions.toolTip.toolTipDecimalPrecision),
357
- },
358
- { key: "Legend", value: lineData[legendIndex].data[dimensionIndex].legend.includes("~$~") ? lineData[legendIndex].data[dimensionIndex].legend.split("~$~")[1] : lineData[legendIndex].data[dimensionIndex].legend },
359
- // { key: "Calculated Tooltip", value: lineData[legendIndex].data[dimensionIndex]. },
360
- ], formatOptions));
361
- }
362
- catch (error) {
363
- logError(fileName, "onHoverMarkerForAreaChartFamily.mousemove", error);
364
- }
365
- }
366
- }
367
- catch (error) {
368
- logError(fileName, "onHoverMarkerForAreaChartFamily", error);
369
- }
370
- }
371
- /**
372
- * Calculates the SVG `transform` attribute value to position a marker
373
- * at the correct (x, y) coordinate based on chart data and scales.
374
- *
375
- * @param {any} chartData - A single series object containing `data`, which holds dimension and value pairs.
376
- * @param {number} pos - Index in the `chartData.data` array to locate the specific data point.
377
- * @param {any} xScale - D3 scale function used to convert the dimension to an x-coordinate.
378
- * @param {any} yScaleLeft - D3 scale function used to convert the value to a y-coordinate.
379
- *
380
- * @return {string} A `translate(x, y)` string used for SVG positioning.
381
- */
382
- const getCoordinates = (chartData, pos, xScale, yScaleLeft) => {
383
- try {
384
- return `translate(${xScale(chartData.data[pos].dimension)},${yScaleLeft(chartData.data[pos].value)})`;
385
- }
386
- catch (error) {
387
- logError(fileName, "getCoordinates", error);
388
- }
389
- };
390
- /**
391
- * Function to calculate actual height, width of content primarily used for margin calculations
392
- * @returns { width: 0, height: 0, rotatedWidth: 0, rotatedHeight: 0 }
393
- */
394
- export function preCalculateTextDimensions(content, fontSize, fontFamily, rotationDegree, fixedWidth) {
395
- try {
396
- const div = document.createElement('div');
397
- Object.assign(div.style, {
398
- position: 'absolute',
399
- visibility: 'hidden',
400
- top: '0',
401
- left: '0',
402
- margin: '0',
403
- padding: '0',
404
- border: 'none',
405
- whiteSpace: 'nowrap',
406
- overflowWrap: '',
407
- transform: '',
408
- });
409
- document.body.appendChild(div);
410
- div.style.transform = '';
411
- div.style.width = '';
412
- div.style.whiteSpace = 'nowrap';
413
- div.style.overflowWrap = '';
414
- if (fontSize != null)
415
- div.style.fontSize = `${fontSize}px`;
416
- if (fontFamily != null)
417
- div.style.fontFamily = fontFamily;
418
- if (fixedWidth != null) {
419
- // to calculate height of content if width is restricted
420
- div.style.width = `${fixedWidth}px`;
421
- div.style.whiteSpace = 'normal';
422
- div.style.overflowWrap = 'break-word';
423
- }
424
- // Set text and measure
425
- div.textContent = content;
426
- const baseRect = div.getBoundingClientRect();
427
- const w = baseRect.width, h = baseRect.height;
428
- // Optional rotation
429
- if (rotationDegree && rotationDegree !== 0) {
430
- div.style.transform = `rotate(${rotationDegree}deg)`;
431
- const rotRect = div.getBoundingClientRect();
432
- div.remove();
433
- return { width: w, height: h, rotatedWidth: rotRect.width, rotatedHeight: rotRect.height };
434
- }
435
- div.remove();
436
- return { width: w, height: h, rotatedWidth: 0, rotatedHeight: 0 };
437
- }
438
- catch (error) {
439
- logError(fileName, "preCalculateTextDimensions", error);
440
- }
441
- }
442
- /**
443
- * adds non defined properties from `defaults` to `target` to avoid further checks for undefined values
444
- * @param defaults -> Object which contains default properties
445
- * @param target -> Object which may contain some undefined properties
446
- * @returns object with all properties from defaults
447
- */
448
- export function addUndefinedDefaults(defaults, target) {
449
- try {
450
- if (typeof defaults !== 'object' || defaults === null) {
451
- throw new TypeError('`defaults` must be a non-null object');
452
- }
453
- if (typeof target !== 'object' || target === null) {
454
- throw new TypeError('`target` must be a non-null object');
455
- }
456
- Object.keys(defaults).forEach((key) => {
457
- const defaultVal = defaults[key];
458
- const targetHasKey = Object.prototype.hasOwnProperty.call(target, key);
459
- const targetVal = target[key];
460
- // If key is missing or explicitly undefined, adopt the default wholesale
461
- if (!targetHasKey || targetVal === undefined) {
462
- // Note: clone objects/arrays to avoid accidental shared references
463
- target[key] = Array.isArray(defaultVal)
464
- ? [...defaultVal]
465
- : (typeof defaultVal === 'object' && defaultVal !== null)
466
- ? { ...defaultVal }
467
- : defaultVal;
468
- return;
469
- }
470
- // Both have the key and both values are plain objects → recurse
471
- const isDefaultPlainObj = isPlainObject(defaultVal);
472
- const isTargetPlainObj = isPlainObject(targetVal);
473
- if (isDefaultPlainObj && isTargetPlainObj) {
474
- addUndefinedDefaults(defaultVal, targetVal);
475
- }
476
- // Otherwise: target already has a concrete (non-object) value → leave it
477
- });
478
- return target;
479
- }
480
- catch (error) {
481
- logError(fileName, "addUndefinedDefaults", error);
482
- }
483
- }
484
- /** Helper: is a value a plain (literal) object? */
485
- function isPlainObject(val) {
486
- try {
487
- return Object.prototype.toString.call(val) === '[object Object]';
488
- }
489
- catch (error) {
490
- logError(fileName, "isPlainObject", error);
491
- }
492
- }
493
- /**
494
- * Number formating function
495
- * @returns function which takes number as input and return formatted number
496
- */
497
- export function getNumberWithFormatFunction(displayUnits, numberFormat, decimalPrecision) {
498
- try {
499
- let Unit;
500
- let displayUnitsPostFix = "";
501
- let decimalValues = decimalPrecision;
502
- let formatter;
503
- return function (d) {
504
- try {
505
- if (displayUnits != "None") {
506
- displayUnits == "Thousands"
507
- ? ((Unit = 1000), (displayUnitsPostFix = "K"))
508
- : null;
509
- displayUnits == "Millions"
510
- ? ((Unit = 1000000), (displayUnitsPostFix = "M"))
511
- : null;
512
- displayUnits == "Billions"
513
- ? ((Unit = 1000000000), (displayUnitsPostFix = "B"))
514
- : null;
515
- d = d / Unit;
516
- }
517
- switch (numberFormat) {
518
- case ",.0%":
519
- formatter = `.${decimalValues}%`;
520
- return d3.format(formatter)(d);
521
- case "":
522
- formatter = `.${decimalValues}f`;
523
- return d3.format(formatter)(d) + displayUnitsPostFix;
524
- case ".2n":
525
- formatter = `.${decimalValues == 0 ? 1 : (parseFloat(decimalValues) + 1).toString()}n`;
526
- return d3.format(formatter)(d) + displayUnitsPostFix;
527
- case ".2$":
528
- formatter = `,.${decimalValues}f`;
529
- return "$" + d3.format(formatter)(d) + displayUnitsPostFix;
530
- case ".2c":
531
- formatter = `,.${decimalValues}f`;
532
- return "C$" + d3.format(formatter)(d) + displayUnitsPostFix;
533
- case ".2ē":
534
- formatter = `,.${decimalValues}f`;
535
- return "€" + d3.format(formatter)(d) + displayUnitsPostFix;
536
- case ".2ch":
537
- formatter = `,.${decimalValues}f`;
538
- return "CHF" + d3.format(formatter)(d) + displayUnitsPostFix;
539
- case ".2£":
540
- formatter = `,.${decimalValues}f`;
541
- return "£" + d3.format(formatter)(d) + displayUnitsPostFix;
542
- case ".2₹":
543
- formatter = `,.${decimalValues}f`;
544
- return "₹" + d3.format(formatter)(d) + displayUnitsPostFix;
545
- case ",":
546
- formatter = `,.${decimalValues}f`;
547
- return d3.format(formatter)(d) + displayUnitsPostFix;
548
- default:
549
- formatter = `.${2}f`;
550
- return d3.format(formatter)(d) + displayUnitsPostFix;
551
- }
552
- }
553
- catch (error) {
554
- logError(fileName, "getNumberWithFormatFunction.inner", error);
555
- }
556
- };
557
- }
558
- catch (error) {
559
- logError(fileName, "getNumberWithFormatFunction", error);
560
- }
561
- }
562
- /**
563
- * @param elements -> array of key value pair which should be added to tooltip one after another;
564
- * @param chartFormatOptions -> rightpane format options;
565
- * @param event -> optional mouse event to track mouse;
566
- */
567
- export function showTooltipOnMouseMove(elements, chartFormatOptions, event) {
568
- try {
569
- d3.selectAll(".chartTooltip").style("visibility", "hidden");
570
- // Clear and create new tooltip container
571
- let tooltip = d3
572
- .select("#chartTooltipDiv")
573
- .html("")
574
- .append("div")
575
- .attr("class", chartFormatOptions.toolTip.toolTipTheme == "Light"
576
- ? "tooltipParentLight chartTooltip"
577
- : "tooltipParentDark chartTooltip");
578
- // Use passed event or fallback
579
- const e = event || window.event;
580
- const mouseX = e.pageX;
581
- const mouseY = e.pageY;
582
- // Build content
583
- const tooltipElements = elements.reduce((p, c) => {
584
- p += `<label class="tooltipLabel">${c.value ? c.key : ""}</label>
585
- <span class="tooltipValue">${c.value ? c.value : ""}</span>`;
586
- return p;
587
- }, ``);
588
- tooltip.html(`<div class="arrow-placeholder"></div>
589
- <div class="tooltipInner">${tooltipElements}</div>`);
590
- // Get tooltip dimensions after it's in DOM
591
- const tooltipNode = tooltip.node();
592
- const tooltipWidth = tooltipNode.offsetWidth;
593
- const tooltipHeight = tooltipNode.offsetHeight;
594
- // Determine quadrant (screen is divided into 4 from center)
595
- const halfWidth = window.innerWidth / 2;
596
- const halfHeight = window.innerHeight / 2;
597
- let left = 0;
598
- let top = 0;
599
- let arrow = "";
600
- if (mouseX > halfWidth && mouseY < halfHeight) {
601
- // Top-right
602
- left = mouseX - tooltipWidth - 10;
603
- top = mouseY - 10;
604
- arrow = "right-top";
605
- }
606
- else if (mouseX < halfWidth && mouseY < halfHeight) {
607
- // Top-left
608
- left = mouseX + 20;
609
- top = mouseY - 10;
610
- arrow = "left-top";
611
- }
612
- else if (mouseX < halfWidth && mouseY >= halfHeight) {
613
- // Bottom-left
614
- left = mouseX + 20;
615
- top = mouseY - tooltipHeight + 10;
616
- arrow = "left-bottom";
617
- }
618
- else {
619
- // Bottom-right
620
- left = mouseX - tooltipWidth - 10;
621
- top = mouseY - tooltipHeight + 10;
622
- arrow = "right-bottom";
623
- }
624
- // Set final position
625
- tooltip
626
- .style("left", `${left}px`)
627
- .style("top", `${top}px`)
628
- .style("visibility", chartFormatOptions.toolTip.toolTipVisibility ? "visible" : "hidden");
629
- // Update arrow direction
630
- tooltip.select(".arrow-placeholder").attr("class", `arrow-${arrow}`);
631
- }
632
- catch (error) {
633
- logError(fileName, "showTooltipOnMouseMove", error);
634
- }
635
- }
636
- export function hideTooltipOnMouseOut() {
637
- try {
638
- d3
639
- .select("#chartTooltipDiv")
640
- .html("")
641
- .style("visibility", "hidden");
642
- }
643
- catch (error) {
644
- logError(fileName, "hideTooltipOnMouseOut", error);
645
- }
646
- }
647
- /**
648
- * Adds chart title to svg
649
- * @param chartSvg -> svgRef from use ref hook;
650
- * @param chartTitleHeight -> height of chart title;
651
- * @param chartTitleWidth -> width of chart title;
652
- * @param chartFormatOptions -> rightpane format options;
653
- */
654
- export const drawChartTitle = (chartSvg, chartTitleHeight, chartTitleWidth, chartFormatOptions) => {
655
- try {
656
- let svg = d3.select(chartSvg.current);
657
- let object = svg
658
- .append("foreignObject")
659
- .attr("visibility", chartFormatOptions.chartTitle.chartTitleVisibility
660
- ? "visible"
661
- : "hidden")
662
- .attr("transform", `translate(2,2)`)
663
- .attr("class", "chartTitle")
664
- .attr("width", chartTitleWidth)
665
- .attr("height", chartTitleHeight + "px");
666
- // if text set from editor except default chart title
667
- if (chartFormatOptions.chartTitle.dynamicTitleText.length !== 0) {
668
- object
669
- .append("xhtml:div")
670
- .style("color", "rgba(119,119,119)")
671
- .attr("title", chartFormatOptions.chartTitle.chartTitleText)
672
- .style("white-space", "pre")
673
- .style("text-overflow", "ellipsis")
674
- .html(chartFormatOptions.chartTitle.chartTitleHTML
675
- ? chartFormatOptions.chartTitle.chartTitleHTML
676
- : chartFormatOptions.chartTitle.chartTitleText);
677
- }
678
- else {
679
- object
680
- .append("xhtml:div")
681
- .style("white-space", "pre")
682
- .style("user-select", "none")
683
- .style("text-overflow", "ellipsis")
684
- .style("overflow", "hidden")
685
- .attr("class", "chartTiltle")
686
- .attr("id", "chartTitleId")
687
- .style("text-anchor", "start")
688
- .style("color", "rgba(119,119,119)")
689
- .style("font-size", "16px")
690
- .style("font-family", chartFormatOptions.chartTitle.chartTitleFontFamily)
691
- .attr("title", chartFormatOptions.chartTitle.chartTitleText)
692
- .html(chartFormatOptions.chartTitle.chartTitleText);
693
- }
694
- }
695
- catch (error) {
696
- logError(fileName, "drawChartTitle", error);
697
- }
698
- };
699
- /**
700
- * Finds the longest string from an array of strings or an array of objects.
701
- * @param {Array<string | Object>} data -> The input array containing strings or objects.
702
- * @param {string} [key] -> (Optional) If the array contains objects, specify the key to extract string values.
703
- * @returns {string} The longest string found in the array.
704
- */
705
- export const findStringWithLongestLength = (data, key) => {
706
- try {
707
- return data.reduce((longest, item) => {
708
- const currentValue = typeof item === "string"
709
- ? item
710
- : (key && typeof item === "object" && item[key]) || "";
711
- return currentValue.length > longest.length ? currentValue : longest;
712
- }, "");
713
- }
714
- catch (error) {
715
- logError(fileName, "findStringWithLongestLength", error);
716
- }
717
- };
718
- /**
719
- * Renders chart legends within an SVG element with scroll support when needed.
720
- * @param {SVGElement} svg - The D3 or SVG selection where the legends will be appended.
721
- * @param {TSeries[]} seriesData - Array of data series passed to chart as props.
722
- * @param {number} x - The x-coordinate for placing the legends container.
723
- * @param {number} y - The y-coordinate for placing the legends container.
724
- * @param {number} width - The width of the legend container.
725
- * @param {number} height - The height of the legend container.
726
- * @param {string} legendPosition - The position of the legend (e.g., 'top', 'bottom', 'left', 'right').
727
- * @param {string} alignment - Alignment of the legends within the container ('start', 'center', 'end', 'Top','Mid','Bottom').
728
- * @param {string} legendShape - Shape of the legend symbol (e.g., 'circle', 'rect', 'line', 'hollow circle').
729
- * @param {TDefaultChartFormatOptionsType} chartFormatOptions - Configuration object for formatting styles and settings.
730
- * @param {string} chartId - Unique ID for the chart, used to identify elements within the SVG.
731
- */
732
- export const legendsWithScroll = (svg, seriesData, x, y, width, height, legendPosition, alignment, legendShape, chartFormatOptions, chartId, isVennChart = false) => {
733
- try {
734
- if (chartFormatOptions.legends.legendVisibility) {
735
- let justifyContent = "";
736
- let flexDirection = "";
737
- if (legendPosition == staticLegendPosition.left || legendPosition == staticLegendPosition.right) {
738
- flexDirection = "column";
739
- justifyContent =
740
- alignment == verticalLegendAllignment.top ? "start" : alignment == verticalLegendAllignment.middle ? "center" : "end";
741
- }
742
- else {
743
- flexDirection = "row";
744
- justifyContent =
745
- alignment == horizontalLegendAllignment.start
746
- ? "start"
747
- : alignment == horizontalLegendAllignment.middle
748
- ? "center"
749
- : "end";
750
- }
751
- let object = svg
752
- .append("foreignObject")
753
- .attr("x", x)
754
- .attr("y", y)
755
- .style("pointer-events", "auto")
756
- .attr("width", width + "px")
757
- .attr("height", height + "px")
758
- .style("user-select", "none");
759
- var div = object
760
- .append("xhtml:div")
761
- .attr("id", "legendObject" + chartId)
762
- .attr("class", "legendsBoxWrapper")
763
- .style("width", width + "px")
764
- .style("display", "flex")
765
- .style("height", height - 1 + "px")
766
- .style("overflow", "auto")
767
- .style("pointer-events", "auto")
768
- .style("justify-content", justifyContent)
769
- .style("flex-direction", flexDirection)
770
- .style("outline-offset", '-' + chartFormatOptions.legends.legendBorderThickness + "px")
771
- .style("outline", chartFormatOptions.legends.legendBorder
772
- ? `${chartFormatOptions.legends.legendBorderThickness +
773
- "px" +
774
- " solid" +
775
- chartFormatOptions.legends.legendBorderColor}`
776
- : "none")
777
- .append("div")
778
- // .style("width", "100%")
779
- .attr("class", "scrollbar")
780
- .style("display", "flex")
781
- .style("justify-content", justifyContent)
782
- .style("flex-direction", flexDirection)
783
- .style("flex-wrap", "nowrap")
784
- .style("padding-left", "3px");
785
- if (legendPosition == staticLegendPosition.top || legendPosition == staticLegendPosition.bottom)
786
- div.style("flex-direction", "row");
787
- seriesData.forEach((d, i) => {
788
- let innerdiv = div
789
- .append("div")
790
- .style("display", "inline-flex")
791
- .style("justify-content", "flex-start")
792
- .style("align-items", "center")
793
- .style("width", "fit-content")
794
- .style("margin", "3px 0px")
795
- .style("flex-wrap", "nowrap")
796
- .style("white-space", "nowrap")
797
- .on("mousemove", function (d) {
798
- if (chartFormatOptions.legends.onHoverEffect) {
799
- svg
800
- .selectAll(".parentGroup")
801
- .classed("highlight", false)
802
- .classed("unhighlight", true);
803
- svg
804
- .selectAll('[hoverId="' + this.textContent.replace(/ /g, "-") + '"]')
805
- .classed("highlight", true)
806
- .classed("unhighlight", false);
807
- }
808
- })
809
- .on("mouseout", function (d) {
810
- if (chartFormatOptions.legends.onHoverEffect) {
811
- svg
812
- .selectAll(".parentGroup")
813
- .classed("highlight", false)
814
- .classed("unhighlight", false);
815
- svg
816
- .selectAll('[hoverId="' + this.textContent.replace(/ /g, "-") + '"]')
817
- .classed("highlight", false)
818
- .classed("unhighlight", false);
819
- }
820
- });
821
- if (legendPosition == staticLegendPosition.top || legendPosition == staticLegendPosition.bottom) {
822
- innerdiv.style("margin-right", isVennChart ? "0px" : "16px").style("white-space", "nowrap");
823
- }
824
- if (legendShape == staticLegendShape.circle) {
825
- getCircleShape(d, innerdiv);
826
- }
827
- else if (legendShape == staticLegendShape.circle) {
828
- getHollowCircleShape(d, innerdiv);
829
- }
830
- else if (legendShape == staticLegendShape.line) {
831
- getLineShape(d, innerdiv, chartFormatOptions);
832
- }
833
- else if (legendShape == staticLegendShape.areaWithLine) {
834
- getAreaShape(d, innerdiv, chartFormatOptions);
835
- }
836
- else if (legendShape == staticLegendShape.rectangle) {
837
- getReactShape(d, innerdiv);
838
- }
839
- let vennSaparator = (isVennChart && (legendPosition == staticLegendPosition.bottom || legendPosition == staticLegendPosition.top)) ? (i != seriesData.length - 1 ? ' |' : '') : '';
840
- let legendColor = isVennChart ? chartFormatOptions.legends.legendSelectedUnicolor :
841
- (chartFormatOptions.legends.legendColorMode == legendColorMode.multiColor)
842
- ? d.properties.color
843
- ? d.properties.color
844
- : "#000000"
845
- : chartFormatOptions.legends.legendSelectedUnicolor;
846
- innerdiv
847
- .append("div")
848
- .style("margin-left", "5px")
849
- .style("color", legendColor)
850
- .style("font-size", (!isVennChart ? d.properties.fontSize : chartFormatOptions.legends.legendFontSize) + "px")
851
- .style("font-family", !isVennChart ? d.properties.fontFamily : chartFormatOptions.legends.legendFontFamily)
852
- .style("font-style", () => {
853
- let style = !isVennChart ? d.properties.fontStyle : chartFormatOptions.legends.legendFontStyle;
854
- return style.includes(fontStyleOptions.italic) ? fontStyleOptions.italic : "";
855
- })
856
- .style("text-decoration", () => {
857
- let style = !isVennChart ? d.properties.fontStyle : chartFormatOptions.legends.legendFontStyle;
858
- return style.includes(fontStyleOptions.underline) ? fontStyleOptions.underline : "";
859
- })
860
- .style("font-weight", () => {
861
- let style = !isVennChart ? d.properties.fontStyle : chartFormatOptions.legends.legendFontStyle;
862
- return style.includes(fontStyleOptions.bold) ? fontStyleOptions.bold : "";
863
- })
864
- .style("white-space", "nowrap")
865
- .attr("title", !isVennChart ? d.properties.alias : d.legendDisplay + ' : ' + d.actualValue)
866
- .html(!isVennChart ? d.properties.alias : d.legendDisplay + ' : ' + d.actualValue + vennSaparator);
867
- });
868
- }
869
- }
870
- catch (error) {
871
- logError(fileName, "legendsWithScroll", error);
872
- }
873
- };
874
- // Functionality of legends without scroll bar but having buttons for scroll functionality
875
- // On Hold, will resume after finishing with all charts
876
- // export const legendsWithScroll = (
877
- // svg: any,
878
- // seriesData: TSeries[],
879
- // x: number,
880
- // y: number,
881
- // width: number,
882
- // height: number,
883
- // legendPosition: string,
884
- // alignment: string,
885
- // legendShape: string,
886
- // chartFormatOptions: TDefaultChartFormatOptionsType,
887
- // chartId: string
888
- // ) => {
889
- // // 1. Flex and alignment logic
890
- // let justifyContent = "";
891
- // let flexDirection = "";
892
- // if (legendPosition === "Left" || legendPosition === "Right") {
893
- // flexDirection = "column";
894
- // justifyContent =
895
- // alignment === "Top" ? "flex-start" :
896
- // alignment === "Middle" ? "center" : "flex-end";
897
- // } else {
898
- // flexDirection = "row";
899
- // justifyContent =
900
- // alignment === "Start" ? "flex-start" :
901
- // alignment === "Middle" ? "center" : "flex-end";
902
- // }
903
- // // 2. Main container
904
- // const foreignObject = svg
905
- // .append("foreignObject")
906
- // .attr("x", x)
907
- // .attr("y", y)
908
- // .attr("width", width)
909
- // .attr("height", height)
910
- // .style("pointer-events", "auto");
911
- // // 3. Legend wrapper (for buttons and content)
912
- // const legendWrapper = foreignObject
913
- // .append("xhtml:div")
914
- // .attr("id", "legendWrapper" + chartId)
915
- // .style("position", "relative")
916
- // .style("width", width + "px")
917
- // .style("height", height + "px")
918
- // .style("overflow", "hidden")
919
- // .style("display", "flex")
920
- // .style("align-items", "center")
921
- // .style("justify-content", "center")
922
- // .style("background", "transparent");
923
- // // 4. Scrollable content area
924
- // const content = legendWrapper
925
- // .append("div")
926
- // .attr("class", "legend-content")
927
- // .style("display", "flex")
928
- // .style("flex-direction", flexDirection)
929
- // .style("justify-content", justifyContent)
930
- // .style("align-items", "center")
931
- // .style("height", flexDirection === "row" ? "100%" : "auto")
932
- // .style("width", flexDirection === "row" ? "calc(100% - 40px)" : "100%")
933
- // .style("overflow", "hidden")
934
- // .style("scroll-behavior", "smooth")
935
- // .style("margin", flexDirection === "row" ? "0 16px" : "30px 0");
936
- // // 5. Add legend entries
937
- // seriesData.forEach((d, i) => {
938
- // const entry = content
939
- // .append("div")
940
- // .attr("class", "legend-entry")
941
- // .style("display", "inline-flex")
942
- // .style("align-items", "center")
943
- // .style("margin", flexDirection === "row" ? "0 8px 0 0" : "0 0 8px 0")
944
- // .style("white-space", "nowrap")
945
- // .on("mousemove", function () {
946
- // if (chartFormatOptions.legends.onHoverEffect) {
947
- // svg.selectAll(".parentGroup")
948
- // .classed("highlight", false)
949
- // .classed("unhighlight", true);
950
- // svg.selectAll('[hoverId="' + d.legend.replace(/ /g, "-") + '"]')
951
- // .classed("highlight", true)
952
- // .classed("unhighlight", false);
953
- // }
954
- // })
955
- // .on("mouseout", function () {
956
- // if (chartFormatOptions.legends.onHoverEffect) {
957
- // svg.selectAll(".parentGroup")
958
- // .classed("highlight", false)
959
- // .classed("unhighlight", false);
960
- // svg.selectAll('[hoverId="' + d.legend.replace(/ /g, "-") + '"]')
961
- // .classed("highlight", false)
962
- // .classed("unhighlight", false);
963
- // }
964
- // });
965
- // // Add legend shape
966
- // if (legendShape === staticLegendShape.circle) {
967
- // getCircleShape(d, entry);
968
- // } else if (legendShape === staticLegendShape.circle) {
969
- // getHollowCircleShape(d, entry);
970
- // } else if (legendShape === staticLegendShape.line) {
971
- // getLineShape(d, entry);
972
- // } else if (legendShape === staticLegendShape.areaWithLine) {
973
- // getAreaShape(d, entry);
974
- // } else if (legendShape === staticLegendShape.rectangle) {
975
- // getReactShape(d, entry);
976
- // }
977
- // // Add legend text
978
- // let legendColor =
979
- // chartFormatOptions.legends.legendColorMode === 1
980
- // ? d.properties.Color || "#000000"
981
- // : chartFormatOptions.legends.legendSelectedUnicolor;
982
- // entry.append("div")
983
- // .style("margin-left", "5px")
984
- // .style("color", legendColor)
985
- // .style("font-size", d.properties.FontSize + "px")
986
- // .style("font-family", d.properties.FontFamily)
987
- // .style("font-style", d.properties.FontStyle.includes(fontStyleOptions.italic) ? fontStyleOptions.italic : "")
988
- // .style("text-decoration", d.properties.FontStyle.includes(fontStyleOptions.underline) ? fontStyleOptions.underline : "")
989
- // .style("font-weight", d.properties.FontStyle.includes(fontStyleOptions.bold) ? fontStyleOptions.bold : "")
990
- // .style("white-space", "nowrap")
991
- // .attr("title", d.legend)
992
- // .html(d.legend);
993
- // });
994
- // // 6. Add scroll buttons
995
- // const btnStyle = `
996
- // position: absolute;
997
- // background: rgba(250,250,250,0.85);
998
- // border: unset;
999
- // border-radius: 3px;
1000
- // width: 15px;
1001
- // height: 22px;
1002
- // display: flex;
1003
- // align-items: center;
1004
- // justify-content: center;
1005
- // cursor: pointer;
1006
- // z-index: 10;
1007
- // font-size: 12px;
1008
- // box-shadow: 0 1px 4px rgba(0,0,0,0.08);
1009
- // opacity: 0.85;
1010
- // transition: opacity 0.2s;
1011
- // color: grey;
1012
- // outline: none;
1013
- // padding: unset;
1014
- // `;
1015
- // // Left/Top button
1016
- // const leftBtn = legendWrapper
1017
- // .append("button")
1018
- // .attr("type", "button")
1019
- // .attr("tabindex", -1)
1020
- // .attr("aria-label", flexDirection === "row" ? "Scroll left" : "Scroll up")
1021
- // .style("display", "none")
1022
- // .attr("style", btnStyle +
1023
- // (flexDirection === "row"
1024
- // ? "left:1px;top:50%;transform:translateY(-50%);"
1025
- // : "top:0;left:50%;transform:translateX(-50%);"))
1026
- // .text(flexDirection === "row" ? "◀" : "▲");
1027
- // // Right/Bottom button
1028
- // const rightBtn = legendWrapper
1029
- // .append("button")
1030
- // .attr("type", "button")
1031
- // .attr("tabindex", -1)
1032
- // .attr("aria-label", flexDirection === "row" ? "Scroll right" : "Scroll down")
1033
- // .style("display", "none")
1034
- // .attr("style", btnStyle +
1035
- // (flexDirection === "row"
1036
- // ? "right:1px;top:50%;transform:translateY(-50%);"
1037
- // : "bottom:0;left:50%;transform:translateX(-50%);"))
1038
- // .text(flexDirection === "row" ? "▶" : "▼");
1039
- // // 7. Scrolling logic
1040
- // function updateButtonVisibility() {
1041
- // if (flexDirection == "row") {
1042
- // if (content.node().clientWidth == content.node().scrollWidth) {
1043
- // content.node().style.width = "100%";
1044
- // content.node().style.margin = "10px 0";
1045
- // leftBtn.remove();
1046
- // rightBtn.remove();
1047
- // }
1048
- // }
1049
- // }
1050
- // function scrollContent(amount: number) {
1051
- // const node = content.node() as HTMLElement;
1052
- // if (!node) return;
1053
- // if (flexDirection === "row") {
1054
- // node.scrollBy({ left: amount, behavior: "smooth" });
1055
- // } else {
1056
- // node.scrollBy({ top: amount, behavior: "smooth" });
1057
- // }
1058
- // }
1059
- // leftBtn.on("click", () => scrollContent(flexDirection === "row" ? -100 : -50));
1060
- // rightBtn.on("click", () => scrollContent(flexDirection === "row" ? 100 : 50));
1061
- // // Mouse wheel scrolling
1062
- // content.on("wheel", function (event: any) {
1063
- // const node = this as HTMLElement;
1064
- // if (flexDirection === "row") {
1065
- // node.scrollLeft += event.deltaY;
1066
- // } else {
1067
- // node.scrollTop += event.deltaY;
1068
- // }
1069
- // event.preventDefault();
1070
- // });
1071
- // updateButtonVisibility();
1072
- // // Update buttons on scroll and resize
1073
- // // content.on("scroll", updateButtonVisibility);
1074
- // // setTimeout(updateButtonVisibility, 100); // Initial
1075
- // // Optional: update on window resize
1076
- // // window.addEventListener("resize", updateButtonVisibility);
1077
- // };
1078
- /**
1079
- *
1080
- * Appends a filled circle shape to the given legend container.
1081
- * @param d - The data object containing legend properties (like color, size).
1082
- * @param innerDiv - The D3 selection where the shape will be appended.
1083
- */
1084
- export function getCircleShape(d, innerDiv) {
1085
- try {
1086
- innerDiv
1087
- .append("div")
1088
- .style("height", "12px")
1089
- .style("width", "12px")
1090
- .style("border-radius", "50%")
1091
- .style("background", d.properties.color);
1092
- }
1093
- catch (error) {
1094
- logError(fileName, "getCircleShape", error);
1095
- }
1096
- }
1097
- /**
1098
- * Appends a hollow (outlined) circle shape to the given legend container.
1099
- * @param d - The data object containing legend properties.
1100
- * @param innerDiv - The D3 selection where the shape will be appended.
1101
- */
1102
- export function getHollowCircleShape(d, innerDiv) {
1103
- try {
1104
- innerDiv
1105
- .append("div")
1106
- .style("height", "12px")
1107
- .style("width", "12px")
1108
- .style("border-radius", "50%")
1109
- .style("border", `3px solid ${d.properties.Color}`);
1110
- }
1111
- catch (error) {
1112
- logError(fileName, "getHollowCircleShape", error);
1113
- }
1114
- }
1115
- /**
1116
- * @param {Object} d - Data object containing properties such as lineStyle, color, markerShape, and markerColor.
1117
- * @param {Object} innerDiv - A D3 selection of a container element to append the line shape.
1118
- * @param {TDefaultChartFormatOptionsType} formatOptions - Formatting options including marker visibility.
1119
- * @return {void}
1120
- */
1121
- export function getLineShape(d, innerDiv, formatOptions) {
1122
- try {
1123
- let shape = innerDiv
1124
- .append("div")
1125
- .style("height", "2px")
1126
- .style("width", "20px")
1127
- .style("background", d.properties.lineStyle == "solid" ? d.properties.color : "transparent")
1128
- .style("position", "relative")
1129
- .style("border-top", d.properties.lineStyle == "None" ? "unset" : d.properties.lineStyle == "dotted" ? "2px dotted " + d.properties.color : "2px dashed " + d.properties.color);
1130
- if (formatOptions.marker.markerVisibility) {
1131
- switch (d.properties.markerShape.toLowerCase()) {
1132
- case "circle":
1133
- shape
1134
- .append("div")
1135
- .append("svg")
1136
- .style("position", "absolute")
1137
- .style("left", "50%")
1138
- .style("top", "50%")
1139
- .attr("transform", "translate(-5,-6)")
1140
- .attr("height", "10px")
1141
- .attr("width", "10px")
1142
- .append("circle")
1143
- .attr("cx", "5")
1144
- .attr("cy", "5")
1145
- .attr("r", "4.5")
1146
- .style("fill", d.properties.markerColor);
1147
- break;
1148
- case "square":
1149
- shape
1150
- .append("div")
1151
- .style("position", "absolute")
1152
- .style("left", "50%")
1153
- .style("top", "50%")
1154
- .style("transform", "translate(-2px, -7px)")
1155
- .style("height", "8px")
1156
- .style("width", "8px")
1157
- .style("top", "2px")
1158
- .style("left", "9px")
1159
- .style("background", d.properties.markerColor);
1160
- break;
1161
- case "triangle":
1162
- shape
1163
- .append("div")
1164
- .style("position", "absolute")
1165
- .style("transform", "translate(5px, -6.5px)")
1166
- .style("border-left", "6px solid transparent")
1167
- .style("border-right", "6px solid transparent")
1168
- .style("border-bottom", `10px solid ${d.properties.markerColor}`);
1169
- break;
1170
- case "cross":
1171
- shape
1172
- .append("div")
1173
- .style("position", "absolute")
1174
- .style("left", "50%")
1175
- .style("top", "50%")
1176
- .style("transform", "translate(-5px, -3px)")
1177
- .style("height", "4px")
1178
- .style("width", "10px")
1179
- .style("background", d.properties.markerColor)
1180
- .append("div")
1181
- .style("height", "10px")
1182
- .style("width", "4px")
1183
- .style("background", d.properties.markerColor)
1184
- .style("position", "relative")
1185
- .style("top", "-3px")
1186
- .style("left", "3px");
1187
- break;
1188
- case "diamond":
1189
- shape
1190
- .append("div")
1191
- .style("height", "7px")
1192
- .style("width", "7px")
1193
- .style("background", d.properties.markerColor)
1194
- .style("transform", "rotate(45deg)")
1195
- .style("top", "-4px")
1196
- .style("left", "7px")
1197
- .style("position", "absolute");
1198
- break;
1199
- case "star":
1200
- shape
1201
- .append("div")
1202
- .style("border-left", "4px solid transparent")
1203
- .style("border-right", "4px solid transparent")
1204
- .style("border-bottom", `8px solid ${d.properties.markerColor}`)
1205
- .style("position", "absolute")
1206
- .style("top", "-6.5px")
1207
- .style("left", "7px")
1208
- .style("transform", "rotate(0deg)")
1209
- .append("div")
1210
- .style("border-left", "4px solid transparent")
1211
- .style("border-right", "4px solid transparent")
1212
- .style("border-top", `8px solid ${d.properties.markerColor}`)
1213
- .style("position", "absolute")
1214
- .style("top", "2px")
1215
- .style("left", "-4px")
1216
- .style("transform", "rotate(360deg)");
1217
- break;
1218
- case "wye":
1219
- shape
1220
- .append("div")
1221
- .style("height", "6.5px")
1222
- .style("width", "3px")
1223
- .style("background", d.properties.markerColor)
1224
- .style("position", "absolute")
1225
- .style("left", "10px")
1226
- .style("top", "-3.5px")
1227
- .append("div")
1228
- .style("height", "5px")
1229
- .style("width", "3px")
1230
- .style("background", d.properties.markerColor)
1231
- .style("transform", "rotate(-55deg)")
1232
- .style("position", "relative")
1233
- .style("top", "-2px")
1234
- .style("left", "-2px")
1235
- .append("div")
1236
- .style("height", "5px")
1237
- .style("width", "3px")
1238
- .style("background", d.properties.markerColor)
1239
- .style("transform", "rotate(108deg)")
1240
- .style("position", "relative")
1241
- .style("top", "3px")
1242
- .style("left", "2px");
1243
- break;
1244
- case "none":
1245
- shape;
1246
- default:
1247
- break;
1248
- }
1249
- }
1250
- }
1251
- catch (error) {
1252
- logError(fileName, "getLineShape", error);
1253
- }
1254
- }
1255
- /**
1256
- * @param {Object} d - Data object containing color, markerShape array, and properties including markerColor.
1257
- * @param {Object} innerDiv - A D3 selection of a container element to append the area shape.
1258
- * @param {TDefaultChartFormatOptionsType} formatOptions - Formatting options including marker visibility.
1259
- * @return {void}
1260
- */
1261
- export function getAreaShape(d, innerDiv, formatOptions) {
1262
- try {
1263
- let flexdiv = innerDiv
1264
- .append("div")
1265
- .style("height", "10px")
1266
- .style("width", "15px")
1267
- .style("background", d.properties.color)
1268
- .style("display", "flex")
1269
- .style("flex-direction", "column")
1270
- .style("border-radius", "1px");
1271
- if (formatOptions.marker.markerVisibility) {
1272
- switch (d.properties.markerShape.toLowerCase()) {
1273
- case "circle":
1274
- flexdiv
1275
- .append("div")
1276
- .style("height", "20%")
1277
- .style("width", "100%")
1278
- .style("background", d.properties.color)
1279
- .style("position", "relative")
1280
- .append("svg")
1281
- .style("position", "absolute")
1282
- .style("left", "50%")
1283
- .style("top", "50%")
1284
- .attr("transform", "translate(-5,-5)")
1285
- .attr("height", "10px")
1286
- .attr("width", "10px")
1287
- .append("circle")
1288
- .attr("cx", "5")
1289
- .attr("cy", "5")
1290
- .attr("r", "2.5")
1291
- .style("fill", d.properties.markerColor);
1292
- break;
1293
- case "square":
1294
- flexdiv
1295
- .append("div")
1296
- .style("height", "20%")
1297
- .style("width", "100%")
1298
- .style("background", d.properties.markerColor)
1299
- .style("position", "relative")
1300
- .append("div")
1301
- .style("position", "absolute")
1302
- .style("left", "50%")
1303
- .style("top", "50%")
1304
- .style("transform", "translate(-4px, -3.5px)")
1305
- .style("height", "5px")
1306
- .style("width", "5px")
1307
- .style("top", "2px")
1308
- .style("left", "9px")
1309
- .style("background", d.properties.markerColor)
1310
- .style("border-radius", "1px");
1311
- break;
1312
- case "triangle":
1313
- flexdiv
1314
- .append("div")
1315
- .style("height", "20%")
1316
- .style("width", "100%")
1317
- .style("background", d.properties.markerColor)
1318
- .style("position", "relative")
1319
- .append("div")
1320
- .style("position", "absolute")
1321
- .style("transform", "translate(5px, -3.5px)")
1322
- .style("border-left", "3px solid transparent")
1323
- .style("border-right", "3px solid transparent")
1324
- .style("border-bottom", `7px solid ${d.properties.markerColor}`);
1325
- break;
1326
- case "cross":
1327
- flexdiv
1328
- .append("div")
1329
- .style("height", "20%")
1330
- .style("width", "100%")
1331
- .style("background", d.properties.markerColor)
1332
- .style("position", "relative")
1333
- .append("div")
1334
- .style("position", "absolute")
1335
- .style("left", "50%")
1336
- .style("top", "50%")
1337
- .style("transform", "translate(-3px, -2px)")
1338
- .style("height", "4px")
1339
- .style("width", "7px")
1340
- .style("background", d.properties.markerColor)
1341
- .append("div")
1342
- .style("height", "6px")
1343
- .style("width", "3px")
1344
- .style("background", d.properties.markerColor)
1345
- .style("position", "relative")
1346
- .style("top", "-1px")
1347
- .style("left", "2px");
1348
- break;
1349
- case "diamond":
1350
- flexdiv
1351
- .append("div")
1352
- .style("height", "20%")
1353
- .style("width", "100%")
1354
- .style("background", d.properties.markerColor)
1355
- .style("position", "relative")
1356
- .append("div")
1357
- .style("height", "4px")
1358
- .style("width", "4px")
1359
- .style("background", d.properties.markerColor)
1360
- .style("transform", "rotate(45deg)")
1361
- .style("top", "-1px")
1362
- .style("left", "5px")
1363
- .style("position", "absolute");
1364
- break;
1365
- case "star":
1366
- flexdiv
1367
- .append("div")
1368
- .style("height", "20%")
1369
- .style("width", "100%")
1370
- .style("background", d.properties.markerColor)
1371
- .style("position", "relative")
1372
- .append("div")
1373
- .style("border-left", "2.5px solid transparent")
1374
- .style("border-right", "2.5px solid transparent")
1375
- .style("border-bottom", `6px solid ${d.properties.markerColor}`)
1376
- .style("position", "absolute")
1377
- .style("top", "-3px")
1378
- .style("left", "6px")
1379
- .style("transform", "rotate(0deg)")
1380
- .append("div")
1381
- .style("border-left", "2.5px solid transparent")
1382
- .style("border-right", "2.5px solid transparent")
1383
- .style("border-top", `6px solid ${d.properties.markerColor}`)
1384
- .style("position", "absolute")
1385
- .style("top", "0.5px")
1386
- .style("left", "-2px")
1387
- .style("transform", "rotate(360deg)");
1388
- break;
1389
- case "wye":
1390
- flexdiv
1391
- .append("div")
1392
- .style("height", "20%")
1393
- .style("width", "100%")
1394
- .style("background", d.properties.markerColor)
1395
- .style("position", "relative")
1396
- .append("div")
1397
- .style("height", "4.5px")
1398
- .style("width", "2px")
1399
- .style("background", d.properties.markerColor)
1400
- .style("position", "absolute")
1401
- .style("left", "6.5px")
1402
- .style("top", "-0.5px")
1403
- .append("div")
1404
- .style("height", "3px")
1405
- .style("width", "2px")
1406
- .style("background", d.properties.markerColor)
1407
- .style("transform", "rotate(-55deg)")
1408
- .style("position", "relative")
1409
- .style("top", "-2px")
1410
- .style("left", "-2px")
1411
- .append("div")
1412
- .style("height", "3px")
1413
- .style("width", "2px")
1414
- .style("background", d.properties.markerColor)
1415
- .style("transform", "rotate(108deg)")
1416
- .style("position", "relative")
1417
- .style("top", "3px")
1418
- .style("left", "2px");
1419
- break;
1420
- case "none":
1421
- flexdiv
1422
- .append("div")
1423
- .style("height", "20%")
1424
- .style("width", "100%")
1425
- .style("background", d.properties.markerColor);
1426
- break;
1427
- default:
1428
- break;
1429
- }
1430
- }
1431
- flexdiv
1432
- .append("div")
1433
- .style("height", "20%")
1434
- .style("width", "100%")
1435
- .style("background", "white");
1436
- flexdiv
1437
- .append("div")
1438
- .style("height", "60%")
1439
- .style("width", "100%")
1440
- .style("background", d.properties.color)
1441
- .style("border-radius", "1px");
1442
- }
1443
- catch (error) {
1444
- logError(fileName, "getAreaShape", error);
1445
- }
1446
- }
1447
- /**
1448
- * Appends a rectangle shape to the given legend container.
1449
- * @param d - The data object that includes styling for the rectangle (like color, border).
1450
- * @param innerDiv - The D3 selection where the shape will be inserted.
1451
- */
1452
- export function getReactShape(d, innerDiv) {
1453
- try {
1454
- innerDiv
1455
- .append("div")
1456
- .style("height", "10px")
1457
- .style("width", "15px")
1458
- .style("border-style", d)
1459
- .style("border-width", d)
1460
- .style("border-color", d)
1461
- .style("background", d.properties.color)
1462
- .style("border-radius", "1px");
1463
- }
1464
- catch (error) {
1465
- logError(fileName, "getReactShape", error);
1466
- }
1467
- }
1468
- export function drawAnnotations(oldAnnotationList, newAnnotationList, chartFormatOptions) {
1469
- try {
1470
- // Implementation here if needed
1471
- }
1472
- catch (error) {
1473
- logError(fileName, "drawAnnotations", error);
1474
- }
1475
- }
1476
- /**
1477
- * Initializes the SVG element with the specified dimensions and chart format options.
1478
- * @param svgRef - The reference to the SVG element.
1479
- * @param width - The width of the SVG element.
1480
- * @param height - The height of the SVG element.
1481
- * @param chartFormatOptions - The format options for the chart, which may include properties like background color and border.
1482
- */
1483
- export const initSvg = (svgRef, width, height, chartFormatOptions) => {
1484
- try {
1485
- let svgElement = svgRef.current;
1486
- svgElement.setAttribute("viewBox", `0 0 ${width} ${height}`);
1487
- const { chartAreaColor, chartAreaBorder } = chartFormatOptions.chartArea;
1488
- svgElement.style.backgroundColor = chartAreaColor;
1489
- const isBorderEnable = chartAreaBorder;
1490
- if (isBorderEnable) {
1491
- let borderColor = chartFormatOptions.chartArea.chartAreaBorderColor;
1492
- let borderWidth = chartFormatOptions.chartArea.chartAreaBorderThickness + "px";
1493
- let borderStyle = convertStringToNumber(chartFormatOptions.chartArea.chartAreaBorderStyle);
1494
- let border = borderStyle == 1 ? "solid" : borderStyle == 2 ? "dashed" : "dotted";
1495
- svgElement.style.outline = `${borderWidth} ${border} ${borderColor}`;
1496
- svgElement.style.outlineOffset = `-${borderWidth}`;
1497
- }
1498
- else {
1499
- svgElement.style.outline = `unset`;
1500
- }
1501
- }
1502
- catch (error) {
1503
- logError(fileName, "initSvg", error);
1504
- }
1505
- };
1506
- /**
1507
- * Initializes the chart area within the SVG element, applying margins and setting a default font color.
1508
- * @param svg - The D3 selection of the SVG element.
1509
- * @param margins - The margins to apply to the chart area.
1510
- * @return {d3.Selection<SVGGElement, any, any, any>} - The D3 selection of the chart area group element.
1511
- */
1512
- export const initChartArea = (svg, margins) => {
1513
- try {
1514
- return svg
1515
- .append("g")
1516
- .attr("transform", `translate(${margins.left},${margins.top})`)
1517
- .attr("font-color", "#ccc");
1518
- }
1519
- catch (error) {
1520
- logError(fileName, "initChartArea", error);
1521
- }
1522
- };
1523
- /**
1524
- * all common functions to do before draw chart .
1525
- * @param svgRef - The reference to the SVG element.
1526
- * @param formatOptions - The format options for the chart which may contains some undefined values.
1527
- * @returns { chartFormatOptions: TDefaultChartFormatOptionsType } - The chart format options with defaults applied.
1528
- * @returns { svg: d3.Selection<SVGSVGElement, any, any, any> } - The D3 selection of the SVG element.
1529
- *
1530
- *
1531
- */
1532
- export const firstFunctionBeforeRender = (svgRef, formatOptions) => {
1533
- try {
1534
- let svg = d3.select(svgRef.current);
1535
- svg.selectAll("*").remove();
1536
- let chartFormatOptions = addUndefinedDefaults(defaultChartFormatOptions, formatOptions);
1537
- let svgBounds = svgRef.current.getBoundingClientRect();
1538
- let width = svgBounds.width;
1539
- let height = svgBounds.height;
1540
- return { chartFormatOptions, svg, width, height };
1541
- }
1542
- catch (error) {
1543
- logError(fileName, "firstFunctionBeforeRender", error);
1544
- }
1545
- };
1546
- export const marginCalculationsForChartsWithoutAxis = (chartFormatOptions, width, height, maxLegendDimensions, margins, isVennChart = false) => {
1547
- try {
1548
- let legendPosition = chartFormatOptions.legends.legendPosition;
1549
- let width15Percent = width * 0.15 * 0.8;
1550
- let legendListWidth = isVennChart ? maxLegendDimensions[0] :
1551
- width15Percent < maxLegendDimensions[0] + 15
1552
- ? width15Percent
1553
- : maxLegendDimensions[0] + 15;
1554
- let chartTitleHeight = chartFormatOptions.chartTitle.chartTitleVisibility
1555
- ? chartFormatOptions.chartTitle.dynamicTitleText.length !== 0
1556
- ? preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleHTML, undefined, undefined).height
1557
- : preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleText, 16, "Helvetica").height
1558
- : 5;
1559
- switch (legendPosition) {
1560
- case staticLegendPosition.none:
1561
- margins.top = chartTitleHeight + 20;
1562
- margins.bottom = 50;
1563
- margins.right = 50;
1564
- margins.left = 50;
1565
- break;
1566
- case staticLegendPosition.top:
1567
- margins.top = chartTitleHeight + 50;
1568
- margins.bottom = 15;
1569
- margins.right = 15;
1570
- margins.left = 15;
1571
- break;
1572
- case staticLegendPosition.right:
1573
- margins.right = legendListWidth + 50;
1574
- margins.top = chartTitleHeight + 15;
1575
- margins.bottom = 15;
1576
- margins.left = 15;
1577
- break;
1578
- case staticLegendPosition.bottom:
1579
- margins.bottom = 45;
1580
- margins.top = chartTitleHeight + 15;
1581
- margins.right = 15;
1582
- margins.left = 15;
1583
- break;
1584
- case staticLegendPosition.left:
1585
- margins.left = legendListWidth + 50;
1586
- margins.top = chartTitleHeight + 15;
1587
- margins.bottom = 15;
1588
- margins.right = 15;
1589
- }
1590
- let innerHeight = height - margins.top - margins.bottom;
1591
- let innerWidth = width - margins.left - margins.right;
1592
- return { margins, innerHeight, innerWidth, legendListWidth, chartTitleHeight };
1593
- }
1594
- catch (error) {
1595
- logError(fileName, "marginCalculationsForChartsWithoutAxis", error);
1596
- }
1597
- };
1598
- /**
1599
- * Initializes the legend list with total value allowance and appends to svg.
1600
- * @param chartFormatOptions - The format options for the chart.
1601
- * @param svg - The D3 selection of the SVG element.
1602
- * @param seriesData - The data series to be displayed in the legend.
1603
- * @param width - The width of the SVG element.
1604
- * @param height - The height of the SVG element.
1605
- * @param legendListWidth - The width allocated for the legend list.
1606
- * @param chartTitleHeight - The height of the chart title.
1607
- * @param chartId - The unique identifier for the chart.
1608
- * @param margins - The margins for the chart area.
1609
- */
1610
- export const initLegendListWithTotalValueAllowance = (chartFormatOptions, svg, seriesData, width, height, legendListWidth, chartTitleHeight, chartId, margins, shouldAllowTotalValueMargin = true) => {
1611
- try {
1612
- let position = chartFormatOptions.legends.legendPosition;
1613
- let totalPosition = chartFormatOptions.total.totalPosition;
1614
- let totalAlignment = chartFormatOptions.total.totalAlignment;
1615
- let shouldTotalValueAdjustment = chartFormatOptions.total.totalVisibility && shouldAllowTotalValueMargin;
1616
- let horizontalLegendAlignment = chartFormatOptions.legends.legendAlignmentTopBottom;
1617
- let verticalLegendAlignment = chartFormatOptions.legends.legendAlignment;
1618
- switch (position) {
1619
- case staticLegendPosition.none:
1620
- break;
1621
- case staticLegendPosition.right:
1622
- legendsWithScroll(svg, seriesData, width - legendListWidth - 25, chartTitleHeight +
1623
- 5 +
1624
- (shouldTotalValueAdjustment
1625
- ? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.end
1626
- ? 10
1627
- : 0
1628
- : 0), legendListWidth + 15, height -
1629
- chartTitleHeight -
1630
- 10 -
1631
- (shouldTotalValueAdjustment
1632
- ? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.end
1633
- ? 10
1634
- : totalPosition == staticTotalPosition.bottom && totalAlignment == staticTotalAlignment.start
1635
- ? 20
1636
- : 0
1637
- : 0), position, verticalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
1638
- break;
1639
- case staticLegendPosition.top:
1640
- legendsWithScroll(svg, seriesData, 5, chartTitleHeight + 5, width - 10, 30, position, horizontalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
1641
- break;
1642
- case staticLegendPosition.left:
1643
- legendsWithScroll(svg, seriesData, 5, margins.top +
1644
- (shouldTotalValueAdjustment
1645
- ? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.start
1646
- ? 10
1647
- : 0
1648
- : 0), legendListWidth + 15, height -
1649
- chartTitleHeight -
1650
- 10 -
1651
- (shouldTotalValueAdjustment
1652
- ? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.start
1653
- ? 10
1654
- : totalPosition == staticTotalPosition.bottom && totalAlignment == staticTotalAlignment.start
1655
- ? 20
1656
- : 0
1657
- : 0), position, verticalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
1658
- break;
1659
- case staticLegendPosition.bottom:
1660
- legendsWithScroll(svg, seriesData, 5, height - 35, width - 10, 30, position, horizontalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
1661
- break;
1662
- }
1663
- }
1664
- catch (error) {
1665
- logError(fileName, "initLegendListWithTotalValueAllowance", error);
1666
- }
1667
- };
1668
- /**
1669
- * Calculates the maximum possible width and height for the legends based on the longest legend string.
1670
- * @param chartFormatOptions - The format options for the chart.
1671
- * @param seriesData - The data series to be displayed in the legend.
1672
- * @returns The maximum possible width and height for the legends.
1673
- */
1674
- export const calculateLegendsMaxPossibleWidth = (chartFormatOptions, seriesData, key = "legend") => {
1675
- try {
1676
- let legendDims = preCalculateTextDimensions(findStringWithLongestLength(seriesData, key), convertStringToNumber(chartFormatOptions.legends.legendFontSize), chartFormatOptions.legends.legendFontFamily);
1677
- return [legendDims.width, legendDims.height];
1678
- }
1679
- catch (error) {
1680
- logError(fileName, "calculateLegendsMaxPossibleWidth", error);
1681
- }
1682
- };
1683
- /**
1684
- * Calculates the margins and inner dimensions for the charts without legends.
1685
- * @param chartFormatOptions - The format options for the chart.
1686
- * @param height - The height of the chart area.
1687
- * @param width - The width of the chart area.
1688
- * @param shouldShowColorScale - Only allow treemap to show color scale.
1689
- * @returns The calculated margins and inner dimensions for the chart.
1690
- */
1691
- export const marginCalculationsForChartsWithoutLegends = (chartFormatOptions, height, width, shouldShowColorScale = false) => {
1692
- try {
1693
- let chartTitleHeight = chartFormatOptions.chartTitle.chartTitleVisibility
1694
- ? chartFormatOptions.chartTitle.dynamicTitleText.length !== 0
1695
- ? preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleHTML, undefined, undefined).height
1696
- : preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleText, 16, "Helvetica").height
1697
- : 5;
1698
- let margins = {
1699
- top: chartFormatOptions.chartTitle.chartTitleVisibility
1700
- ? chartTitleHeight
1701
- : 10,
1702
- bottom: (shouldShowColorScale && chartFormatOptions.colorScale.showColor == colorThemeTypes.colorTheme) ? 40 : 10,
1703
- left: 10,
1704
- right: 10,
1705
- };
1706
- innerHeight = height - margins.top - margins.bottom;
1707
- innerWidth = width - margins.left - margins.right;
1708
- return { margins, chartTitleHeight, innerHeight, innerWidth };
1709
- }
1710
- catch (error) {
1711
- logError(fileName, "marginCalculationsForChartsWithoutLegends", error);
1712
- }
1713
- };
1714
- export const convertStringToNumber = (value) => {
1715
- try {
1716
- if (typeof value !== 'string') {
1717
- return value;
1718
- }
1719
- // Trim the string to remove whitespace
1720
- const trimmed = value.trim();
1721
- // Check for empty string
1722
- if (trimmed === '') {
1723
- return value;
1724
- }
1725
- // Try parsing
1726
- const num = parseFloat(trimmed);
1727
- // Check if it's a valid number
1728
- if (isNaN(num)) {
1729
- return value;
1730
- }
1731
- return num;
1732
- }
1733
- catch (error) {
1734
- logError(fileName, "convertStringToNumber", error);
1735
- }
1736
- };
1737
- export function generalizedChartData(chartData, dimensionList) {
1738
- try {
1739
- return chartData.map(item => {
1740
- // Ensure properties exist
1741
- let properties;
1742
- if (!item.properties) {
1743
- properties = {
1744
- ...chartProperties,
1745
- legend: item.legend,
1746
- currentLegend: item.legend,
1747
- alias: item.legend,
1748
- name: item.legend
1749
- };
1750
- }
1751
- else {
1752
- properties = { ...chartProperties, ...item.properties };
1753
- }
1754
- // Normalize dimensions and clone points
1755
- const normalizedData = dimensionList
1756
- ? dimensionList.map(dim => {
1757
- const found = item.data.find(d => d.dimension === dim);
1758
- if (found) {
1759
- // clone the point to make it extensible
1760
- return { ...found };
1761
- }
1762
- else {
1763
- // insert missing dimension with 0 value
1764
- return {
1765
- dimension: dim,
1766
- legend: item.legend,
1767
- value: 0
1768
- };
1769
- }
1770
- })
1771
- : item.data.map(d => ({ ...d }));
1772
- return {
1773
- ...item,
1774
- properties,
1775
- data: normalizedData
1776
- };
1777
- });
1778
- }
1779
- catch (error) {
1780
- logError(fileName, "generalizedChartData", error);
1781
- }
1782
- }