@scality/core-ui 0.176.0 → 0.178.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/dist/components/barchartv2/Barchart.component.d.ts +2 -2
- package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
- package/dist/components/barchartv2/Barchart.component.js +16 -10
- package/dist/components/barchartv2/BarchartTooltip.d.ts +3 -2
- package/dist/components/barchartv2/BarchartTooltip.d.ts.map +1 -1
- package/dist/components/barchartv2/BarchartTooltip.js +6 -8
- package/dist/components/barchartv2/utils.d.ts +6 -1
- package/dist/components/barchartv2/utils.d.ts.map +1 -1
- package/dist/components/barchartv2/utils.js +34 -8
- package/dist/components/charttooltip/ChartTooltip.d.ts +23 -0
- package/dist/components/charttooltip/ChartTooltip.d.ts.map +1 -1
- package/dist/components/charttooltip/ChartTooltip.js +85 -3
- package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts.map +1 -1
- package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.js +27 -1
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts +1 -1
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts.map +1 -1
- package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.js +19 -59
- package/dist/components/globalhealthbar/components/HealthBarXAxis.js +1 -1
- package/dist/components/globalhealthbar/useHealthBarData.d.ts +1 -0
- package/dist/components/globalhealthbar/useHealthBarData.d.ts.map +1 -1
- package/dist/components/globalhealthbar/useHealthBarData.js +1 -0
- package/dist/components/globalhealthbar/useHealthBarData.spec.js +2 -0
- package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
- package/dist/components/linetimeseriechart/linetimeseriechart.component.js +43 -47
- package/dist/components/linetimeseriechart/utils.js +2 -2
- package/dist/style/theme.js +1 -1
- package/package.json +1 -1
- package/src/lib/components/barchartv2/Barchart.component.tsx +25 -16
- package/src/lib/components/barchartv2/BarchartTooltip.test.tsx +30 -0
- package/src/lib/components/barchartv2/BarchartTooltip.tsx +21 -8
- package/src/lib/components/barchartv2/utils.test.ts +72 -17
- package/src/lib/components/barchartv2/utils.ts +39 -7
- package/src/lib/components/charttooltip/ChartTooltip.tsx +136 -3
- package/src/lib/components/globalhealthbar/GlobalHealthBarRecharts.component.tsx +56 -11
- package/src/lib/components/globalhealthbar/components/GlobalHealthBarTooltip.tsx +75 -117
- package/src/lib/components/globalhealthbar/components/HealthBarXAxis.tsx +1 -1
- package/src/lib/components/globalhealthbar/useHealthBarData.spec.tsx +2 -0
- package/src/lib/components/globalhealthbar/useHealthBarData.ts +2 -0
- package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +86 -82
- package/src/lib/components/linetimeseriechart/utils.test.ts +3 -3
- package/src/lib/components/linetimeseriechart/utils.ts +2 -2
- package/src/lib/style/theme.ts +1 -1
- package/stories/BarChart/barchart.stories.tsx +23 -8
|
@@ -41,6 +41,7 @@ export type BarchartSortFn<T extends BarchartBars> = (pointA: Record<T[number]['
|
|
|
41
41
|
}) => 1 | -1 | 0;
|
|
42
42
|
export type BarchartProps<T extends BarchartBars> = {
|
|
43
43
|
type: CategoryType | TimeType;
|
|
44
|
+
title: string;
|
|
44
45
|
bars?: T;
|
|
45
46
|
tooltip?: BarchartTooltipFn<T>;
|
|
46
47
|
defaultSort?: BarchartSortFn<T>;
|
|
@@ -54,7 +55,6 @@ export type BarchartProps<T extends BarchartBars> = {
|
|
|
54
55
|
* @default 'default'
|
|
55
56
|
*/
|
|
56
57
|
stackedBarSort?: 'default' | 'legend';
|
|
57
|
-
title?: string;
|
|
58
58
|
secondaryTitle?: string;
|
|
59
59
|
rightTitle?: React.ReactNode;
|
|
60
60
|
height?: number;
|
|
@@ -73,7 +73,7 @@ interface CustomTickProps {
|
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
75
|
* Get the format of the date based on the duration
|
|
76
|
-
* @param duration - Duration in
|
|
76
|
+
* @param duration - Duration in seconds
|
|
77
77
|
* @returns Formatted string
|
|
78
78
|
*/
|
|
79
79
|
export declare const formatDate: (duration: number) => "time" | "day-month-abbreviated" | "chart-long-term-date";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Barchart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchartv2/Barchart.component.tsx"],"names":[],"mappings":"AAsBA,OAAO,
|
|
1
|
+
{"version":3,"file":"Barchart.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchartv2/Barchart.component.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useState, useRef } from 'react';
|
|
3
3
|
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
|
|
4
4
|
import styled, { useTheme } from 'styled-components';
|
|
5
5
|
import { spacing, Stack, Wrap } from '../../spacing';
|
|
@@ -12,7 +12,7 @@ import { IconHelp } from '../iconhelper/IconHelper';
|
|
|
12
12
|
import { Loader } from '../loader/Loader.component';
|
|
13
13
|
import { Text } from '../text/Text.component';
|
|
14
14
|
import { BarchartTooltip } from './BarchartTooltip';
|
|
15
|
-
import { useChartData } from './utils';
|
|
15
|
+
import { getTicks, useChartData } from './utils';
|
|
16
16
|
const CHART_CONSTANTS = {
|
|
17
17
|
TICK_WIDTH_OFFSET: 4,
|
|
18
18
|
BAR_SIZE: 12,
|
|
@@ -25,17 +25,18 @@ const CHART_CONSTANTS = {
|
|
|
25
25
|
bottom: 0,
|
|
26
26
|
},
|
|
27
27
|
};
|
|
28
|
+
const maxWidthTooltip = { maxWidth: '20rem' };
|
|
28
29
|
/* ---------------------------------- COMPONENTS ---------------------------------- */
|
|
29
30
|
/**
|
|
30
31
|
* Get the format of the date based on the duration
|
|
31
|
-
* @param duration - Duration in
|
|
32
|
+
* @param duration - Duration in seconds
|
|
32
33
|
* @returns Formatted string
|
|
33
34
|
*/
|
|
34
35
|
export const formatDate = (duration) => {
|
|
35
|
-
if (duration <= 24 * 60 * 60
|
|
36
|
+
if (duration <= 24 * 60 * 60) {
|
|
36
37
|
return 'time';
|
|
37
38
|
}
|
|
38
|
-
else if (duration <= 7 * 24 * 60 * 60
|
|
39
|
+
else if (duration <= 7 * 24 * 60 * 60) {
|
|
39
40
|
return 'day-month-abbreviated';
|
|
40
41
|
}
|
|
41
42
|
else {
|
|
@@ -47,7 +48,9 @@ export const CustomTick = ({ x, y, payload, visibleTicksCount, width, type, }) =
|
|
|
47
48
|
const tickWidth = width / visibleTicksCount - CHART_CONSTANTS.TICK_WIDTH_OFFSET;
|
|
48
49
|
const centerX = x - tickWidth / 2;
|
|
49
50
|
const duration = type.type === 'time'
|
|
50
|
-
? type.timeRange.endDate.getTime() -
|
|
51
|
+
? (type.timeRange.endDate.getTime() -
|
|
52
|
+
type.timeRange.startDate.getTime()) /
|
|
53
|
+
1000
|
|
51
54
|
: 0;
|
|
52
55
|
return (_jsx("foreignObject", { x: centerX, y: y - 8, width: tickWidth, color: theme.textSecondary, overflow: "visible", children: _jsx(ConstrainedText, { color: "textSecondary", text: _jsx(Text, { variant: "Smaller", children: type.type === 'time' ? (_jsx(FormattedDateTime, { format: formatDate(duration), value: new Date(payload.value) })) : (String(payload.value)) }), centered: true, tooltipStyle: {
|
|
53
56
|
backgroundColor: theme.backgroundLevel1,
|
|
@@ -60,11 +63,12 @@ export const CustomTick = ({ x, y, payload, visibleTicksCount, width, type, }) =
|
|
|
60
63
|
export const StyledResponsiveContainer = styled(ResponsiveContainer) `
|
|
61
64
|
// Avoid tooltip over constrained text to be cut off
|
|
62
65
|
& .recharts-surface {
|
|
66
|
+
outline: none;
|
|
63
67
|
overflow: visible;
|
|
64
68
|
}
|
|
65
69
|
`;
|
|
66
70
|
const ChartHeader = ({ title, secondaryTitle, helpTooltip, rightTitle, }) => {
|
|
67
|
-
return (_jsxs(Wrap, { children: [_jsxs(Stack, { gap: "r4", children: [_jsx(Text, { variant: "ChartTitle", children: title }), helpTooltip && _jsx(IconHelp, { tooltipMessage: helpTooltip }), secondaryTitle && (_jsx(Text, { color: "textSecondary", style: {
|
|
71
|
+
return (_jsxs(Wrap, { children: [_jsxs(Stack, { gap: "r4", children: [_jsx(Text, { variant: "ChartTitle", children: title }), helpTooltip && (_jsx(IconHelp, { tooltipMessage: helpTooltip, overlayStyle: maxWidthTooltip })), secondaryTitle && (_jsx(Text, { color: "textSecondary", style: {
|
|
68
72
|
marginLeft: spacing.r8,
|
|
69
73
|
}, children: secondaryTitle }))] }), rightTitle && _jsx(Text, { children: rightTitle })] }));
|
|
70
74
|
};
|
|
@@ -87,6 +91,7 @@ export const Barchart = (props) => {
|
|
|
87
91
|
const theme = useTheme();
|
|
88
92
|
const { getColor } = useChartLegend();
|
|
89
93
|
const [hoveredValue, setHoveredValue] = useState();
|
|
94
|
+
const chartRef = useRef(null);
|
|
90
95
|
const { height = CHART_CONSTANTS.DEFAULT_HEIGHT, bars, type = { type: 'category' }, unitRange, stacked, stackedBarSort = 'default', defaultSort, tooltip, title, secondaryTitle, helpTooltip, rightTitle, isLoading, isError, } = props;
|
|
91
96
|
// Create colorSet from ChartLegendWrapper
|
|
92
97
|
const colorSet = bars === null || bars === void 0 ? void 0 : bars.reduce((acc, bar) => {
|
|
@@ -97,14 +102,15 @@ export const Barchart = (props) => {
|
|
|
97
102
|
return acc;
|
|
98
103
|
}, {});
|
|
99
104
|
const { rechartsBars, unitLabel, roundReferenceValue, rechartsData } = useChartData(bars || [], type, colorSet || {}, stacked, defaultSort, unitRange, stackedBarSort);
|
|
100
|
-
|
|
105
|
+
const titleWithUnit = unitLabel ? `${title} (${unitLabel})` : title;
|
|
106
|
+
return (_jsxs(Stack, { direction: "vertical", style: { gap: '0' }, children: [_jsx(ChartHeader, { title: titleWithUnit, secondaryTitle: secondaryTitle, helpTooltip: helpTooltip, rightTitle: rightTitle }), isError || (!bars && !isLoading) ? (_jsx(Error, { height: height })) : isLoading ? (_jsx(Loading, { height: height })) : (_jsx(StyledResponsiveContainer, { ref: chartRef, width: "100%", height: height, children: _jsxs(BarChart, { data: rechartsData, accessibilityLayer: true, barSize: type.type === 'category'
|
|
101
107
|
? type.gap === 0
|
|
102
108
|
? undefined
|
|
103
109
|
: CHART_CONSTANTS.BAR_SIZE
|
|
104
110
|
: CHART_CONSTANTS.BAR_SIZE, height: height, margin: CHART_CONSTANTS.CHART_MARGIN, barCategoryGap: type.type === 'category' ? type.gap : undefined, children: [_jsx(CartesianGrid, { vertical: true, horizontal: true, verticalPoints: [0], horizontalPoints: [0], stroke: theme.border, fill: theme.backgroundLevel4, strokeWidth: 1 }), rechartsBars.map((bar) => {
|
|
105
111
|
const { fill, dataKey, stackId } = bar;
|
|
106
112
|
return (_jsx(Bar, { dataKey: dataKey, fill: chartColors[fill] || fill, minPointSize: stacked ? 0 : CHART_CONSTANTS.MIN_POINT_SIZE, stackId: stackId, isAnimationActive: false, onMouseOver: () => setHoveredValue(dataKey), onMouseLeave: () => setHoveredValue(undefined) }, dataKey));
|
|
107
|
-
}), _jsx(YAxis, {
|
|
113
|
+
}), _jsx(YAxis, { interval: 0, domain: [0, roundReferenceValue], ticks: getTicks(roundReferenceValue, false), tickFormatter: (value) => new Intl.NumberFormat('fr-FR').format(value) // Add a space as thousand separator
|
|
108
114
|
, axisLine: { stroke: theme.border }, tick: {
|
|
109
115
|
fill: theme.textSecondary,
|
|
110
116
|
fontSize: fontSize.smaller,
|
|
@@ -112,5 +118,5 @@ export const Barchart = (props) => {
|
|
|
112
118
|
stroke: theme.border,
|
|
113
119
|
}, axisLine: {
|
|
114
120
|
stroke: theme.border,
|
|
115
|
-
} }), _jsx(Tooltip, { content: (props) => (_jsx(BarchartTooltip, { type: type, colorSet: colorSet, tooltipProps: props, hoveredValue: hoveredValue, tooltip: tooltip, unitLabel: unitLabel })), cursor: false })] }) }))] }));
|
|
121
|
+
} }), _jsx(Tooltip, { content: (props) => (_jsx(BarchartTooltip, { type: type, colorSet: colorSet, tooltipProps: props, hoveredValue: hoveredValue, tooltip: tooltip, unitLabel: unitLabel, chartContainerRef: chartRef })), cursor: false })] }) }))] }));
|
|
116
122
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { TooltipContentProps } from 'recharts';
|
|
2
2
|
import { BarchartBars, BarchartTooltipFn, CategoryType, TimeType } from './Barchart.component';
|
|
3
|
-
export declare const BarchartTooltip: <T extends BarchartBars>({ type, tooltipProps, colorSet, hoveredValue, tooltip, unitLabel, }: {
|
|
3
|
+
export declare const BarchartTooltip: <T extends BarchartBars>({ type, tooltipProps, colorSet, hoveredValue, tooltip, unitLabel, chartContainerRef, }: {
|
|
4
4
|
type: TimeType | CategoryType;
|
|
5
5
|
tooltipProps: TooltipContentProps<number, string>;
|
|
6
6
|
colorSet?: Record<string, string>;
|
|
7
7
|
hoveredValue: string | undefined;
|
|
8
8
|
tooltip?: BarchartTooltipFn<T>;
|
|
9
9
|
unitLabel?: string;
|
|
10
|
-
|
|
10
|
+
chartContainerRef: React.RefObject<HTMLDivElement>;
|
|
11
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
11
12
|
//# sourceMappingURL=BarchartTooltip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BarchartTooltip.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchartv2/BarchartTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAS/C,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAG9B,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,YAAY,
|
|
1
|
+
{"version":3,"file":"BarchartTooltip.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchartv2/BarchartTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAS/C,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAG9B,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,YAAY,0FAQnD;IACD,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC9B,YAAY,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;CACpD,mDAgEA,CAAC"}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { LegendShape } from '../chartlegend/ChartLegend';
|
|
3
|
-
import {
|
|
3
|
+
import { ChartTooltipPortal, ChartTooltipHeader, ChartTooltipItem, ChartTooltipItemsContainer, TooltipHeader, } from '../charttooltip/ChartTooltip';
|
|
4
4
|
import { getCurrentPoint } from './utils';
|
|
5
|
-
export const BarchartTooltip = ({ type, tooltipProps, colorSet, hoveredValue, tooltip, unitLabel, }) => {
|
|
6
|
-
const { active } = tooltipProps;
|
|
5
|
+
export const BarchartTooltip = ({ type, tooltipProps, colorSet, hoveredValue, tooltip, unitLabel, chartContainerRef, }) => {
|
|
6
|
+
const { active, coordinate } = tooltipProps;
|
|
7
7
|
if (!active) {
|
|
8
8
|
return null;
|
|
9
9
|
}
|
|
10
10
|
const currentPoint = getCurrentPoint(tooltipProps, hoveredValue);
|
|
11
|
-
if (tooltip) {
|
|
12
|
-
return tooltip(currentPoint);
|
|
13
|
-
}
|
|
14
11
|
const duration = type.type === 'time'
|
|
15
12
|
? type.timeRange.startDate.getTime() - type.timeRange.endDate.getTime()
|
|
16
13
|
: 0;
|
|
17
|
-
|
|
14
|
+
const tooltipContent = tooltip ? (tooltip(currentPoint)) : (_jsxs(_Fragment, { children: [_jsx(ChartTooltipHeader, { children: type.type === 'time' ? (_jsx(TooltipHeader, { duration: duration, value: currentPoint.category })) : (currentPoint.category) }), _jsx(ChartTooltipItemsContainer, { children: currentPoint.values.map((value) => {
|
|
18
15
|
const legendIcon = colorSet && (_jsx(LegendShape, { color: colorSet[value.label], shape: "rectangle", chartColors: colorSet }));
|
|
19
16
|
const formattedValue = Number.isInteger(value.value)
|
|
20
17
|
? `${value.value}`
|
|
@@ -24,4 +21,5 @@ export const BarchartTooltip = ({ type, tooltipProps, colorSet, hoveredValue, to
|
|
|
24
21
|
: formattedValue;
|
|
25
22
|
return (_jsx(ChartTooltipItem, { label: value.label, value: valueWithUnit, isHovered: value.isHovered, legendIcon: legendIcon }, value.label));
|
|
26
23
|
}) })] }));
|
|
24
|
+
return (_jsx(ChartTooltipPortal, { coordinate: coordinate, chartContainerRef: chartContainerRef, isVisible: active, children: tooltipContent }));
|
|
27
25
|
};
|
|
@@ -2,6 +2,7 @@ import { BarchartProps, BarchartBars } from './Barchart.component';
|
|
|
2
2
|
import { TooltipContentProps } from 'recharts';
|
|
3
3
|
import { ChartColors } from '../../style/theme';
|
|
4
4
|
export declare const getRoundReferenceValue: (value: number) => number;
|
|
5
|
+
export declare const getTicks: (topValue: number, isSymmetrical: boolean) => number[];
|
|
5
6
|
export declare const getMaxBarValue: (data: {
|
|
6
7
|
[key: string]: string | number;
|
|
7
8
|
}[], stacked?: boolean) => number;
|
|
@@ -53,6 +54,10 @@ export type UnitRange = {
|
|
|
53
54
|
label: string;
|
|
54
55
|
}[];
|
|
55
56
|
export declare const computeUnitLabelAndRoundReferenceValue: (data: any, maxValue: number, unitRange: UnitRange | undefined) => {
|
|
57
|
+
unitLabel: undefined;
|
|
58
|
+
roundReferenceValue: number;
|
|
59
|
+
rechartsData: any;
|
|
60
|
+
} | {
|
|
56
61
|
unitLabel: string;
|
|
57
62
|
roundReferenceValue: number;
|
|
58
63
|
rechartsData: any;
|
|
@@ -110,7 +115,7 @@ export declare const useChartData: <T extends BarchartBars>(bars: T, type: Barch
|
|
|
110
115
|
fill: string;
|
|
111
116
|
stackId?: string;
|
|
112
117
|
}[];
|
|
113
|
-
unitLabel: string;
|
|
118
|
+
unitLabel: string | undefined;
|
|
114
119
|
roundReferenceValue: number;
|
|
115
120
|
rechartsData: any;
|
|
116
121
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchartv2/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAe,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG7D,eAAO,MAAM,sBAAsB,UAAW,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/components/barchartv2/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,23 +2,49 @@ import { chartColors } from '../../style/theme';
|
|
|
2
2
|
import { useChartLegend } from '../chartlegend/ChartLegendWrapper';
|
|
3
3
|
export const getRoundReferenceValue = (value) => {
|
|
4
4
|
if (value <= 0)
|
|
5
|
-
return
|
|
5
|
+
return 1; // Default for zero or negative values
|
|
6
6
|
// Get the magnitude (10^n where n is the number of digits - 1)
|
|
7
7
|
const magnitude = Math.pow(10, Math.floor(Math.log10(value)));
|
|
8
|
+
// Buffer the value by 10% to avoid being too close to the edge of the chart
|
|
9
|
+
const bufferedValue = value * 1.1;
|
|
8
10
|
// Normalized value between 1 and 10
|
|
9
|
-
const normalized =
|
|
11
|
+
const normalized = bufferedValue / magnitude;
|
|
10
12
|
// Round to nice numbers based on normalized value
|
|
13
|
+
// skip 1.5, 3, 4, 7.5 as top value for better chart
|
|
14
|
+
// appearance for small values
|
|
11
15
|
let result;
|
|
12
16
|
if (normalized <= 1)
|
|
13
17
|
result = magnitude;
|
|
14
|
-
else if (normalized <= 2
|
|
15
|
-
result = 2
|
|
18
|
+
else if (normalized <= 2)
|
|
19
|
+
result = 2 * magnitude;
|
|
20
|
+
else if (value > 10 && normalized <= 4)
|
|
21
|
+
result = 4 * magnitude;
|
|
16
22
|
else if (normalized <= 5)
|
|
17
23
|
result = 5 * magnitude;
|
|
24
|
+
else if (value > 10 && normalized <= 7.5)
|
|
25
|
+
result = 7.5 * magnitude;
|
|
18
26
|
else
|
|
19
27
|
result = 10 * magnitude;
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
export const getTicks = (topValue, isSymmetrical) => {
|
|
31
|
+
if (topValue < 10) {
|
|
32
|
+
if (isSymmetrical) {
|
|
33
|
+
return [-topValue, 0, topValue];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return [0, topValue];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const numberOfTicks = topValue % 3 === 0 ? 4 : 3;
|
|
40
|
+
const tickInterval = topValue / (numberOfTicks - 1);
|
|
41
|
+
const ticks = Array.from({ length: numberOfTicks }, (_, index) => index * tickInterval);
|
|
42
|
+
if (isSymmetrical) {
|
|
43
|
+
// Create negative ticks in order without 0
|
|
44
|
+
const negativeTicks = Array.from({ length: numberOfTicks - 1 }, (_, index) => -(numberOfTicks - 1 - index) * tickInterval);
|
|
45
|
+
ticks.unshift(...negativeTicks);
|
|
46
|
+
}
|
|
47
|
+
return ticks;
|
|
22
48
|
};
|
|
23
49
|
export const getMaxBarValue = (data, stacked) => {
|
|
24
50
|
const values = data.map((item) => {
|
|
@@ -189,10 +215,10 @@ export const formatPrometheusDataToRechartsDataAndBars = (bars, type, colorSet,
|
|
|
189
215
|
export const computeUnitLabelAndRoundReferenceValue = (data, maxValue, unitRange) => {
|
|
190
216
|
if (!unitRange) {
|
|
191
217
|
const roundReferenceValue = getRoundReferenceValue(maxValue);
|
|
192
|
-
return { unitLabel:
|
|
218
|
+
return { unitLabel: undefined, roundReferenceValue, rechartsData: data };
|
|
193
219
|
}
|
|
194
220
|
const { valueBase, unitLabel } = getUnitLabel(unitRange, maxValue);
|
|
195
|
-
const topValue =
|
|
221
|
+
const topValue = maxValue / valueBase;
|
|
196
222
|
const roundReferenceValue = getRoundReferenceValue(topValue);
|
|
197
223
|
const rechartsData = data.map((dataPoint) => {
|
|
198
224
|
const normalizedDataPoint = { ...dataPoint };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { Middleware } from '@floating-ui/react';
|
|
2
3
|
export declare const ChartTooltipContainer: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>;
|
|
3
4
|
interface ChartTooltipItemProps {
|
|
4
5
|
label: React.ReactNode;
|
|
@@ -15,5 +16,27 @@ export declare const TooltipHeader: ({ duration, value, }: {
|
|
|
15
16
|
duration: number;
|
|
16
17
|
value: string | number;
|
|
17
18
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export interface ChartTooltipPortalProps {
|
|
20
|
+
children: React.ReactNode;
|
|
21
|
+
coordinate?: {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
};
|
|
25
|
+
chartContainerRef: React.RefObject<HTMLDivElement>;
|
|
26
|
+
isVisible?: boolean;
|
|
27
|
+
middleware?: Middleware[];
|
|
28
|
+
offset?: number | (({ placement }: {
|
|
29
|
+
placement: string;
|
|
30
|
+
}) => number);
|
|
31
|
+
customPosition?: (chartRect: DOMRect, coordinate?: {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
}) => {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
};
|
|
38
|
+
containerComponent?: React.ComponentType<any>;
|
|
39
|
+
}
|
|
40
|
+
export declare const ChartTooltipPortal: React.FC<ChartTooltipPortalProps>;
|
|
18
41
|
export {};
|
|
19
42
|
//# sourceMappingURL=ChartTooltip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartTooltip.d.ts","sourceRoot":"","sources":["../../../src/lib/components/charttooltip/ChartTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ChartTooltip.d.ts","sourceRoot":"","sources":["../../../src/lib/components/charttooltip/ChartTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAML,UAAU,EACX,MAAM,oBAAoB,CAAC;AAM5B,eAAO,MAAM,qBAAqB,yGAWjC,CAAC;AA+BF,UAAU,qBAAqB;IAC7B,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAe5D,CAAC;AAEF,eAAO,MAAM,kBAAkB,yGAK9B,CAAC;AAEF,eAAO,MAAM,0BAA0B,yGAKtC,CAAC;AAEF,eAAO,MAAM,qBAAqB,yGAKjC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,wCAAwC,GACxC,0CAA0C,GAC1C,mCAAmC,CAAC;AAcxC,eAAO,MAAM,aAAa,yBAGvB;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB,4CAOA,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC,CAAC;IACrE,cAAc,CAAC,EAAE,CACf,SAAS,EAAE,OAAO,EAClB,UAAU,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAClC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,kBAAkB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;CAC/C;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA0GhE,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { useEffect, useState, useRef } from 'react';
|
|
4
|
+
import { useFloating, autoUpdate, offset, flip, shift, } from '@floating-ui/react';
|
|
2
5
|
import styled from 'styled-components';
|
|
3
6
|
import { spacing } from '../../spacing';
|
|
4
7
|
import { fontSize, fontWeight } from '../../style/theme';
|
|
@@ -11,7 +14,8 @@ export const ChartTooltipContainer = styled.div `
|
|
|
11
14
|
font-size: ${fontSize.small};
|
|
12
15
|
padding: ${spacing.r8};
|
|
13
16
|
min-width: 10rem;
|
|
14
|
-
max-width:
|
|
17
|
+
max-width: 40rem;
|
|
18
|
+
|
|
15
19
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
16
20
|
`;
|
|
17
21
|
const TooltipText = styled.div `
|
|
@@ -55,10 +59,10 @@ export const ChartTooltipSeparator = styled.div `
|
|
|
55
59
|
width: 100%;
|
|
56
60
|
`;
|
|
57
61
|
const getTooltipDateFormat = (duration) => {
|
|
58
|
-
if (duration <= 60 * 60
|
|
62
|
+
if (duration <= 60 * 60) {
|
|
59
63
|
return 'day-month-abbreviated-hour-minute-second';
|
|
60
64
|
}
|
|
61
|
-
else if (duration <= 7 * 24 * 60 * 60
|
|
65
|
+
else if (duration <= 7 * 24 * 60 * 60) {
|
|
62
66
|
return 'day-month-abbreviated-hour-minute';
|
|
63
67
|
}
|
|
64
68
|
else {
|
|
@@ -69,3 +73,81 @@ export const TooltipHeader = ({ duration, value, }) => {
|
|
|
69
73
|
const timeFormat = getTooltipDateFormat(duration);
|
|
70
74
|
return (_jsx(ChartTooltipHeader, { children: _jsx(FormattedDateTime, { format: timeFormat, value: new Date(value) }) }));
|
|
71
75
|
};
|
|
76
|
+
export const ChartTooltipPortal = ({ children, coordinate, chartContainerRef, isVisible = true, middleware, offset: customOffset, customPosition, containerComponent: ContainerComponent = ChartTooltipContainer, }) => {
|
|
77
|
+
const [virtualElement, setVirtualElement] = useState(null);
|
|
78
|
+
const previousPositionRef = useRef(null);
|
|
79
|
+
const [portalContainer, setPortalContainer] = useState(null);
|
|
80
|
+
// Default middleware configuration
|
|
81
|
+
const defaultMiddleware = [
|
|
82
|
+
offset(customOffset || 20),
|
|
83
|
+
flip(),
|
|
84
|
+
shift({ padding: 10 }),
|
|
85
|
+
];
|
|
86
|
+
const { refs, floatingStyles } = useFloating({
|
|
87
|
+
elements: {
|
|
88
|
+
reference: virtualElement,
|
|
89
|
+
},
|
|
90
|
+
placement: 'top',
|
|
91
|
+
middleware: middleware || defaultMiddleware,
|
|
92
|
+
whileElementsMounted: autoUpdate,
|
|
93
|
+
});
|
|
94
|
+
// Create portal container once
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const container = document.createElement('div');
|
|
97
|
+
document.body.appendChild(container);
|
|
98
|
+
setPortalContainer(container);
|
|
99
|
+
return () => {
|
|
100
|
+
document.body.removeChild(container);
|
|
101
|
+
};
|
|
102
|
+
}, []);
|
|
103
|
+
// Create virtual element from coordinate or custom position
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (chartContainerRef.current) {
|
|
106
|
+
const chartRect = chartContainerRef.current.getBoundingClientRect();
|
|
107
|
+
let tooltipX;
|
|
108
|
+
let tooltipY;
|
|
109
|
+
if (customPosition) {
|
|
110
|
+
// Use custom positioning function
|
|
111
|
+
const position = customPosition(chartRect, coordinate);
|
|
112
|
+
tooltipX = position.x;
|
|
113
|
+
tooltipY = position.y;
|
|
114
|
+
}
|
|
115
|
+
else if (coordinate) {
|
|
116
|
+
// Use default coordinate-based positioning
|
|
117
|
+
tooltipX = chartRect.left + coordinate.x;
|
|
118
|
+
tooltipY = chartRect.top + coordinate.y;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return; // No positioning method available
|
|
122
|
+
}
|
|
123
|
+
// Check if position has changed significantly
|
|
124
|
+
const hasPositionChanged = !previousPositionRef.current ||
|
|
125
|
+
Math.abs(previousPositionRef.current.x - tooltipX) > 5 ||
|
|
126
|
+
Math.abs(previousPositionRef.current.y - tooltipY) > 5;
|
|
127
|
+
if (hasPositionChanged) {
|
|
128
|
+
previousPositionRef.current = { x: tooltipX, y: tooltipY };
|
|
129
|
+
}
|
|
130
|
+
setVirtualElement({
|
|
131
|
+
getBoundingClientRect() {
|
|
132
|
+
return {
|
|
133
|
+
width: 0,
|
|
134
|
+
height: 0,
|
|
135
|
+
x: tooltipX,
|
|
136
|
+
y: tooltipY,
|
|
137
|
+
left: tooltipX,
|
|
138
|
+
top: tooltipY,
|
|
139
|
+
right: tooltipX,
|
|
140
|
+
bottom: tooltipY,
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}, [coordinate, chartContainerRef, customPosition]);
|
|
146
|
+
if (!isVisible || !virtualElement || !portalContainer)
|
|
147
|
+
return null;
|
|
148
|
+
const tooltipContent = (_jsx(ContainerComponent, { ref: refs.setFloating, style: {
|
|
149
|
+
...floatingStyles,
|
|
150
|
+
opacity: isVisible ? 1 : 0,
|
|
151
|
+
}, children: children }));
|
|
152
|
+
return createPortal(tooltipContent, portalContainer);
|
|
153
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalHealthBarRecharts.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/globalhealthbar/GlobalHealthBarRecharts.component.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,EAAoB,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;CACX;
|
|
1
|
+
{"version":3,"file":"GlobalHealthBarRecharts.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/globalhealthbar/GlobalHealthBarRecharts.component.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,EAAoB,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;CACX;AAUD,wBAAgB,eAAe,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,iBAAiB,2CAkN5E;AAGD,YAAY,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -8,11 +8,16 @@ import { CHART_CONFIG, getNavigationAction, getNavigationStateUpdate, } from './
|
|
|
8
8
|
import { useHealthBarData } from './useHealthBarData';
|
|
9
9
|
const ChartInteractiveContainer = styled.div `
|
|
10
10
|
position: relative;
|
|
11
|
+
outline: none;
|
|
12
|
+
.recharts-surface {
|
|
13
|
+
outline: none;
|
|
14
|
+
}
|
|
11
15
|
`;
|
|
12
16
|
export function GlobalHealthBar({ id, alerts, start, end }) {
|
|
13
17
|
const [tooltipData, setTooltipData] = useState(null);
|
|
14
18
|
const [focusedAlertIndex, setFocusedAlertIndex] = useState(-1);
|
|
15
19
|
const [keyboardActive, setKeyboardActive] = useState(false);
|
|
20
|
+
const [activeBarKey, setActiveBarKey] = useState(null);
|
|
16
21
|
const chartContainerRef = useRef(null);
|
|
17
22
|
const theme = useTheme();
|
|
18
23
|
const startTimestamp = new Date(start).getTime();
|
|
@@ -20,10 +25,12 @@ export function GlobalHealthBar({ id, alerts, start, end }) {
|
|
|
20
25
|
const { chartData, alertsMap, alertKeys } = useHealthBarData(alerts, startTimestamp, endTimestamp, id);
|
|
21
26
|
const handlePointerEnter = useCallback((key) => {
|
|
22
27
|
setTooltipData(alertsMap[key]);
|
|
28
|
+
setActiveBarKey(key);
|
|
23
29
|
}, [alertsMap]);
|
|
24
30
|
const handlePointerLeave = useCallback(() => {
|
|
25
31
|
if (!keyboardActive) {
|
|
26
32
|
setTooltipData(null);
|
|
33
|
+
setActiveBarKey(null);
|
|
27
34
|
}
|
|
28
35
|
}, [keyboardActive]);
|
|
29
36
|
const { warningKeys, criticalKeys, unavailableKeys } = alertKeys;
|
|
@@ -43,6 +50,10 @@ export function GlobalHealthBar({ id, alerts, start, end }) {
|
|
|
43
50
|
setFocusedAlertIndex(update.newIndex);
|
|
44
51
|
setTooltipData(update.selectedAlert);
|
|
45
52
|
setKeyboardActive(update.shouldActivateKeyboard);
|
|
53
|
+
// Set active bar key for keyboard navigation
|
|
54
|
+
if (update.selectedAlert) {
|
|
55
|
+
setActiveBarKey(update.selectedAlert.key);
|
|
56
|
+
}
|
|
46
57
|
}, [allAlertKeys, focusedAlertIndex]);
|
|
47
58
|
// Handle focus events
|
|
48
59
|
const handleFocus = useCallback(() => {
|
|
@@ -50,12 +61,15 @@ export function GlobalHealthBar({ id, alerts, start, end }) {
|
|
|
50
61
|
setFocusedAlertIndex(0);
|
|
51
62
|
setTooltipData(allAlertKeys[0]);
|
|
52
63
|
setKeyboardActive(true);
|
|
64
|
+
// Set active bar key for initial focus
|
|
65
|
+
setActiveBarKey(allAlertKeys[0].key);
|
|
53
66
|
}
|
|
54
67
|
}, [allAlertKeys, focusedAlertIndex]);
|
|
55
68
|
const handleBlur = useCallback(() => {
|
|
56
69
|
setKeyboardActive(false);
|
|
57
70
|
setFocusedAlertIndex(-1);
|
|
58
71
|
setTooltipData(null);
|
|
72
|
+
setActiveBarKey(null);
|
|
59
73
|
}, []);
|
|
60
74
|
// Handle mouse enter to disable keyboard mode
|
|
61
75
|
const handleMouseEnter = useCallback(() => {
|
|
@@ -74,5 +88,17 @@ export function GlobalHealthBar({ id, alerts, start, end }) {
|
|
|
74
88
|
position: 'fixed',
|
|
75
89
|
}, content: (props) => {
|
|
76
90
|
return (_jsx(GlobalHealthBarTooltip, { tooltipData: tooltipData, tooltipProps: props, chartContainerRef: chartContainerRef, isKeyboardActive: keyboardActive, startTimestamp: startTimestamp, endTimestamp: endTimestamp }));
|
|
77
|
-
} }), _jsx(YAxis, { yAxisId: 'background', type: "category", hide: true }), allAlertBars.map(({ key }) => (_jsx(YAxis, { yAxisId: key, type: "category", hide: true }, `yAxis${key}`))), _jsx(Bar, { dataKey: "range", fill: theme.statusHealthy, radius: CHART_CONFIG.RADIUS_SIZE, yAxisId: "background", isAnimationActive: false }), allAlertBars.map(({ key, fill }) =>
|
|
91
|
+
} }), _jsx(YAxis, { yAxisId: 'background', type: "category", hide: true }), allAlertBars.map(({ key }) => (_jsx(YAxis, { yAxisId: key, type: "category", hide: true }, `yAxis${key}`))), _jsx(Bar, { dataKey: "range", fill: theme.statusHealthy, radius: CHART_CONFIG.RADIUS_SIZE, yAxisId: "background", isAnimationActive: false }), allAlertBars.map(({ key, fill }) => {
|
|
92
|
+
const isActive = key === activeBarKey;
|
|
93
|
+
// Skip active bar here - it will be rendered last
|
|
94
|
+
if (isActive)
|
|
95
|
+
return null;
|
|
96
|
+
return (_jsx(Bar, { dataKey: key, yAxisId: key, fill: fill, onPointerEnter: () => handlePointerEnter(key), onPointerLeave: () => handlePointerLeave(), isAnimationActive: false }, key));
|
|
97
|
+
}), activeBarKey &&
|
|
98
|
+
(() => {
|
|
99
|
+
const activeBar = allAlertBars.find((bar) => bar.key === activeBarKey);
|
|
100
|
+
if (!activeBar)
|
|
101
|
+
return null;
|
|
102
|
+
return (_jsx(Bar, { dataKey: activeBar.key, yAxisId: activeBar.key, fill: activeBar.fill, stroke: theme.selectedActive, onPointerEnter: () => handlePointerEnter(activeBar.key), onPointerLeave: () => handlePointerLeave(), isAnimationActive: false }, `${activeBar.key}-active`));
|
|
103
|
+
})()] }) }) }));
|
|
78
104
|
}
|
|
@@ -13,6 +13,6 @@ interface GlobalHealthBarTooltipProps {
|
|
|
13
13
|
startTimestamp?: number;
|
|
14
14
|
endTimestamp?: number;
|
|
15
15
|
}
|
|
16
|
-
export declare const GlobalHealthBarTooltip: (props: GlobalHealthBarTooltipProps) =>
|
|
16
|
+
export declare const GlobalHealthBarTooltip: (props: GlobalHealthBarTooltipProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
17
17
|
export {};
|
|
18
18
|
//# sourceMappingURL=GlobalHealthBarTooltip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalHealthBarTooltip.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/globalhealthbar/components/GlobalHealthBarTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GlobalHealthBarTooltip.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/globalhealthbar/components/GlobalHealthBarTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAK/C,UAAU,2BAA2B;IACnC,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,YAAY,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACnD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAoBD,eAAO,MAAM,sBAAsB,UAAW,2BAA2B,mDA6FxE,CAAC"}
|