@alfalab/core-components-circular-progress-bar 2.4.2 → 2.4.3

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.
@@ -2,8 +2,23 @@
2
2
  --color-light-bg-tertiary: #e7e9eb;
3
3
  --color-light-graphic-negative: #f15045;
4
4
  --color-light-graphic-positive: #2fc26e;
5
+ --color-light-graphic-primary: #0b1f35;
6
+ --color-light-graphic-primary-inverted: #fff;
7
+ --color-light-graphic-secondary: #6d7986;
8
+ --color-light-graphic-tertiary: #b6bcc3;
5
9
  }
10
+ :root {
11
+
12
+ /* Hard */
13
+
14
+ /* Up */
6
15
 
16
+ /* Hard up */
17
+ }
18
+ :root {
19
+ --font-family-system: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica,
20
+ sans-serif;
21
+ }
7
22
  :root {
8
23
  /* bg */
9
24
  --circular-progress-bar-bg-color: var(--color-light-bg-tertiary);
@@ -13,94 +28,184 @@
13
28
 
14
29
  /* negative */
15
30
  --circular-progress-bar-negative-color: var(--color-light-graphic-negative);
16
- }
17
31
 
32
+ /* theme */
33
+ --circular-progress-bar-font-family: var(--font-family-system);
34
+ --circular-progress-bar-font-weight: 600;
35
+ }
18
36
  .component {
19
37
  position: relative;
20
38
  display: flex;
21
39
  justify-content: center;
22
40
  align-items: center;
23
41
  }
24
-
25
42
  .svg {
26
43
  display: block;
27
44
  width: 100%;
28
45
  }
29
-
30
46
  .title,
31
47
  .subtitle {
32
48
  overflow: hidden;
33
49
  word-break: break-word;
50
+ white-space: nowrap;
51
+ text-overflow: ellipsis;
52
+ margin: 0 6px;
34
53
  }
35
-
36
54
  .subtitle {
37
55
  max-height: 40px;
38
56
  }
39
-
40
- .l {
57
+ .labelWrapper {
58
+ text-align: center;
59
+ position: absolute;
60
+ top: 50%;
61
+ left: 50%;
62
+ width: 100%;
63
+ transform: translate(-50%, -50%)
64
+ }
65
+ .labelWrapper.label {
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ }
70
+ .typography {
71
+ font-feature-settings: 'ss01';
72
+ font-weight: var(--circular-progress-bar-font-weight);
73
+ font-family: var(--circular-progress-bar-font-family);
74
+ }
75
+ .xxl {
41
76
  width: 144px;
42
77
  height: 144px
43
78
  }
44
-
45
- .l .label {
46
- max-width: 120px;
79
+ .xxl .labelWrapper {
80
+ max-width: 128px;
47
81
  }
48
-
49
- .l .title {
82
+ .xxl .title {
50
83
  max-height: 32px;
51
84
  }
52
-
85
+ .xl {
86
+ width: 128px;
87
+ height: 128px
88
+ }
89
+ .xl .labelWrapper {
90
+ max-width: 108px;
91
+ }
92
+ .xl .title {
93
+ max-height: 32px;
94
+ }
95
+ .l {
96
+ width: 80px;
97
+ height: 80px
98
+ }
99
+ .l .labelWrapper {
100
+ max-width: 64px;
101
+ }
102
+ .l .title {
103
+ max-height: 24px;
104
+ }
53
105
  .m {
54
- width: 120px;
55
- height: 120px
106
+ width: 64px;
107
+ height: 64px
56
108
  }
57
-
58
- .m .label {
59
- max-width: 96px;
109
+ .m .labelWrapper {
110
+ max-width: 48px;
60
111
  }
61
-
62
112
  .m .title {
63
- max-height: 24px;
113
+ max-height: 16px;
114
+ margin: 0;
64
115
  }
65
-
66
116
  .s {
67
- width: 96px;
68
- height: 96px
117
+ width: 48px;
118
+ height: 48px
69
119
  }
70
-
71
- .s .label {
72
- max-width: 72px;
120
+ .s .labelWrapper {
121
+ max-width: 40px;
73
122
  }
74
-
75
123
  .s .title {
76
- max-height: 24px;
124
+ max-height: 16px;
125
+ margin: 0;
77
126
  }
78
-
79
- .label {
80
- text-align: center;
81
- position: absolute;
82
- top: 50%;
83
- left: 50%;
84
- width: 100%;
85
- transform: translate(-50%, -50%);
127
+ .xs {
128
+ width: 24px;
129
+ height: 24px
86
130
  }
87
-
131
+ .xs .labelWrapper {
132
+ max-width: 24px;
133
+ }
88
134
  .backgroundCircle,
89
135
  .progressCircle {
90
136
  width: 100%;
91
137
  height: 100%;
92
138
  fill: transparent;
93
- stroke-width: 8;
94
139
  }
95
-
96
140
  .positive {
97
141
  stroke: var(--circular-progress-bar-positive-color);
98
142
  }
99
-
100
143
  .negative {
101
144
  stroke: var(--circular-progress-bar-negative-color);
102
145
  }
103
-
104
146
  .backgroundCircle {
105
- stroke: var(--circular-progress-bar-bg-color);
147
+ stroke: var(--circular-progress-bar-bg-color)
148
+ }
149
+ .backgroundCircle.stroke {
150
+ stroke: transparent;
151
+ }
152
+ .progressCircle {
153
+ stroke-linecap: round
154
+ }
155
+ .progressCircle.bg-positive {
156
+ fill: var(--circular-progress-bar-positive-color);
157
+ }
158
+ .progressCircle.bg-negative {
159
+ fill: var(--circular-progress-bar-negative-color);
160
+ }
161
+ .iconWrapper {
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center
165
+ }
166
+ .iconWrapper.xxl {
167
+ max-width: 64px;
168
+ max-height: 64px;
169
+ }
170
+ .iconWrapper.xl {
171
+ max-width: 64px;
172
+ max-height: 64px;
173
+ }
174
+ .iconWrapper.l {
175
+ max-width: 48px;
176
+ max-height: 48px;
177
+ }
178
+ .iconWrapper.m {
179
+ max-width: 36px;
180
+ max-height: 36px;
181
+ }
182
+ .iconWrapper.s {
183
+ max-width: 24px;
184
+ max-height: 24px;
185
+ }
186
+ .iconWrapper.xs {
187
+ max-width: 16px;
188
+ max-height: 16px;
189
+ }
190
+ .iconWrapper.icon-tertiary {
191
+ color: var(--color-light-graphic-tertiary);
192
+ }
193
+ .iconWrapper.icon-positive {
194
+ color: var(--color-light-graphic-positive);
195
+ }
196
+ .iconWrapper.icon-negative {
197
+ color: var(--color-light-graphic-negative);
198
+ }
199
+ .iconWrapper.icon-primary-inverted {
200
+ color: var(--color-light-graphic-primary-inverted);
201
+ }
202
+ .iconWrapper.icon-primary {
203
+ color: var(--color-light-graphic-primary);
204
+ }
205
+ .iconWrapper.icon-secondary {
206
+ color: var(--color-light-graphic-secondary);
207
+ }
208
+ .icon {
209
+ width: 100%;
210
+ height: 100%;
106
211
  }
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import React from 'react';
3
- import { ReactNode } from "react";
3
+ import { ReactNode, ElementType } from "react";
4
4
  type CircularProgressBarProps = {
5
5
  /**
6
6
  * Уровень прогресса, %
@@ -14,18 +14,73 @@ type CircularProgressBarProps = {
14
14
  * Основной текст
15
15
  */
16
16
  title?: ReactNode;
17
+ /**
18
+ * Цвет контента
19
+ */
20
+ contentColor?: 'primary' | 'secondary' | 'tertiary' | 'positive' | 'negative';
17
21
  /**
18
22
  * Дополнительный текст
19
23
  */
20
24
  subtitle?: ReactNode;
25
+ /**
26
+ * Основной текст при 100%
27
+ */
28
+ titleComplete?: ReactNode;
29
+ /**
30
+ * Дополнительный текст при 100%
31
+ */
32
+ subtitleComplete?: ReactNode;
21
33
  /**
22
34
  * Цвет заполнения
23
35
  */
24
36
  view?: 'positive' | 'negative';
25
37
  /**
26
- * Размер (l — 144×144px, m — 120×120px, s — 96×96px)
38
+ * Размер (xxl — 144×144px, xl — 128×128px, l — 80×80px, m — 64×64px, s — 48×48px, xs — 24×24px)
39
+ */
40
+ size?: 'xxl' | 'xl' | 'l' | 'm' | 's' | 'xs';
41
+ /**
42
+ * Наличие желоба
43
+ */
44
+ stroke?: boolean;
45
+ /**
46
+ * Заливка при 100%
47
+ */
48
+ fillComplete?: boolean;
49
+ /**
50
+ * Цвет текста при 100%
51
+ */
52
+ completeTextColor?: 'primary' | 'primary-inverted' | 'positive' | 'negative';
53
+ /**
54
+ * Цвет иконки при 100%
55
+ */
56
+ completeIconColor?: 'primary-inverted' | 'positive' | 'negative' | 'tertiary';
57
+ /**
58
+ * Компонент иконки
59
+ */
60
+ icon?: ElementType<{
61
+ className?: string;
62
+ }>;
63
+ /**
64
+ * Компонент иконки при 100%
65
+ */
66
+ iconComplete?: ElementType<{
67
+ className?: string;
68
+ }>;
69
+ /**
70
+ * Направление прогресса (clockwise - по часовой стрелке, counter-clockwise - против часовой стрелки)
71
+ */
72
+ direction?: 'clockwise' | 'counter-clockwise';
73
+ /**
74
+ * Высота компонента, min = 24; max = 144
75
+ * использовать совместно с size :
76
+ * xxl от 144
77
+ * xl от 128 до 143
78
+ * l от 80 до 127
79
+ * m от 64 до 79
80
+ * s от 48 до 63
81
+ * xs от 24 до 47
27
82
  */
28
- size?: 'l' | 'm' | 's';
83
+ height?: number;
29
84
  /**
30
85
  * Id компонента для тестов
31
86
  */
package/esm/Component.js CHANGED
@@ -2,47 +2,131 @@ import cn from 'classnames';
2
2
  import React, { useMemo } from 'react';
3
3
  import { Typography } from '@alfalab/core-components-typography/esm';
4
4
 
5
- var styles = {"component":"circular-progress-bar__component_mot4l","svg":"circular-progress-bar__svg_mot4l","title":"circular-progress-bar__title_mot4l","subtitle":"circular-progress-bar__subtitle_mot4l","l":"circular-progress-bar__l_mot4l","label":"circular-progress-bar__label_mot4l","m":"circular-progress-bar__m_mot4l","s":"circular-progress-bar__s_mot4l","backgroundCircle":"circular-progress-bar__backgroundCircle_mot4l","progressCircle":"circular-progress-bar__progressCircle_mot4l","positive":"circular-progress-bar__positive_mot4l","negative":"circular-progress-bar__negative_mot4l"};
5
+ /*! *****************************************************************************
6
+ Copyright (c) Microsoft Corporation.
7
+
8
+ Permission to use, copy, modify, and/or distribute this software for any
9
+ purpose with or without fee is hereby granted.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ ***************************************************************************** */
19
+ var __assign = function () {
20
+ __assign = Object.assign || function __assign(t) {
21
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
22
+ s = arguments[i];
23
+ for (var p in s)
24
+ if (Object.prototype.hasOwnProperty.call(s, p))
25
+ t[p] = s[p];
26
+ }
27
+ return t;
28
+ };
29
+ return __assign.apply(this, arguments);
30
+ };
31
+
32
+ var styles = {"component":"circular-progress-bar__component_1piud","svg":"circular-progress-bar__svg_1piud","title":"circular-progress-bar__title_1piud","subtitle":"circular-progress-bar__subtitle_1piud","labelWrapper":"circular-progress-bar__labelWrapper_1piud","label":"circular-progress-bar__label_1piud","typography":"circular-progress-bar__typography_1piud","xxl":"circular-progress-bar__xxl_1piud","xl":"circular-progress-bar__xl_1piud","l":"circular-progress-bar__l_1piud","m":"circular-progress-bar__m_1piud","s":"circular-progress-bar__s_1piud","xs":"circular-progress-bar__xs_1piud","backgroundCircle":"circular-progress-bar__backgroundCircle_1piud","progressCircle":"circular-progress-bar__progressCircle_1piud","positive":"circular-progress-bar__positive_1piud","negative":"circular-progress-bar__negative_1piud","stroke":"circular-progress-bar__stroke_1piud","bg-positive":"circular-progress-bar__bg-positive_1piud","bg-negative":"circular-progress-bar__bg-negative_1piud","iconWrapper":"circular-progress-bar__iconWrapper_1piud","icon-tertiary":"circular-progress-bar__icon-tertiary_1piud","icon-positive":"circular-progress-bar__icon-positive_1piud","icon-negative":"circular-progress-bar__icon-negative_1piud","icon-primary-inverted":"circular-progress-bar__icon-primary-inverted_1piud","icon-primary":"circular-progress-bar__icon-primary_1piud","icon-secondary":"circular-progress-bar__icon-secondary_1piud","icon":"circular-progress-bar__icon_1piud"};
6
33
  require('./index.css')
7
34
 
8
35
  var SIZES = {
9
- s: 96,
10
- m: 120,
11
- l: 144,
36
+ xs: 24,
37
+ s: 48,
38
+ m: 64,
39
+ l: 80,
40
+ xl: 128,
41
+ xxl: 144,
42
+ };
43
+ var STROKE = {
44
+ xs: 4,
45
+ s: 4,
46
+ m: 6,
47
+ l: 8,
48
+ xl: 10,
49
+ xxl: 12,
50
+ };
51
+ var VIEW_TITLE = {
52
+ xs: 'small',
53
+ s: 'small',
54
+ m: 'small',
55
+ l: 'xsmall',
56
+ xl: 'medium',
57
+ xxl: 'medium',
58
+ };
59
+ var VIEW_TEXT = {
60
+ xs: 'secondary-small',
61
+ s: 'secondary-small',
62
+ m: 'secondary-large',
63
+ l: 'secondary-large',
64
+ xl: 'secondary-large',
65
+ xxl: 'secondary-large',
12
66
  };
13
67
  /**
14
68
  * Компонент круглого прогресс бара.
15
69
  */
16
70
  var CircularProgressBar = function (_a) {
17
- var value = _a.value, _b = _a.view, view = _b === void 0 ? 'positive' : _b, _c = _a.size, size = _c === void 0 ? 'm' : _c, className = _a.className, dataTestId = _a.dataTestId, _d = _a.title, title = _d === void 0 ? value.toString() : _d, subtitle = _a.subtitle, children = _a.children;
71
+ var _b, _c, _d;
72
+ var value = _a.value, _e = _a.view, view = _e === void 0 ? 'positive' : _e, _f = _a.size, size = _f === void 0 ? 'm' : _f, className = _a.className, dataTestId = _a.dataTestId, _g = _a.title, title = _g === void 0 ? value ? value.toString() : '0' : _g, titleComplete = _a.titleComplete, subtitle = _a.subtitle, _h = _a.contentColor, contentColor = _h === void 0 ? 'secondary' : _h, subtitleComplete = _a.subtitleComplete, _j = _a.stroke, stroke = _j === void 0 ? true : _j, fillComplete = _a.fillComplete, Icon = _a.icon, IconComplete = _a.iconComplete, completeTextColor = _a.completeTextColor, _k = _a.completeIconColor, completeIconColor = _k === void 0 ? 'tertiary' : _k, _l = _a.direction, direction = _l === void 0 ? 'clockwise' : _l, height = _a.height, children = _a.children;
18
73
  var memorized = useMemo(function () {
19
- var strokeWidth = 8;
74
+ var strokeWidth = STROKE[size];
20
75
  var maxProgress = 100;
21
76
  var minProgress = 0;
22
- var width = SIZES[size];
23
- var height = SIZES[size];
24
- var center = width / 2;
77
+ var widthSVG = SIZES[size];
78
+ var heightSVG = SIZES[size];
79
+ var center = widthSVG / 2;
25
80
  var radius = center - strokeWidth / 2;
26
81
  var circumference = Math.PI * radius * 2;
27
82
  var progress = Math.min(Math.max(value, minProgress), maxProgress);
28
83
  var strokeDasharray = circumference.toFixed(3);
29
84
  var strokeDashoffset = (((100 - progress) / 100) * circumference).toFixed(3);
30
85
  return {
31
- width: width,
32
- height: height,
86
+ widthSVG: widthSVG,
87
+ heightSVG: heightSVG,
33
88
  center: center,
34
89
  radius: radius,
35
90
  strokeDasharray: strokeDasharray,
36
91
  strokeDashoffset: strokeDashoffset,
37
92
  };
38
93
  }, [value, size]);
39
- return (React.createElement("div", { className: cn(styles.component, styles[size], className), "data-test-id": dataTestId },
40
- React.createElement("svg", { viewBox: "0 0 " + memorized.width + " " + memorized.height, className: styles.svg, xmlns: 'http://www.w3.org/2000/svg' },
41
- React.createElement("circle", { className: styles.backgroundCircle, cx: memorized.center, cy: memorized.center, r: memorized.radius }),
42
- React.createElement("circle", { className: cn(styles.progressCircle, styles[view]), cx: memorized.center, cy: memorized.center, r: memorized.radius, strokeDasharray: memorized.strokeDasharray, strokeDashoffset: memorized.strokeDashoffset, transform: "rotate(" + -90 + " " + memorized.center + " " + memorized.center + ")" })),
43
- React.createElement("div", { className: styles.label }, children || (React.createElement(React.Fragment, null,
44
- typeof title === 'string' ? (React.createElement(Typography.Title, { className: styles.title, color: 'secondary', tag: 'div', view: size === 'l' ? 'small' : 'xsmall' }, title)) : (title),
45
- typeof subtitle === 'string' ? (React.createElement(Typography.Text, { tag: 'div', className: styles.subtitle, color: 'primary', view: 'primary-small' }, subtitle)) : (subtitle))))));
94
+ var isComplete = value === 100;
95
+ var isCompleteTextColor = isComplete && completeTextColor;
96
+ var titleContent = titleComplete && isComplete ? titleComplete : title;
97
+ var subtitleContent = subtitleComplete && isComplete ? subtitleComplete : subtitle;
98
+ var IconComponent = IconComplete && isComplete ? IconComplete : Icon;
99
+ var renderTitleString = function () {
100
+ return (React.createElement(React.Fragment, null, SIZES[size] > 64 ? (React.createElement(Typography.TitleMobile, { className: cn(styles.typography, styles.title), color: isCompleteTextColor ? completeTextColor : contentColor, tag: 'div', font: 'system', view: VIEW_TITLE[size] }, titleContent)) : (React.createElement(Typography.Text, { className: styles.title, color: isCompleteTextColor ? completeTextColor : contentColor, tag: 'div', weight: 'bold', view: VIEW_TEXT[size] }, titleContent))));
101
+ };
102
+ var renderTitle = function () { return (typeof title === 'string' ? renderTitleString() : titleContent); };
103
+ var renderSubTitle = function () {
104
+ return typeof subtitle === 'string' ? (React.createElement(Typography.Text, { tag: 'div', className: styles.subtitle, color: isCompleteTextColor ? completeTextColor : contentColor, view: 'primary-small' }, subtitleContent)) : (subtitleContent);
105
+ };
106
+ var renderIcon = function () {
107
+ var _a;
108
+ return (React.createElement("span", { className: cn(styles.iconWrapper, styles[size], styles.tertiary, styles["icon-" + contentColor], (_a = {},
109
+ _a[styles["icon-" + completeIconColor]] = completeIconColor,
110
+ _a)) }, IconComponent && React.createElement(IconComponent, { className: styles.icon })));
111
+ };
112
+ var renderContent = function () {
113
+ return Icon || (IconComplete && isComplete) ? (renderIcon()) : (React.createElement(React.Fragment, null,
114
+ SIZES[size] > 24 && renderTitle(),
115
+ SIZES[size] > 64 && renderSubTitle()));
116
+ };
117
+ return (React.createElement("div", { className: cn(styles.component, styles[size], className), style: __assign({}, (height && { height: height, width: height })), "data-test-id": dataTestId },
118
+ React.createElement("svg", { viewBox: "0 0 " + memorized.widthSVG + " " + memorized.heightSVG, className: styles.svg, xmlns: 'http://www.w3.org/2000/svg' },
119
+ React.createElement("circle", { className: cn(styles.backgroundCircle, styles[size], (_b = {},
120
+ _b[styles.stroke] = !stroke,
121
+ _b)), cx: memorized.center, cy: memorized.center, r: memorized.radius, strokeWidth: STROKE[size] }),
122
+ React.createElement("circle", { className: cn(styles.progressCircle, styles[view], styles[size], (_c = {},
123
+ _c[styles["bg-" + view]] = fillComplete && isComplete,
124
+ _c)), cx: memorized.center, cy: memorized.center, r: memorized.radius, strokeWidth: STROKE[size], strokeDasharray: memorized.strokeDasharray, strokeDashoffset: direction === 'counter-clockwise'
125
+ ? -memorized.strokeDashoffset
126
+ : memorized.strokeDashoffset, transform: "rotate(" + -90 + " " + memorized.center + " " + memorized.center + ")" })),
127
+ React.createElement("div", { className: cn(styles.labelWrapper, (_d = {},
128
+ _d[styles.label] = Icon || IconComplete,
129
+ _d)) }, children || renderContent())));
46
130
  };
47
131
 
48
132
  export { CircularProgressBar };