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,217 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { StyleSheet, View, Text } from 'react-native';
5
+ import Svg, { Path } from 'react-native-svg';
6
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
7
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
8
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
9
+ import SupportText from '../SupportText/SupportText';
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ const clamp = (value, min, max) => {
12
+ if (max <= min) {
13
+ return 0;
14
+ }
15
+ return Math.min(1, Math.max(0, (value - min) / (max - min)));
16
+ };
17
+ const toNumber = (value, fallback) => {
18
+ if (typeof value === 'number') {
19
+ return Number.isFinite(value) ? value : fallback;
20
+ }
21
+ if (typeof value === 'string') {
22
+ const parsed = Number(value);
23
+ return Number.isFinite(parsed) ? parsed : fallback;
24
+ }
25
+ return fallback;
26
+ };
27
+ const toFontWeight = (value, fallback) => {
28
+ if (typeof value === 'number') {
29
+ return String(value);
30
+ }
31
+ if (typeof value === 'string') {
32
+ return value;
33
+ }
34
+ return fallback;
35
+ };
36
+ const getStrokeColor = (style, fallback) => {
37
+ const flattened = StyleSheet.flatten(style);
38
+ return typeof flattened.backgroundColor === 'string' ? flattened.backgroundColor : fallback;
39
+ };
40
+ function Gauge({
41
+ value = 84,
42
+ min = 0,
43
+ max = 100,
44
+ valueLabel,
45
+ title = 'Your score is based on strong data',
46
+ caption = 'Add more details for even better accuracy',
47
+ supportText = 'Support Text',
48
+ supportTextStatus = 'Success',
49
+ showTitle = true,
50
+ showCaption = true,
51
+ showSupportText = true,
52
+ modes: propModes = EMPTY_MODES,
53
+ children,
54
+ style,
55
+ arcStyle,
56
+ readoutStyle,
57
+ titleStyle,
58
+ valueStyle,
59
+ captionStyle,
60
+ trackStyle,
61
+ progressStyle,
62
+ accessibilityLabel,
63
+ ...rest
64
+ }) {
65
+ const {
66
+ modes: globalModes
67
+ } = useTokens();
68
+ const modes = {
69
+ ...globalModes,
70
+ ...propModes
71
+ };
72
+ const supportTextModes = {
73
+ ...modes,
74
+ Status: supportTextStatus
75
+ };
76
+ const gap = toNumber(getVariableByName('gauge/gap', modes), 30);
77
+ const padding = toNumber(getVariableByName('gauge/padding', modes), 16);
78
+ const width = toNumber(getVariableByName('gauge/width', modes), 299);
79
+ const arcWidth = toNumber(getVariableByName('gauge/arc/width', modes), 267);
80
+ const arcHeight = arcWidth * (186 / 328);
81
+ const trackSize = toNumber(getVariableByName('gauge/track/size', modes), 244);
82
+ const trackInnerRadius = toNumber(getVariableByName('gauge/track/radius', modes), 99);
83
+ const progressInnerRadius = toNumber(getVariableByName('gauge/progress/radius', modes), 99);
84
+ const innerRadius = Math.min(trackInnerRadius, progressInnerRadius);
85
+ const strokeWidth = Math.max(1, trackSize / 2 - innerRadius);
86
+ const radius = innerRadius + strokeWidth / 2;
87
+ const centerX = arcWidth / 2;
88
+ const centerY = Math.min(arcHeight - strokeWidth / 2, radius + strokeWidth / 2);
89
+ const startX = centerX - radius;
90
+ const endX = centerX + radius;
91
+ const arcPath = `M ${startX} ${centerY} A ${radius} ${radius} 0 0 1 ${endX} ${centerY}`;
92
+ const arcLength = Math.PI * radius;
93
+ const progress = clamp(value, min, max);
94
+ const titleColor = getVariableByName('gauge/title/color', modes) || '#0c0d10';
95
+ const titleFontSize = toNumber(getVariableByName('gauge/title/fontSize', modes), 23);
96
+ const titleLineHeight = toNumber(getVariableByName('gauge/title/lineHeight', modes), 23);
97
+ const titleFontFamily = getVariableByName('gauge/title/fontFamily', modes) || 'JioType Var';
98
+ const titleFontWeight = toFontWeight(getVariableByName('gauge/title/fontWeight', modes), '900');
99
+ const titleHeight = toNumber(getVariableByName('gauge/title/height', modes), 46);
100
+ const readoutGap = toNumber(getVariableByName('gauge/readout/gap', modes), 8);
101
+ const readoutPadding = toNumber(getVariableByName('gauge/readout/padding', modes), 8);
102
+ const valueColor = getVariableByName('gauge/readout/value/color', modes) || '#0c0d10';
103
+ const valueFontSize = toNumber(getVariableByName('gauge/readout/value/fontSize', modes), 36);
104
+ const valueLineHeight = toNumber(getVariableByName('gauge/readout/value/lineHeight', modes), 36);
105
+ const valueFontFamily = getVariableByName('gauge/readout/value/fontFamily', modes) || 'JioType Var';
106
+ const valueFontWeight = toFontWeight(getVariableByName('gauge/readout/value/fontWeight', modes), '800');
107
+ const captionColor = getVariableByName('gauge/caption/color', modes) || '#0c0d10';
108
+ const captionFontSize = toNumber(getVariableByName('gauge/caption/fontSize', modes), 14);
109
+ const captionLineHeight = toNumber(getVariableByName('gauge/caption/lineHeight', modes), 18);
110
+ const captionFontFamily = getVariableByName('gauge/caption/fontFamily', modes) || 'JioType Var';
111
+ const captionFontWeight = toFontWeight(getVariableByName('gauge/caption/fontWeight', modes), '500');
112
+ const trackColor = getStrokeColor(trackStyle, getVariableByName('gauge/track/color', modes) || '#f5f5f6');
113
+ const progressColor = getStrokeColor(progressStyle, getVariableByName('gauge/progress/color', modes) || '#25ab21');
114
+ const containerStyle = {
115
+ alignItems: 'center',
116
+ gap,
117
+ padding,
118
+ width
119
+ };
120
+ const computedTitleStyle = {
121
+ color: titleColor,
122
+ fontFamily: titleFontFamily,
123
+ fontSize: titleFontSize,
124
+ fontWeight: titleFontWeight,
125
+ lineHeight: titleLineHeight,
126
+ minHeight: titleHeight,
127
+ textAlign: 'center',
128
+ width: '100%'
129
+ };
130
+ const computedArcStyle = {
131
+ height: arcHeight,
132
+ overflow: 'hidden',
133
+ position: 'relative',
134
+ width: '100%'
135
+ };
136
+ const computedReadoutStyle = {
137
+ alignItems: 'center',
138
+ gap: readoutGap,
139
+ left: 0,
140
+ padding: readoutPadding,
141
+ position: 'absolute',
142
+ right: 0,
143
+ top: arcHeight * 0.42
144
+ };
145
+ const computedValueStyle = {
146
+ color: valueColor,
147
+ fontFamily: valueFontFamily,
148
+ fontSize: valueFontSize,
149
+ fontWeight: valueFontWeight,
150
+ lineHeight: valueLineHeight,
151
+ textAlign: 'center'
152
+ };
153
+ const computedCaptionStyle = {
154
+ color: captionColor,
155
+ fontFamily: captionFontFamily,
156
+ fontSize: captionFontSize,
157
+ fontWeight: captionFontWeight,
158
+ lineHeight: captionLineHeight,
159
+ textAlign: 'center',
160
+ width: '100%'
161
+ };
162
+ const defaultValueLabel = valueLabel ?? String(Math.round(value));
163
+ const defaultAccessibilityLabel = accessibilityLabel ?? `${title}. ${defaultValueLabel} out of ${max}. ${supportText}. ${caption}`;
164
+ return /*#__PURE__*/_jsxs(View, {
165
+ accessibilityRole: "progressbar",
166
+ accessibilityLabel: defaultAccessibilityLabel,
167
+ accessibilityValue: {
168
+ min,
169
+ max,
170
+ now: value
171
+ },
172
+ style: [containerStyle, style],
173
+ ...rest,
174
+ children: [showTitle ? /*#__PURE__*/_jsx(Text, {
175
+ style: [computedTitleStyle, titleStyle],
176
+ children: title
177
+ }) : null, /*#__PURE__*/_jsxs(View, {
178
+ style: [computedArcStyle, arcStyle],
179
+ children: [/*#__PURE__*/_jsxs(Svg, {
180
+ width: "100%",
181
+ height: arcHeight,
182
+ viewBox: `0 0 ${arcWidth} ${arcHeight}`,
183
+ children: [/*#__PURE__*/_jsx(Path, {
184
+ d: arcPath,
185
+ stroke: trackColor,
186
+ strokeWidth: strokeWidth,
187
+ strokeLinecap: "butt",
188
+ fill: "none"
189
+ }), /*#__PURE__*/_jsx(Path, {
190
+ d: arcPath,
191
+ stroke: progressColor,
192
+ strokeWidth: strokeWidth,
193
+ strokeLinecap: "butt",
194
+ fill: "none",
195
+ strokeDasharray: `${arcLength} ${arcLength}`,
196
+ strokeDashoffset: arcLength * (1 - progress)
197
+ })]
198
+ }), /*#__PURE__*/_jsx(View, {
199
+ style: [computedReadoutStyle, readoutStyle],
200
+ children: children ? cloneChildrenWithModes(children, modes) : /*#__PURE__*/_jsxs(_Fragment, {
201
+ children: [/*#__PURE__*/_jsx(Text, {
202
+ style: [computedValueStyle, valueStyle],
203
+ children: defaultValueLabel
204
+ }), showSupportText ? /*#__PURE__*/_jsx(SupportText, {
205
+ label: supportText,
206
+ status: supportTextStatus,
207
+ modes: supportTextModes
208
+ }) : null]
209
+ })
210
+ })]
211
+ }), showCaption ? /*#__PURE__*/_jsx(Text, {
212
+ style: [computedCaptionStyle, captionStyle],
213
+ children: caption
214
+ }) : null]
215
+ });
216
+ }
217
+ export default Gauge;
@@ -3,7 +3,7 @@
3
3
  import React from 'react';
4
4
  import { View, Text, Pressable, Image } from 'react-native';
5
5
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
- import RadioButton from '../RadioButton/RadioButton';
6
+ import Radio from '../Radio/Radio';
7
7
  import { EMPTY_MODES } from '../../utils/react-utils';
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  const GRID_COLUMNS = 3;
@@ -123,7 +123,7 @@ export default function HoldingsCard({
123
123
  }
124
124
  }), /*#__PURE__*/_jsx(View, {
125
125
  pointerEvents: "none",
126
- children: /*#__PURE__*/_jsx(RadioButton, {
126
+ children: /*#__PURE__*/_jsx(Radio, {
127
127
  selected: selected,
128
128
  disabled: disabled,
129
129
  modes: modes
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+
3
+ import React, { useMemo } from 'react';
4
+ import { Text, View } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
7
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
8
+ import MediaSource from '../../utils/MediaSource';
9
+
10
+ // Default avatar asset (shared with the Avatar component) so that
11
+ // InstitutionBadge has a sensible visual fallback when no `source` is
12
+ // provided in stories or playgrounds.
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ const DEFAULT_AVATAR_IMAGE = require('../Avatar/31595e70c4181263f9971590224b12934b280c9b.png');
15
+ const toNumber = (value, fallback) => {
16
+ if (typeof value === 'number') {
17
+ return Number.isFinite(value) ? value : fallback;
18
+ }
19
+ if (typeof value === 'string') {
20
+ const parsed = Number(value);
21
+ return Number.isFinite(parsed) ? parsed : fallback;
22
+ }
23
+ return fallback;
24
+ };
25
+ const toFontWeight = (value, fallback) => {
26
+ if (typeof value === 'number') {
27
+ return String(value);
28
+ }
29
+ if (typeof value === 'string') {
30
+ return value;
31
+ }
32
+ return fallback;
33
+ };
34
+ function resolveInstitutionBadgeTokens(modes) {
35
+ const gap = toNumber(getVariableByName('institutionBadge/gap', modes), 8);
36
+ const foreground = getVariableByName('institutionBadge/foreground', modes) || '#080d1a';
37
+ const fontSize = toNumber(getVariableByName('institutionBadge/fontSize', modes), 14);
38
+ const fontFamily = getVariableByName('institutionBadge/fontFamily', modes) || 'JioType Var';
39
+ const lineHeight = toNumber(getVariableByName('institutionBadge/lineHeight', modes), 18);
40
+ const fontWeight = toFontWeight(getVariableByName('institutionBadge/fontWeight', modes), '500');
41
+
42
+ // Avatar wrapper styled from shared `avatar/*` tokens so the badge stays
43
+ // visually consistent with other Avatar-bearing components.
44
+ const avatarSize = toNumber(getVariableByName('avatar/size', modes), 36);
45
+ const avatarRadiusRaw = toNumber(getVariableByName('avatar/radius', modes), 9999);
46
+ // 9999 is the design-token sentinel for "perfect circle".
47
+ const avatarRadius = avatarRadiusRaw === 9999 ? avatarSize / 2 : avatarRadiusRaw;
48
+ const avatarBorderColor = getVariableByName('avatar/border/color', modes) || 'rgba(255,255,255,0)';
49
+ const avatarBorderSize = toNumber(getVariableByName('avatar/border/size', modes), 1);
50
+ return {
51
+ containerStyle: {
52
+ alignItems: 'center',
53
+ flexDirection: 'row',
54
+ gap
55
+ },
56
+ avatarStyle: {
57
+ width: avatarSize,
58
+ height: avatarSize,
59
+ borderRadius: avatarRadius,
60
+ borderWidth: avatarBorderSize,
61
+ borderColor: avatarBorderColor,
62
+ overflow: 'hidden'
63
+ },
64
+ avatarSize,
65
+ labelStyle: {
66
+ color: foreground,
67
+ fontFamily,
68
+ fontSize,
69
+ fontWeight,
70
+ lineHeight
71
+ }
72
+ };
73
+ }
74
+
75
+ // Default Avatar Size = M (36px in tokens) — matches the Figma badge. Callers
76
+ // can override via `modes` if needed.
77
+ const DEFAULT_AVATAR_MODE = 'M';
78
+ function InstitutionBadge({
79
+ label = 'State Bank of India',
80
+ source,
81
+ avatarSlot,
82
+ modes: propModes = EMPTY_MODES,
83
+ style,
84
+ labelStyle,
85
+ accessibilityLabel,
86
+ ...rest
87
+ }) {
88
+ const {
89
+ modes: globalModes
90
+ } = useTokens();
91
+ const modes = useMemo(() => globalModes === EMPTY_MODES && propModes === EMPTY_MODES ? EMPTY_MODES : {
92
+ ...globalModes,
93
+ ...propModes
94
+ }, [globalModes, propModes]);
95
+ const avatarModes = useMemo(() => ({
96
+ 'Avatar Size': DEFAULT_AVATAR_MODE,
97
+ ...modes
98
+ }), [modes]);
99
+ const tokens = useMemo(() => resolveInstitutionBadgeTokens(avatarModes), [avatarModes]);
100
+ const processedAvatarSlot = useMemo(() => {
101
+ if (!avatarSlot) return null;
102
+ const processed = cloneChildrenWithModes(React.Children.toArray(avatarSlot), avatarModes);
103
+ return processed.length === 1 ? processed[0] : processed;
104
+ }, [avatarSlot, avatarModes]);
105
+ const resolvedSource = source ?? DEFAULT_AVATAR_IMAGE;
106
+ const defaultAccessibilityLabel = accessibilityLabel ?? label;
107
+ return /*#__PURE__*/_jsxs(View, {
108
+ accessibilityLabel: defaultAccessibilityLabel,
109
+ style: [tokens.containerStyle, style],
110
+ ...rest,
111
+ children: [processedAvatarSlot || /*#__PURE__*/_jsx(View, {
112
+ style: tokens.avatarStyle,
113
+ children: /*#__PURE__*/_jsx(MediaSource, {
114
+ source: resolvedSource,
115
+ size: tokens.avatarSize,
116
+ resizeMode: "cover",
117
+ accessibilityElementsHidden: true,
118
+ importantForAccessibility: "no"
119
+ })
120
+ }), /*#__PURE__*/_jsx(Text, {
121
+ style: [tokens.labelStyle, labelStyle],
122
+ numberOfLines: 1,
123
+ children: label
124
+ })]
125
+ });
126
+ }
127
+ export default /*#__PURE__*/React.memo(InstitutionBadge);
@@ -47,7 +47,9 @@ function ListGroup({
47
47
  }) {
48
48
  // Resolve container tokens
49
49
  const backgroundColor = getVariableByName('listGroup/background', modes) || 'rgba(255,255,255,0)';
50
- const borderColor = getVariableByName('listGroup/border/color', modes) || 'rgba(255,255,255,0)';
50
+ // The current exported token aliases a missing Figma variable. Keep the
51
+ // transparent fallback without logging the missing alias on every render.
52
+ const borderColor = 'rgba(255,255,255,0)';
51
53
  const borderWidth = getVariableByName('listGroup/borderWidth', modes) || 0;
52
54
  const gap = getVariableByName('listGroup/gap', modes) || 12;
53
55