@scality/core-ui 0.186.0 → 0.187.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 +73 -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 +180 -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
@@ -10,9 +10,10 @@ import {
10
10
  Middleware,
11
11
  } from '@floating-ui/react';
12
12
  import styled from 'styled-components';
13
- import { spacing } from '../../spacing';
14
- import { fontSize, fontWeight } from '../../style/theme';
15
- import { FormattedDateTime } from '../date/FormattedDateTime';
13
+ import { spacing } from '../../../spacing';
14
+ import { fontSize, fontWeight } from '../../../style/theme';
15
+ import { FormattedDateTime } from '../../date/FormattedDateTime';
16
+ import { getTooltipDateFormat } from './chartUtils';
16
17
 
17
18
  export const ChartTooltipContainer = styled.div`
18
19
  border: 1px solid ${({ theme }) => theme.border};
@@ -106,25 +107,17 @@ export type TooltipDateFormat =
106
107
  | 'day-month-abbreviated-hour-minute-second'
107
108
  | 'day-month-abbreviated-hour-minute';
108
109
 
109
- const getTooltipDateFormat: (duration: number) => TooltipDateFormat = (
110
- duration: number,
111
- ) => {
112
- if (duration <= 60 * 60) {
113
- return 'day-month-abbreviated-hour-minute-second';
114
- } else if (duration <= 7 * 24 * 60 * 60) {
115
- return 'day-month-abbreviated-hour-minute';
116
- } else {
117
- return 'day-month-abbreviated-year-hour-minute';
118
- }
119
- };
120
-
121
- export const TooltipHeader = ({
122
- duration,
123
- value,
124
- }: {
110
+ export type TooltipHeaderProps = {
125
111
  duration: number;
126
112
  value: string | number;
127
- }) => {
113
+ };
114
+ /**
115
+ * Tooltip header component
116
+ * @param duration - Duration in seconds
117
+ * @param value - Value to format
118
+ * @returns Formatted string type
119
+ */
120
+ export const TooltipHeader = ({ duration, value }: TooltipHeaderProps) => {
128
121
  const timeFormat = getTooltipDateFormat(duration);
129
122
  return (
130
123
  <ChartTooltipHeader>
@@ -0,0 +1,180 @@
1
+ import { ResponsiveContainer } from 'recharts';
2
+ import styled, { useTheme } from 'styled-components';
3
+ import { spacing, Stack, Wrap } from '../../../spacing';
4
+ import { Box } from '../../box/Box';
5
+ import { ConstrainedText } from '../../constrainedtext/Constrainedtext.component';
6
+ import { FormattedDateTime } from '../../date/FormattedDateTime';
7
+ import { IconHelp } from '../../iconhelper/IconHelper';
8
+ import { Loader } from '../../loader/Loader.component';
9
+ import { Text } from '../../text/Text.component';
10
+ import { formatXAxisDate, maxWidthTooltip } from './chartUtils';
11
+ import { TimeType } from '../types';
12
+
13
+ /**
14
+ * Styled ResponsiveContainer for charts
15
+ * Shared by Barchart and LineTimeSerieChart
16
+ * Ensures tooltip overflow is visible and removes outline
17
+ */
18
+ export const StyledResponsiveContainer = styled(ResponsiveContainer)`
19
+ // Avoid tooltip over constrained text to be cut off
20
+ & .recharts-surface {
21
+ outline: none;
22
+ overflow: visible;
23
+ }
24
+ `;
25
+
26
+ interface ChartLoadingOrErrorProps {
27
+ height: number;
28
+ }
29
+
30
+ /**
31
+ * Error state component for charts
32
+ */
33
+ export const ChartError = ({ height }: ChartLoadingOrErrorProps) => {
34
+ return (
35
+ <Box
36
+ height={height}
37
+ style={{
38
+ alignItems: 'center',
39
+ justifyContent: 'center',
40
+ display: 'flex',
41
+ }}
42
+ >
43
+ <Text>Chart data is not available</Text>
44
+ </Box>
45
+ );
46
+ };
47
+
48
+ /**
49
+ * Loading state component for charts
50
+ */
51
+ export const ChartLoading = ({ height }: ChartLoadingOrErrorProps) => {
52
+ return (
53
+ <Box
54
+ height={height}
55
+ style={{
56
+ alignItems: 'center',
57
+ justifyContent: 'center',
58
+ display: 'flex',
59
+ }}
60
+ >
61
+ <Loader size="larger" children={<Text>Loading Chart Data...</Text>} />
62
+ </Box>
63
+ );
64
+ };
65
+
66
+ interface ChartHeaderProps {
67
+ title?: string;
68
+ secondaryTitle?: string;
69
+ helpTooltip?: React.ReactNode;
70
+ rightTitle?: React.ReactNode;
71
+ }
72
+
73
+ /**
74
+ * Shared chart header component
75
+ * Used by Barchart and can be used by other charts
76
+ */
77
+ export const ChartHeader = ({
78
+ title,
79
+ secondaryTitle,
80
+ helpTooltip,
81
+ rightTitle,
82
+ }: ChartHeaderProps) => {
83
+ return (
84
+ <Wrap>
85
+ <Stack gap="r4">
86
+ <Text variant="ChartTitle">{title}</Text>
87
+ {helpTooltip && (
88
+ <IconHelp
89
+ tooltipMessage={helpTooltip}
90
+ overlayStyle={maxWidthTooltip}
91
+ />
92
+ )}
93
+
94
+ {secondaryTitle && (
95
+ <Text
96
+ color="textSecondary"
97
+ style={{
98
+ marginLeft: spacing.r8,
99
+ }}
100
+ >
101
+ {secondaryTitle}
102
+ </Text>
103
+ )}
104
+ </Stack>
105
+
106
+ {rightTitle && <Text>{rightTitle}</Text>}
107
+ </Wrap>
108
+ );
109
+ };
110
+
111
+ interface CustomTickProps {
112
+ x: number;
113
+ y: number;
114
+ payload: {
115
+ value: number;
116
+ };
117
+ visibleTicksCount: number;
118
+ width: number;
119
+ type: TimeType;
120
+ tickWidthOffset?: number;
121
+ }
122
+
123
+ /**
124
+ * Custom tick component for charts
125
+ * Used by Barchart for time-based x-axis ticks
126
+ */
127
+ export const CustomTick = ({
128
+ x,
129
+ y,
130
+ payload,
131
+ visibleTicksCount,
132
+ width,
133
+ type,
134
+ tickWidthOffset = 4,
135
+ }: CustomTickProps) => {
136
+ const theme = useTheme();
137
+ const tickWidth = width / visibleTicksCount - tickWidthOffset;
138
+ const centerX = x - tickWidth / 2;
139
+
140
+ const duration =
141
+ type.type === 'time'
142
+ ? (type.timeRange.endDate.getTime() -
143
+ type.timeRange.startDate.getTime()) /
144
+ 1000
145
+ : 0;
146
+
147
+ return (
148
+ <foreignObject
149
+ x={centerX}
150
+ y={y - 10}
151
+ width={tickWidth}
152
+ color={theme.textSecondary}
153
+ overflow="visible"
154
+ >
155
+ <ConstrainedText
156
+ color="textSecondary"
157
+ text={
158
+ <Text variant="Smaller">
159
+ {type.type === 'time' ? (
160
+ <FormattedDateTime
161
+ format={formatXAxisDate(duration)}
162
+ value={new Date(payload.value)}
163
+ />
164
+ ) : (
165
+ String(payload.value)
166
+ )}
167
+ </Text>
168
+ }
169
+ centered
170
+ tooltipStyle={{
171
+ backgroundColor: theme.backgroundLevel1,
172
+ padding: spacing.r10,
173
+ borderRadius: spacing.r8,
174
+ border: `1px solid ${theme.border}`,
175
+ position: 'absolute',
176
+ }}
177
+ />
178
+ </foreignObject>
179
+ );
180
+ };
@@ -0,0 +1,402 @@
1
+ import {
2
+ getRoundReferenceValue,
3
+ getTicks,
4
+ getUnitLabel,
5
+ addMissingDataPoint,
6
+ formatXAxisDate,
7
+ normalizeChartDataWithUnits,
8
+ getTooltipDateFormat,
9
+ } from './chartUtils';
10
+ import { NAN_STRING } from '../../constants';
11
+ import { UnitRange } from '../types';
12
+
13
+ describe('getRoundReferenceValue', () => {
14
+ it('should return appropriate rounded values with 10% buffer', () => {
15
+ // Small values (< 10)
16
+ expect(getRoundReferenceValue(0.1)).toBe(0.1); // 0.1 → 0.11 → 0.1 (magnitude 0.1, remainder 0.01)
17
+ expect(getRoundReferenceValue(1)).toBe(1); // 1 → 1.1 → 1 (magnitude 1, remainder 0.1)
18
+ expect(getRoundReferenceValue(2)).toBe(2); // 2 → 2.2 → 2 (magnitude 1, remainder 0.2)
19
+ expect(getRoundReferenceValue(3)).toBe(3); // 3 → 3.3 → 3 (magnitude 1, remainder 0.3)
20
+
21
+ // Values 5-10 range
22
+ expect(getRoundReferenceValue(6)).toBe(6); // 6 → 6.6 → 6 (magnitude 1, remainder 0.6)
23
+ expect(getRoundReferenceValue(9)).toBe(9); // 9 → 9.9 → 9 (magnitude 1, remainder 0.9)
24
+
25
+ // Larger values get 10% buffer applied
26
+ expect(getRoundReferenceValue(15)).toBe(10); // 15 → 16.5, remainder 5, incremented 20 > 16.5, so round down to 10
27
+ expect(getRoundReferenceValue(35)).toBe(30); // 35 → 38.5, remainder 5, incremented 40 > 38.5, so round down to 30
28
+ expect(getRoundReferenceValue(75)).toBe(80); // 75 → 82.5, remainder 5, incremented 80 <= 82.5, so round up to 80
29
+ expect(getRoundReferenceValue(150)).toBe(150); // 150 → 165, remainder 0, so return 150
30
+ expect(getRoundReferenceValue(350)).toBe(350); // 350 → 385, remainder 0, so return 350
31
+ expect(getRoundReferenceValue(750)).toBe(750); // 750 → 825, remainder 0, so return 750
32
+ expect(getRoundReferenceValue(1500)).toBe(1500); // 1500 → 1650, remainder 0, so return 1500
33
+ expect(getRoundReferenceValue(3500)).toBe(3500); // 3500 → 3850, remainder 0, so return 3500
34
+ expect(getRoundReferenceValue(7500)).toBe(7500); // 7500 → 8250, remainder 0, so return 7500
35
+ expect(getRoundReferenceValue(15000)).toBe(15000); // 15000 → 16500, remainder 0, so return 15000
36
+ });
37
+ });
38
+
39
+ describe('getTicks', () => {
40
+ it('should return ticks for small values < 10', () => {
41
+ // Non-symmetrical ticks
42
+ expect(getTicks(1, false)).toEqual([0, 0.5, 1]); // 1 % 2 != 0, defaults to 3 ticks
43
+ expect(getTicks(2, false)).toEqual([0, 1, 2]); // 2 % (3-1) == 0, uses 3 ticks
44
+ expect(getTicks(5, false)).toEqual([0, 2.5, 5]); // 5 % 2 != 0 and 5 % 3 != 0, defaults to 3 ticks
45
+ expect(getTicks(10, false)).toEqual([0, 5, 10]); // 10 % 2 == 0, uses 3 ticks
46
+ expect(getTicks(15, false)).toEqual([0, 5, 10, 15]); // 15 % 3= 0, uses 4 ticks
47
+ expect(getTicks(20, false)).toEqual([0, 10, 20]); // 20 % 2 == 0, uses 3 ticks
48
+ expect(getTicks(250, false)).toEqual([0, 125, 250]); // 250 % 3 = 0, uses 3 ticks
49
+ // Symmetrical ticks
50
+ expect(getTicks(1, true)).toEqual([-1, -0.5, 0, 0.5, 1]); // 1 % 2 != 0, defaults to 3 ticks, symmetrical adds negatives
51
+ expect(getTicks(2, true)).toEqual([-2, -1, 0, 1, 2]); // 2 % (3-1) == 0, uses 3 ticks, symmetrical adds negatives
52
+ expect(getTicks(5, true)).toEqual([-5, -2.5, 0, 2.5, 5]); // 5 % 2 != 0 and 5 % 3 != 0, defaults to 3 ticks, symmetrical adds negatives
53
+ expect(getTicks(10, true)).toEqual([-10, -5, 0, 5, 10]); // 10 % 2 == 0, uses 3 ticks, symmetrical adds negatives
54
+ expect(getTicks(15, true)).toEqual([-15, -10, -5, 0, 5, 10, 15]); // 15 % 3 = 0, uses 4 ticks, symmetrical adds negatives
55
+ expect(getTicks(20, true)).toEqual([-20, -10, 0, 10, 20]); // 20 % 2 == 0, uses 3 ticks, symmetrical adds negatives
56
+ expect(getTicks(250, true)).toEqual([-250, -125, 0, 125, 250]); // 250 % 3 = 0, uses 3 ticks, symmetrical adds negatives
57
+ });
58
+
59
+ it('should generate evenly spaced ticks for larger values', () => {
60
+ const ticks = getTicks(100, false);
61
+ expect(ticks).toHaveLength(3);
62
+ expect(ticks[0]).toBe(0);
63
+ expect(ticks[ticks.length - 1]).toBe(100);
64
+ });
65
+ });
66
+
67
+ describe('getUnitLabel', () => {
68
+ const unitRange: UnitRange = [
69
+ { threshold: 1, label: 'B' },
70
+ { threshold: 1000, label: 'KB' },
71
+ { threshold: 1000000, label: 'MB' },
72
+ { threshold: 1000000000, label: 'GB' },
73
+ ];
74
+ it('should return correct unit label and threshold', () => {
75
+ const result = getUnitLabel(unitRange, 500);
76
+ expect(result).toEqual({ valueBase: 1, unitLabel: 'B' });
77
+ const result2 = getUnitLabel(unitRange, 500000);
78
+ expect(result2).toEqual({ valueBase: 1000, unitLabel: 'KB' });
79
+ const result3 = getUnitLabel(unitRange, 500000000);
80
+ expect(result3).toEqual({ valueBase: 1000000, unitLabel: 'MB' });
81
+ const result4 = getUnitLabel(unitRange, 500000000000);
82
+ expect(result4).toEqual({ valueBase: 1000000000, unitLabel: 'GB' });
83
+ });
84
+
85
+ it('should return correct unit for medium values even if range is disordered', () => {
86
+ const unsortedRange = [
87
+ { threshold: 1000000, label: 'MB' },
88
+ { threshold: 1000, label: 'KB' },
89
+ { threshold: 1000000000, label: 'GB' },
90
+ { threshold: 1, label: 'B' },
91
+ ];
92
+ const result = getUnitLabel(unsortedRange, 50000);
93
+ expect(result).toEqual({ valueBase: 1000, unitLabel: 'KB' });
94
+ });
95
+ });
96
+
97
+ describe('addMissingDataPoint', () => {
98
+ it('should return empty array for invalid inputs', () => {
99
+ expect(addMissingDataPoint([], 0, 100, 10)).toEqual([]);
100
+ expect(addMissingDataPoint([[10, 5]], undefined, 100, 10)).toEqual([]);
101
+ expect(addMissingDataPoint([[10, 5]], 0, 0, 10)).toEqual([]);
102
+ expect(addMissingDataPoint([[10, 5]], -1, 100, 10)).toEqual([]);
103
+ });
104
+
105
+ it('should add missing data points at the beginning', () => {
106
+ const original: [number, number][] = [
107
+ [20, 5],
108
+ [30, 10],
109
+ ];
110
+ const result = addMissingDataPoint(original, 0, 100, 10);
111
+
112
+ expect(result[0]).toEqual([0, NAN_STRING]);
113
+ expect(result[1]).toEqual([10, NAN_STRING]);
114
+ expect(result[2]).toEqual([20, 5]);
115
+ });
116
+
117
+ it('should add missing data points in the middle', () => {
118
+ const original: [number, number][] = [
119
+ [0, 5],
120
+ [30, 10],
121
+ ];
122
+ const result = addMissingDataPoint(original, 0, 100, 10);
123
+
124
+ expect(result[0]).toEqual([0, 5]);
125
+ expect(result[1]).toEqual([10, NAN_STRING]);
126
+ expect(result[2]).toEqual([20, NAN_STRING]);
127
+ expect(result[3]).toEqual([30, 10]);
128
+ });
129
+
130
+ it('should add missing data points at the end', () => {
131
+ const original: [number, number][] = [
132
+ [0, 5],
133
+ [10, 10],
134
+ ];
135
+ const result = addMissingDataPoint(original, 0, 40, 10);
136
+
137
+ expect(result[result.length - 3]).toEqual([10, 10]);
138
+ expect(result[result.length - 2]).toEqual([20, NAN_STRING]);
139
+ expect(result[result.length - 1]).toEqual([30, NAN_STRING]);
140
+ });
141
+
142
+ it('should handle data points with null values', () => {
143
+ const original: [number, number | null][] = [
144
+ [0, 5],
145
+ [10, null],
146
+ [20, 10],
147
+ ];
148
+ const result = addMissingDataPoint(original, 0, 30, 10);
149
+
150
+ expect(result).toEqual([
151
+ [0, 5],
152
+ [10, null],
153
+ [20, 10],
154
+ ]);
155
+ });
156
+
157
+ it('should handle string values', () => {
158
+ const original: [number, string][] = [
159
+ [0, '5'],
160
+ [10, '10'],
161
+ ];
162
+ const result = addMissingDataPoint(original, 0, 30, 10);
163
+
164
+ expect(result[0]).toEqual([0, '5']);
165
+ expect(result[1]).toEqual([10, '10']);
166
+ expect(result[2]).toEqual([20, NAN_STRING]);
167
+ });
168
+ });
169
+
170
+ describe('formatXAxisDate', () => {
171
+ const ONE_DAY = 24 * 60 * 60;
172
+ const ONE_WEEK = 7 * ONE_DAY;
173
+
174
+ it('should return "time" for durations <= 1 day', () => {
175
+ expect(formatXAxisDate(ONE_DAY)).toBe('time');
176
+ expect(formatXAxisDate(ONE_DAY / 2)).toBe('time');
177
+ expect(formatXAxisDate(1000)).toBe('time');
178
+ });
179
+
180
+ it('should return "day-month-abbreviated" for durations <= 1 week', () => {
181
+ expect(formatXAxisDate(ONE_DAY * 2)).toBe('day-month-abbreviated');
182
+ expect(formatXAxisDate(ONE_WEEK - 1000)).toBe('day-month-abbreviated');
183
+ });
184
+
185
+ it('should return "chart-long-term-date" for durations > 1 week', () => {
186
+ expect(formatXAxisDate(ONE_WEEK + 1000)).toBe('chart-long-term-date');
187
+ expect(formatXAxisDate(ONE_DAY * 30)).toBe('chart-long-term-date');
188
+ expect(formatXAxisDate(ONE_DAY * 365)).toBe('chart-long-term-date');
189
+ });
190
+ });
191
+
192
+ describe('getTooltipDateFormat', () => {
193
+ it('should return "day-month-abbreviated-hour-minute-second" for durations <= 1 hour', () => {
194
+ expect(getTooltipDateFormat(60)).toBe(
195
+ 'day-month-abbreviated-hour-minute-second',
196
+ );
197
+ expect(getTooltipDateFormat(60 * 40)).toBe(
198
+ 'day-month-abbreviated-hour-minute-second',
199
+ );
200
+ expect(getTooltipDateFormat(60 * 60)).toBe(
201
+ 'day-month-abbreviated-hour-minute-second',
202
+ );
203
+ });
204
+ it('should return "day-month-abbreviated-hour-minute" for durations <= 7 days', () => {
205
+ expect(getTooltipDateFormat(60 * 60 * 2)).toBe(
206
+ 'day-month-abbreviated-hour-minute',
207
+ );
208
+ expect(getTooltipDateFormat(60 * 60 * 24)).toBe(
209
+ 'day-month-abbreviated-hour-minute',
210
+ );
211
+ expect(getTooltipDateFormat(60 * 60 * 24 * 7)).toBe(
212
+ 'day-month-abbreviated-hour-minute',
213
+ );
214
+ });
215
+ it('should return "day-month-abbreviated-year-hour-minute" for durations > 7 days', () => {
216
+ expect(getTooltipDateFormat(60 * 60 * 24 * 7.1)).toBe(
217
+ 'day-month-abbreviated-year-hour-minute',
218
+ );
219
+ expect(getTooltipDateFormat(60 * 60 * 24 * 30)).toBe(
220
+ 'day-month-abbreviated-year-hour-minute',
221
+ );
222
+ });
223
+ });
224
+
225
+ describe('normalizeChartDataWithUnits', () => {
226
+ describe('with Barchart (category as excludeKey)', () => {
227
+ it('should compute unit label and normalize data when unit range is provided', () => {
228
+ const data = [
229
+ { category: 'category1', success: 1680 },
230
+ { category: 'category2', success: 2000 },
231
+ ];
232
+ const maxValue = 2000;
233
+ const unitRange: UnitRange = [{ threshold: 1000, label: 'kB' }];
234
+
235
+ const result = normalizeChartDataWithUnits(
236
+ data,
237
+ maxValue,
238
+ unitRange,
239
+ 'category',
240
+ );
241
+
242
+ expect(result.unitLabel).toBe('kB');
243
+ // 2000 / 1000 = 2 → getRoundReferenceValue(2) = 2
244
+ expect(result.topValue).toBe(2);
245
+ expect(result.rechartsData).toEqual([
246
+ { category: 'category1', success: 1.68 },
247
+ { category: 'category2', success: 2 },
248
+ ]);
249
+ });
250
+
251
+ it('should handle threshold of 0 (bytes)', () => {
252
+ const data = [{ category: 'category1', success: 680 }];
253
+ const maxValue = 680;
254
+ const unitRange: UnitRange = [
255
+ { threshold: 0, label: 'B' },
256
+ { threshold: 1000, label: 'kB' },
257
+ ];
258
+
259
+ const result = normalizeChartDataWithUnits(
260
+ data,
261
+ maxValue,
262
+ unitRange,
263
+ 'category',
264
+ );
265
+
266
+ expect(result.unitLabel).toBe('B');
267
+ // 680 / 1 = 680 → getRoundReferenceValue(680) = 680
268
+ expect(result.topValue).toBe(680);
269
+ expect(result.rechartsData).toEqual([
270
+ { category: 'category1', success: 680 },
271
+ ]);
272
+ });
273
+
274
+ it('should not normalize when no unit range provided', () => {
275
+ const data = [
276
+ { category: 'A', value: 100 },
277
+ { category: 'B', value: 200 },
278
+ ];
279
+ const maxValue = 200;
280
+
281
+ const result = normalizeChartDataWithUnits(
282
+ data,
283
+ maxValue,
284
+ undefined,
285
+ 'category',
286
+ );
287
+
288
+ expect(result.unitLabel).toBeUndefined();
289
+ // 200 → getRoundReferenceValue(200) = 200
290
+ expect(result.topValue).toBe(200);
291
+ expect(result.rechartsData).toEqual(data);
292
+ });
293
+
294
+ it('should exclude category key from normalization', () => {
295
+ const data = [{ category: 1000, value: 1000 }];
296
+ const maxValue = 1000;
297
+ const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
298
+
299
+ const result = normalizeChartDataWithUnits(
300
+ data,
301
+ maxValue,
302
+ unitRange,
303
+ 'category',
304
+ );
305
+
306
+ // category should remain unchanged (1000, not normalized to 1)
307
+ expect(result.rechartsData[0].category).toBe(1000);
308
+ // value should be normalized
309
+ expect(result.rechartsData[0].value).toBe(1);
310
+ });
311
+ });
312
+
313
+ describe('with LineTimeSerieChart (timestamp as excludeKey)', () => {
314
+ it('should normalize data and exclude timestamp', () => {
315
+ const data = [
316
+ { timestamp: 1634567890000, metric1: 5000, metric2: 3000 },
317
+ { timestamp: 1634567900000, metric1: 6000, metric2: 4000 },
318
+ ];
319
+ const maxValue = 6000;
320
+ const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
321
+
322
+ const result = normalizeChartDataWithUnits(
323
+ data,
324
+ maxValue,
325
+ unitRange,
326
+ 'timestamp',
327
+ );
328
+
329
+ expect(result.unitLabel).toBe('k');
330
+ // 6000 / 1000 = 6 → getRoundReferenceValue(6) = 6
331
+ expect(result.topValue).toBe(6);
332
+ expect(result.rechartsData).toEqual([
333
+ { timestamp: 1634567890000, metric1: 5, metric2: 3 },
334
+ { timestamp: 1634567900000, metric1: 6, metric2: 4 },
335
+ ]);
336
+ });
337
+
338
+ it('should handle multiple metrics with timestamp', () => {
339
+ const data = [{ timestamp: 100, cpu: 2500, memory: 1500 }];
340
+ const maxValue = 2500;
341
+ const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
342
+
343
+ const result = normalizeChartDataWithUnits(
344
+ data,
345
+ maxValue,
346
+ unitRange,
347
+ 'timestamp',
348
+ );
349
+
350
+ expect(result.rechartsData[0].timestamp).toBe(100); // unchanged
351
+ expect(result.rechartsData[0].cpu).toBe(2.5); // normalized
352
+ expect(result.rechartsData[0].memory).toBe(1.5); // normalized
353
+ });
354
+ });
355
+
356
+ describe('edge cases', () => {
357
+ it('should handle empty data array', () => {
358
+ const result = normalizeChartDataWithUnits([], 0, undefined, 'category');
359
+
360
+ expect(result.unitLabel).toBeUndefined();
361
+ expect(result.topValue).toBe(1); // Default for 0
362
+ expect(result.rechartsData).toEqual([]);
363
+ });
364
+
365
+ it('should handle data with only exclude key', () => {
366
+ const data = [{ category: 'A' }, { category: 'B' }];
367
+ const result = normalizeChartDataWithUnits(
368
+ data,
369
+ 10,
370
+ undefined,
371
+ 'category',
372
+ );
373
+
374
+ expect(result.rechartsData).toEqual(data);
375
+ });
376
+
377
+ it('should handle mixed string and number values', () => {
378
+ const data = [{ category: 'test', value1: 1000, value2: 'text' }];
379
+ const unitRange: UnitRange = [{ threshold: 1000, label: 'k' }];
380
+
381
+ const result = normalizeChartDataWithUnits(
382
+ data,
383
+ 1000,
384
+ unitRange,
385
+ 'category',
386
+ );
387
+
388
+ expect(result.rechartsData[0].value1).toBe(1); // normalized
389
+ expect(result.rechartsData[0].value2).toBe('text'); // unchanged
390
+ });
391
+
392
+ it('should handle empty unit range array', () => {
393
+ const data = [{ category: 'A', value: 100 }];
394
+ const result = normalizeChartDataWithUnits(data, 100, [], 'category');
395
+
396
+ expect(result.unitLabel).toBeUndefined();
397
+ // 100 → getRoundReferenceValue(100) = 100
398
+ expect(result.topValue).toBe(100);
399
+ expect(result.rechartsData).toEqual(data);
400
+ });
401
+ });
402
+ });