@scality/core-ui 0.186.0 → 0.188.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 (171) hide show
  1. package/dist/components/{linetemporalchart/MetricTimespanProvider.d.ts → charts/MetricsTimeSpanProvider.d.ts} +1 -1
  2. package/dist/components/charts/MetricsTimeSpanProvider.d.ts.map +1 -0
  3. package/dist/components/{barchartv2/Barchart.component.d.ts → charts/barchart/Barchart.d.ts} +2 -33
  4. package/dist/components/charts/barchart/Barchart.d.ts.map +1 -0
  5. package/dist/components/charts/barchart/Barchart.js +56 -0
  6. package/dist/components/{barchartv2/utils.d.ts → charts/barchart/Barchart.utils.d.ts} +8 -35
  7. package/dist/components/charts/barchart/Barchart.utils.d.ts.map +1 -0
  8. package/dist/components/{barchartv2/utils.js → charts/barchart/Barchart.utils.js} +7 -88
  9. package/dist/components/{barchartv2 → charts/barchart}/BarchartTooltip.d.ts +2 -1
  10. package/dist/components/charts/barchart/BarchartTooltip.d.ts.map +1 -0
  11. package/dist/components/{barchartv2 → charts/barchart}/BarchartTooltip.js +3 -3
  12. package/dist/components/{charttooltip → charts/common}/ChartTooltip.d.ts +9 -2
  13. package/dist/components/charts/common/ChartTooltip.d.ts.map +1 -0
  14. package/dist/components/{charttooltip → charts/common}/ChartTooltip.js +11 -15
  15. package/dist/components/charts/common/SharedComponents.d.ts +47 -0
  16. package/dist/components/charts/common/SharedComponents.d.ts.map +1 -0
  17. package/dist/components/charts/common/SharedComponents.js +83 -0
  18. package/dist/components/charts/common/chartUtils.d.ts +91 -0
  19. package/dist/components/charts/common/chartUtils.d.ts.map +1 -0
  20. package/dist/components/charts/common/chartUtils.js +243 -0
  21. package/dist/components/{globalhealthbar/GlobalHealthBarRecharts.component.d.ts → charts/globalhealthbar/GlobalHealthBar.d.ts} +2 -2
  22. package/dist/components/charts/globalhealthbar/GlobalHealthBar.d.ts.map +1 -0
  23. package/dist/components/{globalhealthbar/useHealthBarData.d.ts → charts/globalhealthbar/GlobalHealthBar.hooks.d.ts} +1 -1
  24. package/dist/components/charts/globalhealthbar/GlobalHealthBar.hooks.d.ts.map +1 -0
  25. package/dist/components/{globalhealthbar/GlobalHealthBarRecharts.component.js → charts/globalhealthbar/GlobalHealthBar.js} +4 -4
  26. package/dist/components/{globalhealthbar/healthBarUtils.d.ts → charts/globalhealthbar/GlobalHealthBar.utils.d.ts} +1 -1
  27. package/dist/components/charts/globalhealthbar/GlobalHealthBar.utils.d.ts.map +1 -0
  28. package/dist/components/{globalhealthbar/healthBarUtils.js → charts/globalhealthbar/GlobalHealthBar.utils.js} +1 -1
  29. package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/GlobalHealthBarTooltip.d.ts +1 -1
  30. package/dist/components/charts/globalhealthbar/GlobalHealthBarTooltip.d.ts.map +1 -0
  31. package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/GlobalHealthBarTooltip.js +7 -3
  32. package/dist/components/charts/globalhealthbar/HealthBarXAxis.d.ts.map +1 -0
  33. package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/HealthBarXAxis.js +1 -1
  34. package/dist/components/charts/index.d.ts +16 -0
  35. package/dist/components/charts/index.d.ts.map +1 -0
  36. package/dist/components/charts/index.js +15 -0
  37. package/dist/components/{chartlegend → charts/legend}/ChartLegend.d.ts +1 -1
  38. package/dist/components/charts/legend/ChartLegend.d.ts.map +1 -0
  39. package/dist/components/{chartlegend → charts/legend}/ChartLegend.js +2 -2
  40. package/dist/components/{chartlegend → charts/legend}/ChartLegendWrapper.d.ts +1 -1
  41. package/dist/components/charts/legend/ChartLegendWrapper.d.ts.map +1 -0
  42. package/dist/components/{linetimeseriechart/linetimeseriechart.component.d.ts → charts/linetimeseries/LineTimeSerieChart.d.ts} +12 -2
  43. package/dist/components/charts/linetimeseries/LineTimeSerieChart.d.ts.map +1 -0
  44. package/dist/components/{linetimeseriechart/linetimeseriechart.component.js → charts/linetimeseries/LineTimeSerieChart.js} +34 -35
  45. package/dist/components/charts/linetimeseries/LineTimeSerieChart.utils.d.ts +14 -0
  46. package/dist/components/charts/linetimeseries/LineTimeSerieChart.utils.d.ts.map +1 -0
  47. package/dist/components/{linetimeseriechart/utils.js → charts/linetimeseries/LineTimeSerieChart.utils.js} +4 -6
  48. package/dist/components/charts/sparkline/Sparkline.d.ts +23 -0
  49. package/dist/components/charts/sparkline/Sparkline.d.ts.map +1 -0
  50. package/dist/components/{sparkline/sparkline.component.js → charts/sparkline/Sparkline.js} +12 -6
  51. package/dist/components/charts/types.d.ts +34 -0
  52. package/dist/components/charts/types.d.ts.map +1 -0
  53. package/dist/components/charts/types.js +4 -0
  54. package/dist/components/icon/Icon.component.d.ts +1 -0
  55. package/dist/components/icon/Icon.component.d.ts.map +1 -1
  56. package/dist/components/icon/Icon.component.js +2 -2
  57. package/dist/components/textbadge/TextBadge.component.d.ts +1 -1
  58. package/dist/components/textbadge/TextBadge.component.d.ts.map +1 -1
  59. package/dist/index.d.ts +0 -2
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +4 -2
  62. package/dist/next.d.ts +3 -11
  63. package/dist/next.d.ts.map +1 -1
  64. package/dist/next.js +4 -11
  65. package/package.json +2 -6
  66. package/src/lib/components/{barchartv2/Barchart.component.test.tsx → charts/barchart/Barchart.test.tsx} +35 -10
  67. package/src/lib/components/{barchartv2/Barchart.component.tsx → charts/barchart/Barchart.tsx} +42 -207
  68. package/src/lib/components/{barchartv2/utils.test.ts → charts/barchart/Barchart.utils.test.ts} +2 -141
  69. package/src/lib/components/{barchartv2/utils.ts → charts/barchart/Barchart.utils.ts} +17 -143
  70. package/src/lib/components/{barchartv2 → charts/barchart}/BarchartTooltip.tsx +5 -9
  71. package/src/lib/components/{charttooltip → charts/common}/ChartTooltip.tsx +13 -20
  72. package/src/lib/components/charts/common/SharedComponents.tsx +193 -0
  73. package/src/lib/components/charts/common/chartUtils.test.ts +402 -0
  74. package/src/lib/components/charts/common/chartUtils.ts +334 -0
  75. package/src/lib/components/{globalhealthbar/useHealthBarData.spec.tsx → charts/globalhealthbar/GlobalHealthBar.hooks.test.tsx} +1 -1
  76. package/src/lib/components/{globalhealthbar/GlobalHealthBarRecharts.component.tsx → charts/globalhealthbar/GlobalHealthBar.tsx} +4 -4
  77. package/src/lib/components/{globalhealthbar/healthBarUtils.spec.ts → charts/globalhealthbar/GlobalHealthBar.utils.test.ts} +1 -1
  78. package/src/lib/components/{globalhealthbar/healthBarUtils.ts → charts/globalhealthbar/GlobalHealthBar.utils.ts} +1 -1
  79. package/src/lib/components/{globalhealthbar/components → charts/globalhealthbar}/GlobalHealthBarTooltip.tsx +8 -4
  80. package/src/lib/components/{globalhealthbar/components → charts/globalhealthbar}/HealthBarXAxis.tsx +1 -1
  81. package/src/lib/components/charts/index.ts +59 -0
  82. package/src/lib/components/{chartlegend → charts/legend}/ChartLegend.tsx +2 -2
  83. package/src/lib/components/{chartlegend → charts/legend}/ChartLegendWrapper.tsx +1 -1
  84. package/src/lib/components/{linetimeseriechart/linetimeseriechart.test.tsx → charts/linetimeseries/LineTimeSerieChart.test.tsx} +3 -6
  85. package/src/lib/components/{linetimeseriechart/linetimeseriechart.component.tsx → charts/linetimeseries/LineTimeSerieChart.tsx} +48 -44
  86. package/src/lib/components/{linetimeseriechart/utils.test.ts → charts/linetimeseries/LineTimeSerieChart.utils.test.ts} +1 -1
  87. package/src/lib/components/{linetimeseriechart/utils.ts → charts/linetimeseries/LineTimeSerieChart.utils.ts} +4 -6
  88. package/src/lib/components/charts/sparkline/Sparkline.tsx +80 -0
  89. package/src/lib/components/charts/types.ts +36 -0
  90. package/src/lib/components/icon/Icon.component.tsx +12 -8
  91. package/src/lib/components/textbadge/TextBadge.component.tsx +1 -1
  92. package/src/lib/index.ts +4 -2
  93. package/src/lib/next.ts +26 -13
  94. package/stories/BarChart/barchart.stories.tsx +10 -9
  95. package/stories/GlobalHealthBar/{globalhealthbarRecharts.stories.tsx → globalhealthbar.stories.tsx} +3 -21
  96. package/stories/GlobalHealthBar/globalheathbarrecharts.guideline.mdx +2 -2
  97. package/stories/guideline/chart-guideline.mdx +1 -38
  98. package/stories/linetimeseriechart.stories.tsx +4 -6
  99. package/stories/sparkline.stories.tsx +13 -11
  100. package/stories/textbadge.stories.tsx +15 -0
  101. package/dist/components/barchart/BarChart.component.d.ts +0 -17
  102. package/dist/components/barchart/BarChart.component.d.ts.map +0 -1
  103. package/dist/components/barchart/BarChart.component.js +0 -27
  104. package/dist/components/barchartv2/Barchart.component.d.ts.map +0 -1
  105. package/dist/components/barchartv2/Barchart.component.js +0 -122
  106. package/dist/components/barchartv2/BarchartTooltip.d.ts.map +0 -1
  107. package/dist/components/barchartv2/utils.d.ts.map +0 -1
  108. package/dist/components/chartlegend/ChartLegend.d.ts.map +0 -1
  109. package/dist/components/chartlegend/ChartLegendWrapper.d.ts.map +0 -1
  110. package/dist/components/charttooltip/ChartTooltip.d.ts.map +0 -1
  111. package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts +0 -23
  112. package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map +0 -1
  113. package/dist/components/globalhealthbar/GlobalHealthBar.component.js +0 -173
  114. package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts.map +0 -1
  115. package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts.map +0 -1
  116. package/dist/components/globalhealthbar/components/HealthBarXAxis.d.ts.map +0 -1
  117. package/dist/components/globalhealthbar/healthBarUtils.d.ts.map +0 -1
  118. package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts +0 -2
  119. package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts.map +0 -1
  120. package/dist/components/globalhealthbar/healthBarUtils.spec.js +0 -391
  121. package/dist/components/globalhealthbar/tooltip/index.d.ts +0 -8
  122. package/dist/components/globalhealthbar/tooltip/index.d.ts.map +0 -1
  123. package/dist/components/globalhealthbar/tooltip/index.js +0 -55
  124. package/dist/components/globalhealthbar/useHealthBarData.d.ts.map +0 -1
  125. package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts +0 -2
  126. package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts.map +0 -1
  127. package/dist/components/globalhealthbar/useHealthBarData.spec.js +0 -209
  128. package/dist/components/linetemporalchart/ChartUtil.d.ts +0 -41
  129. package/dist/components/linetemporalchart/ChartUtil.d.ts.map +0 -1
  130. package/dist/components/linetemporalchart/ChartUtil.js +0 -148
  131. package/dist/components/linetemporalchart/LineTemporalChart.component.d.ts +0 -46
  132. package/dist/components/linetemporalchart/LineTemporalChart.component.d.ts.map +0 -1
  133. package/dist/components/linetemporalchart/LineTemporalChart.component.js +0 -579
  134. package/dist/components/linetemporalchart/MetricTimespanProvider.d.ts.map +0 -1
  135. package/dist/components/linetemporalchart/tooltip/index.d.ts +0 -30
  136. package/dist/components/linetemporalchart/tooltip/index.d.ts.map +0 -1
  137. package/dist/components/linetemporalchart/tooltip/index.js +0 -104
  138. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +0 -1
  139. package/dist/components/linetimeseriechart/utils.d.ts +0 -16
  140. package/dist/components/linetimeseriechart/utils.d.ts.map +0 -1
  141. package/dist/components/sparkline/sparkline.component.d.ts +0 -17
  142. package/dist/components/sparkline/sparkline.component.d.ts.map +0 -1
  143. package/dist/components/vegachartv2/SyncedCursorCharts.d.ts +0 -12
  144. package/dist/components/vegachartv2/SyncedCursorCharts.d.ts.map +0 -1
  145. package/dist/components/vegachartv2/SyncedCursorCharts.js +0 -15
  146. package/dist/components/vegachartv2/VegaChartV2.component.d.ts +0 -15
  147. package/dist/components/vegachartv2/VegaChartV2.component.d.ts.map +0 -1
  148. package/dist/components/vegachartv2/VegaChartV2.component.js +0 -218
  149. package/src/lib/components/barchart/BarChart.component.tsx +0 -51
  150. package/src/lib/components/globalhealthbar/GlobalHealthBar.component.tsx +0 -204
  151. package/src/lib/components/globalhealthbar/tooltip/index.ts +0 -72
  152. package/src/lib/components/linetemporalchart/ChartUtil.test.ts +0 -250
  153. package/src/lib/components/linetemporalchart/ChartUtil.ts +0 -225
  154. package/src/lib/components/linetemporalchart/LineTemporalChart.component.tsx +0 -800
  155. package/src/lib/components/linetemporalchart/tooltip/index.ts +0 -178
  156. package/src/lib/components/sparkline/sparkline.component.tsx +0 -56
  157. package/src/lib/components/vegachartv2/SyncedCursorCharts.tsx +0 -28
  158. package/src/lib/components/vegachartv2/VegaChartV2.component.tsx +0 -276
  159. package/stories/barchart.stories.tsx +0 -142
  160. package/stories/globalhealthbar.stories.tsx +0 -191
  161. package/stories/guideline/mdxExampleComponents.tsx +0 -57
  162. package/stories/linecharttemporal.stories.tsx +0 -88
  163. /package/dist/components/{linetemporalchart/MetricTimespanProvider.js → charts/MetricsTimeSpanProvider.js} +0 -0
  164. /package/dist/components/{globalhealthbar/useHealthBarData.js → charts/globalhealthbar/GlobalHealthBar.hooks.js} +0 -0
  165. /package/dist/components/{globalhealthbar/components → charts/globalhealthbar}/HealthBarXAxis.d.ts +0 -0
  166. /package/dist/components/{chartlegend → charts/legend}/ChartLegendWrapper.js +0 -0
  167. /package/src/lib/components/{linetemporalchart/MetricTimespanProvider.tsx → charts/MetricsTimeSpanProvider.tsx} +0 -0
  168. /package/src/lib/components/{barchartv2 → charts/barchart}/BarchartTooltip.test.tsx +0 -0
  169. /package/src/lib/components/{globalhealthbar/useHealthBarData.ts → charts/globalhealthbar/GlobalHealthBar.hooks.ts} +0 -0
  170. /package/src/lib/components/{chartlegend → charts/legend}/ChartLegend.test.tsx +0 -0
  171. /package/src/lib/components/{chartlegend → charts/legend}/ChartLegendWrapper.test.tsx +0 -0
@@ -0,0 +1,334 @@
1
+ import { NAN_STRING } from '../../constants';
2
+ import { TooltipDateFormat } from './ChartTooltip';
3
+ import { UnitRange } from '../types';
4
+
5
+ /* -------------------------------------------------------------------------- */
6
+ /* constants */
7
+ /* -------------------------------------------------------------------------- */
8
+
9
+ export const maxWidthTooltip = { maxWidth: '20rem' };
10
+
11
+ /* -------------------------------------------------------------------------- */
12
+ /* utils functions */
13
+ /* -------------------------------------------------------------------------- */
14
+
15
+ /**
16
+ * Round a value to a nice number for chart display
17
+ * Used by Barchart and LineTimeSerieChart for Y-axis scaling
18
+ */
19
+ export const getRoundReferenceValue = (value: number): number => {
20
+ if (value <= 0) return 1; // Default for zero or negative values
21
+
22
+ // Buffer the value by 10% to avoid being too close to the edge of the chart
23
+ const bufferedValue = value * 1.1;
24
+
25
+ if (value >= 10) {
26
+ const remainder = value % 10;
27
+ const incremented = value + (10 - remainder);
28
+
29
+ // If the remainder is less than 5, round down to the nearest 10
30
+ if (remainder < 5) {
31
+ return value - remainder;
32
+ }
33
+
34
+ // If incrementing would exceed the buffered max, also round down
35
+ if (incremented > bufferedValue) {
36
+ return value - remainder;
37
+ }
38
+
39
+ // Otherwise, round up to the next 10
40
+ return incremented;
41
+ }
42
+
43
+ const magnitude = Math.pow(10, Math.floor(Math.log10(value)));
44
+
45
+ const remainder = bufferedValue % magnitude;
46
+
47
+ // Round to nice numbers based on normalized value
48
+ // appearance for small values
49
+ return remainder === 0 ? bufferedValue : bufferedValue - remainder;
50
+ };
51
+
52
+ /**
53
+ * Generate tick values for Y-axis
54
+ * Used by Barchart and LineTimeSerieChart
55
+ */
56
+ export const getTicks = (topValue: number, isSymmetrical: boolean) => {
57
+ const possibleTickNumbers = [4, 3];
58
+ const numberOfTicks =
59
+ possibleTickNumbers.find((number) => topValue % (number - 1) === 0) || 3; // Default to 3 ticks if no match
60
+
61
+ const tickInterval = topValue / (numberOfTicks - 1);
62
+ const ticks = Array.from(
63
+ { length: numberOfTicks },
64
+ (_, index) => index * tickInterval,
65
+ );
66
+ if (isSymmetrical) {
67
+ // Create negative ticks in order without 0
68
+ const negativeTicks = Array.from(
69
+ { length: numberOfTicks - 1 },
70
+ (_, index) => (index - numberOfTicks + 1) * tickInterval,
71
+ );
72
+ ticks.unshift(...negativeTicks);
73
+ }
74
+ return ticks;
75
+ };
76
+
77
+ /**
78
+ * Return the unit label based on the current dataset, and the valueBase which is used to convert the data
79
+ * Used by LineTimeSerieChart
80
+ * @param unitRange - Array of threshold and label pairs
81
+ * @param maxValue - The maximum value among the data set
82
+ * @returns Object with valueBase and unitLabel
83
+ */
84
+ export function getUnitLabel(
85
+ unitRange: {
86
+ threshold: number;
87
+ label: string;
88
+ }[],
89
+ maxValue: number,
90
+ ): {
91
+ valueBase: number;
92
+ unitLabel: string | undefined;
93
+ } {
94
+ if (!unitRange || unitRange.length === 0) {
95
+ return {
96
+ valueBase: 1,
97
+ unitLabel: undefined,
98
+ };
99
+ }
100
+ // first sort the unitRange
101
+ unitRange.sort(
102
+ (
103
+ unitA: {
104
+ threshold: number;
105
+ label: string;
106
+ },
107
+ unitB: {
108
+ threshold: number;
109
+ label: string;
110
+ },
111
+ ) => {
112
+ return unitA.threshold - unitB.threshold;
113
+ },
114
+ );
115
+ let index = unitRange.findIndex((range) => range.threshold > maxValue);
116
+
117
+ // last unit
118
+ if (index === -1) {
119
+ index = unitRange.length;
120
+ }
121
+
122
+ if (index === 0) {
123
+ return {
124
+ valueBase: unitRange[index].threshold || 1,
125
+ unitLabel: unitRange[index].label,
126
+ };
127
+ }
128
+
129
+ return {
130
+ // if the threshold is 0, we use 1 as the value base to avoid division by 0
131
+ valueBase: unitRange[index - 1].threshold || 1,
132
+ unitLabel: unitRange[index - 1].label,
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Computes unit label and normalizes chart data based on unit range.
138
+ * This is shared logic used by both Barchart and LineTimeSerieChart.
139
+ *
140
+ * @param data - Chart data to normalize
141
+ * @param maxValue - Maximum value in the dataset
142
+ * @param unitRange - Optional unit range configuration for automatic scaling
143
+ * @param excludeKey - Key to exclude from normalization (e.g., 'category' for Barchart, 'timestamp' for LineTimeSerieChart)
144
+ * @returns Object containing unit label, top value for Y-axis, and normalized data
145
+ */
146
+ export const normalizeChartDataWithUnits = <T extends Record<string, any>>(
147
+ data: T[],
148
+ maxValue: number,
149
+ unitRange: UnitRange | undefined,
150
+ excludeKey: string,
151
+ ): {
152
+ unitLabel: string | undefined;
153
+ topValue: number;
154
+ rechartsData: T[];
155
+ topDomain: number;
156
+ } => {
157
+ // If no unit range provided, just calculate top value without unit conversion
158
+ if (!unitRange || unitRange.length === 0) {
159
+ const topValue = getRoundReferenceValue(maxValue);
160
+ return {
161
+ unitLabel: undefined,
162
+ topValue,
163
+ rechartsData: data,
164
+ topDomain: maxValue * 1.1,
165
+ };
166
+ }
167
+
168
+ // Get appropriate unit and value base for normalization
169
+ const { valueBase, unitLabel } = getUnitLabel(unitRange, maxValue);
170
+ const basedValue = maxValue / valueBase;
171
+ const topValue = getRoundReferenceValue(basedValue);
172
+ const topDomain = basedValue * 1.1;
173
+ // Normalize all numeric values by dividing by valueBase
174
+ const rechartsData = data.map((dataPoint) => {
175
+ const normalizedDataPoint: Record<string, number | string> = {
176
+ ...dataPoint,
177
+ };
178
+ Object.entries(dataPoint).forEach(([key, value]) => {
179
+ if (key !== excludeKey && typeof value === 'number') {
180
+ normalizedDataPoint[key] = value / valueBase;
181
+ }
182
+ });
183
+ return normalizedDataPoint as T;
184
+ });
185
+
186
+ return { unitLabel, topValue, rechartsData, topDomain };
187
+ };
188
+
189
+ /**
190
+ * This function manually adds the missing data points with `null` value caused by downtime of the VMs
191
+ * Missing data points are only added when the gap between consecutive data points is bigger than 2 intervals
192
+ * Used by LineTimeSerieChart and Sparkline
193
+ *
194
+ * @param orginalValues - The array of the data points are already sorted according to the time series
195
+ * @param startingTimeStamp - The starting timestamp in seconds
196
+ * @param sampleDuration - The time span value in seconds
197
+ * @param sampleInterval - The time difference between two data points in seconds
198
+ */
199
+ export function addMissingDataPoint(
200
+ originalValues: [number, number | string | null][],
201
+ startingTimeStamp?: number,
202
+ sampleDuration?: number,
203
+ sampleInterval?: number,
204
+ ): [number, number | string | null][] {
205
+ if (
206
+ !originalValues ||
207
+ startingTimeStamp === undefined ||
208
+ !sampleDuration ||
209
+ !sampleInterval ||
210
+ startingTimeStamp < 0 ||
211
+ sampleDuration <= 0 ||
212
+ sampleInterval <= 0
213
+ ) {
214
+ return [];
215
+ }
216
+
217
+ // If there are no original values, return empty array
218
+ if (originalValues.length === 0) {
219
+ return [];
220
+ }
221
+
222
+ const newValues: [number, number | string | null][] = [];
223
+
224
+ // add missing data points for the starting time
225
+ for (
226
+ let i = startingTimeStamp;
227
+ i < originalValues[0][0];
228
+ i += sampleInterval
229
+ ) {
230
+ newValues.push([i, NAN_STRING]);
231
+ }
232
+
233
+ // Process all but the last element
234
+ for (let i = 0; i < originalValues.length - 1; i++) {
235
+ if (
236
+ originalValues[i][0] < startingTimeStamp ||
237
+ originalValues[i][0] > startingTimeStamp + sampleDuration
238
+ ) {
239
+ continue;
240
+ }
241
+
242
+ // Always add the current data point
243
+ newValues.push(originalValues[i]);
244
+
245
+ const currentTimestamp = originalValues[i][0];
246
+ const nextTimestamp = originalValues[i + 1][0];
247
+ const gap = nextTimestamp - currentTimestamp;
248
+
249
+ // Calculate how many missing points to add
250
+ const missingIntervals = Math.floor(gap / sampleInterval) - 1;
251
+
252
+ // Add missing data points with NAN_STRING (only executes if missingIntervals > 0)
253
+ for (let j = 1; j <= missingIntervals; j++) {
254
+ const missingTimestamp = currentTimestamp + j * sampleInterval;
255
+ newValues.push([missingTimestamp, NAN_STRING]);
256
+ }
257
+ }
258
+
259
+ // Add the last element
260
+ newValues.push(originalValues[originalValues.length - 1]);
261
+
262
+ // add missing data points for the ending time
263
+ for (
264
+ let i = originalValues[originalValues.length - 1][0] + sampleInterval;
265
+ i < startingTimeStamp + sampleDuration;
266
+ i += sampleInterval
267
+ ) {
268
+ newValues.push([i, NAN_STRING]);
269
+ }
270
+
271
+ return newValues;
272
+ }
273
+ /**
274
+ * Date Format Reference Table
275
+ * ============================
276
+ *
277
+ * This table documents the date formatting logic used across charts:
278
+ * - X-Axis Format: Used for chart axis labels (formatXAxisDate + LineTimeSerieChart's formatXAxisLabel)
279
+ * - Tooltip Format: Used for tooltip headers (getTooltipDateFormat)
280
+ *
281
+ * ┌─────────────────┬──────────────┬────────────────────────┬──────────────────┬──────────────────────────────────────────┬───────────────────────────┐
282
+ * │ Interval │ Duration (s) │ X-axis format │ Example (X-axis) │ Tooltip format │ Example (Tooltip) │
283
+ * ├─────────────────┼──────────────┼────────────────────────┼──────────────────┼──────────────────────────────────────────┼───────────────────────────┤
284
+ * │ Last hour │ ≤ 3,600 │ HH:MM │ 14:05 │ DD MMM HH:MM:SS │ 01 Oct 00:15:00 │
285
+ * │ Last 24 hours │ ≤ 86,400 │ HH:MM │ 23:00 │ DD MMM HH:MM │ 01 Oct 00:15 │
286
+ * │ Last 7 days │ ≤ 604,800 │ DD MMM HH:MM │ 27 Sep 10:12 │ DD MMM HH:MM │ 01 Oct 00:15 │
287
+ * │ Long term │ > 604,800 │ DDMMMYY │ 15Sep25 │ DD MMM YYYY HH:MM │ 01 Oct 2025 00:15 │
288
+ * └─────────────────┴──────────────┴────────────────────────┴──────────────────┴──────────────────────────────────────────┴───────────────────────────┘
289
+ *
290
+ * Note: Duration is in seconds. Some intervals share the same format, which is why both functions only have 3 cases.
291
+ */
292
+
293
+ /**
294
+ * Get the format of the date based on the duration
295
+ * Used by Barchart CustomTick component
296
+ * @param duration - Duration in seconds
297
+ * @returns Formatted string type
298
+ */
299
+ export const formatXAxisDate = (
300
+ duration: number,
301
+ ): 'time' | 'day-month-abbreviated' | 'chart-long-term-date' => {
302
+ if (duration <= 24 * 60 * 60) {
303
+ return 'time';
304
+ } else if (duration <= 7 * 24 * 60 * 60) {
305
+ return 'day-month-abbreviated';
306
+ } else {
307
+ return 'chart-long-term-date';
308
+ }
309
+ };
310
+
311
+ /**
312
+ * Get the format of the date based on the duration
313
+ * Used by TooltipHeader component
314
+ * @param duration - Duration in seconds
315
+ * @returns Formatted string type
316
+ */
317
+ export const getTooltipDateFormat: (duration: number) => TooltipDateFormat = (
318
+ duration: number,
319
+ ) => {
320
+ if (duration <= 60 * 60) {
321
+ return 'day-month-abbreviated-hour-minute-second';
322
+ } else if (duration <= 7 * 24 * 60 * 60) {
323
+ return 'day-month-abbreviated-hour-minute';
324
+ } else {
325
+ return 'day-month-abbreviated-year-hour-minute';
326
+ }
327
+ };
328
+
329
+ export const formatToISONumber = (value: number): string => {
330
+ const formattedValue = new Intl.NumberFormat('fr-FR')
331
+ .format(value)
332
+ .replace(',', '.');
333
+ return formattedValue;
334
+ };
@@ -1,4 +1,4 @@
1
- import { useHealthBarData, Alert } from './useHealthBarData';
1
+ import { useHealthBarData, Alert } from './GlobalHealthBar.hooks';
2
2
  import { renderHook } from '@testing-library/react';
3
3
  describe('useHealthBarData', () => {
4
4
  const mockTimestamp = {
@@ -8,14 +8,14 @@ import {
8
8
  YAxis,
9
9
  } from 'recharts';
10
10
  import styled, { useTheme } from 'styled-components';
11
- import { GlobalHealthBarTooltip } from './components/GlobalHealthBarTooltip';
12
- import { HealthBarXAxis } from './components/HealthBarXAxis';
11
+ import { GlobalHealthBarTooltip } from './GlobalHealthBarTooltip';
12
+ import { HealthBarXAxis } from './HealthBarXAxis';
13
13
  import {
14
14
  CHART_CONFIG,
15
15
  getNavigationAction,
16
16
  getNavigationStateUpdate,
17
- } from './healthBarUtils';
18
- import { Alert, useHealthBarData } from './useHealthBarData';
17
+ } from './GlobalHealthBar.utils';
18
+ import { Alert, useHealthBarData } from './GlobalHealthBar.hooks';
19
19
 
20
20
  export interface GlobalHealthProps {
21
21
  id: string;
@@ -10,7 +10,7 @@ import {
10
10
  getNavigationAction,
11
11
  calculateNavigationIndex,
12
12
  getNavigationStateUpdate,
13
- } from './healthBarUtils';
13
+ } from './GlobalHealthBar.utils';
14
14
 
15
15
  describe('Health Bar Utils', () => {
16
16
  describe('Tick Calculations', () => {
@@ -1,4 +1,4 @@
1
- import { fontSize } from '../../style/theme';
1
+ import { fontSize } from '../../../style/theme';
2
2
 
3
3
  // =============================================================================
4
4
  // CONSTANTS
@@ -1,11 +1,15 @@
1
1
  import React from 'react';
2
2
  import styled, { css, useTheme } from 'styled-components';
3
- import { FormattedDateTime, Stack, Text, Wrap, spacing } from '../../../index';
4
- import { Alert } from '../GlobalHealthBarRecharts.component';
5
3
  import { TooltipContentProps } from 'recharts';
4
+ import { FormattedDateTime } from '../../date/FormattedDateTime';
5
+ import { Stack } from '../../../spacing';
6
+ import { Text } from '../../text/Text.component';
7
+ import { Wrap } from '../../../spacing';
8
+ import { spacing } from '../../../spacing';
9
+ import { Alert } from './GlobalHealthBar.hooks';
6
10
  import { zIndex } from '../../../style/theme';
7
- import { CHART_CONFIG, getTooltipPosition } from '../healthBarUtils';
8
- import { ChartTooltipPortal } from '../../charttooltip/ChartTooltip';
11
+ import { CHART_CONFIG, getTooltipPosition } from './GlobalHealthBar.utils';
12
+ import { ChartTooltipPortal } from '../common/ChartTooltip';
9
13
 
10
14
  interface GlobalHealthBarTooltipProps {
11
15
  tooltipData: Alert | null;
@@ -6,7 +6,7 @@ import {
6
6
  calculateLabelVisibility,
7
7
  TIME_CONSTANTS,
8
8
  getEdgeMargin,
9
- } from '../healthBarUtils';
9
+ } from './GlobalHealthBar.utils';
10
10
  import { FormattedDateTime } from '../../date/FormattedDateTime';
11
11
 
12
12
  interface HealthBarXAxisProps {
@@ -0,0 +1,59 @@
1
+ // Components
2
+ export { Barchart } from './barchart/Barchart';
3
+ export type {
4
+ BarchartProps,
5
+ BarchartBars,
6
+ BarchartTooltipFn,
7
+ BarchartSortFn,
8
+ Point,
9
+ } from './barchart/Barchart';
10
+
11
+ export { LineTimeSerieChart } from './linetimeseries/LineTimeSerieChart';
12
+ export type {
13
+ LineChartProps,
14
+ Serie,
15
+ } from './linetimeseries/LineTimeSerieChart';
16
+
17
+ export { GlobalHealthBar } from './globalhealthbar/GlobalHealthBar';
18
+ export type { GlobalHealthProps } from './globalhealthbar/GlobalHealthBar';
19
+ export type { Alert } from './globalhealthbar/GlobalHealthBar.hooks';
20
+
21
+ export { Sparkline } from './sparkline/Sparkline';
22
+
23
+ // Legend
24
+ export { ChartLegend } from './legend/ChartLegend';
25
+ export {
26
+ ChartLegendWrapper,
27
+ useChartId,
28
+ useChartLegend,
29
+ } from './legend/ChartLegendWrapper';
30
+
31
+ // Tooltips (for advanced usage)
32
+ export { BarchartTooltip } from './barchart/BarchartTooltip';
33
+ export {
34
+ ChartTooltipContainer,
35
+ ChartTooltipItem,
36
+ ChartTooltipHeader,
37
+ ChartTooltipItemsContainer,
38
+ ChartTooltipPortal,
39
+ } from './common/ChartTooltip';
40
+
41
+ // Shared utilities (for advanced usage)
42
+ export {
43
+ getRoundReferenceValue,
44
+ getTicks,
45
+ getUnitLabel,
46
+ addMissingDataPoint,
47
+ formatXAxisDate,
48
+ getTooltipDateFormat,
49
+ normalizeChartDataWithUnits,
50
+ } from './common/chartUtils';
51
+
52
+ // Context Providers (for backward compatibility)
53
+ export {
54
+ MetricsTimeSpanProvider,
55
+ useMetricsTimeSpan,
56
+ } from './MetricsTimeSpanProvider';
57
+
58
+ // Types
59
+ export type { UnitRange, TimeType, CategoryType } from './types';
@@ -1,7 +1,7 @@
1
1
  import styled from 'styled-components';
2
2
  import { useChartLegend } from './ChartLegendWrapper';
3
- import { Text, TextVariant } from '../text/Text.component';
4
- import { chartColors } from '../../style/theme';
3
+ import { Text, TextVariant } from '../../text/Text.component';
4
+ import { chartColors } from '../../../style/theme';
5
5
  import { useCallback } from 'react';
6
6
 
7
7
  type ChartLegendProps = {
@@ -9,7 +9,7 @@ import {
9
9
  useRef,
10
10
  } from 'react';
11
11
  import { v4 as uuidv4 } from 'uuid';
12
- import { ChartColors } from '../../style/theme';
12
+ import { ChartColors } from '../../../style/theme';
13
13
 
14
14
  export const useChartId = (): string => {
15
15
  const idRef = useRef<string | null>(null);
@@ -1,12 +1,9 @@
1
1
  import { render } from '@testing-library/react';
2
2
  import React from 'react';
3
- import {
4
- LineChartProps,
5
- LineTimeSerieChart,
6
- } from './linetimeseriechart.component';
7
- import { ChartLegendWrapper } from '../chartlegend/ChartLegendWrapper';
3
+ import { LineChartProps, LineTimeSerieChart } from './LineTimeSerieChart';
4
+ import { ChartLegendWrapper } from '../legend/ChartLegendWrapper';
8
5
  import { ThemeProvider } from 'styled-components';
9
- import { coreUIAvailableThemes } from '../../style/theme';
6
+ import { coreUIAvailableThemes } from '../../../style/theme';
10
7
 
11
8
  const TestSeries = [
12
9
  {
@@ -1,3 +1,4 @@
1
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
1
2
  import {
2
3
  CartesianGrid,
3
4
  Line,
@@ -8,32 +9,31 @@ import {
8
9
  XAxis,
9
10
  YAxis,
10
11
  } from 'recharts';
11
- import React, { useCallback, useMemo, useRef, useState } from 'react';
12
12
  import styled, { useTheme } from 'styled-components';
13
- import { Stack } from '../../spacing';
14
- import { fontSize } from '../../style/theme';
15
- import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
13
+ import { Stack } from '../../../spacing';
14
+ import { fontSize } from '../../../style/theme';
15
+ import { IconHelp } from '../../iconhelper/IconHelper';
16
+ import { Loader } from '../../loader/Loader.component';
17
+ import { ChartTitleText } from '../../text/Text.component';
18
+ import { LegendShape } from '../legend/ChartLegend';
19
+ import { useChartLegend } from '../legend/ChartLegendWrapper';
20
+ import { StyledResponsiveContainer } from '../common/SharedComponents';
16
21
  import {
17
- addMissingDataPoint,
18
- getUnitLabel,
19
- } from '../linetemporalchart/ChartUtil';
20
- import { Loader } from '../loader/Loader.component';
21
- import { ChartTitleText } from '../text/Text.component';
22
- import { formatXAxisLabel } from './utils';
23
- import {
24
- ChartTooltipPortal,
25
- ChartTooltipItem,
26
22
  ChartTooltipHeader,
23
+ ChartTooltipItem,
27
24
  ChartTooltipItemsContainer,
25
+ ChartTooltipPortal,
28
26
  ChartTooltipSeparator,
29
27
  TooltipHeader,
30
- } from '../charttooltip/ChartTooltip';
31
- import { LegendShape } from '../chartlegend/ChartLegend';
32
- import { StyledResponsiveContainer } from '../barchartv2/Barchart.component';
33
- import { getRoundReferenceValue, getTicks } from '../barchartv2/utils';
34
- import { IconHelp } from '../iconhelper/IconHelper';
35
-
36
- const maxWidthTooltip = { maxWidth: '20rem' };
28
+ } from '../common/ChartTooltip';
29
+ import {
30
+ addMissingDataPoint,
31
+ formatToISONumber,
32
+ getTicks,
33
+ maxWidthTooltip,
34
+ normalizeChartDataWithUnits,
35
+ } from '../common/chartUtils';
36
+ import { formatXAxisLabel } from './LineTimeSerieChart.utils';
37
37
 
38
38
  const LineTemporalChartWrapper = styled.div`
39
39
  display: flex;
@@ -211,6 +211,16 @@ const isSymmetricalSeries = (
211
211
  return 'above' in series && 'below' in series;
212
212
  };
213
213
 
214
+ /**
215
+ * Props for LineTimeSerieChart component
216
+ * @param series - The data series to display
217
+ * @param title - The title of the chart
218
+ * @param height - The height of the chart in pixels
219
+ * @param startingTimeStamp - Starting timestamp in seconds
220
+ * @param interval - Interval between data points in seconds
221
+ * @param duration - Total duration of the chart in seconds
222
+ *
223
+ */
214
224
  export function LineTimeSerieChart({
215
225
  series,
216
226
  title,
@@ -361,7 +371,6 @@ export function LineTimeSerieChart({
361
371
 
362
372
  // 3. Transform the data base on the valuebase
363
373
  const { topValue, unitLabel, rechartsData, topDomain } = useMemo(() => {
364
-
365
374
  const values = chartData.flatMap((dataPoint) =>
366
375
  Object.entries(dataPoint)
367
376
  .filter(([key]) => key !== 'timestamp')
@@ -386,22 +395,21 @@ export function LineTimeSerieChart({
386
395
  const top = Math.abs(Math.max(...values));
387
396
  const bottom = Math.abs(Math.min(...values));
388
397
  const maxValue = Math.max(top, bottom);
389
- const { valueBase, unitLabel } = yAxisType === 'percentage' ? { valueBase: 1, unitLabel: '%' } : getUnitLabel(unitRange ?? [], maxValue);
390
- // Use round reference value to add extra padding to the top value
391
- const basedValue = maxValue / valueBase
392
- const topDomain = basedValue * 1.1;
393
- const topValue = getRoundReferenceValue(basedValue);
394
- const rechartsData = chartData.map((dataPoint) => {
395
- const normalizedDataPoint = { ...dataPoint };
396
- Object.entries(dataPoint).forEach(([key, value]) => {
397
- if (key !== 'timestamp' && typeof value === 'number') {
398
- normalizedDataPoint[key] = value / valueBase;
399
- }
400
- });
401
- return normalizedDataPoint;
402
- });
403
398
 
404
- return { topValue, unitLabel, rechartsData, topDomain };
399
+ // Use shared normalization function
400
+ const result = normalizeChartDataWithUnits(
401
+ chartData,
402
+ maxValue,
403
+ unitRange,
404
+ 'timestamp', // LineTimeSerieChart uses 'timestamp' as the key to exclude
405
+ );
406
+
407
+ return {
408
+ topValue: result.topValue,
409
+ unitLabel: result.unitLabel,
410
+ rechartsData: result.rechartsData,
411
+ topDomain: result.topDomain,
412
+ };
405
413
  }, [chartData, yAxisType, unitRange]);
406
414
 
407
415
  // Group series by resource and create color mapping
@@ -516,20 +524,16 @@ export function LineTimeSerieChart({
516
524
  },
517
525
  }}
518
526
  domain={
519
- yAxisType === 'percentage'
520
- ? [0, topDomain]
521
- : yAxisType === 'symmetrical'
522
- ? [-topDomain, topDomain]
523
- : [0, topDomain]
527
+ yAxisType === 'symmetrical'
528
+ ? [-topDomain, topDomain]
529
+ : [0, topDomain]
524
530
  }
525
531
  axisLine={{ stroke: theme.border }}
526
532
  tick={{
527
533
  fill: theme.textSecondary,
528
534
  fontSize: fontSize.smaller,
529
535
  }}
530
- tickFormatter={(value) =>
531
- new Intl.NumberFormat('fr-FR').format(value)
532
- }
536
+ tickFormatter={(value) => formatToISONumber(value)}
533
537
  ticks={getTicks(topValue, yAxisType === 'symmetrical')}
534
538
  interval={0}
535
539
  />
@@ -1,4 +1,4 @@
1
- import { formatXAxisLabel } from './utils';
1
+ import { formatXAxisLabel } from './LineTimeSerieChart.utils';
2
2
 
3
3
  describe('formatXAxisLabel', () => {
4
4
  const mockTimestamp = new Date('2025-09-15T14:30:00Z').getTime();