@scality/core-ui 0.167.0 → 0.169.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 (45) hide show
  1. package/.github/workflows/github-pages.yml +5 -3
  2. package/.storybook/preview.js +1 -0
  3. package/dist/components/barchartv2/Barchart.component.d.ts +5 -1
  4. package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
  5. package/dist/components/barchartv2/Barchart.component.js +12 -7
  6. package/dist/components/barchartv2/ChartTooltip.d.ts +9 -13
  7. package/dist/components/barchartv2/ChartTooltip.d.ts.map +1 -1
  8. package/dist/components/barchartv2/ChartTooltip.js +14 -4
  9. package/dist/components/barchartv2/utils.d.ts +9 -2
  10. package/dist/components/barchartv2/utils.d.ts.map +1 -1
  11. package/dist/components/barchartv2/utils.js +14 -18
  12. package/dist/components/buttonv2/Buttonv2.component.d.ts.map +1 -1
  13. package/dist/components/buttonv2/Buttonv2.component.js +27 -6
  14. package/dist/components/date/FormattedDateTime.d.ts +20 -1
  15. package/dist/components/date/FormattedDateTime.d.ts.map +1 -1
  16. package/dist/components/date/FormattedDateTime.js +36 -0
  17. package/dist/components/linetemporalchart/ChartUtil.d.ts.map +1 -1
  18. package/dist/components/linetemporalchart/ChartUtil.js +6 -0
  19. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +7 -1
  20. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
  21. package/dist/components/linetimeseriechart/linetimeseriechart.component.js +36 -32
  22. package/dist/components/linetimeseriechart/utils.d.ts +16 -0
  23. package/dist/components/linetimeseriechart/utils.d.ts.map +1 -0
  24. package/dist/components/linetimeseriechart/utils.js +28 -0
  25. package/dist/style/theme.d.ts +2 -2
  26. package/dist/style/theme.d.ts.map +1 -1
  27. package/dist/style/theme.js +26 -0
  28. package/package.json +5 -4
  29. package/src/lib/components/barchartv2/Barchart.component.test.tsx +12 -8
  30. package/src/lib/components/barchartv2/Barchart.component.tsx +29 -9
  31. package/src/lib/components/barchartv2/ChartTooltip.test.tsx +119 -0
  32. package/src/lib/components/barchartv2/ChartTooltip.tsx +49 -19
  33. package/src/lib/components/barchartv2/utils.test.ts +31 -46
  34. package/src/lib/components/barchartv2/utils.ts +24 -31
  35. package/src/lib/components/buttonv2/Buttonv2.component.tsx +27 -6
  36. package/src/lib/components/date/FormattedDateTime.tsx +43 -1
  37. package/src/lib/components/linetemporalchart/ChartUtil.ts +6 -0
  38. package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +81 -54
  39. package/src/lib/components/linetimeseriechart/linetimeseriechart.test.tsx +71 -0
  40. package/src/lib/components/linetimeseriechart/utils.test.ts +87 -0
  41. package/src/lib/components/linetimeseriechart/utils.ts +43 -0
  42. package/src/lib/style/theme.ts +26 -0
  43. package/stories/BarChart/barchart.stories.tsx +108 -13
  44. package/stories/color.mdx +12 -0
  45. package/stories/linetimeseriechart.stories.tsx +97 -0
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Line, LineChart, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, CartesianGrid, } from 'recharts';
3
- import { useMemo, useRef } from 'react';
3
+ import { useCallback, useMemo, useRef } from 'react';
4
4
  import { useTheme } from 'styled-components';
5
5
  import { addMissingDataPoint } from '../linetemporalchart/ChartUtil';
6
6
  import styled from 'styled-components';
@@ -12,7 +12,9 @@ import { spacing } from '../../spacing';
12
12
  import { getUnitLabel } from '../linetemporalchart/ChartUtil';
13
13
  import { Icon } from '../icon/Icon.component';
14
14
  import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component';
15
- import { DAY_MONTH_ABBREVIATED_HOUR_MINUTE, FormattedDateTime, } from '../date/FormattedDateTime';
15
+ import { FormattedDateTime } from '../date/FormattedDateTime';
16
+ import { Box } from '../box/Box';
17
+ import { formatXAxisLabel } from './utils';
16
18
  const LineTemporalChartWrapper = styled.div `
17
19
  display: flex;
18
20
  flex-direction: column;
@@ -44,6 +46,8 @@ const TooltipValue = styled.div `
44
46
  color: ${(props) => props.theme.textSecondary};
45
47
  display: flex;
46
48
  align-items: flex-start;
49
+ justify-content: space-between;
50
+ width: 100%;
47
51
  `;
48
52
  const TooltipLegend = styled.div `
49
53
  width: 12px;
@@ -53,28 +57,30 @@ const TooltipLegend = styled.div `
53
57
  flex-shrink: 0;
54
58
  margin-top: 8px;
55
59
  `;
56
- const TooltipContent = styled.div `
60
+ const TooltipLeftGroup = styled.div `
57
61
  display: flex;
62
+ align-items: flex-start;
58
63
  min-width: 0;
59
64
  flex: 1;
60
65
  `;
61
66
  const TooltipName = styled.div `
62
- margin-right: 4px;
63
67
  word-wrap: break-word;
64
68
  word-break: break-word;
65
- justify-content: flex-start;
69
+ flex: 1;
66
70
  `;
67
71
  const TooltipInstanceValue = styled.div `
68
- justify-content: flex-end;
72
+ margin-left: 16px;
73
+ flex-shrink: 0;
74
+ text-align: right;
69
75
  `;
70
- const CustomTooltip = ({ active, payload, label, unitLabel, }) => {
76
+ const CustomTooltip = ({ active, payload, label, unitLabel, timeFormat, }) => {
71
77
  if (!active || !payload || !payload.length || !label)
72
78
  return null;
73
79
  // We can't use the default itemSorter method because it's a custom tooltip.
74
80
  // Sort the payload here instead
75
81
  const sortedPayload = [...payload].sort((a, b) => {
76
- const aValue = Number(a.value);
77
- const bValue = Number(b.value);
82
+ const aValue = a.value;
83
+ const bValue = b.value;
78
84
  if (aValue >= 0 && bValue >= 0) {
79
85
  return bValue - aValue; // Higher positive values first
80
86
  }
@@ -83,14 +89,16 @@ const CustomTooltip = ({ active, payload, label, unitLabel, }) => {
83
89
  }
84
90
  return bValue - aValue; // Positives before negatives
85
91
  });
86
- return (_jsxs(TooltipContainer, { children: [_jsx(TooltipTime, { children: _jsx(FormattedDateTime, { format: "day-month-abbreviated-hour-minute-second", value: new Date(label) }) }), sortedPayload.map((entry, index) => (_jsxs(TooltipValue, { children: [_jsx(TooltipLegend, { color: entry.color }), _jsxs(TooltipContent, { children: [_jsx(TooltipName, { children: entry.name }), _jsx(TooltipInstanceValue, { children: isNaN(Number(entry.value))
87
- ? '-'
88
- : `${Number(entry.value).toFixed(2)}${unitLabel}` })] })] }, index)))] }));
92
+ return (_jsxs(TooltipContainer, { children: [_jsx(TooltipTime, { children: _jsx(FormattedDateTime, { format: timeFormat === 'date-time'
93
+ ? 'day-month-abbreviated-hour-minute-second'
94
+ : 'long-date-without-weekday', value: new Date(label) }) }), sortedPayload.map((entry, index) => (_jsxs(TooltipValue, { children: [_jsxs(TooltipLeftGroup, { children: [_jsx(TooltipLegend, { color: entry.color }), _jsx(TooltipName, { children: entry.name })] }), _jsx(TooltipInstanceValue, { children: !Number.isFinite(entry.value)
95
+ ? '-'
96
+ : `${entry.value.toFixed(2)} ${unitLabel}` })] }, index)))] }));
89
97
  };
90
98
  const isSymmetricalSeries = (series) => {
91
99
  return 'above' in series && 'below' in series;
92
100
  };
93
- export function LineTimeSerieChart({ series, title, height, startingTimeStamp, interval, duration, unitRange, isLoading = false, yAxisType = 'default', yAxisTitle, helpText, ...rest }) {
101
+ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, interval, duration, unitRange, isLoading = false, timeFormat = 'date-time', yAxisType = 'default', yAxisTitle, helpText, ...rest }) {
94
102
  const theme = useTheme();
95
103
  const { getColor } = useChartLegend();
96
104
  const chartRef = useRef(null);
@@ -135,25 +143,24 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
135
143
  // Convert object to array for Recharts
136
144
  return Object.values(dataPointsByTime).sort((a, b) => a.timestamp - b.timestamp);
137
145
  }, [series, startingTimeStamp, duration, interval, yAxisType]);
138
- // Calculate 5 perfectly evenly spaced ticks
146
+ // Calculate evenly spaced ticks that avoid the very beginning and end
139
147
  const xAxisTicks = useMemo(() => {
140
148
  if (!chartData || chartData.length === 0)
141
149
  return [];
142
150
  const timestamps = chartData.map((d) => d.timestamp);
143
151
  const minTimestamp = Math.min(...timestamps);
144
152
  const maxTimestamp = Math.max(...timestamps);
145
- // Calculate 5 perfectly evenly spaced ticks
146
153
  const timeRange = maxTimestamp - minTimestamp;
147
- const interval = timeRange / 4; // 4 intervals create 5 points
148
- const exactEvenTicks = [
149
- minTimestamp,
150
- minTimestamp + interval,
151
- minTimestamp + interval * 2,
152
- minTimestamp + interval * 3,
153
- maxTimestamp,
154
- ];
155
- // Return perfectly even ticks (guaranteed to be evenly divided)
156
- return exactEvenTicks;
154
+ // Add padding to avoid labels at the very edges (10% padding on each side)
155
+ const padding = timeRange * 0.1;
156
+ const paddedStart = minTimestamp + padding;
157
+ const paddedEnd = maxTimestamp - padding;
158
+ const paddedRange = paddedEnd - paddedStart;
159
+ // Create 5 evenly spaced ticks within the padded range
160
+ const numTicks = 5;
161
+ const tickInterval = paddedRange / (numTicks - 1);
162
+ const evenlySpacedTicks = Array.from({ length: numTicks }, (_, index) => paddedStart + index * tickInterval);
163
+ return evenlySpacedTicks;
157
164
  }, [chartData]);
158
165
  // 3. Transform the data base on the valuebase
159
166
  const { topValue, unitLabel, rechartsData } = useMemo(() => {
@@ -217,11 +224,8 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
217
224
  };
218
225
  }, [series, getColor]);
219
226
  // Format time for display the tick in the x axis
220
- const formatTime = useMemo(() => (timestamp) => {
221
- const date = new Date(timestamp);
222
- return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
223
- }, []);
224
- return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(ChartHeader, { children: [_jsxs(ChartTitleText, { children: [title, " ", unitLabel && `(${unitLabel})`] }), helpText && (_jsx(TooltipComponent, { placement: 'right', overlay: _jsx(SmallerText, { children: helpText }), children: _jsx(Icon, { name: "Info", color: theme.buttonSecondary }) })), isLoading && _jsx(Loader, {})] }), _jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(LineChart, { data: rechartsData, ref: chartRef, margin: { top: 0, right: 0, bottom: 0, left: 0 }, "aria-label": `Time series chart for ${title}`, children: [_jsx(CartesianGrid, { vertical: true, horizontal: true, verticalPoints: [0], horizontalPoints: [0], stroke: theme.border, fill: theme.backgroundLevel4, strokeWidth: 1 }), _jsx(XAxis, { dataKey: "timestamp", type: "number", domain: ['dataMin', 'dataMax'], ticks: xAxisTicks, tickFormatter: formatTime, tickCount: 5, tick: {
227
+ const formatXAxisLabelCallback = useCallback((timestamp) => formatXAxisLabel(timestamp, timeFormat, chartData), [timeFormat, chartData]);
228
+ return (_jsxs(LineTemporalChartWrapper, { children: [_jsxs(ChartHeader, { children: [_jsxs(ChartTitleText, { children: [title, " ", unitLabel && `(${unitLabel})`] }), helpText && (_jsx(Box, { ml: spacing.r4, children: _jsx(TooltipComponent, { placement: 'right', overlay: _jsx(SmallerText, { children: helpText }), children: _jsx(Icon, { name: "Info", color: theme.buttonSecondary }) }) })), isLoading && _jsx(Loader, {})] }), _jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(LineChart, { data: rechartsData, ref: chartRef, margin: { top: 0, right: 0, bottom: 0, left: 0 }, "aria-label": `Time series chart for ${title}`, children: [_jsx(CartesianGrid, { vertical: true, horizontal: true, verticalPoints: [0], horizontalPoints: [0], stroke: theme.border, fill: theme.backgroundLevel4, strokeWidth: 1 }), _jsx(XAxis, { dataKey: "timestamp", type: "number", domain: ['dataMin', 'dataMax'], ticks: xAxisTicks, tickFormatter: formatXAxisLabelCallback, tickCount: 5, tick: {
225
229
  fill: theme.textSecondary,
226
230
  fontSize: fontSize.smaller,
227
231
  }, axisLine: { stroke: theme.border } }), _jsx(YAxis, { orientation: "right", allowDataOverflow: false, label: {
@@ -240,8 +244,8 @@ export function LineTimeSerieChart({ series, title, height, startingTimeStamp, i
240
244
  : [0, topValue], axisLine: { stroke: theme.border }, tick: {
241
245
  fill: theme.textSecondary,
242
246
  fontSize: fontSize.smaller,
243
- }, tickFormatter: (value) => Math.round(value).toString() }), _jsx(Tooltip, { content: _jsx(CustomTooltip, { unitLabel: unitLabel }) }), yAxisType === 'symmetrical' && (_jsx(ReferenceLine, { y: 0, stroke: theme.border })), Object.entries(groupedSeries).map(([resource, resourceSeries]) => resourceSeries.map((serie, serieIndex) => {
247
+ }, tickFormatter: (value) => Math.round(value).toString(), tickCount: 5, interval: 'preserveStartEnd' }), _jsx(Tooltip, { content: _jsx(CustomTooltip, { unitLabel: unitLabel, timeFormat: timeFormat }) }), yAxisType === 'symmetrical' && (_jsx(ReferenceLine, { y: 0, stroke: theme.border })), Object.entries(groupedSeries).map(([resource, resourceSeries]) => resourceSeries.map((serie, serieIndex) => {
244
248
  const label = serie.getTooltipLabel(serie.metricPrefix, serie.resource);
245
- return (_jsx(Line, { type: "monotone", dataKey: label, stroke: colorMapping[resource], dot: false }, `${title}-${resource}-${serieIndex}`));
249
+ return (_jsx(Line, { type: "monotone", dataKey: label, stroke: colorMapping[resource], dot: false, isAnimationActive: false }, `${title}-${resource}-${serieIndex}`));
246
250
  }))] }) })] }));
247
251
  }
@@ -0,0 +1,16 @@
1
+ export declare const ONE_YEAR_MILLISECONDS: number;
2
+ export type ChartDataPoint = {
3
+ timestamp: number;
4
+ } & Record<string, number | null>;
5
+ /**
6
+ * Formats timestamp for X-axis labels based on time format and data range:
7
+ * For 'date-time' format, return day-month-abbreviated-hour-minute format
8
+ * For 'date' format, return YYYY-MM-DD format if time range is greater than 1 year, otherwise return MM-DD format
9
+ *
10
+ * @param timestamp - The timestamp to format in milliseconds
11
+ * @param timeFormat - The format type ('date-time' or 'date')
12
+ * @param chartData - The chart data to determine time range for optimal formatting
13
+ * @returns Formatted string for display on X-axis
14
+ */
15
+ export declare const formatXAxisLabel: (timestamp: number, timeFormat?: "date-time" | "date", chartData?: ChartDataPoint[]) => string;
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/linetimeseriechart/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,QAA4B,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAElC;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,cAChB,MAAM,eACL,WAAW,GAAG,MAAM,cACrB,cAAc,EAAE,KAC1B,MAgBF,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { DAY_MONTH_ABBREVIATED_HOUR_MINUTE, YEAR_MONTH_DAY_FORMATTER, MONTH_DAY_FORMATTER, } from '../date/FormattedDateTime';
2
+ export const ONE_YEAR_MILLISECONDS = 366 * 24 * 60 * 60 * 1000;
3
+ /**
4
+ * Formats timestamp for X-axis labels based on time format and data range:
5
+ * For 'date-time' format, return day-month-abbreviated-hour-minute format
6
+ * For 'date' format, return YYYY-MM-DD format if time range is greater than 1 year, otherwise return MM-DD format
7
+ *
8
+ * @param timestamp - The timestamp to format in milliseconds
9
+ * @param timeFormat - The format type ('date-time' or 'date')
10
+ * @param chartData - The chart data to determine time range for optimal formatting
11
+ * @returns Formatted string for display on X-axis
12
+ */
13
+ export const formatXAxisLabel = (timestamp, timeFormat = 'date-time', chartData = []) => {
14
+ const date = new Date(timestamp);
15
+ if (!chartData.length) {
16
+ return YEAR_MONTH_DAY_FORMATTER.format(date);
17
+ }
18
+ if (timeFormat === 'date-time') {
19
+ return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
20
+ }
21
+ const timestamps = chartData.map((d) => d.timestamp);
22
+ const minTimestamp = Math.min(...timestamps);
23
+ const maxTimestamp = Math.max(...timestamps);
24
+ const timeRangeMilliseconds = maxTimestamp - minTimestamp;
25
+ return timeRangeMilliseconds >= ONE_YEAR_MILLISECONDS
26
+ ? YEAR_MONTH_DAY_FORMATTER.format(date)
27
+ : MONTH_DAY_FORMATTER.format(date);
28
+ };
@@ -52,7 +52,7 @@ export type CoreUITheme = {
52
52
  textReverse: string;
53
53
  textLink: string;
54
54
  };
55
- export declare const coreUIAvailableThemesNames: readonly ["darkRebrand", "artescaLight", "ring9dark"];
55
+ export declare const coreUIAvailableThemesNames: readonly ["darkRebrand", "artescaLight", "ring9dark", "G-Dark"];
56
56
  export type CoreUIThemeName = (typeof coreUIAvailableThemesNames)[number];
57
57
  export declare const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme>;
58
58
  /**
@@ -62,7 +62,7 @@ export declare const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme>
62
62
  *
63
63
  * import { coreUIAvailableThemes } from '@scality/core-ui/dist/style/theme';
64
64
  */
65
- export declare const defaultTheme: Record<"darkRebrand" | "artescaLight" | "ring9dark", CoreUITheme>;
65
+ export declare const defaultTheme: Record<"darkRebrand" | "artescaLight" | "ring9dark" | "G-Dark", CoreUITheme>;
66
66
  /**
67
67
  * @deprecated
68
68
  * Instead should use useTheme()
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/style/theme.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/style/theme.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,7 @@ export const coreUIAvailableThemesNames = [
33
33
  'darkRebrand',
34
34
  'artescaLight',
35
35
  'ring9dark',
36
+ 'G-Dark'
36
37
  ];
37
38
  export const coreUIAvailableThemes = {
38
39
  darkRebrand: {
@@ -110,6 +111,31 @@ export const coreUIAvailableThemes = {
110
111
  textReverse: '#000000',
111
112
  textLink: '#71AEFF',
112
113
  },
114
+ 'G-Dark': {
115
+ statusHealthy: '#0AADA6',
116
+ statusHealthyRGB: '10,173,166',
117
+ statusWarning: '#F8F32B',
118
+ statusWarningRGB: '248,243,43',
119
+ statusCritical: '#E84855',
120
+ statusCriticalRGB: '232,72,85',
121
+ selectedActive: '#037AFF',
122
+ highlight: '#1A3C75',
123
+ border: '#4A4A4A',
124
+ buttonPrimary: 'linear-gradient(130deg, #9355E7 0%, #2E4AA3 100%)',
125
+ buttonSecondary: 'linear-gradient(130deg, #595A78 0%, #44455F 100%)',
126
+ buttonDelete: '#3D0808',
127
+ infoPrimary: '#8E8EAC',
128
+ infoSecondary: '#333366',
129
+ backgroundLevel1: '#121219',
130
+ backgroundLevel2: '#323245',
131
+ backgroundLevel3: '#232331',
132
+ backgroundLevel4: '#1B1B27',
133
+ textPrimary: '#EAEAEA',
134
+ textSecondary: '#B5B5B5',
135
+ textTertiary: '#DFDFDF',
136
+ textReverse: '#000000',
137
+ textLink: '#71AEFF',
138
+ },
113
139
  };
114
140
  /**
115
141
  * @deprecated
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scality/core-ui",
3
- "version": "0.167.0",
3
+ "version": "0.169.0",
4
4
  "description": "Scality common React component library",
5
5
  "author": "Scality Engineering",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -22,7 +22,7 @@
22
22
  "test": "jest",
23
23
  "storybook": "storybook dev -p 3000",
24
24
  "build-storybook": "storybook build",
25
- "storybook:deploy": "storybook-to-ghpages"
25
+ "storybook:deploy": "npm run build-storybook && gh-pages -d storybook-static -u \"github-actions-bot <support+actions@github.com>\""
26
26
  },
27
27
  "keywords": [],
28
28
  "browserslist": [
@@ -67,6 +67,7 @@
67
67
  "eslint": "^8.15.0",
68
68
  "eslint-config-react-app": "^7.0.1",
69
69
  "eslint-plugin-storybook": "^0.10.1",
70
+ "gh-pages": "^6.3.0",
70
71
  "husky": "^3.0.5",
71
72
  "jest": "^30.0.5",
72
73
  "jest-canvas-mock": "^2.3.1",
@@ -84,7 +85,7 @@
84
85
  },
85
86
  "dependencies": {
86
87
  "@floating-ui/dom": "^1.6.3",
87
- "@floating-ui/react": "^0.26.28",
88
+ "@floating-ui/react": "^0.27.15",
88
89
  "@fortawesome/fontawesome-free": "^5.10.2",
89
90
  "@fortawesome/fontawesome-svg-core": "^1.2.35",
90
91
  "@fortawesome/free-regular-svg-icons": "^5.15.3",
@@ -96,7 +97,7 @@
96
97
  "polished": "3.4.1",
97
98
  "pretty-bytes": "^5.6.0",
98
99
  "react-dropzone": "^14.2.3",
99
- "react-hook-form": "^7.49.2",
100
+ "react-hook-form": "^7.62.0",
100
101
  "react-query": "^3.34.0",
101
102
  "react-router": "7.8.1",
102
103
  "react-router-dom": "7.8.1",
@@ -1,6 +1,6 @@
1
1
  import { render, screen, waitFor } from '@testing-library/react';
2
2
  import { getWrapper } from '../../testUtils';
3
- import { Barchart, CustomTick, formatDate } from './Barchart.component';
3
+ import { Barchart, CustomTick } from './Barchart.component';
4
4
  import { ChartLegendWrapper } from '../chartlegend/ChartLegendWrapper';
5
5
  import React from 'react';
6
6
 
@@ -60,7 +60,7 @@ describe('Barchart', () => {
60
60
  render(
61
61
  <Wrapper>
62
62
  <ChartLegendWrapper colorSet={testColorSet}>
63
- <Barchart type="category" bars={testBars} />
63
+ <Barchart type={{ type: 'category' }} bars={testBars} />
64
64
  </ChartLegendWrapper>
65
65
  </Wrapper>,
66
66
  );
@@ -98,7 +98,7 @@ describe('Barchart', () => {
98
98
  render(
99
99
  <Wrapper>
100
100
  <ChartLegendWrapper colorSet={testColorSet}>
101
- <Barchart type="category" bars={[]} isError />
101
+ <Barchart type={{ type: 'category' }} bars={[]} isError />
102
102
  </ChartLegendWrapper>
103
103
  </Wrapper>,
104
104
  );
@@ -111,7 +111,7 @@ describe('Barchart', () => {
111
111
  render(
112
112
  <Wrapper>
113
113
  <ChartLegendWrapper colorSet={testColorSet}>
114
- <Barchart type="category" bars={[]} isLoading />
114
+ <Barchart type={{ type: 'category' }} bars={[]} isLoading />
115
115
  </ChartLegendWrapper>
116
116
  </Wrapper>,
117
117
  );
@@ -122,7 +122,7 @@ describe('Barchart', () => {
122
122
  render(
123
123
  <Wrapper>
124
124
  <ChartLegendWrapper colorSet={testColorSet}>
125
- <Barchart type="category" bars={undefined} />
125
+ <Barchart type={{ type: 'category' }} bars={undefined} />
126
126
  </ChartLegendWrapper>
127
127
  </Wrapper>,
128
128
  );
@@ -316,7 +316,11 @@ describe('Barchart', () => {
316
316
  render(
317
317
  <Wrapper>
318
318
  <ChartLegendWrapper colorSet={{ ...testColorSet, Failed: 'red' }}>
319
- <Barchart type="category" bars={testStackedBars} stacked={true} />
319
+ <Barchart
320
+ type={{ type: 'category' }}
321
+ bars={testStackedBars}
322
+ stacked
323
+ />
320
324
  </ChartLegendWrapper>
321
325
  </Wrapper>,
322
326
  );
@@ -344,7 +348,7 @@ describe('Barchart', () => {
344
348
  <Wrapper>
345
349
  <ChartLegendWrapper colorSet={testColorSet}>
346
350
  <Barchart
347
- type="category"
351
+ type={{ type: 'category' }}
348
352
  bars={testBars}
349
353
  defaultSort={(pointA, pointB) => {
350
354
  const valueA = pointA.Success;
@@ -369,7 +373,7 @@ describe('Barchart', () => {
369
373
  <Wrapper>
370
374
  <ChartLegendWrapper colorSet={testColorSet}>
371
375
  <Barchart
372
- type="category"
376
+ type={{ type: 'category' }}
373
377
  bars={[]}
374
378
  title="Test Title"
375
379
  secondaryTitle="Test Secondary Title"
@@ -14,13 +14,14 @@ import styled, { useTheme } from 'styled-components';
14
14
  import { spacing, Stack, Wrap } from '../../spacing';
15
15
  import { chartColors, ChartColors, fontSize } from '../../style/theme';
16
16
  import { Box } from '../box/Box';
17
+ import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
17
18
  import { ConstrainedText } from '../constrainedtext/Constrainedtext.component';
19
+ import { FormattedDateTime } from '../date/FormattedDateTime';
18
20
  import { IconHelp } from '../iconhelper/IconHelper';
19
21
  import { Loader } from '../loader/Loader.component';
20
22
  import { Text } from '../text/Text.component';
21
- import { renderTooltipContent, UnitRange, useChartData } from './utils';
22
- import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
23
- import { FormattedDateTime } from '../date/FormattedDateTime';
23
+ import { ChartTooltip } from './ChartTooltip';
24
+ import { UnitRange, useChartData } from './utils';
24
25
 
25
26
  const CHART_CONSTANTS = {
26
27
  TICK_WIDTH_OFFSET: 5,
@@ -45,6 +46,11 @@ export type TimeType = {
45
46
  interval: number;
46
47
  };
47
48
  };
49
+
50
+ export type CategoryType = {
51
+ type: 'category';
52
+ gap?: number;
53
+ };
48
54
  export type Point = {
49
55
  key: string | number;
50
56
  values: { label: string; value: number }[];
@@ -70,7 +76,7 @@ export type BarchartSortFn<T extends BarchartBars> = (
70
76
  ) => 1 | -1 | 0;
71
77
 
72
78
  export type BarchartProps<T extends BarchartBars> = {
73
- type: 'category' | TimeType;
79
+ type: CategoryType | TimeType;
74
80
  bars?: T;
75
81
  tooltip?: BarchartTooltipFn<T>;
76
82
  defaultSort?: BarchartSortFn<T>;
@@ -260,7 +266,7 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
260
266
  const {
261
267
  height = CHART_CONSTANTS.DEFAULT_HEIGHT,
262
268
  bars,
263
- type = 'category',
269
+ type = { type: 'category' },
264
270
  unitRange,
265
271
  stacked,
266
272
  stackedBarSort = 'default',
@@ -314,9 +320,16 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
314
320
  <BarChart
315
321
  data={rechartsData}
316
322
  accessibilityLayer
317
- barSize={CHART_CONSTANTS.BAR_SIZE}
323
+ barSize={
324
+ type.type === 'category'
325
+ ? type.gap === 0
326
+ ? undefined
327
+ : CHART_CONSTANTS.BAR_SIZE
328
+ : CHART_CONSTANTS.BAR_SIZE
329
+ }
318
330
  height={height}
319
331
  margin={CHART_CONSTANTS.CHART_MARGIN}
332
+ barCategoryGap={type.type === 'category' ? type.gap : undefined}
320
333
  >
321
334
  <CartesianGrid
322
335
  vertical={false}
@@ -332,6 +345,7 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
332
345
  fill={chartColors[fill] || fill}
333
346
  minPointSize={stacked ? 0 : CHART_CONSTANTS.MIN_POINT_SIZE}
334
347
  stackId={stackId}
348
+ isAnimationActive={false}
335
349
  onMouseOver={() => setHoveredValue(dataKey)}
336
350
  onMouseLeave={() => setHoveredValue(undefined)}
337
351
  />
@@ -378,9 +392,15 @@ export const Barchart = <T extends BarchartBars>(props: BarchartProps<T>) => {
378
392
  />
379
393
 
380
394
  <Tooltip
381
- content={(props: TooltipContentProps<number, string>) =>
382
- renderTooltipContent(props, tooltip, hoveredValue)
383
- }
395
+ content={(props: TooltipContentProps<number, string>) => (
396
+ <ChartTooltip
397
+ type={type}
398
+ colorSet={colorSet}
399
+ tooltipProps={props}
400
+ hoveredValue={hoveredValue}
401
+ tooltip={tooltip}
402
+ />
403
+ )}
384
404
  cursor={false}
385
405
  />
386
406
  </BarChart>
@@ -0,0 +1,119 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { ChartTooltip } from './ChartTooltip';
4
+
5
+ const ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000;
6
+ const ONE_HOUR_IN_MILLISECONDS = 60 * 60 * 1000;
7
+ const SUCCESS_VALUE = 39;
8
+ const FAILED_VALUE = 13;
9
+ const testTooltipProps = {
10
+ payload: [
11
+ { name: 'Success', value: SUCCESS_VALUE },
12
+ { name: 'Failed', value: FAILED_VALUE },
13
+ ],
14
+ label: 'Test',
15
+ coordinate: { x: 10, y: 10 },
16
+ active: true,
17
+ accessibilityLayer: false,
18
+ };
19
+ const testTooltip = () => <div>Test Tooltip</div>;
20
+ const date = new Date('2024-07-01T00:00:00').getTime();
21
+
22
+ describe('ChartTooltip', () => {
23
+ const selectors = {
24
+ tooltip: () => screen.queryByText(/Test Tooltip/),
25
+ category: () => screen.queryByText(/Test/),
26
+ success: () => screen.queryByText(/Success/),
27
+ successValue: () => screen.queryByText(SUCCESS_VALUE),
28
+ failed: () => screen.queryByText(/Failed/),
29
+ failedValue: () => screen.queryByText(FAILED_VALUE),
30
+ date: () => screen.queryByText(/Monday, 1 July 2024/),
31
+ time: () => screen.queryByText(/00:00/),
32
+ };
33
+ it('should render the ChartTooltip component', () => {
34
+ render(
35
+ <ChartTooltip
36
+ type={{ type: 'category' }}
37
+ tooltipProps={testTooltipProps}
38
+ hoveredValue="Success"
39
+ tooltip={undefined}
40
+ />,
41
+ );
42
+ expect(selectors.category()).toBeInTheDocument();
43
+ expect(selectors.success()).toBeInTheDocument();
44
+ expect(selectors.successValue()).toBeInTheDocument();
45
+ expect(selectors.failed()).toBeInTheDocument();
46
+ expect(selectors.failedValue()).toBeInTheDocument();
47
+ });
48
+ it('should render tooltip when tooltip is provided', () => {
49
+ render(
50
+ <ChartTooltip
51
+ type={{ type: 'category' }}
52
+ tooltipProps={testTooltipProps}
53
+ hoveredValue="Success"
54
+ tooltip={testTooltip}
55
+ />,
56
+ );
57
+ expect(selectors.tooltip()).toBeInTheDocument();
58
+ });
59
+ it('should not render tooltip when tooltipProps is not active', () => {
60
+ render(
61
+ <ChartTooltip
62
+ type={{ type: 'category' }}
63
+ tooltipProps={{ ...testTooltipProps, active: false }}
64
+ hoveredValue="Success"
65
+ tooltip={testTooltip}
66
+ />,
67
+ );
68
+ expect(selectors.tooltip()).not.toBeInTheDocument();
69
+ });
70
+ it('should render time tooltip when type is time', () => {
71
+ // timestamp for Mon Jul 01 2024 00:00:00 GMT+0000 (Coordinated Universal Time)
72
+ const label = date;
73
+ render(
74
+ <ChartTooltip
75
+ type={{
76
+ type: 'time',
77
+ timeRange: {
78
+ startDate: new Date(),
79
+ endDate: new Date(),
80
+ interval: ONE_DAY_IN_MILLISECONDS,
81
+ },
82
+ }}
83
+ tooltipProps={{ ...testTooltipProps, label }}
84
+ hoveredValue="Success"
85
+ />,
86
+ );
87
+
88
+ expect(selectors.success()).toBeInTheDocument();
89
+ expect(selectors.successValue()).toBeInTheDocument();
90
+ expect(selectors.failed()).toBeInTheDocument();
91
+ expect(selectors.failedValue()).toBeInTheDocument();
92
+
93
+ expect(selectors.date()).toBeInTheDocument();
94
+ expect(selectors.time()).not.toBeInTheDocument();
95
+ });
96
+ it('should render time tooltip when type is time and interval is one hour', () => {
97
+ const label = date;
98
+ render(
99
+ <ChartTooltip
100
+ type={{
101
+ type: 'time',
102
+ timeRange: {
103
+ startDate: new Date(),
104
+ endDate: new Date(),
105
+ interval: ONE_HOUR_IN_MILLISECONDS,
106
+ },
107
+ }}
108
+ tooltipProps={{ ...testTooltipProps, label }}
109
+ hoveredValue="Success"
110
+ />,
111
+ );
112
+ expect(selectors.success()).toBeInTheDocument();
113
+ expect(selectors.successValue()).toBeInTheDocument();
114
+ expect(selectors.failed()).toBeInTheDocument();
115
+ expect(selectors.failedValue()).toBeInTheDocument();
116
+ expect(selectors.date()).toBeInTheDocument();
117
+ expect(selectors.time()).toBeInTheDocument();
118
+ });
119
+ });