jfs-components 0.0.70 → 0.0.72

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 (66) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +203 -0
  3. package/lib/commonjs/components/CardCTA/CardCTA.js +198 -16
  4. package/lib/commonjs/components/CardFinancialCondition/CardFinancialCondition.js +213 -0
  5. package/lib/commonjs/components/Carousel/Carousel.js +9 -7
  6. package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +147 -0
  7. package/lib/commonjs/components/CircularProgressBarDoted/CircularProgressBarDoted.js +258 -0
  8. package/lib/commonjs/components/CircularRating/CircularRating.js +161 -0
  9. package/lib/commonjs/components/Gauge/Gauge.js +223 -0
  10. package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -2
  11. package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +132 -0
  12. package/lib/commonjs/components/ListGroup/ListGroup.js +3 -1
  13. package/lib/commonjs/components/Nudge/Nudge.js +179 -87
  14. package/lib/commonjs/components/Radio/Radio.js +194 -0
  15. package/lib/commonjs/components/RadioButton/RadioButton.js +21 -188
  16. package/lib/commonjs/components/index.js +56 -0
  17. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  18. package/lib/commonjs/icons/registry.js +1 -1
  19. package/lib/module/components/CardAdvisory/CardAdvisory.js +197 -0
  20. package/lib/module/components/CardCTA/CardCTA.js +199 -17
  21. package/lib/module/components/CardFinancialCondition/CardFinancialCondition.js +207 -0
  22. package/lib/module/components/Carousel/Carousel.js +9 -7
  23. package/lib/module/components/CircularProgressBar/CircularProgressBar.js +141 -0
  24. package/lib/module/components/CircularProgressBarDoted/CircularProgressBarDoted.js +253 -0
  25. package/lib/module/components/CircularRating/CircularRating.js +155 -0
  26. package/lib/module/components/Gauge/Gauge.js +217 -0
  27. package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -2
  28. package/lib/module/components/InstitutionBadge/InstitutionBadge.js +127 -0
  29. package/lib/module/components/ListGroup/ListGroup.js +3 -1
  30. package/lib/module/components/Nudge/Nudge.js +178 -87
  31. package/lib/module/components/Radio/Radio.js +188 -0
  32. package/lib/module/components/RadioButton/RadioButton.js +20 -185
  33. package/lib/module/components/index.js +12 -0
  34. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  35. package/lib/module/icons/registry.js +1 -1
  36. package/lib/typescript/src/components/CardAdvisory/CardAdvisory.d.ts +49 -0
  37. package/lib/typescript/src/components/CardCTA/CardCTA.d.ts +16 -1
  38. package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +50 -0
  39. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +27 -0
  40. package/lib/typescript/src/components/CircularProgressBarDoted/CircularProgressBarDoted.d.ts +48 -0
  41. package/lib/typescript/src/components/CircularRating/CircularRating.d.ts +49 -0
  42. package/lib/typescript/src/components/Gauge/Gauge.d.ts +53 -0
  43. package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +30 -0
  44. package/lib/typescript/src/components/Nudge/Nudge.d.ts +14 -11
  45. package/lib/typescript/src/components/Radio/Radio.d.ts +30 -0
  46. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +20 -28
  47. package/lib/typescript/src/components/index.d.ts +13 -1
  48. package/lib/typescript/src/icons/registry.d.ts +1 -1
  49. package/package.json +1 -1
  50. package/src/components/CardAdvisory/CardAdvisory.tsx +283 -0
  51. package/src/components/CardCTA/CardCTA.tsx +236 -13
  52. package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +366 -0
  53. package/src/components/Carousel/Carousel.tsx +14 -6
  54. package/src/components/CircularProgressBar/CircularProgressBar.tsx +190 -0
  55. package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +357 -0
  56. package/src/components/CircularRating/CircularRating.tsx +241 -0
  57. package/src/components/Gauge/Gauge.tsx +303 -0
  58. package/src/components/HoldingsCard/HoldingsCard.tsx +2 -2
  59. package/src/components/InstitutionBadge/InstitutionBadge.tsx +216 -0
  60. package/src/components/ListGroup/ListGroup.tsx +3 -1
  61. package/src/components/Nudge/Nudge.tsx +222 -82
  62. package/src/components/Radio/Radio.tsx +227 -0
  63. package/src/components/RadioButton/RadioButton.tsx +23 -225
  64. package/src/components/index.ts +13 -1
  65. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  66. package/src/icons/registry.ts +1 -1
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
11
+ var _reactUtils = require("../../utils/react-utils");
12
+ var _Button = _interopRequireDefault(require("../Button/Button"));
13
+ var _CircularProgressBar = _interopRequireDefault(require("../CircularProgressBar/CircularProgressBar"));
14
+ var _Divider = _interopRequireDefault(require("../Divider/Divider"));
15
+ var _Nudge = _interopRequireDefault(require("../Nudge/Nudge"));
16
+ var _jsxRuntime = require("react/jsx-runtime");
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
19
+ const toNumber = (value, fallback) => {
20
+ if (typeof value === 'number') {
21
+ return Number.isFinite(value) ? value : fallback;
22
+ }
23
+ if (typeof value === 'string') {
24
+ const parsed = Number(value);
25
+ return Number.isFinite(parsed) ? parsed : fallback;
26
+ }
27
+ return fallback;
28
+ };
29
+ const toFontWeight = (value, fallback) => {
30
+ if (typeof value === 'number') {
31
+ return String(value);
32
+ }
33
+ if (typeof value === 'string') {
34
+ return value;
35
+ }
36
+ return fallback;
37
+ };
38
+ function resolveCardFinancialConditionTokens(modes) {
39
+ const background = (0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/background', modes) || '#ffffff';
40
+ const radius = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/radius', modes), 16);
41
+ const paddingH = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/padding/horizontal', modes), 16);
42
+ const paddingV = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/padding/vertical', modes), 16);
43
+ const gap = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/gap', modes), 8);
44
+ const headerGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/header/gap', modes), 16);
45
+ const textContentGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/textContent/gap', modes), 8);
46
+ const titleColor = (0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/title/color', modes) || '#0c0d10';
47
+ const titleFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/title/fontSize', modes), 16);
48
+ const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/title/fontFamily', modes) || 'JioType Var';
49
+ const titleLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/title/lineHeight', modes), 18);
50
+ const titleFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/title/fontWeight', modes), '700');
51
+ const bodyColor = (0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/body/color', modes) || '#0c0d10';
52
+ const bodyFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/body/fontSize', modes), 14);
53
+ const bodyFontFamily = (0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/body/fontFamily', modes) || 'JioType Var';
54
+ const bodyLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/body/lineHeight', modes), 17);
55
+ const bodyFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('financialConditionCard/body/fontWeight', modes), '400');
56
+ const nudgeBodyColor = (0, _figmaVariablesResolver.getVariableByName)('nudge/body/color', modes) || '#1a1c1f';
57
+ const nudgeBodyFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('nudge/body/fontSize', modes), 12);
58
+ const nudgeBodyFontFamily = (0, _figmaVariablesResolver.getVariableByName)('nudge/body/fontFamily', modes) || 'JioType Var';
59
+ const nudgeBodyLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('nudge/body/lineHeight', modes), 16);
60
+ const nudgeBodyFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('nudge/body/fontWeight', modes), '500');
61
+ return {
62
+ containerStyle: {
63
+ alignItems: 'flex-start',
64
+ backgroundColor: background,
65
+ borderRadius: radius,
66
+ gap,
67
+ justifyContent: 'center',
68
+ overflow: 'hidden',
69
+ paddingHorizontal: paddingH,
70
+ paddingVertical: paddingV
71
+ },
72
+ headerStyle: {
73
+ alignItems: 'center',
74
+ flexDirection: 'row',
75
+ gap: headerGap,
76
+ width: '100%'
77
+ },
78
+ textContentStyle: {
79
+ alignItems: 'flex-start',
80
+ flex: 1,
81
+ gap: textContentGap,
82
+ minWidth: 1
83
+ },
84
+ titleStyle: {
85
+ color: titleColor,
86
+ fontFamily: titleFontFamily,
87
+ fontSize: titleFontSize,
88
+ fontWeight: titleFontWeight,
89
+ lineHeight: titleLineHeight
90
+ },
91
+ bodyStyle: {
92
+ color: bodyColor,
93
+ fontFamily: bodyFontFamily,
94
+ fontSize: bodyFontSize,
95
+ fontWeight: bodyFontWeight,
96
+ lineHeight: bodyLineHeight
97
+ },
98
+ nudgeBodyStyle: {
99
+ color: nudgeBodyColor,
100
+ fontFamily: nudgeBodyFontFamily,
101
+ fontSize: nudgeBodyFontSize,
102
+ fontWeight: nudgeBodyFontWeight,
103
+ lineHeight: nudgeBodyLineHeight
104
+ },
105
+ buttonWrapStyle: {
106
+ alignSelf: 'stretch',
107
+ alignItems: 'flex-start'
108
+ }
109
+ };
110
+ }
111
+ function CardFinancialCondition({
112
+ title = 'Protection',
113
+ body = 'Check your coverage and gaps',
114
+ value = 0,
115
+ progressState = 'Inactive',
116
+ valueLabel,
117
+ showNudge = true,
118
+ nudgeBody = 'There may be gaps in your health or life cover\nAdd coverage to stay financially secure',
119
+ showDivider = true,
120
+ showButton = true,
121
+ buttonLabel = 'View Details',
122
+ onPressButton,
123
+ progressSlot,
124
+ nudgeSlot,
125
+ buttonSlot,
126
+ modes: propModes = _reactUtils.EMPTY_MODES,
127
+ style,
128
+ headerStyle,
129
+ titleStyle,
130
+ bodyStyle,
131
+ accessibilityLabel,
132
+ ...rest
133
+ }) {
134
+ const {
135
+ modes: globalModes
136
+ } = (0, _JFSThemeProvider.useTokens)();
137
+ const modes = (0, _react.useMemo)(() => globalModes === _reactUtils.EMPTY_MODES && propModes === _reactUtils.EMPTY_MODES ? _reactUtils.EMPTY_MODES : {
138
+ ...globalModes,
139
+ ...propModes
140
+ }, [globalModes, propModes]);
141
+ const tokens = (0, _react.useMemo)(() => resolveCardFinancialConditionTokens(modes), [modes]);
142
+
143
+ // Match Figma: the action button is the primary call-to-action and uses the
144
+ // Secondary brand (purple) regardless of the card's overall AppearanceBrand,
145
+ // while Nudge / CircularProgressBar still follow the user-supplied modes.
146
+ const buttonModes = (0, _react.useMemo)(() => ({
147
+ ...modes,
148
+ AppearanceBrand: 'Secondary'
149
+ }), [modes]);
150
+ const processedProgressSlot = (0, _react.useMemo)(() => {
151
+ if (!progressSlot) return null;
152
+ const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(progressSlot), modes);
153
+ return processed.length === 1 ? processed[0] : processed;
154
+ }, [progressSlot, modes]);
155
+ const processedNudgeSlot = (0, _react.useMemo)(() => {
156
+ if (!nudgeSlot) return null;
157
+ const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(nudgeSlot), modes);
158
+ return processed.length === 1 ? processed[0] : processed;
159
+ }, [nudgeSlot, modes]);
160
+ const processedButtonSlot = (0, _react.useMemo)(() => {
161
+ if (!buttonSlot) return null;
162
+ const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(buttonSlot), buttonModes);
163
+ return processed.length === 1 ? processed[0] : processed;
164
+ }, [buttonSlot, buttonModes]);
165
+ const defaultAccessibilityLabel = accessibilityLabel ?? `${title}. ${body}.`;
166
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
167
+ accessibilityLabel: defaultAccessibilityLabel,
168
+ style: [tokens.containerStyle, style],
169
+ ...rest,
170
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
171
+ style: [tokens.headerStyle, headerStyle],
172
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
173
+ style: tokens.textContentStyle,
174
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
175
+ style: [tokens.titleStyle, titleStyle],
176
+ children: title
177
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
178
+ style: [tokens.bodyStyle, bodyStyle],
179
+ children: body
180
+ })]
181
+ }), processedProgressSlot || /*#__PURE__*/(0, _jsxRuntime.jsx)(_CircularProgressBar.default, {
182
+ state: progressState,
183
+ value: value,
184
+ modes: modes,
185
+ ...(valueLabel ? {
186
+ valueLabel
187
+ } : {})
188
+ })]
189
+ }), showNudge ? processedNudgeSlot || /*#__PURE__*/(0, _jsxRuntime.jsx)(_Nudge.default, {
190
+ type: "inline-compact",
191
+ modes: modes,
192
+ style: {
193
+ width: '100%'
194
+ },
195
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
196
+ style: tokens.nudgeBodyStyle,
197
+ children: nudgeBody
198
+ })
199
+ }) : null, showDivider ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
200
+ modes: modes
201
+ }) : null, showButton ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
202
+ style: tokens.buttonWrapStyle,
203
+ children: processedButtonSlot || /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
204
+ label: buttonLabel,
205
+ modes: buttonModes,
206
+ ...(onPressButton ? {
207
+ onPress: onPressButton
208
+ } : {})
209
+ })
210
+ }) : null]
211
+ });
212
+ }
213
+ var _default = exports.default = /*#__PURE__*/_react.default.memo(CardFinancialCondition);
@@ -51,6 +51,8 @@ function Carousel({
51
51
  const gap = gapProp ?? tokenGap;
52
52
  const containerPaddingH = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/padding/horizontal', modes) || '0');
53
53
  const containerPaddingV = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/padding/vertical', modes) || '0');
54
+ // Outer container max height per Figma (`carousel/maxHeight`).
55
+ const maxHeight = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/maxHeight', modes) || '280');
54
56
  // Spacing between the cards row and the pagination dots uses `carousel/gap`.
55
57
  const paginationOffset = gap;
56
58
 
@@ -162,7 +164,8 @@ function Carousel({
162
164
 
163
165
  // ---- Render ----
164
166
  const outerStyle = {
165
- paddingVertical: containerPaddingV
167
+ paddingVertical: containerPaddingV,
168
+ maxHeight
166
169
  };
167
170
  const contentContainerStyle = {
168
171
  paddingHorizontal: containerPaddingH * 2,
@@ -270,13 +273,12 @@ function Pagination({
270
273
  const modes = propModes || ctxModes || {};
271
274
 
272
275
  // Token resolution for dots — matches Figma tokens
273
- // (carousel/pagination/gap, carousel/pagination/indicator/{activecolor,inactivecolor,radius}).
274
- // Dot dimensions are fixed per Figma spec: inactive 6x6, active 16x6.
275
- const dotSize = 6;
276
- const dotActiveWidth = 16;
276
+ // (carousel/pagination/gap, carousel/pagination/indicator/{activeColor,inactiveColor,radius,size,activeWidth}).
277
+ const dotSize = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/size', modes) || '6');
278
+ const dotActiveWidth = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/activeWidth', modes) || '16');
277
279
  const dotGap = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/gap', modes) || '4');
278
- const dotColor = (0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/inactivecolor', modes) || 'rgba(0,0,0,0.3)';
279
- const dotActiveColor = (0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/activecolor', modes) || '#170d0a';
280
+ const dotColor = (0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/inactiveColor', modes) || 'rgba(0,0,0,0.3)';
281
+ const dotActiveColor = (0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/activeColor', modes) || '#170d0a';
280
282
  const dotRadius = parseFloat((0, _figmaVariablesResolver.getVariableByName)('carousel/pagination/indicator/radius', modes) || '9999');
281
283
  const containerStyle = {
282
284
  flexDirection: 'row',
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
10
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
12
+ var _reactUtils = require("../../utils/react-utils");
13
+ var _IconMinus = require("../../icons/components/IconMinus");
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ const STROKE_WIDTH_RATIO = 8 / 60;
18
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
19
+ const toNumber = (value, fallback) => {
20
+ if (typeof value === 'number') {
21
+ return Number.isFinite(value) ? value : fallback;
22
+ }
23
+ if (typeof value === 'string') {
24
+ const parsed = Number(value);
25
+ return Number.isFinite(parsed) ? parsed : fallback;
26
+ }
27
+ return fallback;
28
+ };
29
+ const toFontWeight = (value, fallback) => {
30
+ if (typeof value === 'number') {
31
+ return String(value);
32
+ }
33
+ if (typeof value === 'string') {
34
+ return value;
35
+ }
36
+ return fallback;
37
+ };
38
+ const getStrokeColor = (style, fallback) => {
39
+ const flattened = _reactNative.StyleSheet.flatten(style);
40
+ return typeof flattened.backgroundColor === 'string' ? flattened.backgroundColor : fallback;
41
+ };
42
+ function CircularProgressBar({
43
+ value = 70,
44
+ state = 'Inactive',
45
+ valueLabel,
46
+ modes: propModes = _reactUtils.EMPTY_MODES,
47
+ style,
48
+ trackStyle,
49
+ progressStyle,
50
+ valueStyle,
51
+ accessibilityLabel,
52
+ ...rest
53
+ }) {
54
+ const {
55
+ modes: globalModes
56
+ } = (0, _JFSThemeProvider.useTokens)();
57
+ const modes = {
58
+ ...globalModes,
59
+ ...propModes
60
+ };
61
+ const isActive = state === true || state === 'Active';
62
+ const normalizedValue = clamp(value, 0, 100);
63
+ const size = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/size', modes), 60);
64
+ const strokeWidth = Math.max(1, size * STROKE_WIDTH_RATIO);
65
+ const radius = Math.max(0, (size - strokeWidth) / 2);
66
+ const center = size / 2;
67
+ const circumference = 2 * Math.PI * radius;
68
+ const trackColor = getStrokeColor(trackStyle, (0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/track/color', modes) || '#ebebed');
69
+ const progressColor = getStrokeColor(progressStyle, (0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/progress/color', modes) || '#25ab21');
70
+ const iconColor = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/icon/color', modes) || '#666666';
71
+ const iconSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/icon/size', modes), 24);
72
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/foreground', modes) || '#0d0d0f';
73
+ const fontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/fontSize', modes), 18);
74
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/fontFamily', modes) || 'JioType Var';
75
+ const lineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/lineHeight', modes), 21);
76
+ const fontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('circularProgressBar/fontWeight', modes), '700');
77
+ const computedContainerStyle = {
78
+ alignItems: 'center',
79
+ height: size,
80
+ justifyContent: 'center',
81
+ position: 'relative',
82
+ width: size
83
+ };
84
+ const computedValueStyle = {
85
+ color: foreground,
86
+ fontFamily,
87
+ fontSize,
88
+ fontWeight,
89
+ lineHeight,
90
+ position: 'absolute',
91
+ textAlign: 'center'
92
+ };
93
+ const iconStyle = {
94
+ left: (size - iconSize) / 2,
95
+ position: 'absolute',
96
+ top: (size - iconSize) / 2
97
+ };
98
+ const displayValue = valueLabel ?? String(Math.round(normalizedValue));
99
+ const defaultAccessibilityLabel = accessibilityLabel ?? (isActive ? `${displayValue} out of 100` : 'Inactive progress');
100
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
101
+ accessibilityRole: "progressbar",
102
+ accessibilityLabel: defaultAccessibilityLabel,
103
+ accessibilityValue: {
104
+ min: 0,
105
+ max: 100,
106
+ now: normalizedValue
107
+ },
108
+ style: [computedContainerStyle, style],
109
+ ...rest,
110
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSvg.default, {
111
+ width: size,
112
+ height: size,
113
+ viewBox: `0 0 ${size} ${size}`,
114
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
115
+ cx: center,
116
+ cy: center,
117
+ r: radius,
118
+ stroke: trackColor,
119
+ strokeWidth: strokeWidth,
120
+ fill: "none"
121
+ }), isActive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Circle, {
122
+ cx: center,
123
+ cy: center,
124
+ r: radius,
125
+ stroke: progressColor,
126
+ strokeWidth: strokeWidth,
127
+ strokeLinecap: "round",
128
+ fill: "none",
129
+ strokeDasharray: `${circumference} ${circumference}`,
130
+ strokeDashoffset: circumference * (1 - normalizedValue / 100),
131
+ rotation: "-90",
132
+ originX: center,
133
+ originY: center
134
+ }) : null]
135
+ }), isActive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
136
+ style: [computedValueStyle, valueStyle],
137
+ children: displayValue
138
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconMinus.IconMinus, {
139
+ width: iconSize,
140
+ height: iconSize,
141
+ fill: iconColor,
142
+ color: iconColor,
143
+ style: iconStyle
144
+ })]
145
+ });
146
+ }
147
+ var _default = exports.default = CircularProgressBar;
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
11
+ var _reactUtils = require("../../utils/react-utils");
12
+ var _IconChevronright = require("../../icons/components/IconChevronright");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
15
+ const DEFAULT_DOT_COUNT = 24;
16
+ const START_ANGLE_DEGREES = -90;
17
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
18
+ const toNumber = (value, fallback) => {
19
+ if (typeof value === 'number') {
20
+ return Number.isFinite(value) ? value : fallback;
21
+ }
22
+ if (typeof value === 'string') {
23
+ const parsed = Number(value);
24
+ return Number.isFinite(parsed) ? parsed : fallback;
25
+ }
26
+ return fallback;
27
+ };
28
+ const toFontWeight = (value, fallback) => {
29
+ if (typeof value === 'number') {
30
+ return String(value);
31
+ }
32
+ if (typeof value === 'string') {
33
+ return value;
34
+ }
35
+ return fallback;
36
+ };
37
+ const getBackgroundColor = (style, fallback) => {
38
+ const flattened = _reactNative.StyleSheet.flatten(style);
39
+ return typeof flattened.backgroundColor === 'string' ? flattened.backgroundColor : fallback;
40
+ };
41
+ function CircularProgressBarDoted({
42
+ value = 72,
43
+ dotCount = DEFAULT_DOT_COUNT,
44
+ label = 'Rating',
45
+ tierLabel = 'Doing great',
46
+ showChevron = true,
47
+ onPress,
48
+ onTierPress,
49
+ modes: propModes = _reactUtils.EMPTY_MODES,
50
+ children,
51
+ style,
52
+ ringStyle,
53
+ trackDotStyle,
54
+ progressDotStyle,
55
+ contentStyle,
56
+ scoreTierStyle,
57
+ scoreTrendStyle,
58
+ labelStyle,
59
+ scoreLabelStyle,
60
+ tierLabelStyle,
61
+ accessibilityLabel,
62
+ onLayout,
63
+ ...rest
64
+ }) {
65
+ const {
66
+ modes: globalModes
67
+ } = (0, _JFSThemeProvider.useTokens)();
68
+ const modes = {
69
+ ...globalModes,
70
+ ...propModes
71
+ };
72
+ const [layoutSize, setLayoutSize] = (0, _react.useState)(0);
73
+ const normalizedValue = clamp(value, 0, 100);
74
+ const resolvedDotCount = Math.max(1, Math.floor(dotCount));
75
+ const activeDots = normalizedValue <= 0 ? 0 : Math.ceil(normalizedValue / 100 * resolvedDotCount);
76
+ const dotShadowSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/dot/shadow/size', modes), 6);
77
+ const baseDotSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/dot/size', modes), 6);
78
+ const dotSize = baseDotSize + dotShadowSize;
79
+ const outerDotSize = dotSize;
80
+ const ringSize = layoutSize;
81
+ const ringRadius = Math.max(0, (ringSize - outerDotSize) / 2);
82
+ const trackDotColor = getBackgroundColor(trackDotStyle, (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/trackDot/bg', modes) || '#ebebed');
83
+ const progressDotColor = getBackgroundColor(progressDotStyle, (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/progressDot/bg', modes) || '#25ab21');
84
+ const contentGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/gap', modes), 12);
85
+ const scoreTierGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreTier/gap', modes), 6);
86
+ const scoreTierWidth = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreTier/width', modes), 116);
87
+ const scoreTrendGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreTrend/gap', modes), 2);
88
+ const scoreTrendHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreTrend/height', modes), 24);
89
+ const typographyFontFamily = (0, _figmaVariablesResolver.getVariableByName)('Typography/Font Family', modes) || 'JioType Var';
90
+ const labelColor = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/label/color', modes) || '#080d1a';
91
+ const labelFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('Typography/Size/Body/XS', modes), 12);
92
+ const labelFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('Typography/Font Weight/Body Low (Regular)', modes), '400');
93
+ const scoreColor = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreLabel/color', modes) || '#080d1a';
94
+ const scoreFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreLabel/fontSize', modes), 56);
95
+ const scoreFontFamily = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreLabel/fontFamily', modes) || 'JioType Var';
96
+ const scoreLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreLabel/lineHeight', modes), 56);
97
+ const scoreFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/scoreLabel/fontWeight', modes), '900');
98
+ const tierColor = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/tierLabel/color', modes) || '#080d1a';
99
+ const tierFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('Typography/Size/Body/M', modes), 16);
100
+ const tierFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('Typography/Font Weight/Body High', modes), '700');
101
+ const iconColor = (0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/icon/color', modes) || '#303338';
102
+ const iconSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('circularProgressBarDoted/icon/size', modes), 24);
103
+ const dots = (0, _react.useMemo)(() => Array.from({
104
+ length: resolvedDotCount
105
+ }, (_, index) => {
106
+ const angle = (360 / resolvedDotCount * index + START_ANGLE_DEGREES) * (Math.PI / 180);
107
+ const center = ringSize / 2;
108
+ return {
109
+ isActive: index < activeDots,
110
+ left: center + ringRadius * Math.cos(angle) - outerDotSize / 2,
111
+ top: center + ringRadius * Math.sin(angle) - outerDotSize / 2
112
+ };
113
+ }), [activeDots, outerDotSize, resolvedDotCount, ringRadius, ringSize]);
114
+ const containerStyle = {
115
+ alignItems: 'center',
116
+ alignSelf: 'stretch',
117
+ height: '100%',
118
+ justifyContent: 'center',
119
+ position: 'relative',
120
+ width: '100%'
121
+ };
122
+ const computedRingStyle = {
123
+ height: ringSize,
124
+ position: 'absolute',
125
+ width: ringSize
126
+ };
127
+ const dotOuterStyle = {
128
+ alignItems: 'center',
129
+ height: outerDotSize,
130
+ justifyContent: 'center',
131
+ position: 'absolute',
132
+ width: outerDotSize
133
+ };
134
+ const dotInnerStyle = {
135
+ borderRadius: dotSize / 2,
136
+ height: dotSize,
137
+ width: dotSize
138
+ };
139
+ const computedContentStyle = {
140
+ alignItems: 'center',
141
+ gap: contentGap,
142
+ justifyContent: 'center',
143
+ minWidth: scoreTierWidth
144
+ };
145
+ const computedScoreTierStyle = {
146
+ alignItems: 'center',
147
+ gap: scoreTierGap,
148
+ justifyContent: 'center',
149
+ width: '100%'
150
+ };
151
+ const computedScoreTrendStyle = {
152
+ alignItems: 'center',
153
+ flexDirection: 'row',
154
+ gap: scoreTrendGap,
155
+ height: scoreTrendHeight,
156
+ justifyContent: 'center',
157
+ minWidth: scoreTierWidth
158
+ };
159
+ const computedLabelStyle = {
160
+ color: labelColor,
161
+ fontFamily: typographyFontFamily,
162
+ fontSize: labelFontSize,
163
+ fontWeight: labelFontWeight,
164
+ lineHeight: labelFontSize * 1.3,
165
+ textAlign: 'center'
166
+ };
167
+ const computedScoreLabelStyle = {
168
+ color: scoreColor,
169
+ fontFamily: scoreFontFamily,
170
+ fontSize: scoreFontSize,
171
+ fontWeight: scoreFontWeight,
172
+ lineHeight: scoreLineHeight,
173
+ textAlign: 'center'
174
+ };
175
+ const computedTierLabelStyle = {
176
+ color: tierColor,
177
+ fontFamily: typographyFontFamily,
178
+ fontSize: tierFontSize,
179
+ fontWeight: tierFontWeight,
180
+ lineHeight: tierFontSize * 1.3,
181
+ textAlign: 'center'
182
+ };
183
+ const resolvedScoreLabel = String(Math.round(normalizedValue));
184
+ const defaultAccessibilityLabel = accessibilityLabel ?? `${label}. ${resolvedScoreLabel} out of 100. ${tierLabel}`;
185
+ const handleLayout = event => {
186
+ onLayout?.(event);
187
+ const {
188
+ width,
189
+ height
190
+ } = event.nativeEvent.layout;
191
+ const nextSize = Math.max(0, Math.min(width, height));
192
+ setLayoutSize(currentSize => currentSize === nextSize ? currentSize : nextSize);
193
+ };
194
+ const trendContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
195
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
196
+ numberOfLines: 1,
197
+ style: [computedTierLabelStyle, tierLabelStyle],
198
+ children: tierLabel
199
+ }), showChevron ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconChevronright.IconChevronright, {
200
+ width: iconSize,
201
+ height: iconSize,
202
+ fill: iconColor,
203
+ color: iconColor
204
+ }) : null]
205
+ });
206
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
207
+ accessibilityRole: "progressbar",
208
+ accessibilityLabel: defaultAccessibilityLabel,
209
+ accessibilityValue: {
210
+ min: 0,
211
+ max: 100,
212
+ now: normalizedValue
213
+ },
214
+ disabled: !onPress,
215
+ onLayout: handleLayout,
216
+ onPress: onPress,
217
+ style: [containerStyle, style],
218
+ ...rest,
219
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
220
+ pointerEvents: "none",
221
+ style: [computedRingStyle, ringStyle],
222
+ children: dots.map((dot, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
223
+ style: [dotOuterStyle, {
224
+ left: dot.left,
225
+ top: dot.top
226
+ }],
227
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
228
+ style: [dotInnerStyle, {
229
+ backgroundColor: dot.isActive ? progressDotColor : trackDotColor
230
+ }, dot.isActive ? progressDotStyle : trackDotStyle]
231
+ })
232
+ }, index))
233
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
234
+ style: [computedContentStyle, contentStyle],
235
+ children: children ? (0, _reactUtils.cloneChildrenWithModes)(children, modes) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
236
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
237
+ style: [computedScoreTierStyle, scoreTierStyle],
238
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
239
+ style: [computedLabelStyle, labelStyle],
240
+ children: label
241
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
242
+ style: [computedScoreLabelStyle, scoreLabelStyle],
243
+ children: resolvedScoreLabel
244
+ })]
245
+ }), onTierPress ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
246
+ accessibilityRole: "button",
247
+ onPress: onTierPress,
248
+ style: [computedScoreTrendStyle, scoreTrendStyle],
249
+ children: trendContent
250
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
251
+ style: [computedScoreTrendStyle, scoreTrendStyle],
252
+ children: trendContent
253
+ })]
254
+ })
255
+ })]
256
+ });
257
+ }
258
+ var _default = exports.default = CircularProgressBarDoted;