-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathProgressViewer.tsx
116 lines (98 loc) · 3.37 KB
/
ProgressViewer.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import {useTheme} from '@gravity-ui/uikit';
import {cn} from '../../utils/cn';
import {formatNumber, roundToPrecision} from '../../utils/dataFormatters/dataFormatters';
import {calculateProgressStatus} from '../../utils/progress';
import {isNumeric} from '../../utils/utils';
import './ProgressViewer.scss';
const b = cn('progress-viewer');
type ProgressViewerSize = 'xs' | 's' | 'ns' | 'm' | 'n' | 'l' | 'head';
export type FormatProgressViewerValues = (
value?: number,
capacity?: number,
) => (string | number | undefined)[];
const formatValue = (value?: number) => {
return formatNumber(roundToPrecision(Number(value), 2));
};
const defaultFormatValues: FormatProgressViewerValues = (value, total) => {
return [formatValue(value), formatValue(total)];
};
/*
Props description:
1) value - the amount of progress
2) capacity - maximum possible progress value
3) formatValues - function for formatting the value and capacity
4) percents - display progress in percents
5) colorizeProgress - change the color of the progress bar depending on its value
6) inverseColorize - invert the colors of the progress bar
7) warningThreshold - the percentage of fullness at which the color of the progress bar changes to yellow
8) dangerThreshold - the percentage of fullness at which the color of the progress bar changes to red
*/
export interface ProgressViewerProps {
value?: number | string;
capacity?: number | string;
formatValues?: FormatProgressViewerValues;
percents?: boolean;
className?: string;
size?: ProgressViewerSize;
colorizeProgress?: boolean;
inverseColorize?: boolean;
warningThreshold?: number;
dangerThreshold?: number;
hideCapacity?: boolean;
}
export function ProgressViewer({
value,
capacity,
formatValues = defaultFormatValues,
percents,
className,
size = 'xs',
colorizeProgress,
inverseColorize,
warningThreshold = 60,
dangerThreshold = 80,
hideCapacity,
}: ProgressViewerProps) {
const theme = useTheme();
let fillWidth =
Math.round((parseFloat(String(value)) / parseFloat(String(capacity))) * 100) || 0;
fillWidth = fillWidth > 100 ? 100 : fillWidth;
let valueText: number | string | undefined = value,
capacityText: number | string | undefined = capacity,
divider = '/';
if (percents) {
valueText = fillWidth + '%';
capacityText = '';
divider = '';
} else if (formatValues) {
[valueText, capacityText] = formatValues(Number(value), Number(capacity));
}
const status = calculateProgressStatus({
fillWidth,
warningThreshold,
dangerThreshold,
colorizeProgress,
inverseColorize,
});
if (colorizeProgress && !isNumeric(capacity)) {
fillWidth = 100;
}
const lineStyle = {
width: fillWidth + '%',
};
const renderContent = () => {
if (isNumeric(capacity) && !hideCapacity) {
return `${valueText} ${divider} ${capacityText}`;
}
return valueText;
};
if (isNumeric(value)) {
return (
<div className={b({size, theme, status}, className)}>
<div className={b('line')} style={lineStyle}></div>
<span className={b('text')}>{renderContent()}</span>
</div>
);
}
return <div className={`${b({size})} ${className} error`}>no data</div>;
}