@scality/core-ui 0.168.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.
- package/.github/workflows/github-pages.yml +5 -3
- package/.storybook/preview.js +1 -0
- package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
- package/dist/components/barchartv2/Barchart.component.js +6 -5
- package/dist/components/barchartv2/ChartTooltip.d.ts +9 -13
- package/dist/components/barchartv2/ChartTooltip.d.ts.map +1 -1
- package/dist/components/barchartv2/ChartTooltip.js +14 -4
- package/dist/components/barchartv2/utils.d.ts +9 -2
- package/dist/components/barchartv2/utils.d.ts.map +1 -1
- package/dist/components/barchartv2/utils.js +12 -16
- package/dist/components/buttonv2/Buttonv2.component.d.ts.map +1 -1
- package/dist/components/buttonv2/Buttonv2.component.js +27 -6
- package/dist/components/date/FormattedDateTime.d.ts +15 -1
- package/dist/components/date/FormattedDateTime.d.ts.map +1 -1
- package/dist/components/date/FormattedDateTime.js +25 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
- package/dist/components/linetimeseriechart/linetimeseriechart.component.js +30 -32
- package/dist/components/linetimeseriechart/utils.d.ts +16 -0
- package/dist/components/linetimeseriechart/utils.d.ts.map +1 -0
- package/dist/components/linetimeseriechart/utils.js +28 -0
- package/dist/style/theme.d.ts +2 -2
- package/dist/style/theme.d.ts.map +1 -1
- package/dist/style/theme.js +26 -0
- package/package.json +5 -4
- package/src/lib/components/barchartv2/Barchart.component.test.tsx +1 -1
- package/src/lib/components/barchartv2/Barchart.component.tsx +14 -6
- package/src/lib/components/barchartv2/ChartTooltip.test.tsx +119 -0
- package/src/lib/components/barchartv2/ChartTooltip.tsx +49 -19
- package/src/lib/components/barchartv2/utils.test.ts +29 -44
- package/src/lib/components/barchartv2/utils.ts +22 -29
- package/src/lib/components/buttonv2/Buttonv2.component.tsx +27 -6
- package/src/lib/components/date/FormattedDateTime.tsx +30 -1
- package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +61 -57
- package/src/lib/components/linetimeseriechart/linetimeseriechart.test.tsx +58 -55
- package/src/lib/components/linetimeseriechart/utils.test.ts +87 -0
- package/src/lib/components/linetimeseriechart/utils.ts +43 -0
- package/src/lib/style/theme.ts +26 -0
- package/stories/BarChart/barchart.stories.tsx +1 -1
- package/stories/color.mdx +12 -0
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
YAxis,
|
|
9
9
|
CartesianGrid,
|
|
10
10
|
} from 'recharts';
|
|
11
|
+
import type { Payload } from 'recharts/types/component/DefaultTooltipContent';
|
|
11
12
|
import { useCallback, useMemo, useRef } from 'react';
|
|
12
13
|
import { useTheme } from 'styled-components';
|
|
13
14
|
import { addMissingDataPoint } from '../linetemporalchart/ChartUtil';
|
|
@@ -20,11 +21,15 @@ import { spacing } from '../../spacing';
|
|
|
20
21
|
import { getUnitLabel } from '../linetemporalchart/ChartUtil';
|
|
21
22
|
import { Icon } from '../icon/Icon.component';
|
|
22
23
|
import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
import { FormattedDateTime } from '../date/FormattedDateTime';
|
|
25
|
+
import { Box } from '../box/Box';
|
|
26
|
+
import { formatXAxisLabel } from './utils';
|
|
27
|
+
|
|
28
|
+
type TooltipPayload = Payload<number, string> & {
|
|
29
|
+
value: number;
|
|
30
|
+
name: string;
|
|
31
|
+
color: string;
|
|
32
|
+
};
|
|
28
33
|
|
|
29
34
|
const LineTemporalChartWrapper = styled.div`
|
|
30
35
|
display: flex;
|
|
@@ -61,6 +66,8 @@ const TooltipValue = styled.div`
|
|
|
61
66
|
color: ${(props) => props.theme.textSecondary};
|
|
62
67
|
display: flex;
|
|
63
68
|
align-items: flex-start;
|
|
69
|
+
justify-content: space-between;
|
|
70
|
+
width: 100%;
|
|
64
71
|
`;
|
|
65
72
|
|
|
66
73
|
const TooltipLegend = styled.div<{ color: string }>`
|
|
@@ -72,21 +79,23 @@ const TooltipLegend = styled.div<{ color: string }>`
|
|
|
72
79
|
margin-top: 8px;
|
|
73
80
|
`;
|
|
74
81
|
|
|
75
|
-
const
|
|
82
|
+
const TooltipLeftGroup = styled.div`
|
|
76
83
|
display: flex;
|
|
84
|
+
align-items: flex-start;
|
|
77
85
|
min-width: 0;
|
|
78
86
|
flex: 1;
|
|
79
87
|
`;
|
|
80
88
|
|
|
81
89
|
const TooltipName = styled.div`
|
|
82
|
-
margin-right: 4px;
|
|
83
90
|
word-wrap: break-word;
|
|
84
91
|
word-break: break-word;
|
|
85
|
-
|
|
92
|
+
flex: 1;
|
|
86
93
|
`;
|
|
87
94
|
|
|
88
95
|
const TooltipInstanceValue = styled.div`
|
|
89
|
-
|
|
96
|
+
margin-left: 16px;
|
|
97
|
+
flex-shrink: 0;
|
|
98
|
+
text-align: right;
|
|
90
99
|
`;
|
|
91
100
|
|
|
92
101
|
export type Serie = {
|
|
@@ -148,12 +157,7 @@ const CustomTooltip = ({
|
|
|
148
157
|
timeFormat,
|
|
149
158
|
}: {
|
|
150
159
|
active?: boolean;
|
|
151
|
-
payload?: Array<
|
|
152
|
-
value: number;
|
|
153
|
-
name: string;
|
|
154
|
-
color: string;
|
|
155
|
-
dataKey: string;
|
|
156
|
-
}>;
|
|
160
|
+
payload?: Array<TooltipPayload>;
|
|
157
161
|
label?: string;
|
|
158
162
|
unitLabel?: string;
|
|
159
163
|
timeFormat?: 'date-time' | 'date';
|
|
@@ -162,8 +166,8 @@ const CustomTooltip = ({
|
|
|
162
166
|
// We can't use the default itemSorter method because it's a custom tooltip.
|
|
163
167
|
// Sort the payload here instead
|
|
164
168
|
const sortedPayload = [...payload].sort((a, b) => {
|
|
165
|
-
const aValue =
|
|
166
|
-
const bValue =
|
|
169
|
+
const aValue = a.value;
|
|
170
|
+
const bValue = b.value;
|
|
167
171
|
|
|
168
172
|
if (aValue >= 0 && bValue >= 0) {
|
|
169
173
|
return bValue - aValue; // Higher positive values first
|
|
@@ -181,22 +185,22 @@ const CustomTooltip = ({
|
|
|
181
185
|
format={
|
|
182
186
|
timeFormat === 'date-time'
|
|
183
187
|
? 'day-month-abbreviated-hour-minute-second'
|
|
184
|
-
: 'long-date'
|
|
188
|
+
: 'long-date-without-weekday'
|
|
185
189
|
}
|
|
186
190
|
value={new Date(label)}
|
|
187
191
|
/>
|
|
188
192
|
</TooltipTime>
|
|
189
193
|
{sortedPayload.map((entry, index) => (
|
|
190
194
|
<TooltipValue key={index}>
|
|
191
|
-
<
|
|
192
|
-
|
|
195
|
+
<TooltipLeftGroup>
|
|
196
|
+
<TooltipLegend color={entry.color} />
|
|
193
197
|
<TooltipName>{entry.name}</TooltipName>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
</
|
|
198
|
+
</TooltipLeftGroup>
|
|
199
|
+
<TooltipInstanceValue>
|
|
200
|
+
{!Number.isFinite(entry.value)
|
|
201
|
+
? '-'
|
|
202
|
+
: `${entry.value.toFixed(2)} ${unitLabel}`}
|
|
203
|
+
</TooltipInstanceValue>
|
|
200
204
|
</TooltipValue>
|
|
201
205
|
))}
|
|
202
206
|
</TooltipContainer>
|
|
@@ -305,7 +309,7 @@ export function LineTimeSerieChart({
|
|
|
305
309
|
);
|
|
306
310
|
}, [series, startingTimeStamp, duration, interval, yAxisType]);
|
|
307
311
|
|
|
308
|
-
// Calculate
|
|
312
|
+
// Calculate evenly spaced ticks that avoid the very beginning and end
|
|
309
313
|
const xAxisTicks = useMemo(() => {
|
|
310
314
|
if (!chartData || chartData.length === 0) return [];
|
|
311
315
|
|
|
@@ -313,20 +317,23 @@ export function LineTimeSerieChart({
|
|
|
313
317
|
const minTimestamp = Math.min(...timestamps);
|
|
314
318
|
const maxTimestamp = Math.max(...timestamps);
|
|
315
319
|
|
|
316
|
-
// Calculate 5 perfectly evenly spaced ticks
|
|
317
320
|
const timeRange = maxTimestamp - minTimestamp;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
321
|
+
// Add padding to avoid labels at the very edges (10% padding on each side)
|
|
322
|
+
const padding = timeRange * 0.1;
|
|
323
|
+
const paddedStart = minTimestamp + padding;
|
|
324
|
+
const paddedEnd = maxTimestamp - padding;
|
|
325
|
+
const paddedRange = paddedEnd - paddedStart;
|
|
326
|
+
|
|
327
|
+
// Create 5 evenly spaced ticks within the padded range
|
|
328
|
+
const numTicks = 5;
|
|
329
|
+
const tickInterval = paddedRange / (numTicks - 1);
|
|
330
|
+
|
|
331
|
+
const evenlySpacedTicks = Array.from(
|
|
332
|
+
{ length: numTicks },
|
|
333
|
+
(_, index) => paddedStart + index * tickInterval,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
return evenlySpacedTicks;
|
|
330
337
|
}, [chartData]);
|
|
331
338
|
|
|
332
339
|
// 3. Transform the data base on the valuebase
|
|
@@ -407,16 +414,9 @@ export function LineTimeSerieChart({
|
|
|
407
414
|
}, [series, getColor]);
|
|
408
415
|
|
|
409
416
|
// Format time for display the tick in the x axis
|
|
410
|
-
const
|
|
411
|
-
(timestamp: number) =>
|
|
412
|
-
|
|
413
|
-
return timeFormat === 'date-time'
|
|
414
|
-
? DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '')
|
|
415
|
-
: timeFormat === 'date'
|
|
416
|
-
? YEAR_MONTH_DAY_FORMATTER.format(date)
|
|
417
|
-
: '';
|
|
418
|
-
},
|
|
419
|
-
[timeFormat],
|
|
417
|
+
const formatXAxisLabelCallback = useCallback(
|
|
418
|
+
(timestamp: number) => formatXAxisLabel(timestamp, timeFormat, chartData),
|
|
419
|
+
[timeFormat, chartData],
|
|
420
420
|
);
|
|
421
421
|
|
|
422
422
|
return (
|
|
@@ -426,12 +426,14 @@ export function LineTimeSerieChart({
|
|
|
426
426
|
{title} {unitLabel && `(${unitLabel})`}
|
|
427
427
|
</ChartTitleText>
|
|
428
428
|
{helpText && (
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
429
|
+
<Box ml={spacing.r4}>
|
|
430
|
+
<TooltipComponent
|
|
431
|
+
placement={'right'}
|
|
432
|
+
overlay={<SmallerText>{helpText}</SmallerText>}
|
|
433
|
+
>
|
|
434
|
+
<Icon name="Info" color={theme.buttonSecondary} />
|
|
435
|
+
</TooltipComponent>
|
|
436
|
+
</Box>
|
|
435
437
|
)}
|
|
436
438
|
{isLoading && <Loader />}
|
|
437
439
|
</ChartHeader>
|
|
@@ -456,7 +458,7 @@ export function LineTimeSerieChart({
|
|
|
456
458
|
type="number"
|
|
457
459
|
domain={['dataMin', 'dataMax']}
|
|
458
460
|
ticks={xAxisTicks}
|
|
459
|
-
tickFormatter={
|
|
461
|
+
tickFormatter={formatXAxisLabelCallback}
|
|
460
462
|
tickCount={5}
|
|
461
463
|
tick={{
|
|
462
464
|
fill: theme.textSecondary,
|
|
@@ -490,6 +492,8 @@ export function LineTimeSerieChart({
|
|
|
490
492
|
fontSize: fontSize.smaller,
|
|
491
493
|
}}
|
|
492
494
|
tickFormatter={(value) => Math.round(value).toString()}
|
|
495
|
+
tickCount={5}
|
|
496
|
+
interval={'preserveStartEnd'}
|
|
493
497
|
/>
|
|
494
498
|
<Tooltip
|
|
495
499
|
content={
|
|
@@ -1,68 +1,71 @@
|
|
|
1
|
-
import { render } from
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import {
|
|
4
|
+
LineChartProps,
|
|
5
|
+
LineTimeSerieChart,
|
|
6
|
+
} from './linetimeseriechart.component';
|
|
7
|
+
import { ChartLegendWrapper } from '../chartlegend/ChartLegendWrapper';
|
|
8
|
+
import { ThemeProvider } from 'styled-components';
|
|
9
|
+
import { coreUIAvailableThemes } from '../../style/theme';
|
|
6
10
|
|
|
7
11
|
const TestSeries = [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
12
|
+
{
|
|
13
|
+
resource: 'Series 1',
|
|
14
|
+
getTooltipLabel: () => `Series 1`,
|
|
15
|
+
data: [
|
|
16
|
+
[1622505600000, 10],
|
|
17
|
+
[1622509200000, 20],
|
|
18
|
+
[1622512800000, 30],
|
|
19
|
+
] as [number, number][],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
resource: 'Series 2',
|
|
23
|
+
getTooltipLabel: () => `Series 2`,
|
|
24
|
+
data: [
|
|
25
|
+
[1622505600000, 15],
|
|
26
|
+
[1622509200000, 25],
|
|
27
|
+
[1622512800000, 35],
|
|
28
|
+
] as [number, number][],
|
|
29
|
+
},
|
|
27
30
|
];
|
|
28
31
|
|
|
29
32
|
const ColorSet = {
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
'Series 1': '#FF0000',
|
|
34
|
+
'Series 2': '#00FF00',
|
|
32
35
|
};
|
|
33
36
|
|
|
34
37
|
const renderLineTimeSerieChart = (props: Partial<LineChartProps> = {}) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
return render(
|
|
39
|
+
<ThemeProvider theme={coreUIAvailableThemes.artescaLight}>
|
|
40
|
+
<ChartLegendWrapper colorSet={ColorSet}>
|
|
41
|
+
<LineTimeSerieChart
|
|
42
|
+
{...({
|
|
43
|
+
title: 'Test Chart',
|
|
44
|
+
yAxisType: 'default',
|
|
45
|
+
series: TestSeries,
|
|
46
|
+
height: 400,
|
|
47
|
+
startingTimeStamp: TestSeries[0].data[0][0],
|
|
48
|
+
interval: TestSeries[0].data[1][0] - TestSeries[0].data[0][0],
|
|
49
|
+
duration:
|
|
50
|
+
TestSeries[0].data[TestSeries[0].data.length - 1][0] -
|
|
51
|
+
TestSeries[0].data[0][0],
|
|
52
|
+
unitRange: [{ label: 'units', value: 1 }],
|
|
53
|
+
...props,
|
|
54
|
+
} as LineChartProps)}
|
|
55
|
+
/>
|
|
56
|
+
</ChartLegendWrapper>
|
|
57
|
+
</ThemeProvider>,
|
|
58
|
+
);
|
|
56
59
|
};
|
|
57
60
|
|
|
58
61
|
describe('LineTimeSerieChart', () => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
it('should render when with basic parameters', async () => {
|
|
63
|
+
const { container } = renderLineTimeSerieChart();
|
|
64
|
+
expect(container).toBeInTheDocument();
|
|
65
|
+
});
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
it('should render when no unitRange is provided', async () => {
|
|
68
|
+
const { container } = renderLineTimeSerieChart({ unitRange: undefined });
|
|
69
|
+
expect(container).toBeInTheDocument();
|
|
70
|
+
});
|
|
68
71
|
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { formatXAxisLabel } from './utils';
|
|
2
|
+
|
|
3
|
+
const createChartData = (startDate: Date, endDate: Date) => [
|
|
4
|
+
{ timestamp: startDate.getTime() },
|
|
5
|
+
{ timestamp: endDate.getTime() },
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
describe('formatXAxisLabel', () => {
|
|
9
|
+
const mockTimestamp = new Date('2025-09-15T14:30:00Z').getTime();
|
|
10
|
+
|
|
11
|
+
describe('date-time format', () => {
|
|
12
|
+
it('should format timestamp with day-month-abbreviated-hour-minute format', () => {
|
|
13
|
+
const chartData = createChartData(
|
|
14
|
+
new Date('2022-01-01'),
|
|
15
|
+
new Date('2022-01-02'),
|
|
16
|
+
);
|
|
17
|
+
const result = formatXAxisLabel(mockTimestamp, 'date-time', chartData);
|
|
18
|
+
expect(result).toBe('15 Sept 14:30');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('date format', () => {
|
|
23
|
+
it('should use YYYY-MM-DD format for time ranges greater than 1 year', () => {
|
|
24
|
+
const startDate = new Date('2022-01-01');
|
|
25
|
+
const endDate = new Date('2024-01-01'); // More than 1 year
|
|
26
|
+
const chartData = createChartData(startDate, endDate);
|
|
27
|
+
|
|
28
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
|
|
29
|
+
expect(result).toBe('2025-09-15');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should use MM-DD format for time ranges less than 1 year', () => {
|
|
33
|
+
const startDate = new Date('2023-09-01');
|
|
34
|
+
const endDate = new Date('2023-12-01'); // Less than 1 year
|
|
35
|
+
const chartData = createChartData(startDate, endDate);
|
|
36
|
+
|
|
37
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
|
|
38
|
+
expect(result).toBe('09-15');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should use YYYY-MM-DD format when chartData is empty', () => {
|
|
42
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', []);
|
|
43
|
+
expect(result).toBe('2025-09-15');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should handle edge case of exactly 1 year time range', () => {
|
|
47
|
+
const startDate = new Date('2022-09-15');
|
|
48
|
+
const endDate = new Date('2023-09-15'); // Exactly 1 year
|
|
49
|
+
const chartData = createChartData(startDate, endDate);
|
|
50
|
+
|
|
51
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
|
|
52
|
+
expect(result).toBe('09-15');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should handle leap year calculation correctly', () => {
|
|
56
|
+
const startDate = new Date('2023-01-01');
|
|
57
|
+
const endDate = new Date('2024-01-02'); // Just over 1 year including leap year
|
|
58
|
+
const chartData = createChartData(startDate, endDate);
|
|
59
|
+
|
|
60
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
|
|
61
|
+
|
|
62
|
+
expect(result).toBe('2025-09-15');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('chartData with various scenarios', () => {
|
|
67
|
+
it('should handle chartData with single data point', () => {
|
|
68
|
+
const chartData = [{ timestamp: mockTimestamp }];
|
|
69
|
+
|
|
70
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
|
|
71
|
+
|
|
72
|
+
expect(result).toBe('09-15');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should handle chartData with mixed timestamp values', () => {
|
|
76
|
+
const chartData = [
|
|
77
|
+
{ timestamp: new Date('2023-01-01').getTime() },
|
|
78
|
+
{ timestamp: new Date('2023-06-01').getTime() },
|
|
79
|
+
{ timestamp: new Date('2023-12-01').getTime() },
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
|
|
83
|
+
|
|
84
|
+
expect(result).toBe('09-15');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DAY_MONTH_ABBREVIATED_HOUR_MINUTE,
|
|
3
|
+
YEAR_MONTH_DAY_FORMATTER,
|
|
4
|
+
MONTH_DAY_FORMATTER,
|
|
5
|
+
} from '../date/FormattedDateTime';
|
|
6
|
+
|
|
7
|
+
export const ONE_YEAR_MILLISECONDS = 366 * 24 * 60 * 60 * 1000;
|
|
8
|
+
|
|
9
|
+
export type ChartDataPoint = {
|
|
10
|
+
timestamp: number;
|
|
11
|
+
} & Record<string, number | null>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Formats timestamp for X-axis labels based on time format and data range:
|
|
15
|
+
* For 'date-time' format, return day-month-abbreviated-hour-minute format
|
|
16
|
+
* For 'date' format, return YYYY-MM-DD format if time range is greater than 1 year, otherwise return MM-DD format
|
|
17
|
+
*
|
|
18
|
+
* @param timestamp - The timestamp to format in milliseconds
|
|
19
|
+
* @param timeFormat - The format type ('date-time' or 'date')
|
|
20
|
+
* @param chartData - The chart data to determine time range for optimal formatting
|
|
21
|
+
* @returns Formatted string for display on X-axis
|
|
22
|
+
*/
|
|
23
|
+
export const formatXAxisLabel = (
|
|
24
|
+
timestamp: number,
|
|
25
|
+
timeFormat: 'date-time' | 'date' = 'date-time',
|
|
26
|
+
chartData: ChartDataPoint[] = [],
|
|
27
|
+
): string => {
|
|
28
|
+
const date = new Date(timestamp);
|
|
29
|
+
if (!chartData.length) {
|
|
30
|
+
return YEAR_MONTH_DAY_FORMATTER.format(date);
|
|
31
|
+
}
|
|
32
|
+
if (timeFormat === 'date-time') {
|
|
33
|
+
return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
|
|
34
|
+
}
|
|
35
|
+
const timestamps = chartData.map((d) => d.timestamp);
|
|
36
|
+
const minTimestamp = Math.min(...timestamps);
|
|
37
|
+
const maxTimestamp = Math.max(...timestamps);
|
|
38
|
+
const timeRangeMilliseconds = maxTimestamp - minTimestamp;
|
|
39
|
+
|
|
40
|
+
return timeRangeMilliseconds >= ONE_YEAR_MILLISECONDS
|
|
41
|
+
? YEAR_MONTH_DAY_FORMATTER.format(date)
|
|
42
|
+
: MONTH_DAY_FORMATTER.format(date);
|
|
43
|
+
};
|
package/src/lib/style/theme.ts
CHANGED
|
@@ -60,6 +60,7 @@ export const coreUIAvailableThemesNames = [
|
|
|
60
60
|
'darkRebrand',
|
|
61
61
|
'artescaLight',
|
|
62
62
|
'ring9dark',
|
|
63
|
+
'G-Dark'
|
|
63
64
|
] as const;
|
|
64
65
|
export type CoreUIThemeName = (typeof coreUIAvailableThemesNames)[number];
|
|
65
66
|
|
|
@@ -139,6 +140,31 @@ export const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme> = {
|
|
|
139
140
|
textReverse: '#000000',
|
|
140
141
|
textLink: '#71AEFF',
|
|
141
142
|
},
|
|
143
|
+
'G-Dark': {
|
|
144
|
+
statusHealthy: '#0AADA6',
|
|
145
|
+
statusHealthyRGB: '10,173,166',
|
|
146
|
+
statusWarning: '#F8F32B',
|
|
147
|
+
statusWarningRGB: '248,243,43',
|
|
148
|
+
statusCritical: '#E84855',
|
|
149
|
+
statusCriticalRGB: '232,72,85',
|
|
150
|
+
selectedActive: '#037AFF',
|
|
151
|
+
highlight: '#1A3C75',
|
|
152
|
+
border: '#4A4A4A',
|
|
153
|
+
buttonPrimary: 'linear-gradient(130deg, #9355E7 0%, #2E4AA3 100%)',
|
|
154
|
+
buttonSecondary: 'linear-gradient(130deg, #595A78 0%, #44455F 100%)',
|
|
155
|
+
buttonDelete: '#3D0808',
|
|
156
|
+
infoPrimary: '#8E8EAC',
|
|
157
|
+
infoSecondary: '#333366',
|
|
158
|
+
backgroundLevel1: '#121219',
|
|
159
|
+
backgroundLevel2: '#323245',
|
|
160
|
+
backgroundLevel3: '#232331',
|
|
161
|
+
backgroundLevel4: '#1B1B27',
|
|
162
|
+
textPrimary: '#EAEAEA',
|
|
163
|
+
textSecondary: '#B5B5B5',
|
|
164
|
+
textTertiary: '#DFDFDF',
|
|
165
|
+
textReverse: '#000000',
|
|
166
|
+
textLink: '#71AEFF',
|
|
167
|
+
},
|
|
142
168
|
};
|
|
143
169
|
|
|
144
170
|
/**
|
|
@@ -937,7 +937,6 @@ export const Histogram: Story = {
|
|
|
937
937
|
<ChartLegendWrapper
|
|
938
938
|
colorSet={{
|
|
939
939
|
Success: theme.statusHealthy,
|
|
940
|
-
Failed: theme.statusCritical,
|
|
941
940
|
}}
|
|
942
941
|
>
|
|
943
942
|
<Barchart
|
|
@@ -945,6 +944,7 @@ export const Histogram: Story = {
|
|
|
945
944
|
bars={histogramData}
|
|
946
945
|
title="Histogram"
|
|
947
946
|
/>
|
|
947
|
+
<ChartLegend shape="rectangle" />
|
|
948
948
|
</ChartLegendWrapper>
|
|
949
949
|
</div>
|
|
950
950
|
);
|
package/stories/color.mdx
CHANGED
|
@@ -41,3 +41,15 @@ import { coreUIAvailableThemes } from '../src/lib/style/theme';
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
</ColorPalette>
|
|
44
|
+
|
|
45
|
+
## G-Dark
|
|
46
|
+
|
|
47
|
+
<ColorPalette>
|
|
48
|
+
{
|
|
49
|
+
Object.entries(coreUIAvailableThemes['G-Dark']).map(([key, value]) => {
|
|
50
|
+
if (!/RGB/.test(key)) return <ColorItem title={key} colors={[value]}/>;
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
</ColorPalette>
|